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