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