Move asm label functions from tccasm.c to tccgen.c
[tinycc/miki.git] / tccelf.c
blobc93955b504bec7d1eef380105a27ebb39d81db1c
1 /*
2 * ELF file handling for TCC
3 *
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "tcc.h"
23 #ifdef TCC_TARGET_X86_64
24 #define ElfW_Rel ElfW(Rela)
25 #define SHT_RELX SHT_RELA
26 #define REL_SECTION_FMT ".rela%s"
27 /* x86-64 requires PLT for DLLs */
28 #define TCC_OUTPUT_DLL_WITH_PLT
29 #else
30 #define ElfW_Rel ElfW(Rel)
31 #define SHT_RELX SHT_REL
32 #define REL_SECTION_FMT ".rel%s"
33 #endif
35 static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */
37 /* XXX: DLL with PLT would only work with x86-64 for now */
38 //#define TCC_OUTPUT_DLL_WITH_PLT
40 ST_FUNC int put_elf_str(Section *s, const char *sym)
42 int offset, len;
43 char *ptr;
45 len = strlen(sym) + 1;
46 offset = s->data_offset;
47 ptr = section_ptr_add(s, len);
48 memcpy(ptr, sym, len);
49 return offset;
52 /* elf symbol hashing function */
53 static unsigned long elf_hash(const unsigned char *name)
55 unsigned long h = 0, g;
57 while (*name) {
58 h = (h << 4) + *name++;
59 g = h & 0xf0000000;
60 if (g)
61 h ^= g >> 24;
62 h &= ~g;
64 return h;
67 /* rebuild hash table of section s */
68 /* NOTE: we do factorize the hash table code to go faster */
69 static void rebuild_hash(Section *s, unsigned int nb_buckets)
71 ElfW(Sym) *sym;
72 int *ptr, *hash, nb_syms, sym_index, h;
73 char *strtab;
75 strtab = s->link->data;
76 nb_syms = s->data_offset / sizeof(ElfW(Sym));
78 s->hash->data_offset = 0;
79 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
80 ptr[0] = nb_buckets;
81 ptr[1] = nb_syms;
82 ptr += 2;
83 hash = ptr;
84 memset(hash, 0, (nb_buckets + 1) * sizeof(int));
85 ptr += nb_buckets + 1;
87 sym = (ElfW(Sym) *)s->data + 1;
88 for(sym_index = 1; sym_index < nb_syms; sym_index++) {
89 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
90 h = elf_hash(strtab + sym->st_name) % nb_buckets;
91 *ptr = hash[h];
92 hash[h] = sym_index;
93 } else {
94 *ptr = 0;
96 ptr++;
97 sym++;
101 /* return the symbol number */
102 ST_FUNC int put_elf_sym(Section *s, uplong value, unsigned long size,
103 int info, int other, int shndx, const char *name)
105 int name_offset, sym_index;
106 int nbuckets, h;
107 ElfW(Sym) *sym;
108 Section *hs;
110 sym = section_ptr_add(s, sizeof(ElfW(Sym)));
111 if (name)
112 name_offset = put_elf_str(s->link, name);
113 else
114 name_offset = 0;
115 /* XXX: endianness */
116 sym->st_name = name_offset;
117 sym->st_value = value;
118 sym->st_size = size;
119 sym->st_info = info;
120 sym->st_other = other;
121 sym->st_shndx = shndx;
122 sym_index = sym - (ElfW(Sym) *)s->data;
123 hs = s->hash;
124 if (hs) {
125 int *ptr, *base;
126 ptr = section_ptr_add(hs, sizeof(int));
127 base = (int *)hs->data;
128 /* only add global or weak symbols */
129 if (ELFW(ST_BIND)(info) != STB_LOCAL) {
130 /* add another hashing entry */
131 nbuckets = base[0];
132 h = elf_hash(name) % nbuckets;
133 *ptr = base[2 + h];
134 base[2 + h] = sym_index;
135 base[1]++;
136 /* we resize the hash table */
137 hs->nb_hashed_syms++;
138 if (hs->nb_hashed_syms > 2 * nbuckets) {
139 rebuild_hash(s, 2 * nbuckets);
141 } else {
142 *ptr = 0;
143 base[1]++;
146 return sym_index;
149 /* find global ELF symbol 'name' and return its index. Return 0 if not
150 found. */
151 ST_FUNC int find_elf_sym(Section *s, const char *name)
153 ElfW(Sym) *sym;
154 Section *hs;
155 int nbuckets, sym_index, h;
156 const char *name1;
158 hs = s->hash;
159 if (!hs)
160 return 0;
161 nbuckets = ((int *)hs->data)[0];
162 h = elf_hash(name) % nbuckets;
163 sym_index = ((int *)hs->data)[2 + h];
164 while (sym_index != 0) {
165 sym = &((ElfW(Sym) *)s->data)[sym_index];
166 name1 = s->link->data + sym->st_name;
167 if (!strcmp(name, name1))
168 return sym_index;
169 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
171 return 0;
174 /* return elf symbol value, signal error if 'err' is nonzero */
175 static void *get_elf_sym_addr(TCCState *s, const char *name, int err)
177 int sym_index;
178 ElfW(Sym) *sym;
180 sym_index = find_elf_sym(symtab_section, name);
181 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
182 if (!sym_index || sym->st_shndx == SHN_UNDEF) {
183 if (err)
184 error("%s not defined", name);
185 return NULL;
187 return (void*)(uplong)sym->st_value;
190 /* return elf symbol value */
191 LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
193 return get_elf_sym_addr(s, name, 0);
196 /* return elf symbol value or error */
197 ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name)
199 return get_elf_sym_addr(s, name, 1);
202 /* add an elf symbol : check if it is already defined and patch
203 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
204 ST_FUNC int add_elf_sym(Section *s, uplong value, unsigned long size,
205 int info, int other, int sh_num, const char *name)
207 ElfW(Sym) *esym;
208 int sym_bind, sym_index, sym_type, esym_bind;
209 unsigned char sym_vis, esym_vis, new_vis;
211 sym_bind = ELFW(ST_BIND)(info);
212 sym_type = ELFW(ST_TYPE)(info);
213 sym_vis = ELFW(ST_VISIBILITY)(other);
215 if (sym_bind != STB_LOCAL) {
216 /* we search global or weak symbols */
217 sym_index = find_elf_sym(s, name);
218 if (!sym_index)
219 goto do_def;
220 esym = &((ElfW(Sym) *)s->data)[sym_index];
221 if (esym->st_shndx != SHN_UNDEF) {
222 esym_bind = ELFW(ST_BIND)(esym->st_info);
223 /* propagate the most constraining visibility */
224 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
225 esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
226 if (esym_vis == STV_DEFAULT) {
227 new_vis = sym_vis;
228 } else if (sym_vis == STV_DEFAULT) {
229 new_vis = esym_vis;
230 } else {
231 new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
233 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
234 | new_vis;
235 other = esym->st_other; /* in case we have to patch esym */
236 if (sh_num == SHN_UNDEF) {
237 /* ignore adding of undefined symbol if the
238 corresponding symbol is already defined */
239 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
240 /* global overrides weak, so patch */
241 goto do_patch;
242 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
243 /* weak is ignored if already global */
244 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
245 /* ignore hidden symbols after */
246 } else if (esym->st_shndx == SHN_COMMON
247 && (sh_num < SHN_LORESERVE || sh_num == SHN_COMMON)) {
248 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
249 No idea if this is the correct solution ... */
250 goto do_patch;
251 } else if (s == tcc_state->dynsymtab_section) {
252 /* we accept that two DLL define the same symbol */
253 } else {
254 #if 1
255 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
256 sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
257 #endif
258 error_noabort("'%s' defined twice", name);
260 } else {
261 do_patch:
262 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
263 esym->st_shndx = sh_num;
264 new_undef_sym = 1;
265 esym->st_value = value;
266 esym->st_size = size;
267 esym->st_other = other;
269 } else {
270 do_def:
271 sym_index = put_elf_sym(s, value, size,
272 ELFW(ST_INFO)(sym_bind, sym_type), other,
273 sh_num, name);
275 return sym_index;
278 /* put relocation */
279 ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
280 int type, int symbol)
282 char buf[256];
283 Section *sr;
284 ElfW_Rel *rel;
286 sr = s->reloc;
287 if (!sr) {
288 /* if no relocation section, create it */
289 snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
290 /* if the symtab is allocated, then we consider the relocation
291 are also */
292 sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
293 sr->sh_entsize = sizeof(ElfW_Rel);
294 sr->link = symtab;
295 sr->sh_info = s->sh_num;
296 s->reloc = sr;
298 rel = section_ptr_add(sr, sizeof(ElfW_Rel));
299 rel->r_offset = offset;
300 rel->r_info = ELFW(R_INFO)(symbol, type);
301 #ifdef TCC_TARGET_X86_64
302 rel->r_addend = 0;
303 #endif
306 /* put stab debug information */
308 ST_FUNC void put_stabs(const char *str, int type, int other, int desc,
309 unsigned long value)
311 Stab_Sym *sym;
313 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
314 if (str) {
315 sym->n_strx = put_elf_str(stabstr_section, str);
316 } else {
317 sym->n_strx = 0;
319 sym->n_type = type;
320 sym->n_other = other;
321 sym->n_desc = desc;
322 sym->n_value = value;
325 ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc,
326 unsigned long value, Section *sec, int sym_index)
328 put_stabs(str, type, other, desc, value);
329 put_elf_reloc(symtab_section, stab_section,
330 stab_section->data_offset - sizeof(unsigned int),
331 R_DATA_32, sym_index);
334 ST_FUNC void put_stabn(int type, int other, int desc, int value)
336 put_stabs(NULL, type, other, desc, value);
339 ST_FUNC void put_stabd(int type, int other, int desc)
341 put_stabs(NULL, type, other, desc, 0);
344 /* In an ELF file symbol table, the local symbols must appear below
345 the global and weak ones. Since TCC cannot sort it while generating
346 the code, we must do it after. All the relocation tables are also
347 modified to take into account the symbol table sorting */
348 static void sort_syms(TCCState *s1, Section *s)
350 int *old_to_new_syms;
351 ElfW(Sym) *new_syms;
352 int nb_syms, i;
353 ElfW(Sym) *p, *q;
354 ElfW_Rel *rel, *rel_end;
355 Section *sr;
356 int type, sym_index;
358 nb_syms = s->data_offset / sizeof(ElfW(Sym));
359 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
360 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
362 /* first pass for local symbols */
363 p = (ElfW(Sym) *)s->data;
364 q = new_syms;
365 for(i = 0; i < nb_syms; i++) {
366 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
367 old_to_new_syms[i] = q - new_syms;
368 *q++ = *p;
370 p++;
372 /* save the number of local symbols in section header */
373 s->sh_info = q - new_syms;
375 /* then second pass for non local symbols */
376 p = (ElfW(Sym) *)s->data;
377 for(i = 0; i < nb_syms; i++) {
378 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
379 old_to_new_syms[i] = q - new_syms;
380 *q++ = *p;
382 p++;
385 /* we copy the new symbols to the old */
386 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
387 tcc_free(new_syms);
389 /* now we modify all the relocations */
390 for(i = 1; i < s1->nb_sections; i++) {
391 sr = s1->sections[i];
392 if (sr->sh_type == SHT_RELX && sr->link == s) {
393 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
394 for(rel = (ElfW_Rel *)sr->data;
395 rel < rel_end;
396 rel++) {
397 sym_index = ELFW(R_SYM)(rel->r_info);
398 type = ELFW(R_TYPE)(rel->r_info);
399 sym_index = old_to_new_syms[sym_index];
400 rel->r_info = ELFW(R_INFO)(sym_index, type);
405 tcc_free(old_to_new_syms);
408 /* relocate common symbols in the .bss section */
409 ST_FUNC void relocate_common_syms(void)
411 ElfW(Sym) *sym, *sym_end;
412 unsigned long offset, align;
414 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
415 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
416 sym < sym_end;
417 sym++) {
418 if (sym->st_shndx == SHN_COMMON) {
419 /* align symbol */
420 align = sym->st_value;
421 offset = bss_section->data_offset;
422 offset = (offset + align - 1) & -align;
423 sym->st_value = offset;
424 sym->st_shndx = bss_section->sh_num;
425 offset += sym->st_size;
426 bss_section->data_offset = offset;
431 /* relocate symbol table, resolve undefined symbols if do_resolve is
432 true and output error if undefined symbol. */
433 ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
435 ElfW(Sym) *sym, *esym, *sym_end;
436 int sym_bind, sh_num, sym_index;
437 const char *name;
439 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
440 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
441 sym < sym_end;
442 sym++) {
443 sh_num = sym->st_shndx;
444 if (sh_num == SHN_UNDEF) {
445 name = strtab_section->data + sym->st_name;
446 if (do_resolve) {
447 #if !defined TCC_TARGET_PE || !defined _WIN32
448 void *addr;
449 name = symtab_section->link->data + sym->st_name;
450 addr = resolve_sym(s1, name);
451 if (addr) {
452 sym->st_value = (uplong)addr;
453 goto found;
455 #endif
456 } else if (s1->dynsym) {
457 /* if dynamic symbol exist, then use it */
458 sym_index = find_elf_sym(s1->dynsym, name);
459 if (sym_index) {
460 esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
461 sym->st_value = esym->st_value;
462 goto found;
465 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
466 it */
467 if (!strcmp(name, "_fp_hw"))
468 goto found;
469 /* only weak symbols are accepted to be undefined. Their
470 value is zero */
471 sym_bind = ELFW(ST_BIND)(sym->st_info);
472 if (sym_bind == STB_WEAK) {
473 sym->st_value = 0;
474 } else {
475 error_noabort("undefined symbol '%s'", name);
477 } else if (sh_num < SHN_LORESERVE) {
478 /* add section base */
479 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
481 found: ;
485 #ifndef TCC_TARGET_PE
486 #ifdef TCC_TARGET_X86_64
487 #define JMP_TABLE_ENTRY_SIZE 14
488 static uplong add_jmp_table(TCCState *s1, uplong val)
490 char *p = s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset;
491 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
492 /* jmp *0x0(%rip) */
493 p[0] = 0xff;
494 p[1] = 0x25;
495 *(int *)(p + 2) = 0;
496 *(uplong *)(p + 6) = val;
497 return (uplong)p;
500 static uplong add_got_table(TCCState *s1, uplong val)
502 uplong *p = (uplong *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
503 s1->runtime_plt_and_got_offset += sizeof(uplong);
504 *p = val;
505 return (uplong)p;
507 #elif defined TCC_TARGET_ARM
508 #define JMP_TABLE_ENTRY_SIZE 8
509 static int add_jmp_table(TCCState *s1, int val)
511 uint32_t *p = (uint32_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
512 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
513 /* ldr pc, [pc, #-4] */
514 p[0] = 0xE51FF004;
515 p[1] = val;
516 return (int)p;
518 #endif
519 #endif
521 /* relocate a given section (CPU dependent) */
522 ST_FUNC void relocate_section(TCCState *s1, Section *s)
524 Section *sr;
525 ElfW_Rel *rel, *rel_end, *qrel;
526 ElfW(Sym) *sym;
527 int type, sym_index;
528 unsigned char *ptr;
529 uplong val, addr;
530 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
531 int esym_index;
532 #endif
534 sr = s->reloc;
535 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
536 qrel = (ElfW_Rel *)sr->data;
537 for(rel = qrel;
538 rel < rel_end;
539 rel++) {
540 ptr = s->data + rel->r_offset;
542 sym_index = ELFW(R_SYM)(rel->r_info);
543 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
544 val = sym->st_value;
545 #ifdef TCC_TARGET_X86_64
546 /* XXX: not tested */
547 val += rel->r_addend;
548 #endif
549 type = ELFW(R_TYPE)(rel->r_info);
550 addr = s->sh_addr + rel->r_offset;
552 /* CPU specific */
553 switch(type) {
554 #if defined(TCC_TARGET_I386)
555 case R_386_32:
556 if (s1->output_type == TCC_OUTPUT_DLL) {
557 esym_index = s1->symtab_to_dynsym[sym_index];
558 qrel->r_offset = rel->r_offset;
559 if (esym_index) {
560 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
561 qrel++;
562 break;
563 } else {
564 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
565 qrel++;
568 *(int *)ptr += val;
569 break;
570 case R_386_PC32:
571 if (s1->output_type == TCC_OUTPUT_DLL) {
572 /* DLL relocation */
573 esym_index = s1->symtab_to_dynsym[sym_index];
574 if (esym_index) {
575 qrel->r_offset = rel->r_offset;
576 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
577 qrel++;
578 break;
581 *(int *)ptr += val - addr;
582 break;
583 case R_386_PLT32:
584 *(int *)ptr += val - addr;
585 break;
586 case R_386_GLOB_DAT:
587 case R_386_JMP_SLOT:
588 *(int *)ptr = val;
589 break;
590 case R_386_GOTPC:
591 *(int *)ptr += s1->got->sh_addr - addr;
592 break;
593 case R_386_GOTOFF:
594 *(int *)ptr += val - s1->got->sh_addr;
595 break;
596 case R_386_GOT32:
597 /* we load the got offset */
598 *(int *)ptr += s1->got_offsets[sym_index];
599 break;
600 case R_386_16:
601 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
602 output_file:
603 error("can only produce 16-bit binary files");
605 *(short *)ptr += val;
606 break;
607 case R_386_PC16:
608 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
609 goto output_file;
610 *(short *)ptr += val - addr;
611 break;
612 #elif defined(TCC_TARGET_ARM)
613 case R_ARM_PC24:
614 case R_ARM_CALL:
615 case R_ARM_JUMP24:
616 case R_ARM_PLT32:
618 int x;
619 x = (*(int *)ptr)&0xffffff;
620 (*(int *)ptr) &= 0xff000000;
621 if (x & 0x800000)
622 x -= 0x1000000;
623 x *= 4;
624 x += val - addr;
625 #ifndef TCC_TARGET_PE
626 if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
627 if (s1->output_type == TCC_OUTPUT_MEMORY)
628 x += add_jmp_table(s1, val) - val; /* add veneer */
629 #endif
630 if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
631 error("can't relocate value at %x",addr);
632 x >>= 2;
633 x &= 0xffffff;
634 (*(int *)ptr) |= x;
636 break;
637 case R_ARM_PREL31:
639 int x;
640 x = (*(int *)ptr) & 0x7fffffff;
641 (*(int *)ptr) &= 0x80000000;
642 x = (x * 2) / 2;
643 x += val - addr;
644 if((x^(x>>1))&0x40000000)
645 error("can't relocate value at %x",addr);
646 (*(int *)ptr) |= x & 0x7fffffff;
648 case R_ARM_ABS32:
649 *(int *)ptr += val;
650 break;
651 case R_ARM_BASE_PREL:
652 *(int *)ptr += s1->got->sh_addr - addr;
653 break;
654 case R_ARM_GOTOFF32:
655 *(int *)ptr += val - s1->got->sh_addr;
656 break;
657 case R_ARM_GOT_BREL:
658 /* we load the got offset */
659 *(int *)ptr += s1->got_offsets[sym_index];
660 break;
661 case R_ARM_COPY:
662 break;
663 case R_ARM_V4BX:
664 /* trade Thumb support for ARMv4 support */
665 if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
666 *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
667 break;
668 default:
669 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
670 type,addr,(unsigned int)(long)ptr,val);
671 break;
672 #elif defined(TCC_TARGET_C67)
673 case R_C60_32:
674 *(int *)ptr += val;
675 break;
676 case R_C60LO16:
678 uint32_t orig;
680 /* put the low 16 bits of the absolute address */
681 // add to what is already there
683 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
684 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
686 //patch both at once - assumes always in pairs Low - High
688 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
689 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
691 break;
692 case R_C60HI16:
693 break;
694 default:
695 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
696 type,addr,(unsigned int)(long)ptr, val);
697 break;
698 #elif defined(TCC_TARGET_X86_64)
699 case R_X86_64_64:
700 if (s1->output_type == TCC_OUTPUT_DLL) {
701 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
702 qrel->r_addend = *(long long *)ptr + val;
703 qrel++;
705 *(long long *)ptr += val;
706 break;
707 case R_X86_64_32:
708 case R_X86_64_32S:
709 if (s1->output_type == TCC_OUTPUT_DLL) {
710 /* XXX: this logic may depend on TCC's codegen
711 now TCC uses R_X86_64_32 even for a 64bit pointer */
712 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
713 qrel->r_addend = *(int *)ptr + val;
714 qrel++;
716 *(int *)ptr += val;
717 break;
718 case R_X86_64_PC32: {
719 long long diff;
720 if (s1->output_type == TCC_OUTPUT_DLL) {
721 /* DLL relocation */
722 esym_index = s1->symtab_to_dynsym[sym_index];
723 if (esym_index) {
724 qrel->r_offset = rel->r_offset;
725 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
726 qrel->r_addend = *(int *)ptr;
727 qrel++;
728 break;
731 diff = (long long)val - addr;
732 if (diff <= -2147483647 || diff > 2147483647) {
733 #ifndef TCC_TARGET_PE
734 /* XXX: naive support for over 32bit jump */
735 if (s1->output_type == TCC_OUTPUT_MEMORY) {
736 val = add_jmp_table(s1, val);
737 diff = val - addr;
739 #endif
740 if (diff <= -2147483647 || diff > 2147483647) {
741 error("internal error: relocation failed");
744 *(int *)ptr += diff;
746 break;
747 case R_X86_64_PLT32:
748 *(int *)ptr += val - addr;
749 break;
750 case R_X86_64_GLOB_DAT:
751 case R_X86_64_JUMP_SLOT:
752 *(int *)ptr = val;
753 break;
754 case R_X86_64_GOTPCREL:
755 #ifndef TCC_TARGET_PE
756 if (s1->output_type == TCC_OUTPUT_MEMORY) {
757 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
758 *(int *)ptr += val - addr;
759 break;
761 #endif
762 *(int *)ptr += (s1->got->sh_addr - addr +
763 s1->got_offsets[sym_index] - 4);
764 break;
765 case R_X86_64_GOTTPOFF:
766 *(int *)ptr += val - s1->got->sh_addr;
767 break;
768 case R_X86_64_GOT32:
769 /* we load the got offset */
770 *(int *)ptr += s1->got_offsets[sym_index];
771 break;
772 #else
773 #error unsupported processor
774 #endif
777 /* if the relocation is allocated, we change its symbol table */
778 if (sr->sh_flags & SHF_ALLOC)
779 sr->link = s1->dynsym;
782 /* relocate relocation table in 'sr' */
783 static void relocate_rel(TCCState *s1, Section *sr)
785 Section *s;
786 ElfW_Rel *rel, *rel_end;
788 s = s1->sections[sr->sh_info];
789 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
790 for(rel = (ElfW_Rel *)sr->data;
791 rel < rel_end;
792 rel++) {
793 rel->r_offset += s->sh_addr;
797 /* count the number of dynamic relocations so that we can reserve
798 their space */
799 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
801 ElfW_Rel *rel, *rel_end;
802 int sym_index, esym_index, type, count;
804 count = 0;
805 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
806 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
807 sym_index = ELFW(R_SYM)(rel->r_info);
808 type = ELFW(R_TYPE)(rel->r_info);
809 switch(type) {
810 #if defined(TCC_TARGET_I386)
811 case R_386_32:
812 #elif defined(TCC_TARGET_X86_64)
813 case R_X86_64_32:
814 case R_X86_64_32S:
815 case R_X86_64_64:
816 #endif
817 count++;
818 break;
819 #if defined(TCC_TARGET_I386)
820 case R_386_PC32:
821 #elif defined(TCC_TARGET_X86_64)
822 case R_X86_64_PC32:
823 #endif
824 esym_index = s1->symtab_to_dynsym[sym_index];
825 if (esym_index)
826 count++;
827 break;
828 default:
829 break;
832 if (count) {
833 /* allocate the section */
834 sr->sh_flags |= SHF_ALLOC;
835 sr->sh_size = count * sizeof(ElfW_Rel);
837 return count;
840 static void put_got_offset(TCCState *s1, int index, unsigned long val)
842 int n;
843 unsigned long *tab;
845 if (index >= s1->nb_got_offsets) {
846 /* find immediately bigger power of 2 and reallocate array */
847 n = 1;
848 while (index >= n)
849 n *= 2;
850 tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
851 if (!tab)
852 error("memory full");
853 s1->got_offsets = tab;
854 memset(s1->got_offsets + s1->nb_got_offsets, 0,
855 (n - s1->nb_got_offsets) * sizeof(unsigned long));
856 s1->nb_got_offsets = n;
858 s1->got_offsets[index] = val;
861 /* XXX: suppress that */
862 static void put32(unsigned char *p, uint32_t val)
864 p[0] = val;
865 p[1] = val >> 8;
866 p[2] = val >> 16;
867 p[3] = val >> 24;
870 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
871 defined(TCC_TARGET_X86_64)
872 static uint32_t get32(unsigned char *p)
874 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
876 #endif
878 static void build_got(TCCState *s1)
880 unsigned char *ptr;
882 /* if no got, then create it */
883 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
884 s1->got->sh_entsize = 4;
885 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
886 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
887 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
888 #if PTR_SIZE == 4
889 /* keep space for _DYNAMIC pointer, if present */
890 put32(ptr, 0);
891 /* two dummy got entries */
892 put32(ptr + 4, 0);
893 put32(ptr + 8, 0);
894 #else
895 /* keep space for _DYNAMIC pointer, if present */
896 put32(ptr, 0);
897 put32(ptr + 4, 0);
898 /* two dummy got entries */
899 put32(ptr + 8, 0);
900 put32(ptr + 12, 0);
901 put32(ptr + 16, 0);
902 put32(ptr + 20, 0);
903 #endif
906 /* put a got entry corresponding to a symbol in symtab_section. 'size'
907 and 'info' can be modifed if more precise info comes from the DLL */
908 static void put_got_entry(TCCState *s1,
909 int reloc_type, unsigned long size, int info,
910 int sym_index)
912 int index;
913 const char *name;
914 ElfW(Sym) *sym;
915 unsigned long offset;
916 int *ptr;
918 if (!s1->got)
919 build_got(s1);
921 /* if a got entry already exists for that symbol, no need to add one */
922 if (sym_index < s1->nb_got_offsets &&
923 s1->got_offsets[sym_index] != 0)
924 return;
926 put_got_offset(s1, sym_index, s1->got->data_offset);
928 if (s1->dynsym) {
929 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
930 name = symtab_section->link->data + sym->st_name;
931 offset = sym->st_value;
932 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
933 if (reloc_type ==
934 #ifdef TCC_TARGET_X86_64
935 R_X86_64_JUMP_SLOT
936 #else
937 R_386_JMP_SLOT
938 #endif
940 Section *plt;
941 uint8_t *p;
942 int modrm;
944 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
945 modrm = 0x25;
946 #else
947 /* if we build a DLL, we add a %ebx offset */
948 if (s1->output_type == TCC_OUTPUT_DLL)
949 modrm = 0xa3;
950 else
951 modrm = 0x25;
952 #endif
954 /* add a PLT entry */
955 plt = s1->plt;
956 if (plt->data_offset == 0) {
957 /* first plt entry */
958 p = section_ptr_add(plt, 16);
959 p[0] = 0xff; /* pushl got + PTR_SIZE */
960 p[1] = modrm + 0x10;
961 put32(p + 2, PTR_SIZE);
962 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
963 p[7] = modrm;
964 put32(p + 8, PTR_SIZE * 2);
967 p = section_ptr_add(plt, 16);
968 p[0] = 0xff; /* jmp *(got + x) */
969 p[1] = modrm;
970 put32(p + 2, s1->got->data_offset);
971 p[6] = 0x68; /* push $xxx */
972 put32(p + 7, (plt->data_offset - 32) >> 1);
973 p[11] = 0xe9; /* jmp plt_start */
974 put32(p + 12, -(plt->data_offset));
976 /* the symbol is modified so that it will be relocated to
977 the PLT */
978 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
979 if (s1->output_type == TCC_OUTPUT_EXE)
980 #endif
981 offset = plt->data_offset - 16;
983 #elif defined(TCC_TARGET_ARM)
984 if (reloc_type == R_ARM_JUMP_SLOT) {
985 Section *plt;
986 uint8_t *p;
988 /* if we build a DLL, we add a %ebx offset */
989 if (s1->output_type == TCC_OUTPUT_DLL)
990 error("DLLs unimplemented!");
992 /* add a PLT entry */
993 plt = s1->plt;
994 if (plt->data_offset == 0) {
995 /* first plt entry */
996 p = section_ptr_add(plt, 16);
997 put32(p , 0xe52de004);
998 put32(p + 4, 0xe59fe010);
999 put32(p + 8, 0xe08fe00e);
1000 put32(p + 12, 0xe5bef008);
1003 p = section_ptr_add(plt, 16);
1004 put32(p , 0xe59fc004);
1005 put32(p+4, 0xe08fc00c);
1006 put32(p+8, 0xe59cf000);
1007 put32(p+12, s1->got->data_offset);
1009 /* the symbol is modified so that it will be relocated to
1010 the PLT */
1011 if (s1->output_type == TCC_OUTPUT_EXE)
1012 offset = plt->data_offset - 16;
1014 #elif defined(TCC_TARGET_C67)
1015 error("C67 got not implemented");
1016 #else
1017 #error unsupported CPU
1018 #endif
1019 index = put_elf_sym(s1->dynsym, offset,
1020 size, info, 0, sym->st_shndx, name);
1021 /* put a got entry */
1022 put_elf_reloc(s1->dynsym, s1->got,
1023 s1->got->data_offset,
1024 reloc_type, index);
1026 ptr = section_ptr_add(s1->got, PTR_SIZE);
1027 *ptr = 0;
1030 /* build GOT and PLT entries */
1031 ST_FUNC void build_got_entries(TCCState *s1)
1033 Section *s, *symtab;
1034 ElfW_Rel *rel, *rel_end;
1035 ElfW(Sym) *sym;
1036 int i, type, reloc_type, sym_index;
1038 for(i = 1; i < s1->nb_sections; i++) {
1039 s = s1->sections[i];
1040 if (s->sh_type != SHT_RELX)
1041 continue;
1042 /* no need to handle got relocations */
1043 if (s->link != symtab_section)
1044 continue;
1045 symtab = s->link;
1046 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1047 for(rel = (ElfW_Rel *)s->data;
1048 rel < rel_end;
1049 rel++) {
1050 type = ELFW(R_TYPE)(rel->r_info);
1051 switch(type) {
1052 #if defined(TCC_TARGET_I386)
1053 case R_386_GOT32:
1054 case R_386_GOTOFF:
1055 case R_386_GOTPC:
1056 case R_386_PLT32:
1057 if (!s1->got)
1058 build_got(s1);
1059 if (type == R_386_GOT32 || type == R_386_PLT32) {
1060 sym_index = ELFW(R_SYM)(rel->r_info);
1061 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1062 /* look at the symbol got offset. If none, then add one */
1063 if (type == R_386_GOT32)
1064 reloc_type = R_386_GLOB_DAT;
1065 else
1066 reloc_type = R_386_JMP_SLOT;
1067 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1068 sym_index);
1070 break;
1071 #elif defined(TCC_TARGET_ARM)
1072 case R_ARM_GOT_BREL:
1073 case R_ARM_GOTOFF32:
1074 case R_ARM_BASE_PREL:
1075 case R_ARM_PLT32:
1076 if (!s1->got)
1077 build_got(s1);
1078 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1079 sym_index = ELFW(R_SYM)(rel->r_info);
1080 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1081 /* look at the symbol got offset. If none, then add one */
1082 if (type == R_ARM_GOT_BREL)
1083 reloc_type = R_ARM_GLOB_DAT;
1084 else
1085 reloc_type = R_ARM_JUMP_SLOT;
1086 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1087 sym_index);
1089 break;
1090 #elif defined(TCC_TARGET_C67)
1091 case R_C60_GOT32:
1092 case R_C60_GOTOFF:
1093 case R_C60_GOTPC:
1094 case R_C60_PLT32:
1095 if (!s1->got)
1096 build_got(s1);
1097 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1098 sym_index = ELFW(R_SYM)(rel->r_info);
1099 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1100 /* look at the symbol got offset. If none, then add one */
1101 if (type == R_C60_GOT32)
1102 reloc_type = R_C60_GLOB_DAT;
1103 else
1104 reloc_type = R_C60_JMP_SLOT;
1105 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1106 sym_index);
1108 break;
1109 #elif defined(TCC_TARGET_X86_64)
1110 case R_X86_64_GOT32:
1111 case R_X86_64_GOTTPOFF:
1112 case R_X86_64_GOTPCREL:
1113 case R_X86_64_PLT32:
1114 if (!s1->got)
1115 build_got(s1);
1116 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1117 type == R_X86_64_PLT32) {
1118 sym_index = ELFW(R_SYM)(rel->r_info);
1119 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1120 /* look at the symbol got offset. If none, then add one */
1121 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1122 reloc_type = R_X86_64_GLOB_DAT;
1123 else
1124 reloc_type = R_X86_64_JUMP_SLOT;
1125 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1126 sym_index);
1128 break;
1129 #else
1130 #error unsupported CPU
1131 #endif
1132 default:
1133 break;
1139 ST_FUNC Section *new_symtab(TCCState *s1,
1140 const char *symtab_name, int sh_type, int sh_flags,
1141 const char *strtab_name,
1142 const char *hash_name, int hash_sh_flags)
1144 Section *symtab, *strtab, *hash;
1145 int *ptr, nb_buckets;
1147 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1148 symtab->sh_entsize = sizeof(ElfW(Sym));
1149 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1150 put_elf_str(strtab, "");
1151 symtab->link = strtab;
1152 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1154 nb_buckets = 1;
1156 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1157 hash->sh_entsize = sizeof(int);
1158 symtab->hash = hash;
1159 hash->link = symtab;
1161 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1162 ptr[0] = nb_buckets;
1163 ptr[1] = 1;
1164 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1165 return symtab;
1168 /* put dynamic tag */
1169 static void put_dt(Section *dynamic, int dt, unsigned long val)
1171 ElfW(Dyn) *dyn;
1172 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1173 dyn->d_tag = dt;
1174 dyn->d_un.d_val = val;
1177 static void add_init_array_defines(TCCState *s1, const char *section_name)
1179 Section *s;
1180 long end_offset;
1181 char sym_start[1024];
1182 char sym_end[1024];
1184 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1185 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1187 s = find_section(s1, section_name);
1188 if (!s) {
1189 end_offset = 0;
1190 s = data_section;
1191 } else {
1192 end_offset = s->data_offset;
1195 add_elf_sym(symtab_section,
1196 0, 0,
1197 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1198 s->sh_num, sym_start);
1199 add_elf_sym(symtab_section,
1200 end_offset, 0,
1201 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1202 s->sh_num, sym_end);
1205 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1207 #ifdef CONFIG_TCC_BCHECK
1208 unsigned long *ptr;
1209 Section *init_section;
1210 unsigned char *pinit;
1211 int sym_index;
1213 if (0 == s1->do_bounds_check)
1214 return;
1216 /* XXX: add an object file to do that */
1217 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1218 *ptr = 0;
1219 add_elf_sym(symtab_section, 0, 0,
1220 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1221 bounds_section->sh_num, "__bounds_start");
1222 /* add bound check code */
1223 #ifndef TCC_TARGET_PE
1225 char buf[1024];
1226 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "bcheck.o");
1227 tcc_add_file(s1, buf);
1229 #endif
1230 #ifdef TCC_TARGET_I386
1231 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1232 /* add 'call __bound_init()' in .init section */
1233 init_section = find_section(s1, ".init");
1234 pinit = section_ptr_add(init_section, 5);
1235 pinit[0] = 0xe8;
1236 put32(pinit + 1, -4);
1237 sym_index = find_elf_sym(symtab_section, "__bound_init");
1238 put_elf_reloc(symtab_section, init_section,
1239 init_section->data_offset - 4, R_386_PC32, sym_index);
1241 #endif
1242 #endif
1245 /* add tcc runtime libraries */
1246 ST_FUNC void tcc_add_runtime(TCCState *s1)
1248 tcc_add_bcheck(s1);
1250 /* add libc */
1251 if (!s1->nostdlib) {
1252 #ifdef CONFIG_USE_LIBGCC
1253 tcc_add_library(s1, "c");
1254 tcc_add_file(s1, CONFIG_SYSROOT "/lib/libgcc_s.so.1");
1255 #else
1256 tcc_add_library(s1, "c");
1257 #ifndef WITHOUT_LIBTCC
1259 char buf[1024];
1260 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "libtcc1.a");
1261 tcc_add_file(s1, buf);
1263 #endif
1264 #endif
1266 /* add crt end if not memory output */
1267 if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) {
1268 tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
1272 /* add various standard linker symbols (must be done after the
1273 sections are filled (for example after allocating common
1274 symbols)) */
1275 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1277 char buf[1024];
1278 int i;
1279 Section *s;
1281 add_elf_sym(symtab_section,
1282 text_section->data_offset, 0,
1283 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1284 text_section->sh_num, "_etext");
1285 add_elf_sym(symtab_section,
1286 data_section->data_offset, 0,
1287 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1288 data_section->sh_num, "_edata");
1289 add_elf_sym(symtab_section,
1290 bss_section->data_offset, 0,
1291 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1292 bss_section->sh_num, "_end");
1293 /* horrible new standard ldscript defines */
1294 add_init_array_defines(s1, ".preinit_array");
1295 add_init_array_defines(s1, ".init_array");
1296 add_init_array_defines(s1, ".fini_array");
1298 /* add start and stop symbols for sections whose name can be
1299 expressed in C */
1300 for(i = 1; i < s1->nb_sections; i++) {
1301 s = s1->sections[i];
1302 if (s->sh_type == SHT_PROGBITS &&
1303 (s->sh_flags & SHF_ALLOC)) {
1304 const char *p;
1305 int ch;
1307 /* check if section name can be expressed in C */
1308 p = s->name;
1309 for(;;) {
1310 ch = *p;
1311 if (!ch)
1312 break;
1313 if (!isid(ch) && !isnum(ch))
1314 goto next_sec;
1315 p++;
1317 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1318 add_elf_sym(symtab_section,
1319 0, 0,
1320 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1321 s->sh_num, buf);
1322 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1323 add_elf_sym(symtab_section,
1324 s->data_offset, 0,
1325 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1326 s->sh_num, buf);
1328 next_sec: ;
1332 /* name of ELF interpreter */
1333 #if defined __FreeBSD__
1334 static const char elf_interp[] = "/libexec/ld-elf.so.1";
1335 #elif defined __FreeBSD_kernel__
1336 static char elf_interp[] = "/lib/ld.so.1";
1337 #elif defined TCC_ARM_EABI
1338 static const char elf_interp[] = "/lib/ld-linux.so.3";
1339 #elif defined(TCC_TARGET_X86_64)
1340 # if defined(TCC_TARGET_X86_64_CENTOS)
1341 static const char elf_interp[] = "/lib64/ld-linux-x86-64.so.2";
1342 # else
1343 static const char elf_interp[] = "/lib/ld-linux-x86-64.so.2";
1344 # endif /* TCC_TARGET_X86_64_CENTOS */
1345 #elif defined(TCC_UCLIBC)
1346 static const char elf_interp[] = "/lib/ld-uClibc.so.0";
1347 #else
1348 static const char elf_interp[] = "/lib/ld-linux.so.2";
1349 #endif
1351 static void tcc_output_binary(TCCState *s1, FILE *f,
1352 const int *section_order)
1354 Section *s;
1355 int i, offset, size;
1357 offset = 0;
1358 for(i=1;i<s1->nb_sections;i++) {
1359 s = s1->sections[section_order[i]];
1360 if (s->sh_type != SHT_NOBITS &&
1361 (s->sh_flags & SHF_ALLOC)) {
1362 while (offset < s->sh_offset) {
1363 fputc(0, f);
1364 offset++;
1366 size = s->sh_size;
1367 fwrite(s->data, 1, size, f);
1368 offset += size;
1373 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1374 #define HAVE_PHDR 1
1375 #define EXTRA_RELITEMS 14
1377 /* move the relocation value from .dynsym to .got */
1378 void patch_dynsym_undef(TCCState *s1, Section *s)
1380 uint32_t *gotd = (void *)s1->got->data;
1381 ElfW(Sym) *sym, *sym_end;
1383 gotd += 3; // dummy entries in .got
1384 /* relocate symbols in .dynsym */
1385 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1386 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1387 if (sym->st_shndx == SHN_UNDEF) {
1388 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1389 sym->st_value = 0;
1393 #else
1394 #define HAVE_PHDR 0
1395 #define EXTRA_RELITEMS 9
1396 #endif
1398 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1400 int sym_index = ELFW(R_SYM) (rel->r_info);
1401 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1402 unsigned long offset;
1404 if (sym_index >= s1->nb_got_offsets)
1405 return;
1406 offset = s1->got_offsets[sym_index];
1407 section_reserve(s1->got, offset + PTR_SIZE);
1408 #ifdef TCC_TARGET_X86_64
1409 /* only works for x86-64 */
1410 put32(s1->got->data + offset, sym->st_value >> 32);
1411 #endif
1412 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1415 ST_FUNC void fill_got(TCCState *s1)
1417 Section *s;
1418 ElfW_Rel *rel, *rel_end;
1419 int i;
1421 for(i = 1; i < s1->nb_sections; i++) {
1422 s = s1->sections[i];
1423 if (s->sh_type != SHT_RELX)
1424 continue;
1425 /* no need to handle got relocations */
1426 if (s->link != symtab_section)
1427 continue;
1428 rel_end = (ElfW_Rel *) (s->data + s->data_offset);
1429 for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
1430 switch (ELFW(R_TYPE) (rel->r_info)) {
1431 case R_X86_64_GOT32:
1432 case R_X86_64_GOTPCREL:
1433 case R_X86_64_PLT32:
1434 fill_got_entry(s1, rel);
1435 break;
1442 /* output an ELF file */
1443 /* XXX: suppress unneeded sections */
1444 static int elf_output_file(TCCState *s1, const char *filename)
1446 ElfW(Ehdr) ehdr;
1447 FILE *f;
1448 int fd, mode, ret;
1449 int *section_order;
1450 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
1451 unsigned long addr;
1452 Section *strsec, *s;
1453 ElfW(Shdr) shdr, *sh;
1454 ElfW(Phdr) *phdr, *ph;
1455 Section *interp, *dynamic, *dynstr;
1456 unsigned long saved_dynamic_data_offset;
1457 ElfW(Sym) *sym;
1458 int type, file_type;
1459 unsigned long rel_addr, rel_size;
1460 unsigned long bss_addr, bss_size;
1462 file_type = s1->output_type;
1463 s1->nb_errors = 0;
1465 if (file_type != TCC_OUTPUT_OBJ) {
1466 tcc_add_runtime(s1);
1469 phdr = NULL;
1470 section_order = NULL;
1471 interp = NULL;
1472 dynamic = NULL;
1473 dynstr = NULL; /* avoid warning */
1474 saved_dynamic_data_offset = 0; /* avoid warning */
1476 if (file_type != TCC_OUTPUT_OBJ) {
1477 relocate_common_syms();
1479 tcc_add_linker_symbols(s1);
1481 if (!s1->static_link) {
1482 const char *name;
1483 int sym_index, index;
1484 ElfW(Sym) *esym, *sym_end;
1486 if (file_type == TCC_OUTPUT_EXE) {
1487 char *ptr;
1488 /* allow override the dynamic loader */
1489 const char *elfint = getenv("LD_SO");
1490 if (elfint == NULL)
1491 elfint = elf_interp;
1492 /* add interpreter section only if executable */
1493 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1494 interp->sh_addralign = 1;
1495 ptr = section_ptr_add(interp, 1+strlen(elfint));
1496 strcpy(ptr, elfint);
1499 /* add dynamic symbol table */
1500 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1501 ".dynstr",
1502 ".hash", SHF_ALLOC);
1503 dynstr = s1->dynsym->link;
1505 /* add dynamic section */
1506 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1507 SHF_ALLOC | SHF_WRITE);
1508 dynamic->link = dynstr;
1509 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1511 /* add PLT */
1512 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1513 SHF_ALLOC | SHF_EXECINSTR);
1514 s1->plt->sh_entsize = 4;
1516 build_got(s1);
1518 /* scan for undefined symbols and see if they are in the
1519 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1520 is found, then we add it in the PLT. If a symbol
1521 STT_OBJECT is found, we add it in the .bss section with
1522 a suitable relocation */
1523 sym_end = (ElfW(Sym) *)(symtab_section->data +
1524 symtab_section->data_offset);
1525 if (file_type == TCC_OUTPUT_EXE) {
1526 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1527 sym < sym_end;
1528 sym++) {
1529 if (sym->st_shndx == SHN_UNDEF) {
1530 name = symtab_section->link->data + sym->st_name;
1531 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1532 if (sym_index) {
1533 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1534 type = ELFW(ST_TYPE)(esym->st_info);
1535 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1536 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1537 esym->st_info,
1538 sym - (ElfW(Sym) *)symtab_section->data);
1539 } else if (type == STT_OBJECT) {
1540 unsigned long offset;
1541 ElfW(Sym) *dynsym, *dynsym_end;
1542 offset = bss_section->data_offset;
1543 /* XXX: which alignment ? */
1544 offset = (offset + 16 - 1) & -16;
1545 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1546 esym->st_info, 0,
1547 bss_section->sh_num, name);
1548 /* Ensure symbol aliases (that is, symbols with
1549 the same st_value) resolve to the same
1550 address in program .bss or .data section. */
1551 dynsym_end = (ElfW(Sym) *)
1552 (s1->dynsymtab_section->data +
1553 s1->dynsymtab_section->data_offset);
1554 for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1555 dynsym < dynsym_end; dynsym++) {
1556 if (dynsym->st_value == esym->st_value) {
1557 char *dynname;
1558 dynname = s1->dynsymtab_section->link->data
1559 + dynsym->st_name;
1560 put_elf_sym(s1->dynsym, offset,
1561 dynsym->st_size,
1562 dynsym->st_info, 0,
1563 bss_section->sh_num,
1564 dynname);
1567 put_elf_reloc(s1->dynsym, bss_section,
1568 offset, R_COPY, index);
1569 offset += esym->st_size;
1570 bss_section->data_offset = offset;
1572 } else {
1573 /* STB_WEAK undefined symbols are accepted */
1574 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1575 it */
1576 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1577 !strcmp(name, "_fp_hw")) {
1578 } else {
1579 error_noabort("undefined symbol '%s'", name);
1582 } else if (s1->rdynamic &&
1583 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1584 /* if -rdynamic option, then export all non
1585 local symbols */
1586 name = symtab_section->link->data + sym->st_name;
1587 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1588 sym->st_info, 0,
1589 sym->st_shndx, name);
1593 if (s1->nb_errors)
1594 goto fail;
1596 /* now look at unresolved dynamic symbols and export
1597 corresponding symbol */
1598 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1599 s1->dynsymtab_section->data_offset);
1600 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1601 esym < sym_end;
1602 esym++) {
1603 if (esym->st_shndx == SHN_UNDEF) {
1604 name = s1->dynsymtab_section->link->data + esym->st_name;
1605 sym_index = find_elf_sym(symtab_section, name);
1606 if (sym_index) {
1607 /* XXX: avoid adding a symbol if already
1608 present because of -rdynamic ? */
1609 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1610 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1611 sym->st_info, 0,
1612 sym->st_shndx, name);
1613 } else {
1614 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1615 /* weak symbols can stay undefined */
1616 } else {
1617 warning("undefined dynamic symbol '%s'", name);
1622 } else {
1623 int nb_syms;
1624 /* shared library case : we simply export all the global symbols */
1625 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1626 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1627 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1628 sym < sym_end;
1629 sym++) {
1630 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1631 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1632 if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
1633 ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
1634 && sym->st_shndx == SHN_UNDEF) {
1635 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1636 sym->st_info,
1637 sym - (ElfW(Sym) *)symtab_section->data);
1639 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1640 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1641 sym->st_info,
1642 sym - (ElfW(Sym) *)symtab_section->data);
1644 else
1645 #endif
1647 name = symtab_section->link->data + sym->st_name;
1648 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1649 sym->st_info, 0,
1650 sym->st_shndx, name);
1651 s1->symtab_to_dynsym[sym -
1652 (ElfW(Sym) *)symtab_section->data] =
1653 index;
1659 build_got_entries(s1);
1661 /* add a list of needed dlls */
1662 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1663 DLLReference *dllref = s1->loaded_dlls[i];
1664 if (dllref->level == 0)
1665 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1668 if (s1->rpath)
1669 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1671 /* XXX: currently, since we do not handle PIC code, we
1672 must relocate the readonly segments */
1673 if (file_type == TCC_OUTPUT_DLL) {
1674 if (s1->soname)
1675 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1676 put_dt(dynamic, DT_TEXTREL, 0);
1679 if (s1->symbolic)
1680 put_dt(dynamic, DT_SYMBOLIC, 0);
1682 /* add necessary space for other entries */
1683 saved_dynamic_data_offset = dynamic->data_offset;
1684 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1685 } else {
1686 /* still need to build got entries in case of static link */
1687 build_got_entries(s1);
1691 memset(&ehdr, 0, sizeof(ehdr));
1693 /* we add a section for symbols */
1694 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1695 put_elf_str(strsec, "");
1697 /* compute number of sections */
1698 shnum = s1->nb_sections;
1700 /* this array is used to reorder sections in the output file */
1701 section_order = tcc_malloc(sizeof(int) * shnum);
1702 section_order[0] = 0;
1703 sh_order_index = 1;
1705 /* compute number of program headers */
1706 switch(file_type) {
1707 default:
1708 case TCC_OUTPUT_OBJ:
1709 phnum = 0;
1710 break;
1711 case TCC_OUTPUT_EXE:
1712 if (!s1->static_link)
1713 phnum = 4 + HAVE_PHDR;
1714 else
1715 phnum = 2;
1716 break;
1717 case TCC_OUTPUT_DLL:
1718 phnum = 3;
1719 break;
1722 /* allocate strings for section names and decide if an unallocated
1723 section should be output */
1724 /* NOTE: the strsec section comes last, so its size is also
1725 correct ! */
1726 for(i = 1; i < s1->nb_sections; i++) {
1727 s = s1->sections[i];
1728 s->sh_name = put_elf_str(strsec, s->name);
1729 #if 0 //gr
1730 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1731 s->sh_flags,
1732 s->sh_type,
1733 s->sh_info,
1734 s->name,
1735 s->reloc ? s->reloc->name : "n"
1737 #endif
1738 /* when generating a DLL, we include relocations but we may
1739 patch them */
1740 if (file_type == TCC_OUTPUT_DLL &&
1741 s->sh_type == SHT_RELX &&
1742 !(s->sh_flags & SHF_ALLOC)) {
1743 /* //gr: avoid bogus relocs for empty (debug) sections */
1744 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1745 prepare_dynamic_rel(s1, s);
1746 else if (s1->do_debug)
1747 s->sh_size = s->data_offset;
1748 } else if (s1->do_debug ||
1749 file_type == TCC_OUTPUT_OBJ ||
1750 (s->sh_flags & SHF_ALLOC) ||
1751 i == (s1->nb_sections - 1)) {
1752 /* we output all sections if debug or object file */
1753 s->sh_size = s->data_offset;
1757 /* allocate program segment headers */
1758 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1760 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1761 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1762 } else {
1763 file_offset = 0;
1765 if (phnum > 0) {
1766 /* compute section to program header mapping */
1767 if (s1->has_text_addr) {
1768 int a_offset, p_offset;
1769 addr = s1->text_addr;
1770 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1771 ELF_PAGE_SIZE */
1772 a_offset = addr & (s1->section_align - 1);
1773 p_offset = file_offset & (s1->section_align - 1);
1774 if (a_offset < p_offset)
1775 a_offset += s1->section_align;
1776 file_offset += (a_offset - p_offset);
1777 } else {
1778 if (file_type == TCC_OUTPUT_DLL)
1779 addr = 0;
1780 else
1781 addr = ELF_START_ADDR;
1782 /* compute address after headers */
1783 addr += (file_offset & (s1->section_align - 1));
1786 /* dynamic relocation table information, for .dynamic section */
1787 rel_size = 0;
1788 rel_addr = 0;
1790 bss_addr = bss_size = 0;
1791 /* leave one program header for the program interpreter */
1792 ph = &phdr[0];
1793 if (interp)
1794 ph += 1 + HAVE_PHDR;
1796 for(j = 0; j < 2; j++) {
1797 ph->p_type = PT_LOAD;
1798 if (j == 0)
1799 ph->p_flags = PF_R | PF_X;
1800 else
1801 ph->p_flags = PF_R | PF_W;
1802 ph->p_align = s1->section_align;
1804 /* we do the following ordering: interp, symbol tables,
1805 relocations, progbits, nobits */
1806 /* XXX: do faster and simpler sorting */
1807 for(k = 0; k < 5; k++) {
1808 for(i = 1; i < s1->nb_sections; i++) {
1809 s = s1->sections[i];
1810 /* compute if section should be included */
1811 if (j == 0) {
1812 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1813 SHF_ALLOC)
1814 continue;
1815 } else {
1816 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1817 (SHF_ALLOC | SHF_WRITE))
1818 continue;
1820 if (s == interp) {
1821 if (k != 0)
1822 continue;
1823 } else if (s->sh_type == SHT_DYNSYM ||
1824 s->sh_type == SHT_STRTAB ||
1825 s->sh_type == SHT_HASH) {
1826 if (k != 1)
1827 continue;
1828 } else if (s->sh_type == SHT_RELX) {
1829 if (k != 2)
1830 continue;
1831 } else if (s->sh_type == SHT_NOBITS) {
1832 if (k != 4)
1833 continue;
1834 } else {
1835 if (k != 3)
1836 continue;
1838 section_order[sh_order_index++] = i;
1840 /* section matches: we align it and add its size */
1841 tmp = addr;
1842 addr = (addr + s->sh_addralign - 1) &
1843 ~(s->sh_addralign - 1);
1844 file_offset += addr - tmp;
1845 s->sh_offset = file_offset;
1846 s->sh_addr = addr;
1848 /* update program header infos */
1849 if (ph->p_offset == 0) {
1850 ph->p_offset = file_offset;
1851 ph->p_vaddr = addr;
1852 ph->p_paddr = ph->p_vaddr;
1854 /* update dynamic relocation infos */
1855 if (s->sh_type == SHT_RELX) {
1856 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1857 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1858 rel_addr = addr;
1859 rel_size += s->sh_size; // XXX only first rel.
1861 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1862 bss_addr = addr;
1863 bss_size = s->sh_size; // XXX only first rel.
1865 #else
1866 if (rel_size == 0)
1867 rel_addr = addr;
1868 rel_size += s->sh_size;
1869 #endif
1871 addr += s->sh_size;
1872 if (s->sh_type != SHT_NOBITS)
1873 file_offset += s->sh_size;
1876 ph->p_filesz = file_offset - ph->p_offset;
1877 ph->p_memsz = addr - ph->p_vaddr;
1878 ph++;
1879 if (j == 0) {
1880 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1881 /* if in the middle of a page, we duplicate the page in
1882 memory so that one copy is RX and the other is RW */
1883 if ((addr & (s1->section_align - 1)) != 0)
1884 addr += s1->section_align;
1885 } else {
1886 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1887 file_offset = (file_offset + s1->section_align - 1) &
1888 ~(s1->section_align - 1);
1893 /* if interpreter, then add corresponing program header */
1894 if (interp) {
1895 ph = &phdr[0];
1897 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1899 int len = phnum * sizeof(ElfW(Phdr));
1901 ph->p_type = PT_PHDR;
1902 ph->p_offset = sizeof(ElfW(Ehdr));
1903 ph->p_vaddr = interp->sh_addr - len;
1904 ph->p_paddr = ph->p_vaddr;
1905 ph->p_filesz = ph->p_memsz = len;
1906 ph->p_flags = PF_R | PF_X;
1907 ph->p_align = 4; // interp->sh_addralign;
1908 ph++;
1910 #endif
1912 ph->p_type = PT_INTERP;
1913 ph->p_offset = interp->sh_offset;
1914 ph->p_vaddr = interp->sh_addr;
1915 ph->p_paddr = ph->p_vaddr;
1916 ph->p_filesz = interp->sh_size;
1917 ph->p_memsz = interp->sh_size;
1918 ph->p_flags = PF_R;
1919 ph->p_align = interp->sh_addralign;
1922 /* if dynamic section, then add corresponing program header */
1923 if (dynamic) {
1924 ElfW(Sym) *sym_end;
1926 ph = &phdr[phnum - 1];
1928 ph->p_type = PT_DYNAMIC;
1929 ph->p_offset = dynamic->sh_offset;
1930 ph->p_vaddr = dynamic->sh_addr;
1931 ph->p_paddr = ph->p_vaddr;
1932 ph->p_filesz = dynamic->sh_size;
1933 ph->p_memsz = dynamic->sh_size;
1934 ph->p_flags = PF_R | PF_W;
1935 ph->p_align = dynamic->sh_addralign;
1937 /* put GOT dynamic section address */
1938 put32(s1->got->data, dynamic->sh_addr);
1940 /* relocate the PLT */
1941 if (file_type == TCC_OUTPUT_EXE
1942 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1943 || file_type == TCC_OUTPUT_DLL
1944 #endif
1946 uint8_t *p, *p_end;
1948 p = s1->plt->data;
1949 p_end = p + s1->plt->data_offset;
1950 if (p < p_end) {
1951 #if defined(TCC_TARGET_I386)
1952 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1953 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1954 p += 16;
1955 while (p < p_end) {
1956 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1957 p += 16;
1959 #elif defined(TCC_TARGET_X86_64)
1960 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1961 put32(p + 2, get32(p + 2) + x);
1962 put32(p + 8, get32(p + 8) + x - 6);
1963 p += 16;
1964 while (p < p_end) {
1965 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1966 p += 16;
1968 #elif defined(TCC_TARGET_ARM)
1969 int x;
1970 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1971 p +=16;
1972 while (p < p_end) {
1973 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1974 p += 16;
1976 #elif defined(TCC_TARGET_C67)
1977 /* XXX: TODO */
1978 #else
1979 #error unsupported CPU
1980 #endif
1984 /* relocate symbols in .dynsym */
1985 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
1986 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
1987 sym < sym_end;
1988 sym++) {
1989 if (sym->st_shndx == SHN_UNDEF) {
1990 /* relocate to the PLT if the symbol corresponds
1991 to a PLT entry */
1992 if (sym->st_value)
1993 sym->st_value += s1->plt->sh_addr;
1994 } else if (sym->st_shndx < SHN_LORESERVE) {
1995 /* do symbol relocation */
1996 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
2000 /* put dynamic section entries */
2001 dynamic->data_offset = saved_dynamic_data_offset;
2002 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
2003 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
2004 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2005 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
2006 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2007 #ifdef TCC_TARGET_X86_64
2008 put_dt(dynamic, DT_RELA, rel_addr);
2009 put_dt(dynamic, DT_RELASZ, rel_size);
2010 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2011 #else
2012 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2013 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2014 put_dt(dynamic, DT_PLTRELSZ, rel_size);
2015 put_dt(dynamic, DT_JMPREL, rel_addr);
2016 put_dt(dynamic, DT_PLTREL, DT_REL);
2017 put_dt(dynamic, DT_REL, bss_addr);
2018 put_dt(dynamic, DT_RELSZ, bss_size);
2019 #else
2020 put_dt(dynamic, DT_REL, rel_addr);
2021 put_dt(dynamic, DT_RELSZ, rel_size);
2022 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2023 #endif
2024 #endif
2025 if (s1->do_debug)
2026 put_dt(dynamic, DT_DEBUG, 0);
2027 put_dt(dynamic, DT_NULL, 0);
2030 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2031 ehdr.e_phnum = phnum;
2032 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2035 /* all other sections come after */
2036 for(i = 1; i < s1->nb_sections; i++) {
2037 s = s1->sections[i];
2038 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2039 continue;
2040 section_order[sh_order_index++] = i;
2042 file_offset = (file_offset + s->sh_addralign - 1) &
2043 ~(s->sh_addralign - 1);
2044 s->sh_offset = file_offset;
2045 if (s->sh_type != SHT_NOBITS)
2046 file_offset += s->sh_size;
2049 /* if building executable or DLL, then relocate each section
2050 except the GOT which is already relocated */
2051 if (file_type != TCC_OUTPUT_OBJ) {
2052 relocate_syms(s1, 0);
2054 if (s1->nb_errors != 0) {
2055 fail:
2056 ret = -1;
2057 goto the_end;
2060 /* relocate sections */
2061 /* XXX: ignore sections with allocated relocations ? */
2062 for(i = 1; i < s1->nb_sections; i++) {
2063 s = s1->sections[i];
2064 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
2065 relocate_section(s1, s);
2068 /* relocate relocation entries if the relocation tables are
2069 allocated in the executable */
2070 for(i = 1; i < s1->nb_sections; i++) {
2071 s = s1->sections[i];
2072 if ((s->sh_flags & SHF_ALLOC) &&
2073 s->sh_type == SHT_RELX) {
2074 relocate_rel(s1, s);
2078 /* get entry point address */
2079 if (file_type == TCC_OUTPUT_EXE)
2080 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
2081 else
2082 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2084 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2085 fill_got(s1);
2087 /* write elf file */
2088 if (file_type == TCC_OUTPUT_OBJ)
2089 mode = 0666;
2090 else
2091 mode = 0777;
2092 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2093 if (fd < 0) {
2094 error_noabort("could not write '%s'", filename);
2095 goto fail;
2097 f = fdopen(fd, "wb");
2098 if (s1->verbose)
2099 printf("<- %s\n", filename);
2101 #ifdef TCC_TARGET_COFF
2102 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2103 tcc_output_coff(s1, f);
2104 } else
2105 #endif
2106 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2107 sort_syms(s1, symtab_section);
2109 /* align to 4 */
2110 file_offset = (file_offset + 3) & -4;
2112 /* fill header */
2113 ehdr.e_ident[0] = ELFMAG0;
2114 ehdr.e_ident[1] = ELFMAG1;
2115 ehdr.e_ident[2] = ELFMAG2;
2116 ehdr.e_ident[3] = ELFMAG3;
2117 ehdr.e_ident[4] = TCC_ELFCLASS;
2118 ehdr.e_ident[5] = ELFDATA2LSB;
2119 ehdr.e_ident[6] = EV_CURRENT;
2120 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2121 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2122 #endif
2123 #ifdef TCC_TARGET_ARM
2124 #ifdef TCC_ARM_EABI
2125 ehdr.e_ident[EI_OSABI] = 0;
2126 ehdr.e_flags = 4 << 24;
2127 #else
2128 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2129 #endif
2130 #endif
2131 switch(file_type) {
2132 default:
2133 case TCC_OUTPUT_EXE:
2134 ehdr.e_type = ET_EXEC;
2135 break;
2136 case TCC_OUTPUT_DLL:
2137 ehdr.e_type = ET_DYN;
2138 break;
2139 case TCC_OUTPUT_OBJ:
2140 ehdr.e_type = ET_REL;
2141 break;
2143 ehdr.e_machine = EM_TCC_TARGET;
2144 ehdr.e_version = EV_CURRENT;
2145 ehdr.e_shoff = file_offset;
2146 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2147 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2148 ehdr.e_shnum = shnum;
2149 ehdr.e_shstrndx = shnum - 1;
2151 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2152 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2153 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2155 for(i=1;i<s1->nb_sections;i++) {
2156 s = s1->sections[section_order[i]];
2157 if (s->sh_type != SHT_NOBITS) {
2158 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2159 if (s->sh_type == SHT_DYNSYM)
2160 patch_dynsym_undef(s1, s);
2161 #endif
2162 while (offset < s->sh_offset) {
2163 fputc(0, f);
2164 offset++;
2166 size = s->sh_size;
2167 fwrite(s->data, 1, size, f);
2168 offset += size;
2172 /* output section headers */
2173 while (offset < ehdr.e_shoff) {
2174 fputc(0, f);
2175 offset++;
2178 for(i=0;i<s1->nb_sections;i++) {
2179 sh = &shdr;
2180 memset(sh, 0, sizeof(ElfW(Shdr)));
2181 s = s1->sections[i];
2182 if (s) {
2183 sh->sh_name = s->sh_name;
2184 sh->sh_type = s->sh_type;
2185 sh->sh_flags = s->sh_flags;
2186 sh->sh_entsize = s->sh_entsize;
2187 sh->sh_info = s->sh_info;
2188 if (s->link)
2189 sh->sh_link = s->link->sh_num;
2190 sh->sh_addralign = s->sh_addralign;
2191 sh->sh_addr = s->sh_addr;
2192 sh->sh_offset = s->sh_offset;
2193 sh->sh_size = s->sh_size;
2195 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2197 } else {
2198 tcc_output_binary(s1, f, section_order);
2200 fclose(f);
2202 ret = 0;
2203 the_end:
2204 tcc_free(s1->symtab_to_dynsym);
2205 tcc_free(section_order);
2206 tcc_free(phdr);
2207 tcc_free(s1->got_offsets);
2208 return ret;
2211 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2213 int ret;
2214 #ifdef TCC_TARGET_PE
2215 if (s->output_type != TCC_OUTPUT_OBJ) {
2216 ret = pe_output_file(s, filename);
2217 } else
2218 #endif
2220 ret = elf_output_file(s, filename);
2222 return ret;
2225 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2227 void *data;
2229 data = tcc_malloc(size);
2230 lseek(fd, file_offset, SEEK_SET);
2231 read(fd, data, size);
2232 return data;
2235 typedef struct SectionMergeInfo {
2236 Section *s; /* corresponding existing section */
2237 unsigned long offset; /* offset of the new section in the existing section */
2238 uint8_t new_section; /* true if section 's' was added */
2239 uint8_t link_once; /* true if link once section */
2240 } SectionMergeInfo;
2242 /* load an object file and merge it with current files */
2243 /* XXX: handle correctly stab (debug) info */
2244 ST_FUNC int tcc_load_object_file(TCCState *s1,
2245 int fd, unsigned long file_offset)
2247 ElfW(Ehdr) ehdr;
2248 ElfW(Shdr) *shdr, *sh;
2249 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2250 unsigned char *strsec, *strtab;
2251 int *old_to_new_syms;
2252 char *sh_name, *name;
2253 SectionMergeInfo *sm_table, *sm;
2254 ElfW(Sym) *sym, *symtab;
2255 ElfW_Rel *rel, *rel_end;
2256 Section *s;
2258 int stab_index;
2259 int stabstr_index;
2261 stab_index = stabstr_index = 0;
2263 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2264 goto fail1;
2265 if (ehdr.e_ident[0] != ELFMAG0 ||
2266 ehdr.e_ident[1] != ELFMAG1 ||
2267 ehdr.e_ident[2] != ELFMAG2 ||
2268 ehdr.e_ident[3] != ELFMAG3)
2269 goto fail1;
2270 /* test if object file */
2271 if (ehdr.e_type != ET_REL)
2272 goto fail1;
2273 /* test CPU specific stuff */
2274 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2275 ehdr.e_machine != EM_TCC_TARGET) {
2276 fail1:
2277 error_noabort("invalid object file");
2278 return -1;
2280 /* read sections */
2281 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2282 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2283 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2285 /* load section names */
2286 sh = &shdr[ehdr.e_shstrndx];
2287 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2289 /* load symtab and strtab */
2290 old_to_new_syms = NULL;
2291 symtab = NULL;
2292 strtab = NULL;
2293 nb_syms = 0;
2294 for(i = 1; i < ehdr.e_shnum; i++) {
2295 sh = &shdr[i];
2296 if (sh->sh_type == SHT_SYMTAB) {
2297 if (symtab) {
2298 error_noabort("object must contain only one symtab");
2299 fail:
2300 ret = -1;
2301 goto the_end;
2303 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2304 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2305 sm_table[i].s = symtab_section;
2307 /* now load strtab */
2308 sh = &shdr[sh->sh_link];
2309 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2313 /* now examine each section and try to merge its content with the
2314 ones in memory */
2315 for(i = 1; i < ehdr.e_shnum; i++) {
2316 /* no need to examine section name strtab */
2317 if (i == ehdr.e_shstrndx)
2318 continue;
2319 sh = &shdr[i];
2320 sh_name = strsec + sh->sh_name;
2321 /* ignore sections types we do not handle */
2322 if (sh->sh_type != SHT_PROGBITS &&
2323 sh->sh_type != SHT_RELX &&
2324 #ifdef TCC_ARM_EABI
2325 sh->sh_type != SHT_ARM_EXIDX &&
2326 #endif
2327 sh->sh_type != SHT_NOBITS &&
2328 sh->sh_type != SHT_PREINIT_ARRAY &&
2329 sh->sh_type != SHT_INIT_ARRAY &&
2330 sh->sh_type != SHT_FINI_ARRAY &&
2331 strcmp(sh_name, ".stabstr")
2333 continue;
2334 if (sh->sh_addralign < 1)
2335 sh->sh_addralign = 1;
2336 /* find corresponding section, if any */
2337 for(j = 1; j < s1->nb_sections;j++) {
2338 s = s1->sections[j];
2339 if (!strcmp(s->name, sh_name)) {
2340 if (!strncmp(sh_name, ".gnu.linkonce",
2341 sizeof(".gnu.linkonce") - 1)) {
2342 /* if a 'linkonce' section is already present, we
2343 do not add it again. It is a little tricky as
2344 symbols can still be defined in
2345 it. */
2346 sm_table[i].link_once = 1;
2347 goto next;
2348 } else {
2349 goto found;
2353 /* not found: create new section */
2354 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2355 /* take as much info as possible from the section. sh_link and
2356 sh_info will be updated later */
2357 s->sh_addralign = sh->sh_addralign;
2358 s->sh_entsize = sh->sh_entsize;
2359 sm_table[i].new_section = 1;
2360 found:
2361 if (sh->sh_type != s->sh_type) {
2362 error_noabort("invalid section type");
2363 goto fail;
2366 /* align start of section */
2367 offset = s->data_offset;
2369 if (0 == strcmp(sh_name, ".stab")) {
2370 stab_index = i;
2371 goto no_align;
2373 if (0 == strcmp(sh_name, ".stabstr")) {
2374 stabstr_index = i;
2375 goto no_align;
2378 size = sh->sh_addralign - 1;
2379 offset = (offset + size) & ~size;
2380 if (sh->sh_addralign > s->sh_addralign)
2381 s->sh_addralign = sh->sh_addralign;
2382 s->data_offset = offset;
2383 no_align:
2384 sm_table[i].offset = offset;
2385 sm_table[i].s = s;
2386 /* concatenate sections */
2387 size = sh->sh_size;
2388 if (sh->sh_type != SHT_NOBITS) {
2389 unsigned char *ptr;
2390 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2391 ptr = section_ptr_add(s, size);
2392 read(fd, ptr, size);
2393 } else {
2394 s->data_offset += size;
2396 next: ;
2399 /* //gr relocate stab strings */
2400 if (stab_index && stabstr_index) {
2401 Stab_Sym *a, *b;
2402 unsigned o;
2403 s = sm_table[stab_index].s;
2404 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2405 b = (Stab_Sym *)(s->data + s->data_offset);
2406 o = sm_table[stabstr_index].offset;
2407 while (a < b)
2408 a->n_strx += o, a++;
2411 /* second short pass to update sh_link and sh_info fields of new
2412 sections */
2413 for(i = 1; i < ehdr.e_shnum; i++) {
2414 s = sm_table[i].s;
2415 if (!s || !sm_table[i].new_section)
2416 continue;
2417 sh = &shdr[i];
2418 if (sh->sh_link > 0)
2419 s->link = sm_table[sh->sh_link].s;
2420 if (sh->sh_type == SHT_RELX) {
2421 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2422 /* update backward link */
2423 s1->sections[s->sh_info]->reloc = s;
2426 sm = sm_table;
2428 /* resolve symbols */
2429 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2431 sym = symtab + 1;
2432 for(i = 1; i < nb_syms; i++, sym++) {
2433 if (sym->st_shndx != SHN_UNDEF &&
2434 sym->st_shndx < SHN_LORESERVE) {
2435 sm = &sm_table[sym->st_shndx];
2436 if (sm->link_once) {
2437 /* if a symbol is in a link once section, we use the
2438 already defined symbol. It is very important to get
2439 correct relocations */
2440 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2441 name = strtab + sym->st_name;
2442 sym_index = find_elf_sym(symtab_section, name);
2443 if (sym_index)
2444 old_to_new_syms[i] = sym_index;
2446 continue;
2448 /* if no corresponding section added, no need to add symbol */
2449 if (!sm->s)
2450 continue;
2451 /* convert section number */
2452 sym->st_shndx = sm->s->sh_num;
2453 /* offset value */
2454 sym->st_value += sm->offset;
2456 /* add symbol */
2457 name = strtab + sym->st_name;
2458 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2459 sym->st_info, sym->st_other,
2460 sym->st_shndx, name);
2461 old_to_new_syms[i] = sym_index;
2464 /* third pass to patch relocation entries */
2465 for(i = 1; i < ehdr.e_shnum; i++) {
2466 s = sm_table[i].s;
2467 if (!s)
2468 continue;
2469 sh = &shdr[i];
2470 offset = sm_table[i].offset;
2471 switch(s->sh_type) {
2472 case SHT_RELX:
2473 /* take relocation offset information */
2474 offseti = sm_table[sh->sh_info].offset;
2475 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2476 for(rel = (ElfW_Rel *)(s->data + offset);
2477 rel < rel_end;
2478 rel++) {
2479 int type;
2480 unsigned sym_index;
2481 /* convert symbol index */
2482 type = ELFW(R_TYPE)(rel->r_info);
2483 sym_index = ELFW(R_SYM)(rel->r_info);
2484 /* NOTE: only one symtab assumed */
2485 if (sym_index >= nb_syms)
2486 goto invalid_reloc;
2487 sym_index = old_to_new_syms[sym_index];
2488 /* ignore link_once in rel section. */
2489 if (!sym_index && !sm->link_once
2490 #ifdef TCC_TARGET_ARM
2491 && type != R_ARM_V4BX
2492 #endif
2494 invalid_reloc:
2495 error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2496 i, strsec + sh->sh_name, rel->r_offset);
2497 goto fail;
2499 rel->r_info = ELFW(R_INFO)(sym_index, type);
2500 /* offset the relocation offset */
2501 rel->r_offset += offseti;
2503 break;
2504 default:
2505 break;
2509 ret = 0;
2510 the_end:
2511 tcc_free(symtab);
2512 tcc_free(strtab);
2513 tcc_free(old_to_new_syms);
2514 tcc_free(sm_table);
2515 tcc_free(strsec);
2516 tcc_free(shdr);
2517 return ret;
2520 typedef struct ArchiveHeader {
2521 char ar_name[16]; /* name of this member */
2522 char ar_date[12]; /* file mtime */
2523 char ar_uid[6]; /* owner uid; printed as decimal */
2524 char ar_gid[6]; /* owner gid; printed as decimal */
2525 char ar_mode[8]; /* file mode, printed as octal */
2526 char ar_size[10]; /* file size, printed as decimal */
2527 char ar_fmag[2]; /* should contain ARFMAG */
2528 } ArchiveHeader;
2530 static int get_be32(const uint8_t *b)
2532 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2535 /* load only the objects which resolve undefined symbols */
2536 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2538 int i, bound, nsyms, sym_index, off, ret;
2539 uint8_t *data;
2540 const char *ar_names, *p;
2541 const uint8_t *ar_index;
2542 ElfW(Sym) *sym;
2544 data = tcc_malloc(size);
2545 if (read(fd, data, size) != size)
2546 goto fail;
2547 nsyms = get_be32(data);
2548 ar_index = data + 4;
2549 ar_names = ar_index + nsyms * 4;
2551 do {
2552 bound = 0;
2553 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2554 sym_index = find_elf_sym(symtab_section, p);
2555 if(sym_index) {
2556 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2557 if(sym->st_shndx == SHN_UNDEF) {
2558 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2559 #if 0
2560 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2561 #endif
2562 ++bound;
2563 lseek(fd, off, SEEK_SET);
2564 if(tcc_load_object_file(s1, fd, off) < 0) {
2565 fail:
2566 ret = -1;
2567 goto the_end;
2572 } while(bound);
2573 ret = 0;
2574 the_end:
2575 tcc_free(data);
2576 return ret;
2579 /* load a '.a' file */
2580 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2582 ArchiveHeader hdr;
2583 char ar_size[11];
2584 char ar_name[17];
2585 char magic[8];
2586 int size, len, i;
2587 unsigned long file_offset;
2589 /* skip magic which was already checked */
2590 read(fd, magic, sizeof(magic));
2592 for(;;) {
2593 len = read(fd, &hdr, sizeof(hdr));
2594 if (len == 0)
2595 break;
2596 if (len != sizeof(hdr)) {
2597 error_noabort("invalid archive");
2598 return -1;
2600 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2601 ar_size[sizeof(hdr.ar_size)] = '\0';
2602 size = strtol(ar_size, NULL, 0);
2603 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2604 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2605 if (ar_name[i] != ' ')
2606 break;
2608 ar_name[i + 1] = '\0';
2609 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2610 file_offset = lseek(fd, 0, SEEK_CUR);
2611 /* align to even */
2612 size = (size + 1) & ~1;
2613 if (!strcmp(ar_name, "/")) {
2614 /* coff symbol table : we handle it */
2615 if(s1->alacarte_link)
2616 return tcc_load_alacarte(s1, fd, size);
2617 } else if (!strcmp(ar_name, "//") ||
2618 !strcmp(ar_name, "__.SYMDEF") ||
2619 !strcmp(ar_name, "__.SYMDEF/") ||
2620 !strcmp(ar_name, "ARFILENAMES/")) {
2621 /* skip symbol table or archive names */
2622 } else {
2623 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2624 return -1;
2626 lseek(fd, file_offset + size, SEEK_SET);
2628 return 0;
2631 #ifndef TCC_TARGET_PE
2632 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2633 is referenced by the user (so it should be added as DT_NEEDED in
2634 the generated ELF file) */
2635 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2637 ElfW(Ehdr) ehdr;
2638 ElfW(Shdr) *shdr, *sh, *sh1;
2639 int i, j, nb_syms, nb_dts, sym_bind, ret;
2640 ElfW(Sym) *sym, *dynsym;
2641 ElfW(Dyn) *dt, *dynamic;
2642 unsigned char *dynstr;
2643 const char *name, *soname;
2644 DLLReference *dllref;
2646 read(fd, &ehdr, sizeof(ehdr));
2648 /* test CPU specific stuff */
2649 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2650 ehdr.e_machine != EM_TCC_TARGET) {
2651 error_noabort("bad architecture");
2652 return -1;
2655 /* read sections */
2656 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2658 /* load dynamic section and dynamic symbols */
2659 nb_syms = 0;
2660 nb_dts = 0;
2661 dynamic = NULL;
2662 dynsym = NULL; /* avoid warning */
2663 dynstr = NULL; /* avoid warning */
2664 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2665 switch(sh->sh_type) {
2666 case SHT_DYNAMIC:
2667 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2668 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2669 break;
2670 case SHT_DYNSYM:
2671 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2672 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2673 sh1 = &shdr[sh->sh_link];
2674 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2675 break;
2676 default:
2677 break;
2681 /* compute the real library name */
2682 soname = tcc_basename(filename);
2684 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2685 if (dt->d_tag == DT_SONAME) {
2686 soname = dynstr + dt->d_un.d_val;
2690 /* if the dll is already loaded, do not load it */
2691 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2692 dllref = s1->loaded_dlls[i];
2693 if (!strcmp(soname, dllref->name)) {
2694 /* but update level if needed */
2695 if (level < dllref->level)
2696 dllref->level = level;
2697 ret = 0;
2698 goto the_end;
2702 // printf("loading dll '%s'\n", soname);
2704 /* add the dll and its level */
2705 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2706 dllref->level = level;
2707 strcpy(dllref->name, soname);
2708 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2710 /* add dynamic symbols in dynsym_section */
2711 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2712 sym_bind = ELFW(ST_BIND)(sym->st_info);
2713 if (sym_bind == STB_LOCAL)
2714 continue;
2715 name = dynstr + sym->st_name;
2716 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2717 sym->st_info, sym->st_other, sym->st_shndx, name);
2720 /* load all referenced DLLs */
2721 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2722 switch(dt->d_tag) {
2723 case DT_NEEDED:
2724 name = dynstr + dt->d_un.d_val;
2725 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2726 dllref = s1->loaded_dlls[j];
2727 if (!strcmp(name, dllref->name))
2728 goto already_loaded;
2730 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2731 error_noabort("referenced dll '%s' not found", name);
2732 ret = -1;
2733 goto the_end;
2735 already_loaded:
2736 break;
2739 ret = 0;
2740 the_end:
2741 tcc_free(dynstr);
2742 tcc_free(dynsym);
2743 tcc_free(dynamic);
2744 tcc_free(shdr);
2745 return ret;
2748 #define LD_TOK_NAME 256
2749 #define LD_TOK_EOF (-1)
2751 /* return next ld script token */
2752 static int ld_next(TCCState *s1, char *name, int name_size)
2754 int c;
2755 char *q;
2757 redo:
2758 switch(ch) {
2759 case ' ':
2760 case '\t':
2761 case '\f':
2762 case '\v':
2763 case '\r':
2764 case '\n':
2765 inp();
2766 goto redo;
2767 case '/':
2768 minp();
2769 if (ch == '*') {
2770 file->buf_ptr = parse_comment(file->buf_ptr);
2771 ch = file->buf_ptr[0];
2772 goto redo;
2773 } else {
2774 q = name;
2775 *q++ = '/';
2776 goto parse_name;
2778 break;
2779 /* case 'a' ... 'z': */
2780 case 'a':
2781 case 'b':
2782 case 'c':
2783 case 'd':
2784 case 'e':
2785 case 'f':
2786 case 'g':
2787 case 'h':
2788 case 'i':
2789 case 'j':
2790 case 'k':
2791 case 'l':
2792 case 'm':
2793 case 'n':
2794 case 'o':
2795 case 'p':
2796 case 'q':
2797 case 'r':
2798 case 's':
2799 case 't':
2800 case 'u':
2801 case 'v':
2802 case 'w':
2803 case 'x':
2804 case 'y':
2805 case 'z':
2806 /* case 'A' ... 'z': */
2807 case 'A':
2808 case 'B':
2809 case 'C':
2810 case 'D':
2811 case 'E':
2812 case 'F':
2813 case 'G':
2814 case 'H':
2815 case 'I':
2816 case 'J':
2817 case 'K':
2818 case 'L':
2819 case 'M':
2820 case 'N':
2821 case 'O':
2822 case 'P':
2823 case 'Q':
2824 case 'R':
2825 case 'S':
2826 case 'T':
2827 case 'U':
2828 case 'V':
2829 case 'W':
2830 case 'X':
2831 case 'Y':
2832 case 'Z':
2833 case '_':
2834 case '\\':
2835 case '.':
2836 case '$':
2837 case '~':
2838 q = name;
2839 parse_name:
2840 for(;;) {
2841 if (!((ch >= 'a' && ch <= 'z') ||
2842 (ch >= 'A' && ch <= 'Z') ||
2843 (ch >= '0' && ch <= '9') ||
2844 strchr("/.-_+=$:\\,~", ch)))
2845 break;
2846 if ((q - name) < name_size - 1) {
2847 *q++ = ch;
2849 minp();
2851 *q = '\0';
2852 c = LD_TOK_NAME;
2853 break;
2854 case CH_EOF:
2855 c = LD_TOK_EOF;
2856 break;
2857 default:
2858 c = ch;
2859 inp();
2860 break;
2862 #if 0
2863 printf("tok=%c %d\n", c, c);
2864 if (c == LD_TOK_NAME)
2865 printf(" name=%s\n", name);
2866 #endif
2867 return c;
2870 char *tcc_strcpy_part(char *out, const char *in, size_t num)
2872 memcpy(out, in, num);
2873 out[num] = '\0';
2874 return out;
2878 * Extract the library name from the file name
2879 * Return 0 if the file isn't a library
2881 * /!\ No test on filename capacity, be careful
2883 static int filename_to_libname(TCCState *s1, const char filename[], char libname[])
2885 char *ext;
2886 int libprefix;
2888 /* already converted to library name */
2889 if (libname[0] != '\0')
2890 return 1;
2891 ext = tcc_fileextension(filename);
2892 if (*ext == '\0')
2893 return 0;
2894 libprefix = !strncmp(filename, "lib", 3);
2895 if (!s1->static_link) {
2896 #ifdef TCC_TARGET_PE
2897 if (!strcmp(ext, ".def")) {
2898 size_t len = ext - filename;
2899 tcc_strcpy_part(libname, filename, len);
2900 return 1;
2902 #else
2903 if (libprefix && (!strcmp(ext, ".so"))) {
2904 size_t len = ext - filename - 3;
2905 tcc_strcpy_part(libname, filename + 3, len);
2906 return 1;
2908 #endif
2909 } else {
2910 if (libprefix && (!strcmp(ext, ".a"))) {
2911 size_t len = ext - filename - 3;
2912 tcc_strcpy_part(libname, filename + 3, len);
2913 return 1;
2916 return 0;
2920 * Extract the file name from the library name
2922 * /!\ No test on filename capacity, be careful
2924 static void libname_to_filename(TCCState *s1, const char libname[], char filename[])
2926 if (!s1->static_link) {
2927 #ifdef TCC_TARGET_PE
2928 sprintf(filename, "%s.def", libname);
2929 #else
2930 sprintf(filename, "lib%s.so", libname);
2931 #endif
2932 } else {
2933 sprintf(filename, "lib%s.a", libname);
2937 static int ld_add_file(TCCState *s1, const char filename[], char libname[])
2939 int ret;
2941 ret = tcc_add_file_internal(s1, filename, 0);
2942 if (ret) {
2943 if (filename_to_libname(s1, filename, libname))
2944 ret = tcc_add_library(s1, libname);
2946 return ret;
2949 static inline int new_undef_syms(void)
2951 int ret = 0;
2952 ret = new_undef_sym;
2953 new_undef_sym = 0;
2954 return ret;
2957 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
2959 char filename[1024], libname[1024];
2960 int t, group, nblibs = 0, ret = 0;
2961 char **libs = NULL;
2963 group = !strcmp(cmd, "GROUP");
2964 if (!as_needed)
2965 new_undef_syms();
2966 t = ld_next(s1, filename, sizeof(filename));
2967 if (t != '(')
2968 expect("(");
2969 t = ld_next(s1, filename, sizeof(filename));
2970 for(;;) {
2971 libname[0] = '\0';
2972 if (t == LD_TOK_EOF) {
2973 error_noabort("unexpected end of file");
2974 ret = -1;
2975 goto lib_parse_error;
2976 } else if (t == ')') {
2977 break;
2978 } else if (t == '-') {
2979 t = ld_next(s1, filename, sizeof(filename));
2980 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
2981 error_noabort("library name expected");
2982 ret = -1;
2983 goto lib_parse_error;
2985 strcpy(libname, &filename[1]);
2986 libname_to_filename(s1, libname, filename);
2987 } else if (t != LD_TOK_NAME) {
2988 error_noabort("filename expected");
2989 ret = -1;
2990 goto lib_parse_error;
2992 if (!strcmp(filename, "AS_NEEDED")) {
2993 ret = ld_add_file_list(s1, cmd, 1);
2994 if (ret)
2995 goto lib_parse_error;
2996 } else {
2997 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2998 if (!as_needed) {
2999 ret = ld_add_file(s1, filename, libname);
3000 if (ret)
3001 goto lib_parse_error;
3002 if (group) {
3003 /* Add the filename *and* the libname to avoid future conversions */
3004 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
3005 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
3009 t = ld_next(s1, filename, sizeof(filename));
3010 if (t == ',') {
3011 t = ld_next(s1, filename, sizeof(filename));
3014 if (group && !as_needed) {
3015 while (new_undef_syms()) {
3016 int i;
3018 for (i = 0; i < nblibs; i += 2)
3019 ld_add_file(s1, libs[i], libs[i+1]);
3022 lib_parse_error:
3023 dynarray_reset(&libs, &nblibs);
3024 return ret;
3027 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3028 files */
3029 ST_FUNC int tcc_load_ldscript(TCCState *s1)
3031 char cmd[64];
3032 char filename[1024];
3033 int t, ret;
3035 ch = file->buf_ptr[0];
3036 ch = handle_eob();
3037 for(;;) {
3038 t = ld_next(s1, cmd, sizeof(cmd));
3039 if (t == LD_TOK_EOF)
3040 return 0;
3041 else if (t != LD_TOK_NAME)
3042 return -1;
3043 if (!strcmp(cmd, "INPUT") ||
3044 !strcmp(cmd, "GROUP")) {
3045 ret = ld_add_file_list(s1, cmd, 0);
3046 if (ret)
3047 return ret;
3048 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3049 !strcmp(cmd, "TARGET")) {
3050 /* ignore some commands */
3051 t = ld_next(s1, cmd, sizeof(cmd));
3052 if (t != '(')
3053 expect("(");
3054 for(;;) {
3055 t = ld_next(s1, filename, sizeof(filename));
3056 if (t == LD_TOK_EOF) {
3057 error_noabort("unexpected end of file");
3058 return -1;
3059 } else if (t == ')') {
3060 break;
3063 } else {
3064 return -1;
3067 return 0;
3069 #endif