libtcc: tcc_get_symbol uses the TCCState parameter
[tinycc.git] / tccelf.c
blob90e48155d824515da2935acafbf12da13d58aa9a
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(s->symtab, name);
166 sym = &((ElfW(Sym) *)s->symtab->data)[sym_index];
167 if (!sym_index || sym->st_shndx == SHN_UNDEF) {
168 if (err)
169 tcc_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 tcc_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 tcc_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 tcc_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 tcc_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 tcc_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 tcc_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 s1->got_offsets = tab;
840 memset(s1->got_offsets + s1->nb_got_offsets, 0,
841 (n - s1->nb_got_offsets) * sizeof(unsigned long));
842 s1->nb_got_offsets = n;
844 s1->got_offsets[index] = val;
847 /* XXX: suppress that */
848 static void put32(unsigned char *p, uint32_t val)
850 p[0] = val;
851 p[1] = val >> 8;
852 p[2] = val >> 16;
853 p[3] = val >> 24;
856 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
857 defined(TCC_TARGET_X86_64)
858 static uint32_t get32(unsigned char *p)
860 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
862 #endif
864 static void build_got(TCCState *s1)
866 unsigned char *ptr;
868 /* if no got, then create it */
869 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
870 s1->got->sh_entsize = 4;
871 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
872 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
873 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
874 #if PTR_SIZE == 4
875 /* keep space for _DYNAMIC pointer, if present */
876 put32(ptr, 0);
877 /* two dummy got entries */
878 put32(ptr + 4, 0);
879 put32(ptr + 8, 0);
880 #else
881 /* keep space for _DYNAMIC pointer, if present */
882 put32(ptr, 0);
883 put32(ptr + 4, 0);
884 /* two dummy got entries */
885 put32(ptr + 8, 0);
886 put32(ptr + 12, 0);
887 put32(ptr + 16, 0);
888 put32(ptr + 20, 0);
889 #endif
892 /* put a got entry corresponding to a symbol in symtab_section. 'size'
893 and 'info' can be modifed if more precise info comes from the DLL */
894 static void put_got_entry(TCCState *s1,
895 int reloc_type, unsigned long size, int info,
896 int sym_index)
898 int index;
899 const char *name;
900 ElfW(Sym) *sym;
901 unsigned long offset;
902 int *ptr;
904 if (!s1->got)
905 build_got(s1);
907 /* if a got entry already exists for that symbol, no need to add one */
908 if (sym_index < s1->nb_got_offsets &&
909 s1->got_offsets[sym_index] != 0)
910 return;
912 put_got_offset(s1, sym_index, s1->got->data_offset);
914 if (s1->dynsym) {
915 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
916 name = symtab_section->link->data + sym->st_name;
917 offset = sym->st_value;
918 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
919 if (reloc_type ==
920 #ifdef TCC_TARGET_X86_64
921 R_X86_64_JUMP_SLOT
922 #else
923 R_386_JMP_SLOT
924 #endif
926 Section *plt;
927 uint8_t *p;
928 int modrm;
930 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
931 modrm = 0x25;
932 #else
933 /* if we build a DLL, we add a %ebx offset */
934 if (s1->output_type == TCC_OUTPUT_DLL)
935 modrm = 0xa3;
936 else
937 modrm = 0x25;
938 #endif
940 /* add a PLT entry */
941 plt = s1->plt;
942 if (plt->data_offset == 0) {
943 /* first plt entry */
944 p = section_ptr_add(plt, 16);
945 p[0] = 0xff; /* pushl got + PTR_SIZE */
946 p[1] = modrm + 0x10;
947 put32(p + 2, PTR_SIZE);
948 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
949 p[7] = modrm;
950 put32(p + 8, PTR_SIZE * 2);
953 p = section_ptr_add(plt, 16);
954 p[0] = 0xff; /* jmp *(got + x) */
955 p[1] = modrm;
956 put32(p + 2, s1->got->data_offset);
957 p[6] = 0x68; /* push $xxx */
958 put32(p + 7, (plt->data_offset - 32) >> 1);
959 p[11] = 0xe9; /* jmp plt_start */
960 put32(p + 12, -(plt->data_offset));
962 /* the symbol is modified so that it will be relocated to
963 the PLT */
964 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
965 if (s1->output_type == TCC_OUTPUT_EXE)
966 #endif
967 offset = plt->data_offset - 16;
969 #elif defined(TCC_TARGET_ARM)
970 if (reloc_type == R_ARM_JUMP_SLOT) {
971 Section *plt;
972 uint8_t *p;
974 /* if we build a DLL, we add a %ebx offset */
975 if (s1->output_type == TCC_OUTPUT_DLL)
976 tcc_error("DLLs unimplemented!");
978 /* add a PLT entry */
979 plt = s1->plt;
980 if (plt->data_offset == 0) {
981 /* first plt entry */
982 p = section_ptr_add(plt, 16);
983 put32(p , 0xe52de004);
984 put32(p + 4, 0xe59fe010);
985 put32(p + 8, 0xe08fe00e);
986 put32(p + 12, 0xe5bef008);
989 p = section_ptr_add(plt, 16);
990 put32(p , 0xe59fc004);
991 put32(p+4, 0xe08fc00c);
992 put32(p+8, 0xe59cf000);
993 put32(p+12, s1->got->data_offset);
995 /* the symbol is modified so that it will be relocated to
996 the PLT */
997 if (s1->output_type == TCC_OUTPUT_EXE)
998 offset = plt->data_offset - 16;
1000 #elif defined(TCC_TARGET_C67)
1001 tcc_error("C67 got not implemented");
1002 #else
1003 #error unsupported CPU
1004 #endif
1005 index = put_elf_sym(s1->dynsym, offset,
1006 size, info, 0, sym->st_shndx, name);
1007 /* put a got entry */
1008 put_elf_reloc(s1->dynsym, s1->got,
1009 s1->got->data_offset,
1010 reloc_type, index);
1012 ptr = section_ptr_add(s1->got, PTR_SIZE);
1013 *ptr = 0;
1016 /* build GOT and PLT entries */
1017 ST_FUNC void build_got_entries(TCCState *s1)
1019 Section *s;
1020 ElfW_Rel *rel, *rel_end;
1021 ElfW(Sym) *sym;
1022 int i, type, reloc_type, sym_index;
1024 for(i = 1; i < s1->nb_sections; i++) {
1025 s = s1->sections[i];
1026 if (s->sh_type != SHT_RELX)
1027 continue;
1028 /* no need to handle got relocations */
1029 if (s->link != symtab_section)
1030 continue;
1031 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1032 for(rel = (ElfW_Rel *)s->data;
1033 rel < rel_end;
1034 rel++) {
1035 type = ELFW(R_TYPE)(rel->r_info);
1036 switch(type) {
1037 #if defined(TCC_TARGET_I386)
1038 case R_386_GOT32:
1039 case R_386_GOTOFF:
1040 case R_386_GOTPC:
1041 case R_386_PLT32:
1042 if (!s1->got)
1043 build_got(s1);
1044 if (type == R_386_GOT32 || type == R_386_PLT32) {
1045 sym_index = ELFW(R_SYM)(rel->r_info);
1046 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1047 /* look at the symbol got offset. If none, then add one */
1048 if (type == R_386_GOT32)
1049 reloc_type = R_386_GLOB_DAT;
1050 else
1051 reloc_type = R_386_JMP_SLOT;
1052 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1053 sym_index);
1055 break;
1056 #elif defined(TCC_TARGET_ARM)
1057 case R_ARM_GOT_BREL:
1058 case R_ARM_GOTOFF32:
1059 case R_ARM_BASE_PREL:
1060 case R_ARM_PLT32:
1061 if (!s1->got)
1062 build_got(s1);
1063 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1064 sym_index = ELFW(R_SYM)(rel->r_info);
1065 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1066 /* look at the symbol got offset. If none, then add one */
1067 if (type == R_ARM_GOT_BREL)
1068 reloc_type = R_ARM_GLOB_DAT;
1069 else
1070 reloc_type = R_ARM_JUMP_SLOT;
1071 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1072 sym_index);
1074 break;
1075 #elif defined(TCC_TARGET_C67)
1076 case R_C60_GOT32:
1077 case R_C60_GOTOFF:
1078 case R_C60_GOTPC:
1079 case R_C60_PLT32:
1080 if (!s1->got)
1081 build_got(s1);
1082 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1083 sym_index = ELFW(R_SYM)(rel->r_info);
1084 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1085 /* look at the symbol got offset. If none, then add one */
1086 if (type == R_C60_GOT32)
1087 reloc_type = R_C60_GLOB_DAT;
1088 else
1089 reloc_type = R_C60_JMP_SLOT;
1090 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1091 sym_index);
1093 break;
1094 #elif defined(TCC_TARGET_X86_64)
1095 case R_X86_64_GOT32:
1096 case R_X86_64_GOTTPOFF:
1097 case R_X86_64_GOTPCREL:
1098 case R_X86_64_PLT32:
1099 if (!s1->got)
1100 build_got(s1);
1101 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1102 type == R_X86_64_PLT32) {
1103 sym_index = ELFW(R_SYM)(rel->r_info);
1104 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1105 /* look at the symbol got offset. If none, then add one */
1106 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1107 reloc_type = R_X86_64_GLOB_DAT;
1108 else
1109 reloc_type = R_X86_64_JUMP_SLOT;
1110 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1111 sym_index);
1113 break;
1114 #else
1115 #error unsupported CPU
1116 #endif
1117 default:
1118 break;
1124 ST_FUNC Section *new_symtab(TCCState *s1,
1125 const char *symtab_name, int sh_type, int sh_flags,
1126 const char *strtab_name,
1127 const char *hash_name, int hash_sh_flags)
1129 Section *symtab, *strtab, *hash;
1130 int *ptr, nb_buckets;
1132 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1133 symtab->sh_entsize = sizeof(ElfW(Sym));
1134 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1135 put_elf_str(strtab, "");
1136 symtab->link = strtab;
1137 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1139 nb_buckets = 1;
1141 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1142 hash->sh_entsize = sizeof(int);
1143 symtab->hash = hash;
1144 hash->link = symtab;
1146 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1147 ptr[0] = nb_buckets;
1148 ptr[1] = 1;
1149 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1150 return symtab;
1153 /* put dynamic tag */
1154 static void put_dt(Section *dynamic, int dt, uplong val)
1156 ElfW(Dyn) *dyn;
1157 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1158 dyn->d_tag = dt;
1159 dyn->d_un.d_val = val;
1162 static void add_init_array_defines(TCCState *s1, const char *section_name)
1164 Section *s;
1165 long end_offset;
1166 char sym_start[1024];
1167 char sym_end[1024];
1169 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1170 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1172 s = find_section(s1, section_name);
1173 if (!s) {
1174 end_offset = 0;
1175 s = data_section;
1176 } else {
1177 end_offset = s->data_offset;
1180 add_elf_sym(symtab_section,
1181 0, 0,
1182 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1183 s->sh_num, sym_start);
1184 add_elf_sym(symtab_section,
1185 end_offset, 0,
1186 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1187 s->sh_num, sym_end);
1190 static int tcc_add_support(TCCState *s1, const char *filename)
1192 char buf[1024];
1193 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, filename);
1194 return tcc_add_file(s1, buf);
1197 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1199 #ifdef CONFIG_TCC_BCHECK
1200 unsigned long *ptr;
1201 Section *init_section;
1202 unsigned char *pinit;
1203 int sym_index;
1205 if (0 == s1->do_bounds_check)
1206 return;
1208 /* XXX: add an object file to do that */
1209 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1210 *ptr = 0;
1211 add_elf_sym(symtab_section, 0, 0,
1212 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1213 bounds_section->sh_num, "__bounds_start");
1214 /* add bound check code */
1215 #ifndef TCC_TARGET_PE
1216 tcc_add_support(s1, "bcheck.o");
1217 #endif
1218 #ifdef TCC_TARGET_I386
1219 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1220 /* add 'call __bound_init()' in .init section */
1221 init_section = find_section(s1, ".init");
1222 pinit = section_ptr_add(init_section, 5);
1223 pinit[0] = 0xe8;
1224 put32(pinit + 1, -4);
1225 sym_index = find_elf_sym(symtab_section, "__bound_init");
1226 put_elf_reloc(symtab_section, init_section,
1227 init_section->data_offset - 4, R_386_PC32, sym_index);
1229 #endif
1230 #endif
1233 /* add tcc runtime libraries */
1234 ST_FUNC void tcc_add_runtime(TCCState *s1)
1236 tcc_add_bcheck(s1);
1238 /* add libc */
1239 if (!s1->nostdlib) {
1240 tcc_add_library(s1, "c");
1241 #ifdef CONFIG_USE_LIBGCC
1242 tcc_add_file(s1, TCC_LIBGCC);
1243 #elif !defined WITHOUT_LIBTCC
1244 tcc_add_support(s1, "libtcc1.a");
1245 #endif
1246 /* add crt end if not memory output */
1247 if (s1->output_type != TCC_OUTPUT_MEMORY)
1248 tcc_add_crt(s1, "crtn.o");
1252 /* add various standard linker symbols (must be done after the
1253 sections are filled (for example after allocating common
1254 symbols)) */
1255 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1257 char buf[1024];
1258 int i;
1259 Section *s;
1261 add_elf_sym(symtab_section,
1262 text_section->data_offset, 0,
1263 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1264 text_section->sh_num, "_etext");
1265 add_elf_sym(symtab_section,
1266 data_section->data_offset, 0,
1267 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1268 data_section->sh_num, "_edata");
1269 add_elf_sym(symtab_section,
1270 bss_section->data_offset, 0,
1271 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1272 bss_section->sh_num, "_end");
1273 /* horrible new standard ldscript defines */
1274 add_init_array_defines(s1, ".preinit_array");
1275 add_init_array_defines(s1, ".init_array");
1276 add_init_array_defines(s1, ".fini_array");
1278 /* add start and stop symbols for sections whose name can be
1279 expressed in C */
1280 for(i = 1; i < s1->nb_sections; i++) {
1281 s = s1->sections[i];
1282 if (s->sh_type == SHT_PROGBITS &&
1283 (s->sh_flags & SHF_ALLOC)) {
1284 const char *p;
1285 int ch;
1287 /* check if section name can be expressed in C */
1288 p = s->name;
1289 for(;;) {
1290 ch = *p;
1291 if (!ch)
1292 break;
1293 if (!isid(ch) && !isnum(ch))
1294 goto next_sec;
1295 p++;
1297 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1298 add_elf_sym(symtab_section,
1299 0, 0,
1300 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1301 s->sh_num, buf);
1302 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1303 add_elf_sym(symtab_section,
1304 s->data_offset, 0,
1305 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1306 s->sh_num, buf);
1308 next_sec: ;
1312 static void tcc_output_binary(TCCState *s1, FILE *f,
1313 const int *section_order)
1315 Section *s;
1316 int i, offset, size;
1318 offset = 0;
1319 for(i=1;i<s1->nb_sections;i++) {
1320 s = s1->sections[section_order[i]];
1321 if (s->sh_type != SHT_NOBITS &&
1322 (s->sh_flags & SHF_ALLOC)) {
1323 while (offset < s->sh_offset) {
1324 fputc(0, f);
1325 offset++;
1327 size = s->sh_size;
1328 fwrite(s->data, 1, size, f);
1329 offset += size;
1334 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1335 #define HAVE_PHDR 1
1336 #define EXTRA_RELITEMS 14
1338 /* move the relocation value from .dynsym to .got */
1339 void patch_dynsym_undef(TCCState *s1, Section *s)
1341 uint32_t *gotd = (void *)s1->got->data;
1342 ElfW(Sym) *sym, *sym_end;
1344 gotd += 3; // dummy entries in .got
1345 /* relocate symbols in .dynsym */
1346 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1347 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1348 if (sym->st_shndx == SHN_UNDEF) {
1349 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1350 sym->st_value = 0;
1354 #else
1355 #define HAVE_PHDR 0
1356 #define EXTRA_RELITEMS 9
1358 /* zero plt offsets of weak symbols in .dynsym */
1359 void patch_dynsym_undef(TCCState *s1, Section *s)
1361 ElfW(Sym) *sym, *sym_end;
1363 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1364 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++)
1365 if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
1366 sym->st_value = 0;
1368 #endif
1370 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1372 int sym_index = ELFW(R_SYM) (rel->r_info);
1373 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1374 unsigned long offset;
1376 if (sym_index >= s1->nb_got_offsets)
1377 return;
1378 offset = s1->got_offsets[sym_index];
1379 section_reserve(s1->got, offset + PTR_SIZE);
1380 #ifdef TCC_TARGET_X86_64
1381 /* only works for x86-64 */
1382 put32(s1->got->data + offset + 4, sym->st_value >> 32);
1383 #endif
1384 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1387 ST_FUNC void fill_got(TCCState *s1)
1389 Section *s;
1390 ElfW_Rel *rel, *rel_end;
1391 int i;
1393 for(i = 1; i < s1->nb_sections; i++) {
1394 s = s1->sections[i];
1395 if (s->sh_type != SHT_RELX)
1396 continue;
1397 /* no need to handle got relocations */
1398 if (s->link != symtab_section)
1399 continue;
1400 rel_end = (ElfW_Rel *) (s->data + s->data_offset);
1401 for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
1402 switch (ELFW(R_TYPE) (rel->r_info)) {
1403 case R_X86_64_GOT32:
1404 case R_X86_64_GOTPCREL:
1405 case R_X86_64_PLT32:
1406 fill_got_entry(s1, rel);
1407 break;
1414 /* output an ELF file */
1415 /* XXX: suppress unneeded sections */
1416 static int elf_output_file(TCCState *s1, const char *filename)
1418 ElfW(Ehdr) ehdr;
1419 FILE *f;
1420 int fd, mode, ret;
1421 int *section_order;
1422 int shnum, i, phnum, file_offset, offset, size, j, sh_order_index, k;
1423 long long tmp;
1424 uplong 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 uplong rel_addr, rel_size;
1433 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1434 uplong bss_addr, bss_size;
1435 #endif
1437 file_type = s1->output_type;
1438 s1->nb_errors = 0;
1440 if (file_type != TCC_OUTPUT_OBJ) {
1441 tcc_add_runtime(s1);
1444 phdr = NULL;
1445 section_order = NULL;
1446 interp = NULL;
1447 dynamic = NULL;
1448 dynstr = NULL; /* avoid warning */
1449 saved_dynamic_data_offset = 0; /* avoid warning */
1451 if (file_type != TCC_OUTPUT_OBJ) {
1452 relocate_common_syms();
1454 tcc_add_linker_symbols(s1);
1456 if (!s1->static_link) {
1457 const char *name;
1458 int sym_index, index;
1459 ElfW(Sym) *esym, *sym_end;
1461 if (file_type == TCC_OUTPUT_EXE) {
1462 char *ptr;
1463 /* allow override the dynamic loader */
1464 const char *elfint = getenv("LD_SO");
1465 if (elfint == NULL)
1466 elfint = CONFIG_TCC_ELFINTERP;
1467 /* add interpreter section only if executable */
1468 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1469 interp->sh_addralign = 1;
1470 ptr = section_ptr_add(interp, 1+strlen(elfint));
1471 strcpy(ptr, elfint);
1474 /* add dynamic symbol table */
1475 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1476 ".dynstr",
1477 ".hash", SHF_ALLOC);
1478 dynstr = s1->dynsym->link;
1480 /* add dynamic section */
1481 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1482 SHF_ALLOC | SHF_WRITE);
1483 dynamic->link = dynstr;
1484 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1486 /* add PLT */
1487 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1488 SHF_ALLOC | SHF_EXECINSTR);
1489 s1->plt->sh_entsize = 4;
1491 build_got(s1);
1493 /* scan for undefined symbols and see if they are in the
1494 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1495 is found, then we add it in the PLT. If a symbol
1496 STT_OBJECT is found, we add it in the .bss section with
1497 a suitable relocation */
1498 sym_end = (ElfW(Sym) *)(symtab_section->data +
1499 symtab_section->data_offset);
1500 if (file_type == TCC_OUTPUT_EXE) {
1501 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1502 sym < sym_end;
1503 sym++) {
1504 if (sym->st_shndx == SHN_UNDEF) {
1505 name = symtab_section->link->data + sym->st_name;
1506 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1507 if (sym_index) {
1508 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1509 type = ELFW(ST_TYPE)(esym->st_info);
1510 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1511 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1512 ELFW(ST_INFO)(STB_GLOBAL,type),
1513 sym - (ElfW(Sym) *)symtab_section->data);
1514 } else if (type == STT_OBJECT) {
1515 unsigned long offset;
1516 ElfW(Sym) *dynsym, *dynsym_end;
1517 offset = bss_section->data_offset;
1518 /* XXX: which alignment ? */
1519 offset = (offset + 16 - 1) & -16;
1520 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1521 esym->st_info, 0,
1522 bss_section->sh_num, name);
1523 // Ensure R_COPY works for weak symbol aliases
1524 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1525 dynsym_end = (ElfW(Sym) *)
1526 (s1->dynsymtab_section->data +
1527 s1->dynsymtab_section->data_offset);
1528 for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1529 dynsym < dynsym_end; dynsym++) {
1530 if ((dynsym->st_value == esym->st_value)
1531 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1532 char *dynname;
1533 dynname = s1->dynsymtab_section->link->data
1534 + dynsym->st_name;
1535 put_elf_sym(s1->dynsym, offset,
1536 dynsym->st_size,
1537 dynsym->st_info, 0,
1538 bss_section->sh_num,
1539 dynname);
1540 break;
1544 put_elf_reloc(s1->dynsym, bss_section,
1545 offset, R_COPY, index);
1546 offset += esym->st_size;
1547 bss_section->data_offset = offset;
1549 } else {
1550 /* STB_WEAK undefined symbols are accepted */
1551 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1552 it */
1553 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1554 !strcmp(name, "_fp_hw")) {
1555 } else {
1556 tcc_error_noabort("undefined symbol '%s'", name);
1559 } else if (s1->rdynamic &&
1560 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1561 /* if -rdynamic option, then export all non
1562 local symbols */
1563 name = symtab_section->link->data + sym->st_name;
1564 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1565 sym->st_info, 0,
1566 sym->st_shndx, name);
1570 if (s1->nb_errors)
1571 goto fail;
1573 /* now look at unresolved dynamic symbols and export
1574 corresponding symbol */
1575 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1576 s1->dynsymtab_section->data_offset);
1577 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1578 esym < sym_end;
1579 esym++) {
1580 if (esym->st_shndx == SHN_UNDEF) {
1581 name = s1->dynsymtab_section->link->data + esym->st_name;
1582 sym_index = find_elf_sym(symtab_section, name);
1583 if (sym_index) {
1584 /* XXX: avoid adding a symbol if already
1585 present because of -rdynamic ? */
1586 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1587 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1588 sym->st_info, 0,
1589 sym->st_shndx, name);
1590 } else {
1591 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1592 /* weak symbols can stay undefined */
1593 } else {
1594 tcc_warning("undefined dynamic symbol '%s'", name);
1599 } else {
1600 int nb_syms;
1601 /* shared library case : we simply export all the global symbols */
1602 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1603 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1604 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1605 sym < sym_end;
1606 sym++) {
1607 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1608 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1609 if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
1610 ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
1611 && sym->st_shndx == SHN_UNDEF) {
1612 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1613 sym->st_info,
1614 sym - (ElfW(Sym) *)symtab_section->data);
1616 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1617 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1618 sym->st_info,
1619 sym - (ElfW(Sym) *)symtab_section->data);
1621 else
1622 #endif
1624 name = symtab_section->link->data + sym->st_name;
1625 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1626 sym->st_info, 0,
1627 sym->st_shndx, name);
1628 s1->symtab_to_dynsym[sym -
1629 (ElfW(Sym) *)symtab_section->data] =
1630 index;
1636 build_got_entries(s1);
1638 /* add a list of needed dlls */
1639 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1640 DLLReference *dllref = s1->loaded_dlls[i];
1641 if (dllref->level == 0)
1642 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1645 if (s1->rpath)
1646 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1648 /* XXX: currently, since we do not handle PIC code, we
1649 must relocate the readonly segments */
1650 if (file_type == TCC_OUTPUT_DLL) {
1651 if (s1->soname)
1652 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1653 put_dt(dynamic, DT_TEXTREL, 0);
1656 if (s1->symbolic)
1657 put_dt(dynamic, DT_SYMBOLIC, 0);
1659 /* add necessary space for other entries */
1660 saved_dynamic_data_offset = dynamic->data_offset;
1661 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1662 } else {
1663 /* still need to build got entries in case of static link */
1664 build_got_entries(s1);
1668 memset(&ehdr, 0, sizeof(ehdr));
1670 /* we add a section for symbols */
1671 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1672 put_elf_str(strsec, "");
1674 /* compute number of sections */
1675 shnum = s1->nb_sections;
1677 /* this array is used to reorder sections in the output file */
1678 section_order = tcc_malloc(sizeof(int) * shnum);
1679 section_order[0] = 0;
1680 sh_order_index = 1;
1682 /* compute number of program headers */
1683 switch(file_type) {
1684 default:
1685 case TCC_OUTPUT_OBJ:
1686 phnum = 0;
1687 break;
1688 case TCC_OUTPUT_EXE:
1689 if (!s1->static_link)
1690 phnum = 4 + HAVE_PHDR;
1691 else
1692 phnum = 2;
1693 break;
1694 case TCC_OUTPUT_DLL:
1695 phnum = 3;
1696 break;
1699 /* allocate strings for section names and decide if an unallocated
1700 section should be output */
1701 /* NOTE: the strsec section comes last, so its size is also
1702 correct ! */
1703 for(i = 1; i < s1->nb_sections; i++) {
1704 s = s1->sections[i];
1705 s->sh_name = put_elf_str(strsec, s->name);
1706 #if 0 //gr
1707 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1708 s->sh_flags,
1709 s->sh_type,
1710 s->sh_info,
1711 s->name,
1712 s->reloc ? s->reloc->name : "n"
1714 #endif
1715 /* when generating a DLL, we include relocations but we may
1716 patch them */
1717 if (file_type == TCC_OUTPUT_DLL &&
1718 s->sh_type == SHT_RELX &&
1719 !(s->sh_flags & SHF_ALLOC)) {
1720 /* //gr: avoid bogus relocs for empty (debug) sections */
1721 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1722 prepare_dynamic_rel(s1, s);
1723 else if (s1->do_debug)
1724 s->sh_size = s->data_offset;
1725 } else if (s1->do_debug ||
1726 file_type == TCC_OUTPUT_OBJ ||
1727 (s->sh_flags & SHF_ALLOC) ||
1728 i == (s1->nb_sections - 1)) {
1729 /* we output all sections if debug or object file */
1730 s->sh_size = s->data_offset;
1734 /* allocate program segment headers */
1735 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1737 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1738 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1739 } else {
1740 file_offset = 0;
1742 if (phnum > 0) {
1743 /* compute section to program header mapping */
1744 if (s1->has_text_addr) {
1745 int a_offset, p_offset;
1746 addr = s1->text_addr;
1747 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1748 ELF_PAGE_SIZE */
1749 a_offset = (int) (addr & (s1->section_align - 1));
1750 p_offset = file_offset & (s1->section_align - 1);
1751 if (a_offset < p_offset)
1752 a_offset += s1->section_align;
1753 file_offset += (a_offset - p_offset);
1754 } else {
1755 if (file_type == TCC_OUTPUT_DLL)
1756 addr = 0;
1757 else
1758 addr = ELF_START_ADDR;
1759 /* compute address after headers */
1760 addr += (file_offset & (s1->section_align - 1));
1763 /* dynamic relocation table information, for .dynamic section */
1764 rel_size = 0;
1765 rel_addr = 0;
1767 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1768 bss_addr = bss_size = 0;
1769 #endif
1770 /* leave one program header for the program interpreter */
1771 ph = &phdr[0];
1772 if (interp)
1773 ph += 1 + HAVE_PHDR;
1775 for(j = 0; j < 2; j++) {
1776 ph->p_type = PT_LOAD;
1777 if (j == 0)
1778 ph->p_flags = PF_R | PF_X;
1779 else
1780 ph->p_flags = PF_R | PF_W;
1781 ph->p_align = s1->section_align;
1783 /* we do the following ordering: interp, symbol tables,
1784 relocations, progbits, nobits */
1785 /* XXX: do faster and simpler sorting */
1786 for(k = 0; k < 5; k++) {
1787 for(i = 1; i < s1->nb_sections; i++) {
1788 s = s1->sections[i];
1789 /* compute if section should be included */
1790 if (j == 0) {
1791 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1792 SHF_ALLOC)
1793 continue;
1794 } else {
1795 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1796 (SHF_ALLOC | SHF_WRITE))
1797 continue;
1799 if (s == interp) {
1800 if (k != 0)
1801 continue;
1802 } else if (s->sh_type == SHT_DYNSYM ||
1803 s->sh_type == SHT_STRTAB ||
1804 s->sh_type == SHT_HASH) {
1805 if (k != 1)
1806 continue;
1807 } else if (s->sh_type == SHT_RELX) {
1808 if (k != 2)
1809 continue;
1810 } else if (s->sh_type == SHT_NOBITS) {
1811 if (k != 4)
1812 continue;
1813 } else {
1814 if (k != 3)
1815 continue;
1817 section_order[sh_order_index++] = i;
1819 /* section matches: we align it and add its size */
1820 tmp = addr;
1821 addr = (addr + s->sh_addralign - 1) &
1822 ~(s->sh_addralign - 1);
1823 file_offset += (int) ( addr - tmp );
1824 s->sh_offset = file_offset;
1825 s->sh_addr = addr;
1827 /* update program header infos */
1828 if (ph->p_offset == 0) {
1829 ph->p_offset = file_offset;
1830 ph->p_vaddr = addr;
1831 ph->p_paddr = ph->p_vaddr;
1833 /* update dynamic relocation infos */
1834 if (s->sh_type == SHT_RELX) {
1835 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1836 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1837 rel_addr = addr;
1838 rel_size += s->sh_size; // XXX only first rel.
1840 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1841 bss_addr = addr;
1842 bss_size = s->sh_size; // XXX only first rel.
1844 #else
1845 if (rel_size == 0)
1846 rel_addr = addr;
1847 rel_size += s->sh_size;
1848 #endif
1850 addr += s->sh_size;
1851 if (s->sh_type != SHT_NOBITS)
1852 file_offset += s->sh_size;
1855 ph->p_filesz = file_offset - ph->p_offset;
1856 ph->p_memsz = addr - ph->p_vaddr;
1857 ph++;
1858 if (j == 0) {
1859 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1860 /* if in the middle of a page, we duplicate the page in
1861 memory so that one copy is RX and the other is RW */
1862 if ((addr & (s1->section_align - 1)) != 0)
1863 addr += s1->section_align;
1864 } else {
1865 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1866 file_offset = (file_offset + s1->section_align - 1) &
1867 ~(s1->section_align - 1);
1872 /* if interpreter, then add corresponing program header */
1873 if (interp) {
1874 ph = &phdr[0];
1876 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1878 int len = phnum * sizeof(ElfW(Phdr));
1880 ph->p_type = PT_PHDR;
1881 ph->p_offset = sizeof(ElfW(Ehdr));
1882 ph->p_vaddr = interp->sh_addr - len;
1883 ph->p_paddr = ph->p_vaddr;
1884 ph->p_filesz = ph->p_memsz = len;
1885 ph->p_flags = PF_R | PF_X;
1886 ph->p_align = 4; // interp->sh_addralign;
1887 ph++;
1889 #endif
1891 ph->p_type = PT_INTERP;
1892 ph->p_offset = interp->sh_offset;
1893 ph->p_vaddr = interp->sh_addr;
1894 ph->p_paddr = ph->p_vaddr;
1895 ph->p_filesz = interp->sh_size;
1896 ph->p_memsz = interp->sh_size;
1897 ph->p_flags = PF_R;
1898 ph->p_align = interp->sh_addralign;
1901 /* if dynamic section, then add corresponing program header */
1902 if (dynamic) {
1903 ElfW(Sym) *sym_end;
1905 ph = &phdr[phnum - 1];
1907 ph->p_type = PT_DYNAMIC;
1908 ph->p_offset = dynamic->sh_offset;
1909 ph->p_vaddr = dynamic->sh_addr;
1910 ph->p_paddr = ph->p_vaddr;
1911 ph->p_filesz = dynamic->sh_size;
1912 ph->p_memsz = dynamic->sh_size;
1913 ph->p_flags = PF_R | PF_W;
1914 ph->p_align = dynamic->sh_addralign;
1916 /* put GOT dynamic section address */
1917 put32(s1->got->data, dynamic->sh_addr);
1919 /* relocate the PLT */
1920 if (file_type == TCC_OUTPUT_EXE
1921 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1922 || file_type == TCC_OUTPUT_DLL
1923 #endif
1925 uint8_t *p, *p_end;
1927 p = s1->plt->data;
1928 p_end = p + s1->plt->data_offset;
1929 if (p < p_end) {
1930 #if defined(TCC_TARGET_I386)
1931 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1932 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1933 p += 16;
1934 while (p < p_end) {
1935 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1936 p += 16;
1938 #elif defined(TCC_TARGET_X86_64)
1939 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1940 put32(p + 2, get32(p + 2) + x);
1941 put32(p + 8, get32(p + 8) + x - 6);
1942 p += 16;
1943 while (p < p_end) {
1944 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1945 p += 16;
1947 #elif defined(TCC_TARGET_ARM)
1948 int x;
1949 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1950 p +=16;
1951 while (p < p_end) {
1952 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1953 p += 16;
1955 #elif defined(TCC_TARGET_C67)
1956 /* XXX: TODO */
1957 #else
1958 #error unsupported CPU
1959 #endif
1963 /* relocate symbols in .dynsym */
1964 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
1965 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
1966 sym < sym_end;
1967 sym++) {
1968 if (sym->st_shndx == SHN_UNDEF) {
1969 /* relocate to the PLT if the symbol corresponds
1970 to a PLT entry */
1971 if (sym->st_value)
1972 sym->st_value += s1->plt->sh_addr;
1973 } else if (sym->st_shndx < SHN_LORESERVE) {
1974 /* do symbol relocation */
1975 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
1979 /* put dynamic section entries */
1980 dynamic->data_offset = saved_dynamic_data_offset;
1981 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
1982 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
1983 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
1984 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
1985 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
1986 #ifdef TCC_TARGET_X86_64
1987 put_dt(dynamic, DT_RELA, rel_addr);
1988 put_dt(dynamic, DT_RELASZ, rel_size);
1989 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
1990 #else
1991 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1992 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
1993 put_dt(dynamic, DT_PLTRELSZ, rel_size);
1994 put_dt(dynamic, DT_JMPREL, rel_addr);
1995 put_dt(dynamic, DT_PLTREL, DT_REL);
1996 put_dt(dynamic, DT_REL, bss_addr);
1997 put_dt(dynamic, DT_RELSZ, bss_size);
1998 #else
1999 put_dt(dynamic, DT_REL, rel_addr);
2000 put_dt(dynamic, DT_RELSZ, rel_size);
2001 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2002 #endif
2003 #endif
2004 if (s1->do_debug)
2005 put_dt(dynamic, DT_DEBUG, 0);
2006 put_dt(dynamic, DT_NULL, 0);
2009 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2010 ehdr.e_phnum = phnum;
2011 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2014 /* all other sections come after */
2015 for(i = 1; i < s1->nb_sections; i++) {
2016 s = s1->sections[i];
2017 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2018 continue;
2019 section_order[sh_order_index++] = i;
2021 file_offset = (file_offset + s->sh_addralign - 1) &
2022 ~(s->sh_addralign - 1);
2023 s->sh_offset = file_offset;
2024 if (s->sh_type != SHT_NOBITS)
2025 file_offset += s->sh_size;
2028 /* if building executable or DLL, then relocate each section
2029 except the GOT which is already relocated */
2030 if (file_type != TCC_OUTPUT_OBJ) {
2031 relocate_syms(s1, 0);
2033 if (s1->nb_errors != 0) {
2034 fail:
2035 ret = -1;
2036 goto the_end;
2039 /* relocate sections */
2040 /* XXX: ignore sections with allocated relocations ? */
2041 for(i = 1; i < s1->nb_sections; i++) {
2042 s = s1->sections[i];
2043 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
2044 relocate_section(s1, s);
2047 /* relocate relocation entries if the relocation tables are
2048 allocated in the executable */
2049 for(i = 1; i < s1->nb_sections; i++) {
2050 s = s1->sections[i];
2051 if ((s->sh_flags & SHF_ALLOC) &&
2052 s->sh_type == SHT_RELX) {
2053 relocate_rel(s1, s);
2057 /* get entry point address */
2058 if (file_type == TCC_OUTPUT_EXE)
2059 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
2060 else
2061 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2063 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2064 fill_got(s1);
2066 /* write elf file */
2067 if (file_type == TCC_OUTPUT_OBJ)
2068 mode = 0666;
2069 else
2070 mode = 0777;
2071 unlink(filename);
2072 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2073 if (fd < 0) {
2074 tcc_error_noabort("could not write '%s'", filename);
2075 goto fail;
2077 f = fdopen(fd, "wb");
2078 if (s1->verbose)
2079 printf("<- %s\n", filename);
2081 #ifdef TCC_TARGET_COFF
2082 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2083 tcc_output_coff(s1, f);
2084 } else
2085 #endif
2086 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2087 sort_syms(s1, symtab_section);
2089 /* align to 4 */
2090 file_offset = (file_offset + 3) & -4;
2092 /* fill header */
2093 ehdr.e_ident[0] = ELFMAG0;
2094 ehdr.e_ident[1] = ELFMAG1;
2095 ehdr.e_ident[2] = ELFMAG2;
2096 ehdr.e_ident[3] = ELFMAG3;
2097 ehdr.e_ident[4] = ELFCLASSW;
2098 ehdr.e_ident[5] = ELFDATA2LSB;
2099 ehdr.e_ident[6] = EV_CURRENT;
2100 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2101 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2102 #endif
2103 #ifdef TCC_TARGET_ARM
2104 #ifdef TCC_ARM_EABI
2105 ehdr.e_ident[EI_OSABI] = 0;
2106 ehdr.e_flags = 4 << 24;
2107 #else
2108 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2109 #endif
2110 #endif
2111 switch(file_type) {
2112 default:
2113 case TCC_OUTPUT_EXE:
2114 ehdr.e_type = ET_EXEC;
2115 break;
2116 case TCC_OUTPUT_DLL:
2117 ehdr.e_type = ET_DYN;
2118 break;
2119 case TCC_OUTPUT_OBJ:
2120 ehdr.e_type = ET_REL;
2121 break;
2123 ehdr.e_machine = EM_TCC_TARGET;
2124 ehdr.e_version = EV_CURRENT;
2125 ehdr.e_shoff = file_offset;
2126 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2127 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2128 ehdr.e_shnum = shnum;
2129 ehdr.e_shstrndx = shnum - 1;
2131 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2132 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2133 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2135 for(i=1;i<s1->nb_sections;i++) {
2136 s = s1->sections[section_order[i]];
2137 if (s->sh_type != SHT_NOBITS) {
2138 if (s->sh_type == SHT_DYNSYM)
2139 patch_dynsym_undef(s1, s);
2140 while (offset < s->sh_offset) {
2141 fputc(0, f);
2142 offset++;
2144 size = s->sh_size;
2145 fwrite(s->data, 1, size, f);
2146 offset += size;
2150 /* output section headers */
2151 while (offset < ehdr.e_shoff) {
2152 fputc(0, f);
2153 offset++;
2156 for(i=0;i<s1->nb_sections;i++) {
2157 sh = &shdr;
2158 memset(sh, 0, sizeof(ElfW(Shdr)));
2159 s = s1->sections[i];
2160 if (s) {
2161 sh->sh_name = s->sh_name;
2162 sh->sh_type = s->sh_type;
2163 sh->sh_flags = s->sh_flags;
2164 sh->sh_entsize = s->sh_entsize;
2165 sh->sh_info = s->sh_info;
2166 if (s->link)
2167 sh->sh_link = s->link->sh_num;
2168 sh->sh_addralign = s->sh_addralign;
2169 sh->sh_addr = s->sh_addr;
2170 sh->sh_offset = s->sh_offset;
2171 sh->sh_size = s->sh_size;
2173 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2175 } else {
2176 tcc_output_binary(s1, f, section_order);
2178 fclose(f);
2180 ret = 0;
2181 the_end:
2182 tcc_free(s1->symtab_to_dynsym);
2183 tcc_free(section_order);
2184 tcc_free(phdr);
2185 tcc_free(s1->got_offsets);
2186 return ret;
2189 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2191 int ret;
2192 #ifdef TCC_TARGET_PE
2193 if (s->output_type != TCC_OUTPUT_OBJ) {
2194 ret = pe_output_file(s, filename);
2195 } else
2196 #endif
2198 ret = elf_output_file(s, filename);
2200 return ret;
2203 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2205 void *data;
2207 data = tcc_malloc(size);
2208 lseek(fd, file_offset, SEEK_SET);
2209 read(fd, data, size);
2210 return data;
2213 typedef struct SectionMergeInfo {
2214 Section *s; /* corresponding existing section */
2215 unsigned long offset; /* offset of the new section in the existing section */
2216 uint8_t new_section; /* true if section 's' was added */
2217 uint8_t link_once; /* true if link once section */
2218 } SectionMergeInfo;
2220 /* load an object file and merge it with current files */
2221 /* XXX: handle correctly stab (debug) info */
2222 ST_FUNC int tcc_load_object_file(TCCState *s1,
2223 int fd, unsigned long file_offset)
2225 ElfW(Ehdr) ehdr;
2226 ElfW(Shdr) *shdr, *sh;
2227 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2228 unsigned char *strsec, *strtab;
2229 int *old_to_new_syms;
2230 char *sh_name, *name;
2231 SectionMergeInfo *sm_table, *sm;
2232 ElfW(Sym) *sym, *symtab;
2233 ElfW_Rel *rel, *rel_end;
2234 Section *s;
2236 int stab_index;
2237 int stabstr_index;
2239 stab_index = stabstr_index = 0;
2241 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2242 goto fail1;
2243 if (ehdr.e_ident[0] != ELFMAG0 ||
2244 ehdr.e_ident[1] != ELFMAG1 ||
2245 ehdr.e_ident[2] != ELFMAG2 ||
2246 ehdr.e_ident[3] != ELFMAG3)
2247 goto fail1;
2248 /* test if object file */
2249 if (ehdr.e_type != ET_REL)
2250 goto fail1;
2251 /* test CPU specific stuff */
2252 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2253 ehdr.e_machine != EM_TCC_TARGET) {
2254 fail1:
2255 tcc_error_noabort("invalid object file");
2256 return -1;
2258 /* read sections */
2259 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2260 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2261 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2263 /* load section names */
2264 sh = &shdr[ehdr.e_shstrndx];
2265 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2267 /* load symtab and strtab */
2268 old_to_new_syms = NULL;
2269 symtab = NULL;
2270 strtab = NULL;
2271 nb_syms = 0;
2272 for(i = 1; i < ehdr.e_shnum; i++) {
2273 sh = &shdr[i];
2274 if (sh->sh_type == SHT_SYMTAB) {
2275 if (symtab) {
2276 tcc_error_noabort("object must contain only one symtab");
2277 fail:
2278 ret = -1;
2279 goto the_end;
2281 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2282 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2283 sm_table[i].s = symtab_section;
2285 /* now load strtab */
2286 sh = &shdr[sh->sh_link];
2287 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2291 /* now examine each section and try to merge its content with the
2292 ones in memory */
2293 for(i = 1; i < ehdr.e_shnum; i++) {
2294 /* no need to examine section name strtab */
2295 if (i == ehdr.e_shstrndx)
2296 continue;
2297 sh = &shdr[i];
2298 sh_name = strsec + sh->sh_name;
2299 /* ignore sections types we do not handle */
2300 if (sh->sh_type != SHT_PROGBITS &&
2301 sh->sh_type != SHT_RELX &&
2302 #ifdef TCC_ARM_EABI
2303 sh->sh_type != SHT_ARM_EXIDX &&
2304 #endif
2305 sh->sh_type != SHT_NOBITS &&
2306 sh->sh_type != SHT_PREINIT_ARRAY &&
2307 sh->sh_type != SHT_INIT_ARRAY &&
2308 sh->sh_type != SHT_FINI_ARRAY &&
2309 strcmp(sh_name, ".stabstr")
2311 continue;
2312 if (sh->sh_addralign < 1)
2313 sh->sh_addralign = 1;
2314 /* find corresponding section, if any */
2315 for(j = 1; j < s1->nb_sections;j++) {
2316 s = s1->sections[j];
2317 if (!strcmp(s->name, sh_name)) {
2318 if (!strncmp(sh_name, ".gnu.linkonce",
2319 sizeof(".gnu.linkonce") - 1)) {
2320 /* if a 'linkonce' section is already present, we
2321 do not add it again. It is a little tricky as
2322 symbols can still be defined in
2323 it. */
2324 sm_table[i].link_once = 1;
2325 goto next;
2326 } else {
2327 goto found;
2331 /* not found: create new section */
2332 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2333 /* take as much info as possible from the section. sh_link and
2334 sh_info will be updated later */
2335 s->sh_addralign = sh->sh_addralign;
2336 s->sh_entsize = sh->sh_entsize;
2337 sm_table[i].new_section = 1;
2338 found:
2339 if (sh->sh_type != s->sh_type) {
2340 tcc_error_noabort("invalid section type");
2341 goto fail;
2344 /* align start of section */
2345 offset = s->data_offset;
2347 if (0 == strcmp(sh_name, ".stab")) {
2348 stab_index = i;
2349 goto no_align;
2351 if (0 == strcmp(sh_name, ".stabstr")) {
2352 stabstr_index = i;
2353 goto no_align;
2356 size = sh->sh_addralign - 1;
2357 offset = (offset + size) & ~size;
2358 if (sh->sh_addralign > s->sh_addralign)
2359 s->sh_addralign = sh->sh_addralign;
2360 s->data_offset = offset;
2361 no_align:
2362 sm_table[i].offset = offset;
2363 sm_table[i].s = s;
2364 /* concatenate sections */
2365 size = sh->sh_size;
2366 if (sh->sh_type != SHT_NOBITS) {
2367 unsigned char *ptr;
2368 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2369 ptr = section_ptr_add(s, size);
2370 read(fd, ptr, size);
2371 } else {
2372 s->data_offset += size;
2374 next: ;
2377 /* //gr relocate stab strings */
2378 if (stab_index && stabstr_index) {
2379 Stab_Sym *a, *b;
2380 unsigned o;
2381 s = sm_table[stab_index].s;
2382 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2383 b = (Stab_Sym *)(s->data + s->data_offset);
2384 o = sm_table[stabstr_index].offset;
2385 while (a < b)
2386 a->n_strx += o, a++;
2389 /* second short pass to update sh_link and sh_info fields of new
2390 sections */
2391 for(i = 1; i < ehdr.e_shnum; i++) {
2392 s = sm_table[i].s;
2393 if (!s || !sm_table[i].new_section)
2394 continue;
2395 sh = &shdr[i];
2396 if (sh->sh_link > 0)
2397 s->link = sm_table[sh->sh_link].s;
2398 if (sh->sh_type == SHT_RELX) {
2399 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2400 /* update backward link */
2401 s1->sections[s->sh_info]->reloc = s;
2404 sm = sm_table;
2406 /* resolve symbols */
2407 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2409 sym = symtab + 1;
2410 for(i = 1; i < nb_syms; i++, sym++) {
2411 if (sym->st_shndx != SHN_UNDEF &&
2412 sym->st_shndx < SHN_LORESERVE) {
2413 sm = &sm_table[sym->st_shndx];
2414 if (sm->link_once) {
2415 /* if a symbol is in a link once section, we use the
2416 already defined symbol. It is very important to get
2417 correct relocations */
2418 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2419 name = strtab + sym->st_name;
2420 sym_index = find_elf_sym(symtab_section, name);
2421 if (sym_index)
2422 old_to_new_syms[i] = sym_index;
2424 continue;
2426 /* if no corresponding section added, no need to add symbol */
2427 if (!sm->s)
2428 continue;
2429 /* convert section number */
2430 sym->st_shndx = sm->s->sh_num;
2431 /* offset value */
2432 sym->st_value += sm->offset;
2434 /* add symbol */
2435 name = strtab + sym->st_name;
2436 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2437 sym->st_info, sym->st_other,
2438 sym->st_shndx, name);
2439 old_to_new_syms[i] = sym_index;
2442 /* third pass to patch relocation entries */
2443 for(i = 1; i < ehdr.e_shnum; i++) {
2444 s = sm_table[i].s;
2445 if (!s)
2446 continue;
2447 sh = &shdr[i];
2448 offset = sm_table[i].offset;
2449 switch(s->sh_type) {
2450 case SHT_RELX:
2451 /* take relocation offset information */
2452 offseti = sm_table[sh->sh_info].offset;
2453 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2454 for(rel = (ElfW_Rel *)(s->data + offset);
2455 rel < rel_end;
2456 rel++) {
2457 int type;
2458 unsigned sym_index;
2459 /* convert symbol index */
2460 type = ELFW(R_TYPE)(rel->r_info);
2461 sym_index = ELFW(R_SYM)(rel->r_info);
2462 /* NOTE: only one symtab assumed */
2463 if (sym_index >= nb_syms)
2464 goto invalid_reloc;
2465 sym_index = old_to_new_syms[sym_index];
2466 /* ignore link_once in rel section. */
2467 if (!sym_index && !sm->link_once
2468 #ifdef TCC_TARGET_ARM
2469 && type != R_ARM_V4BX
2470 #endif
2472 invalid_reloc:
2473 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2474 i, strsec + sh->sh_name, rel->r_offset);
2475 goto fail;
2477 rel->r_info = ELFW(R_INFO)(sym_index, type);
2478 /* offset the relocation offset */
2479 rel->r_offset += offseti;
2481 break;
2482 default:
2483 break;
2487 ret = 0;
2488 the_end:
2489 tcc_free(symtab);
2490 tcc_free(strtab);
2491 tcc_free(old_to_new_syms);
2492 tcc_free(sm_table);
2493 tcc_free(strsec);
2494 tcc_free(shdr);
2495 return ret;
2498 typedef struct ArchiveHeader {
2499 char ar_name[16]; /* name of this member */
2500 char ar_date[12]; /* file mtime */
2501 char ar_uid[6]; /* owner uid; printed as decimal */
2502 char ar_gid[6]; /* owner gid; printed as decimal */
2503 char ar_mode[8]; /* file mode, printed as octal */
2504 char ar_size[10]; /* file size, printed as decimal */
2505 char ar_fmag[2]; /* should contain ARFMAG */
2506 } ArchiveHeader;
2508 static int get_be32(const uint8_t *b)
2510 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2513 /* load only the objects which resolve undefined symbols */
2514 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2516 int i, bound, nsyms, sym_index, off, ret;
2517 uint8_t *data;
2518 const char *ar_names, *p;
2519 const uint8_t *ar_index;
2520 ElfW(Sym) *sym;
2522 data = tcc_malloc(size);
2523 if (read(fd, data, size) != size)
2524 goto fail;
2525 nsyms = get_be32(data);
2526 ar_index = data + 4;
2527 ar_names = ar_index + nsyms * 4;
2529 do {
2530 bound = 0;
2531 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2532 sym_index = find_elf_sym(symtab_section, p);
2533 if(sym_index) {
2534 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2535 if(sym->st_shndx == SHN_UNDEF) {
2536 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2537 #if 0
2538 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2539 #endif
2540 ++bound;
2541 lseek(fd, off, SEEK_SET);
2542 if(tcc_load_object_file(s1, fd, off) < 0) {
2543 fail:
2544 ret = -1;
2545 goto the_end;
2550 } while(bound);
2551 ret = 0;
2552 the_end:
2553 tcc_free(data);
2554 return ret;
2557 /* load a '.a' file */
2558 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2560 ArchiveHeader hdr;
2561 char ar_size[11];
2562 char ar_name[17];
2563 char magic[8];
2564 int size, len, i;
2565 unsigned long file_offset;
2567 /* skip magic which was already checked */
2568 read(fd, magic, sizeof(magic));
2570 for(;;) {
2571 len = read(fd, &hdr, sizeof(hdr));
2572 if (len == 0)
2573 break;
2574 if (len != sizeof(hdr)) {
2575 tcc_error_noabort("invalid archive");
2576 return -1;
2578 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2579 ar_size[sizeof(hdr.ar_size)] = '\0';
2580 size = strtol(ar_size, NULL, 0);
2581 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2582 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2583 if (ar_name[i] != ' ')
2584 break;
2586 ar_name[i + 1] = '\0';
2587 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2588 file_offset = lseek(fd, 0, SEEK_CUR);
2589 /* align to even */
2590 size = (size + 1) & ~1;
2591 if (!strcmp(ar_name, "/")) {
2592 /* coff symbol table : we handle it */
2593 if(s1->alacarte_link)
2594 return tcc_load_alacarte(s1, fd, size);
2595 } else if (!strcmp(ar_name, "//") ||
2596 !strcmp(ar_name, "__.SYMDEF") ||
2597 !strcmp(ar_name, "__.SYMDEF/") ||
2598 !strcmp(ar_name, "ARFILENAMES/")) {
2599 /* skip symbol table or archive names */
2600 } else {
2601 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2602 return -1;
2604 lseek(fd, file_offset + size, SEEK_SET);
2606 return 0;
2609 #ifndef TCC_TARGET_PE
2610 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2611 is referenced by the user (so it should be added as DT_NEEDED in
2612 the generated ELF file) */
2613 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2615 ElfW(Ehdr) ehdr;
2616 ElfW(Shdr) *shdr, *sh, *sh1;
2617 int i, j, nb_syms, nb_dts, sym_bind, ret;
2618 ElfW(Sym) *sym, *dynsym;
2619 ElfW(Dyn) *dt, *dynamic;
2620 unsigned char *dynstr;
2621 const char *name, *soname;
2622 DLLReference *dllref;
2624 read(fd, &ehdr, sizeof(ehdr));
2626 /* test CPU specific stuff */
2627 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2628 ehdr.e_machine != EM_TCC_TARGET) {
2629 tcc_error_noabort("bad architecture");
2630 return -1;
2633 /* read sections */
2634 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2636 /* load dynamic section and dynamic symbols */
2637 nb_syms = 0;
2638 nb_dts = 0;
2639 dynamic = NULL;
2640 dynsym = NULL; /* avoid warning */
2641 dynstr = NULL; /* avoid warning */
2642 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2643 switch(sh->sh_type) {
2644 case SHT_DYNAMIC:
2645 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2646 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2647 break;
2648 case SHT_DYNSYM:
2649 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2650 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2651 sh1 = &shdr[sh->sh_link];
2652 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2653 break;
2654 default:
2655 break;
2659 /* compute the real library name */
2660 soname = tcc_basename(filename);
2662 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2663 if (dt->d_tag == DT_SONAME) {
2664 soname = dynstr + dt->d_un.d_val;
2668 /* if the dll is already loaded, do not load it */
2669 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2670 dllref = s1->loaded_dlls[i];
2671 if (!strcmp(soname, dllref->name)) {
2672 /* but update level if needed */
2673 if (level < dllref->level)
2674 dllref->level = level;
2675 ret = 0;
2676 goto the_end;
2680 // printf("loading dll '%s'\n", soname);
2682 /* add the dll and its level */
2683 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2684 dllref->level = level;
2685 strcpy(dllref->name, soname);
2686 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2688 /* add dynamic symbols in dynsym_section */
2689 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2690 sym_bind = ELFW(ST_BIND)(sym->st_info);
2691 if (sym_bind == STB_LOCAL)
2692 continue;
2693 name = dynstr + sym->st_name;
2694 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2695 sym->st_info, sym->st_other, sym->st_shndx, name);
2698 /* load all referenced DLLs */
2699 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2700 switch(dt->d_tag) {
2701 case DT_NEEDED:
2702 name = dynstr + dt->d_un.d_val;
2703 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2704 dllref = s1->loaded_dlls[j];
2705 if (!strcmp(name, dllref->name))
2706 goto already_loaded;
2708 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2709 tcc_error_noabort("referenced dll '%s' not found", name);
2710 ret = -1;
2711 goto the_end;
2713 already_loaded:
2714 break;
2717 ret = 0;
2718 the_end:
2719 tcc_free(dynstr);
2720 tcc_free(dynsym);
2721 tcc_free(dynamic);
2722 tcc_free(shdr);
2723 return ret;
2726 #define LD_TOK_NAME 256
2727 #define LD_TOK_EOF (-1)
2729 /* return next ld script token */
2730 static int ld_next(TCCState *s1, char *name, int name_size)
2732 int c;
2733 char *q;
2735 redo:
2736 switch(ch) {
2737 case ' ':
2738 case '\t':
2739 case '\f':
2740 case '\v':
2741 case '\r':
2742 case '\n':
2743 inp();
2744 goto redo;
2745 case '/':
2746 minp();
2747 if (ch == '*') {
2748 file->buf_ptr = parse_comment(file->buf_ptr);
2749 ch = file->buf_ptr[0];
2750 goto redo;
2751 } else {
2752 q = name;
2753 *q++ = '/';
2754 goto parse_name;
2756 break;
2757 /* case 'a' ... 'z': */
2758 case 'a':
2759 case 'b':
2760 case 'c':
2761 case 'd':
2762 case 'e':
2763 case 'f':
2764 case 'g':
2765 case 'h':
2766 case 'i':
2767 case 'j':
2768 case 'k':
2769 case 'l':
2770 case 'm':
2771 case 'n':
2772 case 'o':
2773 case 'p':
2774 case 'q':
2775 case 'r':
2776 case 's':
2777 case 't':
2778 case 'u':
2779 case 'v':
2780 case 'w':
2781 case 'x':
2782 case 'y':
2783 case 'z':
2784 /* case 'A' ... 'z': */
2785 case 'A':
2786 case 'B':
2787 case 'C':
2788 case 'D':
2789 case 'E':
2790 case 'F':
2791 case 'G':
2792 case 'H':
2793 case 'I':
2794 case 'J':
2795 case 'K':
2796 case 'L':
2797 case 'M':
2798 case 'N':
2799 case 'O':
2800 case 'P':
2801 case 'Q':
2802 case 'R':
2803 case 'S':
2804 case 'T':
2805 case 'U':
2806 case 'V':
2807 case 'W':
2808 case 'X':
2809 case 'Y':
2810 case 'Z':
2811 case '_':
2812 case '\\':
2813 case '.':
2814 case '$':
2815 case '~':
2816 q = name;
2817 parse_name:
2818 for(;;) {
2819 if (!((ch >= 'a' && ch <= 'z') ||
2820 (ch >= 'A' && ch <= 'Z') ||
2821 (ch >= '0' && ch <= '9') ||
2822 strchr("/.-_+=$:\\,~", ch)))
2823 break;
2824 if ((q - name) < name_size - 1) {
2825 *q++ = ch;
2827 minp();
2829 *q = '\0';
2830 c = LD_TOK_NAME;
2831 break;
2832 case CH_EOF:
2833 c = LD_TOK_EOF;
2834 break;
2835 default:
2836 c = ch;
2837 inp();
2838 break;
2840 #if 0
2841 printf("tok=%c %d\n", c, c);
2842 if (c == LD_TOK_NAME)
2843 printf(" name=%s\n", name);
2844 #endif
2845 return c;
2849 * Extract the file name from the library name
2851 * /!\ No test on filename capacity, be careful
2853 static void libname_to_filename(TCCState *s1, const char libname[], char filename[])
2855 if (!s1->static_link) {
2856 sprintf(filename, "lib%s.so", libname);
2857 } else {
2858 sprintf(filename, "lib%s.a", libname);
2862 static int ld_add_file(TCCState *s1, const char filename[])
2864 int ret;
2866 ret = tcc_add_file_internal(s1, filename, 0);
2867 if (ret)
2868 ret = tcc_add_dll(s1, filename, 0);
2869 return ret;
2872 static inline int new_undef_syms(void)
2874 int ret = 0;
2875 ret = new_undef_sym;
2876 new_undef_sym = 0;
2877 return ret;
2880 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
2882 char filename[1024], libname[1024];
2883 int t, group, nblibs = 0, ret = 0;
2884 char **libs = NULL;
2886 group = !strcmp(cmd, "GROUP");
2887 if (!as_needed)
2888 new_undef_syms();
2889 t = ld_next(s1, filename, sizeof(filename));
2890 if (t != '(')
2891 expect("(");
2892 t = ld_next(s1, filename, sizeof(filename));
2893 for(;;) {
2894 libname[0] = '\0';
2895 if (t == LD_TOK_EOF) {
2896 tcc_error_noabort("unexpected end of file");
2897 ret = -1;
2898 goto lib_parse_error;
2899 } else if (t == ')') {
2900 break;
2901 } else if (t == '-') {
2902 t = ld_next(s1, filename, sizeof(filename));
2903 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
2904 tcc_error_noabort("library name expected");
2905 ret = -1;
2906 goto lib_parse_error;
2908 strcpy(libname, &filename[1]);
2909 libname_to_filename(s1, libname, filename);
2910 } else if (t != LD_TOK_NAME) {
2911 tcc_error_noabort("filename expected");
2912 ret = -1;
2913 goto lib_parse_error;
2915 if (!strcmp(filename, "AS_NEEDED")) {
2916 ret = ld_add_file_list(s1, cmd, 1);
2917 if (ret)
2918 goto lib_parse_error;
2919 } else {
2920 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2921 if (!as_needed) {
2922 ret = ld_add_file(s1, filename);
2923 if (ret)
2924 goto lib_parse_error;
2925 if (group) {
2926 /* Add the filename *and* the libname to avoid future conversions */
2927 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
2928 if (libname[0] != '\0')
2929 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
2933 t = ld_next(s1, filename, sizeof(filename));
2934 if (t == ',') {
2935 t = ld_next(s1, filename, sizeof(filename));
2938 if (group && !as_needed) {
2939 while (new_undef_syms()) {
2940 int i;
2942 for (i = 0; i < nblibs; i ++)
2943 ld_add_file(s1, libs[i]);
2946 lib_parse_error:
2947 dynarray_reset(&libs, &nblibs);
2948 return ret;
2951 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
2952 files */
2953 ST_FUNC int tcc_load_ldscript(TCCState *s1)
2955 char cmd[64];
2956 char filename[1024];
2957 int t, ret;
2959 ch = file->buf_ptr[0];
2960 ch = handle_eob();
2961 for(;;) {
2962 t = ld_next(s1, cmd, sizeof(cmd));
2963 if (t == LD_TOK_EOF)
2964 return 0;
2965 else if (t != LD_TOK_NAME)
2966 return -1;
2967 if (!strcmp(cmd, "INPUT") ||
2968 !strcmp(cmd, "GROUP")) {
2969 ret = ld_add_file_list(s1, cmd, 0);
2970 if (ret)
2971 return ret;
2972 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
2973 !strcmp(cmd, "TARGET")) {
2974 /* ignore some commands */
2975 t = ld_next(s1, cmd, sizeof(cmd));
2976 if (t != '(')
2977 expect("(");
2978 for(;;) {
2979 t = ld_next(s1, filename, sizeof(filename));
2980 if (t == LD_TOK_EOF) {
2981 tcc_error_noabort("unexpected end of file");
2982 return -1;
2983 } else if (t == ')') {
2984 break;
2987 } else {
2988 return -1;
2991 return 0;
2993 #endif /* ndef TCC_TARGET_PE */