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