tccrun: rt_printline: fix no-stabs case
[tinycc.git] / tccelf.c
blob3c3450188f1e2aaf71417595718853eae52ccec9
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;
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 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1049 for(rel = (ElfW_Rel *)s->data;
1050 rel < rel_end;
1051 rel++) {
1052 type = ELFW(R_TYPE)(rel->r_info);
1053 switch(type) {
1054 #if defined(TCC_TARGET_I386)
1055 case R_386_GOT32:
1056 case R_386_GOTOFF:
1057 case R_386_GOTPC:
1058 case R_386_PLT32:
1059 if (!s1->got)
1060 build_got(s1);
1061 if (type == R_386_GOT32 || type == R_386_PLT32) {
1062 sym_index = ELFW(R_SYM)(rel->r_info);
1063 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1064 /* look at the symbol got offset. If none, then add one */
1065 if (type == R_386_GOT32)
1066 reloc_type = R_386_GLOB_DAT;
1067 else
1068 reloc_type = R_386_JMP_SLOT;
1069 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1070 sym_index);
1072 break;
1073 #elif defined(TCC_TARGET_ARM)
1074 case R_ARM_GOT_BREL:
1075 case R_ARM_GOTOFF32:
1076 case R_ARM_BASE_PREL:
1077 case R_ARM_PLT32:
1078 if (!s1->got)
1079 build_got(s1);
1080 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1081 sym_index = ELFW(R_SYM)(rel->r_info);
1082 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1083 /* look at the symbol got offset. If none, then add one */
1084 if (type == R_ARM_GOT_BREL)
1085 reloc_type = R_ARM_GLOB_DAT;
1086 else
1087 reloc_type = R_ARM_JUMP_SLOT;
1088 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1089 sym_index);
1091 break;
1092 #elif defined(TCC_TARGET_C67)
1093 case R_C60_GOT32:
1094 case R_C60_GOTOFF:
1095 case R_C60_GOTPC:
1096 case R_C60_PLT32:
1097 if (!s1->got)
1098 build_got(s1);
1099 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1100 sym_index = ELFW(R_SYM)(rel->r_info);
1101 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1102 /* look at the symbol got offset. If none, then add one */
1103 if (type == R_C60_GOT32)
1104 reloc_type = R_C60_GLOB_DAT;
1105 else
1106 reloc_type = R_C60_JMP_SLOT;
1107 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1108 sym_index);
1110 break;
1111 #elif defined(TCC_TARGET_X86_64)
1112 case R_X86_64_GOT32:
1113 case R_X86_64_GOTTPOFF:
1114 case R_X86_64_GOTPCREL:
1115 case R_X86_64_PLT32:
1116 if (!s1->got)
1117 build_got(s1);
1118 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1119 type == R_X86_64_PLT32) {
1120 sym_index = ELFW(R_SYM)(rel->r_info);
1121 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1122 /* look at the symbol got offset. If none, then add one */
1123 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1124 reloc_type = R_X86_64_GLOB_DAT;
1125 else
1126 reloc_type = R_X86_64_JUMP_SLOT;
1127 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1128 sym_index);
1130 break;
1131 #else
1132 #error unsupported CPU
1133 #endif
1134 default:
1135 break;
1141 ST_FUNC Section *new_symtab(TCCState *s1,
1142 const char *symtab_name, int sh_type, int sh_flags,
1143 const char *strtab_name,
1144 const char *hash_name, int hash_sh_flags)
1146 Section *symtab, *strtab, *hash;
1147 int *ptr, nb_buckets;
1149 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1150 symtab->sh_entsize = sizeof(ElfW(Sym));
1151 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1152 put_elf_str(strtab, "");
1153 symtab->link = strtab;
1154 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1156 nb_buckets = 1;
1158 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1159 hash->sh_entsize = sizeof(int);
1160 symtab->hash = hash;
1161 hash->link = symtab;
1163 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1164 ptr[0] = nb_buckets;
1165 ptr[1] = 1;
1166 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1167 return symtab;
1170 /* put dynamic tag */
1171 static void put_dt(Section *dynamic, int dt, unsigned long val)
1173 ElfW(Dyn) *dyn;
1174 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1175 dyn->d_tag = dt;
1176 dyn->d_un.d_val = val;
1179 static void add_init_array_defines(TCCState *s1, const char *section_name)
1181 Section *s;
1182 long end_offset;
1183 char sym_start[1024];
1184 char sym_end[1024];
1186 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1187 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1189 s = find_section(s1, section_name);
1190 if (!s) {
1191 end_offset = 0;
1192 s = data_section;
1193 } else {
1194 end_offset = s->data_offset;
1197 add_elf_sym(symtab_section,
1198 0, 0,
1199 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1200 s->sh_num, sym_start);
1201 add_elf_sym(symtab_section,
1202 end_offset, 0,
1203 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1204 s->sh_num, sym_end);
1207 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1209 #ifdef CONFIG_TCC_BCHECK
1210 unsigned long *ptr;
1211 Section *init_section;
1212 unsigned char *pinit;
1213 int sym_index;
1215 if (0 == s1->do_bounds_check)
1216 return;
1218 /* XXX: add an object file to do that */
1219 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1220 *ptr = 0;
1221 add_elf_sym(symtab_section, 0, 0,
1222 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1223 bounds_section->sh_num, "__bounds_start");
1224 /* add bound check code */
1225 #ifndef TCC_TARGET_PE
1227 char buf[1024];
1228 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "bcheck.o");
1229 tcc_add_file(s1, buf);
1231 #endif
1232 #ifdef TCC_TARGET_I386
1233 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1234 /* add 'call __bound_init()' in .init section */
1235 init_section = find_section(s1, ".init");
1236 pinit = section_ptr_add(init_section, 5);
1237 pinit[0] = 0xe8;
1238 put32(pinit + 1, -4);
1239 sym_index = find_elf_sym(symtab_section, "__bound_init");
1240 put_elf_reloc(symtab_section, init_section,
1241 init_section->data_offset - 4, R_386_PC32, sym_index);
1243 #endif
1244 #endif
1247 /* add tcc runtime libraries */
1248 ST_FUNC void tcc_add_runtime(TCCState *s1)
1250 tcc_add_bcheck(s1);
1252 /* add libc */
1253 if (!s1->nostdlib) {
1254 #ifdef CONFIG_USE_LIBGCC
1255 tcc_add_library(s1, "c");
1256 tcc_add_file(s1, CONFIG_SYSROOT CONFIG_TCC_LDDIR"/libgcc_s.so.1");
1257 #else
1258 tcc_add_library(s1, "c");
1259 #ifndef WITHOUT_LIBTCC
1261 char buf[1024];
1262 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "libtcc1.a");
1263 tcc_add_file(s1, buf);
1265 #endif
1266 #endif
1268 /* add crt end if not memory output */
1269 if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) {
1270 tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
1274 /* add various standard linker symbols (must be done after the
1275 sections are filled (for example after allocating common
1276 symbols)) */
1277 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1279 char buf[1024];
1280 int i;
1281 Section *s;
1283 add_elf_sym(symtab_section,
1284 text_section->data_offset, 0,
1285 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1286 text_section->sh_num, "_etext");
1287 add_elf_sym(symtab_section,
1288 data_section->data_offset, 0,
1289 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1290 data_section->sh_num, "_edata");
1291 add_elf_sym(symtab_section,
1292 bss_section->data_offset, 0,
1293 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1294 bss_section->sh_num, "_end");
1295 /* horrible new standard ldscript defines */
1296 add_init_array_defines(s1, ".preinit_array");
1297 add_init_array_defines(s1, ".init_array");
1298 add_init_array_defines(s1, ".fini_array");
1300 /* add start and stop symbols for sections whose name can be
1301 expressed in C */
1302 for(i = 1; i < s1->nb_sections; i++) {
1303 s = s1->sections[i];
1304 if (s->sh_type == SHT_PROGBITS &&
1305 (s->sh_flags & SHF_ALLOC)) {
1306 const char *p;
1307 int ch;
1309 /* check if section name can be expressed in C */
1310 p = s->name;
1311 for(;;) {
1312 ch = *p;
1313 if (!ch)
1314 break;
1315 if (!isid(ch) && !isnum(ch))
1316 goto next_sec;
1317 p++;
1319 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1320 add_elf_sym(symtab_section,
1321 0, 0,
1322 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1323 s->sh_num, buf);
1324 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1325 add_elf_sym(symtab_section,
1326 s->data_offset, 0,
1327 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1328 s->sh_num, buf);
1330 next_sec: ;
1334 /* name of ELF interpreter */
1335 #if defined __FreeBSD__
1336 static const char elf_interp[] = "/libexec/ld-elf.so.1";
1337 #elif defined __FreeBSD_kernel__
1338 static char elf_interp[] = CONFIG_TCC_LDDIR"/ld.so.1";
1339 #elif defined TCC_ARM_EABI
1340 static const char elf_interp[] = CONFIG_TCC_LDDIR"/ld-linux.so.3";
1341 #elif defined(TCC_TARGET_X86_64)
1342 static const char elf_interp[] = CONFIG_TCC_LDDIR"/ld-linux-x86-64.so.2";
1343 #elif defined(TCC_UCLIBC)
1344 static const char elf_interp[] = CONFIG_TCC_LDDIR"/ld-uClibc.so.0";
1345 #else
1346 static const char elf_interp[] = CONFIG_TCC_LDDIR"/ld-linux.so.2";
1347 #endif
1349 static void tcc_output_binary(TCCState *s1, FILE *f,
1350 const int *section_order)
1352 Section *s;
1353 int i, offset, size;
1355 offset = 0;
1356 for(i=1;i<s1->nb_sections;i++) {
1357 s = s1->sections[section_order[i]];
1358 if (s->sh_type != SHT_NOBITS &&
1359 (s->sh_flags & SHF_ALLOC)) {
1360 while (offset < s->sh_offset) {
1361 fputc(0, f);
1362 offset++;
1364 size = s->sh_size;
1365 fwrite(s->data, 1, size, f);
1366 offset += size;
1371 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1372 #define HAVE_PHDR 1
1373 #define EXTRA_RELITEMS 14
1375 /* move the relocation value from .dynsym to .got */
1376 void patch_dynsym_undef(TCCState *s1, Section *s)
1378 uint32_t *gotd = (void *)s1->got->data;
1379 ElfW(Sym) *sym, *sym_end;
1381 gotd += 3; // dummy entries in .got
1382 /* relocate symbols in .dynsym */
1383 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1384 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1385 if (sym->st_shndx == SHN_UNDEF) {
1386 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1387 sym->st_value = 0;
1391 #else
1392 #define HAVE_PHDR 0
1393 #define EXTRA_RELITEMS 9
1394 #endif
1396 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1398 int sym_index = ELFW(R_SYM) (rel->r_info);
1399 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1400 unsigned long offset;
1402 if (sym_index >= s1->nb_got_offsets)
1403 return;
1404 offset = s1->got_offsets[sym_index];
1405 section_reserve(s1->got, offset + PTR_SIZE);
1406 #ifdef TCC_TARGET_X86_64
1407 /* only works for x86-64 */
1408 put32(s1->got->data + offset, sym->st_value >> 32);
1409 #endif
1410 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1413 ST_FUNC void fill_got(TCCState *s1)
1415 Section *s;
1416 ElfW_Rel *rel, *rel_end;
1417 int i;
1419 for(i = 1; i < s1->nb_sections; i++) {
1420 s = s1->sections[i];
1421 if (s->sh_type != SHT_RELX)
1422 continue;
1423 /* no need to handle got relocations */
1424 if (s->link != symtab_section)
1425 continue;
1426 rel_end = (ElfW_Rel *) (s->data + s->data_offset);
1427 for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
1428 switch (ELFW(R_TYPE) (rel->r_info)) {
1429 case R_X86_64_GOT32:
1430 case R_X86_64_GOTPCREL:
1431 case R_X86_64_PLT32:
1432 fill_got_entry(s1, rel);
1433 break;
1440 /* output an ELF file */
1441 /* XXX: suppress unneeded sections */
1442 static int elf_output_file(TCCState *s1, const char *filename)
1444 ElfW(Ehdr) ehdr;
1445 FILE *f;
1446 int fd, mode, ret;
1447 int *section_order;
1448 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
1449 unsigned long addr;
1450 Section *strsec, *s;
1451 ElfW(Shdr) shdr, *sh;
1452 ElfW(Phdr) *phdr, *ph;
1453 Section *interp, *dynamic, *dynstr;
1454 unsigned long saved_dynamic_data_offset;
1455 ElfW(Sym) *sym;
1456 int type, file_type;
1457 unsigned long rel_addr, rel_size;
1458 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1459 unsigned long bss_addr, bss_size;
1460 #endif
1462 file_type = s1->output_type;
1463 s1->nb_errors = 0;
1465 if (file_type != TCC_OUTPUT_OBJ) {
1466 tcc_add_runtime(s1);
1469 phdr = NULL;
1470 section_order = NULL;
1471 interp = NULL;
1472 dynamic = NULL;
1473 dynstr = NULL; /* avoid warning */
1474 saved_dynamic_data_offset = 0; /* avoid warning */
1476 if (file_type != TCC_OUTPUT_OBJ) {
1477 relocate_common_syms();
1479 tcc_add_linker_symbols(s1);
1481 if (!s1->static_link) {
1482 const char *name;
1483 int sym_index, index;
1484 ElfW(Sym) *esym, *sym_end;
1486 if (file_type == TCC_OUTPUT_EXE) {
1487 char *ptr;
1488 /* allow override the dynamic loader */
1489 const char *elfint = getenv("LD_SO");
1490 if (elfint == NULL)
1491 elfint = elf_interp;
1492 /* add interpreter section only if executable */
1493 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1494 interp->sh_addralign = 1;
1495 ptr = section_ptr_add(interp, 1+strlen(elfint));
1496 strcpy(ptr, elfint);
1499 /* add dynamic symbol table */
1500 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1501 ".dynstr",
1502 ".hash", SHF_ALLOC);
1503 dynstr = s1->dynsym->link;
1505 /* add dynamic section */
1506 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1507 SHF_ALLOC | SHF_WRITE);
1508 dynamic->link = dynstr;
1509 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1511 /* add PLT */
1512 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1513 SHF_ALLOC | SHF_EXECINSTR);
1514 s1->plt->sh_entsize = 4;
1516 build_got(s1);
1518 /* scan for undefined symbols and see if they are in the
1519 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1520 is found, then we add it in the PLT. If a symbol
1521 STT_OBJECT is found, we add it in the .bss section with
1522 a suitable relocation */
1523 sym_end = (ElfW(Sym) *)(symtab_section->data +
1524 symtab_section->data_offset);
1525 if (file_type == TCC_OUTPUT_EXE) {
1526 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1527 sym < sym_end;
1528 sym++) {
1529 if (sym->st_shndx == SHN_UNDEF) {
1530 name = symtab_section->link->data + sym->st_name;
1531 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1532 if (sym_index) {
1533 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1534 type = ELFW(ST_TYPE)(esym->st_info);
1535 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1536 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1537 esym->st_info,
1538 sym - (ElfW(Sym) *)symtab_section->data);
1539 } else if (type == STT_OBJECT) {
1540 unsigned long offset;
1541 ElfW(Sym) *dynsym, *dynsym_end;
1542 offset = bss_section->data_offset;
1543 /* XXX: which alignment ? */
1544 offset = (offset + 16 - 1) & -16;
1545 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1546 esym->st_info, 0,
1547 bss_section->sh_num, name);
1548 // Ensure R_COPY works for weak symbol aliases
1549 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
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 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1557 char *dynname;
1558 dynname = s1->dynsymtab_section->link->data
1559 + dynsym->st_name;
1560 put_elf_sym(s1->dynsym, offset,
1561 dynsym->st_size,
1562 dynsym->st_info, 0,
1563 bss_section->sh_num,
1564 dynname);
1565 break;
1569 put_elf_reloc(s1->dynsym, bss_section,
1570 offset, R_COPY, index);
1571 offset += esym->st_size;
1572 bss_section->data_offset = offset;
1574 } else {
1575 /* STB_WEAK undefined symbols are accepted */
1576 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1577 it */
1578 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1579 !strcmp(name, "_fp_hw")) {
1580 } else {
1581 error_noabort("undefined symbol '%s'", name);
1584 } else if (s1->rdynamic &&
1585 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1586 /* if -rdynamic option, then export all non
1587 local symbols */
1588 name = symtab_section->link->data + sym->st_name;
1589 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1590 sym->st_info, 0,
1591 sym->st_shndx, name);
1595 if (s1->nb_errors)
1596 goto fail;
1598 /* now look at unresolved dynamic symbols and export
1599 corresponding symbol */
1600 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1601 s1->dynsymtab_section->data_offset);
1602 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1603 esym < sym_end;
1604 esym++) {
1605 if (esym->st_shndx == SHN_UNDEF) {
1606 name = s1->dynsymtab_section->link->data + esym->st_name;
1607 sym_index = find_elf_sym(symtab_section, name);
1608 if (sym_index) {
1609 /* XXX: avoid adding a symbol if already
1610 present because of -rdynamic ? */
1611 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1612 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1613 sym->st_info, 0,
1614 sym->st_shndx, name);
1615 } else {
1616 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1617 /* weak symbols can stay undefined */
1618 } else {
1619 warning("undefined dynamic symbol '%s'", name);
1624 } else {
1625 int nb_syms;
1626 /* shared library case : we simply export all the global symbols */
1627 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1628 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1629 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1630 sym < sym_end;
1631 sym++) {
1632 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1633 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1634 if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
1635 ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
1636 && sym->st_shndx == SHN_UNDEF) {
1637 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1638 sym->st_info,
1639 sym - (ElfW(Sym) *)symtab_section->data);
1641 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1642 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1643 sym->st_info,
1644 sym - (ElfW(Sym) *)symtab_section->data);
1646 else
1647 #endif
1649 name = symtab_section->link->data + sym->st_name;
1650 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1651 sym->st_info, 0,
1652 sym->st_shndx, name);
1653 s1->symtab_to_dynsym[sym -
1654 (ElfW(Sym) *)symtab_section->data] =
1655 index;
1661 build_got_entries(s1);
1663 /* add a list of needed dlls */
1664 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1665 DLLReference *dllref = s1->loaded_dlls[i];
1666 if (dllref->level == 0)
1667 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1670 if (s1->rpath)
1671 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1673 /* XXX: currently, since we do not handle PIC code, we
1674 must relocate the readonly segments */
1675 if (file_type == TCC_OUTPUT_DLL) {
1676 if (s1->soname)
1677 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1678 put_dt(dynamic, DT_TEXTREL, 0);
1681 if (s1->symbolic)
1682 put_dt(dynamic, DT_SYMBOLIC, 0);
1684 /* add necessary space for other entries */
1685 saved_dynamic_data_offset = dynamic->data_offset;
1686 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1687 } else {
1688 /* still need to build got entries in case of static link */
1689 build_got_entries(s1);
1693 memset(&ehdr, 0, sizeof(ehdr));
1695 /* we add a section for symbols */
1696 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1697 put_elf_str(strsec, "");
1699 /* compute number of sections */
1700 shnum = s1->nb_sections;
1702 /* this array is used to reorder sections in the output file */
1703 section_order = tcc_malloc(sizeof(int) * shnum);
1704 section_order[0] = 0;
1705 sh_order_index = 1;
1707 /* compute number of program headers */
1708 switch(file_type) {
1709 default:
1710 case TCC_OUTPUT_OBJ:
1711 phnum = 0;
1712 break;
1713 case TCC_OUTPUT_EXE:
1714 if (!s1->static_link)
1715 phnum = 4 + HAVE_PHDR;
1716 else
1717 phnum = 2;
1718 break;
1719 case TCC_OUTPUT_DLL:
1720 phnum = 3;
1721 break;
1724 /* allocate strings for section names and decide if an unallocated
1725 section should be output */
1726 /* NOTE: the strsec section comes last, so its size is also
1727 correct ! */
1728 for(i = 1; i < s1->nb_sections; i++) {
1729 s = s1->sections[i];
1730 s->sh_name = put_elf_str(strsec, s->name);
1731 #if 0 //gr
1732 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1733 s->sh_flags,
1734 s->sh_type,
1735 s->sh_info,
1736 s->name,
1737 s->reloc ? s->reloc->name : "n"
1739 #endif
1740 /* when generating a DLL, we include relocations but we may
1741 patch them */
1742 if (file_type == TCC_OUTPUT_DLL &&
1743 s->sh_type == SHT_RELX &&
1744 !(s->sh_flags & SHF_ALLOC)) {
1745 /* //gr: avoid bogus relocs for empty (debug) sections */
1746 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1747 prepare_dynamic_rel(s1, s);
1748 else if (s1->do_debug)
1749 s->sh_size = s->data_offset;
1750 } else if (s1->do_debug ||
1751 file_type == TCC_OUTPUT_OBJ ||
1752 (s->sh_flags & SHF_ALLOC) ||
1753 i == (s1->nb_sections - 1)) {
1754 /* we output all sections if debug or object file */
1755 s->sh_size = s->data_offset;
1759 /* allocate program segment headers */
1760 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1762 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1763 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1764 } else {
1765 file_offset = 0;
1767 if (phnum > 0) {
1768 /* compute section to program header mapping */
1769 if (s1->has_text_addr) {
1770 int a_offset, p_offset;
1771 addr = s1->text_addr;
1772 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1773 ELF_PAGE_SIZE */
1774 a_offset = addr & (s1->section_align - 1);
1775 p_offset = file_offset & (s1->section_align - 1);
1776 if (a_offset < p_offset)
1777 a_offset += s1->section_align;
1778 file_offset += (a_offset - p_offset);
1779 } else {
1780 if (file_type == TCC_OUTPUT_DLL)
1781 addr = 0;
1782 else
1783 addr = ELF_START_ADDR;
1784 /* compute address after headers */
1785 addr += (file_offset & (s1->section_align - 1));
1788 /* dynamic relocation table information, for .dynamic section */
1789 rel_size = 0;
1790 rel_addr = 0;
1792 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1793 bss_addr = bss_size = 0;
1794 #endif
1795 /* leave one program header for the program interpreter */
1796 ph = &phdr[0];
1797 if (interp)
1798 ph += 1 + HAVE_PHDR;
1800 for(j = 0; j < 2; j++) {
1801 ph->p_type = PT_LOAD;
1802 if (j == 0)
1803 ph->p_flags = PF_R | PF_X;
1804 else
1805 ph->p_flags = PF_R | PF_W;
1806 ph->p_align = s1->section_align;
1808 /* we do the following ordering: interp, symbol tables,
1809 relocations, progbits, nobits */
1810 /* XXX: do faster and simpler sorting */
1811 for(k = 0; k < 5; k++) {
1812 for(i = 1; i < s1->nb_sections; i++) {
1813 s = s1->sections[i];
1814 /* compute if section should be included */
1815 if (j == 0) {
1816 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1817 SHF_ALLOC)
1818 continue;
1819 } else {
1820 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1821 (SHF_ALLOC | SHF_WRITE))
1822 continue;
1824 if (s == interp) {
1825 if (k != 0)
1826 continue;
1827 } else if (s->sh_type == SHT_DYNSYM ||
1828 s->sh_type == SHT_STRTAB ||
1829 s->sh_type == SHT_HASH) {
1830 if (k != 1)
1831 continue;
1832 } else if (s->sh_type == SHT_RELX) {
1833 if (k != 2)
1834 continue;
1835 } else if (s->sh_type == SHT_NOBITS) {
1836 if (k != 4)
1837 continue;
1838 } else {
1839 if (k != 3)
1840 continue;
1842 section_order[sh_order_index++] = i;
1844 /* section matches: we align it and add its size */
1845 tmp = addr;
1846 addr = (addr + s->sh_addralign - 1) &
1847 ~(s->sh_addralign - 1);
1848 file_offset += addr - tmp;
1849 s->sh_offset = file_offset;
1850 s->sh_addr = addr;
1852 /* update program header infos */
1853 if (ph->p_offset == 0) {
1854 ph->p_offset = file_offset;
1855 ph->p_vaddr = addr;
1856 ph->p_paddr = ph->p_vaddr;
1858 /* update dynamic relocation infos */
1859 if (s->sh_type == SHT_RELX) {
1860 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1861 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1862 rel_addr = addr;
1863 rel_size += s->sh_size; // XXX only first rel.
1865 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1866 bss_addr = addr;
1867 bss_size = s->sh_size; // XXX only first rel.
1869 #else
1870 if (rel_size == 0)
1871 rel_addr = addr;
1872 rel_size += s->sh_size;
1873 #endif
1875 addr += s->sh_size;
1876 if (s->sh_type != SHT_NOBITS)
1877 file_offset += s->sh_size;
1880 ph->p_filesz = file_offset - ph->p_offset;
1881 ph->p_memsz = addr - ph->p_vaddr;
1882 ph++;
1883 if (j == 0) {
1884 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1885 /* if in the middle of a page, we duplicate the page in
1886 memory so that one copy is RX and the other is RW */
1887 if ((addr & (s1->section_align - 1)) != 0)
1888 addr += s1->section_align;
1889 } else {
1890 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1891 file_offset = (file_offset + s1->section_align - 1) &
1892 ~(s1->section_align - 1);
1897 /* if interpreter, then add corresponing program header */
1898 if (interp) {
1899 ph = &phdr[0];
1901 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1903 int len = phnum * sizeof(ElfW(Phdr));
1905 ph->p_type = PT_PHDR;
1906 ph->p_offset = sizeof(ElfW(Ehdr));
1907 ph->p_vaddr = interp->sh_addr - len;
1908 ph->p_paddr = ph->p_vaddr;
1909 ph->p_filesz = ph->p_memsz = len;
1910 ph->p_flags = PF_R | PF_X;
1911 ph->p_align = 4; // interp->sh_addralign;
1912 ph++;
1914 #endif
1916 ph->p_type = PT_INTERP;
1917 ph->p_offset = interp->sh_offset;
1918 ph->p_vaddr = interp->sh_addr;
1919 ph->p_paddr = ph->p_vaddr;
1920 ph->p_filesz = interp->sh_size;
1921 ph->p_memsz = interp->sh_size;
1922 ph->p_flags = PF_R;
1923 ph->p_align = interp->sh_addralign;
1926 /* if dynamic section, then add corresponing program header */
1927 if (dynamic) {
1928 ElfW(Sym) *sym_end;
1930 ph = &phdr[phnum - 1];
1932 ph->p_type = PT_DYNAMIC;
1933 ph->p_offset = dynamic->sh_offset;
1934 ph->p_vaddr = dynamic->sh_addr;
1935 ph->p_paddr = ph->p_vaddr;
1936 ph->p_filesz = dynamic->sh_size;
1937 ph->p_memsz = dynamic->sh_size;
1938 ph->p_flags = PF_R | PF_W;
1939 ph->p_align = dynamic->sh_addralign;
1941 /* put GOT dynamic section address */
1942 put32(s1->got->data, dynamic->sh_addr);
1944 /* relocate the PLT */
1945 if (file_type == TCC_OUTPUT_EXE
1946 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1947 || file_type == TCC_OUTPUT_DLL
1948 #endif
1950 uint8_t *p, *p_end;
1952 p = s1->plt->data;
1953 p_end = p + s1->plt->data_offset;
1954 if (p < p_end) {
1955 #if defined(TCC_TARGET_I386)
1956 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1957 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1958 p += 16;
1959 while (p < p_end) {
1960 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1961 p += 16;
1963 #elif defined(TCC_TARGET_X86_64)
1964 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1965 put32(p + 2, get32(p + 2) + x);
1966 put32(p + 8, get32(p + 8) + x - 6);
1967 p += 16;
1968 while (p < p_end) {
1969 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1970 p += 16;
1972 #elif defined(TCC_TARGET_ARM)
1973 int x;
1974 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1975 p +=16;
1976 while (p < p_end) {
1977 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1978 p += 16;
1980 #elif defined(TCC_TARGET_C67)
1981 /* XXX: TODO */
1982 #else
1983 #error unsupported CPU
1984 #endif
1988 /* relocate symbols in .dynsym */
1989 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
1990 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
1991 sym < sym_end;
1992 sym++) {
1993 if (sym->st_shndx == SHN_UNDEF) {
1994 /* relocate to the PLT if the symbol corresponds
1995 to a PLT entry */
1996 if (sym->st_value)
1997 sym->st_value += s1->plt->sh_addr;
1998 } else if (sym->st_shndx < SHN_LORESERVE) {
1999 /* do symbol relocation */
2000 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
2004 /* put dynamic section entries */
2005 dynamic->data_offset = saved_dynamic_data_offset;
2006 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
2007 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
2008 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2009 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
2010 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2011 #ifdef TCC_TARGET_X86_64
2012 put_dt(dynamic, DT_RELA, rel_addr);
2013 put_dt(dynamic, DT_RELASZ, rel_size);
2014 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2015 #else
2016 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2017 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2018 put_dt(dynamic, DT_PLTRELSZ, rel_size);
2019 put_dt(dynamic, DT_JMPREL, rel_addr);
2020 put_dt(dynamic, DT_PLTREL, DT_REL);
2021 put_dt(dynamic, DT_REL, bss_addr);
2022 put_dt(dynamic, DT_RELSZ, bss_size);
2023 #else
2024 put_dt(dynamic, DT_REL, rel_addr);
2025 put_dt(dynamic, DT_RELSZ, rel_size);
2026 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2027 #endif
2028 #endif
2029 if (s1->do_debug)
2030 put_dt(dynamic, DT_DEBUG, 0);
2031 put_dt(dynamic, DT_NULL, 0);
2034 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2035 ehdr.e_phnum = phnum;
2036 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2039 /* all other sections come after */
2040 for(i = 1; i < s1->nb_sections; i++) {
2041 s = s1->sections[i];
2042 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2043 continue;
2044 section_order[sh_order_index++] = i;
2046 file_offset = (file_offset + s->sh_addralign - 1) &
2047 ~(s->sh_addralign - 1);
2048 s->sh_offset = file_offset;
2049 if (s->sh_type != SHT_NOBITS)
2050 file_offset += s->sh_size;
2053 /* if building executable or DLL, then relocate each section
2054 except the GOT which is already relocated */
2055 if (file_type != TCC_OUTPUT_OBJ) {
2056 relocate_syms(s1, 0);
2058 if (s1->nb_errors != 0) {
2059 fail:
2060 ret = -1;
2061 goto the_end;
2064 /* relocate sections */
2065 /* XXX: ignore sections with allocated relocations ? */
2066 for(i = 1; i < s1->nb_sections; i++) {
2067 s = s1->sections[i];
2068 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
2069 relocate_section(s1, s);
2072 /* relocate relocation entries if the relocation tables are
2073 allocated in the executable */
2074 for(i = 1; i < s1->nb_sections; i++) {
2075 s = s1->sections[i];
2076 if ((s->sh_flags & SHF_ALLOC) &&
2077 s->sh_type == SHT_RELX) {
2078 relocate_rel(s1, s);
2082 /* get entry point address */
2083 if (file_type == TCC_OUTPUT_EXE)
2084 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
2085 else
2086 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2088 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2089 fill_got(s1);
2091 /* write elf file */
2092 if (file_type == TCC_OUTPUT_OBJ)
2093 mode = 0666;
2094 else
2095 mode = 0777;
2096 unlink(filename);
2097 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2098 if (fd < 0) {
2099 error_noabort("could not write '%s'", filename);
2100 goto fail;
2102 f = fdopen(fd, "wb");
2103 if (s1->verbose)
2104 printf("<- %s\n", filename);
2106 #ifdef TCC_TARGET_COFF
2107 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2108 tcc_output_coff(s1, f);
2109 } else
2110 #endif
2111 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2112 sort_syms(s1, symtab_section);
2114 /* align to 4 */
2115 file_offset = (file_offset + 3) & -4;
2117 /* fill header */
2118 ehdr.e_ident[0] = ELFMAG0;
2119 ehdr.e_ident[1] = ELFMAG1;
2120 ehdr.e_ident[2] = ELFMAG2;
2121 ehdr.e_ident[3] = ELFMAG3;
2122 ehdr.e_ident[4] = TCC_ELFCLASS;
2123 ehdr.e_ident[5] = ELFDATA2LSB;
2124 ehdr.e_ident[6] = EV_CURRENT;
2125 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2126 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2127 #endif
2128 #ifdef TCC_TARGET_ARM
2129 #ifdef TCC_ARM_EABI
2130 ehdr.e_ident[EI_OSABI] = 0;
2131 ehdr.e_flags = 4 << 24;
2132 #else
2133 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2134 #endif
2135 #endif
2136 switch(file_type) {
2137 default:
2138 case TCC_OUTPUT_EXE:
2139 ehdr.e_type = ET_EXEC;
2140 break;
2141 case TCC_OUTPUT_DLL:
2142 ehdr.e_type = ET_DYN;
2143 break;
2144 case TCC_OUTPUT_OBJ:
2145 ehdr.e_type = ET_REL;
2146 break;
2148 ehdr.e_machine = EM_TCC_TARGET;
2149 ehdr.e_version = EV_CURRENT;
2150 ehdr.e_shoff = file_offset;
2151 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2152 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2153 ehdr.e_shnum = shnum;
2154 ehdr.e_shstrndx = shnum - 1;
2156 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2157 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2158 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2160 for(i=1;i<s1->nb_sections;i++) {
2161 s = s1->sections[section_order[i]];
2162 if (s->sh_type != SHT_NOBITS) {
2163 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2164 if (s->sh_type == SHT_DYNSYM)
2165 patch_dynsym_undef(s1, s);
2166 #endif
2167 while (offset < s->sh_offset) {
2168 fputc(0, f);
2169 offset++;
2171 size = s->sh_size;
2172 fwrite(s->data, 1, size, f);
2173 offset += size;
2177 /* output section headers */
2178 while (offset < ehdr.e_shoff) {
2179 fputc(0, f);
2180 offset++;
2183 for(i=0;i<s1->nb_sections;i++) {
2184 sh = &shdr;
2185 memset(sh, 0, sizeof(ElfW(Shdr)));
2186 s = s1->sections[i];
2187 if (s) {
2188 sh->sh_name = s->sh_name;
2189 sh->sh_type = s->sh_type;
2190 sh->sh_flags = s->sh_flags;
2191 sh->sh_entsize = s->sh_entsize;
2192 sh->sh_info = s->sh_info;
2193 if (s->link)
2194 sh->sh_link = s->link->sh_num;
2195 sh->sh_addralign = s->sh_addralign;
2196 sh->sh_addr = s->sh_addr;
2197 sh->sh_offset = s->sh_offset;
2198 sh->sh_size = s->sh_size;
2200 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2202 } else {
2203 tcc_output_binary(s1, f, section_order);
2205 fclose(f);
2207 ret = 0;
2208 the_end:
2209 tcc_free(s1->symtab_to_dynsym);
2210 tcc_free(section_order);
2211 tcc_free(phdr);
2212 tcc_free(s1->got_offsets);
2213 return ret;
2216 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2218 int ret;
2219 #ifdef TCC_TARGET_PE
2220 if (s->output_type != TCC_OUTPUT_OBJ) {
2221 ret = pe_output_file(s, filename);
2222 } else
2223 #endif
2225 ret = elf_output_file(s, filename);
2227 return ret;
2230 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2232 void *data;
2234 data = tcc_malloc(size);
2235 lseek(fd, file_offset, SEEK_SET);
2236 read(fd, data, size);
2237 return data;
2240 typedef struct SectionMergeInfo {
2241 Section *s; /* corresponding existing section */
2242 unsigned long offset; /* offset of the new section in the existing section */
2243 uint8_t new_section; /* true if section 's' was added */
2244 uint8_t link_once; /* true if link once section */
2245 } SectionMergeInfo;
2247 /* load an object file and merge it with current files */
2248 /* XXX: handle correctly stab (debug) info */
2249 ST_FUNC int tcc_load_object_file(TCCState *s1,
2250 int fd, unsigned long file_offset)
2252 ElfW(Ehdr) ehdr;
2253 ElfW(Shdr) *shdr, *sh;
2254 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2255 unsigned char *strsec, *strtab;
2256 int *old_to_new_syms;
2257 char *sh_name, *name;
2258 SectionMergeInfo *sm_table, *sm;
2259 ElfW(Sym) *sym, *symtab;
2260 ElfW_Rel *rel, *rel_end;
2261 Section *s;
2263 int stab_index;
2264 int stabstr_index;
2266 stab_index = stabstr_index = 0;
2268 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2269 goto fail1;
2270 if (ehdr.e_ident[0] != ELFMAG0 ||
2271 ehdr.e_ident[1] != ELFMAG1 ||
2272 ehdr.e_ident[2] != ELFMAG2 ||
2273 ehdr.e_ident[3] != ELFMAG3)
2274 goto fail1;
2275 /* test if object file */
2276 if (ehdr.e_type != ET_REL)
2277 goto fail1;
2278 /* test CPU specific stuff */
2279 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2280 ehdr.e_machine != EM_TCC_TARGET) {
2281 fail1:
2282 error_noabort("invalid object file");
2283 return -1;
2285 /* read sections */
2286 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2287 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2288 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2290 /* load section names */
2291 sh = &shdr[ehdr.e_shstrndx];
2292 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2294 /* load symtab and strtab */
2295 old_to_new_syms = NULL;
2296 symtab = NULL;
2297 strtab = NULL;
2298 nb_syms = 0;
2299 for(i = 1; i < ehdr.e_shnum; i++) {
2300 sh = &shdr[i];
2301 if (sh->sh_type == SHT_SYMTAB) {
2302 if (symtab) {
2303 error_noabort("object must contain only one symtab");
2304 fail:
2305 ret = -1;
2306 goto the_end;
2308 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2309 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2310 sm_table[i].s = symtab_section;
2312 /* now load strtab */
2313 sh = &shdr[sh->sh_link];
2314 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2318 /* now examine each section and try to merge its content with the
2319 ones in memory */
2320 for(i = 1; i < ehdr.e_shnum; i++) {
2321 /* no need to examine section name strtab */
2322 if (i == ehdr.e_shstrndx)
2323 continue;
2324 sh = &shdr[i];
2325 sh_name = strsec + sh->sh_name;
2326 /* ignore sections types we do not handle */
2327 if (sh->sh_type != SHT_PROGBITS &&
2328 sh->sh_type != SHT_RELX &&
2329 #ifdef TCC_ARM_EABI
2330 sh->sh_type != SHT_ARM_EXIDX &&
2331 #endif
2332 sh->sh_type != SHT_NOBITS &&
2333 sh->sh_type != SHT_PREINIT_ARRAY &&
2334 sh->sh_type != SHT_INIT_ARRAY &&
2335 sh->sh_type != SHT_FINI_ARRAY &&
2336 strcmp(sh_name, ".stabstr")
2338 continue;
2339 if (sh->sh_addralign < 1)
2340 sh->sh_addralign = 1;
2341 /* find corresponding section, if any */
2342 for(j = 1; j < s1->nb_sections;j++) {
2343 s = s1->sections[j];
2344 if (!strcmp(s->name, sh_name)) {
2345 if (!strncmp(sh_name, ".gnu.linkonce",
2346 sizeof(".gnu.linkonce") - 1)) {
2347 /* if a 'linkonce' section is already present, we
2348 do not add it again. It is a little tricky as
2349 symbols can still be defined in
2350 it. */
2351 sm_table[i].link_once = 1;
2352 goto next;
2353 } else {
2354 goto found;
2358 /* not found: create new section */
2359 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2360 /* take as much info as possible from the section. sh_link and
2361 sh_info will be updated later */
2362 s->sh_addralign = sh->sh_addralign;
2363 s->sh_entsize = sh->sh_entsize;
2364 sm_table[i].new_section = 1;
2365 found:
2366 if (sh->sh_type != s->sh_type) {
2367 error_noabort("invalid section type");
2368 goto fail;
2371 /* align start of section */
2372 offset = s->data_offset;
2374 if (0 == strcmp(sh_name, ".stab")) {
2375 stab_index = i;
2376 goto no_align;
2378 if (0 == strcmp(sh_name, ".stabstr")) {
2379 stabstr_index = i;
2380 goto no_align;
2383 size = sh->sh_addralign - 1;
2384 offset = (offset + size) & ~size;
2385 if (sh->sh_addralign > s->sh_addralign)
2386 s->sh_addralign = sh->sh_addralign;
2387 s->data_offset = offset;
2388 no_align:
2389 sm_table[i].offset = offset;
2390 sm_table[i].s = s;
2391 /* concatenate sections */
2392 size = sh->sh_size;
2393 if (sh->sh_type != SHT_NOBITS) {
2394 unsigned char *ptr;
2395 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2396 ptr = section_ptr_add(s, size);
2397 read(fd, ptr, size);
2398 } else {
2399 s->data_offset += size;
2401 next: ;
2404 /* //gr relocate stab strings */
2405 if (stab_index && stabstr_index) {
2406 Stab_Sym *a, *b;
2407 unsigned o;
2408 s = sm_table[stab_index].s;
2409 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2410 b = (Stab_Sym *)(s->data + s->data_offset);
2411 o = sm_table[stabstr_index].offset;
2412 while (a < b)
2413 a->n_strx += o, a++;
2416 /* second short pass to update sh_link and sh_info fields of new
2417 sections */
2418 for(i = 1; i < ehdr.e_shnum; i++) {
2419 s = sm_table[i].s;
2420 if (!s || !sm_table[i].new_section)
2421 continue;
2422 sh = &shdr[i];
2423 if (sh->sh_link > 0)
2424 s->link = sm_table[sh->sh_link].s;
2425 if (sh->sh_type == SHT_RELX) {
2426 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2427 /* update backward link */
2428 s1->sections[s->sh_info]->reloc = s;
2431 sm = sm_table;
2433 /* resolve symbols */
2434 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2436 sym = symtab + 1;
2437 for(i = 1; i < nb_syms; i++, sym++) {
2438 if (sym->st_shndx != SHN_UNDEF &&
2439 sym->st_shndx < SHN_LORESERVE) {
2440 sm = &sm_table[sym->st_shndx];
2441 if (sm->link_once) {
2442 /* if a symbol is in a link once section, we use the
2443 already defined symbol. It is very important to get
2444 correct relocations */
2445 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2446 name = strtab + sym->st_name;
2447 sym_index = find_elf_sym(symtab_section, name);
2448 if (sym_index)
2449 old_to_new_syms[i] = sym_index;
2451 continue;
2453 /* if no corresponding section added, no need to add symbol */
2454 if (!sm->s)
2455 continue;
2456 /* convert section number */
2457 sym->st_shndx = sm->s->sh_num;
2458 /* offset value */
2459 sym->st_value += sm->offset;
2461 /* add symbol */
2462 name = strtab + sym->st_name;
2463 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2464 sym->st_info, sym->st_other,
2465 sym->st_shndx, name);
2466 old_to_new_syms[i] = sym_index;
2469 /* third pass to patch relocation entries */
2470 for(i = 1; i < ehdr.e_shnum; i++) {
2471 s = sm_table[i].s;
2472 if (!s)
2473 continue;
2474 sh = &shdr[i];
2475 offset = sm_table[i].offset;
2476 switch(s->sh_type) {
2477 case SHT_RELX:
2478 /* take relocation offset information */
2479 offseti = sm_table[sh->sh_info].offset;
2480 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2481 for(rel = (ElfW_Rel *)(s->data + offset);
2482 rel < rel_end;
2483 rel++) {
2484 int type;
2485 unsigned sym_index;
2486 /* convert symbol index */
2487 type = ELFW(R_TYPE)(rel->r_info);
2488 sym_index = ELFW(R_SYM)(rel->r_info);
2489 /* NOTE: only one symtab assumed */
2490 if (sym_index >= nb_syms)
2491 goto invalid_reloc;
2492 sym_index = old_to_new_syms[sym_index];
2493 /* ignore link_once in rel section. */
2494 if (!sym_index && !sm->link_once
2495 #ifdef TCC_TARGET_ARM
2496 && type != R_ARM_V4BX
2497 #endif
2499 invalid_reloc:
2500 error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2501 i, strsec + sh->sh_name, rel->r_offset);
2502 goto fail;
2504 rel->r_info = ELFW(R_INFO)(sym_index, type);
2505 /* offset the relocation offset */
2506 rel->r_offset += offseti;
2508 break;
2509 default:
2510 break;
2514 ret = 0;
2515 the_end:
2516 tcc_free(symtab);
2517 tcc_free(strtab);
2518 tcc_free(old_to_new_syms);
2519 tcc_free(sm_table);
2520 tcc_free(strsec);
2521 tcc_free(shdr);
2522 return ret;
2525 typedef struct ArchiveHeader {
2526 char ar_name[16]; /* name of this member */
2527 char ar_date[12]; /* file mtime */
2528 char ar_uid[6]; /* owner uid; printed as decimal */
2529 char ar_gid[6]; /* owner gid; printed as decimal */
2530 char ar_mode[8]; /* file mode, printed as octal */
2531 char ar_size[10]; /* file size, printed as decimal */
2532 char ar_fmag[2]; /* should contain ARFMAG */
2533 } ArchiveHeader;
2535 static int get_be32(const uint8_t *b)
2537 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2540 /* load only the objects which resolve undefined symbols */
2541 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2543 int i, bound, nsyms, sym_index, off, ret;
2544 uint8_t *data;
2545 const char *ar_names, *p;
2546 const uint8_t *ar_index;
2547 ElfW(Sym) *sym;
2549 data = tcc_malloc(size);
2550 if (read(fd, data, size) != size)
2551 goto fail;
2552 nsyms = get_be32(data);
2553 ar_index = data + 4;
2554 ar_names = ar_index + nsyms * 4;
2556 do {
2557 bound = 0;
2558 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2559 sym_index = find_elf_sym(symtab_section, p);
2560 if(sym_index) {
2561 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2562 if(sym->st_shndx == SHN_UNDEF) {
2563 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2564 #if 0
2565 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2566 #endif
2567 ++bound;
2568 lseek(fd, off, SEEK_SET);
2569 if(tcc_load_object_file(s1, fd, off) < 0) {
2570 fail:
2571 ret = -1;
2572 goto the_end;
2577 } while(bound);
2578 ret = 0;
2579 the_end:
2580 tcc_free(data);
2581 return ret;
2584 /* load a '.a' file */
2585 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2587 ArchiveHeader hdr;
2588 char ar_size[11];
2589 char ar_name[17];
2590 char magic[8];
2591 int size, len, i;
2592 unsigned long file_offset;
2594 /* skip magic which was already checked */
2595 read(fd, magic, sizeof(magic));
2597 for(;;) {
2598 len = read(fd, &hdr, sizeof(hdr));
2599 if (len == 0)
2600 break;
2601 if (len != sizeof(hdr)) {
2602 error_noabort("invalid archive");
2603 return -1;
2605 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2606 ar_size[sizeof(hdr.ar_size)] = '\0';
2607 size = strtol(ar_size, NULL, 0);
2608 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2609 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2610 if (ar_name[i] != ' ')
2611 break;
2613 ar_name[i + 1] = '\0';
2614 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2615 file_offset = lseek(fd, 0, SEEK_CUR);
2616 /* align to even */
2617 size = (size + 1) & ~1;
2618 if (!strcmp(ar_name, "/")) {
2619 /* coff symbol table : we handle it */
2620 if(s1->alacarte_link)
2621 return tcc_load_alacarte(s1, fd, size);
2622 } else if (!strcmp(ar_name, "//") ||
2623 !strcmp(ar_name, "__.SYMDEF") ||
2624 !strcmp(ar_name, "__.SYMDEF/") ||
2625 !strcmp(ar_name, "ARFILENAMES/")) {
2626 /* skip symbol table or archive names */
2627 } else {
2628 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2629 return -1;
2631 lseek(fd, file_offset + size, SEEK_SET);
2633 return 0;
2636 #ifndef TCC_TARGET_PE
2637 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2638 is referenced by the user (so it should be added as DT_NEEDED in
2639 the generated ELF file) */
2640 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2642 ElfW(Ehdr) ehdr;
2643 ElfW(Shdr) *shdr, *sh, *sh1;
2644 int i, j, nb_syms, nb_dts, sym_bind, ret;
2645 ElfW(Sym) *sym, *dynsym;
2646 ElfW(Dyn) *dt, *dynamic;
2647 unsigned char *dynstr;
2648 const char *name, *soname;
2649 DLLReference *dllref;
2651 read(fd, &ehdr, sizeof(ehdr));
2653 /* test CPU specific stuff */
2654 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2655 ehdr.e_machine != EM_TCC_TARGET) {
2656 error_noabort("bad architecture");
2657 return -1;
2660 /* read sections */
2661 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2663 /* load dynamic section and dynamic symbols */
2664 nb_syms = 0;
2665 nb_dts = 0;
2666 dynamic = NULL;
2667 dynsym = NULL; /* avoid warning */
2668 dynstr = NULL; /* avoid warning */
2669 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2670 switch(sh->sh_type) {
2671 case SHT_DYNAMIC:
2672 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2673 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2674 break;
2675 case SHT_DYNSYM:
2676 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2677 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2678 sh1 = &shdr[sh->sh_link];
2679 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2680 break;
2681 default:
2682 break;
2686 /* compute the real library name */
2687 soname = tcc_basename(filename);
2689 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2690 if (dt->d_tag == DT_SONAME) {
2691 soname = dynstr + dt->d_un.d_val;
2695 /* if the dll is already loaded, do not load it */
2696 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2697 dllref = s1->loaded_dlls[i];
2698 if (!strcmp(soname, dllref->name)) {
2699 /* but update level if needed */
2700 if (level < dllref->level)
2701 dllref->level = level;
2702 ret = 0;
2703 goto the_end;
2707 // printf("loading dll '%s'\n", soname);
2709 /* add the dll and its level */
2710 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2711 dllref->level = level;
2712 strcpy(dllref->name, soname);
2713 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2715 /* add dynamic symbols in dynsym_section */
2716 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2717 sym_bind = ELFW(ST_BIND)(sym->st_info);
2718 if (sym_bind == STB_LOCAL)
2719 continue;
2720 name = dynstr + sym->st_name;
2721 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2722 sym->st_info, sym->st_other, sym->st_shndx, name);
2725 /* load all referenced DLLs */
2726 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2727 switch(dt->d_tag) {
2728 case DT_NEEDED:
2729 name = dynstr + dt->d_un.d_val;
2730 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2731 dllref = s1->loaded_dlls[j];
2732 if (!strcmp(name, dllref->name))
2733 goto already_loaded;
2735 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2736 error_noabort("referenced dll '%s' not found", name);
2737 ret = -1;
2738 goto the_end;
2740 already_loaded:
2741 break;
2744 ret = 0;
2745 the_end:
2746 tcc_free(dynstr);
2747 tcc_free(dynsym);
2748 tcc_free(dynamic);
2749 tcc_free(shdr);
2750 return ret;
2753 #define LD_TOK_NAME 256
2754 #define LD_TOK_EOF (-1)
2756 /* return next ld script token */
2757 static int ld_next(TCCState *s1, char *name, int name_size)
2759 int c;
2760 char *q;
2762 redo:
2763 switch(ch) {
2764 case ' ':
2765 case '\t':
2766 case '\f':
2767 case '\v':
2768 case '\r':
2769 case '\n':
2770 inp();
2771 goto redo;
2772 case '/':
2773 minp();
2774 if (ch == '*') {
2775 file->buf_ptr = parse_comment(file->buf_ptr);
2776 ch = file->buf_ptr[0];
2777 goto redo;
2778 } else {
2779 q = name;
2780 *q++ = '/';
2781 goto parse_name;
2783 break;
2784 /* case 'a' ... 'z': */
2785 case 'a':
2786 case 'b':
2787 case 'c':
2788 case 'd':
2789 case 'e':
2790 case 'f':
2791 case 'g':
2792 case 'h':
2793 case 'i':
2794 case 'j':
2795 case 'k':
2796 case 'l':
2797 case 'm':
2798 case 'n':
2799 case 'o':
2800 case 'p':
2801 case 'q':
2802 case 'r':
2803 case 's':
2804 case 't':
2805 case 'u':
2806 case 'v':
2807 case 'w':
2808 case 'x':
2809 case 'y':
2810 case 'z':
2811 /* case 'A' ... 'z': */
2812 case 'A':
2813 case 'B':
2814 case 'C':
2815 case 'D':
2816 case 'E':
2817 case 'F':
2818 case 'G':
2819 case 'H':
2820 case 'I':
2821 case 'J':
2822 case 'K':
2823 case 'L':
2824 case 'M':
2825 case 'N':
2826 case 'O':
2827 case 'P':
2828 case 'Q':
2829 case 'R':
2830 case 'S':
2831 case 'T':
2832 case 'U':
2833 case 'V':
2834 case 'W':
2835 case 'X':
2836 case 'Y':
2837 case 'Z':
2838 case '_':
2839 case '\\':
2840 case '.':
2841 case '$':
2842 case '~':
2843 q = name;
2844 parse_name:
2845 for(;;) {
2846 if (!((ch >= 'a' && ch <= 'z') ||
2847 (ch >= 'A' && ch <= 'Z') ||
2848 (ch >= '0' && ch <= '9') ||
2849 strchr("/.-_+=$:\\,~", ch)))
2850 break;
2851 if ((q - name) < name_size - 1) {
2852 *q++ = ch;
2854 minp();
2856 *q = '\0';
2857 c = LD_TOK_NAME;
2858 break;
2859 case CH_EOF:
2860 c = LD_TOK_EOF;
2861 break;
2862 default:
2863 c = ch;
2864 inp();
2865 break;
2867 #if 0
2868 printf("tok=%c %d\n", c, c);
2869 if (c == LD_TOK_NAME)
2870 printf(" name=%s\n", name);
2871 #endif
2872 return c;
2875 char *tcc_strcpy_part(char *out, const char *in, size_t num)
2877 memcpy(out, in, num);
2878 out[num] = '\0';
2879 return out;
2883 * Extract the library name from the file name
2884 * Return 0 if the file isn't a library
2886 * /!\ No test on filename capacity, be careful
2888 static int filename_to_libname(TCCState *s1, const char filename[], char libname[])
2890 char *ext;
2891 int libprefix;
2893 /* already converted to library name */
2894 if (libname[0] != '\0')
2895 return 1;
2896 ext = tcc_fileextension(filename);
2897 if (*ext == '\0')
2898 return 0;
2899 libprefix = !strncmp(filename, "lib", 3);
2900 if (!s1->static_link) {
2901 #ifdef TCC_TARGET_PE
2902 if (!strcmp(ext, ".def")) {
2903 size_t len = ext - filename;
2904 tcc_strcpy_part(libname, filename, len);
2905 return 1;
2907 #else
2908 if (libprefix && (!strcmp(ext, ".so"))) {
2909 size_t len = ext - filename - 3;
2910 tcc_strcpy_part(libname, filename + 3, len);
2911 return 1;
2913 #endif
2914 } else {
2915 if (libprefix && (!strcmp(ext, ".a"))) {
2916 size_t len = ext - filename - 3;
2917 tcc_strcpy_part(libname, filename + 3, len);
2918 return 1;
2921 return 0;
2925 * Extract the file name from the library name
2927 * /!\ No test on filename capacity, be careful
2929 static void libname_to_filename(TCCState *s1, const char libname[], char filename[])
2931 if (!s1->static_link) {
2932 #ifdef TCC_TARGET_PE
2933 sprintf(filename, "%s.def", libname);
2934 #else
2935 sprintf(filename, "lib%s.so", libname);
2936 #endif
2937 } else {
2938 sprintf(filename, "lib%s.a", libname);
2942 static int ld_add_file(TCCState *s1, const char filename[], char libname[])
2944 int ret;
2946 ret = tcc_add_file_internal(s1, filename, 0);
2947 if (ret) {
2948 if (filename_to_libname(s1, filename, libname))
2949 ret = tcc_add_library(s1, libname);
2951 return ret;
2954 static inline int new_undef_syms(void)
2956 int ret = 0;
2957 ret = new_undef_sym;
2958 new_undef_sym = 0;
2959 return ret;
2962 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
2964 char filename[1024], libname[1024];
2965 int t, group, nblibs = 0, ret = 0;
2966 char **libs = NULL;
2968 group = !strcmp(cmd, "GROUP");
2969 if (!as_needed)
2970 new_undef_syms();
2971 t = ld_next(s1, filename, sizeof(filename));
2972 if (t != '(')
2973 expect("(");
2974 t = ld_next(s1, filename, sizeof(filename));
2975 for(;;) {
2976 libname[0] = '\0';
2977 if (t == LD_TOK_EOF) {
2978 error_noabort("unexpected end of file");
2979 ret = -1;
2980 goto lib_parse_error;
2981 } else if (t == ')') {
2982 break;
2983 } else if (t == '-') {
2984 t = ld_next(s1, filename, sizeof(filename));
2985 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
2986 error_noabort("library name expected");
2987 ret = -1;
2988 goto lib_parse_error;
2990 strcpy(libname, &filename[1]);
2991 libname_to_filename(s1, libname, filename);
2992 } else if (t != LD_TOK_NAME) {
2993 error_noabort("filename expected");
2994 ret = -1;
2995 goto lib_parse_error;
2997 if (!strcmp(filename, "AS_NEEDED")) {
2998 ret = ld_add_file_list(s1, cmd, 1);
2999 if (ret)
3000 goto lib_parse_error;
3001 } else {
3002 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3003 if (!as_needed) {
3004 ret = ld_add_file(s1, filename, libname);
3005 if (ret)
3006 goto lib_parse_error;
3007 if (group) {
3008 /* Add the filename *and* the libname to avoid future conversions */
3009 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
3010 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
3014 t = ld_next(s1, filename, sizeof(filename));
3015 if (t == ',') {
3016 t = ld_next(s1, filename, sizeof(filename));
3019 if (group && !as_needed) {
3020 while (new_undef_syms()) {
3021 int i;
3023 for (i = 0; i < nblibs; i += 2)
3024 ld_add_file(s1, libs[i], libs[i+1]);
3027 lib_parse_error:
3028 dynarray_reset(&libs, &nblibs);
3029 return ret;
3032 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3033 files */
3034 ST_FUNC int tcc_load_ldscript(TCCState *s1)
3036 char cmd[64];
3037 char filename[1024];
3038 int t, ret;
3040 ch = file->buf_ptr[0];
3041 ch = handle_eob();
3042 for(;;) {
3043 t = ld_next(s1, cmd, sizeof(cmd));
3044 if (t == LD_TOK_EOF)
3045 return 0;
3046 else if (t != LD_TOK_NAME)
3047 return -1;
3048 if (!strcmp(cmd, "INPUT") ||
3049 !strcmp(cmd, "GROUP")) {
3050 ret = ld_add_file_list(s1, cmd, 0);
3051 if (ret)
3052 return ret;
3053 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3054 !strcmp(cmd, "TARGET")) {
3055 /* ignore some commands */
3056 t = ld_next(s1, cmd, sizeof(cmd));
3057 if (t != '(')
3058 expect("(");
3059 for(;;) {
3060 t = ld_next(s1, filename, sizeof(filename));
3061 if (t == LD_TOK_EOF) {
3062 error_noabort("unexpected end of file");
3063 return -1;
3064 } else if (t == ')') {
3065 break;
3068 } else {
3069 return -1;
3072 return 0;
3074 #endif