ARM: implement rt_get_caller_pc
[tinycc.git] / tccelf.c
blob037615a0c75309679098aaa675fb4b6c0f53e486
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 default:
664 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
665 type,addr,(unsigned int)(long)ptr,val);
666 break;
667 #elif defined(TCC_TARGET_C67)
668 case R_C60_32:
669 *(int *)ptr += val;
670 break;
671 case R_C60LO16:
673 uint32_t orig;
675 /* put the low 16 bits of the absolute address */
676 // add to what is already there
678 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
679 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
681 //patch both at once - assumes always in pairs Low - High
683 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
684 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
686 break;
687 case R_C60HI16:
688 break;
689 default:
690 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
691 type,addr,(unsigned int)(long)ptr, val);
692 break;
693 #elif defined(TCC_TARGET_X86_64)
694 case R_X86_64_64:
695 if (s1->output_type == TCC_OUTPUT_DLL) {
696 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
697 qrel->r_addend = *(long long *)ptr + val;
698 qrel++;
700 *(long long *)ptr += val;
701 break;
702 case R_X86_64_32:
703 case R_X86_64_32S:
704 if (s1->output_type == TCC_OUTPUT_DLL) {
705 /* XXX: this logic may depend on TCC's codegen
706 now TCC uses R_X86_64_32 even for a 64bit pointer */
707 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
708 qrel->r_addend = *(int *)ptr + val;
709 qrel++;
711 *(int *)ptr += val;
712 break;
713 case R_X86_64_PC32: {
714 long long diff;
715 if (s1->output_type == TCC_OUTPUT_DLL) {
716 /* DLL relocation */
717 esym_index = s1->symtab_to_dynsym[sym_index];
718 if (esym_index) {
719 qrel->r_offset = rel->r_offset;
720 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
721 qrel->r_addend = *(int *)ptr;
722 qrel++;
723 break;
726 diff = (long long)val - addr;
727 if (diff <= -2147483647 || diff > 2147483647) {
728 #ifndef TCC_TARGET_PE
729 /* XXX: naive support for over 32bit jump */
730 if (s1->output_type == TCC_OUTPUT_MEMORY) {
731 val = add_jmp_table(s1, val);
732 diff = val - addr;
734 #endif
735 if (diff <= -2147483647 || diff > 2147483647) {
736 error("internal error: relocation failed");
739 *(int *)ptr += diff;
741 break;
742 case R_X86_64_PLT32:
743 *(int *)ptr += val - addr;
744 break;
745 case R_X86_64_GLOB_DAT:
746 case R_X86_64_JUMP_SLOT:
747 *(int *)ptr = val;
748 break;
749 case R_X86_64_GOTPCREL:
750 #ifndef TCC_TARGET_PE
751 if (s1->output_type == TCC_OUTPUT_MEMORY) {
752 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
753 *(int *)ptr += val - addr;
754 break;
756 #endif
757 *(int *)ptr += (s1->got->sh_addr - addr +
758 s1->got_offsets[sym_index] - 4);
759 break;
760 case R_X86_64_GOTTPOFF:
761 *(int *)ptr += val - s1->got->sh_addr;
762 break;
763 case R_X86_64_GOT32:
764 /* we load the got offset */
765 *(int *)ptr += s1->got_offsets[sym_index];
766 break;
767 #else
768 #error unsupported processor
769 #endif
772 /* if the relocation is allocated, we change its symbol table */
773 if (sr->sh_flags & SHF_ALLOC)
774 sr->link = s1->dynsym;
777 /* relocate relocation table in 'sr' */
778 static void relocate_rel(TCCState *s1, Section *sr)
780 Section *s;
781 ElfW_Rel *rel, *rel_end;
783 s = s1->sections[sr->sh_info];
784 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
785 for(rel = (ElfW_Rel *)sr->data;
786 rel < rel_end;
787 rel++) {
788 rel->r_offset += s->sh_addr;
792 /* count the number of dynamic relocations so that we can reserve
793 their space */
794 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
796 ElfW_Rel *rel, *rel_end;
797 int sym_index, esym_index, type, count;
799 count = 0;
800 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
801 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
802 sym_index = ELFW(R_SYM)(rel->r_info);
803 type = ELFW(R_TYPE)(rel->r_info);
804 switch(type) {
805 #if defined(TCC_TARGET_I386)
806 case R_386_32:
807 #elif defined(TCC_TARGET_X86_64)
808 case R_X86_64_32:
809 case R_X86_64_32S:
810 case R_X86_64_64:
811 #endif
812 count++;
813 break;
814 #if defined(TCC_TARGET_I386)
815 case R_386_PC32:
816 #elif defined(TCC_TARGET_X86_64)
817 case R_X86_64_PC32:
818 #endif
819 esym_index = s1->symtab_to_dynsym[sym_index];
820 if (esym_index)
821 count++;
822 break;
823 default:
824 break;
827 if (count) {
828 /* allocate the section */
829 sr->sh_flags |= SHF_ALLOC;
830 sr->sh_size = count * sizeof(ElfW_Rel);
832 return count;
835 static void put_got_offset(TCCState *s1, int index, unsigned long val)
837 int n;
838 unsigned long *tab;
840 if (index >= s1->nb_got_offsets) {
841 /* find immediately bigger power of 2 and reallocate array */
842 n = 1;
843 while (index >= n)
844 n *= 2;
845 tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
846 if (!tab)
847 error("memory full");
848 s1->got_offsets = tab;
849 memset(s1->got_offsets + s1->nb_got_offsets, 0,
850 (n - s1->nb_got_offsets) * sizeof(unsigned long));
851 s1->nb_got_offsets = n;
853 s1->got_offsets[index] = val;
856 /* XXX: suppress that */
857 static void put32(unsigned char *p, uint32_t val)
859 p[0] = val;
860 p[1] = val >> 8;
861 p[2] = val >> 16;
862 p[3] = val >> 24;
865 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
866 defined(TCC_TARGET_X86_64)
867 static uint32_t get32(unsigned char *p)
869 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
871 #endif
873 static void build_got(TCCState *s1)
875 unsigned char *ptr;
877 /* if no got, then create it */
878 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
879 s1->got->sh_entsize = 4;
880 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
881 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
882 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
883 #if PTR_SIZE == 4
884 /* keep space for _DYNAMIC pointer, if present */
885 put32(ptr, 0);
886 /* two dummy got entries */
887 put32(ptr + 4, 0);
888 put32(ptr + 8, 0);
889 #else
890 /* keep space for _DYNAMIC pointer, if present */
891 put32(ptr, 0);
892 put32(ptr + 4, 0);
893 /* two dummy got entries */
894 put32(ptr + 8, 0);
895 put32(ptr + 12, 0);
896 put32(ptr + 16, 0);
897 put32(ptr + 20, 0);
898 #endif
901 /* put a got entry corresponding to a symbol in symtab_section. 'size'
902 and 'info' can be modifed if more precise info comes from the DLL */
903 static void put_got_entry(TCCState *s1,
904 int reloc_type, unsigned long size, int info,
905 int sym_index)
907 int index;
908 const char *name;
909 ElfW(Sym) *sym;
910 unsigned long offset;
911 int *ptr;
913 if (!s1->got)
914 build_got(s1);
916 /* if a got entry already exists for that symbol, no need to add one */
917 if (sym_index < s1->nb_got_offsets &&
918 s1->got_offsets[sym_index] != 0)
919 return;
921 put_got_offset(s1, sym_index, s1->got->data_offset);
923 if (s1->dynsym) {
924 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
925 name = symtab_section->link->data + sym->st_name;
926 offset = sym->st_value;
927 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
928 if (reloc_type ==
929 #ifdef TCC_TARGET_X86_64
930 R_X86_64_JUMP_SLOT
931 #else
932 R_386_JMP_SLOT
933 #endif
935 Section *plt;
936 uint8_t *p;
937 int modrm;
939 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
940 modrm = 0x25;
941 #else
942 /* if we build a DLL, we add a %ebx offset */
943 if (s1->output_type == TCC_OUTPUT_DLL)
944 modrm = 0xa3;
945 else
946 modrm = 0x25;
947 #endif
949 /* add a PLT entry */
950 plt = s1->plt;
951 if (plt->data_offset == 0) {
952 /* first plt entry */
953 p = section_ptr_add(plt, 16);
954 p[0] = 0xff; /* pushl got + PTR_SIZE */
955 p[1] = modrm + 0x10;
956 put32(p + 2, PTR_SIZE);
957 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
958 p[7] = modrm;
959 put32(p + 8, PTR_SIZE * 2);
962 p = section_ptr_add(plt, 16);
963 p[0] = 0xff; /* jmp *(got + x) */
964 p[1] = modrm;
965 put32(p + 2, s1->got->data_offset);
966 p[6] = 0x68; /* push $xxx */
967 put32(p + 7, (plt->data_offset - 32) >> 1);
968 p[11] = 0xe9; /* jmp plt_start */
969 put32(p + 12, -(plt->data_offset));
971 /* the symbol is modified so that it will be relocated to
972 the PLT */
973 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
974 if (s1->output_type == TCC_OUTPUT_EXE)
975 #endif
976 offset = plt->data_offset - 16;
978 #elif defined(TCC_TARGET_ARM)
979 if (reloc_type == R_ARM_JUMP_SLOT) {
980 Section *plt;
981 uint8_t *p;
983 /* if we build a DLL, we add a %ebx offset */
984 if (s1->output_type == TCC_OUTPUT_DLL)
985 error("DLLs unimplemented!");
987 /* add a PLT entry */
988 plt = s1->plt;
989 if (plt->data_offset == 0) {
990 /* first plt entry */
991 p = section_ptr_add(plt, 16);
992 put32(p , 0xe52de004);
993 put32(p + 4, 0xe59fe010);
994 put32(p + 8, 0xe08fe00e);
995 put32(p + 12, 0xe5bef008);
998 p = section_ptr_add(plt, 16);
999 put32(p , 0xe59fc004);
1000 put32(p+4, 0xe08fc00c);
1001 put32(p+8, 0xe59cf000);
1002 put32(p+12, s1->got->data_offset);
1004 /* the symbol is modified so that it will be relocated to
1005 the PLT */
1006 if (s1->output_type == TCC_OUTPUT_EXE)
1007 offset = plt->data_offset - 16;
1009 #elif defined(TCC_TARGET_C67)
1010 error("C67 got not implemented");
1011 #else
1012 #error unsupported CPU
1013 #endif
1014 index = put_elf_sym(s1->dynsym, offset,
1015 size, info, 0, sym->st_shndx, name);
1016 /* put a got entry */
1017 put_elf_reloc(s1->dynsym, s1->got,
1018 s1->got->data_offset,
1019 reloc_type, index);
1021 ptr = section_ptr_add(s1->got, PTR_SIZE);
1022 *ptr = 0;
1025 /* build GOT and PLT entries */
1026 ST_FUNC void build_got_entries(TCCState *s1)
1028 Section *s, *symtab;
1029 ElfW_Rel *rel, *rel_end;
1030 ElfW(Sym) *sym;
1031 int i, type, reloc_type, sym_index;
1033 for(i = 1; i < s1->nb_sections; i++) {
1034 s = s1->sections[i];
1035 if (s->sh_type != SHT_RELX)
1036 continue;
1037 /* no need to handle got relocations */
1038 if (s->link != symtab_section)
1039 continue;
1040 symtab = s->link;
1041 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1042 for(rel = (ElfW_Rel *)s->data;
1043 rel < rel_end;
1044 rel++) {
1045 type = ELFW(R_TYPE)(rel->r_info);
1046 switch(type) {
1047 #if defined(TCC_TARGET_I386)
1048 case R_386_GOT32:
1049 case R_386_GOTOFF:
1050 case R_386_GOTPC:
1051 case R_386_PLT32:
1052 if (!s1->got)
1053 build_got(s1);
1054 if (type == R_386_GOT32 || type == R_386_PLT32) {
1055 sym_index = ELFW(R_SYM)(rel->r_info);
1056 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1057 /* look at the symbol got offset. If none, then add one */
1058 if (type == R_386_GOT32)
1059 reloc_type = R_386_GLOB_DAT;
1060 else
1061 reloc_type = R_386_JMP_SLOT;
1062 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1063 sym_index);
1065 break;
1066 #elif defined(TCC_TARGET_ARM)
1067 case R_ARM_GOT_BREL:
1068 case R_ARM_GOTOFF32:
1069 case R_ARM_BASE_PREL:
1070 case R_ARM_PLT32:
1071 if (!s1->got)
1072 build_got(s1);
1073 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1074 sym_index = ELFW(R_SYM)(rel->r_info);
1075 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1076 /* look at the symbol got offset. If none, then add one */
1077 if (type == R_ARM_GOT_BREL)
1078 reloc_type = R_ARM_GLOB_DAT;
1079 else
1080 reloc_type = R_ARM_JUMP_SLOT;
1081 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1082 sym_index);
1084 break;
1085 #elif defined(TCC_TARGET_C67)
1086 case R_C60_GOT32:
1087 case R_C60_GOTOFF:
1088 case R_C60_GOTPC:
1089 case R_C60_PLT32:
1090 if (!s1->got)
1091 build_got(s1);
1092 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1093 sym_index = ELFW(R_SYM)(rel->r_info);
1094 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1095 /* look at the symbol got offset. If none, then add one */
1096 if (type == R_C60_GOT32)
1097 reloc_type = R_C60_GLOB_DAT;
1098 else
1099 reloc_type = R_C60_JMP_SLOT;
1100 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1101 sym_index);
1103 break;
1104 #elif defined(TCC_TARGET_X86_64)
1105 case R_X86_64_GOT32:
1106 case R_X86_64_GOTTPOFF:
1107 case R_X86_64_GOTPCREL:
1108 case R_X86_64_PLT32:
1109 if (!s1->got)
1110 build_got(s1);
1111 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1112 type == R_X86_64_PLT32) {
1113 sym_index = ELFW(R_SYM)(rel->r_info);
1114 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1115 /* look at the symbol got offset. If none, then add one */
1116 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1117 reloc_type = R_X86_64_GLOB_DAT;
1118 else
1119 reloc_type = R_X86_64_JUMP_SLOT;
1120 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1121 sym_index);
1123 break;
1124 #else
1125 #error unsupported CPU
1126 #endif
1127 default:
1128 break;
1134 ST_FUNC Section *new_symtab(TCCState *s1,
1135 const char *symtab_name, int sh_type, int sh_flags,
1136 const char *strtab_name,
1137 const char *hash_name, int hash_sh_flags)
1139 Section *symtab, *strtab, *hash;
1140 int *ptr, nb_buckets;
1142 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1143 symtab->sh_entsize = sizeof(ElfW(Sym));
1144 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1145 put_elf_str(strtab, "");
1146 symtab->link = strtab;
1147 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1149 nb_buckets = 1;
1151 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1152 hash->sh_entsize = sizeof(int);
1153 symtab->hash = hash;
1154 hash->link = symtab;
1156 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1157 ptr[0] = nb_buckets;
1158 ptr[1] = 1;
1159 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1160 return symtab;
1163 /* put dynamic tag */
1164 static void put_dt(Section *dynamic, int dt, unsigned long val)
1166 ElfW(Dyn) *dyn;
1167 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1168 dyn->d_tag = dt;
1169 dyn->d_un.d_val = val;
1172 static void add_init_array_defines(TCCState *s1, const char *section_name)
1174 Section *s;
1175 long end_offset;
1176 char sym_start[1024];
1177 char sym_end[1024];
1179 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1180 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1182 s = find_section(s1, section_name);
1183 if (!s) {
1184 end_offset = 0;
1185 s = data_section;
1186 } else {
1187 end_offset = s->data_offset;
1190 add_elf_sym(symtab_section,
1191 0, 0,
1192 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1193 s->sh_num, sym_start);
1194 add_elf_sym(symtab_section,
1195 end_offset, 0,
1196 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1197 s->sh_num, sym_end);
1200 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1202 #ifdef CONFIG_TCC_BCHECK
1203 unsigned long *ptr;
1204 Section *init_section;
1205 unsigned char *pinit;
1206 int sym_index;
1208 if (0 == s1->do_bounds_check)
1209 return;
1211 /* XXX: add an object file to do that */
1212 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1213 *ptr = 0;
1214 add_elf_sym(symtab_section, 0, 0,
1215 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1216 bounds_section->sh_num, "__bounds_start");
1217 /* add bound check code */
1218 #ifndef TCC_TARGET_PE
1220 char buf[1024];
1221 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "bcheck.o");
1222 tcc_add_file(s1, buf);
1224 #endif
1225 #ifdef TCC_TARGET_I386
1226 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1227 /* add 'call __bound_init()' in .init section */
1228 init_section = find_section(s1, ".init");
1229 pinit = section_ptr_add(init_section, 5);
1230 pinit[0] = 0xe8;
1231 put32(pinit + 1, -4);
1232 sym_index = find_elf_sym(symtab_section, "__bound_init");
1233 put_elf_reloc(symtab_section, init_section,
1234 init_section->data_offset - 4, R_386_PC32, sym_index);
1236 #endif
1237 #endif
1240 /* add tcc runtime libraries */
1241 ST_FUNC void tcc_add_runtime(TCCState *s1)
1243 tcc_add_bcheck(s1);
1245 /* add libc */
1246 if (!s1->nostdlib) {
1247 #ifdef CONFIG_USE_LIBGCC
1248 tcc_add_library(s1, "c");
1249 tcc_add_file(s1, CONFIG_SYSROOT "/lib/libgcc_s.so.1");
1250 #else
1251 tcc_add_library(s1, "c");
1252 #ifndef WITHOUT_LIBTCC
1254 char buf[1024];
1255 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "libtcc1.a");
1256 tcc_add_file(s1, buf);
1258 #endif
1259 #endif
1261 /* add crt end if not memory output */
1262 if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) {
1263 tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
1267 /* add various standard linker symbols (must be done after the
1268 sections are filled (for example after allocating common
1269 symbols)) */
1270 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1272 char buf[1024];
1273 int i;
1274 Section *s;
1276 add_elf_sym(symtab_section,
1277 text_section->data_offset, 0,
1278 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1279 text_section->sh_num, "_etext");
1280 add_elf_sym(symtab_section,
1281 data_section->data_offset, 0,
1282 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1283 data_section->sh_num, "_edata");
1284 add_elf_sym(symtab_section,
1285 bss_section->data_offset, 0,
1286 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1287 bss_section->sh_num, "_end");
1288 /* horrible new standard ldscript defines */
1289 add_init_array_defines(s1, ".preinit_array");
1290 add_init_array_defines(s1, ".init_array");
1291 add_init_array_defines(s1, ".fini_array");
1293 /* add start and stop symbols for sections whose name can be
1294 expressed in C */
1295 for(i = 1; i < s1->nb_sections; i++) {
1296 s = s1->sections[i];
1297 if (s->sh_type == SHT_PROGBITS &&
1298 (s->sh_flags & SHF_ALLOC)) {
1299 const char *p;
1300 int ch;
1302 /* check if section name can be expressed in C */
1303 p = s->name;
1304 for(;;) {
1305 ch = *p;
1306 if (!ch)
1307 break;
1308 if (!isid(ch) && !isnum(ch))
1309 goto next_sec;
1310 p++;
1312 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1313 add_elf_sym(symtab_section,
1314 0, 0,
1315 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1316 s->sh_num, buf);
1317 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1318 add_elf_sym(symtab_section,
1319 s->data_offset, 0,
1320 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1321 s->sh_num, buf);
1323 next_sec: ;
1327 /* name of ELF interpreter */
1328 #if defined __FreeBSD__
1329 static const char elf_interp[] = "/libexec/ld-elf.so.1";
1330 #elif defined TCC_ARM_EABI
1331 static const char elf_interp[] = "/lib/ld-linux.so.3";
1332 #elif defined(TCC_TARGET_X86_64)
1333 # if defined(TCC_TARGET_X86_64_CENTOS)
1334 static const char elf_interp[] = "/lib64/ld-linux-x86-64.so.2";
1335 # else
1336 static const char elf_interp[] = "/lib/ld-linux-x86-64.so.2";
1337 # endif /* TCC_TARGET_X86_64_CENTOS */
1338 #elif defined(TCC_UCLIBC)
1339 static const char elf_interp[] = "/lib/ld-uClibc.so.0";
1340 #else
1341 static const char elf_interp[] = "/lib/ld-linux.so.2";
1342 #endif
1344 static void tcc_output_binary(TCCState *s1, FILE *f,
1345 const int *section_order)
1347 Section *s;
1348 int i, offset, size;
1350 offset = 0;
1351 for(i=1;i<s1->nb_sections;i++) {
1352 s = s1->sections[section_order[i]];
1353 if (s->sh_type != SHT_NOBITS &&
1354 (s->sh_flags & SHF_ALLOC)) {
1355 while (offset < s->sh_offset) {
1356 fputc(0, f);
1357 offset++;
1359 size = s->sh_size;
1360 fwrite(s->data, 1, size, f);
1361 offset += size;
1366 #if defined(__FreeBSD__)
1367 #define HAVE_PHDR 1
1368 #define EXTRA_RELITEMS 14
1370 /* move the relocation value from .dynsym to .got */
1371 void patch_dynsym_undef(TCCState *s1, Section *s)
1373 uint32_t *gotd = (void *)s1->got->data;
1374 ElfW(Sym) *sym, *sym_end;
1376 gotd += 3; // dummy entries in .got
1377 /* relocate symbols in .dynsym */
1378 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1379 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1380 if (sym->st_shndx == SHN_UNDEF) {
1381 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1382 sym->st_value = 0;
1386 #else
1387 #define HAVE_PHDR 0
1388 #define EXTRA_RELITEMS 9
1389 #endif
1391 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1393 int sym_index = ELFW(R_SYM) (rel->r_info);
1394 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1395 unsigned long offset;
1397 if (sym_index >= s1->nb_got_offsets)
1398 return;
1399 offset = s1->got_offsets[sym_index];
1400 section_reserve(s1->got, offset + PTR_SIZE);
1401 #ifdef TCC_TARGET_X86_64
1402 /* only works for x86-64 */
1403 put32(s1->got->data + offset, sym->st_value >> 32);
1404 #endif
1405 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1408 ST_FUNC void fill_got(TCCState *s1)
1410 Section *s;
1411 ElfW_Rel *rel, *rel_end;
1412 int i;
1414 for(i = 1; i < s1->nb_sections; i++) {
1415 s = s1->sections[i];
1416 if (s->sh_type != SHT_RELX)
1417 continue;
1418 /* no need to handle got relocations */
1419 if (s->link != symtab_section)
1420 continue;
1421 rel_end = (ElfW_Rel *) (s->data + s->data_offset);
1422 for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
1423 switch (ELFW(R_TYPE) (rel->r_info)) {
1424 case R_X86_64_GOT32:
1425 case R_X86_64_GOTPCREL:
1426 case R_X86_64_PLT32:
1427 fill_got_entry(s1, rel);
1428 break;
1435 /* output an ELF file */
1436 /* XXX: suppress unneeded sections */
1437 static int elf_output_file(TCCState *s1, const char *filename)
1439 ElfW(Ehdr) ehdr;
1440 FILE *f;
1441 int fd, mode, ret;
1442 int *section_order;
1443 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
1444 unsigned long addr;
1445 Section *strsec, *s;
1446 ElfW(Shdr) shdr, *sh;
1447 ElfW(Phdr) *phdr, *ph;
1448 Section *interp, *dynamic, *dynstr;
1449 unsigned long saved_dynamic_data_offset;
1450 ElfW(Sym) *sym;
1451 int type, file_type;
1452 unsigned long rel_addr, rel_size;
1453 unsigned long bss_addr, bss_size;
1455 file_type = s1->output_type;
1456 s1->nb_errors = 0;
1458 if (file_type != TCC_OUTPUT_OBJ) {
1459 tcc_add_runtime(s1);
1462 phdr = NULL;
1463 section_order = NULL;
1464 interp = NULL;
1465 dynamic = NULL;
1466 dynstr = NULL; /* avoid warning */
1467 saved_dynamic_data_offset = 0; /* avoid warning */
1469 if (file_type != TCC_OUTPUT_OBJ) {
1470 relocate_common_syms();
1472 tcc_add_linker_symbols(s1);
1474 if (!s1->static_link) {
1475 const char *name;
1476 int sym_index, index;
1477 ElfW(Sym) *esym, *sym_end;
1479 if (file_type == TCC_OUTPUT_EXE) {
1480 char *ptr;
1481 /* allow override the dynamic loader */
1482 const char *elfint = getenv("LD_SO");
1483 if (elfint == NULL)
1484 elfint = elf_interp;
1485 /* add interpreter section only if executable */
1486 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1487 interp->sh_addralign = 1;
1488 ptr = section_ptr_add(interp, 1+strlen(elfint));
1489 strcpy(ptr, elfint);
1492 /* add dynamic symbol table */
1493 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1494 ".dynstr",
1495 ".hash", SHF_ALLOC);
1496 dynstr = s1->dynsym->link;
1498 /* add dynamic section */
1499 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1500 SHF_ALLOC | SHF_WRITE);
1501 dynamic->link = dynstr;
1502 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1504 /* add PLT */
1505 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1506 SHF_ALLOC | SHF_EXECINSTR);
1507 s1->plt->sh_entsize = 4;
1509 build_got(s1);
1511 /* scan for undefined symbols and see if they are in the
1512 dynamic symbols. If a symbol STT_FUNC is found, then we
1513 add it in the PLT. If a symbol STT_OBJECT is found, we
1514 add it in the .bss section with a suitable relocation */
1515 sym_end = (ElfW(Sym) *)(symtab_section->data +
1516 symtab_section->data_offset);
1517 if (file_type == TCC_OUTPUT_EXE) {
1518 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1519 sym < sym_end;
1520 sym++) {
1521 if (sym->st_shndx == SHN_UNDEF) {
1522 name = symtab_section->link->data + sym->st_name;
1523 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1524 if (sym_index) {
1525 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1526 type = ELFW(ST_TYPE)(esym->st_info);
1527 if (type == STT_FUNC) {
1528 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1529 esym->st_info,
1530 sym - (ElfW(Sym) *)symtab_section->data);
1531 } else if (type == STT_OBJECT) {
1532 unsigned long offset;
1533 ElfW(Sym) *dynsym, *dynsym_end;
1534 offset = bss_section->data_offset;
1535 /* XXX: which alignment ? */
1536 offset = (offset + 16 - 1) & -16;
1537 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1538 esym->st_info, 0,
1539 bss_section->sh_num, name);
1540 /* Ensure symbol aliases (that is, symbols with
1541 the same st_value) resolve to the same
1542 address in program .bss or .data section. */
1543 dynsym_end = (ElfW(Sym) *)
1544 (s1->dynsymtab_section->data +
1545 s1->dynsymtab_section->data_offset);
1546 for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1547 dynsym < dynsym_end; dynsym++) {
1548 if (dynsym->st_value == esym->st_value) {
1549 char *dynname;
1550 dynname = s1->dynsymtab_section->link->data
1551 + dynsym->st_name;
1552 put_elf_sym(s1->dynsym, offset,
1553 dynsym->st_size,
1554 dynsym->st_info, 0,
1555 bss_section->sh_num,
1556 dynname);
1559 put_elf_reloc(s1->dynsym, bss_section,
1560 offset, R_COPY, index);
1561 offset += esym->st_size;
1562 bss_section->data_offset = offset;
1564 } else {
1565 /* STB_WEAK undefined symbols are accepted */
1566 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1567 it */
1568 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1569 !strcmp(name, "_fp_hw")) {
1570 } else {
1571 error_noabort("undefined symbol '%s'", name);
1574 } else if (s1->rdynamic &&
1575 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1576 /* if -rdynamic option, then export all non
1577 local symbols */
1578 name = symtab_section->link->data + sym->st_name;
1579 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1580 sym->st_info, 0,
1581 sym->st_shndx, name);
1585 if (s1->nb_errors)
1586 goto fail;
1588 /* now look at unresolved dynamic symbols and export
1589 corresponding symbol */
1590 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1591 s1->dynsymtab_section->data_offset);
1592 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1593 esym < sym_end;
1594 esym++) {
1595 if (esym->st_shndx == SHN_UNDEF) {
1596 name = s1->dynsymtab_section->link->data + esym->st_name;
1597 sym_index = find_elf_sym(symtab_section, name);
1598 if (sym_index) {
1599 /* XXX: avoid adding a symbol if already
1600 present because of -rdynamic ? */
1601 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1602 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1603 sym->st_info, 0,
1604 sym->st_shndx, name);
1605 } else {
1606 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1607 /* weak symbols can stay undefined */
1608 } else {
1609 warning("undefined dynamic symbol '%s'", name);
1614 } else {
1615 int nb_syms;
1616 /* shared library case : we simply export all the global symbols */
1617 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1618 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1619 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1620 sym < sym_end;
1621 sym++) {
1622 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1623 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1624 if (ELFW(ST_TYPE)(sym->st_info) == STT_FUNC &&
1625 sym->st_shndx == SHN_UNDEF) {
1626 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1627 sym->st_info,
1628 sym - (ElfW(Sym) *)symtab_section->data);
1630 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1631 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1632 sym->st_info,
1633 sym - (ElfW(Sym) *)symtab_section->data);
1635 else
1636 #endif
1638 name = symtab_section->link->data + sym->st_name;
1639 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1640 sym->st_info, 0,
1641 sym->st_shndx, name);
1642 s1->symtab_to_dynsym[sym -
1643 (ElfW(Sym) *)symtab_section->data] =
1644 index;
1650 build_got_entries(s1);
1652 /* add a list of needed dlls */
1653 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1654 DLLReference *dllref = s1->loaded_dlls[i];
1655 if (dllref->level == 0)
1656 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1659 if (s1->rpath)
1660 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1662 /* XXX: currently, since we do not handle PIC code, we
1663 must relocate the readonly segments */
1664 if (file_type == TCC_OUTPUT_DLL) {
1665 if (s1->soname)
1666 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1667 put_dt(dynamic, DT_TEXTREL, 0);
1670 if (s1->symbolic)
1671 put_dt(dynamic, DT_SYMBOLIC, 0);
1673 /* add necessary space for other entries */
1674 saved_dynamic_data_offset = dynamic->data_offset;
1675 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1676 } else {
1677 /* still need to build got entries in case of static link */
1678 build_got_entries(s1);
1682 memset(&ehdr, 0, sizeof(ehdr));
1684 /* we add a section for symbols */
1685 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1686 put_elf_str(strsec, "");
1688 /* compute number of sections */
1689 shnum = s1->nb_sections;
1691 /* this array is used to reorder sections in the output file */
1692 section_order = tcc_malloc(sizeof(int) * shnum);
1693 section_order[0] = 0;
1694 sh_order_index = 1;
1696 /* compute number of program headers */
1697 switch(file_type) {
1698 default:
1699 case TCC_OUTPUT_OBJ:
1700 phnum = 0;
1701 break;
1702 case TCC_OUTPUT_EXE:
1703 if (!s1->static_link)
1704 phnum = 4 + HAVE_PHDR;
1705 else
1706 phnum = 2;
1707 break;
1708 case TCC_OUTPUT_DLL:
1709 phnum = 3;
1710 break;
1713 /* allocate strings for section names and decide if an unallocated
1714 section should be output */
1715 /* NOTE: the strsec section comes last, so its size is also
1716 correct ! */
1717 for(i = 1; i < s1->nb_sections; i++) {
1718 s = s1->sections[i];
1719 s->sh_name = put_elf_str(strsec, s->name);
1720 #if 0 //gr
1721 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1722 s->sh_flags,
1723 s->sh_type,
1724 s->sh_info,
1725 s->name,
1726 s->reloc ? s->reloc->name : "n"
1728 #endif
1729 /* when generating a DLL, we include relocations but we may
1730 patch them */
1731 if (file_type == TCC_OUTPUT_DLL &&
1732 s->sh_type == SHT_RELX &&
1733 !(s->sh_flags & SHF_ALLOC)) {
1734 /* //gr: avoid bogus relocs for empty (debug) sections */
1735 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1736 prepare_dynamic_rel(s1, s);
1737 else if (s1->do_debug)
1738 s->sh_size = s->data_offset;
1739 } else if (s1->do_debug ||
1740 file_type == TCC_OUTPUT_OBJ ||
1741 (s->sh_flags & SHF_ALLOC) ||
1742 i == (s1->nb_sections - 1)) {
1743 /* we output all sections if debug or object file */
1744 s->sh_size = s->data_offset;
1748 /* allocate program segment headers */
1749 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1751 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1752 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1753 } else {
1754 file_offset = 0;
1756 if (phnum > 0) {
1757 /* compute section to program header mapping */
1758 if (s1->has_text_addr) {
1759 int a_offset, p_offset;
1760 addr = s1->text_addr;
1761 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1762 ELF_PAGE_SIZE */
1763 a_offset = addr & (s1->section_align - 1);
1764 p_offset = file_offset & (s1->section_align - 1);
1765 if (a_offset < p_offset)
1766 a_offset += s1->section_align;
1767 file_offset += (a_offset - p_offset);
1768 } else {
1769 if (file_type == TCC_OUTPUT_DLL)
1770 addr = 0;
1771 else
1772 addr = ELF_START_ADDR;
1773 /* compute address after headers */
1774 addr += (file_offset & (s1->section_align - 1));
1777 /* dynamic relocation table information, for .dynamic section */
1778 rel_size = 0;
1779 rel_addr = 0;
1781 bss_addr = bss_size = 0;
1782 /* leave one program header for the program interpreter */
1783 ph = &phdr[0];
1784 if (interp)
1785 ph += 1 + HAVE_PHDR;
1787 for(j = 0; j < 2; j++) {
1788 ph->p_type = PT_LOAD;
1789 if (j == 0)
1790 ph->p_flags = PF_R | PF_X;
1791 else
1792 ph->p_flags = PF_R | PF_W;
1793 ph->p_align = s1->section_align;
1795 /* we do the following ordering: interp, symbol tables,
1796 relocations, progbits, nobits */
1797 /* XXX: do faster and simpler sorting */
1798 for(k = 0; k < 5; k++) {
1799 for(i = 1; i < s1->nb_sections; i++) {
1800 s = s1->sections[i];
1801 /* compute if section should be included */
1802 if (j == 0) {
1803 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1804 SHF_ALLOC)
1805 continue;
1806 } else {
1807 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1808 (SHF_ALLOC | SHF_WRITE))
1809 continue;
1811 if (s == interp) {
1812 if (k != 0)
1813 continue;
1814 } else if (s->sh_type == SHT_DYNSYM ||
1815 s->sh_type == SHT_STRTAB ||
1816 s->sh_type == SHT_HASH) {
1817 if (k != 1)
1818 continue;
1819 } else if (s->sh_type == SHT_RELX) {
1820 if (k != 2)
1821 continue;
1822 } else if (s->sh_type == SHT_NOBITS) {
1823 if (k != 4)
1824 continue;
1825 } else {
1826 if (k != 3)
1827 continue;
1829 section_order[sh_order_index++] = i;
1831 /* section matches: we align it and add its size */
1832 tmp = addr;
1833 addr = (addr + s->sh_addralign - 1) &
1834 ~(s->sh_addralign - 1);
1835 file_offset += addr - tmp;
1836 s->sh_offset = file_offset;
1837 s->sh_addr = addr;
1839 /* update program header infos */
1840 if (ph->p_offset == 0) {
1841 ph->p_offset = file_offset;
1842 ph->p_vaddr = addr;
1843 ph->p_paddr = ph->p_vaddr;
1845 /* update dynamic relocation infos */
1846 if (s->sh_type == SHT_RELX) {
1847 #if defined(__FreeBSD__)
1848 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1849 rel_addr = addr;
1850 rel_size += s->sh_size; // XXX only first rel.
1852 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1853 bss_addr = addr;
1854 bss_size = s->sh_size; // XXX only first rel.
1856 #else
1857 if (rel_size == 0)
1858 rel_addr = addr;
1859 rel_size += s->sh_size;
1860 #endif
1862 addr += s->sh_size;
1863 if (s->sh_type != SHT_NOBITS)
1864 file_offset += s->sh_size;
1867 ph->p_filesz = file_offset - ph->p_offset;
1868 ph->p_memsz = addr - ph->p_vaddr;
1869 ph++;
1870 if (j == 0) {
1871 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1872 /* if in the middle of a page, we duplicate the page in
1873 memory so that one copy is RX and the other is RW */
1874 if ((addr & (s1->section_align - 1)) != 0)
1875 addr += s1->section_align;
1876 } else {
1877 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1878 file_offset = (file_offset + s1->section_align - 1) &
1879 ~(s1->section_align - 1);
1884 /* if interpreter, then add corresponing program header */
1885 if (interp) {
1886 ph = &phdr[0];
1888 #if defined(__FreeBSD__)
1890 int len = phnum * sizeof(ElfW(Phdr));
1892 ph->p_type = PT_PHDR;
1893 ph->p_offset = sizeof(ElfW(Ehdr));
1894 ph->p_vaddr = interp->sh_addr - len;
1895 ph->p_paddr = ph->p_vaddr;
1896 ph->p_filesz = ph->p_memsz = len;
1897 ph->p_flags = PF_R | PF_X;
1898 ph->p_align = 4; // interp->sh_addralign;
1899 ph++;
1901 #endif
1903 ph->p_type = PT_INTERP;
1904 ph->p_offset = interp->sh_offset;
1905 ph->p_vaddr = interp->sh_addr;
1906 ph->p_paddr = ph->p_vaddr;
1907 ph->p_filesz = interp->sh_size;
1908 ph->p_memsz = interp->sh_size;
1909 ph->p_flags = PF_R;
1910 ph->p_align = interp->sh_addralign;
1913 /* if dynamic section, then add corresponing program header */
1914 if (dynamic) {
1915 ElfW(Sym) *sym_end;
1917 ph = &phdr[phnum - 1];
1919 ph->p_type = PT_DYNAMIC;
1920 ph->p_offset = dynamic->sh_offset;
1921 ph->p_vaddr = dynamic->sh_addr;
1922 ph->p_paddr = ph->p_vaddr;
1923 ph->p_filesz = dynamic->sh_size;
1924 ph->p_memsz = dynamic->sh_size;
1925 ph->p_flags = PF_R | PF_W;
1926 ph->p_align = dynamic->sh_addralign;
1928 /* put GOT dynamic section address */
1929 put32(s1->got->data, dynamic->sh_addr);
1931 /* relocate the PLT */
1932 if (file_type == TCC_OUTPUT_EXE
1933 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1934 || file_type == TCC_OUTPUT_DLL
1935 #endif
1937 uint8_t *p, *p_end;
1939 p = s1->plt->data;
1940 p_end = p + s1->plt->data_offset;
1941 if (p < p_end) {
1942 #if defined(TCC_TARGET_I386)
1943 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1944 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1945 p += 16;
1946 while (p < p_end) {
1947 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1948 p += 16;
1950 #elif defined(TCC_TARGET_X86_64)
1951 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1952 put32(p + 2, get32(p + 2) + x);
1953 put32(p + 8, get32(p + 8) + x - 6);
1954 p += 16;
1955 while (p < p_end) {
1956 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1957 p += 16;
1959 #elif defined(TCC_TARGET_ARM)
1960 int x;
1961 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1962 p +=16;
1963 while (p < p_end) {
1964 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1965 p += 16;
1967 #elif defined(TCC_TARGET_C67)
1968 /* XXX: TODO */
1969 #else
1970 #error unsupported CPU
1971 #endif
1975 /* relocate symbols in .dynsym */
1976 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
1977 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
1978 sym < sym_end;
1979 sym++) {
1980 if (sym->st_shndx == SHN_UNDEF) {
1981 /* relocate to the PLT if the symbol corresponds
1982 to a PLT entry */
1983 if (sym->st_value)
1984 sym->st_value += s1->plt->sh_addr;
1985 } else if (sym->st_shndx < SHN_LORESERVE) {
1986 /* do symbol relocation */
1987 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
1991 /* put dynamic section entries */
1992 dynamic->data_offset = saved_dynamic_data_offset;
1993 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
1994 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
1995 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
1996 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
1997 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
1998 #ifdef TCC_TARGET_X86_64
1999 put_dt(dynamic, DT_RELA, rel_addr);
2000 put_dt(dynamic, DT_RELASZ, rel_size);
2001 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2002 #else
2003 #if defined(__FreeBSD__)
2004 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2005 put_dt(dynamic, DT_PLTRELSZ, rel_size);
2006 put_dt(dynamic, DT_JMPREL, rel_addr);
2007 put_dt(dynamic, DT_PLTREL, DT_REL);
2008 put_dt(dynamic, DT_REL, bss_addr);
2009 put_dt(dynamic, DT_RELSZ, bss_size);
2010 #else
2011 put_dt(dynamic, DT_REL, rel_addr);
2012 put_dt(dynamic, DT_RELSZ, rel_size);
2013 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2014 #endif
2015 #endif
2016 if (s1->do_debug)
2017 put_dt(dynamic, DT_DEBUG, 0);
2018 put_dt(dynamic, DT_NULL, 0);
2021 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2022 ehdr.e_phnum = phnum;
2023 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2026 /* all other sections come after */
2027 for(i = 1; i < s1->nb_sections; i++) {
2028 s = s1->sections[i];
2029 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2030 continue;
2031 section_order[sh_order_index++] = i;
2033 file_offset = (file_offset + s->sh_addralign - 1) &
2034 ~(s->sh_addralign - 1);
2035 s->sh_offset = file_offset;
2036 if (s->sh_type != SHT_NOBITS)
2037 file_offset += s->sh_size;
2040 /* if building executable or DLL, then relocate each section
2041 except the GOT which is already relocated */
2042 if (file_type != TCC_OUTPUT_OBJ) {
2043 relocate_syms(s1, 0);
2045 if (s1->nb_errors != 0) {
2046 fail:
2047 ret = -1;
2048 goto the_end;
2051 /* relocate sections */
2052 /* XXX: ignore sections with allocated relocations ? */
2053 for(i = 1; i < s1->nb_sections; i++) {
2054 s = s1->sections[i];
2055 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
2056 relocate_section(s1, s);
2059 /* relocate relocation entries if the relocation tables are
2060 allocated in the executable */
2061 for(i = 1; i < s1->nb_sections; i++) {
2062 s = s1->sections[i];
2063 if ((s->sh_flags & SHF_ALLOC) &&
2064 s->sh_type == SHT_RELX) {
2065 relocate_rel(s1, s);
2069 /* get entry point address */
2070 if (file_type == TCC_OUTPUT_EXE)
2071 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
2072 else
2073 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2075 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2076 fill_got(s1);
2078 /* write elf file */
2079 if (file_type == TCC_OUTPUT_OBJ)
2080 mode = 0666;
2081 else
2082 mode = 0777;
2083 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2084 if (fd < 0) {
2085 error_noabort("could not write '%s'", filename);
2086 goto fail;
2088 f = fdopen(fd, "wb");
2089 if (s1->verbose)
2090 printf("<- %s\n", filename);
2092 #ifdef TCC_TARGET_COFF
2093 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2094 tcc_output_coff(s1, f);
2095 } else
2096 #endif
2097 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2098 sort_syms(s1, symtab_section);
2100 /* align to 4 */
2101 file_offset = (file_offset + 3) & -4;
2103 /* fill header */
2104 ehdr.e_ident[0] = ELFMAG0;
2105 ehdr.e_ident[1] = ELFMAG1;
2106 ehdr.e_ident[2] = ELFMAG2;
2107 ehdr.e_ident[3] = ELFMAG3;
2108 ehdr.e_ident[4] = TCC_ELFCLASS;
2109 ehdr.e_ident[5] = ELFDATA2LSB;
2110 ehdr.e_ident[6] = EV_CURRENT;
2111 #ifdef __FreeBSD__
2112 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2113 #endif
2114 #ifdef TCC_TARGET_ARM
2115 #ifdef TCC_ARM_EABI
2116 ehdr.e_ident[EI_OSABI] = 0;
2117 ehdr.e_flags = 4 << 24;
2118 #else
2119 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2120 #endif
2121 #endif
2122 switch(file_type) {
2123 default:
2124 case TCC_OUTPUT_EXE:
2125 ehdr.e_type = ET_EXEC;
2126 break;
2127 case TCC_OUTPUT_DLL:
2128 ehdr.e_type = ET_DYN;
2129 break;
2130 case TCC_OUTPUT_OBJ:
2131 ehdr.e_type = ET_REL;
2132 break;
2134 ehdr.e_machine = EM_TCC_TARGET;
2135 ehdr.e_version = EV_CURRENT;
2136 ehdr.e_shoff = file_offset;
2137 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2138 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2139 ehdr.e_shnum = shnum;
2140 ehdr.e_shstrndx = shnum - 1;
2142 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2143 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2144 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2146 for(i=1;i<s1->nb_sections;i++) {
2147 s = s1->sections[section_order[i]];
2148 if (s->sh_type != SHT_NOBITS) {
2149 #if defined(__FreeBSD__)
2150 if (s->sh_type == SHT_DYNSYM)
2151 patch_dynsym_undef(s1, s);
2152 #endif
2153 while (offset < s->sh_offset) {
2154 fputc(0, f);
2155 offset++;
2157 size = s->sh_size;
2158 fwrite(s->data, 1, size, f);
2159 offset += size;
2163 /* output section headers */
2164 while (offset < ehdr.e_shoff) {
2165 fputc(0, f);
2166 offset++;
2169 for(i=0;i<s1->nb_sections;i++) {
2170 sh = &shdr;
2171 memset(sh, 0, sizeof(ElfW(Shdr)));
2172 s = s1->sections[i];
2173 if (s) {
2174 sh->sh_name = s->sh_name;
2175 sh->sh_type = s->sh_type;
2176 sh->sh_flags = s->sh_flags;
2177 sh->sh_entsize = s->sh_entsize;
2178 sh->sh_info = s->sh_info;
2179 if (s->link)
2180 sh->sh_link = s->link->sh_num;
2181 sh->sh_addralign = s->sh_addralign;
2182 sh->sh_addr = s->sh_addr;
2183 sh->sh_offset = s->sh_offset;
2184 sh->sh_size = s->sh_size;
2186 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2188 } else {
2189 tcc_output_binary(s1, f, section_order);
2191 fclose(f);
2193 ret = 0;
2194 the_end:
2195 tcc_free(s1->symtab_to_dynsym);
2196 tcc_free(section_order);
2197 tcc_free(phdr);
2198 tcc_free(s1->got_offsets);
2199 return ret;
2202 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2204 int ret;
2205 #ifdef TCC_TARGET_PE
2206 if (s->output_type != TCC_OUTPUT_OBJ) {
2207 ret = pe_output_file(s, filename);
2208 } else
2209 #endif
2211 ret = elf_output_file(s, filename);
2213 return ret;
2216 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2218 void *data;
2220 data = tcc_malloc(size);
2221 lseek(fd, file_offset, SEEK_SET);
2222 read(fd, data, size);
2223 return data;
2226 typedef struct SectionMergeInfo {
2227 Section *s; /* corresponding existing section */
2228 unsigned long offset; /* offset of the new section in the existing section */
2229 uint8_t new_section; /* true if section 's' was added */
2230 uint8_t link_once; /* true if link once section */
2231 } SectionMergeInfo;
2233 /* load an object file and merge it with current files */
2234 /* XXX: handle correctly stab (debug) info */
2235 ST_FUNC int tcc_load_object_file(TCCState *s1,
2236 int fd, unsigned long file_offset)
2238 ElfW(Ehdr) ehdr;
2239 ElfW(Shdr) *shdr, *sh;
2240 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2241 unsigned char *strsec, *strtab;
2242 int *old_to_new_syms;
2243 char *sh_name, *name;
2244 SectionMergeInfo *sm_table, *sm;
2245 ElfW(Sym) *sym, *symtab;
2246 ElfW_Rel *rel, *rel_end;
2247 Section *s;
2249 int stab_index;
2250 int stabstr_index;
2252 stab_index = stabstr_index = 0;
2254 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2255 goto fail1;
2256 if (ehdr.e_ident[0] != ELFMAG0 ||
2257 ehdr.e_ident[1] != ELFMAG1 ||
2258 ehdr.e_ident[2] != ELFMAG2 ||
2259 ehdr.e_ident[3] != ELFMAG3)
2260 goto fail1;
2261 /* test if object file */
2262 if (ehdr.e_type != ET_REL)
2263 goto fail1;
2264 /* test CPU specific stuff */
2265 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2266 ehdr.e_machine != EM_TCC_TARGET) {
2267 fail1:
2268 error_noabort("invalid object file");
2269 return -1;
2271 /* read sections */
2272 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2273 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2274 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2276 /* load section names */
2277 sh = &shdr[ehdr.e_shstrndx];
2278 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2280 /* load symtab and strtab */
2281 old_to_new_syms = NULL;
2282 symtab = NULL;
2283 strtab = NULL;
2284 nb_syms = 0;
2285 for(i = 1; i < ehdr.e_shnum; i++) {
2286 sh = &shdr[i];
2287 if (sh->sh_type == SHT_SYMTAB) {
2288 if (symtab) {
2289 error_noabort("object must contain only one symtab");
2290 fail:
2291 ret = -1;
2292 goto the_end;
2294 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2295 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2296 sm_table[i].s = symtab_section;
2298 /* now load strtab */
2299 sh = &shdr[sh->sh_link];
2300 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2304 /* now examine each section and try to merge its content with the
2305 ones in memory */
2306 for(i = 1; i < ehdr.e_shnum; i++) {
2307 /* no need to examine section name strtab */
2308 if (i == ehdr.e_shstrndx)
2309 continue;
2310 sh = &shdr[i];
2311 sh_name = strsec + sh->sh_name;
2312 /* ignore sections types we do not handle */
2313 if (sh->sh_type != SHT_PROGBITS &&
2314 sh->sh_type != SHT_RELX &&
2315 #ifdef TCC_ARM_EABI
2316 sh->sh_type != SHT_ARM_EXIDX &&
2317 #endif
2318 sh->sh_type != SHT_NOBITS &&
2319 strcmp(sh_name, ".stabstr")
2321 continue;
2322 if (sh->sh_addralign < 1)
2323 sh->sh_addralign = 1;
2324 /* find corresponding section, if any */
2325 for(j = 1; j < s1->nb_sections;j++) {
2326 s = s1->sections[j];
2327 if (!strcmp(s->name, sh_name)) {
2328 if (!strncmp(sh_name, ".gnu.linkonce",
2329 sizeof(".gnu.linkonce") - 1)) {
2330 /* if a 'linkonce' section is already present, we
2331 do not add it again. It is a little tricky as
2332 symbols can still be defined in
2333 it. */
2334 sm_table[i].link_once = 1;
2335 goto next;
2336 } else {
2337 goto found;
2341 /* not found: create new section */
2342 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2343 /* take as much info as possible from the section. sh_link and
2344 sh_info will be updated later */
2345 s->sh_addralign = sh->sh_addralign;
2346 s->sh_entsize = sh->sh_entsize;
2347 sm_table[i].new_section = 1;
2348 found:
2349 if (sh->sh_type != s->sh_type) {
2350 error_noabort("invalid section type");
2351 goto fail;
2354 /* align start of section */
2355 offset = s->data_offset;
2357 if (0 == strcmp(sh_name, ".stab")) {
2358 stab_index = i;
2359 goto no_align;
2361 if (0 == strcmp(sh_name, ".stabstr")) {
2362 stabstr_index = i;
2363 goto no_align;
2366 size = sh->sh_addralign - 1;
2367 offset = (offset + size) & ~size;
2368 if (sh->sh_addralign > s->sh_addralign)
2369 s->sh_addralign = sh->sh_addralign;
2370 s->data_offset = offset;
2371 no_align:
2372 sm_table[i].offset = offset;
2373 sm_table[i].s = s;
2374 /* concatenate sections */
2375 size = sh->sh_size;
2376 if (sh->sh_type != SHT_NOBITS) {
2377 unsigned char *ptr;
2378 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2379 ptr = section_ptr_add(s, size);
2380 read(fd, ptr, size);
2381 } else {
2382 s->data_offset += size;
2384 next: ;
2387 /* //gr relocate stab strings */
2388 if (stab_index && stabstr_index) {
2389 Stab_Sym *a, *b;
2390 unsigned o;
2391 s = sm_table[stab_index].s;
2392 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2393 b = (Stab_Sym *)(s->data + s->data_offset);
2394 o = sm_table[stabstr_index].offset;
2395 while (a < b)
2396 a->n_strx += o, a++;
2399 /* second short pass to update sh_link and sh_info fields of new
2400 sections */
2401 for(i = 1; i < ehdr.e_shnum; i++) {
2402 s = sm_table[i].s;
2403 if (!s || !sm_table[i].new_section)
2404 continue;
2405 sh = &shdr[i];
2406 if (sh->sh_link > 0)
2407 s->link = sm_table[sh->sh_link].s;
2408 if (sh->sh_type == SHT_RELX) {
2409 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2410 /* update backward link */
2411 s1->sections[s->sh_info]->reloc = s;
2414 sm = sm_table;
2416 /* resolve symbols */
2417 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2419 sym = symtab + 1;
2420 for(i = 1; i < nb_syms; i++, sym++) {
2421 if (sym->st_shndx != SHN_UNDEF &&
2422 sym->st_shndx < SHN_LORESERVE) {
2423 sm = &sm_table[sym->st_shndx];
2424 if (sm->link_once) {
2425 /* if a symbol is in a link once section, we use the
2426 already defined symbol. It is very important to get
2427 correct relocations */
2428 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2429 name = strtab + sym->st_name;
2430 sym_index = find_elf_sym(symtab_section, name);
2431 if (sym_index)
2432 old_to_new_syms[i] = sym_index;
2434 continue;
2436 /* if no corresponding section added, no need to add symbol */
2437 if (!sm->s)
2438 continue;
2439 /* convert section number */
2440 sym->st_shndx = sm->s->sh_num;
2441 /* offset value */
2442 sym->st_value += sm->offset;
2444 /* add symbol */
2445 name = strtab + sym->st_name;
2446 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2447 sym->st_info, sym->st_other,
2448 sym->st_shndx, name);
2449 old_to_new_syms[i] = sym_index;
2452 /* third pass to patch relocation entries */
2453 for(i = 1; i < ehdr.e_shnum; i++) {
2454 s = sm_table[i].s;
2455 if (!s)
2456 continue;
2457 sh = &shdr[i];
2458 offset = sm_table[i].offset;
2459 switch(s->sh_type) {
2460 case SHT_RELX:
2461 /* take relocation offset information */
2462 offseti = sm_table[sh->sh_info].offset;
2463 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2464 for(rel = (ElfW_Rel *)(s->data + offset);
2465 rel < rel_end;
2466 rel++) {
2467 int type;
2468 unsigned sym_index;
2469 /* convert symbol index */
2470 type = ELFW(R_TYPE)(rel->r_info);
2471 sym_index = ELFW(R_SYM)(rel->r_info);
2472 /* NOTE: only one symtab assumed */
2473 if (sym_index >= nb_syms)
2474 goto invalid_reloc;
2475 sym_index = old_to_new_syms[sym_index];
2476 /* ignore link_once in rel section. */
2477 if (!sym_index && !sm->link_once) {
2478 invalid_reloc:
2479 error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2480 i, strsec + sh->sh_name, rel->r_offset);
2481 goto fail;
2483 rel->r_info = ELFW(R_INFO)(sym_index, type);
2484 /* offset the relocation offset */
2485 rel->r_offset += offseti;
2487 break;
2488 default:
2489 break;
2493 ret = 0;
2494 the_end:
2495 tcc_free(symtab);
2496 tcc_free(strtab);
2497 tcc_free(old_to_new_syms);
2498 tcc_free(sm_table);
2499 tcc_free(strsec);
2500 tcc_free(shdr);
2501 return ret;
2504 typedef struct ArchiveHeader {
2505 char ar_name[16]; /* name of this member */
2506 char ar_date[12]; /* file mtime */
2507 char ar_uid[6]; /* owner uid; printed as decimal */
2508 char ar_gid[6]; /* owner gid; printed as decimal */
2509 char ar_mode[8]; /* file mode, printed as octal */
2510 char ar_size[10]; /* file size, printed as decimal */
2511 char ar_fmag[2]; /* should contain ARFMAG */
2512 } ArchiveHeader;
2514 static int get_be32(const uint8_t *b)
2516 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2519 /* load only the objects which resolve undefined symbols */
2520 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2522 int i, bound, nsyms, sym_index, off, ret;
2523 uint8_t *data;
2524 const char *ar_names, *p;
2525 const uint8_t *ar_index;
2526 ElfW(Sym) *sym;
2528 data = tcc_malloc(size);
2529 if (read(fd, data, size) != size)
2530 goto fail;
2531 nsyms = get_be32(data);
2532 ar_index = data + 4;
2533 ar_names = ar_index + nsyms * 4;
2535 do {
2536 bound = 0;
2537 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2538 sym_index = find_elf_sym(symtab_section, p);
2539 if(sym_index) {
2540 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2541 if(sym->st_shndx == SHN_UNDEF) {
2542 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2543 #if 0
2544 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2545 #endif
2546 ++bound;
2547 lseek(fd, off, SEEK_SET);
2548 if(tcc_load_object_file(s1, fd, off) < 0) {
2549 fail:
2550 ret = -1;
2551 goto the_end;
2556 } while(bound);
2557 ret = 0;
2558 the_end:
2559 tcc_free(data);
2560 return ret;
2563 /* load a '.a' file */
2564 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2566 ArchiveHeader hdr;
2567 char ar_size[11];
2568 char ar_name[17];
2569 char magic[8];
2570 int size, len, i;
2571 unsigned long file_offset;
2573 /* skip magic which was already checked */
2574 read(fd, magic, sizeof(magic));
2576 for(;;) {
2577 len = read(fd, &hdr, sizeof(hdr));
2578 if (len == 0)
2579 break;
2580 if (len != sizeof(hdr)) {
2581 error_noabort("invalid archive");
2582 return -1;
2584 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2585 ar_size[sizeof(hdr.ar_size)] = '\0';
2586 size = strtol(ar_size, NULL, 0);
2587 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2588 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2589 if (ar_name[i] != ' ')
2590 break;
2592 ar_name[i + 1] = '\0';
2593 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2594 file_offset = lseek(fd, 0, SEEK_CUR);
2595 /* align to even */
2596 size = (size + 1) & ~1;
2597 if (!strcmp(ar_name, "/")) {
2598 /* coff symbol table : we handle it */
2599 if(s1->alacarte_link)
2600 return tcc_load_alacarte(s1, fd, size);
2601 } else if (!strcmp(ar_name, "//") ||
2602 !strcmp(ar_name, "__.SYMDEF") ||
2603 !strcmp(ar_name, "__.SYMDEF/") ||
2604 !strcmp(ar_name, "ARFILENAMES/")) {
2605 /* skip symbol table or archive names */
2606 } else {
2607 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2608 return -1;
2610 lseek(fd, file_offset + size, SEEK_SET);
2612 return 0;
2615 #ifndef TCC_TARGET_PE
2616 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2617 is referenced by the user (so it should be added as DT_NEEDED in
2618 the generated ELF file) */
2619 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2621 ElfW(Ehdr) ehdr;
2622 ElfW(Shdr) *shdr, *sh, *sh1;
2623 int i, j, nb_syms, nb_dts, sym_bind, ret;
2624 ElfW(Sym) *sym, *dynsym;
2625 ElfW(Dyn) *dt, *dynamic;
2626 unsigned char *dynstr;
2627 const char *name, *soname;
2628 DLLReference *dllref;
2630 read(fd, &ehdr, sizeof(ehdr));
2632 /* test CPU specific stuff */
2633 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2634 ehdr.e_machine != EM_TCC_TARGET) {
2635 error_noabort("bad architecture");
2636 return -1;
2639 /* read sections */
2640 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2642 /* load dynamic section and dynamic symbols */
2643 nb_syms = 0;
2644 nb_dts = 0;
2645 dynamic = NULL;
2646 dynsym = NULL; /* avoid warning */
2647 dynstr = NULL; /* avoid warning */
2648 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2649 switch(sh->sh_type) {
2650 case SHT_DYNAMIC:
2651 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2652 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2653 break;
2654 case SHT_DYNSYM:
2655 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2656 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2657 sh1 = &shdr[sh->sh_link];
2658 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2659 break;
2660 default:
2661 break;
2665 /* compute the real library name */
2666 soname = tcc_basename(filename);
2668 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2669 if (dt->d_tag == DT_SONAME) {
2670 soname = dynstr + dt->d_un.d_val;
2674 /* if the dll is already loaded, do not load it */
2675 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2676 dllref = s1->loaded_dlls[i];
2677 if (!strcmp(soname, dllref->name)) {
2678 /* but update level if needed */
2679 if (level < dllref->level)
2680 dllref->level = level;
2681 ret = 0;
2682 goto the_end;
2686 // printf("loading dll '%s'\n", soname);
2688 /* add the dll and its level */
2689 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2690 dllref->level = level;
2691 strcpy(dllref->name, soname);
2692 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2694 /* add dynamic symbols in dynsym_section */
2695 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2696 sym_bind = ELFW(ST_BIND)(sym->st_info);
2697 if (sym_bind == STB_LOCAL)
2698 continue;
2699 name = dynstr + sym->st_name;
2700 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2701 sym->st_info, sym->st_other, sym->st_shndx, name);
2704 /* load all referenced DLLs */
2705 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2706 switch(dt->d_tag) {
2707 case DT_NEEDED:
2708 name = dynstr + dt->d_un.d_val;
2709 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2710 dllref = s1->loaded_dlls[j];
2711 if (!strcmp(name, dllref->name))
2712 goto already_loaded;
2714 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2715 error_noabort("referenced dll '%s' not found", name);
2716 ret = -1;
2717 goto the_end;
2719 already_loaded:
2720 break;
2723 ret = 0;
2724 the_end:
2725 tcc_free(dynstr);
2726 tcc_free(dynsym);
2727 tcc_free(dynamic);
2728 tcc_free(shdr);
2729 return ret;
2732 #define LD_TOK_NAME 256
2733 #define LD_TOK_EOF (-1)
2735 /* return next ld script token */
2736 static int ld_next(TCCState *s1, char *name, int name_size)
2738 int c;
2739 char *q;
2741 redo:
2742 switch(ch) {
2743 case ' ':
2744 case '\t':
2745 case '\f':
2746 case '\v':
2747 case '\r':
2748 case '\n':
2749 inp();
2750 goto redo;
2751 case '/':
2752 minp();
2753 if (ch == '*') {
2754 file->buf_ptr = parse_comment(file->buf_ptr);
2755 ch = file->buf_ptr[0];
2756 goto redo;
2757 } else {
2758 q = name;
2759 *q++ = '/';
2760 goto parse_name;
2762 break;
2763 /* case 'a' ... 'z': */
2764 case 'a':
2765 case 'b':
2766 case 'c':
2767 case 'd':
2768 case 'e':
2769 case 'f':
2770 case 'g':
2771 case 'h':
2772 case 'i':
2773 case 'j':
2774 case 'k':
2775 case 'l':
2776 case 'm':
2777 case 'n':
2778 case 'o':
2779 case 'p':
2780 case 'q':
2781 case 'r':
2782 case 's':
2783 case 't':
2784 case 'u':
2785 case 'v':
2786 case 'w':
2787 case 'x':
2788 case 'y':
2789 case 'z':
2790 /* case 'A' ... 'z': */
2791 case 'A':
2792 case 'B':
2793 case 'C':
2794 case 'D':
2795 case 'E':
2796 case 'F':
2797 case 'G':
2798 case 'H':
2799 case 'I':
2800 case 'J':
2801 case 'K':
2802 case 'L':
2803 case 'M':
2804 case 'N':
2805 case 'O':
2806 case 'P':
2807 case 'Q':
2808 case 'R':
2809 case 'S':
2810 case 'T':
2811 case 'U':
2812 case 'V':
2813 case 'W':
2814 case 'X':
2815 case 'Y':
2816 case 'Z':
2817 case '_':
2818 case '\\':
2819 case '.':
2820 case '$':
2821 case '~':
2822 q = name;
2823 parse_name:
2824 for(;;) {
2825 if (!((ch >= 'a' && ch <= 'z') ||
2826 (ch >= 'A' && ch <= 'Z') ||
2827 (ch >= '0' && ch <= '9') ||
2828 strchr("/.-_+=$:\\,~", ch)))
2829 break;
2830 if ((q - name) < name_size - 1) {
2831 *q++ = ch;
2833 minp();
2835 *q = '\0';
2836 c = LD_TOK_NAME;
2837 break;
2838 case CH_EOF:
2839 c = LD_TOK_EOF;
2840 break;
2841 default:
2842 c = ch;
2843 inp();
2844 break;
2846 #if 0
2847 printf("tok=%c %d\n", c, c);
2848 if (c == LD_TOK_NAME)
2849 printf(" name=%s\n", name);
2850 #endif
2851 return c;
2854 char *tcc_strcpy_part(char *out, const char *in, size_t num)
2856 memcpy(out, in, num);
2857 out[num] = '\0';
2858 return out;
2862 * Extract the library name from the file name
2863 * Return 0 if the file isn't a library
2865 * /!\ No test on filename capacity, be careful
2867 static int filename_to_libname(TCCState *s1, const char filename[], char libname[])
2869 char *ext;
2870 int libprefix;
2872 /* already converted to library name */
2873 if (libname[0] != '\0')
2874 return 1;
2875 ext = tcc_fileextension(filename);
2876 if (*ext == '\0')
2877 return 0;
2878 libprefix = !strncmp(filename, "lib", 3);
2879 if (!s1->static_link) {
2880 #ifdef TCC_TARGET_PE
2881 if (!strcmp(ext, ".def")) {
2882 size_t len = ext - filename;
2883 tcc_strcpy_part(libname, filename, len);
2884 return 1;
2886 #else
2887 if (libprefix && (!strcmp(ext, ".so"))) {
2888 size_t len = ext - filename - 3;
2889 tcc_strcpy_part(libname, filename + 3, len);
2890 return 1;
2892 #endif
2893 } else {
2894 if (libprefix && (!strcmp(ext, ".a"))) {
2895 size_t len = ext - filename - 3;
2896 tcc_strcpy_part(libname, filename + 3, len);
2897 return 1;
2900 return 0;
2904 * Extract the file name from the library name
2906 * /!\ No test on filename capacity, be careful
2908 static void libname_to_filename(TCCState *s1, const char libname[], char filename[])
2910 if (!s1->static_link) {
2911 #ifdef TCC_TARGET_PE
2912 sprintf(filename, "%s.def", libname);
2913 #else
2914 sprintf(filename, "lib%s.so", libname);
2915 #endif
2916 } else {
2917 sprintf(filename, "lib%s.a", libname);
2921 static int ld_add_file(TCCState *s1, const char filename[], char libname[])
2923 int ret;
2925 ret = tcc_add_file_internal(s1, filename, 0);
2926 if (ret) {
2927 if (filename_to_libname(s1, filename, libname))
2928 ret = tcc_add_library(s1, libname);
2930 return ret;
2933 static inline int new_undef_syms(void)
2935 int ret = 0;
2936 ret = new_undef_sym;
2937 new_undef_sym = 0;
2938 return ret;
2941 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
2943 char filename[1024], libname[1024];
2944 int t, group, nblibs = 0, ret = 0;
2945 char **libs = NULL;
2947 group = !strcmp(cmd, "GROUP");
2948 if (!as_needed)
2949 new_undef_syms();
2950 t = ld_next(s1, filename, sizeof(filename));
2951 if (t != '(')
2952 expect("(");
2953 t = ld_next(s1, filename, sizeof(filename));
2954 for(;;) {
2955 libname[0] = '\0';
2956 if (t == LD_TOK_EOF) {
2957 error_noabort("unexpected end of file");
2958 ret = -1;
2959 goto lib_parse_error;
2960 } else if (t == ')') {
2961 break;
2962 } else if (t == '-') {
2963 t = ld_next(s1, filename, sizeof(filename));
2964 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
2965 error_noabort("library name expected");
2966 ret = -1;
2967 goto lib_parse_error;
2969 strcpy(libname, &filename[1]);
2970 libname_to_filename(s1, libname, filename);
2971 } else if (t != LD_TOK_NAME) {
2972 error_noabort("filename expected");
2973 ret = -1;
2974 goto lib_parse_error;
2976 if (!strcmp(filename, "AS_NEEDED")) {
2977 ret = ld_add_file_list(s1, cmd, 1);
2978 if (ret)
2979 goto lib_parse_error;
2980 } else {
2981 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2982 if (!as_needed) {
2983 ret = ld_add_file(s1, filename, libname);
2984 if (ret)
2985 goto lib_parse_error;
2986 if (group) {
2987 /* Add the filename *and* the libname to avoid future conversions */
2988 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
2989 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
2993 t = ld_next(s1, filename, sizeof(filename));
2994 if (t == ',') {
2995 t = ld_next(s1, filename, sizeof(filename));
2998 if (group && !as_needed) {
2999 while (new_undef_syms()) {
3000 int i;
3002 for (i = 0; i < nblibs; i += 2)
3003 ld_add_file(s1, libs[i], libs[i+1]);
3006 lib_parse_error:
3007 dynarray_reset(&libs, &nblibs);
3008 return ret;
3011 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3012 files */
3013 ST_FUNC int tcc_load_ldscript(TCCState *s1)
3015 char cmd[64];
3016 char filename[1024];
3017 int t, ret;
3019 ch = file->buf_ptr[0];
3020 ch = handle_eob();
3021 for(;;) {
3022 t = ld_next(s1, cmd, sizeof(cmd));
3023 if (t == LD_TOK_EOF)
3024 return 0;
3025 else if (t != LD_TOK_NAME)
3026 return -1;
3027 if (!strcmp(cmd, "INPUT") ||
3028 !strcmp(cmd, "GROUP")) {
3029 ret = ld_add_file_list(s1, cmd, 0);
3030 if (ret)
3031 return ret;
3032 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3033 !strcmp(cmd, "TARGET")) {
3034 /* ignore some commands */
3035 t = ld_next(s1, cmd, sizeof(cmd));
3036 if (t != '(')
3037 expect("(");
3038 for(;;) {
3039 t = ld_next(s1, filename, sizeof(filename));
3040 if (t == LD_TOK_EOF) {
3041 error_noabort("unexpected end of file");
3042 return -1;
3043 } else if (t == ')') {
3044 break;
3047 } else {
3048 return -1;
3051 return 0;
3053 #endif