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