don't build tcc1.def on Windows.
[tinycc.git] / tccelf.c
bloba35206e13bd38e36c1d7021114e235d629e84642
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 #ifdef TCC_TARGET_X86_64
24 #define ElfW_Rel ElfW(Rela)
25 #define SHT_RELX SHT_RELA
26 #define REL_SECTION_FMT ".rela%s"
27 /* x86-64 requires PLT for DLLs */
28 #define TCC_OUTPUT_DLL_WITH_PLT
29 #else
30 #define ElfW_Rel ElfW(Rel)
31 #define SHT_RELX SHT_REL
32 #define REL_SECTION_FMT ".rel%s"
33 #endif
35 static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */
37 /* XXX: DLL with PLT would only work with x86-64 for now */
38 //#define TCC_OUTPUT_DLL_WITH_PLT
40 ST_FUNC int put_elf_str(Section *s, const char *sym)
42 int offset, len;
43 char *ptr;
45 len = strlen(sym) + 1;
46 offset = s->data_offset;
47 ptr = section_ptr_add(s, len);
48 memcpy(ptr, sym, len);
49 return offset;
52 /* elf symbol hashing function */
53 static unsigned long elf_hash(const unsigned char *name)
55 unsigned long h = 0, g;
57 while (*name) {
58 h = (h << 4) + *name++;
59 g = h & 0xf0000000;
60 if (g)
61 h ^= g >> 24;
62 h &= ~g;
64 return h;
67 /* rebuild hash table of section s */
68 /* NOTE: we do factorize the hash table code to go faster */
69 static void rebuild_hash(Section *s, unsigned int nb_buckets)
71 ElfW(Sym) *sym;
72 int *ptr, *hash, nb_syms, sym_index, h;
73 char *strtab;
75 strtab = s->link->data;
76 nb_syms = s->data_offset / sizeof(ElfW(Sym));
78 s->hash->data_offset = 0;
79 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
80 ptr[0] = nb_buckets;
81 ptr[1] = nb_syms;
82 ptr += 2;
83 hash = ptr;
84 memset(hash, 0, (nb_buckets + 1) * sizeof(int));
85 ptr += nb_buckets + 1;
87 sym = (ElfW(Sym) *)s->data + 1;
88 for(sym_index = 1; sym_index < nb_syms; sym_index++) {
89 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
90 h = elf_hash(strtab + sym->st_name) % nb_buckets;
91 *ptr = hash[h];
92 hash[h] = sym_index;
93 } else {
94 *ptr = 0;
96 ptr++;
97 sym++;
101 /* return the symbol number */
102 ST_FUNC int put_elf_sym(Section *s, uplong value, unsigned long size,
103 int info, int other, int shndx, const char *name)
105 int name_offset, sym_index;
106 int nbuckets, h;
107 ElfW(Sym) *sym;
108 Section *hs;
110 sym = section_ptr_add(s, sizeof(ElfW(Sym)));
111 if (name)
112 name_offset = put_elf_str(s->link, name);
113 else
114 name_offset = 0;
115 /* XXX: endianness */
116 sym->st_name = name_offset;
117 sym->st_value = value;
118 sym->st_size = size;
119 sym->st_info = info;
120 sym->st_other = other;
121 sym->st_shndx = shndx;
122 sym_index = sym - (ElfW(Sym) *)s->data;
123 hs = s->hash;
124 if (hs) {
125 int *ptr, *base;
126 ptr = section_ptr_add(hs, sizeof(int));
127 base = (int *)hs->data;
128 /* only add global or weak symbols */
129 if (ELFW(ST_BIND)(info) != STB_LOCAL) {
130 /* add another hashing entry */
131 nbuckets = base[0];
132 h = elf_hash(name) % nbuckets;
133 *ptr = base[2 + h];
134 base[2 + h] = sym_index;
135 base[1]++;
136 /* we resize the hash table */
137 hs->nb_hashed_syms++;
138 if (hs->nb_hashed_syms > 2 * nbuckets) {
139 rebuild_hash(s, 2 * nbuckets);
141 } else {
142 *ptr = 0;
143 base[1]++;
146 return sym_index;
149 /* find global ELF symbol 'name' and return its index. Return 0 if not
150 found. */
151 ST_FUNC int find_elf_sym(Section *s, const char *name)
153 ElfW(Sym) *sym;
154 Section *hs;
155 int nbuckets, sym_index, h;
156 const char *name1;
158 hs = s->hash;
159 if (!hs)
160 return 0;
161 nbuckets = ((int *)hs->data)[0];
162 h = elf_hash(name) % nbuckets;
163 sym_index = ((int *)hs->data)[2 + h];
164 while (sym_index != 0) {
165 sym = &((ElfW(Sym) *)s->data)[sym_index];
166 name1 = s->link->data + sym->st_name;
167 if (!strcmp(name, name1))
168 return sym_index;
169 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
171 return 0;
174 /* return elf symbol value, signal error if 'err' is nonzero */
175 static void *get_elf_sym_addr(TCCState *s, const char *name, int err)
177 int sym_index;
178 ElfW(Sym) *sym;
180 sym_index = find_elf_sym(symtab_section, name);
181 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
182 if (!sym_index || sym->st_shndx == SHN_UNDEF) {
183 if (err)
184 error("%s not defined", name);
185 return NULL;
187 return (void*)(uplong)sym->st_value;
190 /* return elf symbol value */
191 LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
193 return get_elf_sym_addr(s, name, 0);
196 /* return elf symbol value or error */
197 ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name)
199 return get_elf_sym_addr(s, name, 1);
202 /* add an elf symbol : check if it is already defined and patch
203 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
204 ST_FUNC int add_elf_sym(Section *s, uplong value, unsigned long size,
205 int info, int other, int sh_num, const char *name)
207 ElfW(Sym) *esym;
208 int sym_bind, sym_index, sym_type, esym_bind;
209 unsigned char sym_vis, esym_vis, new_vis;
211 sym_bind = ELFW(ST_BIND)(info);
212 sym_type = ELFW(ST_TYPE)(info);
213 sym_vis = ELFW(ST_VISIBILITY)(other);
215 if (sym_bind != STB_LOCAL) {
216 /* we search global or weak symbols */
217 sym_index = find_elf_sym(s, name);
218 if (!sym_index)
219 goto do_def;
220 esym = &((ElfW(Sym) *)s->data)[sym_index];
221 if (esym->st_shndx != SHN_UNDEF) {
222 esym_bind = ELFW(ST_BIND)(esym->st_info);
223 /* propagate the most constraining visibility */
224 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
225 esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
226 if (esym_vis == STV_DEFAULT) {
227 new_vis = sym_vis;
228 } else if (sym_vis == STV_DEFAULT) {
229 new_vis = esym_vis;
230 } else {
231 new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
233 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
234 | new_vis;
235 other = esym->st_other; /* in case we have to patch esym */
236 if (sh_num == SHN_UNDEF) {
237 /* ignore adding of undefined symbol if the
238 corresponding symbol is already defined */
239 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
240 /* global overrides weak, so patch */
241 goto do_patch;
242 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
243 /* weak is ignored if already global */
244 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
245 /* ignore hidden symbols after */
246 } else if (esym->st_shndx == SHN_COMMON
247 && (sh_num < SHN_LORESERVE || sh_num == SHN_COMMON)) {
248 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
249 No idea if this is the correct solution ... */
250 goto do_patch;
251 } else if (s == tcc_state->dynsymtab_section) {
252 /* we accept that two DLL define the same symbol */
253 } else {
254 #if 1
255 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
256 sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
257 #endif
258 error_noabort("'%s' defined twice", name);
260 } else {
261 do_patch:
262 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
263 esym->st_shndx = sh_num;
264 new_undef_sym = 1;
265 esym->st_value = value;
266 esym->st_size = size;
267 esym->st_other = other;
269 } else {
270 do_def:
271 sym_index = put_elf_sym(s, value, size,
272 ELFW(ST_INFO)(sym_bind, sym_type), other,
273 sh_num, name);
275 return sym_index;
278 /* put relocation */
279 ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
280 int type, int symbol)
282 char buf[256];
283 Section *sr;
284 ElfW_Rel *rel;
286 sr = s->reloc;
287 if (!sr) {
288 /* if no relocation section, create it */
289 snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
290 /* if the symtab is allocated, then we consider the relocation
291 are also */
292 sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
293 sr->sh_entsize = sizeof(ElfW_Rel);
294 sr->link = symtab;
295 sr->sh_info = s->sh_num;
296 s->reloc = sr;
298 rel = section_ptr_add(sr, sizeof(ElfW_Rel));
299 rel->r_offset = offset;
300 rel->r_info = ELFW(R_INFO)(symbol, type);
301 #ifdef TCC_TARGET_X86_64
302 rel->r_addend = 0;
303 #endif
306 /* put stab debug information */
308 ST_FUNC void put_stabs(const char *str, int type, int other, int desc,
309 unsigned long value)
311 Stab_Sym *sym;
313 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
314 if (str) {
315 sym->n_strx = put_elf_str(stabstr_section, str);
316 } else {
317 sym->n_strx = 0;
319 sym->n_type = type;
320 sym->n_other = other;
321 sym->n_desc = desc;
322 sym->n_value = value;
325 ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc,
326 unsigned long value, Section *sec, int sym_index)
328 put_stabs(str, type, other, desc, value);
329 put_elf_reloc(symtab_section, stab_section,
330 stab_section->data_offset - sizeof(unsigned int),
331 R_DATA_32, sym_index);
334 ST_FUNC void put_stabn(int type, int other, int desc, int value)
336 put_stabs(NULL, type, other, desc, value);
339 ST_FUNC void put_stabd(int type, int other, int desc)
341 put_stabs(NULL, type, other, desc, 0);
344 /* In an ELF file symbol table, the local symbols must appear below
345 the global and weak ones. Since TCC cannot sort it while generating
346 the code, we must do it after. All the relocation tables are also
347 modified to take into account the symbol table sorting */
348 static void sort_syms(TCCState *s1, Section *s)
350 int *old_to_new_syms;
351 ElfW(Sym) *new_syms;
352 int nb_syms, i;
353 ElfW(Sym) *p, *q;
354 ElfW_Rel *rel, *rel_end;
355 Section *sr;
356 int type, sym_index;
358 nb_syms = s->data_offset / sizeof(ElfW(Sym));
359 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
360 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
362 /* first pass for local symbols */
363 p = (ElfW(Sym) *)s->data;
364 q = new_syms;
365 for(i = 0; i < nb_syms; i++) {
366 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
367 old_to_new_syms[i] = q - new_syms;
368 *q++ = *p;
370 p++;
372 /* save the number of local symbols in section header */
373 s->sh_info = q - new_syms;
375 /* then second pass for non local symbols */
376 p = (ElfW(Sym) *)s->data;
377 for(i = 0; i < nb_syms; i++) {
378 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
379 old_to_new_syms[i] = q - new_syms;
380 *q++ = *p;
382 p++;
385 /* we copy the new symbols to the old */
386 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
387 tcc_free(new_syms);
389 /* now we modify all the relocations */
390 for(i = 1; i < s1->nb_sections; i++) {
391 sr = s1->sections[i];
392 if (sr->sh_type == SHT_RELX && sr->link == s) {
393 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
394 for(rel = (ElfW_Rel *)sr->data;
395 rel < rel_end;
396 rel++) {
397 sym_index = ELFW(R_SYM)(rel->r_info);
398 type = ELFW(R_TYPE)(rel->r_info);
399 sym_index = old_to_new_syms[sym_index];
400 rel->r_info = ELFW(R_INFO)(sym_index, type);
405 tcc_free(old_to_new_syms);
408 /* relocate common symbols in the .bss section */
409 ST_FUNC void relocate_common_syms(void)
411 ElfW(Sym) *sym, *sym_end;
412 unsigned long offset, align;
414 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
415 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
416 sym < sym_end;
417 sym++) {
418 if (sym->st_shndx == SHN_COMMON) {
419 /* align symbol */
420 align = sym->st_value;
421 offset = bss_section->data_offset;
422 offset = (offset + align - 1) & -align;
423 sym->st_value = offset;
424 sym->st_shndx = bss_section->sh_num;
425 offset += sym->st_size;
426 bss_section->data_offset = offset;
431 /* relocate symbol table, resolve undefined symbols if do_resolve is
432 true and output error if undefined symbol. */
433 ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
435 ElfW(Sym) *sym, *esym, *sym_end;
436 int sym_bind, sh_num, sym_index;
437 const char *name;
439 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
440 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
441 sym < sym_end;
442 sym++) {
443 sh_num = sym->st_shndx;
444 if (sh_num == SHN_UNDEF) {
445 name = strtab_section->data + sym->st_name;
446 if (do_resolve) {
447 #if !defined TCC_TARGET_PE || !defined _WIN32
448 void *addr;
449 name = symtab_section->link->data + sym->st_name;
450 addr = resolve_sym(s1, name);
451 if (addr) {
452 sym->st_value = (uplong)addr;
453 goto found;
455 #endif
456 } else if (s1->dynsym) {
457 /* if dynamic symbol exist, then use it */
458 sym_index = find_elf_sym(s1->dynsym, name);
459 if (sym_index) {
460 esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
461 sym->st_value = esym->st_value;
462 goto found;
465 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
466 it */
467 if (!strcmp(name, "_fp_hw"))
468 goto found;
469 /* only weak symbols are accepted to be undefined. Their
470 value is zero */
471 sym_bind = ELFW(ST_BIND)(sym->st_info);
472 if (sym_bind == STB_WEAK) {
473 sym->st_value = 0;
474 } else {
475 error_noabort("undefined symbol '%s'", name);
477 } else if (sh_num < SHN_LORESERVE) {
478 /* add section base */
479 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
481 found: ;
485 #ifndef TCC_TARGET_PE
486 #ifdef TCC_TARGET_X86_64
487 #define JMP_TABLE_ENTRY_SIZE 14
488 static uplong add_jmp_table(TCCState *s1, uplong val)
490 char *p = s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset;
491 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
492 /* jmp *0x0(%rip) */
493 p[0] = 0xff;
494 p[1] = 0x25;
495 *(int *)(p + 2) = 0;
496 *(uplong *)(p + 6) = val;
497 return (uplong)p;
500 static uplong add_got_table(TCCState *s1, uplong val)
502 uplong *p = (uplong *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
503 s1->runtime_plt_and_got_offset += sizeof(uplong);
504 *p = val;
505 return (uplong)p;
507 #endif
508 #endif
510 /* relocate a given section (CPU dependent) */
511 ST_FUNC void relocate_section(TCCState *s1, Section *s)
513 Section *sr;
514 ElfW_Rel *rel, *rel_end, *qrel;
515 ElfW(Sym) *sym;
516 int type, sym_index;
517 unsigned char *ptr;
518 uplong val, addr;
519 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
520 int esym_index;
521 #endif
523 sr = s->reloc;
524 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
525 qrel = (ElfW_Rel *)sr->data;
526 for(rel = qrel;
527 rel < rel_end;
528 rel++) {
529 ptr = s->data + rel->r_offset;
531 sym_index = ELFW(R_SYM)(rel->r_info);
532 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
533 val = sym->st_value;
534 #ifdef TCC_TARGET_X86_64
535 /* XXX: not tested */
536 val += rel->r_addend;
537 #endif
538 type = ELFW(R_TYPE)(rel->r_info);
539 addr = s->sh_addr + rel->r_offset;
541 /* CPU specific */
542 switch(type) {
543 #if defined(TCC_TARGET_I386)
544 case R_386_32:
545 if (s1->output_type == TCC_OUTPUT_DLL) {
546 esym_index = s1->symtab_to_dynsym[sym_index];
547 qrel->r_offset = rel->r_offset;
548 if (esym_index) {
549 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
550 qrel++;
551 break;
552 } else {
553 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
554 qrel++;
557 *(int *)ptr += val;
558 break;
559 case R_386_PC32:
560 if (s1->output_type == TCC_OUTPUT_DLL) {
561 /* DLL relocation */
562 esym_index = s1->symtab_to_dynsym[sym_index];
563 if (esym_index) {
564 qrel->r_offset = rel->r_offset;
565 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
566 qrel++;
567 break;
570 *(int *)ptr += val - addr;
571 break;
572 case R_386_PLT32:
573 *(int *)ptr += val - addr;
574 break;
575 case R_386_GLOB_DAT:
576 case R_386_JMP_SLOT:
577 *(int *)ptr = val;
578 break;
579 case R_386_GOTPC:
580 *(int *)ptr += s1->got->sh_addr - addr;
581 break;
582 case R_386_GOTOFF:
583 *(int *)ptr += val - s1->got->sh_addr;
584 break;
585 case R_386_GOT32:
586 /* we load the got offset */
587 *(int *)ptr += s1->got_offsets[sym_index];
588 break;
589 case R_386_16:
590 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
591 output_file:
592 error("can only produce 16-bit binary files");
594 *(short *)ptr += val;
595 break;
596 case R_386_PC16:
597 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
598 goto output_file;
599 *(short *)ptr += val - addr;
600 break;
601 #elif defined(TCC_TARGET_ARM)
602 case R_ARM_PC24:
603 case R_ARM_CALL:
604 case R_ARM_JUMP24:
605 case R_ARM_PLT32:
607 int x;
608 x = (*(int *)ptr)&0xffffff;
609 (*(int *)ptr) &= 0xff000000;
610 if (x & 0x800000)
611 x -= 0x1000000;
612 x *= 4;
613 x += val - addr;
614 if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
615 error("can't relocate value at %x",addr);
616 x >>= 2;
617 x &= 0xffffff;
618 (*(int *)ptr) |= x;
620 break;
621 case R_ARM_PREL31:
623 int x;
624 x = (*(int *)ptr) & 0x7fffffff;
625 (*(int *)ptr) &= 0x80000000;
626 x = (x * 2) / 2;
627 x += val - addr;
628 if((x^(x>>1))&0x40000000)
629 error("can't relocate value at %x",addr);
630 (*(int *)ptr) |= x & 0x7fffffff;
632 case R_ARM_ABS32:
633 *(int *)ptr += val;
634 break;
635 case R_ARM_BASE_PREL:
636 *(int *)ptr += s1->got->sh_addr - addr;
637 break;
638 case R_ARM_GOTOFF32:
639 *(int *)ptr += val - s1->got->sh_addr;
640 break;
641 case R_ARM_GOT_BREL:
642 /* we load the got offset */
643 *(int *)ptr += s1->got_offsets[sym_index];
644 break;
645 case R_ARM_COPY:
646 break;
647 default:
648 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
649 type,addr,(unsigned int)(long)ptr,val);
650 break;
651 #elif defined(TCC_TARGET_C67)
652 case R_C60_32:
653 *(int *)ptr += val;
654 break;
655 case R_C60LO16:
657 uint32_t orig;
659 /* put the low 16 bits of the absolute address */
660 // add to what is already there
662 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
663 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
665 //patch both at once - assumes always in pairs Low - High
667 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
668 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
670 break;
671 case R_C60HI16:
672 break;
673 default:
674 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
675 type,addr,(unsigned int)(long)ptr, val);
676 break;
677 #elif defined(TCC_TARGET_X86_64)
678 case R_X86_64_64:
679 if (s1->output_type == TCC_OUTPUT_DLL) {
680 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
681 qrel->r_addend = *(long long *)ptr + val;
682 qrel++;
684 *(long long *)ptr += val;
685 break;
686 case R_X86_64_32:
687 case R_X86_64_32S:
688 if (s1->output_type == TCC_OUTPUT_DLL) {
689 /* XXX: this logic may depend on TCC's codegen
690 now TCC uses R_X86_64_32 even for a 64bit pointer */
691 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
692 qrel->r_addend = *(int *)ptr + val;
693 qrel++;
695 *(int *)ptr += val;
696 break;
697 case R_X86_64_PC32: {
698 long long diff;
699 if (s1->output_type == TCC_OUTPUT_DLL) {
700 /* DLL relocation */
701 esym_index = s1->symtab_to_dynsym[sym_index];
702 if (esym_index) {
703 qrel->r_offset = rel->r_offset;
704 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
705 qrel->r_addend = *(int *)ptr;
706 qrel++;
707 break;
710 diff = (long long)val - addr;
711 if (diff <= -2147483647 || diff > 2147483647) {
712 #ifndef TCC_TARGET_PE
713 /* XXX: naive support for over 32bit jump */
714 if (s1->output_type == TCC_OUTPUT_MEMORY) {
715 val = add_jmp_table(s1, val);
716 diff = val - addr;
718 #endif
719 if (diff <= -2147483647 || diff > 2147483647) {
720 error("internal error: relocation failed");
723 *(int *)ptr += diff;
725 break;
726 case R_X86_64_PLT32:
727 *(int *)ptr += val - addr;
728 break;
729 case R_X86_64_GLOB_DAT:
730 case R_X86_64_JUMP_SLOT:
731 *(int *)ptr = val;
732 break;
733 case R_X86_64_GOTPCREL:
734 #ifndef TCC_TARGET_PE
735 if (s1->output_type == TCC_OUTPUT_MEMORY) {
736 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
737 *(int *)ptr += val - addr;
738 break;
740 #endif
741 *(int *)ptr += (s1->got->sh_addr - addr +
742 s1->got_offsets[sym_index] - 4);
743 break;
744 case R_X86_64_GOTTPOFF:
745 *(int *)ptr += val - s1->got->sh_addr;
746 break;
747 case R_X86_64_GOT32:
748 /* we load the got offset */
749 *(int *)ptr += s1->got_offsets[sym_index];
750 break;
751 #else
752 #error unsupported processor
753 #endif
756 /* if the relocation is allocated, we change its symbol table */
757 if (sr->sh_flags & SHF_ALLOC)
758 sr->link = s1->dynsym;
761 /* relocate relocation table in 'sr' */
762 static void relocate_rel(TCCState *s1, Section *sr)
764 Section *s;
765 ElfW_Rel *rel, *rel_end;
767 s = s1->sections[sr->sh_info];
768 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
769 for(rel = (ElfW_Rel *)sr->data;
770 rel < rel_end;
771 rel++) {
772 rel->r_offset += s->sh_addr;
776 /* count the number of dynamic relocations so that we can reserve
777 their space */
778 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
780 ElfW_Rel *rel, *rel_end;
781 int sym_index, esym_index, type, count;
783 count = 0;
784 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
785 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
786 sym_index = ELFW(R_SYM)(rel->r_info);
787 type = ELFW(R_TYPE)(rel->r_info);
788 switch(type) {
789 #if defined(TCC_TARGET_I386)
790 case R_386_32:
791 #elif defined(TCC_TARGET_X86_64)
792 case R_X86_64_32:
793 case R_X86_64_32S:
794 case R_X86_64_64:
795 #endif
796 count++;
797 break;
798 #if defined(TCC_TARGET_I386)
799 case R_386_PC32:
800 #elif defined(TCC_TARGET_X86_64)
801 case R_X86_64_PC32:
802 #endif
803 esym_index = s1->symtab_to_dynsym[sym_index];
804 if (esym_index)
805 count++;
806 break;
807 default:
808 break;
811 if (count) {
812 /* allocate the section */
813 sr->sh_flags |= SHF_ALLOC;
814 sr->sh_size = count * sizeof(ElfW_Rel);
816 return count;
819 static void put_got_offset(TCCState *s1, int index, unsigned long val)
821 int n;
822 unsigned long *tab;
824 if (index >= s1->nb_got_offsets) {
825 /* find immediately bigger power of 2 and reallocate array */
826 n = 1;
827 while (index >= n)
828 n *= 2;
829 tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
830 if (!tab)
831 error("memory full");
832 s1->got_offsets = tab;
833 memset(s1->got_offsets + s1->nb_got_offsets, 0,
834 (n - s1->nb_got_offsets) * sizeof(unsigned long));
835 s1->nb_got_offsets = n;
837 s1->got_offsets[index] = val;
840 /* XXX: suppress that */
841 static void put32(unsigned char *p, uint32_t val)
843 p[0] = val;
844 p[1] = val >> 8;
845 p[2] = val >> 16;
846 p[3] = val >> 24;
849 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
850 defined(TCC_TARGET_X86_64)
851 static uint32_t get32(unsigned char *p)
853 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
855 #endif
857 static void build_got(TCCState *s1)
859 unsigned char *ptr;
861 /* if no got, then create it */
862 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
863 s1->got->sh_entsize = 4;
864 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
865 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
866 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
867 #if PTR_SIZE == 4
868 /* keep space for _DYNAMIC pointer, if present */
869 put32(ptr, 0);
870 /* two dummy got entries */
871 put32(ptr + 4, 0);
872 put32(ptr + 8, 0);
873 #else
874 /* keep space for _DYNAMIC pointer, if present */
875 put32(ptr, 0);
876 put32(ptr + 4, 0);
877 /* two dummy got entries */
878 put32(ptr + 8, 0);
879 put32(ptr + 12, 0);
880 put32(ptr + 16, 0);
881 put32(ptr + 20, 0);
882 #endif
885 /* put a got entry corresponding to a symbol in symtab_section. 'size'
886 and 'info' can be modifed if more precise info comes from the DLL */
887 static void put_got_entry(TCCState *s1,
888 int reloc_type, unsigned long size, int info,
889 int sym_index)
891 int index;
892 const char *name;
893 ElfW(Sym) *sym;
894 unsigned long offset;
895 int *ptr;
897 if (!s1->got)
898 build_got(s1);
900 /* if a got entry already exists for that symbol, no need to add one */
901 if (sym_index < s1->nb_got_offsets &&
902 s1->got_offsets[sym_index] != 0)
903 return;
905 put_got_offset(s1, sym_index, s1->got->data_offset);
907 if (s1->dynsym) {
908 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
909 name = symtab_section->link->data + sym->st_name;
910 offset = sym->st_value;
911 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
912 if (reloc_type ==
913 #ifdef TCC_TARGET_X86_64
914 R_X86_64_JUMP_SLOT
915 #else
916 R_386_JMP_SLOT
917 #endif
919 Section *plt;
920 uint8_t *p;
921 int modrm;
923 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
924 modrm = 0x25;
925 #else
926 /* if we build a DLL, we add a %ebx offset */
927 if (s1->output_type == TCC_OUTPUT_DLL)
928 modrm = 0xa3;
929 else
930 modrm = 0x25;
931 #endif
933 /* add a PLT entry */
934 plt = s1->plt;
935 if (plt->data_offset == 0) {
936 /* first plt entry */
937 p = section_ptr_add(plt, 16);
938 p[0] = 0xff; /* pushl got + PTR_SIZE */
939 p[1] = modrm + 0x10;
940 put32(p + 2, PTR_SIZE);
941 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
942 p[7] = modrm;
943 put32(p + 8, PTR_SIZE * 2);
946 p = section_ptr_add(plt, 16);
947 p[0] = 0xff; /* jmp *(got + x) */
948 p[1] = modrm;
949 put32(p + 2, s1->got->data_offset);
950 p[6] = 0x68; /* push $xxx */
951 put32(p + 7, (plt->data_offset - 32) >> 1);
952 p[11] = 0xe9; /* jmp plt_start */
953 put32(p + 12, -(plt->data_offset));
955 /* the symbol is modified so that it will be relocated to
956 the PLT */
957 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
958 if (s1->output_type == TCC_OUTPUT_EXE)
959 #endif
960 offset = plt->data_offset - 16;
962 #elif defined(TCC_TARGET_ARM)
963 if (reloc_type == R_ARM_JUMP_SLOT) {
964 Section *plt;
965 uint8_t *p;
967 /* if we build a DLL, we add a %ebx offset */
968 if (s1->output_type == TCC_OUTPUT_DLL)
969 error("DLLs unimplemented!");
971 /* add a PLT entry */
972 plt = s1->plt;
973 if (plt->data_offset == 0) {
974 /* first plt entry */
975 p = section_ptr_add(plt, 16);
976 put32(p , 0xe52de004);
977 put32(p + 4, 0xe59fe010);
978 put32(p + 8, 0xe08fe00e);
979 put32(p + 12, 0xe5bef008);
982 p = section_ptr_add(plt, 16);
983 put32(p , 0xe59fc004);
984 put32(p+4, 0xe08fc00c);
985 put32(p+8, 0xe59cf000);
986 put32(p+12, s1->got->data_offset);
988 /* the symbol is modified so that it will be relocated to
989 the PLT */
990 if (s1->output_type == TCC_OUTPUT_EXE)
991 offset = plt->data_offset - 16;
993 #elif defined(TCC_TARGET_C67)
994 error("C67 got not implemented");
995 #else
996 #error unsupported CPU
997 #endif
998 index = put_elf_sym(s1->dynsym, offset,
999 size, info, 0, sym->st_shndx, name);
1000 /* put a got entry */
1001 put_elf_reloc(s1->dynsym, s1->got,
1002 s1->got->data_offset,
1003 reloc_type, index);
1005 ptr = section_ptr_add(s1->got, PTR_SIZE);
1006 *ptr = 0;
1009 /* build GOT and PLT entries */
1010 ST_FUNC void build_got_entries(TCCState *s1)
1012 Section *s, *symtab;
1013 ElfW_Rel *rel, *rel_end;
1014 ElfW(Sym) *sym;
1015 int i, type, reloc_type, sym_index;
1017 for(i = 1; i < s1->nb_sections; i++) {
1018 s = s1->sections[i];
1019 if (s->sh_type != SHT_RELX)
1020 continue;
1021 /* no need to handle got relocations */
1022 if (s->link != symtab_section)
1023 continue;
1024 symtab = s->link;
1025 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1026 for(rel = (ElfW_Rel *)s->data;
1027 rel < rel_end;
1028 rel++) {
1029 type = ELFW(R_TYPE)(rel->r_info);
1030 switch(type) {
1031 #if defined(TCC_TARGET_I386)
1032 case R_386_GOT32:
1033 case R_386_GOTOFF:
1034 case R_386_GOTPC:
1035 case R_386_PLT32:
1036 if (!s1->got)
1037 build_got(s1);
1038 if (type == R_386_GOT32 || type == R_386_PLT32) {
1039 sym_index = ELFW(R_SYM)(rel->r_info);
1040 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1041 /* look at the symbol got offset. If none, then add one */
1042 if (type == R_386_GOT32)
1043 reloc_type = R_386_GLOB_DAT;
1044 else
1045 reloc_type = R_386_JMP_SLOT;
1046 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1047 sym_index);
1049 break;
1050 #elif defined(TCC_TARGET_ARM)
1051 case R_ARM_GOT_BREL:
1052 case R_ARM_GOTOFF32:
1053 case R_ARM_BASE_PREL:
1054 case R_ARM_PLT32:
1055 if (!s1->got)
1056 build_got(s1);
1057 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1058 sym_index = ELFW(R_SYM)(rel->r_info);
1059 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1060 /* look at the symbol got offset. If none, then add one */
1061 if (type == R_ARM_GOT_BREL)
1062 reloc_type = R_ARM_GLOB_DAT;
1063 else
1064 reloc_type = R_ARM_JUMP_SLOT;
1065 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1066 sym_index);
1068 break;
1069 #elif defined(TCC_TARGET_C67)
1070 case R_C60_GOT32:
1071 case R_C60_GOTOFF:
1072 case R_C60_GOTPC:
1073 case R_C60_PLT32:
1074 if (!s1->got)
1075 build_got(s1);
1076 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1077 sym_index = ELFW(R_SYM)(rel->r_info);
1078 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1079 /* look at the symbol got offset. If none, then add one */
1080 if (type == R_C60_GOT32)
1081 reloc_type = R_C60_GLOB_DAT;
1082 else
1083 reloc_type = R_C60_JMP_SLOT;
1084 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1085 sym_index);
1087 break;
1088 #elif defined(TCC_TARGET_X86_64)
1089 case R_X86_64_GOT32:
1090 case R_X86_64_GOTTPOFF:
1091 case R_X86_64_GOTPCREL:
1092 case R_X86_64_PLT32:
1093 if (!s1->got)
1094 build_got(s1);
1095 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1096 type == R_X86_64_PLT32) {
1097 sym_index = ELFW(R_SYM)(rel->r_info);
1098 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1099 /* look at the symbol got offset. If none, then add one */
1100 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1101 reloc_type = R_X86_64_GLOB_DAT;
1102 else
1103 reloc_type = R_X86_64_JUMP_SLOT;
1104 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1105 sym_index);
1107 break;
1108 #else
1109 #error unsupported CPU
1110 #endif
1111 default:
1112 break;
1118 ST_FUNC Section *new_symtab(TCCState *s1,
1119 const char *symtab_name, int sh_type, int sh_flags,
1120 const char *strtab_name,
1121 const char *hash_name, int hash_sh_flags)
1123 Section *symtab, *strtab, *hash;
1124 int *ptr, nb_buckets;
1126 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1127 symtab->sh_entsize = sizeof(ElfW(Sym));
1128 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1129 put_elf_str(strtab, "");
1130 symtab->link = strtab;
1131 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1133 nb_buckets = 1;
1135 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1136 hash->sh_entsize = sizeof(int);
1137 symtab->hash = hash;
1138 hash->link = symtab;
1140 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1141 ptr[0] = nb_buckets;
1142 ptr[1] = 1;
1143 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1144 return symtab;
1147 /* put dynamic tag */
1148 static void put_dt(Section *dynamic, int dt, unsigned long val)
1150 ElfW(Dyn) *dyn;
1151 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1152 dyn->d_tag = dt;
1153 dyn->d_un.d_val = val;
1156 static void add_init_array_defines(TCCState *s1, const char *section_name)
1158 Section *s;
1159 long end_offset;
1160 char sym_start[1024];
1161 char sym_end[1024];
1163 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1164 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1166 s = find_section(s1, section_name);
1167 if (!s) {
1168 end_offset = 0;
1169 s = data_section;
1170 } else {
1171 end_offset = s->data_offset;
1174 add_elf_sym(symtab_section,
1175 0, 0,
1176 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1177 s->sh_num, sym_start);
1178 add_elf_sym(symtab_section,
1179 end_offset, 0,
1180 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1181 s->sh_num, sym_end);
1184 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1186 #ifdef CONFIG_TCC_BCHECK
1187 unsigned long *ptr;
1188 Section *init_section;
1189 unsigned char *pinit;
1190 int sym_index;
1192 if (0 == s1->do_bounds_check)
1193 return;
1195 /* XXX: add an object file to do that */
1196 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1197 *ptr = 0;
1198 add_elf_sym(symtab_section, 0, 0,
1199 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1200 bounds_section->sh_num, "__bounds_start");
1201 /* add bound check code */
1202 #ifndef TCC_TARGET_PE
1204 char buf[1024];
1205 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "bcheck.o");
1206 tcc_add_file(s1, buf);
1208 #endif
1209 #ifdef TCC_TARGET_I386
1210 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1211 /* add 'call __bound_init()' in .init section */
1212 init_section = find_section(s1, ".init");
1213 pinit = section_ptr_add(init_section, 5);
1214 pinit[0] = 0xe8;
1215 put32(pinit + 1, -4);
1216 sym_index = find_elf_sym(symtab_section, "__bound_init");
1217 put_elf_reloc(symtab_section, init_section,
1218 init_section->data_offset - 4, R_386_PC32, sym_index);
1220 #endif
1221 #endif
1224 /* add tcc runtime libraries */
1225 ST_FUNC void tcc_add_runtime(TCCState *s1)
1227 tcc_add_bcheck(s1);
1229 /* add libc */
1230 if (!s1->nostdlib) {
1231 #ifdef CONFIG_USE_LIBGCC
1232 tcc_add_library(s1, "c");
1233 tcc_add_file(s1, CONFIG_SYSROOT "/lib/libgcc_s.so.1");
1234 #else
1235 char buf[1024];
1236 tcc_add_library(s1, "c");
1237 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "libtcc1.a");
1238 tcc_add_file(s1, buf);
1239 #endif
1241 /* add crt end if not memory output */
1242 if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) {
1243 tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
1247 /* add various standard linker symbols (must be done after the
1248 sections are filled (for example after allocating common
1249 symbols)) */
1250 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1252 char buf[1024];
1253 int i;
1254 Section *s;
1256 add_elf_sym(symtab_section,
1257 text_section->data_offset, 0,
1258 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1259 text_section->sh_num, "_etext");
1260 add_elf_sym(symtab_section,
1261 data_section->data_offset, 0,
1262 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1263 data_section->sh_num, "_edata");
1264 add_elf_sym(symtab_section,
1265 bss_section->data_offset, 0,
1266 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1267 bss_section->sh_num, "_end");
1268 /* horrible new standard ldscript defines */
1269 add_init_array_defines(s1, ".preinit_array");
1270 add_init_array_defines(s1, ".init_array");
1271 add_init_array_defines(s1, ".fini_array");
1273 /* add start and stop symbols for sections whose name can be
1274 expressed in C */
1275 for(i = 1; i < s1->nb_sections; i++) {
1276 s = s1->sections[i];
1277 if (s->sh_type == SHT_PROGBITS &&
1278 (s->sh_flags & SHF_ALLOC)) {
1279 const char *p;
1280 int ch;
1282 /* check if section name can be expressed in C */
1283 p = s->name;
1284 for(;;) {
1285 ch = *p;
1286 if (!ch)
1287 break;
1288 if (!isid(ch) && !isnum(ch))
1289 goto next_sec;
1290 p++;
1292 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1293 add_elf_sym(symtab_section,
1294 0, 0,
1295 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1296 s->sh_num, buf);
1297 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1298 add_elf_sym(symtab_section,
1299 s->data_offset, 0,
1300 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1301 s->sh_num, buf);
1303 next_sec: ;
1307 /* name of ELF interpreter */
1308 #if defined __FreeBSD__
1309 static const char elf_interp[] = "/libexec/ld-elf.so.1";
1310 #elif defined TCC_ARM_EABI
1311 static const char elf_interp[] = "/lib/ld-linux.so.3";
1312 #elif defined(TCC_TARGET_X86_64)
1313 # if defined(TCC_TARGET_X86_64_CENTOS)
1314 static const char elf_interp[] = "/lib64/ld-linux-x86-64.so.2";
1315 # else
1316 static const char elf_interp[] = "/lib/ld-linux-x86-64.so.2";
1317 # endif /* TCC_TARGET_X86_64_CENTOS */
1318 #elif defined(TCC_UCLIBC)
1319 static const char elf_interp[] = "/lib/ld-uClibc.so.0";
1320 #else
1321 static const char elf_interp[] = "/lib/ld-linux.so.2";
1322 #endif
1324 static void tcc_output_binary(TCCState *s1, FILE *f,
1325 const int *section_order)
1327 Section *s;
1328 int i, offset, size;
1330 offset = 0;
1331 for(i=1;i<s1->nb_sections;i++) {
1332 s = s1->sections[section_order[i]];
1333 if (s->sh_type != SHT_NOBITS &&
1334 (s->sh_flags & SHF_ALLOC)) {
1335 while (offset < s->sh_offset) {
1336 fputc(0, f);
1337 offset++;
1339 size = s->sh_size;
1340 fwrite(s->data, 1, size, f);
1341 offset += size;
1346 #if defined(__FreeBSD__)
1347 #define HAVE_PHDR 1
1348 #define EXTRA_RELITEMS 14
1350 /* move the relocation value from .dynsym to .got */
1351 void patch_dynsym_undef(TCCState *s1, Section *s)
1353 uint32_t *gotd = (void *)s1->got->data;
1354 ElfW(Sym) *sym, *sym_end;
1356 gotd += 3; // dummy entries in .got
1357 /* relocate symbols in .dynsym */
1358 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1359 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1360 if (sym->st_shndx == SHN_UNDEF) {
1361 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1362 sym->st_value = 0;
1366 #else
1367 #define HAVE_PHDR 0
1368 #define EXTRA_RELITEMS 9
1369 #endif
1371 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1373 int sym_index = ELFW(R_SYM) (rel->r_info);
1374 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1375 unsigned long offset;
1377 if (sym_index >= s1->nb_got_offsets)
1378 return;
1379 offset = s1->got_offsets[sym_index];
1380 section_reserve(s1->got, offset + PTR_SIZE);
1381 #ifdef TCC_TARGET_X86_64
1382 /* only works for x86-64 */
1383 put32(s1->got->data + offset, sym->st_value >> 32);
1384 #endif
1385 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1388 ST_FUNC void fill_got(TCCState *s1)
1390 Section *s;
1391 ElfW_Rel *rel, *rel_end;
1392 int i;
1394 for(i = 1; i < s1->nb_sections; i++) {
1395 s = s1->sections[i];
1396 if (s->sh_type != SHT_RELX)
1397 continue;
1398 /* no need to handle got relocations */
1399 if (s->link != symtab_section)
1400 continue;
1401 rel_end = (ElfW_Rel *) (s->data + s->data_offset);
1402 for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
1403 switch (ELFW(R_TYPE) (rel->r_info)) {
1404 case R_X86_64_GOT32:
1405 case R_X86_64_GOTPCREL:
1406 case R_X86_64_PLT32:
1407 fill_got_entry(s1, rel);
1408 break;
1415 /* output an ELF file */
1416 /* XXX: suppress unneeded sections */
1417 static int elf_output_file(TCCState *s1, const char *filename)
1419 ElfW(Ehdr) ehdr;
1420 FILE *f;
1421 int fd, mode, ret;
1422 int *section_order;
1423 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
1424 unsigned long addr;
1425 Section *strsec, *s;
1426 ElfW(Shdr) shdr, *sh;
1427 ElfW(Phdr) *phdr, *ph;
1428 Section *interp, *dynamic, *dynstr;
1429 unsigned long saved_dynamic_data_offset;
1430 ElfW(Sym) *sym;
1431 int type, file_type;
1432 unsigned long rel_addr, rel_size;
1433 unsigned long bss_addr, bss_size;
1435 file_type = s1->output_type;
1436 s1->nb_errors = 0;
1438 if (file_type != TCC_OUTPUT_OBJ) {
1439 tcc_add_runtime(s1);
1442 phdr = NULL;
1443 section_order = NULL;
1444 interp = NULL;
1445 dynamic = NULL;
1446 dynstr = NULL; /* avoid warning */
1447 saved_dynamic_data_offset = 0; /* avoid warning */
1449 if (file_type != TCC_OUTPUT_OBJ) {
1450 relocate_common_syms();
1452 tcc_add_linker_symbols(s1);
1454 if (!s1->static_link) {
1455 const char *name;
1456 int sym_index, index;
1457 ElfW(Sym) *esym, *sym_end;
1459 if (file_type == TCC_OUTPUT_EXE) {
1460 char *ptr;
1461 /* allow override the dynamic loader */
1462 const char *elfint = getenv("LD_SO");
1463 if (elfint == NULL)
1464 elfint = elf_interp;
1465 /* add interpreter section only if executable */
1466 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1467 interp->sh_addralign = 1;
1468 ptr = section_ptr_add(interp, 1+strlen(elfint));
1469 strcpy(ptr, elfint);
1472 /* add dynamic symbol table */
1473 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1474 ".dynstr",
1475 ".hash", SHF_ALLOC);
1476 dynstr = s1->dynsym->link;
1478 /* add dynamic section */
1479 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1480 SHF_ALLOC | SHF_WRITE);
1481 dynamic->link = dynstr;
1482 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1484 /* add PLT */
1485 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1486 SHF_ALLOC | SHF_EXECINSTR);
1487 s1->plt->sh_entsize = 4;
1489 build_got(s1);
1491 /* scan for undefined symbols and see if they are in the
1492 dynamic symbols. If a symbol STT_FUNC is found, then we
1493 add it in the PLT. If a symbol STT_OBJECT is found, we
1494 add it in the .bss section with a suitable relocation */
1495 sym_end = (ElfW(Sym) *)(symtab_section->data +
1496 symtab_section->data_offset);
1497 if (file_type == TCC_OUTPUT_EXE) {
1498 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1499 sym < sym_end;
1500 sym++) {
1501 if (sym->st_shndx == SHN_UNDEF) {
1502 name = symtab_section->link->data + sym->st_name;
1503 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1504 if (sym_index) {
1505 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1506 type = ELFW(ST_TYPE)(esym->st_info);
1507 if (type == STT_FUNC) {
1508 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1509 esym->st_info,
1510 sym - (ElfW(Sym) *)symtab_section->data);
1511 } else if (type == STT_OBJECT) {
1512 unsigned long offset;
1513 offset = bss_section->data_offset;
1514 /* XXX: which alignment ? */
1515 offset = (offset + 16 - 1) & -16;
1516 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1517 esym->st_info, 0,
1518 bss_section->sh_num, name);
1519 put_elf_reloc(s1->dynsym, bss_section,
1520 offset, R_COPY, index);
1521 offset += esym->st_size;
1522 bss_section->data_offset = offset;
1524 } else {
1525 /* STB_WEAK undefined symbols are accepted */
1526 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1527 it */
1528 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1529 !strcmp(name, "_fp_hw")) {
1530 } else {
1531 error_noabort("undefined symbol '%s'", name);
1534 } else if (s1->rdynamic &&
1535 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1536 /* if -rdynamic option, then export all non
1537 local symbols */
1538 name = symtab_section->link->data + sym->st_name;
1539 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1540 sym->st_info, 0,
1541 sym->st_shndx, name);
1545 if (s1->nb_errors)
1546 goto fail;
1548 /* now look at unresolved dynamic symbols and export
1549 corresponding symbol */
1550 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1551 s1->dynsymtab_section->data_offset);
1552 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1553 esym < sym_end;
1554 esym++) {
1555 if (esym->st_shndx == SHN_UNDEF) {
1556 name = s1->dynsymtab_section->link->data + esym->st_name;
1557 sym_index = find_elf_sym(symtab_section, name);
1558 if (sym_index) {
1559 /* XXX: avoid adding a symbol if already
1560 present because of -rdynamic ? */
1561 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1562 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1563 sym->st_info, 0,
1564 sym->st_shndx, name);
1565 } else {
1566 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1567 /* weak symbols can stay undefined */
1568 } else {
1569 warning("undefined dynamic symbol '%s'", name);
1574 } else {
1575 int nb_syms;
1576 /* shared library case : we simply export all the global symbols */
1577 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1578 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1579 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1580 sym < sym_end;
1581 sym++) {
1582 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1583 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1584 if (ELFW(ST_TYPE)(sym->st_info) == STT_FUNC &&
1585 sym->st_shndx == SHN_UNDEF) {
1586 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1587 sym->st_info,
1588 sym - (ElfW(Sym) *)symtab_section->data);
1590 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1591 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1592 sym->st_info,
1593 sym - (ElfW(Sym) *)symtab_section->data);
1595 else
1596 #endif
1598 name = symtab_section->link->data + sym->st_name;
1599 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1600 sym->st_info, 0,
1601 sym->st_shndx, name);
1602 s1->symtab_to_dynsym[sym -
1603 (ElfW(Sym) *)symtab_section->data] =
1604 index;
1610 build_got_entries(s1);
1612 /* add a list of needed dlls */
1613 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1614 DLLReference *dllref = s1->loaded_dlls[i];
1615 if (dllref->level == 0)
1616 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1619 if (s1->rpath)
1620 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1622 /* XXX: currently, since we do not handle PIC code, we
1623 must relocate the readonly segments */
1624 if (file_type == TCC_OUTPUT_DLL) {
1625 if (s1->soname)
1626 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1627 put_dt(dynamic, DT_TEXTREL, 0);
1630 if (s1->symbolic)
1631 put_dt(dynamic, DT_SYMBOLIC, 0);
1633 /* add necessary space for other entries */
1634 saved_dynamic_data_offset = dynamic->data_offset;
1635 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1636 } else {
1637 /* still need to build got entries in case of static link */
1638 build_got_entries(s1);
1642 memset(&ehdr, 0, sizeof(ehdr));
1644 /* we add a section for symbols */
1645 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1646 put_elf_str(strsec, "");
1648 /* compute number of sections */
1649 shnum = s1->nb_sections;
1651 /* this array is used to reorder sections in the output file */
1652 section_order = tcc_malloc(sizeof(int) * shnum);
1653 section_order[0] = 0;
1654 sh_order_index = 1;
1656 /* compute number of program headers */
1657 switch(file_type) {
1658 default:
1659 case TCC_OUTPUT_OBJ:
1660 phnum = 0;
1661 break;
1662 case TCC_OUTPUT_EXE:
1663 if (!s1->static_link)
1664 phnum = 4 + HAVE_PHDR;
1665 else
1666 phnum = 2;
1667 break;
1668 case TCC_OUTPUT_DLL:
1669 phnum = 3;
1670 break;
1673 /* allocate strings for section names and decide if an unallocated
1674 section should be output */
1675 /* NOTE: the strsec section comes last, so its size is also
1676 correct ! */
1677 for(i = 1; i < s1->nb_sections; i++) {
1678 s = s1->sections[i];
1679 s->sh_name = put_elf_str(strsec, s->name);
1680 #if 0 //gr
1681 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1682 s->sh_flags,
1683 s->sh_type,
1684 s->sh_info,
1685 s->name,
1686 s->reloc ? s->reloc->name : "n"
1688 #endif
1689 /* when generating a DLL, we include relocations but we may
1690 patch them */
1691 if (file_type == TCC_OUTPUT_DLL &&
1692 s->sh_type == SHT_RELX &&
1693 !(s->sh_flags & SHF_ALLOC)) {
1694 /* //gr: avoid bogus relocs for empty (debug) sections */
1695 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1696 prepare_dynamic_rel(s1, s);
1697 else if (s1->do_debug)
1698 s->sh_size = s->data_offset;
1699 } else if (s1->do_debug ||
1700 file_type == TCC_OUTPUT_OBJ ||
1701 (s->sh_flags & SHF_ALLOC) ||
1702 i == (s1->nb_sections - 1)) {
1703 /* we output all sections if debug or object file */
1704 s->sh_size = s->data_offset;
1708 /* allocate program segment headers */
1709 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1711 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1712 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1713 } else {
1714 file_offset = 0;
1716 if (phnum > 0) {
1717 /* compute section to program header mapping */
1718 if (s1->has_text_addr) {
1719 int a_offset, p_offset;
1720 addr = s1->text_addr;
1721 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1722 ELF_PAGE_SIZE */
1723 a_offset = addr & (s1->section_align - 1);
1724 p_offset = file_offset & (s1->section_align - 1);
1725 if (a_offset < p_offset)
1726 a_offset += s1->section_align;
1727 file_offset += (a_offset - p_offset);
1728 } else {
1729 if (file_type == TCC_OUTPUT_DLL)
1730 addr = 0;
1731 else
1732 addr = ELF_START_ADDR;
1733 /* compute address after headers */
1734 addr += (file_offset & (s1->section_align - 1));
1737 /* dynamic relocation table information, for .dynamic section */
1738 rel_size = 0;
1739 rel_addr = 0;
1741 bss_addr = bss_size = 0;
1742 /* leave one program header for the program interpreter */
1743 ph = &phdr[0];
1744 if (interp)
1745 ph += 1 + HAVE_PHDR;
1747 for(j = 0; j < 2; j++) {
1748 ph->p_type = PT_LOAD;
1749 if (j == 0)
1750 ph->p_flags = PF_R | PF_X;
1751 else
1752 ph->p_flags = PF_R | PF_W;
1753 ph->p_align = s1->section_align;
1755 /* we do the following ordering: interp, symbol tables,
1756 relocations, progbits, nobits */
1757 /* XXX: do faster and simpler sorting */
1758 for(k = 0; k < 5; k++) {
1759 for(i = 1; i < s1->nb_sections; i++) {
1760 s = s1->sections[i];
1761 /* compute if section should be included */
1762 if (j == 0) {
1763 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1764 SHF_ALLOC)
1765 continue;
1766 } else {
1767 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1768 (SHF_ALLOC | SHF_WRITE))
1769 continue;
1771 if (s == interp) {
1772 if (k != 0)
1773 continue;
1774 } else if (s->sh_type == SHT_DYNSYM ||
1775 s->sh_type == SHT_STRTAB ||
1776 s->sh_type == SHT_HASH) {
1777 if (k != 1)
1778 continue;
1779 } else if (s->sh_type == SHT_RELX) {
1780 if (k != 2)
1781 continue;
1782 } else if (s->sh_type == SHT_NOBITS) {
1783 if (k != 4)
1784 continue;
1785 } else {
1786 if (k != 3)
1787 continue;
1789 section_order[sh_order_index++] = i;
1791 /* section matches: we align it and add its size */
1792 tmp = addr;
1793 addr = (addr + s->sh_addralign - 1) &
1794 ~(s->sh_addralign - 1);
1795 file_offset += addr - tmp;
1796 s->sh_offset = file_offset;
1797 s->sh_addr = addr;
1799 /* update program header infos */
1800 if (ph->p_offset == 0) {
1801 ph->p_offset = file_offset;
1802 ph->p_vaddr = addr;
1803 ph->p_paddr = ph->p_vaddr;
1805 /* update dynamic relocation infos */
1806 if (s->sh_type == SHT_RELX) {
1807 #if defined(__FreeBSD__)
1808 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1809 rel_addr = addr;
1810 rel_size += s->sh_size; // XXX only first rel.
1812 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1813 bss_addr = addr;
1814 bss_size = s->sh_size; // XXX only first rel.
1816 #else
1817 if (rel_size == 0)
1818 rel_addr = addr;
1819 rel_size += s->sh_size;
1820 #endif
1822 addr += s->sh_size;
1823 if (s->sh_type != SHT_NOBITS)
1824 file_offset += s->sh_size;
1827 ph->p_filesz = file_offset - ph->p_offset;
1828 ph->p_memsz = addr - ph->p_vaddr;
1829 ph++;
1830 if (j == 0) {
1831 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1832 /* if in the middle of a page, we duplicate the page in
1833 memory so that one copy is RX and the other is RW */
1834 if ((addr & (s1->section_align - 1)) != 0)
1835 addr += s1->section_align;
1836 } else {
1837 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1838 file_offset = (file_offset + s1->section_align - 1) &
1839 ~(s1->section_align - 1);
1844 /* if interpreter, then add corresponing program header */
1845 if (interp) {
1846 ph = &phdr[0];
1848 #if defined(__FreeBSD__)
1850 int len = phnum * sizeof(ElfW(Phdr));
1852 ph->p_type = PT_PHDR;
1853 ph->p_offset = sizeof(ElfW(Ehdr));
1854 ph->p_vaddr = interp->sh_addr - len;
1855 ph->p_paddr = ph->p_vaddr;
1856 ph->p_filesz = ph->p_memsz = len;
1857 ph->p_flags = PF_R | PF_X;
1858 ph->p_align = 4; // interp->sh_addralign;
1859 ph++;
1861 #endif
1863 ph->p_type = PT_INTERP;
1864 ph->p_offset = interp->sh_offset;
1865 ph->p_vaddr = interp->sh_addr;
1866 ph->p_paddr = ph->p_vaddr;
1867 ph->p_filesz = interp->sh_size;
1868 ph->p_memsz = interp->sh_size;
1869 ph->p_flags = PF_R;
1870 ph->p_align = interp->sh_addralign;
1873 /* if dynamic section, then add corresponing program header */
1874 if (dynamic) {
1875 ElfW(Sym) *sym_end;
1877 ph = &phdr[phnum - 1];
1879 ph->p_type = PT_DYNAMIC;
1880 ph->p_offset = dynamic->sh_offset;
1881 ph->p_vaddr = dynamic->sh_addr;
1882 ph->p_paddr = ph->p_vaddr;
1883 ph->p_filesz = dynamic->sh_size;
1884 ph->p_memsz = dynamic->sh_size;
1885 ph->p_flags = PF_R | PF_W;
1886 ph->p_align = dynamic->sh_addralign;
1888 /* put GOT dynamic section address */
1889 put32(s1->got->data, dynamic->sh_addr);
1891 /* relocate the PLT */
1892 if (file_type == TCC_OUTPUT_EXE
1893 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1894 || file_type == TCC_OUTPUT_DLL
1895 #endif
1897 uint8_t *p, *p_end;
1899 p = s1->plt->data;
1900 p_end = p + s1->plt->data_offset;
1901 if (p < p_end) {
1902 #if defined(TCC_TARGET_I386)
1903 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1904 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1905 p += 16;
1906 while (p < p_end) {
1907 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1908 p += 16;
1910 #elif defined(TCC_TARGET_X86_64)
1911 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1912 put32(p + 2, get32(p + 2) + x);
1913 put32(p + 8, get32(p + 8) + x - 6);
1914 p += 16;
1915 while (p < p_end) {
1916 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1917 p += 16;
1919 #elif defined(TCC_TARGET_ARM)
1920 int x;
1921 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1922 p +=16;
1923 while (p < p_end) {
1924 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1925 p += 16;
1927 #elif defined(TCC_TARGET_C67)
1928 /* XXX: TODO */
1929 #else
1930 #error unsupported CPU
1931 #endif
1935 /* relocate symbols in .dynsym */
1936 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
1937 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
1938 sym < sym_end;
1939 sym++) {
1940 if (sym->st_shndx == SHN_UNDEF) {
1941 /* relocate to the PLT if the symbol corresponds
1942 to a PLT entry */
1943 if (sym->st_value)
1944 sym->st_value += s1->plt->sh_addr;
1945 } else if (sym->st_shndx < SHN_LORESERVE) {
1946 /* do symbol relocation */
1947 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
1951 /* put dynamic section entries */
1952 dynamic->data_offset = saved_dynamic_data_offset;
1953 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
1954 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
1955 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
1956 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
1957 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
1958 #ifdef TCC_TARGET_X86_64
1959 put_dt(dynamic, DT_RELA, rel_addr);
1960 put_dt(dynamic, DT_RELASZ, rel_size);
1961 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
1962 #else
1963 #if defined(__FreeBSD__)
1964 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
1965 put_dt(dynamic, DT_PLTRELSZ, rel_size);
1966 put_dt(dynamic, DT_JMPREL, rel_addr);
1967 put_dt(dynamic, DT_PLTREL, DT_REL);
1968 put_dt(dynamic, DT_REL, bss_addr);
1969 put_dt(dynamic, DT_RELSZ, bss_size);
1970 #else
1971 put_dt(dynamic, DT_REL, rel_addr);
1972 put_dt(dynamic, DT_RELSZ, rel_size);
1973 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
1974 #endif
1975 #endif
1976 if (s1->do_debug)
1977 put_dt(dynamic, DT_DEBUG, 0);
1978 put_dt(dynamic, DT_NULL, 0);
1981 ehdr.e_phentsize = sizeof(ElfW(Phdr));
1982 ehdr.e_phnum = phnum;
1983 ehdr.e_phoff = sizeof(ElfW(Ehdr));
1986 /* all other sections come after */
1987 for(i = 1; i < s1->nb_sections; i++) {
1988 s = s1->sections[i];
1989 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
1990 continue;
1991 section_order[sh_order_index++] = i;
1993 file_offset = (file_offset + s->sh_addralign - 1) &
1994 ~(s->sh_addralign - 1);
1995 s->sh_offset = file_offset;
1996 if (s->sh_type != SHT_NOBITS)
1997 file_offset += s->sh_size;
2000 /* if building executable or DLL, then relocate each section
2001 except the GOT which is already relocated */
2002 if (file_type != TCC_OUTPUT_OBJ) {
2003 relocate_syms(s1, 0);
2005 if (s1->nb_errors != 0) {
2006 fail:
2007 ret = -1;
2008 goto the_end;
2011 /* relocate sections */
2012 /* XXX: ignore sections with allocated relocations ? */
2013 for(i = 1; i < s1->nb_sections; i++) {
2014 s = s1->sections[i];
2015 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
2016 relocate_section(s1, s);
2019 /* relocate relocation entries if the relocation tables are
2020 allocated in the executable */
2021 for(i = 1; i < s1->nb_sections; i++) {
2022 s = s1->sections[i];
2023 if ((s->sh_flags & SHF_ALLOC) &&
2024 s->sh_type == SHT_RELX) {
2025 relocate_rel(s1, s);
2029 /* get entry point address */
2030 if (file_type == TCC_OUTPUT_EXE)
2031 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
2032 else
2033 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2035 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2036 fill_got(s1);
2038 /* write elf file */
2039 if (file_type == TCC_OUTPUT_OBJ)
2040 mode = 0666;
2041 else
2042 mode = 0777;
2043 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2044 if (fd < 0) {
2045 error_noabort("could not write '%s'", filename);
2046 goto fail;
2048 f = fdopen(fd, "wb");
2049 if (s1->verbose)
2050 printf("<- %s\n", filename);
2052 #ifdef TCC_TARGET_COFF
2053 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2054 tcc_output_coff(s1, f);
2055 } else
2056 #endif
2057 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2058 sort_syms(s1, symtab_section);
2060 /* align to 4 */
2061 file_offset = (file_offset + 3) & -4;
2063 /* fill header */
2064 ehdr.e_ident[0] = ELFMAG0;
2065 ehdr.e_ident[1] = ELFMAG1;
2066 ehdr.e_ident[2] = ELFMAG2;
2067 ehdr.e_ident[3] = ELFMAG3;
2068 ehdr.e_ident[4] = TCC_ELFCLASS;
2069 ehdr.e_ident[5] = ELFDATA2LSB;
2070 ehdr.e_ident[6] = EV_CURRENT;
2071 #ifdef __FreeBSD__
2072 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2073 #endif
2074 #ifdef TCC_TARGET_ARM
2075 #ifdef TCC_ARM_EABI
2076 ehdr.e_ident[EI_OSABI] = 0;
2077 ehdr.e_flags = 4 << 24;
2078 #else
2079 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2080 #endif
2081 #endif
2082 switch(file_type) {
2083 default:
2084 case TCC_OUTPUT_EXE:
2085 ehdr.e_type = ET_EXEC;
2086 break;
2087 case TCC_OUTPUT_DLL:
2088 ehdr.e_type = ET_DYN;
2089 break;
2090 case TCC_OUTPUT_OBJ:
2091 ehdr.e_type = ET_REL;
2092 break;
2094 ehdr.e_machine = EM_TCC_TARGET;
2095 ehdr.e_version = EV_CURRENT;
2096 ehdr.e_shoff = file_offset;
2097 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2098 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2099 ehdr.e_shnum = shnum;
2100 ehdr.e_shstrndx = shnum - 1;
2102 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2103 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2104 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2106 for(i=1;i<s1->nb_sections;i++) {
2107 s = s1->sections[section_order[i]];
2108 if (s->sh_type != SHT_NOBITS) {
2109 #if defined(__FreeBSD__)
2110 if (s->sh_type == SHT_DYNSYM)
2111 patch_dynsym_undef(s1, s);
2112 #endif
2113 while (offset < s->sh_offset) {
2114 fputc(0, f);
2115 offset++;
2117 size = s->sh_size;
2118 fwrite(s->data, 1, size, f);
2119 offset += size;
2123 /* output section headers */
2124 while (offset < ehdr.e_shoff) {
2125 fputc(0, f);
2126 offset++;
2129 for(i=0;i<s1->nb_sections;i++) {
2130 sh = &shdr;
2131 memset(sh, 0, sizeof(ElfW(Shdr)));
2132 s = s1->sections[i];
2133 if (s) {
2134 sh->sh_name = s->sh_name;
2135 sh->sh_type = s->sh_type;
2136 sh->sh_flags = s->sh_flags;
2137 sh->sh_entsize = s->sh_entsize;
2138 sh->sh_info = s->sh_info;
2139 if (s->link)
2140 sh->sh_link = s->link->sh_num;
2141 sh->sh_addralign = s->sh_addralign;
2142 sh->sh_addr = s->sh_addr;
2143 sh->sh_offset = s->sh_offset;
2144 sh->sh_size = s->sh_size;
2146 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2148 } else {
2149 tcc_output_binary(s1, f, section_order);
2151 fclose(f);
2153 ret = 0;
2154 the_end:
2155 tcc_free(s1->symtab_to_dynsym);
2156 tcc_free(section_order);
2157 tcc_free(phdr);
2158 tcc_free(s1->got_offsets);
2159 return ret;
2162 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2164 int ret;
2165 #ifdef TCC_TARGET_PE
2166 if (s->output_type != TCC_OUTPUT_OBJ) {
2167 ret = pe_output_file(s, filename);
2168 } else
2169 #endif
2171 ret = elf_output_file(s, filename);
2173 return ret;
2176 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2178 void *data;
2180 data = tcc_malloc(size);
2181 lseek(fd, file_offset, SEEK_SET);
2182 read(fd, data, size);
2183 return data;
2186 typedef struct SectionMergeInfo {
2187 Section *s; /* corresponding existing section */
2188 unsigned long offset; /* offset of the new section in the existing section */
2189 uint8_t new_section; /* true if section 's' was added */
2190 uint8_t link_once; /* true if link once section */
2191 } SectionMergeInfo;
2193 /* load an object file and merge it with current files */
2194 /* XXX: handle correctly stab (debug) info */
2195 ST_FUNC int tcc_load_object_file(TCCState *s1,
2196 int fd, unsigned long file_offset)
2198 ElfW(Ehdr) ehdr;
2199 ElfW(Shdr) *shdr, *sh;
2200 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2201 unsigned char *strsec, *strtab;
2202 int *old_to_new_syms;
2203 char *sh_name, *name;
2204 SectionMergeInfo *sm_table, *sm;
2205 ElfW(Sym) *sym, *symtab;
2206 ElfW_Rel *rel, *rel_end;
2207 Section *s;
2209 int stab_index;
2210 int stabstr_index;
2212 stab_index = stabstr_index = 0;
2214 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2215 goto fail1;
2216 if (ehdr.e_ident[0] != ELFMAG0 ||
2217 ehdr.e_ident[1] != ELFMAG1 ||
2218 ehdr.e_ident[2] != ELFMAG2 ||
2219 ehdr.e_ident[3] != ELFMAG3)
2220 goto fail1;
2221 /* test if object file */
2222 if (ehdr.e_type != ET_REL)
2223 goto fail1;
2224 /* test CPU specific stuff */
2225 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2226 ehdr.e_machine != EM_TCC_TARGET) {
2227 fail1:
2228 error_noabort("invalid object file");
2229 return -1;
2231 /* read sections */
2232 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2233 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2234 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2236 /* load section names */
2237 sh = &shdr[ehdr.e_shstrndx];
2238 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2240 /* load symtab and strtab */
2241 old_to_new_syms = NULL;
2242 symtab = NULL;
2243 strtab = NULL;
2244 nb_syms = 0;
2245 for(i = 1; i < ehdr.e_shnum; i++) {
2246 sh = &shdr[i];
2247 if (sh->sh_type == SHT_SYMTAB) {
2248 if (symtab) {
2249 error_noabort("object must contain only one symtab");
2250 fail:
2251 ret = -1;
2252 goto the_end;
2254 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2255 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2256 sm_table[i].s = symtab_section;
2258 /* now load strtab */
2259 sh = &shdr[sh->sh_link];
2260 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2264 /* now examine each section and try to merge its content with the
2265 ones in memory */
2266 for(i = 1; i < ehdr.e_shnum; i++) {
2267 /* no need to examine section name strtab */
2268 if (i == ehdr.e_shstrndx)
2269 continue;
2270 sh = &shdr[i];
2271 sh_name = strsec + sh->sh_name;
2272 /* ignore sections types we do not handle */
2273 if (sh->sh_type != SHT_PROGBITS &&
2274 sh->sh_type != SHT_RELX &&
2275 #ifdef TCC_ARM_EABI
2276 sh->sh_type != SHT_ARM_EXIDX &&
2277 #endif
2278 sh->sh_type != SHT_NOBITS &&
2279 strcmp(sh_name, ".stabstr")
2281 continue;
2282 if (sh->sh_addralign < 1)
2283 sh->sh_addralign = 1;
2284 /* find corresponding section, if any */
2285 for(j = 1; j < s1->nb_sections;j++) {
2286 s = s1->sections[j];
2287 if (!strcmp(s->name, sh_name)) {
2288 if (!strncmp(sh_name, ".gnu.linkonce",
2289 sizeof(".gnu.linkonce") - 1)) {
2290 /* if a 'linkonce' section is already present, we
2291 do not add it again. It is a little tricky as
2292 symbols can still be defined in
2293 it. */
2294 sm_table[i].link_once = 1;
2295 goto next;
2296 } else {
2297 goto found;
2301 /* not found: create new section */
2302 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2303 /* take as much info as possible from the section. sh_link and
2304 sh_info will be updated later */
2305 s->sh_addralign = sh->sh_addralign;
2306 s->sh_entsize = sh->sh_entsize;
2307 sm_table[i].new_section = 1;
2308 found:
2309 if (sh->sh_type != s->sh_type) {
2310 error_noabort("invalid section type");
2311 goto fail;
2314 /* align start of section */
2315 offset = s->data_offset;
2317 if (0 == strcmp(sh_name, ".stab")) {
2318 stab_index = i;
2319 goto no_align;
2321 if (0 == strcmp(sh_name, ".stabstr")) {
2322 stabstr_index = i;
2323 goto no_align;
2326 size = sh->sh_addralign - 1;
2327 offset = (offset + size) & ~size;
2328 if (sh->sh_addralign > s->sh_addralign)
2329 s->sh_addralign = sh->sh_addralign;
2330 s->data_offset = offset;
2331 no_align:
2332 sm_table[i].offset = offset;
2333 sm_table[i].s = s;
2334 /* concatenate sections */
2335 size = sh->sh_size;
2336 if (sh->sh_type != SHT_NOBITS) {
2337 unsigned char *ptr;
2338 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2339 ptr = section_ptr_add(s, size);
2340 read(fd, ptr, size);
2341 } else {
2342 s->data_offset += size;
2344 next: ;
2347 /* //gr relocate stab strings */
2348 if (stab_index && stabstr_index) {
2349 Stab_Sym *a, *b;
2350 unsigned o;
2351 s = sm_table[stab_index].s;
2352 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2353 b = (Stab_Sym *)(s->data + s->data_offset);
2354 o = sm_table[stabstr_index].offset;
2355 while (a < b)
2356 a->n_strx += o, a++;
2359 /* second short pass to update sh_link and sh_info fields of new
2360 sections */
2361 for(i = 1; i < ehdr.e_shnum; i++) {
2362 s = sm_table[i].s;
2363 if (!s || !sm_table[i].new_section)
2364 continue;
2365 sh = &shdr[i];
2366 if (sh->sh_link > 0)
2367 s->link = sm_table[sh->sh_link].s;
2368 if (sh->sh_type == SHT_RELX) {
2369 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2370 /* update backward link */
2371 s1->sections[s->sh_info]->reloc = s;
2374 sm = sm_table;
2376 /* resolve symbols */
2377 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2379 sym = symtab + 1;
2380 for(i = 1; i < nb_syms; i++, sym++) {
2381 if (sym->st_shndx != SHN_UNDEF &&
2382 sym->st_shndx < SHN_LORESERVE) {
2383 sm = &sm_table[sym->st_shndx];
2384 if (sm->link_once) {
2385 /* if a symbol is in a link once section, we use the
2386 already defined symbol. It is very important to get
2387 correct relocations */
2388 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2389 name = strtab + sym->st_name;
2390 sym_index = find_elf_sym(symtab_section, name);
2391 if (sym_index)
2392 old_to_new_syms[i] = sym_index;
2394 continue;
2396 /* if no corresponding section added, no need to add symbol */
2397 if (!sm->s)
2398 continue;
2399 /* convert section number */
2400 sym->st_shndx = sm->s->sh_num;
2401 /* offset value */
2402 sym->st_value += sm->offset;
2404 /* add symbol */
2405 name = strtab + sym->st_name;
2406 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2407 sym->st_info, sym->st_other,
2408 sym->st_shndx, name);
2409 old_to_new_syms[i] = sym_index;
2412 /* third pass to patch relocation entries */
2413 for(i = 1; i < ehdr.e_shnum; i++) {
2414 s = sm_table[i].s;
2415 if (!s)
2416 continue;
2417 sh = &shdr[i];
2418 offset = sm_table[i].offset;
2419 switch(s->sh_type) {
2420 case SHT_RELX:
2421 /* take relocation offset information */
2422 offseti = sm_table[sh->sh_info].offset;
2423 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2424 for(rel = (ElfW_Rel *)(s->data + offset);
2425 rel < rel_end;
2426 rel++) {
2427 int type;
2428 unsigned sym_index;
2429 /* convert symbol index */
2430 type = ELFW(R_TYPE)(rel->r_info);
2431 sym_index = ELFW(R_SYM)(rel->r_info);
2432 /* NOTE: only one symtab assumed */
2433 if (sym_index >= nb_syms)
2434 goto invalid_reloc;
2435 sym_index = old_to_new_syms[sym_index];
2436 /* ignore link_once in rel section. */
2437 if (!sym_index && !sm->link_once) {
2438 invalid_reloc:
2439 error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2440 i, strsec + sh->sh_name, rel->r_offset);
2441 goto fail;
2443 rel->r_info = ELFW(R_INFO)(sym_index, type);
2444 /* offset the relocation offset */
2445 rel->r_offset += offseti;
2447 break;
2448 default:
2449 break;
2453 ret = 0;
2454 the_end:
2455 tcc_free(symtab);
2456 tcc_free(strtab);
2457 tcc_free(old_to_new_syms);
2458 tcc_free(sm_table);
2459 tcc_free(strsec);
2460 tcc_free(shdr);
2461 return ret;
2464 typedef struct ArchiveHeader {
2465 char ar_name[16]; /* name of this member */
2466 char ar_date[12]; /* file mtime */
2467 char ar_uid[6]; /* owner uid; printed as decimal */
2468 char ar_gid[6]; /* owner gid; printed as decimal */
2469 char ar_mode[8]; /* file mode, printed as octal */
2470 char ar_size[10]; /* file size, printed as decimal */
2471 char ar_fmag[2]; /* should contain ARFMAG */
2472 } ArchiveHeader;
2474 static int get_be32(const uint8_t *b)
2476 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2479 /* load only the objects which resolve undefined symbols */
2480 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2482 int i, bound, nsyms, sym_index, off, ret;
2483 uint8_t *data;
2484 const char *ar_names, *p;
2485 const uint8_t *ar_index;
2486 ElfW(Sym) *sym;
2488 data = tcc_malloc(size);
2489 if (read(fd, data, size) != size)
2490 goto fail;
2491 nsyms = get_be32(data);
2492 ar_index = data + 4;
2493 ar_names = ar_index + nsyms * 4;
2495 do {
2496 bound = 0;
2497 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2498 sym_index = find_elf_sym(symtab_section, p);
2499 if(sym_index) {
2500 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2501 if(sym->st_shndx == SHN_UNDEF) {
2502 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2503 #if 0
2504 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2505 #endif
2506 ++bound;
2507 lseek(fd, off, SEEK_SET);
2508 if(tcc_load_object_file(s1, fd, off) < 0) {
2509 fail:
2510 ret = -1;
2511 goto the_end;
2516 } while(bound);
2517 ret = 0;
2518 the_end:
2519 tcc_free(data);
2520 return ret;
2523 /* load a '.a' file */
2524 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2526 ArchiveHeader hdr;
2527 char ar_size[11];
2528 char ar_name[17];
2529 char magic[8];
2530 int size, len, i;
2531 unsigned long file_offset;
2533 /* skip magic which was already checked */
2534 read(fd, magic, sizeof(magic));
2536 for(;;) {
2537 len = read(fd, &hdr, sizeof(hdr));
2538 if (len == 0)
2539 break;
2540 if (len != sizeof(hdr)) {
2541 error_noabort("invalid archive");
2542 return -1;
2544 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2545 ar_size[sizeof(hdr.ar_size)] = '\0';
2546 size = strtol(ar_size, NULL, 0);
2547 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2548 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2549 if (ar_name[i] != ' ')
2550 break;
2552 ar_name[i + 1] = '\0';
2553 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2554 file_offset = lseek(fd, 0, SEEK_CUR);
2555 /* align to even */
2556 size = (size + 1) & ~1;
2557 if (!strcmp(ar_name, "/")) {
2558 /* coff symbol table : we handle it */
2559 if(s1->alacarte_link)
2560 return tcc_load_alacarte(s1, fd, size);
2561 } else if (!strcmp(ar_name, "//") ||
2562 !strcmp(ar_name, "__.SYMDEF") ||
2563 !strcmp(ar_name, "__.SYMDEF/") ||
2564 !strcmp(ar_name, "ARFILENAMES/")) {
2565 /* skip symbol table or archive names */
2566 } else {
2567 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2568 return -1;
2570 lseek(fd, file_offset + size, SEEK_SET);
2572 return 0;
2575 #ifndef TCC_TARGET_PE
2576 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2577 is referenced by the user (so it should be added as DT_NEEDED in
2578 the generated ELF file) */
2579 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2581 ElfW(Ehdr) ehdr;
2582 ElfW(Shdr) *shdr, *sh, *sh1;
2583 int i, j, nb_syms, nb_dts, sym_bind, ret;
2584 ElfW(Sym) *sym, *dynsym;
2585 ElfW(Dyn) *dt, *dynamic;
2586 unsigned char *dynstr;
2587 const char *name, *soname;
2588 DLLReference *dllref;
2590 read(fd, &ehdr, sizeof(ehdr));
2592 /* test CPU specific stuff */
2593 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2594 ehdr.e_machine != EM_TCC_TARGET) {
2595 error_noabort("bad architecture");
2596 return -1;
2599 /* read sections */
2600 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2602 /* load dynamic section and dynamic symbols */
2603 nb_syms = 0;
2604 nb_dts = 0;
2605 dynamic = NULL;
2606 dynsym = NULL; /* avoid warning */
2607 dynstr = NULL; /* avoid warning */
2608 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2609 switch(sh->sh_type) {
2610 case SHT_DYNAMIC:
2611 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2612 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2613 break;
2614 case SHT_DYNSYM:
2615 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2616 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2617 sh1 = &shdr[sh->sh_link];
2618 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2619 break;
2620 default:
2621 break;
2625 /* compute the real library name */
2626 soname = tcc_basename(filename);
2628 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2629 if (dt->d_tag == DT_SONAME) {
2630 soname = dynstr + dt->d_un.d_val;
2634 /* if the dll is already loaded, do not load it */
2635 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2636 dllref = s1->loaded_dlls[i];
2637 if (!strcmp(soname, dllref->name)) {
2638 /* but update level if needed */
2639 if (level < dllref->level)
2640 dllref->level = level;
2641 ret = 0;
2642 goto the_end;
2646 // printf("loading dll '%s'\n", soname);
2648 /* add the dll and its level */
2649 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2650 dllref->level = level;
2651 strcpy(dllref->name, soname);
2652 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2654 /* add dynamic symbols in dynsym_section */
2655 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2656 sym_bind = ELFW(ST_BIND)(sym->st_info);
2657 if (sym_bind == STB_LOCAL)
2658 continue;
2659 name = dynstr + sym->st_name;
2660 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2661 sym->st_info, sym->st_other, sym->st_shndx, name);
2664 /* load all referenced DLLs */
2665 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2666 switch(dt->d_tag) {
2667 case DT_NEEDED:
2668 name = dynstr + dt->d_un.d_val;
2669 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2670 dllref = s1->loaded_dlls[j];
2671 if (!strcmp(name, dllref->name))
2672 goto already_loaded;
2674 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2675 error_noabort("referenced dll '%s' not found", name);
2676 ret = -1;
2677 goto the_end;
2679 already_loaded:
2680 break;
2683 ret = 0;
2684 the_end:
2685 tcc_free(dynstr);
2686 tcc_free(dynsym);
2687 tcc_free(dynamic);
2688 tcc_free(shdr);
2689 return ret;
2692 #define LD_TOK_NAME 256
2693 #define LD_TOK_EOF (-1)
2695 /* return next ld script token */
2696 static int ld_next(TCCState *s1, char *name, int name_size)
2698 int c;
2699 char *q;
2701 redo:
2702 switch(ch) {
2703 case ' ':
2704 case '\t':
2705 case '\f':
2706 case '\v':
2707 case '\r':
2708 case '\n':
2709 inp();
2710 goto redo;
2711 case '/':
2712 minp();
2713 if (ch == '*') {
2714 file->buf_ptr = parse_comment(file->buf_ptr);
2715 ch = file->buf_ptr[0];
2716 goto redo;
2717 } else {
2718 q = name;
2719 *q++ = '/';
2720 goto parse_name;
2722 break;
2723 /* case 'a' ... 'z': */
2724 case 'a':
2725 case 'b':
2726 case 'c':
2727 case 'd':
2728 case 'e':
2729 case 'f':
2730 case 'g':
2731 case 'h':
2732 case 'i':
2733 case 'j':
2734 case 'k':
2735 case 'l':
2736 case 'm':
2737 case 'n':
2738 case 'o':
2739 case 'p':
2740 case 'q':
2741 case 'r':
2742 case 's':
2743 case 't':
2744 case 'u':
2745 case 'v':
2746 case 'w':
2747 case 'x':
2748 case 'y':
2749 case 'z':
2750 /* case 'A' ... 'z': */
2751 case 'A':
2752 case 'B':
2753 case 'C':
2754 case 'D':
2755 case 'E':
2756 case 'F':
2757 case 'G':
2758 case 'H':
2759 case 'I':
2760 case 'J':
2761 case 'K':
2762 case 'L':
2763 case 'M':
2764 case 'N':
2765 case 'O':
2766 case 'P':
2767 case 'Q':
2768 case 'R':
2769 case 'S':
2770 case 'T':
2771 case 'U':
2772 case 'V':
2773 case 'W':
2774 case 'X':
2775 case 'Y':
2776 case 'Z':
2777 case '_':
2778 case '\\':
2779 case '.':
2780 case '$':
2781 case '~':
2782 q = name;
2783 parse_name:
2784 for(;;) {
2785 if (!((ch >= 'a' && ch <= 'z') ||
2786 (ch >= 'A' && ch <= 'Z') ||
2787 (ch >= '0' && ch <= '9') ||
2788 strchr("/.-_+=$:\\,~", ch)))
2789 break;
2790 if ((q - name) < name_size - 1) {
2791 *q++ = ch;
2793 minp();
2795 *q = '\0';
2796 c = LD_TOK_NAME;
2797 break;
2798 case CH_EOF:
2799 c = LD_TOK_EOF;
2800 break;
2801 default:
2802 c = ch;
2803 inp();
2804 break;
2806 #if 0
2807 printf("tok=%c %d\n", c, c);
2808 if (c == LD_TOK_NAME)
2809 printf(" name=%s\n", name);
2810 #endif
2811 return c;
2814 char *tcc_strcpy_part(char *out, const char *in, size_t num)
2816 memcpy(out, in, num);
2817 out[num] = '\0';
2818 return out;
2822 * Extract the library name from the file name
2823 * Return 0 if the file isn't a library
2825 * /!\ No test on filename capacity, be careful
2827 static int filename_to_libname(TCCState *s1, const char filename[], char libname[])
2829 char *ext;
2830 int libprefix;
2832 /* already converted to library name */
2833 if (libname[0] != '\0')
2834 return 1;
2835 ext = tcc_fileextension(filename);
2836 if (*ext == '\0')
2837 return 0;
2838 libprefix = !strncmp(filename, "lib", 3);
2839 if (!s1->static_link) {
2840 #ifdef TCC_TARGET_PE
2841 if (!strcmp(ext, ".def")) {
2842 size_t len = ext - filename;
2843 tcc_strcpy_part(libname, filename, len);
2844 return 1;
2846 #else
2847 if (libprefix && (!strcmp(ext, ".so"))) {
2848 size_t len = ext - filename - 3;
2849 tcc_strcpy_part(libname, filename + 3, len);
2850 return 1;
2852 #endif
2853 } else {
2854 if (libprefix && (!strcmp(ext, ".a"))) {
2855 size_t len = ext - filename - 3;
2856 tcc_strcpy_part(libname, filename + 3, len);
2857 return 1;
2860 return 0;
2864 * Extract the file name from the library name
2866 * /!\ No test on filename capacity, be careful
2868 static void libname_to_filename(TCCState *s1, const char libname[], char filename[])
2870 if (!s1->static_link) {
2871 #ifdef TCC_TARGET_PE
2872 sprintf(filename, "%s.def", libname);
2873 #else
2874 sprintf(filename, "lib%s.so", libname);
2875 #endif
2876 } else {
2877 sprintf(filename, "lib%s.a", libname);
2881 static int ld_add_file(TCCState *s1, const char filename[], char libname[])
2883 int ret;
2885 ret = tcc_add_file_internal(s1, filename, 0);
2886 if (ret) {
2887 if (filename_to_libname(s1, filename, libname))
2888 ret = tcc_add_library(s1, libname);
2890 return ret;
2893 static inline int new_undef_syms(void)
2895 int ret = 0;
2896 ret = new_undef_sym;
2897 new_undef_sym = 0;
2898 return ret;
2901 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
2903 char filename[1024], libname[1024];
2904 int t, group, nblibs = 0, ret = 0;
2905 char **libs = NULL;
2907 group = !strcmp(cmd, "GROUP");
2908 if (!as_needed)
2909 new_undef_syms();
2910 t = ld_next(s1, filename, sizeof(filename));
2911 if (t != '(')
2912 expect("(");
2913 t = ld_next(s1, filename, sizeof(filename));
2914 for(;;) {
2915 libname[0] = '\0';
2916 if (t == LD_TOK_EOF) {
2917 error_noabort("unexpected end of file");
2918 ret = -1;
2919 goto lib_parse_error;
2920 } else if (t == ')') {
2921 break;
2922 } else if (t == '-') {
2923 t = ld_next(s1, filename, sizeof(filename));
2924 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
2925 error_noabort("library name expected");
2926 ret = -1;
2927 goto lib_parse_error;
2929 strcpy(libname, &filename[1]);
2930 libname_to_filename(s1, libname, filename);
2931 } else if (t != LD_TOK_NAME) {
2932 error_noabort("filename expected");
2933 ret = -1;
2934 goto lib_parse_error;
2936 if (!strcmp(filename, "AS_NEEDED")) {
2937 ret = ld_add_file_list(s1, cmd, 1);
2938 if (ret)
2939 goto lib_parse_error;
2940 } else {
2941 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2942 if (!as_needed) {
2943 ret = ld_add_file(s1, filename, libname);
2944 if (ret)
2945 goto lib_parse_error;
2946 if (group) {
2947 /* Add the filename *and* the libname to avoid future conversions */
2948 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
2949 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
2953 t = ld_next(s1, filename, sizeof(filename));
2954 if (t == ',') {
2955 t = ld_next(s1, filename, sizeof(filename));
2958 if (group && !as_needed) {
2959 while (new_undef_syms()) {
2960 int i;
2962 for (i = 0; i < nblibs; i += 2)
2963 ld_add_file(s1, libs[i], libs[i+1]);
2966 lib_parse_error:
2967 dynarray_reset(&libs, &nblibs);
2968 return ret;
2971 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
2972 files */
2973 ST_FUNC int tcc_load_ldscript(TCCState *s1)
2975 char cmd[64];
2976 char filename[1024];
2977 int t, ret;
2979 ch = file->buf_ptr[0];
2980 ch = handle_eob();
2981 for(;;) {
2982 t = ld_next(s1, cmd, sizeof(cmd));
2983 if (t == LD_TOK_EOF)
2984 return 0;
2985 else if (t != LD_TOK_NAME)
2986 return -1;
2987 if (!strcmp(cmd, "INPUT") ||
2988 !strcmp(cmd, "GROUP")) {
2989 ret = ld_add_file_list(s1, cmd, 0);
2990 if (ret)
2991 return ret;
2992 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
2993 !strcmp(cmd, "TARGET")) {
2994 /* ignore some commands */
2995 t = ld_next(s1, cmd, sizeof(cmd));
2996 if (t != '(')
2997 expect("(");
2998 for(;;) {
2999 t = ld_next(s1, filename, sizeof(filename));
3000 if (t == LD_TOK_EOF) {
3001 error_noabort("unexpected end of file");
3002 return -1;
3003 } else if (t == ')') {
3004 break;
3007 } else {
3008 return -1;
3011 return 0;
3013 #endif