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