get_reg(): try to free r2 for an SValue first
[tinycc.git] / tccelf.c
bloba16499ba7c86c9e1bba73a5cfc8696c25113ccad
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(s->symtab, name);
166 sym = &((ElfW(Sym) *)s->symtab->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_REL32:
638 *(int *)ptr += val - addr;
639 break;
640 case R_ARM_BASE_PREL:
641 *(int *)ptr += s1->got->sh_addr - addr;
642 break;
643 case R_ARM_GOTOFF32:
644 *(int *)ptr += val - s1->got->sh_addr;
645 break;
646 case R_ARM_GOT_BREL:
647 /* we load the got offset */
648 *(int *)ptr += s1->got_offsets[sym_index];
649 break;
650 case R_ARM_COPY:
651 break;
652 case R_ARM_V4BX:
653 /* trade Thumb support for ARMv4 support */
654 if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
655 *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
656 break;
657 default:
658 fprintf(stderr,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
659 type, (unsigned)addr, (unsigned)(uplong)ptr, (unsigned)val);
660 break;
661 #elif defined(TCC_TARGET_C67)
662 case R_C60_32:
663 *(int *)ptr += val;
664 break;
665 case R_C60LO16:
667 uint32_t orig;
669 /* put the low 16 bits of the absolute address */
670 // add to what is already there
672 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
673 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
675 //patch both at once - assumes always in pairs Low - High
677 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
678 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
680 break;
681 case R_C60HI16:
682 break;
683 default:
684 fprintf(stderr,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
685 type, (unsigned)addr, (unsigned)(uplong)ptr, (unsigned)val);
686 break;
687 #elif defined(TCC_TARGET_X86_64)
688 case R_X86_64_64:
689 if (s1->output_type == TCC_OUTPUT_DLL) {
690 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
691 qrel->r_addend = *(long long *)ptr + val;
692 qrel++;
694 *(long long *)ptr += val;
695 break;
696 case R_X86_64_32:
697 case R_X86_64_32S:
698 if (s1->output_type == TCC_OUTPUT_DLL) {
699 /* XXX: this logic may depend on TCC's codegen
700 now TCC uses R_X86_64_32 even for a 64bit pointer */
701 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
702 qrel->r_addend = *(int *)ptr + val;
703 qrel++;
705 *(int *)ptr += val;
706 break;
708 case R_X86_64_PC32:
709 if (s1->output_type == TCC_OUTPUT_DLL) {
710 /* DLL relocation */
711 esym_index = s1->symtab_to_dynsym[sym_index];
712 if (esym_index) {
713 qrel->r_offset = rel->r_offset;
714 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
715 qrel->r_addend = *(int *)ptr;
716 qrel++;
717 break;
720 /* fall through */
721 case R_X86_64_PLT32: {
722 long long diff;
723 diff = (long long)val - addr;
724 if (diff <= -2147483647 || diff > 2147483647) {
725 #ifndef TCC_TARGET_PE
726 /* XXX: naive support for over 32bit jump */
727 if (s1->output_type == TCC_OUTPUT_MEMORY) {
728 val = (add_jmp_table(s1, val - rel->r_addend) +
729 rel->r_addend);
730 diff = val - addr;
732 #endif
733 if (diff <= -2147483647 || diff > 2147483647) {
734 tcc_error("internal error: relocation failed");
737 *(int *)ptr += diff;
739 break;
740 case R_X86_64_GLOB_DAT:
741 case R_X86_64_JUMP_SLOT:
742 /* They don't need addend */
743 *(int *)ptr = val - rel->r_addend;
744 break;
745 case R_X86_64_GOTPCREL:
746 #ifndef TCC_TARGET_PE
747 if (s1->output_type == TCC_OUTPUT_MEMORY) {
748 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
749 *(int *)ptr += val - addr;
750 break;
752 #endif
753 *(int *)ptr += (s1->got->sh_addr - addr +
754 s1->got_offsets[sym_index] - 4);
755 break;
756 case R_X86_64_GOTTPOFF:
757 *(int *)ptr += val - s1->got->sh_addr;
758 break;
759 case R_X86_64_GOT32:
760 /* we load the got offset */
761 *(int *)ptr += s1->got_offsets[sym_index];
762 break;
763 #else
764 #error unsupported processor
765 #endif
768 /* if the relocation is allocated, we change its symbol table */
769 if (sr->sh_flags & SHF_ALLOC)
770 sr->link = s1->dynsym;
773 /* relocate relocation table in 'sr' */
774 static void relocate_rel(TCCState *s1, Section *sr)
776 Section *s;
777 ElfW_Rel *rel, *rel_end;
779 s = s1->sections[sr->sh_info];
780 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
781 for(rel = (ElfW_Rel *)sr->data;
782 rel < rel_end;
783 rel++) {
784 rel->r_offset += s->sh_addr;
788 /* count the number of dynamic relocations so that we can reserve
789 their space */
790 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
792 ElfW_Rel *rel, *rel_end;
793 int sym_index, esym_index, type, count;
795 count = 0;
796 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
797 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
798 sym_index = ELFW(R_SYM)(rel->r_info);
799 type = ELFW(R_TYPE)(rel->r_info);
800 switch(type) {
801 #if defined(TCC_TARGET_I386)
802 case R_386_32:
803 #elif defined(TCC_TARGET_X86_64)
804 case R_X86_64_32:
805 case R_X86_64_32S:
806 case R_X86_64_64:
807 #endif
808 count++;
809 break;
810 #if defined(TCC_TARGET_I386)
811 case R_386_PC32:
812 #elif defined(TCC_TARGET_X86_64)
813 case R_X86_64_PC32:
814 #endif
815 esym_index = s1->symtab_to_dynsym[sym_index];
816 if (esym_index)
817 count++;
818 break;
819 default:
820 break;
823 if (count) {
824 /* allocate the section */
825 sr->sh_flags |= SHF_ALLOC;
826 sr->sh_size = count * sizeof(ElfW_Rel);
828 return count;
831 static void put_got_offset(TCCState *s1, int index, unsigned long val)
833 int n;
834 unsigned long *tab;
836 if (index >= s1->nb_got_offsets) {
837 /* find immediately bigger power of 2 and reallocate array */
838 n = 1;
839 while (index >= n)
840 n *= 2;
841 tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
842 s1->got_offsets = tab;
843 memset(s1->got_offsets + s1->nb_got_offsets, 0,
844 (n - s1->nb_got_offsets) * sizeof(unsigned long));
845 s1->nb_got_offsets = n;
847 s1->got_offsets[index] = val;
850 /* XXX: suppress that */
851 static void put32(unsigned char *p, uint32_t val)
853 p[0] = val;
854 p[1] = val >> 8;
855 p[2] = val >> 16;
856 p[3] = val >> 24;
859 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
860 defined(TCC_TARGET_X86_64)
861 static uint32_t get32(unsigned char *p)
863 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
865 #endif
867 static void build_got(TCCState *s1)
869 unsigned char *ptr;
871 /* if no got, then create it */
872 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
873 s1->got->sh_entsize = 4;
874 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
875 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
876 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
877 #if PTR_SIZE == 4
878 /* keep space for _DYNAMIC pointer, if present */
879 put32(ptr, 0);
880 /* two dummy got entries */
881 put32(ptr + 4, 0);
882 put32(ptr + 8, 0);
883 #else
884 /* keep space for _DYNAMIC pointer, if present */
885 put32(ptr, 0);
886 put32(ptr + 4, 0);
887 /* two dummy got entries */
888 put32(ptr + 8, 0);
889 put32(ptr + 12, 0);
890 put32(ptr + 16, 0);
891 put32(ptr + 20, 0);
892 #endif
895 /* put a got entry corresponding to a symbol in symtab_section. 'size'
896 and 'info' can be modifed if more precise info comes from the DLL */
897 static void put_got_entry(TCCState *s1,
898 int reloc_type, unsigned long size, int info,
899 int sym_index)
901 int index;
902 const char *name;
903 ElfW(Sym) *sym;
904 unsigned long offset;
905 int *ptr;
907 if (!s1->got)
908 build_got(s1);
910 /* if a got entry already exists for that symbol, no need to add one */
911 if (sym_index < s1->nb_got_offsets &&
912 s1->got_offsets[sym_index] != 0)
913 return;
915 put_got_offset(s1, sym_index, s1->got->data_offset);
917 if (s1->dynsym) {
918 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
919 name = symtab_section->link->data + sym->st_name;
920 offset = sym->st_value;
921 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
922 if (reloc_type ==
923 #ifdef TCC_TARGET_X86_64
924 R_X86_64_JUMP_SLOT
925 #else
926 R_386_JMP_SLOT
927 #endif
929 Section *plt;
930 uint8_t *p;
931 int modrm;
933 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
934 modrm = 0x25;
935 #else
936 /* if we build a DLL, we add a %ebx offset */
937 if (s1->output_type == TCC_OUTPUT_DLL)
938 modrm = 0xa3;
939 else
940 modrm = 0x25;
941 #endif
943 /* add a PLT entry */
944 plt = s1->plt;
945 if (plt->data_offset == 0) {
946 /* first plt entry */
947 p = section_ptr_add(plt, 16);
948 p[0] = 0xff; /* pushl got + PTR_SIZE */
949 p[1] = modrm + 0x10;
950 put32(p + 2, PTR_SIZE);
951 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
952 p[7] = modrm;
953 put32(p + 8, PTR_SIZE * 2);
956 p = section_ptr_add(plt, 16);
957 p[0] = 0xff; /* jmp *(got + x) */
958 p[1] = modrm;
959 put32(p + 2, s1->got->data_offset);
960 p[6] = 0x68; /* push $xxx */
961 put32(p + 7, (plt->data_offset - 32) >> 1);
962 p[11] = 0xe9; /* jmp plt_start */
963 put32(p + 12, -(plt->data_offset));
965 /* the symbol is modified so that it will be relocated to
966 the PLT */
967 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
968 if (s1->output_type == TCC_OUTPUT_EXE)
969 #endif
970 offset = plt->data_offset - 16;
972 #elif defined(TCC_TARGET_ARM)
973 if (reloc_type == R_ARM_JUMP_SLOT) {
974 Section *plt;
975 uint8_t *p;
977 /* if we build a DLL, we add a %ebx offset */
978 if (s1->output_type == TCC_OUTPUT_DLL)
979 tcc_error("DLLs unimplemented!");
981 /* add a PLT entry */
982 plt = s1->plt;
983 if (plt->data_offset == 0) {
984 /* first plt entry */
985 p = section_ptr_add(plt, 16);
986 put32(p , 0xe52de004);
987 put32(p + 4, 0xe59fe010);
988 put32(p + 8, 0xe08fe00e);
989 put32(p + 12, 0xe5bef008);
992 p = section_ptr_add(plt, 16);
993 put32(p , 0xe59fc004);
994 put32(p+4, 0xe08fc00c);
995 put32(p+8, 0xe59cf000);
996 put32(p+12, s1->got->data_offset);
998 /* the symbol is modified so that it will be relocated to
999 the PLT */
1000 if (s1->output_type == TCC_OUTPUT_EXE)
1001 offset = plt->data_offset - 16;
1003 #elif defined(TCC_TARGET_C67)
1004 tcc_error("C67 got not implemented");
1005 #else
1006 #error unsupported CPU
1007 #endif
1008 index = put_elf_sym(s1->dynsym, offset,
1009 size, info, 0, sym->st_shndx, name);
1010 /* put a got entry */
1011 put_elf_reloc(s1->dynsym, s1->got,
1012 s1->got->data_offset,
1013 reloc_type, index);
1015 ptr = section_ptr_add(s1->got, PTR_SIZE);
1016 *ptr = 0;
1019 /* build GOT and PLT entries */
1020 ST_FUNC void build_got_entries(TCCState *s1)
1022 Section *s;
1023 ElfW_Rel *rel, *rel_end;
1024 ElfW(Sym) *sym;
1025 int i, type, reloc_type, sym_index;
1027 for(i = 1; i < s1->nb_sections; i++) {
1028 s = s1->sections[i];
1029 if (s->sh_type != SHT_RELX)
1030 continue;
1031 /* no need to handle got relocations */
1032 if (s->link != symtab_section)
1033 continue;
1034 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1035 for(rel = (ElfW_Rel *)s->data;
1036 rel < rel_end;
1037 rel++) {
1038 type = ELFW(R_TYPE)(rel->r_info);
1039 switch(type) {
1040 #if defined(TCC_TARGET_I386)
1041 case R_386_GOT32:
1042 case R_386_GOTOFF:
1043 case R_386_GOTPC:
1044 case R_386_PLT32:
1045 if (!s1->got)
1046 build_got(s1);
1047 if (type == R_386_GOT32 || type == R_386_PLT32) {
1048 sym_index = ELFW(R_SYM)(rel->r_info);
1049 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1050 /* look at the symbol got offset. If none, then add one */
1051 if (type == R_386_GOT32)
1052 reloc_type = R_386_GLOB_DAT;
1053 else
1054 reloc_type = R_386_JMP_SLOT;
1055 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1056 sym_index);
1058 break;
1059 #elif defined(TCC_TARGET_ARM)
1060 case R_ARM_GOT_BREL:
1061 case R_ARM_GOTOFF32:
1062 case R_ARM_BASE_PREL:
1063 case R_ARM_PLT32:
1064 if (!s1->got)
1065 build_got(s1);
1066 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1067 sym_index = ELFW(R_SYM)(rel->r_info);
1068 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1069 /* look at the symbol got offset. If none, then add one */
1070 if (type == R_ARM_GOT_BREL)
1071 reloc_type = R_ARM_GLOB_DAT;
1072 else
1073 reloc_type = R_ARM_JUMP_SLOT;
1074 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1075 sym_index);
1077 break;
1078 #elif defined(TCC_TARGET_C67)
1079 case R_C60_GOT32:
1080 case R_C60_GOTOFF:
1081 case R_C60_GOTPC:
1082 case R_C60_PLT32:
1083 if (!s1->got)
1084 build_got(s1);
1085 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1086 sym_index = ELFW(R_SYM)(rel->r_info);
1087 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1088 /* look at the symbol got offset. If none, then add one */
1089 if (type == R_C60_GOT32)
1090 reloc_type = R_C60_GLOB_DAT;
1091 else
1092 reloc_type = R_C60_JMP_SLOT;
1093 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1094 sym_index);
1096 break;
1097 #elif defined(TCC_TARGET_X86_64)
1098 case R_X86_64_GOT32:
1099 case R_X86_64_GOTTPOFF:
1100 case R_X86_64_GOTPCREL:
1101 case R_X86_64_PLT32:
1102 if (!s1->got)
1103 build_got(s1);
1104 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1105 type == R_X86_64_PLT32) {
1106 sym_index = ELFW(R_SYM)(rel->r_info);
1107 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1108 /* look at the symbol got offset. If none, then add one */
1109 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1110 reloc_type = R_X86_64_GLOB_DAT;
1111 else
1112 reloc_type = R_X86_64_JUMP_SLOT;
1113 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1114 sym_index);
1116 break;
1117 #else
1118 #error unsupported CPU
1119 #endif
1120 default:
1121 break;
1127 ST_FUNC Section *new_symtab(TCCState *s1,
1128 const char *symtab_name, int sh_type, int sh_flags,
1129 const char *strtab_name,
1130 const char *hash_name, int hash_sh_flags)
1132 Section *symtab, *strtab, *hash;
1133 int *ptr, nb_buckets;
1135 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1136 symtab->sh_entsize = sizeof(ElfW(Sym));
1137 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1138 put_elf_str(strtab, "");
1139 symtab->link = strtab;
1140 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1142 nb_buckets = 1;
1144 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1145 hash->sh_entsize = sizeof(int);
1146 symtab->hash = hash;
1147 hash->link = symtab;
1149 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1150 ptr[0] = nb_buckets;
1151 ptr[1] = 1;
1152 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1153 return symtab;
1156 /* put dynamic tag */
1157 static void put_dt(Section *dynamic, int dt, uplong val)
1159 ElfW(Dyn) *dyn;
1160 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1161 dyn->d_tag = dt;
1162 dyn->d_un.d_val = val;
1165 static void add_init_array_defines(TCCState *s1, const char *section_name)
1167 Section *s;
1168 long end_offset;
1169 char sym_start[1024];
1170 char sym_end[1024];
1172 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1173 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1175 s = find_section(s1, section_name);
1176 if (!s) {
1177 end_offset = 0;
1178 s = data_section;
1179 } else {
1180 end_offset = s->data_offset;
1183 add_elf_sym(symtab_section,
1184 0, 0,
1185 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1186 s->sh_num, sym_start);
1187 add_elf_sym(symtab_section,
1188 end_offset, 0,
1189 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1190 s->sh_num, sym_end);
1193 static int tcc_add_support(TCCState *s1, const char *filename)
1195 char buf[1024];
1196 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, filename);
1197 return tcc_add_file(s1, buf);
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
1219 tcc_add_support(s1, "bcheck.o");
1220 #endif
1221 #ifdef TCC_TARGET_I386
1222 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1223 /* add 'call __bound_init()' in .init section */
1224 init_section = find_section(s1, ".init");
1225 pinit = section_ptr_add(init_section, 5);
1226 pinit[0] = 0xe8;
1227 put32(pinit + 1, -4);
1228 sym_index = find_elf_sym(symtab_section, "__bound_init");
1229 put_elf_reloc(symtab_section, init_section,
1230 init_section->data_offset - 4, R_386_PC32, sym_index);
1232 #endif
1233 #endif
1236 /* add tcc runtime libraries */
1237 ST_FUNC void tcc_add_runtime(TCCState *s1)
1239 tcc_add_bcheck(s1);
1241 /* add libc */
1242 if (!s1->nostdlib) {
1243 tcc_add_library(s1, "c");
1244 #ifdef CONFIG_USE_LIBGCC
1245 tcc_add_file(s1, TCC_LIBGCC);
1246 #elif !defined WITHOUT_LIBTCC
1247 tcc_add_support(s1, "libtcc1.a");
1248 #endif
1249 /* add crt end if not memory output */
1250 if (s1->output_type != TCC_OUTPUT_MEMORY)
1251 tcc_add_crt(s1, "crtn.o");
1255 /* add various standard linker symbols (must be done after the
1256 sections are filled (for example after allocating common
1257 symbols)) */
1258 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1260 char buf[1024];
1261 int i;
1262 Section *s;
1264 add_elf_sym(symtab_section,
1265 text_section->data_offset, 0,
1266 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1267 text_section->sh_num, "_etext");
1268 add_elf_sym(symtab_section,
1269 data_section->data_offset, 0,
1270 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1271 data_section->sh_num, "_edata");
1272 add_elf_sym(symtab_section,
1273 bss_section->data_offset, 0,
1274 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1275 bss_section->sh_num, "_end");
1276 /* horrible new standard ldscript defines */
1277 add_init_array_defines(s1, ".preinit_array");
1278 add_init_array_defines(s1, ".init_array");
1279 add_init_array_defines(s1, ".fini_array");
1281 /* add start and stop symbols for sections whose name can be
1282 expressed in C */
1283 for(i = 1; i < s1->nb_sections; i++) {
1284 s = s1->sections[i];
1285 if (s->sh_type == SHT_PROGBITS &&
1286 (s->sh_flags & SHF_ALLOC)) {
1287 const char *p;
1288 int ch;
1290 /* check if section name can be expressed in C */
1291 p = s->name;
1292 for(;;) {
1293 ch = *p;
1294 if (!ch)
1295 break;
1296 if (!isid(ch) && !isnum(ch))
1297 goto next_sec;
1298 p++;
1300 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1301 add_elf_sym(symtab_section,
1302 0, 0,
1303 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1304 s->sh_num, buf);
1305 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1306 add_elf_sym(symtab_section,
1307 s->data_offset, 0,
1308 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1309 s->sh_num, buf);
1311 next_sec: ;
1315 static void tcc_output_binary(TCCState *s1, FILE *f,
1316 const int *section_order)
1318 Section *s;
1319 int i, offset, size;
1321 offset = 0;
1322 for(i=1;i<s1->nb_sections;i++) {
1323 s = s1->sections[section_order[i]];
1324 if (s->sh_type != SHT_NOBITS &&
1325 (s->sh_flags & SHF_ALLOC)) {
1326 while (offset < s->sh_offset) {
1327 fputc(0, f);
1328 offset++;
1330 size = s->sh_size;
1331 fwrite(s->data, 1, size, f);
1332 offset += size;
1337 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1338 #define HAVE_PHDR 1
1339 #define EXTRA_RELITEMS 14
1341 /* move the relocation value from .dynsym to .got */
1342 void patch_dynsym_undef(TCCState *s1, Section *s)
1344 uint32_t *gotd = (void *)s1->got->data;
1345 ElfW(Sym) *sym, *sym_end;
1347 gotd += 3; // dummy entries in .got
1348 /* relocate symbols in .dynsym */
1349 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1350 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1351 if (sym->st_shndx == SHN_UNDEF) {
1352 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1353 sym->st_value = 0;
1357 #else
1358 #define HAVE_PHDR 0
1359 #define EXTRA_RELITEMS 9
1361 /* zero plt offsets of weak symbols in .dynsym */
1362 void patch_dynsym_undef(TCCState *s1, Section *s)
1364 ElfW(Sym) *sym, *sym_end;
1366 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1367 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++)
1368 if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
1369 sym->st_value = 0;
1371 #endif
1373 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1375 int sym_index = ELFW(R_SYM) (rel->r_info);
1376 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1377 unsigned long offset;
1379 if (sym_index >= s1->nb_got_offsets)
1380 return;
1381 offset = s1->got_offsets[sym_index];
1382 section_reserve(s1->got, offset + PTR_SIZE);
1383 #ifdef TCC_TARGET_X86_64
1384 /* only works for x86-64 */
1385 put32(s1->got->data + offset + 4, sym->st_value >> 32);
1386 #endif
1387 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1390 ST_FUNC void fill_got(TCCState *s1)
1392 Section *s;
1393 ElfW_Rel *rel, *rel_end;
1394 int i;
1396 for(i = 1; i < s1->nb_sections; i++) {
1397 s = s1->sections[i];
1398 if (s->sh_type != SHT_RELX)
1399 continue;
1400 /* no need to handle got relocations */
1401 if (s->link != symtab_section)
1402 continue;
1403 rel_end = (ElfW_Rel *) (s->data + s->data_offset);
1404 for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
1405 switch (ELFW(R_TYPE) (rel->r_info)) {
1406 case R_X86_64_GOT32:
1407 case R_X86_64_GOTPCREL:
1408 case R_X86_64_PLT32:
1409 fill_got_entry(s1, rel);
1410 break;
1417 /* output an ELF file */
1418 /* XXX: suppress unneeded sections */
1419 static int elf_output_file(TCCState *s1, const char *filename)
1421 ElfW(Ehdr) ehdr;
1422 FILE *f;
1423 int fd, mode, ret;
1424 int *section_order;
1425 int shnum, i, phnum, file_offset, offset, size, j, sh_order_index, k;
1426 long long tmp;
1427 uplong addr;
1428 Section *strsec, *s;
1429 ElfW(Shdr) shdr, *sh;
1430 ElfW(Phdr) *phdr, *ph;
1431 Section *interp, *dynamic, *dynstr;
1432 unsigned long saved_dynamic_data_offset;
1433 ElfW(Sym) *sym;
1434 int type, file_type;
1435 uplong rel_addr, rel_size;
1436 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1437 uplong bss_addr, bss_size;
1438 #endif
1440 file_type = s1->output_type;
1441 s1->nb_errors = 0;
1443 if (file_type != TCC_OUTPUT_OBJ) {
1444 tcc_add_runtime(s1);
1447 phdr = NULL;
1448 section_order = NULL;
1449 interp = NULL;
1450 dynamic = NULL;
1451 dynstr = NULL; /* avoid warning */
1452 saved_dynamic_data_offset = 0; /* avoid warning */
1454 if (file_type != TCC_OUTPUT_OBJ) {
1455 relocate_common_syms();
1457 tcc_add_linker_symbols(s1);
1459 if (!s1->static_link) {
1460 const char *name;
1461 int sym_index, index;
1462 ElfW(Sym) *esym, *sym_end;
1464 if (file_type == TCC_OUTPUT_EXE) {
1465 char *ptr;
1466 /* allow override the dynamic loader */
1467 const char *elfint = getenv("LD_SO");
1468 if (elfint == NULL)
1469 elfint = CONFIG_TCC_ELFINTERP;
1470 /* add interpreter section only if executable */
1471 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1472 interp->sh_addralign = 1;
1473 ptr = section_ptr_add(interp, 1+strlen(elfint));
1474 strcpy(ptr, elfint);
1477 /* add dynamic symbol table */
1478 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1479 ".dynstr",
1480 ".hash", SHF_ALLOC);
1481 dynstr = s1->dynsym->link;
1483 /* add dynamic section */
1484 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1485 SHF_ALLOC | SHF_WRITE);
1486 dynamic->link = dynstr;
1487 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1489 /* add PLT */
1490 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1491 SHF_ALLOC | SHF_EXECINSTR);
1492 s1->plt->sh_entsize = 4;
1494 build_got(s1);
1496 /* scan for undefined symbols and see if they are in the
1497 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1498 is found, then we add it in the PLT. If a symbol
1499 STT_OBJECT is found, we add it in the .bss section with
1500 a suitable relocation */
1501 sym_end = (ElfW(Sym) *)(symtab_section->data +
1502 symtab_section->data_offset);
1503 if (file_type == TCC_OUTPUT_EXE) {
1504 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1505 sym < sym_end;
1506 sym++) {
1507 if (sym->st_shndx == SHN_UNDEF) {
1508 name = symtab_section->link->data + sym->st_name;
1509 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1510 if (sym_index) {
1511 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1512 type = ELFW(ST_TYPE)(esym->st_info);
1513 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1514 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1515 ELFW(ST_INFO)(STB_GLOBAL,type),
1516 sym - (ElfW(Sym) *)symtab_section->data);
1517 } else if (type == STT_OBJECT) {
1518 unsigned long offset;
1519 ElfW(Sym) *dynsym, *dynsym_end;
1520 offset = bss_section->data_offset;
1521 /* XXX: which alignment ? */
1522 offset = (offset + 16 - 1) & -16;
1523 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1524 esym->st_info, 0,
1525 bss_section->sh_num, name);
1526 // Ensure R_COPY works for weak symbol aliases
1527 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1528 dynsym_end = (ElfW(Sym) *)
1529 (s1->dynsymtab_section->data +
1530 s1->dynsymtab_section->data_offset);
1531 for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1532 dynsym < dynsym_end; dynsym++) {
1533 if ((dynsym->st_value == esym->st_value)
1534 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1535 char *dynname;
1536 dynname = s1->dynsymtab_section->link->data
1537 + dynsym->st_name;
1538 put_elf_sym(s1->dynsym, offset,
1539 dynsym->st_size,
1540 dynsym->st_info, 0,
1541 bss_section->sh_num,
1542 dynname);
1543 break;
1547 put_elf_reloc(s1->dynsym, bss_section,
1548 offset, R_COPY, index);
1549 offset += esym->st_size;
1550 bss_section->data_offset = offset;
1552 } else {
1553 /* STB_WEAK undefined symbols are accepted */
1554 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1555 it */
1556 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1557 !strcmp(name, "_fp_hw")) {
1558 } else {
1559 tcc_error_noabort("undefined symbol '%s'", name);
1562 } else if (s1->rdynamic &&
1563 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1564 /* if -rdynamic option, then export all non
1565 local symbols */
1566 name = symtab_section->link->data + sym->st_name;
1567 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1568 sym->st_info, 0,
1569 sym->st_shndx, name);
1573 if (s1->nb_errors)
1574 goto fail;
1576 /* now look at unresolved dynamic symbols and export
1577 corresponding symbol */
1578 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1579 s1->dynsymtab_section->data_offset);
1580 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1581 esym < sym_end;
1582 esym++) {
1583 if (esym->st_shndx == SHN_UNDEF) {
1584 name = s1->dynsymtab_section->link->data + esym->st_name;
1585 sym_index = find_elf_sym(symtab_section, name);
1586 if (sym_index) {
1587 /* XXX: avoid adding a symbol if already
1588 present because of -rdynamic ? */
1589 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1590 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1591 sym->st_info, 0,
1592 sym->st_shndx, name);
1593 } else {
1594 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1595 /* weak symbols can stay undefined */
1596 } else {
1597 tcc_warning("undefined dynamic symbol '%s'", name);
1602 } else {
1603 int nb_syms;
1604 /* shared library case : we simply export all the global symbols */
1605 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1606 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1607 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1608 sym < sym_end;
1609 sym++) {
1610 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1611 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1612 if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
1613 ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
1614 && sym->st_shndx == SHN_UNDEF) {
1615 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1616 sym->st_info,
1617 sym - (ElfW(Sym) *)symtab_section->data);
1619 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1620 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1621 sym->st_info,
1622 sym - (ElfW(Sym) *)symtab_section->data);
1624 else
1625 #endif
1627 name = symtab_section->link->data + sym->st_name;
1628 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1629 sym->st_info, 0,
1630 sym->st_shndx, name);
1631 s1->symtab_to_dynsym[sym -
1632 (ElfW(Sym) *)symtab_section->data] =
1633 index;
1639 build_got_entries(s1);
1641 /* add a list of needed dlls */
1642 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1643 DLLReference *dllref = s1->loaded_dlls[i];
1644 if (dllref->level == 0)
1645 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1648 if (s1->rpath)
1649 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1651 /* XXX: currently, since we do not handle PIC code, we
1652 must relocate the readonly segments */
1653 if (file_type == TCC_OUTPUT_DLL) {
1654 if (s1->soname)
1655 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1656 put_dt(dynamic, DT_TEXTREL, 0);
1659 if (s1->symbolic)
1660 put_dt(dynamic, DT_SYMBOLIC, 0);
1662 /* add necessary space for other entries */
1663 saved_dynamic_data_offset = dynamic->data_offset;
1664 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1665 } else {
1666 /* still need to build got entries in case of static link */
1667 build_got_entries(s1);
1671 memset(&ehdr, 0, sizeof(ehdr));
1673 /* we add a section for symbols */
1674 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1675 put_elf_str(strsec, "");
1677 /* compute number of sections */
1678 shnum = s1->nb_sections;
1680 /* this array is used to reorder sections in the output file */
1681 section_order = tcc_malloc(sizeof(int) * shnum);
1682 section_order[0] = 0;
1683 sh_order_index = 1;
1685 /* compute number of program headers */
1686 switch(file_type) {
1687 default:
1688 case TCC_OUTPUT_OBJ:
1689 phnum = 0;
1690 break;
1691 case TCC_OUTPUT_EXE:
1692 if (!s1->static_link)
1693 phnum = 4 + HAVE_PHDR;
1694 else
1695 phnum = 2;
1696 break;
1697 case TCC_OUTPUT_DLL:
1698 phnum = 3;
1699 break;
1702 /* allocate strings for section names and decide if an unallocated
1703 section should be output */
1704 /* NOTE: the strsec section comes last, so its size is also
1705 correct ! */
1706 for(i = 1; i < s1->nb_sections; i++) {
1707 s = s1->sections[i];
1708 s->sh_name = put_elf_str(strsec, s->name);
1709 #if 0 //gr
1710 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1711 s->sh_flags,
1712 s->sh_type,
1713 s->sh_info,
1714 s->name,
1715 s->reloc ? s->reloc->name : "n"
1717 #endif
1718 /* when generating a DLL, we include relocations but we may
1719 patch them */
1720 if (file_type == TCC_OUTPUT_DLL &&
1721 s->sh_type == SHT_RELX &&
1722 !(s->sh_flags & SHF_ALLOC)) {
1723 /* //gr: avoid bogus relocs for empty (debug) sections */
1724 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1725 prepare_dynamic_rel(s1, s);
1726 else if (s1->do_debug)
1727 s->sh_size = s->data_offset;
1728 } else if (s1->do_debug ||
1729 file_type == TCC_OUTPUT_OBJ ||
1730 (s->sh_flags & SHF_ALLOC) ||
1731 i == (s1->nb_sections - 1)) {
1732 /* we output all sections if debug or object file */
1733 s->sh_size = s->data_offset;
1737 /* allocate program segment headers */
1738 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1740 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1741 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1742 } else {
1743 file_offset = 0;
1745 if (phnum > 0) {
1746 /* compute section to program header mapping */
1747 if (s1->has_text_addr) {
1748 int a_offset, p_offset;
1749 addr = s1->text_addr;
1750 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1751 ELF_PAGE_SIZE */
1752 a_offset = (int) (addr & (s1->section_align - 1));
1753 p_offset = file_offset & (s1->section_align - 1);
1754 if (a_offset < p_offset)
1755 a_offset += s1->section_align;
1756 file_offset += (a_offset - p_offset);
1757 } else {
1758 if (file_type == TCC_OUTPUT_DLL)
1759 addr = 0;
1760 else
1761 addr = ELF_START_ADDR;
1762 /* compute address after headers */
1763 addr += (file_offset & (s1->section_align - 1));
1766 /* dynamic relocation table information, for .dynamic section */
1767 rel_size = 0;
1768 rel_addr = 0;
1770 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1771 bss_addr = bss_size = 0;
1772 #endif
1773 /* leave one program header for the program interpreter */
1774 ph = &phdr[0];
1775 if (interp)
1776 ph += 1 + HAVE_PHDR;
1778 for(j = 0; j < 2; j++) {
1779 ph->p_type = PT_LOAD;
1780 if (j == 0)
1781 ph->p_flags = PF_R | PF_X;
1782 else
1783 ph->p_flags = PF_R | PF_W;
1784 ph->p_align = s1->section_align;
1786 /* we do the following ordering: interp, symbol tables,
1787 relocations, progbits, nobits */
1788 /* XXX: do faster and simpler sorting */
1789 for(k = 0; k < 5; k++) {
1790 for(i = 1; i < s1->nb_sections; i++) {
1791 s = s1->sections[i];
1792 /* compute if section should be included */
1793 if (j == 0) {
1794 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1795 SHF_ALLOC)
1796 continue;
1797 } else {
1798 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1799 (SHF_ALLOC | SHF_WRITE))
1800 continue;
1802 if (s == interp) {
1803 if (k != 0)
1804 continue;
1805 } else if (s->sh_type == SHT_DYNSYM ||
1806 s->sh_type == SHT_STRTAB ||
1807 s->sh_type == SHT_HASH) {
1808 if (k != 1)
1809 continue;
1810 } else if (s->sh_type == SHT_RELX) {
1811 if (k != 2)
1812 continue;
1813 } else if (s->sh_type == SHT_NOBITS) {
1814 if (k != 4)
1815 continue;
1816 } else {
1817 if (k != 3)
1818 continue;
1820 section_order[sh_order_index++] = i;
1822 /* section matches: we align it and add its size */
1823 tmp = addr;
1824 addr = (addr + s->sh_addralign - 1) &
1825 ~(s->sh_addralign - 1);
1826 file_offset += (int) ( addr - tmp );
1827 s->sh_offset = file_offset;
1828 s->sh_addr = addr;
1830 /* update program header infos */
1831 if (ph->p_offset == 0) {
1832 ph->p_offset = file_offset;
1833 ph->p_vaddr = addr;
1834 ph->p_paddr = ph->p_vaddr;
1836 /* update dynamic relocation infos */
1837 if (s->sh_type == SHT_RELX) {
1838 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1839 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1840 rel_addr = addr;
1841 rel_size += s->sh_size; // XXX only first rel.
1843 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1844 bss_addr = addr;
1845 bss_size = s->sh_size; // XXX only first rel.
1847 #else
1848 if (rel_size == 0)
1849 rel_addr = addr;
1850 rel_size += s->sh_size;
1851 #endif
1853 addr += s->sh_size;
1854 if (s->sh_type != SHT_NOBITS)
1855 file_offset += s->sh_size;
1858 ph->p_filesz = file_offset - ph->p_offset;
1859 ph->p_memsz = addr - ph->p_vaddr;
1860 ph++;
1861 if (j == 0) {
1862 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1863 /* if in the middle of a page, we duplicate the page in
1864 memory so that one copy is RX and the other is RW */
1865 if ((addr & (s1->section_align - 1)) != 0)
1866 addr += s1->section_align;
1867 } else {
1868 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1869 file_offset = (file_offset + s1->section_align - 1) &
1870 ~(s1->section_align - 1);
1875 /* if interpreter, then add corresponing program header */
1876 if (interp) {
1877 ph = &phdr[0];
1879 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1881 int len = phnum * sizeof(ElfW(Phdr));
1883 ph->p_type = PT_PHDR;
1884 ph->p_offset = sizeof(ElfW(Ehdr));
1885 ph->p_vaddr = interp->sh_addr - len;
1886 ph->p_paddr = ph->p_vaddr;
1887 ph->p_filesz = ph->p_memsz = len;
1888 ph->p_flags = PF_R | PF_X;
1889 ph->p_align = 4; // interp->sh_addralign;
1890 ph++;
1892 #endif
1894 ph->p_type = PT_INTERP;
1895 ph->p_offset = interp->sh_offset;
1896 ph->p_vaddr = interp->sh_addr;
1897 ph->p_paddr = ph->p_vaddr;
1898 ph->p_filesz = interp->sh_size;
1899 ph->p_memsz = interp->sh_size;
1900 ph->p_flags = PF_R;
1901 ph->p_align = interp->sh_addralign;
1904 /* if dynamic section, then add corresponing program header */
1905 if (dynamic) {
1906 ElfW(Sym) *sym_end;
1908 ph = &phdr[phnum - 1];
1910 ph->p_type = PT_DYNAMIC;
1911 ph->p_offset = dynamic->sh_offset;
1912 ph->p_vaddr = dynamic->sh_addr;
1913 ph->p_paddr = ph->p_vaddr;
1914 ph->p_filesz = dynamic->sh_size;
1915 ph->p_memsz = dynamic->sh_size;
1916 ph->p_flags = PF_R | PF_W;
1917 ph->p_align = dynamic->sh_addralign;
1919 /* put GOT dynamic section address */
1920 put32(s1->got->data, dynamic->sh_addr);
1922 /* relocate the PLT */
1923 if (file_type == TCC_OUTPUT_EXE
1924 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1925 || file_type == TCC_OUTPUT_DLL
1926 #endif
1928 uint8_t *p, *p_end;
1930 p = s1->plt->data;
1931 p_end = p + s1->plt->data_offset;
1932 if (p < p_end) {
1933 #if defined(TCC_TARGET_I386)
1934 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1935 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1936 p += 16;
1937 while (p < p_end) {
1938 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1939 p += 16;
1941 #elif defined(TCC_TARGET_X86_64)
1942 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1943 put32(p + 2, get32(p + 2) + x);
1944 put32(p + 8, get32(p + 8) + x - 6);
1945 p += 16;
1946 while (p < p_end) {
1947 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1948 p += 16;
1950 #elif defined(TCC_TARGET_ARM)
1951 int x;
1952 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1953 p +=16;
1954 while (p < p_end) {
1955 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1956 p += 16;
1958 #elif defined(TCC_TARGET_C67)
1959 /* XXX: TODO */
1960 #else
1961 #error unsupported CPU
1962 #endif
1966 /* relocate symbols in .dynsym */
1967 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
1968 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
1969 sym < sym_end;
1970 sym++) {
1971 if (sym->st_shndx == SHN_UNDEF) {
1972 /* relocate to the PLT if the symbol corresponds
1973 to a PLT entry */
1974 if (sym->st_value)
1975 sym->st_value += s1->plt->sh_addr;
1976 } else if (sym->st_shndx < SHN_LORESERVE) {
1977 /* do symbol relocation */
1978 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
1982 /* put dynamic section entries */
1983 dynamic->data_offset = saved_dynamic_data_offset;
1984 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
1985 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
1986 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
1987 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
1988 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
1989 #ifdef TCC_TARGET_X86_64
1990 put_dt(dynamic, DT_RELA, rel_addr);
1991 put_dt(dynamic, DT_RELASZ, rel_size);
1992 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
1993 #else
1994 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1995 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
1996 put_dt(dynamic, DT_PLTRELSZ, rel_size);
1997 put_dt(dynamic, DT_JMPREL, rel_addr);
1998 put_dt(dynamic, DT_PLTREL, DT_REL);
1999 put_dt(dynamic, DT_REL, bss_addr);
2000 put_dt(dynamic, DT_RELSZ, bss_size);
2001 #else
2002 put_dt(dynamic, DT_REL, rel_addr);
2003 put_dt(dynamic, DT_RELSZ, rel_size);
2004 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2005 #endif
2006 #endif
2007 if (s1->do_debug)
2008 put_dt(dynamic, DT_DEBUG, 0);
2009 put_dt(dynamic, DT_NULL, 0);
2012 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2013 ehdr.e_phnum = phnum;
2014 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2017 /* all other sections come after */
2018 for(i = 1; i < s1->nb_sections; i++) {
2019 s = s1->sections[i];
2020 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2021 continue;
2022 section_order[sh_order_index++] = i;
2024 file_offset = (file_offset + s->sh_addralign - 1) &
2025 ~(s->sh_addralign - 1);
2026 s->sh_offset = file_offset;
2027 if (s->sh_type != SHT_NOBITS)
2028 file_offset += s->sh_size;
2031 /* if building executable or DLL, then relocate each section
2032 except the GOT which is already relocated */
2033 if (file_type != TCC_OUTPUT_OBJ) {
2034 relocate_syms(s1, 0);
2036 if (s1->nb_errors != 0) {
2037 fail:
2038 ret = -1;
2039 goto the_end;
2042 /* relocate sections */
2043 /* XXX: ignore sections with allocated relocations ? */
2044 for(i = 1; i < s1->nb_sections; i++) {
2045 s = s1->sections[i];
2046 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
2047 relocate_section(s1, s);
2050 /* relocate relocation entries if the relocation tables are
2051 allocated in the executable */
2052 for(i = 1; i < s1->nb_sections; i++) {
2053 s = s1->sections[i];
2054 if ((s->sh_flags & SHF_ALLOC) &&
2055 s->sh_type == SHT_RELX) {
2056 relocate_rel(s1, s);
2060 /* get entry point address */
2061 if (file_type == TCC_OUTPUT_EXE)
2062 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
2063 else
2064 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2066 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2067 fill_got(s1);
2069 /* write elf file */
2070 if (file_type == TCC_OUTPUT_OBJ)
2071 mode = 0666;
2072 else
2073 mode = 0777;
2074 unlink(filename);
2075 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2076 if (fd < 0) {
2077 tcc_error_noabort("could not write '%s'", filename);
2078 goto fail;
2080 f = fdopen(fd, "wb");
2081 if (s1->verbose)
2082 printf("<- %s\n", filename);
2084 #ifdef TCC_TARGET_COFF
2085 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2086 tcc_output_coff(s1, f);
2087 } else
2088 #endif
2089 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2090 sort_syms(s1, symtab_section);
2092 /* align to 4 */
2093 file_offset = (file_offset + 3) & -4;
2095 /* fill header */
2096 ehdr.e_ident[0] = ELFMAG0;
2097 ehdr.e_ident[1] = ELFMAG1;
2098 ehdr.e_ident[2] = ELFMAG2;
2099 ehdr.e_ident[3] = ELFMAG3;
2100 ehdr.e_ident[4] = ELFCLASSW;
2101 ehdr.e_ident[5] = ELFDATA2LSB;
2102 ehdr.e_ident[6] = EV_CURRENT;
2103 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2104 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2105 #endif
2106 #ifdef TCC_TARGET_ARM
2107 #ifdef TCC_ARM_EABI
2108 ehdr.e_ident[EI_OSABI] = 0;
2109 ehdr.e_flags = 4 << 24;
2110 #else
2111 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2112 #endif
2113 #endif
2114 switch(file_type) {
2115 default:
2116 case TCC_OUTPUT_EXE:
2117 ehdr.e_type = ET_EXEC;
2118 break;
2119 case TCC_OUTPUT_DLL:
2120 ehdr.e_type = ET_DYN;
2121 break;
2122 case TCC_OUTPUT_OBJ:
2123 ehdr.e_type = ET_REL;
2124 break;
2126 ehdr.e_machine = EM_TCC_TARGET;
2127 ehdr.e_version = EV_CURRENT;
2128 ehdr.e_shoff = file_offset;
2129 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2130 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2131 ehdr.e_shnum = shnum;
2132 ehdr.e_shstrndx = shnum - 1;
2134 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2135 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2136 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2138 for(i=1;i<s1->nb_sections;i++) {
2139 s = s1->sections[section_order[i]];
2140 if (s->sh_type != SHT_NOBITS) {
2141 if (s->sh_type == SHT_DYNSYM)
2142 patch_dynsym_undef(s1, s);
2143 while (offset < s->sh_offset) {
2144 fputc(0, f);
2145 offset++;
2147 size = s->sh_size;
2148 fwrite(s->data, 1, size, f);
2149 offset += size;
2153 /* output section headers */
2154 while (offset < ehdr.e_shoff) {
2155 fputc(0, f);
2156 offset++;
2159 for(i=0;i<s1->nb_sections;i++) {
2160 sh = &shdr;
2161 memset(sh, 0, sizeof(ElfW(Shdr)));
2162 s = s1->sections[i];
2163 if (s) {
2164 sh->sh_name = s->sh_name;
2165 sh->sh_type = s->sh_type;
2166 sh->sh_flags = s->sh_flags;
2167 sh->sh_entsize = s->sh_entsize;
2168 sh->sh_info = s->sh_info;
2169 if (s->link)
2170 sh->sh_link = s->link->sh_num;
2171 sh->sh_addralign = s->sh_addralign;
2172 sh->sh_addr = s->sh_addr;
2173 sh->sh_offset = s->sh_offset;
2174 sh->sh_size = s->sh_size;
2176 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2178 } else {
2179 tcc_output_binary(s1, f, section_order);
2181 fclose(f);
2183 ret = 0;
2184 the_end:
2185 tcc_free(s1->symtab_to_dynsym);
2186 tcc_free(section_order);
2187 tcc_free(phdr);
2188 tcc_free(s1->got_offsets);
2189 return ret;
2192 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2194 int ret;
2195 #ifdef TCC_TARGET_PE
2196 if (s->output_type != TCC_OUTPUT_OBJ) {
2197 ret = pe_output_file(s, filename);
2198 } else
2199 #endif
2201 ret = elf_output_file(s, filename);
2203 return ret;
2206 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2208 void *data;
2210 data = tcc_malloc(size);
2211 lseek(fd, file_offset, SEEK_SET);
2212 read(fd, data, size);
2213 return data;
2216 typedef struct SectionMergeInfo {
2217 Section *s; /* corresponding existing section */
2218 unsigned long offset; /* offset of the new section in the existing section */
2219 uint8_t new_section; /* true if section 's' was added */
2220 uint8_t link_once; /* true if link once section */
2221 } SectionMergeInfo;
2223 /* load an object file and merge it with current files */
2224 /* XXX: handle correctly stab (debug) info */
2225 ST_FUNC int tcc_load_object_file(TCCState *s1,
2226 int fd, unsigned long file_offset)
2228 ElfW(Ehdr) ehdr;
2229 ElfW(Shdr) *shdr, *sh;
2230 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2231 unsigned char *strsec, *strtab;
2232 int *old_to_new_syms;
2233 char *sh_name, *name;
2234 SectionMergeInfo *sm_table, *sm;
2235 ElfW(Sym) *sym, *symtab;
2236 ElfW_Rel *rel, *rel_end;
2237 Section *s;
2239 int stab_index;
2240 int stabstr_index;
2242 stab_index = stabstr_index = 0;
2244 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2245 goto fail1;
2246 if (ehdr.e_ident[0] != ELFMAG0 ||
2247 ehdr.e_ident[1] != ELFMAG1 ||
2248 ehdr.e_ident[2] != ELFMAG2 ||
2249 ehdr.e_ident[3] != ELFMAG3)
2250 goto fail1;
2251 /* test if object file */
2252 if (ehdr.e_type != ET_REL)
2253 goto fail1;
2254 /* test CPU specific stuff */
2255 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2256 ehdr.e_machine != EM_TCC_TARGET) {
2257 fail1:
2258 tcc_error_noabort("invalid object file");
2259 return -1;
2261 /* read sections */
2262 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2263 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2264 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2266 /* load section names */
2267 sh = &shdr[ehdr.e_shstrndx];
2268 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2270 /* load symtab and strtab */
2271 old_to_new_syms = NULL;
2272 symtab = NULL;
2273 strtab = NULL;
2274 nb_syms = 0;
2275 for(i = 1; i < ehdr.e_shnum; i++) {
2276 sh = &shdr[i];
2277 if (sh->sh_type == SHT_SYMTAB) {
2278 if (symtab) {
2279 tcc_error_noabort("object must contain only one symtab");
2280 fail:
2281 ret = -1;
2282 goto the_end;
2284 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2285 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2286 sm_table[i].s = symtab_section;
2288 /* now load strtab */
2289 sh = &shdr[sh->sh_link];
2290 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2294 /* now examine each section and try to merge its content with the
2295 ones in memory */
2296 for(i = 1; i < ehdr.e_shnum; i++) {
2297 /* no need to examine section name strtab */
2298 if (i == ehdr.e_shstrndx)
2299 continue;
2300 sh = &shdr[i];
2301 sh_name = strsec + sh->sh_name;
2302 /* ignore sections types we do not handle */
2303 if (sh->sh_type != SHT_PROGBITS &&
2304 sh->sh_type != SHT_RELX &&
2305 #ifdef TCC_ARM_EABI
2306 sh->sh_type != SHT_ARM_EXIDX &&
2307 #endif
2308 sh->sh_type != SHT_NOBITS &&
2309 sh->sh_type != SHT_PREINIT_ARRAY &&
2310 sh->sh_type != SHT_INIT_ARRAY &&
2311 sh->sh_type != SHT_FINI_ARRAY &&
2312 strcmp(sh_name, ".stabstr")
2314 continue;
2315 if (sh->sh_addralign < 1)
2316 sh->sh_addralign = 1;
2317 /* find corresponding section, if any */
2318 for(j = 1; j < s1->nb_sections;j++) {
2319 s = s1->sections[j];
2320 if (!strcmp(s->name, sh_name)) {
2321 if (!strncmp(sh_name, ".gnu.linkonce",
2322 sizeof(".gnu.linkonce") - 1)) {
2323 /* if a 'linkonce' section is already present, we
2324 do not add it again. It is a little tricky as
2325 symbols can still be defined in
2326 it. */
2327 sm_table[i].link_once = 1;
2328 goto next;
2329 } else {
2330 goto found;
2334 /* not found: create new section */
2335 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2336 /* take as much info as possible from the section. sh_link and
2337 sh_info will be updated later */
2338 s->sh_addralign = sh->sh_addralign;
2339 s->sh_entsize = sh->sh_entsize;
2340 sm_table[i].new_section = 1;
2341 found:
2342 if (sh->sh_type != s->sh_type) {
2343 tcc_error_noabort("invalid section type");
2344 goto fail;
2347 /* align start of section */
2348 offset = s->data_offset;
2350 if (0 == strcmp(sh_name, ".stab")) {
2351 stab_index = i;
2352 goto no_align;
2354 if (0 == strcmp(sh_name, ".stabstr")) {
2355 stabstr_index = i;
2356 goto no_align;
2359 size = sh->sh_addralign - 1;
2360 offset = (offset + size) & ~size;
2361 if (sh->sh_addralign > s->sh_addralign)
2362 s->sh_addralign = sh->sh_addralign;
2363 s->data_offset = offset;
2364 no_align:
2365 sm_table[i].offset = offset;
2366 sm_table[i].s = s;
2367 /* concatenate sections */
2368 size = sh->sh_size;
2369 if (sh->sh_type != SHT_NOBITS) {
2370 unsigned char *ptr;
2371 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2372 ptr = section_ptr_add(s, size);
2373 read(fd, ptr, size);
2374 } else {
2375 s->data_offset += size;
2377 next: ;
2380 /* //gr relocate stab strings */
2381 if (stab_index && stabstr_index) {
2382 Stab_Sym *a, *b;
2383 unsigned o;
2384 s = sm_table[stab_index].s;
2385 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2386 b = (Stab_Sym *)(s->data + s->data_offset);
2387 o = sm_table[stabstr_index].offset;
2388 while (a < b)
2389 a->n_strx += o, a++;
2392 /* second short pass to update sh_link and sh_info fields of new
2393 sections */
2394 for(i = 1; i < ehdr.e_shnum; i++) {
2395 s = sm_table[i].s;
2396 if (!s || !sm_table[i].new_section)
2397 continue;
2398 sh = &shdr[i];
2399 if (sh->sh_link > 0)
2400 s->link = sm_table[sh->sh_link].s;
2401 if (sh->sh_type == SHT_RELX) {
2402 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2403 /* update backward link */
2404 s1->sections[s->sh_info]->reloc = s;
2407 sm = sm_table;
2409 /* resolve symbols */
2410 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2412 sym = symtab + 1;
2413 for(i = 1; i < nb_syms; i++, sym++) {
2414 if (sym->st_shndx != SHN_UNDEF &&
2415 sym->st_shndx < SHN_LORESERVE) {
2416 sm = &sm_table[sym->st_shndx];
2417 if (sm->link_once) {
2418 /* if a symbol is in a link once section, we use the
2419 already defined symbol. It is very important to get
2420 correct relocations */
2421 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2422 name = strtab + sym->st_name;
2423 sym_index = find_elf_sym(symtab_section, name);
2424 if (sym_index)
2425 old_to_new_syms[i] = sym_index;
2427 continue;
2429 /* if no corresponding section added, no need to add symbol */
2430 if (!sm->s)
2431 continue;
2432 /* convert section number */
2433 sym->st_shndx = sm->s->sh_num;
2434 /* offset value */
2435 sym->st_value += sm->offset;
2437 /* add symbol */
2438 name = strtab + sym->st_name;
2439 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2440 sym->st_info, sym->st_other,
2441 sym->st_shndx, name);
2442 old_to_new_syms[i] = sym_index;
2445 /* third pass to patch relocation entries */
2446 for(i = 1; i < ehdr.e_shnum; i++) {
2447 s = sm_table[i].s;
2448 if (!s)
2449 continue;
2450 sh = &shdr[i];
2451 offset = sm_table[i].offset;
2452 switch(s->sh_type) {
2453 case SHT_RELX:
2454 /* take relocation offset information */
2455 offseti = sm_table[sh->sh_info].offset;
2456 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2457 for(rel = (ElfW_Rel *)(s->data + offset);
2458 rel < rel_end;
2459 rel++) {
2460 int type;
2461 unsigned sym_index;
2462 /* convert symbol index */
2463 type = ELFW(R_TYPE)(rel->r_info);
2464 sym_index = ELFW(R_SYM)(rel->r_info);
2465 /* NOTE: only one symtab assumed */
2466 if (sym_index >= nb_syms)
2467 goto invalid_reloc;
2468 sym_index = old_to_new_syms[sym_index];
2469 /* ignore link_once in rel section. */
2470 if (!sym_index && !sm->link_once
2471 #ifdef TCC_TARGET_ARM
2472 && type != R_ARM_V4BX
2473 #endif
2475 invalid_reloc:
2476 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2477 i, strsec + sh->sh_name, rel->r_offset);
2478 goto fail;
2480 rel->r_info = ELFW(R_INFO)(sym_index, type);
2481 /* offset the relocation offset */
2482 rel->r_offset += offseti;
2484 break;
2485 default:
2486 break;
2490 ret = 0;
2491 the_end:
2492 tcc_free(symtab);
2493 tcc_free(strtab);
2494 tcc_free(old_to_new_syms);
2495 tcc_free(sm_table);
2496 tcc_free(strsec);
2497 tcc_free(shdr);
2498 return ret;
2501 typedef struct ArchiveHeader {
2502 char ar_name[16]; /* name of this member */
2503 char ar_date[12]; /* file mtime */
2504 char ar_uid[6]; /* owner uid; printed as decimal */
2505 char ar_gid[6]; /* owner gid; printed as decimal */
2506 char ar_mode[8]; /* file mode, printed as octal */
2507 char ar_size[10]; /* file size, printed as decimal */
2508 char ar_fmag[2]; /* should contain ARFMAG */
2509 } ArchiveHeader;
2511 static int get_be32(const uint8_t *b)
2513 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2516 /* load only the objects which resolve undefined symbols */
2517 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2519 int i, bound, nsyms, sym_index, off, ret;
2520 uint8_t *data;
2521 const char *ar_names, *p;
2522 const uint8_t *ar_index;
2523 ElfW(Sym) *sym;
2525 data = tcc_malloc(size);
2526 if (read(fd, data, size) != size)
2527 goto fail;
2528 nsyms = get_be32(data);
2529 ar_index = data + 4;
2530 ar_names = ar_index + nsyms * 4;
2532 do {
2533 bound = 0;
2534 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2535 sym_index = find_elf_sym(symtab_section, p);
2536 if(sym_index) {
2537 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2538 if(sym->st_shndx == SHN_UNDEF) {
2539 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2540 #if 0
2541 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2542 #endif
2543 ++bound;
2544 lseek(fd, off, SEEK_SET);
2545 if(tcc_load_object_file(s1, fd, off) < 0) {
2546 fail:
2547 ret = -1;
2548 goto the_end;
2553 } while(bound);
2554 ret = 0;
2555 the_end:
2556 tcc_free(data);
2557 return ret;
2560 /* load a '.a' file */
2561 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2563 ArchiveHeader hdr;
2564 char ar_size[11];
2565 char ar_name[17];
2566 char magic[8];
2567 int size, len, i;
2568 unsigned long file_offset;
2570 /* skip magic which was already checked */
2571 read(fd, magic, sizeof(magic));
2573 for(;;) {
2574 len = read(fd, &hdr, sizeof(hdr));
2575 if (len == 0)
2576 break;
2577 if (len != sizeof(hdr)) {
2578 tcc_error_noabort("invalid archive");
2579 return -1;
2581 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2582 ar_size[sizeof(hdr.ar_size)] = '\0';
2583 size = strtol(ar_size, NULL, 0);
2584 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2585 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2586 if (ar_name[i] != ' ')
2587 break;
2589 ar_name[i + 1] = '\0';
2590 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2591 file_offset = lseek(fd, 0, SEEK_CUR);
2592 /* align to even */
2593 size = (size + 1) & ~1;
2594 if (!strcmp(ar_name, "/")) {
2595 /* coff symbol table : we handle it */
2596 if(s1->alacarte_link)
2597 return tcc_load_alacarte(s1, fd, size);
2598 } else if (!strcmp(ar_name, "//") ||
2599 !strcmp(ar_name, "__.SYMDEF") ||
2600 !strcmp(ar_name, "__.SYMDEF/") ||
2601 !strcmp(ar_name, "ARFILENAMES/")) {
2602 /* skip symbol table or archive names */
2603 } else {
2604 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2605 return -1;
2607 lseek(fd, file_offset + size, SEEK_SET);
2609 return 0;
2612 #ifndef TCC_TARGET_PE
2613 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2614 is referenced by the user (so it should be added as DT_NEEDED in
2615 the generated ELF file) */
2616 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2618 ElfW(Ehdr) ehdr;
2619 ElfW(Shdr) *shdr, *sh, *sh1;
2620 int i, j, nb_syms, nb_dts, sym_bind, ret;
2621 ElfW(Sym) *sym, *dynsym;
2622 ElfW(Dyn) *dt, *dynamic;
2623 unsigned char *dynstr;
2624 const char *name, *soname;
2625 DLLReference *dllref;
2627 read(fd, &ehdr, sizeof(ehdr));
2629 /* test CPU specific stuff */
2630 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2631 ehdr.e_machine != EM_TCC_TARGET) {
2632 tcc_error_noabort("bad architecture");
2633 return -1;
2636 /* read sections */
2637 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2639 /* load dynamic section and dynamic symbols */
2640 nb_syms = 0;
2641 nb_dts = 0;
2642 dynamic = NULL;
2643 dynsym = NULL; /* avoid warning */
2644 dynstr = NULL; /* avoid warning */
2645 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2646 switch(sh->sh_type) {
2647 case SHT_DYNAMIC:
2648 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2649 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2650 break;
2651 case SHT_DYNSYM:
2652 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2653 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2654 sh1 = &shdr[sh->sh_link];
2655 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2656 break;
2657 default:
2658 break;
2662 /* compute the real library name */
2663 soname = tcc_basename(filename);
2665 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2666 if (dt->d_tag == DT_SONAME) {
2667 soname = dynstr + dt->d_un.d_val;
2671 /* if the dll is already loaded, do not load it */
2672 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2673 dllref = s1->loaded_dlls[i];
2674 if (!strcmp(soname, dllref->name)) {
2675 /* but update level if needed */
2676 if (level < dllref->level)
2677 dllref->level = level;
2678 ret = 0;
2679 goto the_end;
2683 // printf("loading dll '%s'\n", soname);
2685 /* add the dll and its level */
2686 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2687 dllref->level = level;
2688 strcpy(dllref->name, soname);
2689 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2691 /* add dynamic symbols in dynsym_section */
2692 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2693 sym_bind = ELFW(ST_BIND)(sym->st_info);
2694 if (sym_bind == STB_LOCAL)
2695 continue;
2696 name = dynstr + sym->st_name;
2697 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2698 sym->st_info, sym->st_other, sym->st_shndx, name);
2701 /* load all referenced DLLs */
2702 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2703 switch(dt->d_tag) {
2704 case DT_NEEDED:
2705 name = dynstr + dt->d_un.d_val;
2706 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2707 dllref = s1->loaded_dlls[j];
2708 if (!strcmp(name, dllref->name))
2709 goto already_loaded;
2711 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2712 tcc_error_noabort("referenced dll '%s' not found", name);
2713 ret = -1;
2714 goto the_end;
2716 already_loaded:
2717 break;
2720 ret = 0;
2721 the_end:
2722 tcc_free(dynstr);
2723 tcc_free(dynsym);
2724 tcc_free(dynamic);
2725 tcc_free(shdr);
2726 return ret;
2729 #define LD_TOK_NAME 256
2730 #define LD_TOK_EOF (-1)
2732 /* return next ld script token */
2733 static int ld_next(TCCState *s1, char *name, int name_size)
2735 int c;
2736 char *q;
2738 redo:
2739 switch(ch) {
2740 case ' ':
2741 case '\t':
2742 case '\f':
2743 case '\v':
2744 case '\r':
2745 case '\n':
2746 inp();
2747 goto redo;
2748 case '/':
2749 minp();
2750 if (ch == '*') {
2751 file->buf_ptr = parse_comment(file->buf_ptr);
2752 ch = file->buf_ptr[0];
2753 goto redo;
2754 } else {
2755 q = name;
2756 *q++ = '/';
2757 goto parse_name;
2759 break;
2760 /* case 'a' ... 'z': */
2761 case 'a':
2762 case 'b':
2763 case 'c':
2764 case 'd':
2765 case 'e':
2766 case 'f':
2767 case 'g':
2768 case 'h':
2769 case 'i':
2770 case 'j':
2771 case 'k':
2772 case 'l':
2773 case 'm':
2774 case 'n':
2775 case 'o':
2776 case 'p':
2777 case 'q':
2778 case 'r':
2779 case 's':
2780 case 't':
2781 case 'u':
2782 case 'v':
2783 case 'w':
2784 case 'x':
2785 case 'y':
2786 case 'z':
2787 /* case 'A' ... 'z': */
2788 case 'A':
2789 case 'B':
2790 case 'C':
2791 case 'D':
2792 case 'E':
2793 case 'F':
2794 case 'G':
2795 case 'H':
2796 case 'I':
2797 case 'J':
2798 case 'K':
2799 case 'L':
2800 case 'M':
2801 case 'N':
2802 case 'O':
2803 case 'P':
2804 case 'Q':
2805 case 'R':
2806 case 'S':
2807 case 'T':
2808 case 'U':
2809 case 'V':
2810 case 'W':
2811 case 'X':
2812 case 'Y':
2813 case 'Z':
2814 case '_':
2815 case '\\':
2816 case '.':
2817 case '$':
2818 case '~':
2819 q = name;
2820 parse_name:
2821 for(;;) {
2822 if (!((ch >= 'a' && ch <= 'z') ||
2823 (ch >= 'A' && ch <= 'Z') ||
2824 (ch >= '0' && ch <= '9') ||
2825 strchr("/.-_+=$:\\,~", ch)))
2826 break;
2827 if ((q - name) < name_size - 1) {
2828 *q++ = ch;
2830 minp();
2832 *q = '\0';
2833 c = LD_TOK_NAME;
2834 break;
2835 case CH_EOF:
2836 c = LD_TOK_EOF;
2837 break;
2838 default:
2839 c = ch;
2840 inp();
2841 break;
2843 #if 0
2844 printf("tok=%c %d\n", c, c);
2845 if (c == LD_TOK_NAME)
2846 printf(" name=%s\n", name);
2847 #endif
2848 return c;
2852 * Extract the file name from the library name
2854 * /!\ No test on filename capacity, be careful
2856 static void libname_to_filename(TCCState *s1, const char libname[], char filename[])
2858 if (!s1->static_link) {
2859 sprintf(filename, "lib%s.so", libname);
2860 } else {
2861 sprintf(filename, "lib%s.a", libname);
2865 static int ld_add_file(TCCState *s1, const char filename[])
2867 int ret;
2869 ret = tcc_add_file_internal(s1, filename, 0);
2870 if (ret)
2871 ret = tcc_add_dll(s1, filename, 0);
2872 return ret;
2875 static inline int new_undef_syms(void)
2877 int ret = 0;
2878 ret = new_undef_sym;
2879 new_undef_sym = 0;
2880 return ret;
2883 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
2885 char filename[1024], libname[1024];
2886 int t, group, nblibs = 0, ret = 0;
2887 char **libs = NULL;
2889 group = !strcmp(cmd, "GROUP");
2890 if (!as_needed)
2891 new_undef_syms();
2892 t = ld_next(s1, filename, sizeof(filename));
2893 if (t != '(')
2894 expect("(");
2895 t = ld_next(s1, filename, sizeof(filename));
2896 for(;;) {
2897 libname[0] = '\0';
2898 if (t == LD_TOK_EOF) {
2899 tcc_error_noabort("unexpected end of file");
2900 ret = -1;
2901 goto lib_parse_error;
2902 } else if (t == ')') {
2903 break;
2904 } else if (t == '-') {
2905 t = ld_next(s1, filename, sizeof(filename));
2906 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
2907 tcc_error_noabort("library name expected");
2908 ret = -1;
2909 goto lib_parse_error;
2911 strcpy(libname, &filename[1]);
2912 libname_to_filename(s1, libname, filename);
2913 } else if (t != LD_TOK_NAME) {
2914 tcc_error_noabort("filename expected");
2915 ret = -1;
2916 goto lib_parse_error;
2918 if (!strcmp(filename, "AS_NEEDED")) {
2919 ret = ld_add_file_list(s1, cmd, 1);
2920 if (ret)
2921 goto lib_parse_error;
2922 } else {
2923 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2924 if (!as_needed) {
2925 ret = ld_add_file(s1, filename);
2926 if (ret)
2927 goto lib_parse_error;
2928 if (group) {
2929 /* Add the filename *and* the libname to avoid future conversions */
2930 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
2931 if (libname[0] != '\0')
2932 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
2936 t = ld_next(s1, filename, sizeof(filename));
2937 if (t == ',') {
2938 t = ld_next(s1, filename, sizeof(filename));
2941 if (group && !as_needed) {
2942 while (new_undef_syms()) {
2943 int i;
2945 for (i = 0; i < nblibs; i ++)
2946 ld_add_file(s1, libs[i]);
2949 lib_parse_error:
2950 dynarray_reset(&libs, &nblibs);
2951 return ret;
2954 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
2955 files */
2956 ST_FUNC int tcc_load_ldscript(TCCState *s1)
2958 char cmd[64];
2959 char filename[1024];
2960 int t, ret;
2962 ch = file->buf_ptr[0];
2963 ch = handle_eob();
2964 for(;;) {
2965 t = ld_next(s1, cmd, sizeof(cmd));
2966 if (t == LD_TOK_EOF)
2967 return 0;
2968 else if (t != LD_TOK_NAME)
2969 return -1;
2970 if (!strcmp(cmd, "INPUT") ||
2971 !strcmp(cmd, "GROUP")) {
2972 ret = ld_add_file_list(s1, cmd, 0);
2973 if (ret)
2974 return ret;
2975 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
2976 !strcmp(cmd, "TARGET")) {
2977 /* ignore some commands */
2978 t = ld_next(s1, cmd, sizeof(cmd));
2979 if (t != '(')
2980 expect("(");
2981 for(;;) {
2982 t = ld_next(s1, filename, sizeof(filename));
2983 if (t == LD_TOK_EOF) {
2984 tcc_error_noabort("unexpected end of file");
2985 return -1;
2986 } else if (t == ')') {
2987 break;
2990 } else {
2991 return -1;
2994 return 0;
2996 #endif /* ndef TCC_TARGET_PE */