Add a --multiarch-triplet switch to configure
[tinycc/miki.git] / tccelf.c
blobf58ae831910cf32df995e029cfe7efddbf295e59
1 /*
2 * ELF file handling for TCC
3 *
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "tcc.h"
23 static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */
25 ST_FUNC int put_elf_str(Section *s, const char *sym)
27 int offset, len;
28 char *ptr;
30 len = strlen(sym) + 1;
31 offset = s->data_offset;
32 ptr = section_ptr_add(s, len);
33 memcpy(ptr, sym, len);
34 return offset;
37 /* elf symbol hashing function */
38 static unsigned long elf_hash(const unsigned char *name)
40 unsigned long h = 0, g;
42 while (*name) {
43 h = (h << 4) + *name++;
44 g = h & 0xf0000000;
45 if (g)
46 h ^= g >> 24;
47 h &= ~g;
49 return h;
52 /* rebuild hash table of section s */
53 /* NOTE: we do factorize the hash table code to go faster */
54 static void rebuild_hash(Section *s, unsigned int nb_buckets)
56 ElfW(Sym) *sym;
57 int *ptr, *hash, nb_syms, sym_index, h;
58 char *strtab;
60 strtab = s->link->data;
61 nb_syms = s->data_offset / sizeof(ElfW(Sym));
63 s->hash->data_offset = 0;
64 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
65 ptr[0] = nb_buckets;
66 ptr[1] = nb_syms;
67 ptr += 2;
68 hash = ptr;
69 memset(hash, 0, (nb_buckets + 1) * sizeof(int));
70 ptr += nb_buckets + 1;
72 sym = (ElfW(Sym) *)s->data + 1;
73 for(sym_index = 1; sym_index < nb_syms; sym_index++) {
74 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
75 h = elf_hash(strtab + sym->st_name) % nb_buckets;
76 *ptr = hash[h];
77 hash[h] = sym_index;
78 } else {
79 *ptr = 0;
81 ptr++;
82 sym++;
86 /* return the symbol number */
87 ST_FUNC int put_elf_sym(Section *s, uplong value, unsigned long size,
88 int info, int other, int shndx, const char *name)
90 int name_offset, sym_index;
91 int nbuckets, h;
92 ElfW(Sym) *sym;
93 Section *hs;
95 sym = section_ptr_add(s, sizeof(ElfW(Sym)));
96 if (name)
97 name_offset = put_elf_str(s->link, name);
98 else
99 name_offset = 0;
100 /* XXX: endianness */
101 sym->st_name = name_offset;
102 sym->st_value = value;
103 sym->st_size = size;
104 sym->st_info = info;
105 sym->st_other = other;
106 sym->st_shndx = shndx;
107 sym_index = sym - (ElfW(Sym) *)s->data;
108 hs = s->hash;
109 if (hs) {
110 int *ptr, *base;
111 ptr = section_ptr_add(hs, sizeof(int));
112 base = (int *)hs->data;
113 /* only add global or weak symbols */
114 if (ELFW(ST_BIND)(info) != STB_LOCAL) {
115 /* add another hashing entry */
116 nbuckets = base[0];
117 h = elf_hash(name) % nbuckets;
118 *ptr = base[2 + h];
119 base[2 + h] = sym_index;
120 base[1]++;
121 /* we resize the hash table */
122 hs->nb_hashed_syms++;
123 if (hs->nb_hashed_syms > 2 * nbuckets) {
124 rebuild_hash(s, 2 * nbuckets);
126 } else {
127 *ptr = 0;
128 base[1]++;
131 return sym_index;
134 /* find global ELF symbol 'name' and return its index. Return 0 if not
135 found. */
136 ST_FUNC int find_elf_sym(Section *s, const char *name)
138 ElfW(Sym) *sym;
139 Section *hs;
140 int nbuckets, sym_index, h;
141 const char *name1;
143 hs = s->hash;
144 if (!hs)
145 return 0;
146 nbuckets = ((int *)hs->data)[0];
147 h = elf_hash(name) % nbuckets;
148 sym_index = ((int *)hs->data)[2 + h];
149 while (sym_index != 0) {
150 sym = &((ElfW(Sym) *)s->data)[sym_index];
151 name1 = s->link->data + sym->st_name;
152 if (!strcmp(name, name1))
153 return sym_index;
154 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
156 return 0;
159 /* return elf symbol value, signal error if 'err' is nonzero */
160 static void *get_elf_sym_addr(TCCState *s, const char *name, int err)
162 int sym_index;
163 ElfW(Sym) *sym;
165 sym_index = find_elf_sym(symtab_section, name);
166 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
167 if (!sym_index || sym->st_shndx == SHN_UNDEF) {
168 if (err)
169 error("%s not defined", name);
170 return NULL;
172 return (void*)(uplong)sym->st_value;
175 /* return elf symbol value */
176 LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
178 return get_elf_sym_addr(s, name, 0);
181 /* return elf symbol value or error */
182 ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name)
184 return get_elf_sym_addr(s, name, 1);
187 /* add an elf symbol : check if it is already defined and patch
188 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
189 ST_FUNC int add_elf_sym(Section *s, uplong value, unsigned long size,
190 int info, int other, int sh_num, const char *name)
192 ElfW(Sym) *esym;
193 int sym_bind, sym_index, sym_type, esym_bind;
194 unsigned char sym_vis, esym_vis, new_vis;
196 sym_bind = ELFW(ST_BIND)(info);
197 sym_type = ELFW(ST_TYPE)(info);
198 sym_vis = ELFW(ST_VISIBILITY)(other);
200 if (sym_bind != STB_LOCAL) {
201 /* we search global or weak symbols */
202 sym_index = find_elf_sym(s, name);
203 if (!sym_index)
204 goto do_def;
205 esym = &((ElfW(Sym) *)s->data)[sym_index];
206 if (esym->st_shndx != SHN_UNDEF) {
207 esym_bind = ELFW(ST_BIND)(esym->st_info);
208 /* propagate the most constraining visibility */
209 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
210 esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
211 if (esym_vis == STV_DEFAULT) {
212 new_vis = sym_vis;
213 } else if (sym_vis == STV_DEFAULT) {
214 new_vis = esym_vis;
215 } else {
216 new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
218 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
219 | new_vis;
220 other = esym->st_other; /* in case we have to patch esym */
221 if (sh_num == SHN_UNDEF) {
222 /* ignore adding of undefined symbol if the
223 corresponding symbol is already defined */
224 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
225 /* global overrides weak, so patch */
226 goto do_patch;
227 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
228 /* weak is ignored if already global */
229 } else if (sym_bind == STB_WEAK && esym_bind == STB_WEAK) {
230 /* keep first-found weak definition, ignore subsequents */
231 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
232 /* ignore hidden symbols after */
233 } else if (esym->st_shndx == SHN_COMMON
234 && (sh_num < SHN_LORESERVE || sh_num == SHN_COMMON)) {
235 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
236 No idea if this is the correct solution ... */
237 goto do_patch;
238 } else if (s == tcc_state->dynsymtab_section) {
239 /* we accept that two DLL define the same symbol */
240 } else {
241 #if 1
242 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
243 sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
244 #endif
245 error_noabort("'%s' defined twice", name);
247 } else {
248 do_patch:
249 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
250 esym->st_shndx = sh_num;
251 new_undef_sym = 1;
252 esym->st_value = value;
253 esym->st_size = size;
254 esym->st_other = other;
256 } else {
257 do_def:
258 sym_index = put_elf_sym(s, value, size,
259 ELFW(ST_INFO)(sym_bind, sym_type), other,
260 sh_num, name);
262 return sym_index;
265 /* put relocation */
266 ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
267 int type, int symbol)
269 char buf[256];
270 Section *sr;
271 ElfW_Rel *rel;
273 sr = s->reloc;
274 if (!sr) {
275 /* if no relocation section, create it */
276 snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
277 /* if the symtab is allocated, then we consider the relocation
278 are also */
279 sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
280 sr->sh_entsize = sizeof(ElfW_Rel);
281 sr->link = symtab;
282 sr->sh_info = s->sh_num;
283 s->reloc = sr;
285 rel = section_ptr_add(sr, sizeof(ElfW_Rel));
286 rel->r_offset = offset;
287 rel->r_info = ELFW(R_INFO)(symbol, type);
288 #ifdef TCC_TARGET_X86_64
289 rel->r_addend = 0;
290 #endif
293 /* put stab debug information */
295 ST_FUNC void put_stabs(const char *str, int type, int other, int desc,
296 unsigned long value)
298 Stab_Sym *sym;
300 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
301 if (str) {
302 sym->n_strx = put_elf_str(stabstr_section, str);
303 } else {
304 sym->n_strx = 0;
306 sym->n_type = type;
307 sym->n_other = other;
308 sym->n_desc = desc;
309 sym->n_value = value;
312 ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc,
313 unsigned long value, Section *sec, int sym_index)
315 put_stabs(str, type, other, desc, value);
316 put_elf_reloc(symtab_section, stab_section,
317 stab_section->data_offset - sizeof(unsigned int),
318 R_DATA_32, sym_index);
321 ST_FUNC void put_stabn(int type, int other, int desc, int value)
323 put_stabs(NULL, type, other, desc, value);
326 ST_FUNC void put_stabd(int type, int other, int desc)
328 put_stabs(NULL, type, other, desc, 0);
331 /* In an ELF file symbol table, the local symbols must appear below
332 the global and weak ones. Since TCC cannot sort it while generating
333 the code, we must do it after. All the relocation tables are also
334 modified to take into account the symbol table sorting */
335 static void sort_syms(TCCState *s1, Section *s)
337 int *old_to_new_syms;
338 ElfW(Sym) *new_syms;
339 int nb_syms, i;
340 ElfW(Sym) *p, *q;
341 ElfW_Rel *rel, *rel_end;
342 Section *sr;
343 int type, sym_index;
345 nb_syms = s->data_offset / sizeof(ElfW(Sym));
346 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
347 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
349 /* first pass for local symbols */
350 p = (ElfW(Sym) *)s->data;
351 q = new_syms;
352 for(i = 0; i < nb_syms; i++) {
353 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
354 old_to_new_syms[i] = q - new_syms;
355 *q++ = *p;
357 p++;
359 /* save the number of local symbols in section header */
360 s->sh_info = q - new_syms;
362 /* then second pass for non local symbols */
363 p = (ElfW(Sym) *)s->data;
364 for(i = 0; i < nb_syms; i++) {
365 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
366 old_to_new_syms[i] = q - new_syms;
367 *q++ = *p;
369 p++;
372 /* we copy the new symbols to the old */
373 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
374 tcc_free(new_syms);
376 /* now we modify all the relocations */
377 for(i = 1; i < s1->nb_sections; i++) {
378 sr = s1->sections[i];
379 if (sr->sh_type == SHT_RELX && sr->link == s) {
380 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
381 for(rel = (ElfW_Rel *)sr->data;
382 rel < rel_end;
383 rel++) {
384 sym_index = ELFW(R_SYM)(rel->r_info);
385 type = ELFW(R_TYPE)(rel->r_info);
386 sym_index = old_to_new_syms[sym_index];
387 rel->r_info = ELFW(R_INFO)(sym_index, type);
392 tcc_free(old_to_new_syms);
395 /* relocate common symbols in the .bss section */
396 ST_FUNC void relocate_common_syms(void)
398 ElfW(Sym) *sym, *sym_end;
399 unsigned long offset, align;
401 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
402 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
403 sym < sym_end;
404 sym++) {
405 if (sym->st_shndx == SHN_COMMON) {
406 /* align symbol */
407 align = sym->st_value;
408 offset = bss_section->data_offset;
409 offset = (offset + align - 1) & -align;
410 sym->st_value = offset;
411 sym->st_shndx = bss_section->sh_num;
412 offset += sym->st_size;
413 bss_section->data_offset = offset;
418 /* relocate symbol table, resolve undefined symbols if do_resolve is
419 true and output error if undefined symbol. */
420 ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
422 ElfW(Sym) *sym, *esym, *sym_end;
423 int sym_bind, sh_num, sym_index;
424 const char *name;
426 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
427 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
428 sym < sym_end;
429 sym++) {
430 sh_num = sym->st_shndx;
431 if (sh_num == SHN_UNDEF) {
432 name = strtab_section->data + sym->st_name;
433 if (do_resolve) {
434 #if !defined TCC_TARGET_PE || !defined _WIN32
435 void *addr;
436 name = symtab_section->link->data + sym->st_name;
437 addr = resolve_sym(s1, name);
438 if (addr) {
439 sym->st_value = (uplong)addr;
440 goto found;
442 #endif
443 } else if (s1->dynsym) {
444 /* if dynamic symbol exist, then use it */
445 sym_index = find_elf_sym(s1->dynsym, name);
446 if (sym_index) {
447 esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
448 sym->st_value = esym->st_value;
449 goto found;
452 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
453 it */
454 if (!strcmp(name, "_fp_hw"))
455 goto found;
456 /* only weak symbols are accepted to be undefined. Their
457 value is zero */
458 sym_bind = ELFW(ST_BIND)(sym->st_info);
459 if (sym_bind == STB_WEAK) {
460 sym->st_value = 0;
461 } else {
462 error_noabort("undefined symbol '%s'", name);
464 } else if (sh_num < SHN_LORESERVE) {
465 /* add section base */
466 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
468 found: ;
472 #ifndef TCC_TARGET_PE
473 #ifdef TCC_TARGET_X86_64
474 #define JMP_TABLE_ENTRY_SIZE 14
475 static uplong add_jmp_table(TCCState *s1, uplong val)
477 char *p = s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset;
478 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
479 /* jmp *0x0(%rip) */
480 p[0] = 0xff;
481 p[1] = 0x25;
482 *(int *)(p + 2) = 0;
483 *(uplong *)(p + 6) = val;
484 return (uplong)p;
487 static uplong add_got_table(TCCState *s1, uplong val)
489 uplong *p = (uplong *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
490 s1->runtime_plt_and_got_offset += sizeof(uplong);
491 *p = val;
492 return (uplong)p;
494 #elif defined TCC_TARGET_ARM
495 #define JMP_TABLE_ENTRY_SIZE 8
496 static uplong add_jmp_table(TCCState *s1, int val)
498 uint32_t *p = (uint32_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
499 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
500 /* ldr pc, [pc, #-4] */
501 p[0] = 0xE51FF004;
502 p[1] = val;
503 return (uplong)p;
505 #endif
506 #endif
508 /* relocate a given section (CPU dependent) */
509 ST_FUNC void relocate_section(TCCState *s1, Section *s)
511 Section *sr;
512 ElfW_Rel *rel, *rel_end, *qrel;
513 ElfW(Sym) *sym;
514 int type, sym_index;
515 unsigned char *ptr;
516 uplong val, addr;
517 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
518 int esym_index;
519 #endif
521 sr = s->reloc;
522 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
523 qrel = (ElfW_Rel *)sr->data;
524 for(rel = qrel;
525 rel < rel_end;
526 rel++) {
527 ptr = s->data + rel->r_offset;
529 sym_index = ELFW(R_SYM)(rel->r_info);
530 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
531 val = sym->st_value;
532 #ifdef TCC_TARGET_X86_64
533 val += rel->r_addend;
534 #endif
535 type = ELFW(R_TYPE)(rel->r_info);
536 addr = s->sh_addr + rel->r_offset;
538 /* CPU specific */
539 switch(type) {
540 #if defined(TCC_TARGET_I386)
541 case R_386_32:
542 if (s1->output_type == TCC_OUTPUT_DLL) {
543 esym_index = s1->symtab_to_dynsym[sym_index];
544 qrel->r_offset = rel->r_offset;
545 if (esym_index) {
546 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
547 qrel++;
548 break;
549 } else {
550 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
551 qrel++;
554 *(int *)ptr += val;
555 break;
556 case R_386_PC32:
557 if (s1->output_type == TCC_OUTPUT_DLL) {
558 /* DLL relocation */
559 esym_index = s1->symtab_to_dynsym[sym_index];
560 if (esym_index) {
561 qrel->r_offset = rel->r_offset;
562 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
563 qrel++;
564 break;
567 *(int *)ptr += val - addr;
568 break;
569 case R_386_PLT32:
570 *(int *)ptr += val - addr;
571 break;
572 case R_386_GLOB_DAT:
573 case R_386_JMP_SLOT:
574 *(int *)ptr = val;
575 break;
576 case R_386_GOTPC:
577 *(int *)ptr += s1->got->sh_addr - addr;
578 break;
579 case R_386_GOTOFF:
580 *(int *)ptr += val - s1->got->sh_addr;
581 break;
582 case R_386_GOT32:
583 /* we load the got offset */
584 *(int *)ptr += s1->got_offsets[sym_index];
585 break;
586 case R_386_16:
587 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
588 output_file:
589 error("can only produce 16-bit binary files");
591 *(short *)ptr += val;
592 break;
593 case R_386_PC16:
594 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
595 goto output_file;
596 *(short *)ptr += val - addr;
597 break;
598 #elif defined(TCC_TARGET_ARM)
599 case R_ARM_PC24:
600 case R_ARM_CALL:
601 case R_ARM_JUMP24:
602 case R_ARM_PLT32:
604 int x;
605 x = (*(int *)ptr)&0xffffff;
606 (*(int *)ptr) &= 0xff000000;
607 if (x & 0x800000)
608 x -= 0x1000000;
609 x *= 4;
610 x += val - addr;
611 #ifndef TCC_TARGET_PE
612 if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
613 if (s1->output_type == TCC_OUTPUT_MEMORY)
614 x += add_jmp_table(s1, val) - val; /* add veneer */
615 #endif
616 if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
617 error("can't relocate value at %x",addr);
618 x >>= 2;
619 x &= 0xffffff;
620 (*(int *)ptr) |= x;
622 break;
623 case R_ARM_PREL31:
625 int x;
626 x = (*(int *)ptr) & 0x7fffffff;
627 (*(int *)ptr) &= 0x80000000;
628 x = (x * 2) / 2;
629 x += val - addr;
630 if((x^(x>>1))&0x40000000)
631 error("can't relocate value at %x",addr);
632 (*(int *)ptr) |= x & 0x7fffffff;
634 case R_ARM_ABS32:
635 *(int *)ptr += val;
636 break;
637 case R_ARM_BASE_PREL:
638 *(int *)ptr += s1->got->sh_addr - addr;
639 break;
640 case R_ARM_GOTOFF32:
641 *(int *)ptr += val - s1->got->sh_addr;
642 break;
643 case R_ARM_GOT_BREL:
644 /* we load the got offset */
645 *(int *)ptr += s1->got_offsets[sym_index];
646 break;
647 case R_ARM_COPY:
648 break;
649 case R_ARM_V4BX:
650 /* trade Thumb support for ARMv4 support */
651 if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
652 *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
653 break;
654 default:
655 fprintf(stderr,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
656 type, (unsigned)addr, (unsigned)(uplong)ptr, (unsigned)val);
657 break;
658 #elif defined(TCC_TARGET_C67)
659 case R_C60_32:
660 *(int *)ptr += val;
661 break;
662 case R_C60LO16:
664 uint32_t orig;
666 /* put the low 16 bits of the absolute address */
667 // add to what is already there
669 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
670 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
672 //patch both at once - assumes always in pairs Low - High
674 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
675 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
677 break;
678 case R_C60HI16:
679 break;
680 default:
681 fprintf(stderr,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
682 type, (unsigned)addr, (unsigned)(uplong)ptr, (unsigned)val);
683 break;
684 #elif defined(TCC_TARGET_X86_64)
685 case R_X86_64_64:
686 if (s1->output_type == TCC_OUTPUT_DLL) {
687 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
688 qrel->r_addend = *(long long *)ptr + val;
689 qrel++;
691 *(long long *)ptr += val;
692 break;
693 case R_X86_64_32:
694 case R_X86_64_32S:
695 if (s1->output_type == TCC_OUTPUT_DLL) {
696 /* XXX: this logic may depend on TCC's codegen
697 now TCC uses R_X86_64_32 even for a 64bit pointer */
698 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
699 qrel->r_addend = *(int *)ptr + val;
700 qrel++;
702 *(int *)ptr += val;
703 break;
705 case R_X86_64_PC32:
706 if (s1->output_type == TCC_OUTPUT_DLL) {
707 /* DLL relocation */
708 esym_index = s1->symtab_to_dynsym[sym_index];
709 if (esym_index) {
710 qrel->r_offset = rel->r_offset;
711 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
712 qrel->r_addend = *(int *)ptr;
713 qrel++;
714 break;
717 /* fall through */
718 case R_X86_64_PLT32: {
719 long long diff;
720 diff = (long long)val - addr;
721 if (diff <= -2147483647 || diff > 2147483647) {
722 #ifndef TCC_TARGET_PE
723 /* XXX: naive support for over 32bit jump */
724 if (s1->output_type == TCC_OUTPUT_MEMORY) {
725 val = (add_jmp_table(s1, val - rel->r_addend) +
726 rel->r_addend);
727 diff = val - addr;
729 #endif
730 if (diff <= -2147483647 || diff > 2147483647) {
731 error("internal error: relocation failed");
734 *(int *)ptr += diff;
736 break;
737 case R_X86_64_GLOB_DAT:
738 case R_X86_64_JUMP_SLOT:
739 /* They don't need addend */
740 *(int *)ptr = val - rel->r_addend;
741 break;
742 case R_X86_64_GOTPCREL:
743 #ifndef TCC_TARGET_PE
744 if (s1->output_type == TCC_OUTPUT_MEMORY) {
745 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
746 *(int *)ptr += val - addr;
747 break;
749 #endif
750 *(int *)ptr += (s1->got->sh_addr - addr +
751 s1->got_offsets[sym_index] - 4);
752 break;
753 case R_X86_64_GOTTPOFF:
754 *(int *)ptr += val - s1->got->sh_addr;
755 break;
756 case R_X86_64_GOT32:
757 /* we load the got offset */
758 *(int *)ptr += s1->got_offsets[sym_index];
759 break;
760 #else
761 #error unsupported processor
762 #endif
765 /* if the relocation is allocated, we change its symbol table */
766 if (sr->sh_flags & SHF_ALLOC)
767 sr->link = s1->dynsym;
770 /* relocate relocation table in 'sr' */
771 static void relocate_rel(TCCState *s1, Section *sr)
773 Section *s;
774 ElfW_Rel *rel, *rel_end;
776 s = s1->sections[sr->sh_info];
777 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
778 for(rel = (ElfW_Rel *)sr->data;
779 rel < rel_end;
780 rel++) {
781 rel->r_offset += s->sh_addr;
785 /* count the number of dynamic relocations so that we can reserve
786 their space */
787 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
789 ElfW_Rel *rel, *rel_end;
790 int sym_index, esym_index, type, count;
792 count = 0;
793 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
794 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
795 sym_index = ELFW(R_SYM)(rel->r_info);
796 type = ELFW(R_TYPE)(rel->r_info);
797 switch(type) {
798 #if defined(TCC_TARGET_I386)
799 case R_386_32:
800 #elif defined(TCC_TARGET_X86_64)
801 case R_X86_64_32:
802 case R_X86_64_32S:
803 case R_X86_64_64:
804 #endif
805 count++;
806 break;
807 #if defined(TCC_TARGET_I386)
808 case R_386_PC32:
809 #elif defined(TCC_TARGET_X86_64)
810 case R_X86_64_PC32:
811 #endif
812 esym_index = s1->symtab_to_dynsym[sym_index];
813 if (esym_index)
814 count++;
815 break;
816 default:
817 break;
820 if (count) {
821 /* allocate the section */
822 sr->sh_flags |= SHF_ALLOC;
823 sr->sh_size = count * sizeof(ElfW_Rel);
825 return count;
828 static void put_got_offset(TCCState *s1, int index, unsigned long val)
830 int n;
831 unsigned long *tab;
833 if (index >= s1->nb_got_offsets) {
834 /* find immediately bigger power of 2 and reallocate array */
835 n = 1;
836 while (index >= n)
837 n *= 2;
838 tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
839 if (!tab)
840 error("memory full");
841 s1->got_offsets = tab;
842 memset(s1->got_offsets + s1->nb_got_offsets, 0,
843 (n - s1->nb_got_offsets) * sizeof(unsigned long));
844 s1->nb_got_offsets = n;
846 s1->got_offsets[index] = val;
849 /* XXX: suppress that */
850 static void put32(unsigned char *p, uint32_t val)
852 p[0] = val;
853 p[1] = val >> 8;
854 p[2] = val >> 16;
855 p[3] = val >> 24;
858 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
859 defined(TCC_TARGET_X86_64)
860 static uint32_t get32(unsigned char *p)
862 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
864 #endif
866 static void build_got(TCCState *s1)
868 unsigned char *ptr;
870 /* if no got, then create it */
871 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
872 s1->got->sh_entsize = 4;
873 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
874 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
875 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
876 #if PTR_SIZE == 4
877 /* keep space for _DYNAMIC pointer, if present */
878 put32(ptr, 0);
879 /* two dummy got entries */
880 put32(ptr + 4, 0);
881 put32(ptr + 8, 0);
882 #else
883 /* keep space for _DYNAMIC pointer, if present */
884 put32(ptr, 0);
885 put32(ptr + 4, 0);
886 /* two dummy got entries */
887 put32(ptr + 8, 0);
888 put32(ptr + 12, 0);
889 put32(ptr + 16, 0);
890 put32(ptr + 20, 0);
891 #endif
894 /* put a got entry corresponding to a symbol in symtab_section. 'size'
895 and 'info' can be modifed if more precise info comes from the DLL */
896 static void put_got_entry(TCCState *s1,
897 int reloc_type, unsigned long size, int info,
898 int sym_index)
900 int index;
901 const char *name;
902 ElfW(Sym) *sym;
903 unsigned long offset;
904 int *ptr;
906 if (!s1->got)
907 build_got(s1);
909 /* if a got entry already exists for that symbol, no need to add one */
910 if (sym_index < s1->nb_got_offsets &&
911 s1->got_offsets[sym_index] != 0)
912 return;
914 put_got_offset(s1, sym_index, s1->got->data_offset);
916 if (s1->dynsym) {
917 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
918 name = symtab_section->link->data + sym->st_name;
919 offset = sym->st_value;
920 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
921 if (reloc_type ==
922 #ifdef TCC_TARGET_X86_64
923 R_X86_64_JUMP_SLOT
924 #else
925 R_386_JMP_SLOT
926 #endif
928 Section *plt;
929 uint8_t *p;
930 int modrm;
932 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
933 modrm = 0x25;
934 #else
935 /* if we build a DLL, we add a %ebx offset */
936 if (s1->output_type == TCC_OUTPUT_DLL)
937 modrm = 0xa3;
938 else
939 modrm = 0x25;
940 #endif
942 /* add a PLT entry */
943 plt = s1->plt;
944 if (plt->data_offset == 0) {
945 /* first plt entry */
946 p = section_ptr_add(plt, 16);
947 p[0] = 0xff; /* pushl got + PTR_SIZE */
948 p[1] = modrm + 0x10;
949 put32(p + 2, PTR_SIZE);
950 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
951 p[7] = modrm;
952 put32(p + 8, PTR_SIZE * 2);
955 p = section_ptr_add(plt, 16);
956 p[0] = 0xff; /* jmp *(got + x) */
957 p[1] = modrm;
958 put32(p + 2, s1->got->data_offset);
959 p[6] = 0x68; /* push $xxx */
960 put32(p + 7, (plt->data_offset - 32) >> 1);
961 p[11] = 0xe9; /* jmp plt_start */
962 put32(p + 12, -(plt->data_offset));
964 /* the symbol is modified so that it will be relocated to
965 the PLT */
966 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
967 if (s1->output_type == TCC_OUTPUT_EXE)
968 #endif
969 offset = plt->data_offset - 16;
971 #elif defined(TCC_TARGET_ARM)
972 if (reloc_type == R_ARM_JUMP_SLOT) {
973 Section *plt;
974 uint8_t *p;
976 /* if we build a DLL, we add a %ebx offset */
977 if (s1->output_type == TCC_OUTPUT_DLL)
978 error("DLLs unimplemented!");
980 /* add a PLT entry */
981 plt = s1->plt;
982 if (plt->data_offset == 0) {
983 /* first plt entry */
984 p = section_ptr_add(plt, 16);
985 put32(p , 0xe52de004);
986 put32(p + 4, 0xe59fe010);
987 put32(p + 8, 0xe08fe00e);
988 put32(p + 12, 0xe5bef008);
991 p = section_ptr_add(plt, 16);
992 put32(p , 0xe59fc004);
993 put32(p+4, 0xe08fc00c);
994 put32(p+8, 0xe59cf000);
995 put32(p+12, s1->got->data_offset);
997 /* the symbol is modified so that it will be relocated to
998 the PLT */
999 if (s1->output_type == TCC_OUTPUT_EXE)
1000 offset = plt->data_offset - 16;
1002 #elif defined(TCC_TARGET_C67)
1003 error("C67 got not implemented");
1004 #else
1005 #error unsupported CPU
1006 #endif
1007 index = put_elf_sym(s1->dynsym, offset,
1008 size, info, 0, sym->st_shndx, name);
1009 /* put a got entry */
1010 put_elf_reloc(s1->dynsym, s1->got,
1011 s1->got->data_offset,
1012 reloc_type, index);
1014 ptr = section_ptr_add(s1->got, PTR_SIZE);
1015 *ptr = 0;
1018 /* build GOT and PLT entries */
1019 ST_FUNC void build_got_entries(TCCState *s1)
1021 Section *s;
1022 ElfW_Rel *rel, *rel_end;
1023 ElfW(Sym) *sym;
1024 int i, type, reloc_type, sym_index;
1026 for(i = 1; i < s1->nb_sections; i++) {
1027 s = s1->sections[i];
1028 if (s->sh_type != SHT_RELX)
1029 continue;
1030 /* no need to handle got relocations */
1031 if (s->link != symtab_section)
1032 continue;
1033 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1034 for(rel = (ElfW_Rel *)s->data;
1035 rel < rel_end;
1036 rel++) {
1037 type = ELFW(R_TYPE)(rel->r_info);
1038 switch(type) {
1039 #if defined(TCC_TARGET_I386)
1040 case R_386_GOT32:
1041 case R_386_GOTOFF:
1042 case R_386_GOTPC:
1043 case R_386_PLT32:
1044 if (!s1->got)
1045 build_got(s1);
1046 if (type == R_386_GOT32 || type == R_386_PLT32) {
1047 sym_index = ELFW(R_SYM)(rel->r_info);
1048 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1049 /* look at the symbol got offset. If none, then add one */
1050 if (type == R_386_GOT32)
1051 reloc_type = R_386_GLOB_DAT;
1052 else
1053 reloc_type = R_386_JMP_SLOT;
1054 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1055 sym_index);
1057 break;
1058 #elif defined(TCC_TARGET_ARM)
1059 case R_ARM_GOT_BREL:
1060 case R_ARM_GOTOFF32:
1061 case R_ARM_BASE_PREL:
1062 case R_ARM_PLT32:
1063 if (!s1->got)
1064 build_got(s1);
1065 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1066 sym_index = ELFW(R_SYM)(rel->r_info);
1067 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1068 /* look at the symbol got offset. If none, then add one */
1069 if (type == R_ARM_GOT_BREL)
1070 reloc_type = R_ARM_GLOB_DAT;
1071 else
1072 reloc_type = R_ARM_JUMP_SLOT;
1073 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1074 sym_index);
1076 break;
1077 #elif defined(TCC_TARGET_C67)
1078 case R_C60_GOT32:
1079 case R_C60_GOTOFF:
1080 case R_C60_GOTPC:
1081 case R_C60_PLT32:
1082 if (!s1->got)
1083 build_got(s1);
1084 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1085 sym_index = ELFW(R_SYM)(rel->r_info);
1086 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1087 /* look at the symbol got offset. If none, then add one */
1088 if (type == R_C60_GOT32)
1089 reloc_type = R_C60_GLOB_DAT;
1090 else
1091 reloc_type = R_C60_JMP_SLOT;
1092 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1093 sym_index);
1095 break;
1096 #elif defined(TCC_TARGET_X86_64)
1097 case R_X86_64_GOT32:
1098 case R_X86_64_GOTTPOFF:
1099 case R_X86_64_GOTPCREL:
1100 case R_X86_64_PLT32:
1101 if (!s1->got)
1102 build_got(s1);
1103 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1104 type == R_X86_64_PLT32) {
1105 sym_index = ELFW(R_SYM)(rel->r_info);
1106 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1107 /* look at the symbol got offset. If none, then add one */
1108 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1109 reloc_type = R_X86_64_GLOB_DAT;
1110 else
1111 reloc_type = R_X86_64_JUMP_SLOT;
1112 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1113 sym_index);
1115 break;
1116 #else
1117 #error unsupported CPU
1118 #endif
1119 default:
1120 break;
1126 ST_FUNC Section *new_symtab(TCCState *s1,
1127 const char *symtab_name, int sh_type, int sh_flags,
1128 const char *strtab_name,
1129 const char *hash_name, int hash_sh_flags)
1131 Section *symtab, *strtab, *hash;
1132 int *ptr, nb_buckets;
1134 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1135 symtab->sh_entsize = sizeof(ElfW(Sym));
1136 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1137 put_elf_str(strtab, "");
1138 symtab->link = strtab;
1139 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1141 nb_buckets = 1;
1143 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1144 hash->sh_entsize = sizeof(int);
1145 symtab->hash = hash;
1146 hash->link = symtab;
1148 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1149 ptr[0] = nb_buckets;
1150 ptr[1] = 1;
1151 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1152 return symtab;
1155 /* put dynamic tag */
1156 static void put_dt(Section *dynamic, int dt, unsigned long val)
1158 ElfW(Dyn) *dyn;
1159 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1160 dyn->d_tag = dt;
1161 dyn->d_un.d_val = val;
1164 static void add_init_array_defines(TCCState *s1, const char *section_name)
1166 Section *s;
1167 long end_offset;
1168 char sym_start[1024];
1169 char sym_end[1024];
1171 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1172 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1174 s = find_section(s1, section_name);
1175 if (!s) {
1176 end_offset = 0;
1177 s = data_section;
1178 } else {
1179 end_offset = s->data_offset;
1182 add_elf_sym(symtab_section,
1183 0, 0,
1184 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1185 s->sh_num, sym_start);
1186 add_elf_sym(symtab_section,
1187 end_offset, 0,
1188 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1189 s->sh_num, sym_end);
1192 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1194 #ifdef CONFIG_TCC_BCHECK
1195 unsigned long *ptr;
1196 Section *init_section;
1197 unsigned char *pinit;
1198 int sym_index;
1200 if (0 == s1->do_bounds_check)
1201 return;
1203 /* XXX: add an object file to do that */
1204 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1205 *ptr = 0;
1206 add_elf_sym(symtab_section, 0, 0,
1207 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1208 bounds_section->sh_num, "__bounds_start");
1209 /* add bound check code */
1210 #ifndef TCC_TARGET_PE
1212 char buf[1024];
1213 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "bcheck.o");
1214 tcc_add_file(s1, buf);
1216 #endif
1217 #ifdef TCC_TARGET_I386
1218 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1219 /* add 'call __bound_init()' in .init section */
1220 init_section = find_section(s1, ".init");
1221 pinit = section_ptr_add(init_section, 5);
1222 pinit[0] = 0xe8;
1223 put32(pinit + 1, -4);
1224 sym_index = find_elf_sym(symtab_section, "__bound_init");
1225 put_elf_reloc(symtab_section, init_section,
1226 init_section->data_offset - 4, R_386_PC32, sym_index);
1228 #endif
1229 #endif
1232 /* add tcc runtime libraries */
1233 ST_FUNC void tcc_add_runtime(TCCState *s1)
1235 tcc_add_bcheck(s1);
1237 /* add libc */
1238 if (!s1->nostdlib) {
1239 #ifdef CONFIG_USE_LIBGCC
1240 tcc_add_library(s1, "c");
1241 #ifdef CONFIG_TCC_MULTIARCH_TRIPLET
1242 if (tcc_add_file_internal(s1, CONFIG_SYSROOT CONFIG_TCC_LDDIR "/" CONFIG_TCC_MULTIARCH_TRIPLET "/libgcc_s.so.1", 0))
1243 #endif
1244 tcc_add_file(s1, CONFIG_SYSROOT CONFIG_TCC_LDDIR"/libgcc_s.so.1");
1245 #else
1246 tcc_add_library(s1, "c");
1247 #ifndef WITHOUT_LIBTCC
1249 char buf[1024];
1250 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "libtcc1.a");
1251 tcc_add_file(s1, buf);
1253 #endif
1254 #endif
1256 /* add crt end if not memory output */
1257 if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) {
1258 #ifdef CONFIG_TCC_MULTIARCH_TRIPLET
1259 if (tcc_add_file_internal(s1, CONFIG_SYSROOT CONFIG_TCC_CRT_PREFIX "/" CONFIG_TCC_MULTIARCH_TRIPLET "/crtn.o", 0))
1260 #endif
1261 tcc_add_file(s1, CONFIG_SYSROOT CONFIG_TCC_CRT_PREFIX "/crtn.o");
1265 /* add various standard linker symbols (must be done after the
1266 sections are filled (for example after allocating common
1267 symbols)) */
1268 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1270 char buf[1024];
1271 int i;
1272 Section *s;
1274 add_elf_sym(symtab_section,
1275 text_section->data_offset, 0,
1276 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1277 text_section->sh_num, "_etext");
1278 add_elf_sym(symtab_section,
1279 data_section->data_offset, 0,
1280 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1281 data_section->sh_num, "_edata");
1282 add_elf_sym(symtab_section,
1283 bss_section->data_offset, 0,
1284 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1285 bss_section->sh_num, "_end");
1286 /* horrible new standard ldscript defines */
1287 add_init_array_defines(s1, ".preinit_array");
1288 add_init_array_defines(s1, ".init_array");
1289 add_init_array_defines(s1, ".fini_array");
1291 /* add start and stop symbols for sections whose name can be
1292 expressed in C */
1293 for(i = 1; i < s1->nb_sections; i++) {
1294 s = s1->sections[i];
1295 if (s->sh_type == SHT_PROGBITS &&
1296 (s->sh_flags & SHF_ALLOC)) {
1297 const char *p;
1298 int ch;
1300 /* check if section name can be expressed in C */
1301 p = s->name;
1302 for(;;) {
1303 ch = *p;
1304 if (!ch)
1305 break;
1306 if (!isid(ch) && !isnum(ch))
1307 goto next_sec;
1308 p++;
1310 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1311 add_elf_sym(symtab_section,
1312 0, 0,
1313 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1314 s->sh_num, buf);
1315 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1316 add_elf_sym(symtab_section,
1317 s->data_offset, 0,
1318 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1319 s->sh_num, buf);
1321 next_sec: ;
1325 /* name of ELF interpreter */
1326 #if defined __FreeBSD__
1327 static const char elf_interp[] = "/libexec/ld-elf.so.1";
1328 #elif defined __FreeBSD_kernel__
1329 static char elf_interp[] = CONFIG_TCC_LDDIR"/ld.so.1";
1330 #elif defined TCC_ARM_EABI
1331 static const char elf_interp[] = CONFIG_TCC_LDDIR"/ld-linux.so.3";
1332 #elif defined(TCC_TARGET_X86_64)
1333 static const char elf_interp[] = CONFIG_TCC_LDDIR"/ld-linux-x86-64.so.2";
1334 #elif defined(TCC_UCLIBC)
1335 static const char elf_interp[] = CONFIG_TCC_LDDIR"/ld-uClibc.so.0";
1336 #else
1337 static const char elf_interp[] = CONFIG_TCC_LDDIR"/ld-linux.so.2";
1338 #endif
1340 static void tcc_output_binary(TCCState *s1, FILE *f,
1341 const int *section_order)
1343 Section *s;
1344 int i, offset, size;
1346 offset = 0;
1347 for(i=1;i<s1->nb_sections;i++) {
1348 s = s1->sections[section_order[i]];
1349 if (s->sh_type != SHT_NOBITS &&
1350 (s->sh_flags & SHF_ALLOC)) {
1351 while (offset < s->sh_offset) {
1352 fputc(0, f);
1353 offset++;
1355 size = s->sh_size;
1356 fwrite(s->data, 1, size, f);
1357 offset += size;
1362 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1363 #define HAVE_PHDR 1
1364 #define EXTRA_RELITEMS 14
1366 /* move the relocation value from .dynsym to .got */
1367 void patch_dynsym_undef(TCCState *s1, Section *s)
1369 uint32_t *gotd = (void *)s1->got->data;
1370 ElfW(Sym) *sym, *sym_end;
1372 gotd += 3; // dummy entries in .got
1373 /* relocate symbols in .dynsym */
1374 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1375 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1376 if (sym->st_shndx == SHN_UNDEF) {
1377 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1378 sym->st_value = 0;
1382 #else
1383 #define HAVE_PHDR 0
1384 #define EXTRA_RELITEMS 9
1385 #endif
1387 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1389 int sym_index = ELFW(R_SYM) (rel->r_info);
1390 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1391 unsigned long offset;
1393 if (sym_index >= s1->nb_got_offsets)
1394 return;
1395 offset = s1->got_offsets[sym_index];
1396 section_reserve(s1->got, offset + PTR_SIZE);
1397 #ifdef TCC_TARGET_X86_64
1398 /* only works for x86-64 */
1399 put32(s1->got->data + offset, sym->st_value >> 32);
1400 #endif
1401 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1404 ST_FUNC void fill_got(TCCState *s1)
1406 Section *s;
1407 ElfW_Rel *rel, *rel_end;
1408 int i;
1410 for(i = 1; i < s1->nb_sections; i++) {
1411 s = s1->sections[i];
1412 if (s->sh_type != SHT_RELX)
1413 continue;
1414 /* no need to handle got relocations */
1415 if (s->link != symtab_section)
1416 continue;
1417 rel_end = (ElfW_Rel *) (s->data + s->data_offset);
1418 for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
1419 switch (ELFW(R_TYPE) (rel->r_info)) {
1420 case R_X86_64_GOT32:
1421 case R_X86_64_GOTPCREL:
1422 case R_X86_64_PLT32:
1423 fill_got_entry(s1, rel);
1424 break;
1431 /* output an ELF file */
1432 /* XXX: suppress unneeded sections */
1433 static int elf_output_file(TCCState *s1, const char *filename)
1435 ElfW(Ehdr) ehdr;
1436 FILE *f;
1437 int fd, mode, ret;
1438 int *section_order;
1439 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
1440 unsigned long addr;
1441 Section *strsec, *s;
1442 ElfW(Shdr) shdr, *sh;
1443 ElfW(Phdr) *phdr, *ph;
1444 Section *interp, *dynamic, *dynstr;
1445 unsigned long saved_dynamic_data_offset;
1446 ElfW(Sym) *sym;
1447 int type, file_type;
1448 unsigned long rel_addr, rel_size;
1449 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1450 unsigned long bss_addr, bss_size;
1451 #endif
1453 file_type = s1->output_type;
1454 s1->nb_errors = 0;
1456 if (file_type != TCC_OUTPUT_OBJ) {
1457 tcc_add_runtime(s1);
1460 phdr = NULL;
1461 section_order = NULL;
1462 interp = NULL;
1463 dynamic = NULL;
1464 dynstr = NULL; /* avoid warning */
1465 saved_dynamic_data_offset = 0; /* avoid warning */
1467 if (file_type != TCC_OUTPUT_OBJ) {
1468 relocate_common_syms();
1470 tcc_add_linker_symbols(s1);
1472 if (!s1->static_link) {
1473 const char *name;
1474 int sym_index, index;
1475 ElfW(Sym) *esym, *sym_end;
1477 if (file_type == TCC_OUTPUT_EXE) {
1478 char *ptr;
1479 /* allow override the dynamic loader */
1480 const char *elfint = getenv("LD_SO");
1481 if (elfint == NULL)
1482 elfint = elf_interp;
1483 /* add interpreter section only if executable */
1484 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1485 interp->sh_addralign = 1;
1486 ptr = section_ptr_add(interp, 1+strlen(elfint));
1487 strcpy(ptr, elfint);
1490 /* add dynamic symbol table */
1491 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1492 ".dynstr",
1493 ".hash", SHF_ALLOC);
1494 dynstr = s1->dynsym->link;
1496 /* add dynamic section */
1497 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1498 SHF_ALLOC | SHF_WRITE);
1499 dynamic->link = dynstr;
1500 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1502 /* add PLT */
1503 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1504 SHF_ALLOC | SHF_EXECINSTR);
1505 s1->plt->sh_entsize = 4;
1507 build_got(s1);
1509 /* scan for undefined symbols and see if they are in the
1510 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1511 is found, then we add it in the PLT. If a symbol
1512 STT_OBJECT is found, we add it in the .bss section with
1513 a suitable relocation */
1514 sym_end = (ElfW(Sym) *)(symtab_section->data +
1515 symtab_section->data_offset);
1516 if (file_type == TCC_OUTPUT_EXE) {
1517 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1518 sym < sym_end;
1519 sym++) {
1520 if (sym->st_shndx == SHN_UNDEF) {
1521 name = symtab_section->link->data + sym->st_name;
1522 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1523 if (sym_index) {
1524 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1525 type = ELFW(ST_TYPE)(esym->st_info);
1526 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1527 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1528 esym->st_info,
1529 sym - (ElfW(Sym) *)symtab_section->data);
1530 } else if (type == STT_OBJECT) {
1531 unsigned long offset;
1532 ElfW(Sym) *dynsym, *dynsym_end;
1533 offset = bss_section->data_offset;
1534 /* XXX: which alignment ? */
1535 offset = (offset + 16 - 1) & -16;
1536 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1537 esym->st_info, 0,
1538 bss_section->sh_num, name);
1539 // Ensure R_COPY works for weak symbol aliases
1540 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1541 dynsym_end = (ElfW(Sym) *)
1542 (s1->dynsymtab_section->data +
1543 s1->dynsymtab_section->data_offset);
1544 for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1545 dynsym < dynsym_end; dynsym++) {
1546 if ((dynsym->st_value == esym->st_value)
1547 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1548 char *dynname;
1549 dynname = s1->dynsymtab_section->link->data
1550 + dynsym->st_name;
1551 put_elf_sym(s1->dynsym, offset,
1552 dynsym->st_size,
1553 dynsym->st_info, 0,
1554 bss_section->sh_num,
1555 dynname);
1556 break;
1560 put_elf_reloc(s1->dynsym, bss_section,
1561 offset, R_COPY, index);
1562 offset += esym->st_size;
1563 bss_section->data_offset = offset;
1565 } else {
1566 /* STB_WEAK undefined symbols are accepted */
1567 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1568 it */
1569 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1570 !strcmp(name, "_fp_hw")) {
1571 } else {
1572 error_noabort("undefined symbol '%s'", name);
1575 } else if (s1->rdynamic &&
1576 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1577 /* if -rdynamic option, then export all non
1578 local symbols */
1579 name = symtab_section->link->data + sym->st_name;
1580 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1581 sym->st_info, 0,
1582 sym->st_shndx, name);
1586 if (s1->nb_errors)
1587 goto fail;
1589 /* now look at unresolved dynamic symbols and export
1590 corresponding symbol */
1591 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1592 s1->dynsymtab_section->data_offset);
1593 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1594 esym < sym_end;
1595 esym++) {
1596 if (esym->st_shndx == SHN_UNDEF) {
1597 name = s1->dynsymtab_section->link->data + esym->st_name;
1598 sym_index = find_elf_sym(symtab_section, name);
1599 if (sym_index) {
1600 /* XXX: avoid adding a symbol if already
1601 present because of -rdynamic ? */
1602 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1603 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1604 sym->st_info, 0,
1605 sym->st_shndx, name);
1606 } else {
1607 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1608 /* weak symbols can stay undefined */
1609 } else {
1610 warning("undefined dynamic symbol '%s'", name);
1615 } else {
1616 int nb_syms;
1617 /* shared library case : we simply export all the global symbols */
1618 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1619 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1620 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1621 sym < sym_end;
1622 sym++) {
1623 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1624 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1625 if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
1626 ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
1627 && sym->st_shndx == SHN_UNDEF) {
1628 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1629 sym->st_info,
1630 sym - (ElfW(Sym) *)symtab_section->data);
1632 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1633 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1634 sym->st_info,
1635 sym - (ElfW(Sym) *)symtab_section->data);
1637 else
1638 #endif
1640 name = symtab_section->link->data + sym->st_name;
1641 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1642 sym->st_info, 0,
1643 sym->st_shndx, name);
1644 s1->symtab_to_dynsym[sym -
1645 (ElfW(Sym) *)symtab_section->data] =
1646 index;
1652 build_got_entries(s1);
1654 /* add a list of needed dlls */
1655 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1656 DLLReference *dllref = s1->loaded_dlls[i];
1657 if (dllref->level == 0)
1658 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1661 if (s1->rpath)
1662 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1664 /* XXX: currently, since we do not handle PIC code, we
1665 must relocate the readonly segments */
1666 if (file_type == TCC_OUTPUT_DLL) {
1667 if (s1->soname)
1668 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1669 put_dt(dynamic, DT_TEXTREL, 0);
1672 if (s1->symbolic)
1673 put_dt(dynamic, DT_SYMBOLIC, 0);
1675 /* add necessary space for other entries */
1676 saved_dynamic_data_offset = dynamic->data_offset;
1677 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1678 } else {
1679 /* still need to build got entries in case of static link */
1680 build_got_entries(s1);
1684 memset(&ehdr, 0, sizeof(ehdr));
1686 /* we add a section for symbols */
1687 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1688 put_elf_str(strsec, "");
1690 /* compute number of sections */
1691 shnum = s1->nb_sections;
1693 /* this array is used to reorder sections in the output file */
1694 section_order = tcc_malloc(sizeof(int) * shnum);
1695 section_order[0] = 0;
1696 sh_order_index = 1;
1698 /* compute number of program headers */
1699 switch(file_type) {
1700 default:
1701 case TCC_OUTPUT_OBJ:
1702 phnum = 0;
1703 break;
1704 case TCC_OUTPUT_EXE:
1705 if (!s1->static_link)
1706 phnum = 4 + HAVE_PHDR;
1707 else
1708 phnum = 2;
1709 break;
1710 case TCC_OUTPUT_DLL:
1711 phnum = 3;
1712 break;
1715 /* allocate strings for section names and decide if an unallocated
1716 section should be output */
1717 /* NOTE: the strsec section comes last, so its size is also
1718 correct ! */
1719 for(i = 1; i < s1->nb_sections; i++) {
1720 s = s1->sections[i];
1721 s->sh_name = put_elf_str(strsec, s->name);
1722 #if 0 //gr
1723 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1724 s->sh_flags,
1725 s->sh_type,
1726 s->sh_info,
1727 s->name,
1728 s->reloc ? s->reloc->name : "n"
1730 #endif
1731 /* when generating a DLL, we include relocations but we may
1732 patch them */
1733 if (file_type == TCC_OUTPUT_DLL &&
1734 s->sh_type == SHT_RELX &&
1735 !(s->sh_flags & SHF_ALLOC)) {
1736 /* //gr: avoid bogus relocs for empty (debug) sections */
1737 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1738 prepare_dynamic_rel(s1, s);
1739 else if (s1->do_debug)
1740 s->sh_size = s->data_offset;
1741 } else if (s1->do_debug ||
1742 file_type == TCC_OUTPUT_OBJ ||
1743 (s->sh_flags & SHF_ALLOC) ||
1744 i == (s1->nb_sections - 1)) {
1745 /* we output all sections if debug or object file */
1746 s->sh_size = s->data_offset;
1750 /* allocate program segment headers */
1751 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1753 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1754 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1755 } else {
1756 file_offset = 0;
1758 if (phnum > 0) {
1759 /* compute section to program header mapping */
1760 if (s1->has_text_addr) {
1761 int a_offset, p_offset;
1762 addr = s1->text_addr;
1763 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1764 ELF_PAGE_SIZE */
1765 a_offset = addr & (s1->section_align - 1);
1766 p_offset = file_offset & (s1->section_align - 1);
1767 if (a_offset < p_offset)
1768 a_offset += s1->section_align;
1769 file_offset += (a_offset - p_offset);
1770 } else {
1771 if (file_type == TCC_OUTPUT_DLL)
1772 addr = 0;
1773 else
1774 addr = ELF_START_ADDR;
1775 /* compute address after headers */
1776 addr += (file_offset & (s1->section_align - 1));
1779 /* dynamic relocation table information, for .dynamic section */
1780 rel_size = 0;
1781 rel_addr = 0;
1783 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1784 bss_addr = bss_size = 0;
1785 #endif
1786 /* leave one program header for the program interpreter */
1787 ph = &phdr[0];
1788 if (interp)
1789 ph += 1 + HAVE_PHDR;
1791 for(j = 0; j < 2; j++) {
1792 ph->p_type = PT_LOAD;
1793 if (j == 0)
1794 ph->p_flags = PF_R | PF_X;
1795 else
1796 ph->p_flags = PF_R | PF_W;
1797 ph->p_align = s1->section_align;
1799 /* we do the following ordering: interp, symbol tables,
1800 relocations, progbits, nobits */
1801 /* XXX: do faster and simpler sorting */
1802 for(k = 0; k < 5; k++) {
1803 for(i = 1; i < s1->nb_sections; i++) {
1804 s = s1->sections[i];
1805 /* compute if section should be included */
1806 if (j == 0) {
1807 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1808 SHF_ALLOC)
1809 continue;
1810 } else {
1811 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1812 (SHF_ALLOC | SHF_WRITE))
1813 continue;
1815 if (s == interp) {
1816 if (k != 0)
1817 continue;
1818 } else if (s->sh_type == SHT_DYNSYM ||
1819 s->sh_type == SHT_STRTAB ||
1820 s->sh_type == SHT_HASH) {
1821 if (k != 1)
1822 continue;
1823 } else if (s->sh_type == SHT_RELX) {
1824 if (k != 2)
1825 continue;
1826 } else if (s->sh_type == SHT_NOBITS) {
1827 if (k != 4)
1828 continue;
1829 } else {
1830 if (k != 3)
1831 continue;
1833 section_order[sh_order_index++] = i;
1835 /* section matches: we align it and add its size */
1836 tmp = addr;
1837 addr = (addr + s->sh_addralign - 1) &
1838 ~(s->sh_addralign - 1);
1839 file_offset += addr - tmp;
1840 s->sh_offset = file_offset;
1841 s->sh_addr = addr;
1843 /* update program header infos */
1844 if (ph->p_offset == 0) {
1845 ph->p_offset = file_offset;
1846 ph->p_vaddr = addr;
1847 ph->p_paddr = ph->p_vaddr;
1849 /* update dynamic relocation infos */
1850 if (s->sh_type == SHT_RELX) {
1851 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1852 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1853 rel_addr = addr;
1854 rel_size += s->sh_size; // XXX only first rel.
1856 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1857 bss_addr = addr;
1858 bss_size = s->sh_size; // XXX only first rel.
1860 #else
1861 if (rel_size == 0)
1862 rel_addr = addr;
1863 rel_size += s->sh_size;
1864 #endif
1866 addr += s->sh_size;
1867 if (s->sh_type != SHT_NOBITS)
1868 file_offset += s->sh_size;
1871 ph->p_filesz = file_offset - ph->p_offset;
1872 ph->p_memsz = addr - ph->p_vaddr;
1873 ph++;
1874 if (j == 0) {
1875 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1876 /* if in the middle of a page, we duplicate the page in
1877 memory so that one copy is RX and the other is RW */
1878 if ((addr & (s1->section_align - 1)) != 0)
1879 addr += s1->section_align;
1880 } else {
1881 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1882 file_offset = (file_offset + s1->section_align - 1) &
1883 ~(s1->section_align - 1);
1888 /* if interpreter, then add corresponing program header */
1889 if (interp) {
1890 ph = &phdr[0];
1892 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1894 int len = phnum * sizeof(ElfW(Phdr));
1896 ph->p_type = PT_PHDR;
1897 ph->p_offset = sizeof(ElfW(Ehdr));
1898 ph->p_vaddr = interp->sh_addr - len;
1899 ph->p_paddr = ph->p_vaddr;
1900 ph->p_filesz = ph->p_memsz = len;
1901 ph->p_flags = PF_R | PF_X;
1902 ph->p_align = 4; // interp->sh_addralign;
1903 ph++;
1905 #endif
1907 ph->p_type = PT_INTERP;
1908 ph->p_offset = interp->sh_offset;
1909 ph->p_vaddr = interp->sh_addr;
1910 ph->p_paddr = ph->p_vaddr;
1911 ph->p_filesz = interp->sh_size;
1912 ph->p_memsz = interp->sh_size;
1913 ph->p_flags = PF_R;
1914 ph->p_align = interp->sh_addralign;
1917 /* if dynamic section, then add corresponing program header */
1918 if (dynamic) {
1919 ElfW(Sym) *sym_end;
1921 ph = &phdr[phnum - 1];
1923 ph->p_type = PT_DYNAMIC;
1924 ph->p_offset = dynamic->sh_offset;
1925 ph->p_vaddr = dynamic->sh_addr;
1926 ph->p_paddr = ph->p_vaddr;
1927 ph->p_filesz = dynamic->sh_size;
1928 ph->p_memsz = dynamic->sh_size;
1929 ph->p_flags = PF_R | PF_W;
1930 ph->p_align = dynamic->sh_addralign;
1932 /* put GOT dynamic section address */
1933 put32(s1->got->data, dynamic->sh_addr);
1935 /* relocate the PLT */
1936 if (file_type == TCC_OUTPUT_EXE
1937 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1938 || file_type == TCC_OUTPUT_DLL
1939 #endif
1941 uint8_t *p, *p_end;
1943 p = s1->plt->data;
1944 p_end = p + s1->plt->data_offset;
1945 if (p < p_end) {
1946 #if defined(TCC_TARGET_I386)
1947 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1948 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1949 p += 16;
1950 while (p < p_end) {
1951 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1952 p += 16;
1954 #elif defined(TCC_TARGET_X86_64)
1955 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1956 put32(p + 2, get32(p + 2) + x);
1957 put32(p + 8, get32(p + 8) + x - 6);
1958 p += 16;
1959 while (p < p_end) {
1960 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1961 p += 16;
1963 #elif defined(TCC_TARGET_ARM)
1964 int x;
1965 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1966 p +=16;
1967 while (p < p_end) {
1968 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1969 p += 16;
1971 #elif defined(TCC_TARGET_C67)
1972 /* XXX: TODO */
1973 #else
1974 #error unsupported CPU
1975 #endif
1979 /* relocate symbols in .dynsym */
1980 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
1981 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
1982 sym < sym_end;
1983 sym++) {
1984 if (sym->st_shndx == SHN_UNDEF) {
1985 /* relocate to the PLT if the symbol corresponds
1986 to a PLT entry */
1987 if (sym->st_value)
1988 sym->st_value += s1->plt->sh_addr;
1989 } else if (sym->st_shndx < SHN_LORESERVE) {
1990 /* do symbol relocation */
1991 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
1995 /* put dynamic section entries */
1996 dynamic->data_offset = saved_dynamic_data_offset;
1997 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
1998 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
1999 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2000 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
2001 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2002 #ifdef TCC_TARGET_X86_64
2003 put_dt(dynamic, DT_RELA, rel_addr);
2004 put_dt(dynamic, DT_RELASZ, rel_size);
2005 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2006 #else
2007 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2008 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2009 put_dt(dynamic, DT_PLTRELSZ, rel_size);
2010 put_dt(dynamic, DT_JMPREL, rel_addr);
2011 put_dt(dynamic, DT_PLTREL, DT_REL);
2012 put_dt(dynamic, DT_REL, bss_addr);
2013 put_dt(dynamic, DT_RELSZ, bss_size);
2014 #else
2015 put_dt(dynamic, DT_REL, rel_addr);
2016 put_dt(dynamic, DT_RELSZ, rel_size);
2017 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2018 #endif
2019 #endif
2020 if (s1->do_debug)
2021 put_dt(dynamic, DT_DEBUG, 0);
2022 put_dt(dynamic, DT_NULL, 0);
2025 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2026 ehdr.e_phnum = phnum;
2027 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2030 /* all other sections come after */
2031 for(i = 1; i < s1->nb_sections; i++) {
2032 s = s1->sections[i];
2033 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2034 continue;
2035 section_order[sh_order_index++] = i;
2037 file_offset = (file_offset + s->sh_addralign - 1) &
2038 ~(s->sh_addralign - 1);
2039 s->sh_offset = file_offset;
2040 if (s->sh_type != SHT_NOBITS)
2041 file_offset += s->sh_size;
2044 /* if building executable or DLL, then relocate each section
2045 except the GOT which is already relocated */
2046 if (file_type != TCC_OUTPUT_OBJ) {
2047 relocate_syms(s1, 0);
2049 if (s1->nb_errors != 0) {
2050 fail:
2051 ret = -1;
2052 goto the_end;
2055 /* relocate sections */
2056 /* XXX: ignore sections with allocated relocations ? */
2057 for(i = 1; i < s1->nb_sections; i++) {
2058 s = s1->sections[i];
2059 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
2060 relocate_section(s1, s);
2063 /* relocate relocation entries if the relocation tables are
2064 allocated in the executable */
2065 for(i = 1; i < s1->nb_sections; i++) {
2066 s = s1->sections[i];
2067 if ((s->sh_flags & SHF_ALLOC) &&
2068 s->sh_type == SHT_RELX) {
2069 relocate_rel(s1, s);
2073 /* get entry point address */
2074 if (file_type == TCC_OUTPUT_EXE)
2075 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
2076 else
2077 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2079 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2080 fill_got(s1);
2082 /* write elf file */
2083 if (file_type == TCC_OUTPUT_OBJ)
2084 mode = 0666;
2085 else
2086 mode = 0777;
2087 unlink(filename);
2088 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2089 if (fd < 0) {
2090 error_noabort("could not write '%s'", filename);
2091 goto fail;
2093 f = fdopen(fd, "wb");
2094 if (s1->verbose)
2095 printf("<- %s\n", filename);
2097 #ifdef TCC_TARGET_COFF
2098 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2099 tcc_output_coff(s1, f);
2100 } else
2101 #endif
2102 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2103 sort_syms(s1, symtab_section);
2105 /* align to 4 */
2106 file_offset = (file_offset + 3) & -4;
2108 /* fill header */
2109 ehdr.e_ident[0] = ELFMAG0;
2110 ehdr.e_ident[1] = ELFMAG1;
2111 ehdr.e_ident[2] = ELFMAG2;
2112 ehdr.e_ident[3] = ELFMAG3;
2113 ehdr.e_ident[4] = ELFCLASSW;
2114 ehdr.e_ident[5] = ELFDATA2LSB;
2115 ehdr.e_ident[6] = EV_CURRENT;
2116 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2117 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2118 #endif
2119 #ifdef TCC_TARGET_ARM
2120 #ifdef TCC_ARM_EABI
2121 ehdr.e_ident[EI_OSABI] = 0;
2122 ehdr.e_flags = 4 << 24;
2123 #else
2124 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2125 #endif
2126 #endif
2127 switch(file_type) {
2128 default:
2129 case TCC_OUTPUT_EXE:
2130 ehdr.e_type = ET_EXEC;
2131 break;
2132 case TCC_OUTPUT_DLL:
2133 ehdr.e_type = ET_DYN;
2134 break;
2135 case TCC_OUTPUT_OBJ:
2136 ehdr.e_type = ET_REL;
2137 break;
2139 ehdr.e_machine = EM_TCC_TARGET;
2140 ehdr.e_version = EV_CURRENT;
2141 ehdr.e_shoff = file_offset;
2142 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2143 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2144 ehdr.e_shnum = shnum;
2145 ehdr.e_shstrndx = shnum - 1;
2147 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2148 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2149 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2151 for(i=1;i<s1->nb_sections;i++) {
2152 s = s1->sections[section_order[i]];
2153 if (s->sh_type != SHT_NOBITS) {
2154 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2155 if (s->sh_type == SHT_DYNSYM)
2156 patch_dynsym_undef(s1, s);
2157 #endif
2158 while (offset < s->sh_offset) {
2159 fputc(0, f);
2160 offset++;
2162 size = s->sh_size;
2163 fwrite(s->data, 1, size, f);
2164 offset += size;
2168 /* output section headers */
2169 while (offset < ehdr.e_shoff) {
2170 fputc(0, f);
2171 offset++;
2174 for(i=0;i<s1->nb_sections;i++) {
2175 sh = &shdr;
2176 memset(sh, 0, sizeof(ElfW(Shdr)));
2177 s = s1->sections[i];
2178 if (s) {
2179 sh->sh_name = s->sh_name;
2180 sh->sh_type = s->sh_type;
2181 sh->sh_flags = s->sh_flags;
2182 sh->sh_entsize = s->sh_entsize;
2183 sh->sh_info = s->sh_info;
2184 if (s->link)
2185 sh->sh_link = s->link->sh_num;
2186 sh->sh_addralign = s->sh_addralign;
2187 sh->sh_addr = s->sh_addr;
2188 sh->sh_offset = s->sh_offset;
2189 sh->sh_size = s->sh_size;
2191 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2193 } else {
2194 tcc_output_binary(s1, f, section_order);
2196 fclose(f);
2198 ret = 0;
2199 the_end:
2200 tcc_free(s1->symtab_to_dynsym);
2201 tcc_free(section_order);
2202 tcc_free(phdr);
2203 tcc_free(s1->got_offsets);
2204 return ret;
2207 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2209 int ret;
2210 #ifdef TCC_TARGET_PE
2211 if (s->output_type != TCC_OUTPUT_OBJ) {
2212 ret = pe_output_file(s, filename);
2213 } else
2214 #endif
2216 ret = elf_output_file(s, filename);
2218 return ret;
2221 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2223 void *data;
2225 data = tcc_malloc(size);
2226 lseek(fd, file_offset, SEEK_SET);
2227 read(fd, data, size);
2228 return data;
2231 typedef struct SectionMergeInfo {
2232 Section *s; /* corresponding existing section */
2233 unsigned long offset; /* offset of the new section in the existing section */
2234 uint8_t new_section; /* true if section 's' was added */
2235 uint8_t link_once; /* true if link once section */
2236 } SectionMergeInfo;
2238 /* load an object file and merge it with current files */
2239 /* XXX: handle correctly stab (debug) info */
2240 ST_FUNC int tcc_load_object_file(TCCState *s1,
2241 int fd, unsigned long file_offset)
2243 ElfW(Ehdr) ehdr;
2244 ElfW(Shdr) *shdr, *sh;
2245 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2246 unsigned char *strsec, *strtab;
2247 int *old_to_new_syms;
2248 char *sh_name, *name;
2249 SectionMergeInfo *sm_table, *sm;
2250 ElfW(Sym) *sym, *symtab;
2251 ElfW_Rel *rel, *rel_end;
2252 Section *s;
2254 int stab_index;
2255 int stabstr_index;
2257 stab_index = stabstr_index = 0;
2259 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2260 goto fail1;
2261 if (ehdr.e_ident[0] != ELFMAG0 ||
2262 ehdr.e_ident[1] != ELFMAG1 ||
2263 ehdr.e_ident[2] != ELFMAG2 ||
2264 ehdr.e_ident[3] != ELFMAG3)
2265 goto fail1;
2266 /* test if object file */
2267 if (ehdr.e_type != ET_REL)
2268 goto fail1;
2269 /* test CPU specific stuff */
2270 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2271 ehdr.e_machine != EM_TCC_TARGET) {
2272 fail1:
2273 error_noabort("invalid object file");
2274 return -1;
2276 /* read sections */
2277 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2278 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2279 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2281 /* load section names */
2282 sh = &shdr[ehdr.e_shstrndx];
2283 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2285 /* load symtab and strtab */
2286 old_to_new_syms = NULL;
2287 symtab = NULL;
2288 strtab = NULL;
2289 nb_syms = 0;
2290 for(i = 1; i < ehdr.e_shnum; i++) {
2291 sh = &shdr[i];
2292 if (sh->sh_type == SHT_SYMTAB) {
2293 if (symtab) {
2294 error_noabort("object must contain only one symtab");
2295 fail:
2296 ret = -1;
2297 goto the_end;
2299 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2300 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2301 sm_table[i].s = symtab_section;
2303 /* now load strtab */
2304 sh = &shdr[sh->sh_link];
2305 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2309 /* now examine each section and try to merge its content with the
2310 ones in memory */
2311 for(i = 1; i < ehdr.e_shnum; i++) {
2312 /* no need to examine section name strtab */
2313 if (i == ehdr.e_shstrndx)
2314 continue;
2315 sh = &shdr[i];
2316 sh_name = strsec + sh->sh_name;
2317 /* ignore sections types we do not handle */
2318 if (sh->sh_type != SHT_PROGBITS &&
2319 sh->sh_type != SHT_RELX &&
2320 #ifdef TCC_ARM_EABI
2321 sh->sh_type != SHT_ARM_EXIDX &&
2322 #endif
2323 sh->sh_type != SHT_NOBITS &&
2324 sh->sh_type != SHT_PREINIT_ARRAY &&
2325 sh->sh_type != SHT_INIT_ARRAY &&
2326 sh->sh_type != SHT_FINI_ARRAY &&
2327 strcmp(sh_name, ".stabstr")
2329 continue;
2330 if (sh->sh_addralign < 1)
2331 sh->sh_addralign = 1;
2332 /* find corresponding section, if any */
2333 for(j = 1; j < s1->nb_sections;j++) {
2334 s = s1->sections[j];
2335 if (!strcmp(s->name, sh_name)) {
2336 if (!strncmp(sh_name, ".gnu.linkonce",
2337 sizeof(".gnu.linkonce") - 1)) {
2338 /* if a 'linkonce' section is already present, we
2339 do not add it again. It is a little tricky as
2340 symbols can still be defined in
2341 it. */
2342 sm_table[i].link_once = 1;
2343 goto next;
2344 } else {
2345 goto found;
2349 /* not found: create new section */
2350 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2351 /* take as much info as possible from the section. sh_link and
2352 sh_info will be updated later */
2353 s->sh_addralign = sh->sh_addralign;
2354 s->sh_entsize = sh->sh_entsize;
2355 sm_table[i].new_section = 1;
2356 found:
2357 if (sh->sh_type != s->sh_type) {
2358 error_noabort("invalid section type");
2359 goto fail;
2362 /* align start of section */
2363 offset = s->data_offset;
2365 if (0 == strcmp(sh_name, ".stab")) {
2366 stab_index = i;
2367 goto no_align;
2369 if (0 == strcmp(sh_name, ".stabstr")) {
2370 stabstr_index = i;
2371 goto no_align;
2374 size = sh->sh_addralign - 1;
2375 offset = (offset + size) & ~size;
2376 if (sh->sh_addralign > s->sh_addralign)
2377 s->sh_addralign = sh->sh_addralign;
2378 s->data_offset = offset;
2379 no_align:
2380 sm_table[i].offset = offset;
2381 sm_table[i].s = s;
2382 /* concatenate sections */
2383 size = sh->sh_size;
2384 if (sh->sh_type != SHT_NOBITS) {
2385 unsigned char *ptr;
2386 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2387 ptr = section_ptr_add(s, size);
2388 read(fd, ptr, size);
2389 } else {
2390 s->data_offset += size;
2392 next: ;
2395 /* //gr relocate stab strings */
2396 if (stab_index && stabstr_index) {
2397 Stab_Sym *a, *b;
2398 unsigned o;
2399 s = sm_table[stab_index].s;
2400 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2401 b = (Stab_Sym *)(s->data + s->data_offset);
2402 o = sm_table[stabstr_index].offset;
2403 while (a < b)
2404 a->n_strx += o, a++;
2407 /* second short pass to update sh_link and sh_info fields of new
2408 sections */
2409 for(i = 1; i < ehdr.e_shnum; i++) {
2410 s = sm_table[i].s;
2411 if (!s || !sm_table[i].new_section)
2412 continue;
2413 sh = &shdr[i];
2414 if (sh->sh_link > 0)
2415 s->link = sm_table[sh->sh_link].s;
2416 if (sh->sh_type == SHT_RELX) {
2417 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2418 /* update backward link */
2419 s1->sections[s->sh_info]->reloc = s;
2422 sm = sm_table;
2424 /* resolve symbols */
2425 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2427 sym = symtab + 1;
2428 for(i = 1; i < nb_syms; i++, sym++) {
2429 if (sym->st_shndx != SHN_UNDEF &&
2430 sym->st_shndx < SHN_LORESERVE) {
2431 sm = &sm_table[sym->st_shndx];
2432 if (sm->link_once) {
2433 /* if a symbol is in a link once section, we use the
2434 already defined symbol. It is very important to get
2435 correct relocations */
2436 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2437 name = strtab + sym->st_name;
2438 sym_index = find_elf_sym(symtab_section, name);
2439 if (sym_index)
2440 old_to_new_syms[i] = sym_index;
2442 continue;
2444 /* if no corresponding section added, no need to add symbol */
2445 if (!sm->s)
2446 continue;
2447 /* convert section number */
2448 sym->st_shndx = sm->s->sh_num;
2449 /* offset value */
2450 sym->st_value += sm->offset;
2452 /* add symbol */
2453 name = strtab + sym->st_name;
2454 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2455 sym->st_info, sym->st_other,
2456 sym->st_shndx, name);
2457 old_to_new_syms[i] = sym_index;
2460 /* third pass to patch relocation entries */
2461 for(i = 1; i < ehdr.e_shnum; i++) {
2462 s = sm_table[i].s;
2463 if (!s)
2464 continue;
2465 sh = &shdr[i];
2466 offset = sm_table[i].offset;
2467 switch(s->sh_type) {
2468 case SHT_RELX:
2469 /* take relocation offset information */
2470 offseti = sm_table[sh->sh_info].offset;
2471 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2472 for(rel = (ElfW_Rel *)(s->data + offset);
2473 rel < rel_end;
2474 rel++) {
2475 int type;
2476 unsigned sym_index;
2477 /* convert symbol index */
2478 type = ELFW(R_TYPE)(rel->r_info);
2479 sym_index = ELFW(R_SYM)(rel->r_info);
2480 /* NOTE: only one symtab assumed */
2481 if (sym_index >= nb_syms)
2482 goto invalid_reloc;
2483 sym_index = old_to_new_syms[sym_index];
2484 /* ignore link_once in rel section. */
2485 if (!sym_index && !sm->link_once
2486 #ifdef TCC_TARGET_ARM
2487 && type != R_ARM_V4BX
2488 #endif
2490 invalid_reloc:
2491 error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2492 i, strsec + sh->sh_name, rel->r_offset);
2493 goto fail;
2495 rel->r_info = ELFW(R_INFO)(sym_index, type);
2496 /* offset the relocation offset */
2497 rel->r_offset += offseti;
2499 break;
2500 default:
2501 break;
2505 ret = 0;
2506 the_end:
2507 tcc_free(symtab);
2508 tcc_free(strtab);
2509 tcc_free(old_to_new_syms);
2510 tcc_free(sm_table);
2511 tcc_free(strsec);
2512 tcc_free(shdr);
2513 return ret;
2516 typedef struct ArchiveHeader {
2517 char ar_name[16]; /* name of this member */
2518 char ar_date[12]; /* file mtime */
2519 char ar_uid[6]; /* owner uid; printed as decimal */
2520 char ar_gid[6]; /* owner gid; printed as decimal */
2521 char ar_mode[8]; /* file mode, printed as octal */
2522 char ar_size[10]; /* file size, printed as decimal */
2523 char ar_fmag[2]; /* should contain ARFMAG */
2524 } ArchiveHeader;
2526 static int get_be32(const uint8_t *b)
2528 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2531 /* load only the objects which resolve undefined symbols */
2532 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2534 int i, bound, nsyms, sym_index, off, ret;
2535 uint8_t *data;
2536 const char *ar_names, *p;
2537 const uint8_t *ar_index;
2538 ElfW(Sym) *sym;
2540 data = tcc_malloc(size);
2541 if (read(fd, data, size) != size)
2542 goto fail;
2543 nsyms = get_be32(data);
2544 ar_index = data + 4;
2545 ar_names = ar_index + nsyms * 4;
2547 do {
2548 bound = 0;
2549 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2550 sym_index = find_elf_sym(symtab_section, p);
2551 if(sym_index) {
2552 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2553 if(sym->st_shndx == SHN_UNDEF) {
2554 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2555 #if 0
2556 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2557 #endif
2558 ++bound;
2559 lseek(fd, off, SEEK_SET);
2560 if(tcc_load_object_file(s1, fd, off) < 0) {
2561 fail:
2562 ret = -1;
2563 goto the_end;
2568 } while(bound);
2569 ret = 0;
2570 the_end:
2571 tcc_free(data);
2572 return ret;
2575 /* load a '.a' file */
2576 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2578 ArchiveHeader hdr;
2579 char ar_size[11];
2580 char ar_name[17];
2581 char magic[8];
2582 int size, len, i;
2583 unsigned long file_offset;
2585 /* skip magic which was already checked */
2586 read(fd, magic, sizeof(magic));
2588 for(;;) {
2589 len = read(fd, &hdr, sizeof(hdr));
2590 if (len == 0)
2591 break;
2592 if (len != sizeof(hdr)) {
2593 error_noabort("invalid archive");
2594 return -1;
2596 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2597 ar_size[sizeof(hdr.ar_size)] = '\0';
2598 size = strtol(ar_size, NULL, 0);
2599 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2600 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2601 if (ar_name[i] != ' ')
2602 break;
2604 ar_name[i + 1] = '\0';
2605 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2606 file_offset = lseek(fd, 0, SEEK_CUR);
2607 /* align to even */
2608 size = (size + 1) & ~1;
2609 if (!strcmp(ar_name, "/")) {
2610 /* coff symbol table : we handle it */
2611 if(s1->alacarte_link)
2612 return tcc_load_alacarte(s1, fd, size);
2613 } else if (!strcmp(ar_name, "//") ||
2614 !strcmp(ar_name, "__.SYMDEF") ||
2615 !strcmp(ar_name, "__.SYMDEF/") ||
2616 !strcmp(ar_name, "ARFILENAMES/")) {
2617 /* skip symbol table or archive names */
2618 } else {
2619 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2620 return -1;
2622 lseek(fd, file_offset + size, SEEK_SET);
2624 return 0;
2627 #ifndef TCC_TARGET_PE
2628 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2629 is referenced by the user (so it should be added as DT_NEEDED in
2630 the generated ELF file) */
2631 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2633 ElfW(Ehdr) ehdr;
2634 ElfW(Shdr) *shdr, *sh, *sh1;
2635 int i, j, nb_syms, nb_dts, sym_bind, ret;
2636 ElfW(Sym) *sym, *dynsym;
2637 ElfW(Dyn) *dt, *dynamic;
2638 unsigned char *dynstr;
2639 const char *name, *soname;
2640 DLLReference *dllref;
2642 read(fd, &ehdr, sizeof(ehdr));
2644 /* test CPU specific stuff */
2645 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2646 ehdr.e_machine != EM_TCC_TARGET) {
2647 error_noabort("bad architecture");
2648 return -1;
2651 /* read sections */
2652 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2654 /* load dynamic section and dynamic symbols */
2655 nb_syms = 0;
2656 nb_dts = 0;
2657 dynamic = NULL;
2658 dynsym = NULL; /* avoid warning */
2659 dynstr = NULL; /* avoid warning */
2660 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2661 switch(sh->sh_type) {
2662 case SHT_DYNAMIC:
2663 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2664 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2665 break;
2666 case SHT_DYNSYM:
2667 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2668 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2669 sh1 = &shdr[sh->sh_link];
2670 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2671 break;
2672 default:
2673 break;
2677 /* compute the real library name */
2678 soname = tcc_basename(filename);
2680 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2681 if (dt->d_tag == DT_SONAME) {
2682 soname = dynstr + dt->d_un.d_val;
2686 /* if the dll is already loaded, do not load it */
2687 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2688 dllref = s1->loaded_dlls[i];
2689 if (!strcmp(soname, dllref->name)) {
2690 /* but update level if needed */
2691 if (level < dllref->level)
2692 dllref->level = level;
2693 ret = 0;
2694 goto the_end;
2698 // printf("loading dll '%s'\n", soname);
2700 /* add the dll and its level */
2701 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2702 dllref->level = level;
2703 strcpy(dllref->name, soname);
2704 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2706 /* add dynamic symbols in dynsym_section */
2707 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2708 sym_bind = ELFW(ST_BIND)(sym->st_info);
2709 if (sym_bind == STB_LOCAL)
2710 continue;
2711 name = dynstr + sym->st_name;
2712 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2713 sym->st_info, sym->st_other, sym->st_shndx, name);
2716 /* load all referenced DLLs */
2717 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2718 switch(dt->d_tag) {
2719 case DT_NEEDED:
2720 name = dynstr + dt->d_un.d_val;
2721 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2722 dllref = s1->loaded_dlls[j];
2723 if (!strcmp(name, dllref->name))
2724 goto already_loaded;
2726 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2727 error_noabort("referenced dll '%s' not found", name);
2728 ret = -1;
2729 goto the_end;
2731 already_loaded:
2732 break;
2735 ret = 0;
2736 the_end:
2737 tcc_free(dynstr);
2738 tcc_free(dynsym);
2739 tcc_free(dynamic);
2740 tcc_free(shdr);
2741 return ret;
2744 #define LD_TOK_NAME 256
2745 #define LD_TOK_EOF (-1)
2747 /* return next ld script token */
2748 static int ld_next(TCCState *s1, char *name, int name_size)
2750 int c;
2751 char *q;
2753 redo:
2754 switch(ch) {
2755 case ' ':
2756 case '\t':
2757 case '\f':
2758 case '\v':
2759 case '\r':
2760 case '\n':
2761 inp();
2762 goto redo;
2763 case '/':
2764 minp();
2765 if (ch == '*') {
2766 file->buf_ptr = parse_comment(file->buf_ptr);
2767 ch = file->buf_ptr[0];
2768 goto redo;
2769 } else {
2770 q = name;
2771 *q++ = '/';
2772 goto parse_name;
2774 break;
2775 /* case 'a' ... 'z': */
2776 case 'a':
2777 case 'b':
2778 case 'c':
2779 case 'd':
2780 case 'e':
2781 case 'f':
2782 case 'g':
2783 case 'h':
2784 case 'i':
2785 case 'j':
2786 case 'k':
2787 case 'l':
2788 case 'm':
2789 case 'n':
2790 case 'o':
2791 case 'p':
2792 case 'q':
2793 case 'r':
2794 case 's':
2795 case 't':
2796 case 'u':
2797 case 'v':
2798 case 'w':
2799 case 'x':
2800 case 'y':
2801 case 'z':
2802 /* case 'A' ... 'z': */
2803 case 'A':
2804 case 'B':
2805 case 'C':
2806 case 'D':
2807 case 'E':
2808 case 'F':
2809 case 'G':
2810 case 'H':
2811 case 'I':
2812 case 'J':
2813 case 'K':
2814 case 'L':
2815 case 'M':
2816 case 'N':
2817 case 'O':
2818 case 'P':
2819 case 'Q':
2820 case 'R':
2821 case 'S':
2822 case 'T':
2823 case 'U':
2824 case 'V':
2825 case 'W':
2826 case 'X':
2827 case 'Y':
2828 case 'Z':
2829 case '_':
2830 case '\\':
2831 case '.':
2832 case '$':
2833 case '~':
2834 q = name;
2835 parse_name:
2836 for(;;) {
2837 if (!((ch >= 'a' && ch <= 'z') ||
2838 (ch >= 'A' && ch <= 'Z') ||
2839 (ch >= '0' && ch <= '9') ||
2840 strchr("/.-_+=$:\\,~", ch)))
2841 break;
2842 if ((q - name) < name_size - 1) {
2843 *q++ = ch;
2845 minp();
2847 *q = '\0';
2848 c = LD_TOK_NAME;
2849 break;
2850 case CH_EOF:
2851 c = LD_TOK_EOF;
2852 break;
2853 default:
2854 c = ch;
2855 inp();
2856 break;
2858 #if 0
2859 printf("tok=%c %d\n", c, c);
2860 if (c == LD_TOK_NAME)
2861 printf(" name=%s\n", name);
2862 #endif
2863 return c;
2867 * Extract the library name from the file name
2868 * Return 0 if the file isn't a library
2870 * /!\ No test on filename capacity, be careful
2872 static int filename_to_libname(TCCState *s1, const char filename[], char libname[])
2874 char *ext;
2875 int libprefix;
2877 /* already converted to library name */
2878 if (libname[0] != '\0')
2879 return 1;
2880 ext = tcc_fileextension(filename);
2881 if (*ext == '\0')
2882 return 0;
2883 libprefix = !strncmp(filename, "lib", 3);
2884 if (!s1->static_link) {
2885 #ifdef TCC_TARGET_PE
2886 if (!strcmp(ext, ".def")) {
2887 size_t len = ext - filename;
2888 pstrncpy(libname, filename, len);
2889 return 1;
2891 #else
2892 if (libprefix && (!strcmp(ext, ".so"))) {
2893 size_t len = ext - filename - 3;
2894 pstrncpy(libname, filename + 3, len);
2895 return 1;
2897 #endif
2898 } else {
2899 if (libprefix && (!strcmp(ext, ".a"))) {
2900 size_t len = ext - filename - 3;
2901 pstrncpy(libname, filename + 3, len);
2902 return 1;
2905 return 0;
2909 * Extract the file name from the library name
2911 * /!\ No test on filename capacity, be careful
2913 static void libname_to_filename(TCCState *s1, const char libname[], char filename[])
2915 if (!s1->static_link) {
2916 #ifdef TCC_TARGET_PE
2917 sprintf(filename, "%s.def", libname);
2918 #else
2919 sprintf(filename, "lib%s.so", libname);
2920 #endif
2921 } else {
2922 sprintf(filename, "lib%s.a", libname);
2926 static int ld_add_file(TCCState *s1, const char filename[], char libname[])
2928 int ret;
2930 ret = tcc_add_file_internal(s1, filename, 0);
2931 if (ret) {
2932 if (filename_to_libname(s1, filename, libname))
2933 ret = tcc_add_library(s1, libname);
2935 return ret;
2938 static inline int new_undef_syms(void)
2940 int ret = 0;
2941 ret = new_undef_sym;
2942 new_undef_sym = 0;
2943 return ret;
2946 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
2948 char filename[1024], libname[1024];
2949 int t, group, nblibs = 0, ret = 0;
2950 char **libs = NULL;
2952 group = !strcmp(cmd, "GROUP");
2953 if (!as_needed)
2954 new_undef_syms();
2955 t = ld_next(s1, filename, sizeof(filename));
2956 if (t != '(')
2957 expect("(");
2958 t = ld_next(s1, filename, sizeof(filename));
2959 for(;;) {
2960 libname[0] = '\0';
2961 if (t == LD_TOK_EOF) {
2962 error_noabort("unexpected end of file");
2963 ret = -1;
2964 goto lib_parse_error;
2965 } else if (t == ')') {
2966 break;
2967 } else if (t == '-') {
2968 t = ld_next(s1, filename, sizeof(filename));
2969 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
2970 error_noabort("library name expected");
2971 ret = -1;
2972 goto lib_parse_error;
2974 strcpy(libname, &filename[1]);
2975 libname_to_filename(s1, libname, filename);
2976 } else if (t != LD_TOK_NAME) {
2977 error_noabort("filename expected");
2978 ret = -1;
2979 goto lib_parse_error;
2981 if (!strcmp(filename, "AS_NEEDED")) {
2982 ret = ld_add_file_list(s1, cmd, 1);
2983 if (ret)
2984 goto lib_parse_error;
2985 } else {
2986 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2987 if (!as_needed) {
2988 ret = ld_add_file(s1, filename, libname);
2989 if (ret)
2990 goto lib_parse_error;
2991 if (group) {
2992 /* Add the filename *and* the libname to avoid future conversions */
2993 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
2994 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
2998 t = ld_next(s1, filename, sizeof(filename));
2999 if (t == ',') {
3000 t = ld_next(s1, filename, sizeof(filename));
3003 if (group && !as_needed) {
3004 while (new_undef_syms()) {
3005 int i;
3007 for (i = 0; i < nblibs; i += 2)
3008 ld_add_file(s1, libs[i], libs[i+1]);
3011 lib_parse_error:
3012 dynarray_reset(&libs, &nblibs);
3013 return ret;
3016 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3017 files */
3018 ST_FUNC int tcc_load_ldscript(TCCState *s1)
3020 char cmd[64];
3021 char filename[1024];
3022 int t, ret;
3024 ch = file->buf_ptr[0];
3025 ch = handle_eob();
3026 for(;;) {
3027 t = ld_next(s1, cmd, sizeof(cmd));
3028 if (t == LD_TOK_EOF)
3029 return 0;
3030 else if (t != LD_TOK_NAME)
3031 return -1;
3032 if (!strcmp(cmd, "INPUT") ||
3033 !strcmp(cmd, "GROUP")) {
3034 ret = ld_add_file_list(s1, cmd, 0);
3035 if (ret)
3036 return ret;
3037 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3038 !strcmp(cmd, "TARGET")) {
3039 /* ignore some commands */
3040 t = ld_next(s1, cmd, sizeof(cmd));
3041 if (t != '(')
3042 expect("(");
3043 for(;;) {
3044 t = ld_next(s1, filename, sizeof(filename));
3045 if (t == LD_TOK_EOF) {
3046 error_noabort("unexpected end of file");
3047 return -1;
3048 } else if (t == ')') {
3049 break;
3052 } else {
3053 return -1;
3056 return 0;
3058 #endif