First naive DLL support on x86-64.
[tinycc/kirr.git] / tccelf.c
blob0bc4bca899e7b7dd3a64833ac67817587dd853a9
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 #ifdef TCC_TARGET_X86_64
22 #define ElfW_Rel ElfW(Rela)
23 #define SHT_RELX SHT_RELA
24 #define REL_SECTION_FMT ".rela%s"
25 #else
26 #define ElfW_Rel ElfW(Rel)
27 #define SHT_RELX SHT_REL
28 #define REL_SECTION_FMT ".rel%s"
29 #endif
31 static int put_elf_str(Section *s, const char *sym)
33 int offset, len;
34 char *ptr;
36 len = strlen(sym) + 1;
37 offset = s->data_offset;
38 ptr = section_ptr_add(s, len);
39 memcpy(ptr, sym, len);
40 return offset;
43 /* elf symbol hashing function */
44 static unsigned long elf_hash(const unsigned char *name)
46 unsigned long h = 0, g;
48 while (*name) {
49 h = (h << 4) + *name++;
50 g = h & 0xf0000000;
51 if (g)
52 h ^= g >> 24;
53 h &= ~g;
55 return h;
58 /* rebuild hash table of section s */
59 /* NOTE: we do factorize the hash table code to go faster */
60 static void rebuild_hash(Section *s, unsigned int nb_buckets)
62 ElfW(Sym) *sym;
63 int *ptr, *hash, nb_syms, sym_index, h;
64 char *strtab;
66 strtab = s->link->data;
67 nb_syms = s->data_offset / sizeof(ElfW(Sym));
69 s->hash->data_offset = 0;
70 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
71 ptr[0] = nb_buckets;
72 ptr[1] = nb_syms;
73 ptr += 2;
74 hash = ptr;
75 memset(hash, 0, (nb_buckets + 1) * sizeof(int));
76 ptr += nb_buckets + 1;
78 sym = (ElfW(Sym) *)s->data + 1;
79 for(sym_index = 1; sym_index < nb_syms; sym_index++) {
80 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
81 h = elf_hash(strtab + sym->st_name) % nb_buckets;
82 *ptr = hash[h];
83 hash[h] = sym_index;
84 } else {
85 *ptr = 0;
87 ptr++;
88 sym++;
92 /* return the symbol number */
93 static int put_elf_sym(Section *s,
94 unsigned long value, unsigned long size,
95 int info, int other, int shndx, const char *name)
97 int name_offset, sym_index;
98 int nbuckets, h;
99 ElfW(Sym) *sym;
100 Section *hs;
102 sym = section_ptr_add(s, sizeof(ElfW(Sym)));
103 if (name)
104 name_offset = put_elf_str(s->link, name);
105 else
106 name_offset = 0;
107 /* XXX: endianness */
108 sym->st_name = name_offset;
109 sym->st_value = value;
110 sym->st_size = size;
111 sym->st_info = info;
112 sym->st_other = other;
113 sym->st_shndx = shndx;
114 sym_index = sym - (ElfW(Sym) *)s->data;
115 hs = s->hash;
116 if (hs) {
117 int *ptr, *base;
118 ptr = section_ptr_add(hs, sizeof(int));
119 base = (int *)hs->data;
120 /* only add global or weak symbols */
121 if (ELFW(ST_BIND)(info) != STB_LOCAL) {
122 /* add another hashing entry */
123 nbuckets = base[0];
124 h = elf_hash(name) % nbuckets;
125 *ptr = base[2 + h];
126 base[2 + h] = sym_index;
127 base[1]++;
128 /* we resize the hash table */
129 hs->nb_hashed_syms++;
130 if (hs->nb_hashed_syms > 2 * nbuckets) {
131 rebuild_hash(s, 2 * nbuckets);
133 } else {
134 *ptr = 0;
135 base[1]++;
138 return sym_index;
141 /* find global ELF symbol 'name' and return its index. Return 0 if not
142 found. */
143 static int find_elf_sym(Section *s, const char *name)
145 ElfW(Sym) *sym;
146 Section *hs;
147 int nbuckets, sym_index, h;
148 const char *name1;
150 hs = s->hash;
151 if (!hs)
152 return 0;
153 nbuckets = ((int *)hs->data)[0];
154 h = elf_hash(name) % nbuckets;
155 sym_index = ((int *)hs->data)[2 + h];
156 while (sym_index != 0) {
157 sym = &((ElfW(Sym) *)s->data)[sym_index];
158 name1 = s->link->data + sym->st_name;
159 if (!strcmp(name, name1))
160 return sym_index;
161 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
163 return 0;
166 /* return elf symbol value or error */
167 int tcc_get_symbol(TCCState *s, unsigned long *pval, const char *name)
169 int sym_index;
170 ElfW(Sym) *sym;
172 sym_index = find_elf_sym(symtab_section, name);
173 if (!sym_index)
174 return -1;
175 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
176 *pval = sym->st_value;
177 return 0;
180 void *tcc_get_symbol_err(TCCState *s, const char *name)
182 unsigned long val;
183 if (tcc_get_symbol(s, &val, name) < 0)
184 error("%s not defined", name);
185 return (void *)val;
188 /* add an elf symbol : check if it is already defined and patch
189 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
190 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
191 int info, int other, int sh_num, const char *name)
193 ElfW(Sym) *esym;
194 int sym_bind, sym_index, sym_type, esym_bind;
195 unsigned char sym_vis, esym_vis, new_vis;
197 sym_bind = ELFW(ST_BIND)(info);
198 sym_type = ELFW(ST_TYPE)(info);
199 sym_vis = ELFW(ST_VISIBILITY)(other);
201 if (sym_bind != STB_LOCAL) {
202 /* we search global or weak symbols */
203 sym_index = find_elf_sym(s, name);
204 if (!sym_index)
205 goto do_def;
206 esym = &((ElfW(Sym) *)s->data)[sym_index];
207 if (esym->st_shndx != SHN_UNDEF) {
208 esym_bind = ELFW(ST_BIND)(esym->st_info);
209 /* propagate the most constraining visibility */
210 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
211 esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
212 if (esym_vis == STV_DEFAULT) {
213 new_vis = sym_vis;
214 } else if (sym_vis == STV_DEFAULT) {
215 new_vis = esym_vis;
216 } else {
217 new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
219 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
220 | new_vis;
221 other = esym->st_other; /* in case we have to patch esym */
222 if (sh_num == SHN_UNDEF) {
223 /* ignore adding of undefined symbol if the
224 corresponding symbol is already defined */
225 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
226 /* global overrides weak, so patch */
227 goto do_patch;
228 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
229 /* weak is ignored if already global */
230 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
231 /* ignore hidden symbols after */
232 } else if (esym->st_shndx == SHN_COMMON && sh_num < SHN_LORESERVE) {
233 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
234 No idea if this is the correct solution ... */
235 goto do_patch;
236 } else if (s == tcc_state->dynsymtab_section) {
237 /* we accept that two DLL define the same symbol */
238 } else {
239 #if 1
240 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
241 sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
242 #endif
243 error_noabort("'%s' defined twice", name);
245 } else {
246 do_patch:
247 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
248 esym->st_shndx = sh_num;
249 esym->st_value = value;
250 esym->st_size = size;
251 esym->st_other = other;
253 } else {
254 do_def:
255 sym_index = put_elf_sym(s, value, size,
256 ELFW(ST_INFO)(sym_bind, sym_type), other,
257 sh_num, name);
259 return sym_index;
262 /* put relocation */
263 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
264 int type, int symbol)
266 char buf[256];
267 Section *sr;
268 ElfW_Rel *rel;
270 sr = s->reloc;
271 if (!sr) {
272 /* if no relocation section, create it */
273 snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
274 /* if the symtab is allocated, then we consider the relocation
275 are also */
276 sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
277 sr->sh_entsize = sizeof(ElfW_Rel);
278 sr->link = symtab;
279 sr->sh_info = s->sh_num;
280 s->reloc = sr;
282 rel = section_ptr_add(sr, sizeof(ElfW_Rel));
283 rel->r_offset = offset;
284 rel->r_info = ELFW(R_INFO)(symbol, type);
285 #ifdef TCC_TARGET_X86_64
286 rel->r_addend = 0;
287 #endif
290 /* put stab debug information */
292 typedef struct {
293 unsigned long n_strx; /* index into string table of name */
294 unsigned char n_type; /* type of symbol */
295 unsigned char n_other; /* misc info (usually empty) */
296 unsigned short n_desc; /* description field */
297 unsigned long n_value; /* value of symbol */
298 } Stab_Sym;
300 static void put_stabs(const char *str, int type, int other, int desc,
301 unsigned long value)
303 Stab_Sym *sym;
305 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
306 if (str) {
307 sym->n_strx = put_elf_str(stabstr_section, str);
308 } else {
309 sym->n_strx = 0;
311 sym->n_type = type;
312 sym->n_other = other;
313 sym->n_desc = desc;
314 sym->n_value = value;
317 static void put_stabs_r(const char *str, int type, int other, int desc,
318 unsigned long value, Section *sec, int sym_index)
320 put_stabs(str, type, other, desc, value);
321 put_elf_reloc(symtab_section, stab_section,
322 stab_section->data_offset - sizeof(unsigned long),
323 R_DATA_32, sym_index);
326 static void put_stabn(int type, int other, int desc, int value)
328 put_stabs(NULL, type, other, desc, value);
331 static void put_stabd(int type, int other, int desc)
333 put_stabs(NULL, type, other, desc, 0);
336 /* In an ELF file symbol table, the local symbols must appear below
337 the global and weak ones. Since TCC cannot sort it while generating
338 the code, we must do it after. All the relocation tables are also
339 modified to take into account the symbol table sorting */
340 static void sort_syms(TCCState *s1, Section *s)
342 int *old_to_new_syms;
343 ElfW(Sym) *new_syms;
344 int nb_syms, i;
345 ElfW(Sym) *p, *q;
346 ElfW_Rel *rel, *rel_end;
347 Section *sr;
348 int type, sym_index;
350 nb_syms = s->data_offset / sizeof(ElfW(Sym));
351 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
352 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
354 /* first pass for local symbols */
355 p = (ElfW(Sym) *)s->data;
356 q = new_syms;
357 for(i = 0; i < nb_syms; i++) {
358 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
359 old_to_new_syms[i] = q - new_syms;
360 *q++ = *p;
362 p++;
364 /* save the number of local symbols in section header */
365 s->sh_info = q - new_syms;
367 /* then second pass for non local symbols */
368 p = (ElfW(Sym) *)s->data;
369 for(i = 0; i < nb_syms; i++) {
370 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
371 old_to_new_syms[i] = q - new_syms;
372 *q++ = *p;
374 p++;
377 /* we copy the new symbols to the old */
378 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
379 tcc_free(new_syms);
381 /* now we modify all the relocations */
382 for(i = 1; i < s1->nb_sections; i++) {
383 sr = s1->sections[i];
384 if (sr->sh_type == SHT_RELX && sr->link == s) {
385 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
386 for(rel = (ElfW_Rel *)sr->data;
387 rel < rel_end;
388 rel++) {
389 sym_index = ELFW(R_SYM)(rel->r_info);
390 type = ELFW(R_TYPE)(rel->r_info);
391 sym_index = old_to_new_syms[sym_index];
392 rel->r_info = ELFW(R_INFO)(sym_index, type);
397 tcc_free(old_to_new_syms);
400 /* relocate common symbols in the .bss section */
401 static void relocate_common_syms(void)
403 ElfW(Sym) *sym, *sym_end;
404 unsigned long offset, align;
406 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
407 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
408 sym < sym_end;
409 sym++) {
410 if (sym->st_shndx == SHN_COMMON) {
411 /* align symbol */
412 align = sym->st_value;
413 offset = bss_section->data_offset;
414 offset = (offset + align - 1) & -align;
415 sym->st_value = offset;
416 sym->st_shndx = bss_section->sh_num;
417 offset += sym->st_size;
418 bss_section->data_offset = offset;
423 /* relocate symbol table, resolve undefined symbols if do_resolve is
424 true and output error if undefined symbol. */
425 static void relocate_syms(TCCState *s1, int do_resolve)
427 ElfW(Sym) *sym, *esym, *sym_end;
428 int sym_bind, sh_num, sym_index;
429 const char *name;
430 unsigned long addr;
432 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
433 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
434 sym < sym_end;
435 sym++) {
436 sh_num = sym->st_shndx;
437 if (sh_num == SHN_UNDEF) {
438 name = strtab_section->data + sym->st_name;
439 if (do_resolve) {
440 name = symtab_section->link->data + sym->st_name;
441 addr = (unsigned long)resolve_sym(s1, name, ELFW(ST_TYPE)(sym->st_info));
442 if (addr) {
443 sym->st_value = addr;
444 goto found;
446 } else if (s1->dynsym) {
447 /* if dynamic symbol exist, then use it */
448 sym_index = find_elf_sym(s1->dynsym, name);
449 if (sym_index) {
450 esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
451 sym->st_value = esym->st_value;
452 goto found;
455 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
456 it */
457 if (!strcmp(name, "_fp_hw"))
458 goto found;
459 /* only weak symbols are accepted to be undefined. Their
460 value is zero */
461 sym_bind = ELFW(ST_BIND)(sym->st_info);
462 if (sym_bind == STB_WEAK) {
463 sym->st_value = 0;
464 } else {
465 error_noabort("undefined symbol '%s'", name);
467 } else if (sh_num < SHN_LORESERVE) {
468 /* add section base */
469 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
471 found: ;
475 #ifdef TCC_TARGET_X86_64
476 #define JMP_TABLE_ENTRY_SIZE 14
477 #define JMP_TABLE_ENTRY_MAX_NUM 4096
478 static unsigned long add_jmp_table(TCCState *s1, unsigned long val)
480 char *p;
481 if (!s1->jmp_table) {
482 int size = JMP_TABLE_ENTRY_SIZE * JMP_TABLE_ENTRY_MAX_NUM;
483 s1->jmp_table_num = 0;
484 s1->jmp_table = (char *)tcc_malloc(size);
485 set_pages_executable(s1->jmp_table, size);
487 if (s1->jmp_table_num == JMP_TABLE_ENTRY_MAX_NUM) {
488 error("relocating >%d symbols are not supported",
489 JMP_TABLE_ENTRY_MAX_NUM);
491 p = s1->jmp_table + s1->jmp_table_num * JMP_TABLE_ENTRY_SIZE;
492 s1->jmp_table_num++;
493 /* jmp *0x0(%rip) */
494 p[0] = 0xff;
495 p[1] = 0x25;
496 *(int *)(p + 2) = 0;
497 *(unsigned long *)(p + 6) = val;
498 return (unsigned long)p;
500 #endif
502 /* relocate a given section (CPU dependent) */
503 static void relocate_section(TCCState *s1, Section *s)
505 Section *sr;
506 ElfW_Rel *rel, *rel_end, *qrel;
507 ElfW(Sym) *sym;
508 int type, sym_index;
509 unsigned char *ptr;
510 unsigned long val, addr;
511 int esym_index;
513 sr = s->reloc;
514 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
515 qrel = (ElfW_Rel *)sr->data;
516 for(rel = qrel;
517 rel < rel_end;
518 rel++) {
519 ptr = s->data + rel->r_offset;
521 sym_index = ELFW(R_SYM)(rel->r_info);
522 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
523 val = sym->st_value;
524 #ifdef TCC_TARGET_X86_64
525 /* XXX: not tested */
526 val += rel->r_addend;
527 #endif
528 type = ELFW(R_TYPE)(rel->r_info);
529 addr = s->sh_addr + rel->r_offset;
531 /* CPU specific */
532 switch(type) {
533 #if defined(TCC_TARGET_I386)
534 case R_386_32:
535 if (s1->output_type == TCC_OUTPUT_DLL) {
536 esym_index = s1->symtab_to_dynsym[sym_index];
537 qrel->r_offset = rel->r_offset;
538 if (esym_index) {
539 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
540 qrel++;
541 break;
542 } else {
543 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
544 qrel++;
547 *(int *)ptr += val;
548 break;
549 case R_386_PC32:
550 if (s1->output_type == TCC_OUTPUT_DLL) {
551 /* DLL relocation */
552 esym_index = s1->symtab_to_dynsym[sym_index];
553 if (esym_index) {
554 qrel->r_offset = rel->r_offset;
555 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
556 qrel++;
557 break;
560 *(int *)ptr += val - addr;
561 break;
562 case R_386_PLT32:
563 *(int *)ptr += val - addr;
564 break;
565 case R_386_GLOB_DAT:
566 case R_386_JMP_SLOT:
567 *(int *)ptr = val;
568 break;
569 case R_386_GOTPC:
570 *(int *)ptr += s1->got->sh_addr - addr;
571 break;
572 case R_386_GOTOFF:
573 *(int *)ptr += val - s1->got->sh_addr;
574 break;
575 case R_386_GOT32:
576 /* we load the got offset */
577 *(int *)ptr += s1->got_offsets[sym_index];
578 break;
579 #elif defined(TCC_TARGET_ARM)
580 case R_ARM_PC24:
581 case R_ARM_CALL:
582 case R_ARM_JUMP24:
583 case R_ARM_PLT32:
585 int x;
586 x = (*(int *)ptr)&0xffffff;
587 (*(int *)ptr) &= 0xff000000;
588 if (x & 0x800000)
589 x -= 0x1000000;
590 x *= 4;
591 x += val - addr;
592 if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
593 error("can't relocate value at %x",addr);
594 x >>= 2;
595 x &= 0xffffff;
596 (*(int *)ptr) |= x;
598 break;
599 case R_ARM_PREL31:
601 int x;
602 x = (*(int *)ptr) & 0x7fffffff;
603 (*(int *)ptr) &= 0x80000000;
604 x = (x * 2) / 2;
605 x += val - addr;
606 if((x^(x>>1))&0x40000000)
607 error("can't relocate value at %x",addr);
608 (*(int *)ptr) |= x & 0x7fffffff;
610 case R_ARM_ABS32:
611 *(int *)ptr += val;
612 break;
613 case R_ARM_BASE_PREL:
614 *(int *)ptr += s1->got->sh_addr - addr;
615 break;
616 case R_ARM_GOTOFF32:
617 *(int *)ptr += val - s1->got->sh_addr;
618 break;
619 case R_ARM_GOT_BREL:
620 /* we load the got offset */
621 *(int *)ptr += s1->got_offsets[sym_index];
622 break;
623 case R_ARM_COPY:
624 break;
625 default:
626 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
627 type,addr,(unsigned int )ptr,val);
628 break;
629 #elif defined(TCC_TARGET_C67)
630 case R_C60_32:
631 *(int *)ptr += val;
632 break;
633 case R_C60LO16:
635 uint32_t orig;
637 /* put the low 16 bits of the absolute address */
638 // add to what is already there
640 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
641 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
643 //patch both at once - assumes always in pairs Low - High
645 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
646 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
648 break;
649 case R_C60HI16:
650 break;
651 default:
652 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
653 type,addr,(unsigned int )ptr,val);
654 break;
655 #elif defined(TCC_TARGET_X86_64)
656 case R_X86_64_64:
657 if (s1->output_type == TCC_OUTPUT_DLL) {
658 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
659 qrel->r_addend = *(long long *)ptr + val;
660 qrel++;
662 *(long long *)ptr += val;
663 break;
664 case R_X86_64_32:
665 case R_X86_64_32S:
666 if (s1->output_type == TCC_OUTPUT_DLL) {
667 /* XXX: this logic may depend on TCC's codegen
668 now TCC uses R_X86_64_32 even for a 64bit pointer */
669 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
670 qrel->r_addend = *(int *)ptr + val;
671 qrel++;
673 *(int *)ptr += val;
674 break;
675 case R_X86_64_PC32: {
676 if (s1->output_type == TCC_OUTPUT_DLL) {
677 /* DLL relocation */
678 esym_index = s1->symtab_to_dynsym[sym_index];
679 if (esym_index) {
680 qrel->r_offset = rel->r_offset;
681 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
682 qrel->r_addend = *(int *)ptr;
683 qrel++;
684 break;
687 long diff = val - addr;
688 if (diff < -2147483648 || diff > 2147483647) {
689 /* XXX: naive support for over 32bit jump */
690 if (s1->output_type == TCC_OUTPUT_MEMORY) {
691 val = add_jmp_table(s1, val);
692 diff = val - addr;
694 if (diff <= -2147483647 || diff > 2147483647) {
695 #if 0
696 /* output memory map to debug easily */
697 FILE* fp;
698 char buf[4096];
699 int size;
700 Dl_info di;
701 printf("%ld - %ld = %ld\n", val, addr, diff);
702 dladdr((void *)addr, &di);
703 printf("addr = %lx = %lx+%lx(%s) ptr=%p\n",
704 addr, s->sh_addr, rel->r_offset, di.dli_sname,
705 ptr);
706 fp = fopen("/proc/self/maps", "r");
707 size = fread(buf, 1, 4095, fp);
708 buf[size] = '\0';
709 printf("%s", buf);
710 #endif
711 error("internal error: relocation failed");
714 *(int *)ptr += diff;
716 break;
717 case R_X86_64_PLT32:
718 *(int *)ptr += val - addr;
719 break;
720 case R_X86_64_GLOB_DAT:
721 case R_X86_64_JUMP_SLOT:
722 *(int *)ptr = val;
723 break;
724 case R_X86_64_GOTPCREL:
725 *(int *)ptr += s1->got->sh_addr - addr;
726 break;
727 case R_X86_64_GOTTPOFF:
728 *(int *)ptr += val - s1->got->sh_addr;
729 break;
730 case R_X86_64_GOT32:
731 /* we load the got offset */
732 *(int *)ptr += s1->got_offsets[sym_index];
733 break;
734 #else
735 #error unsupported processor
736 #endif
739 /* if the relocation is allocated, we change its symbol table */
740 if (sr->sh_flags & SHF_ALLOC)
741 sr->link = s1->dynsym;
744 /* relocate relocation table in 'sr' */
745 static void relocate_rel(TCCState *s1, Section *sr)
747 Section *s;
748 ElfW_Rel *rel, *rel_end;
750 s = s1->sections[sr->sh_info];
751 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
752 for(rel = (ElfW_Rel *)sr->data;
753 rel < rel_end;
754 rel++) {
755 rel->r_offset += s->sh_addr;
759 /* count the number of dynamic relocations so that we can reserve
760 their space */
761 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
763 ElfW_Rel *rel, *rel_end;
764 int sym_index, esym_index, type, count;
766 count = 0;
767 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
768 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
769 sym_index = ELFW(R_SYM)(rel->r_info);
770 type = ELFW(R_TYPE)(rel->r_info);
771 switch(type) {
772 #if defined(TCC_TARGET_I386)
773 case R_386_32:
774 #elif defined(TCC_TARGET_X86_64)
775 case R_X86_64_32:
776 case R_X86_64_32S:
777 #endif
778 count++;
779 break;
780 #if defined(TCC_TARGET_I386)
781 case R_386_PC32:
782 #elif defined(TCC_TARGET_X86_64)
783 case R_X86_64_PC32:
784 #endif
785 esym_index = s1->symtab_to_dynsym[sym_index];
786 if (esym_index)
787 count++;
788 break;
789 default:
790 break;
793 if (count) {
794 /* allocate the section */
795 sr->sh_flags |= SHF_ALLOC;
796 sr->sh_size = count * sizeof(ElfW_Rel);
798 return count;
801 static void put_got_offset(TCCState *s1, int index, unsigned long val)
803 int n;
804 unsigned long *tab;
806 if (index >= s1->nb_got_offsets) {
807 /* find immediately bigger power of 2 and reallocate array */
808 n = 1;
809 while (index >= n)
810 n *= 2;
811 tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
812 if (!tab)
813 error("memory full");
814 s1->got_offsets = tab;
815 memset(s1->got_offsets + s1->nb_got_offsets, 0,
816 (n - s1->nb_got_offsets) * sizeof(unsigned long));
817 s1->nb_got_offsets = n;
819 s1->got_offsets[index] = val;
822 /* XXX: suppress that */
823 static void put32(unsigned char *p, uint32_t val)
825 p[0] = val;
826 p[1] = val >> 8;
827 p[2] = val >> 16;
828 p[3] = val >> 24;
831 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
832 defined(TCC_TARGET_X86_64)
833 static uint32_t get32(unsigned char *p)
835 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
837 #endif
839 static void build_got(TCCState *s1)
841 unsigned char *ptr;
843 /* if no got, then create it */
844 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
845 s1->got->sh_entsize = 4;
846 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
847 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
848 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
849 #if PTR_SIZE == 4
850 /* keep space for _DYNAMIC pointer, if present */
851 put32(ptr, 0);
852 /* two dummy got entries */
853 put32(ptr + 4, 0);
854 put32(ptr + 8, 0);
855 #else
856 /* keep space for _DYNAMIC pointer, if present */
857 put32(ptr, 0);
858 put32(ptr + 4, 0);
859 /* two dummy got entries */
860 put32(ptr + 8, 0);
861 put32(ptr + 12, 0);
862 put32(ptr + 16, 0);
863 put32(ptr + 20, 0);
864 #endif
867 /* put a got entry corresponding to a symbol in symtab_section. 'size'
868 and 'info' can be modifed if more precise info comes from the DLL */
869 static void put_got_entry(TCCState *s1,
870 int reloc_type, unsigned long size, int info,
871 int sym_index)
873 int index;
874 const char *name;
875 ElfW(Sym) *sym;
876 unsigned long offset;
877 int *ptr;
879 if (!s1->got)
880 build_got(s1);
882 /* if a got entry already exists for that symbol, no need to add one */
883 if (sym_index < s1->nb_got_offsets &&
884 s1->got_offsets[sym_index] != 0)
885 return;
887 put_got_offset(s1, sym_index, s1->got->data_offset);
889 if (s1->dynsym) {
890 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
891 name = symtab_section->link->data + sym->st_name;
892 offset = sym->st_value;
893 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
894 if (reloc_type ==
895 #ifdef TCC_TARGET_X86_64
896 R_X86_64_JUMP_SLOT
897 #else
898 R_386_JMP_SLOT
899 #endif
901 Section *plt;
902 uint8_t *p;
903 int modrm;
905 /* if we build a DLL, we add a %ebx offset */
906 if (s1->output_type == TCC_OUTPUT_DLL)
907 modrm = 0xa3;
908 else
909 modrm = 0x25;
911 /* add a PLT entry */
912 plt = s1->plt;
913 if (plt->data_offset == 0) {
914 /* first plt entry */
915 p = section_ptr_add(plt, 16);
916 p[0] = 0xff; /* pushl got + PTR_SIZE */
917 p[1] = modrm + 0x10;
918 put32(p + 2, PTR_SIZE);
919 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
920 p[7] = modrm;
921 put32(p + 8, PTR_SIZE * 2);
924 p = section_ptr_add(plt, 16);
925 p[0] = 0xff; /* jmp *(got + x) */
926 p[1] = modrm;
927 put32(p + 2, s1->got->data_offset);
928 p[6] = 0x68; /* push $xxx */
929 put32(p + 7, (plt->data_offset - 32) >> 1);
930 p[11] = 0xe9; /* jmp plt_start */
931 put32(p + 12, -(plt->data_offset));
933 /* the symbol is modified so that it will be relocated to
934 the PLT */
935 if (s1->output_type == TCC_OUTPUT_EXE)
936 offset = plt->data_offset - 16;
938 #elif defined(TCC_TARGET_ARM)
939 if (reloc_type == R_ARM_JUMP_SLOT) {
940 Section *plt;
941 uint8_t *p;
943 /* if we build a DLL, we add a %ebx offset */
944 if (s1->output_type == TCC_OUTPUT_DLL)
945 error("DLLs unimplemented!");
947 /* add a PLT entry */
948 plt = s1->plt;
949 if (plt->data_offset == 0) {
950 /* first plt entry */
951 p = section_ptr_add(plt, 16);
952 put32(p , 0xe52de004);
953 put32(p + 4, 0xe59fe010);
954 put32(p + 8, 0xe08fe00e);
955 put32(p + 12, 0xe5bef008);
958 p = section_ptr_add(plt, 16);
959 put32(p , 0xe59fc004);
960 put32(p+4, 0xe08fc00c);
961 put32(p+8, 0xe59cf000);
962 put32(p+12, s1->got->data_offset);
964 /* the symbol is modified so that it will be relocated to
965 the PLT */
966 if (s1->output_type == TCC_OUTPUT_EXE)
967 offset = plt->data_offset - 16;
969 #elif defined(TCC_TARGET_C67)
970 error("C67 got not implemented");
971 #else
972 #error unsupported CPU
973 #endif
974 index = put_elf_sym(s1->dynsym, offset,
975 size, info, 0, sym->st_shndx, name);
976 /* put a got entry */
977 put_elf_reloc(s1->dynsym, s1->got,
978 s1->got->data_offset,
979 reloc_type, index);
981 ptr = section_ptr_add(s1->got, PTR_SIZE);
982 *ptr = 0;
985 /* build GOT and PLT entries */
986 static void build_got_entries(TCCState *s1)
988 Section *s, *symtab;
989 ElfW_Rel *rel, *rel_end;
990 ElfW(Sym) *sym;
991 int i, type, reloc_type, sym_index;
993 for(i = 1; i < s1->nb_sections; i++) {
994 s = s1->sections[i];
995 if (s->sh_type != SHT_RELX)
996 continue;
997 /* no need to handle got relocations */
998 if (s->link != symtab_section)
999 continue;
1000 symtab = s->link;
1001 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1002 for(rel = (ElfW_Rel *)s->data;
1003 rel < rel_end;
1004 rel++) {
1005 type = ELFW(R_TYPE)(rel->r_info);
1006 switch(type) {
1007 #if defined(TCC_TARGET_I386)
1008 case R_386_GOT32:
1009 case R_386_GOTOFF:
1010 case R_386_GOTPC:
1011 case R_386_PLT32:
1012 if (!s1->got)
1013 build_got(s1);
1014 if (type == R_386_GOT32 || type == R_386_PLT32) {
1015 sym_index = ELFW(R_SYM)(rel->r_info);
1016 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1017 /* look at the symbol got offset. If none, then add one */
1018 if (type == R_386_GOT32)
1019 reloc_type = R_386_GLOB_DAT;
1020 else
1021 reloc_type = R_386_JMP_SLOT;
1022 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1023 sym_index);
1025 break;
1026 #elif defined(TCC_TARGET_ARM)
1027 case R_ARM_GOT_BREL:
1028 case R_ARM_GOTOFF32:
1029 case R_ARM_BASE_PREL:
1030 case R_ARM_PLT32:
1031 if (!s1->got)
1032 build_got(s1);
1033 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1034 sym_index = ELFW(R_SYM)(rel->r_info);
1035 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1036 /* look at the symbol got offset. If none, then add one */
1037 if (type == R_ARM_GOT_BREL)
1038 reloc_type = R_ARM_GLOB_DAT;
1039 else
1040 reloc_type = R_ARM_JUMP_SLOT;
1041 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1042 sym_index);
1044 break;
1045 #elif defined(TCC_TARGET_C67)
1046 case R_C60_GOT32:
1047 case R_C60_GOTOFF:
1048 case R_C60_GOTPC:
1049 case R_C60_PLT32:
1050 if (!s1->got)
1051 build_got(s1);
1052 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1053 sym_index = ELFW(R_SYM)(rel->r_info);
1054 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1055 /* look at the symbol got offset. If none, then add one */
1056 if (type == R_C60_GOT32)
1057 reloc_type = R_C60_GLOB_DAT;
1058 else
1059 reloc_type = R_C60_JMP_SLOT;
1060 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1061 sym_index);
1063 break;
1064 #elif defined(TCC_TARGET_X86_64)
1065 case R_X86_64_GOT32:
1066 case R_X86_64_GOTTPOFF:
1067 case R_X86_64_GOTPCREL:
1068 case R_X86_64_PLT32:
1069 if (!s1->got)
1070 build_got(s1);
1071 if (type == R_X86_64_GOT32 || type == R_X86_64_PLT32) {
1072 sym_index = ELFW(R_SYM)(rel->r_info);
1073 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1074 /* look at the symbol got offset. If none, then add one */
1075 if (type == R_X86_64_GOT32)
1076 reloc_type = R_X86_64_GLOB_DAT;
1077 else
1078 reloc_type = R_X86_64_JUMP_SLOT;
1079 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1080 sym_index);
1082 break;
1083 #else
1084 #error unsupported CPU
1085 #endif
1086 default:
1087 break;
1093 static Section *new_symtab(TCCState *s1,
1094 const char *symtab_name, int sh_type, int sh_flags,
1095 const char *strtab_name,
1096 const char *hash_name, int hash_sh_flags)
1098 Section *symtab, *strtab, *hash;
1099 int *ptr, nb_buckets;
1101 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1102 symtab->sh_entsize = sizeof(ElfW(Sym));
1103 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1104 put_elf_str(strtab, "");
1105 symtab->link = strtab;
1106 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1108 nb_buckets = 1;
1110 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1111 hash->sh_entsize = sizeof(int);
1112 symtab->hash = hash;
1113 hash->link = symtab;
1115 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1116 ptr[0] = nb_buckets;
1117 ptr[1] = 1;
1118 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1119 return symtab;
1122 /* put dynamic tag */
1123 static void put_dt(Section *dynamic, int dt, unsigned long val)
1125 ElfW(Dyn) *dyn;
1126 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1127 dyn->d_tag = dt;
1128 dyn->d_un.d_val = val;
1131 static void add_init_array_defines(TCCState *s1, const char *section_name)
1133 Section *s;
1134 long end_offset;
1135 char sym_start[1024];
1136 char sym_end[1024];
1138 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1139 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1141 s = find_section(s1, section_name);
1142 if (!s) {
1143 end_offset = 0;
1144 s = data_section;
1145 } else {
1146 end_offset = s->data_offset;
1149 add_elf_sym(symtab_section,
1150 0, 0,
1151 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1152 s->sh_num, sym_start);
1153 add_elf_sym(symtab_section,
1154 end_offset, 0,
1155 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1156 s->sh_num, sym_end);
1159 /* add tcc runtime libraries */
1160 static void tcc_add_runtime(TCCState *s1)
1162 #if defined(CONFIG_TCC_BCHECK) || !defined(CONFIG_USE_LIBGCC)
1163 char buf[1024];
1164 #endif
1166 #ifdef CONFIG_TCC_BCHECK
1167 if (do_bounds_check) {
1168 unsigned long *ptr;
1169 Section *init_section;
1170 unsigned char *pinit;
1171 int sym_index;
1173 /* XXX: add an object file to do that */
1174 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1175 *ptr = 0;
1176 add_elf_sym(symtab_section, 0, 0,
1177 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1178 bounds_section->sh_num, "__bounds_start");
1179 /* add bound check code */
1180 snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "bcheck.o");
1181 tcc_add_file(s1, buf);
1182 #ifdef TCC_TARGET_I386
1183 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1184 /* add 'call __bound_init()' in .init section */
1185 init_section = find_section(s1, ".init");
1186 pinit = section_ptr_add(init_section, 5);
1187 pinit[0] = 0xe8;
1188 put32(pinit + 1, -4);
1189 sym_index = find_elf_sym(symtab_section, "__bound_init");
1190 put_elf_reloc(symtab_section, init_section,
1191 init_section->data_offset - 4, R_386_PC32, sym_index);
1193 #endif
1195 #endif
1196 /* add libc */
1197 if (!s1->nostdlib) {
1198 tcc_add_library(s1, "c");
1200 #ifdef CONFIG_USE_LIBGCC
1201 tcc_add_file(s1, CONFIG_SYSROOT "/lib/libgcc_s.so.1");
1202 #else
1203 snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "libtcc1.a");
1204 tcc_add_file(s1, buf);
1205 #endif
1207 /* add crt end if not memory output */
1208 if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) {
1209 tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
1213 /* add various standard linker symbols (must be done after the
1214 sections are filled (for example after allocating common
1215 symbols)) */
1216 static void tcc_add_linker_symbols(TCCState *s1)
1218 char buf[1024];
1219 int i;
1220 Section *s;
1222 add_elf_sym(symtab_section,
1223 text_section->data_offset, 0,
1224 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1225 text_section->sh_num, "_etext");
1226 add_elf_sym(symtab_section,
1227 data_section->data_offset, 0,
1228 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1229 data_section->sh_num, "_edata");
1230 add_elf_sym(symtab_section,
1231 bss_section->data_offset, 0,
1232 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1233 bss_section->sh_num, "_end");
1234 /* horrible new standard ldscript defines */
1235 add_init_array_defines(s1, ".preinit_array");
1236 add_init_array_defines(s1, ".init_array");
1237 add_init_array_defines(s1, ".fini_array");
1239 /* add start and stop symbols for sections whose name can be
1240 expressed in C */
1241 for(i = 1; i < s1->nb_sections; i++) {
1242 s = s1->sections[i];
1243 if (s->sh_type == SHT_PROGBITS &&
1244 (s->sh_flags & SHF_ALLOC)) {
1245 const char *p;
1246 int ch;
1248 /* check if section name can be expressed in C */
1249 p = s->name;
1250 for(;;) {
1251 ch = *p;
1252 if (!ch)
1253 break;
1254 if (!isid(ch) && !isnum(ch))
1255 goto next_sec;
1256 p++;
1258 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1259 add_elf_sym(symtab_section,
1260 0, 0,
1261 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1262 s->sh_num, buf);
1263 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1264 add_elf_sym(symtab_section,
1265 s->data_offset, 0,
1266 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1267 s->sh_num, buf);
1269 next_sec: ;
1273 /* name of ELF interpreter */
1274 #ifdef __FreeBSD__
1275 static char elf_interp[] = "/usr/libexec/ld-elf.so.1";
1276 #else
1277 #ifdef TCC_ARM_EABI
1278 static char elf_interp[] = "/lib/ld-linux.so.3";
1279 #elif defined(TCC_TARGET_X86_64)
1280 static char elf_interp[] = "/lib/ld-linux-x86-64.so.2";
1281 #else
1282 static char elf_interp[] = "/lib/ld-linux.so.2";
1283 #endif
1284 #endif
1286 static void tcc_output_binary(TCCState *s1, FILE *f,
1287 const int *section_order)
1289 Section *s;
1290 int i, offset, size;
1292 offset = 0;
1293 for(i=1;i<s1->nb_sections;i++) {
1294 s = s1->sections[section_order[i]];
1295 if (s->sh_type != SHT_NOBITS &&
1296 (s->sh_flags & SHF_ALLOC)) {
1297 while (offset < s->sh_offset) {
1298 fputc(0, f);
1299 offset++;
1301 size = s->sh_size;
1302 fwrite(s->data, 1, size, f);
1303 offset += size;
1308 /* output an ELF file */
1309 /* XXX: suppress unneeded sections */
1310 int elf_output_file(TCCState *s1, const char *filename)
1312 ElfW(Ehdr) ehdr;
1313 FILE *f;
1314 int fd, mode, ret;
1315 int *section_order;
1316 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
1317 unsigned long addr;
1318 Section *strsec, *s;
1319 ElfW(Shdr) shdr, *sh;
1320 ElfW(Phdr) *phdr, *ph;
1321 Section *interp, *dynamic, *dynstr;
1322 unsigned long saved_dynamic_data_offset;
1323 ElfW(Sym) *sym;
1324 int type, file_type;
1325 unsigned long rel_addr, rel_size;
1327 file_type = s1->output_type;
1328 s1->nb_errors = 0;
1330 if (file_type != TCC_OUTPUT_OBJ) {
1331 tcc_add_runtime(s1);
1334 phdr = NULL;
1335 section_order = NULL;
1336 interp = NULL;
1337 dynamic = NULL;
1338 dynstr = NULL; /* avoid warning */
1339 saved_dynamic_data_offset = 0; /* avoid warning */
1341 if (file_type != TCC_OUTPUT_OBJ) {
1342 relocate_common_syms();
1344 tcc_add_linker_symbols(s1);
1346 if (!s1->static_link) {
1347 const char *name;
1348 int sym_index, index;
1349 ElfW(Sym) *esym, *sym_end;
1351 if (file_type == TCC_OUTPUT_EXE) {
1352 char *ptr;
1353 /* add interpreter section only if executable */
1354 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1355 interp->sh_addralign = 1;
1356 ptr = section_ptr_add(interp, sizeof(elf_interp));
1357 strcpy(ptr, elf_interp);
1360 /* add dynamic symbol table */
1361 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1362 ".dynstr",
1363 ".hash", SHF_ALLOC);
1364 dynstr = s1->dynsym->link;
1366 /* add dynamic section */
1367 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1368 SHF_ALLOC | SHF_WRITE);
1369 dynamic->link = dynstr;
1370 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1372 /* add PLT */
1373 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1374 SHF_ALLOC | SHF_EXECINSTR);
1375 s1->plt->sh_entsize = 4;
1377 build_got(s1);
1379 /* scan for undefined symbols and see if they are in the
1380 dynamic symbols. If a symbol STT_FUNC is found, then we
1381 add it in the PLT. If a symbol STT_OBJECT is found, we
1382 add it in the .bss section with a suitable relocation */
1383 sym_end = (ElfW(Sym) *)(symtab_section->data +
1384 symtab_section->data_offset);
1385 if (file_type == TCC_OUTPUT_EXE) {
1386 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1387 sym < sym_end;
1388 sym++) {
1389 if (sym->st_shndx == SHN_UNDEF) {
1390 name = symtab_section->link->data + sym->st_name;
1391 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1392 if (sym_index) {
1393 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1394 type = ELFW(ST_TYPE)(esym->st_info);
1395 if (type == STT_FUNC) {
1396 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1397 esym->st_info,
1398 sym - (ElfW(Sym) *)symtab_section->data);
1399 } else if (type == STT_OBJECT) {
1400 unsigned long offset;
1401 offset = bss_section->data_offset;
1402 /* XXX: which alignment ? */
1403 offset = (offset + 16 - 1) & -16;
1404 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1405 esym->st_info, 0,
1406 bss_section->sh_num, name);
1407 put_elf_reloc(s1->dynsym, bss_section,
1408 offset, R_COPY, index);
1409 offset += esym->st_size;
1410 bss_section->data_offset = offset;
1412 } else {
1413 /* STB_WEAK undefined symbols are accepted */
1414 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1415 it */
1416 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1417 !strcmp(name, "_fp_hw")) {
1418 } else {
1419 error_noabort("undefined symbol '%s'", name);
1422 } else if (s1->rdynamic &&
1423 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1424 /* if -rdynamic option, then export all non
1425 local symbols */
1426 name = symtab_section->link->data + sym->st_name;
1427 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1428 sym->st_info, 0,
1429 sym->st_shndx, name);
1433 if (s1->nb_errors)
1434 goto fail;
1436 /* now look at unresolved dynamic symbols and export
1437 corresponding symbol */
1438 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1439 s1->dynsymtab_section->data_offset);
1440 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1441 esym < sym_end;
1442 esym++) {
1443 if (esym->st_shndx == SHN_UNDEF) {
1444 name = s1->dynsymtab_section->link->data + esym->st_name;
1445 sym_index = find_elf_sym(symtab_section, name);
1446 if (sym_index) {
1447 /* XXX: avoid adding a symbol if already
1448 present because of -rdynamic ? */
1449 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1450 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1451 sym->st_info, 0,
1452 sym->st_shndx, name);
1453 } else {
1454 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1455 /* weak symbols can stay undefined */
1456 } else {
1457 warning("undefined dynamic symbol '%s'", name);
1462 } else {
1463 int nb_syms;
1464 /* shared library case : we simply export all the global symbols */
1465 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1466 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1467 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1468 sym < sym_end;
1469 sym++) {
1470 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1471 name = symtab_section->link->data + sym->st_name;
1472 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1473 sym->st_info, 0,
1474 sym->st_shndx, name);
1475 s1->symtab_to_dynsym[sym -
1476 (ElfW(Sym) *)symtab_section->data] =
1477 index;
1482 build_got_entries(s1);
1484 /* add a list of needed dlls */
1485 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1486 DLLReference *dllref = s1->loaded_dlls[i];
1487 if (dllref->level == 0)
1488 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1490 /* XXX: currently, since we do not handle PIC code, we
1491 must relocate the readonly segments */
1492 if (file_type == TCC_OUTPUT_DLL) {
1493 if (s1->soname)
1494 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1495 put_dt(dynamic, DT_TEXTREL, 0);
1498 /* add necessary space for other entries */
1499 saved_dynamic_data_offset = dynamic->data_offset;
1500 dynamic->data_offset += sizeof(ElfW(Dyn)) * 9;
1501 } else {
1502 /* still need to build got entries in case of static link */
1503 build_got_entries(s1);
1507 memset(&ehdr, 0, sizeof(ehdr));
1509 /* we add a section for symbols */
1510 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1511 put_elf_str(strsec, "");
1513 /* compute number of sections */
1514 shnum = s1->nb_sections;
1516 /* this array is used to reorder sections in the output file */
1517 section_order = tcc_malloc(sizeof(int) * shnum);
1518 section_order[0] = 0;
1519 sh_order_index = 1;
1521 /* compute number of program headers */
1522 switch(file_type) {
1523 default:
1524 case TCC_OUTPUT_OBJ:
1525 phnum = 0;
1526 break;
1527 case TCC_OUTPUT_EXE:
1528 if (!s1->static_link)
1529 phnum = 4;
1530 else
1531 phnum = 2;
1532 break;
1533 case TCC_OUTPUT_DLL:
1534 phnum = 3;
1535 break;
1538 /* allocate strings for section names and decide if an unallocated
1539 section should be output */
1540 /* NOTE: the strsec section comes last, so its size is also
1541 correct ! */
1542 for(i = 1; i < s1->nb_sections; i++) {
1543 s = s1->sections[i];
1544 s->sh_name = put_elf_str(strsec, s->name);
1545 #if 0 //gr
1546 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1547 s->sh_flags,
1548 s->sh_type,
1549 s->sh_info,
1550 s->name,
1551 s->reloc ? s->reloc->name : "n"
1553 #endif
1554 /* when generating a DLL, we include relocations but we may
1555 patch them */
1556 if (file_type == TCC_OUTPUT_DLL &&
1557 s->sh_type == SHT_RELX &&
1558 !(s->sh_flags & SHF_ALLOC)) {
1559 /* //gr: avoid bogus relocs for empty (debug) sections */
1560 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1561 prepare_dynamic_rel(s1, s);
1562 else if (do_debug)
1563 s->sh_size = s->data_offset;
1564 } else if (do_debug ||
1565 file_type == TCC_OUTPUT_OBJ ||
1566 (s->sh_flags & SHF_ALLOC) ||
1567 i == (s1->nb_sections - 1)) {
1568 /* we output all sections if debug or object file */
1569 s->sh_size = s->data_offset;
1573 /* allocate program segment headers */
1574 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1576 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1577 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1578 } else {
1579 file_offset = 0;
1581 if (phnum > 0) {
1582 /* compute section to program header mapping */
1583 if (s1->has_text_addr) {
1584 int a_offset, p_offset;
1585 addr = s1->text_addr;
1586 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1587 ELF_PAGE_SIZE */
1588 a_offset = addr & (ELF_PAGE_SIZE - 1);
1589 p_offset = file_offset & (ELF_PAGE_SIZE - 1);
1590 if (a_offset < p_offset)
1591 a_offset += ELF_PAGE_SIZE;
1592 file_offset += (a_offset - p_offset);
1593 } else {
1594 if (file_type == TCC_OUTPUT_DLL)
1595 addr = 0;
1596 else
1597 addr = ELF_START_ADDR;
1598 /* compute address after headers */
1599 addr += (file_offset & (ELF_PAGE_SIZE - 1));
1602 /* dynamic relocation table information, for .dynamic section */
1603 rel_size = 0;
1604 rel_addr = 0;
1606 /* leave one program header for the program interpreter */
1607 ph = &phdr[0];
1608 if (interp)
1609 ph++;
1611 for(j = 0; j < 2; j++) {
1612 ph->p_type = PT_LOAD;
1613 if (j == 0)
1614 ph->p_flags = PF_R | PF_X;
1615 else
1616 ph->p_flags = PF_R | PF_W;
1617 ph->p_align = ELF_PAGE_SIZE;
1619 /* we do the following ordering: interp, symbol tables,
1620 relocations, progbits, nobits */
1621 /* XXX: do faster and simpler sorting */
1622 for(k = 0; k < 5; k++) {
1623 for(i = 1; i < s1->nb_sections; i++) {
1624 s = s1->sections[i];
1625 /* compute if section should be included */
1626 if (j == 0) {
1627 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1628 SHF_ALLOC)
1629 continue;
1630 } else {
1631 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1632 (SHF_ALLOC | SHF_WRITE))
1633 continue;
1635 if (s == interp) {
1636 if (k != 0)
1637 continue;
1638 } else if (s->sh_type == SHT_DYNSYM ||
1639 s->sh_type == SHT_STRTAB ||
1640 s->sh_type == SHT_HASH) {
1641 if (k != 1)
1642 continue;
1643 } else if (s->sh_type == SHT_RELX) {
1644 if (k != 2)
1645 continue;
1646 } else if (s->sh_type == SHT_NOBITS) {
1647 if (k != 4)
1648 continue;
1649 } else {
1650 if (k != 3)
1651 continue;
1653 section_order[sh_order_index++] = i;
1655 /* section matches: we align it and add its size */
1656 tmp = addr;
1657 addr = (addr + s->sh_addralign - 1) &
1658 ~(s->sh_addralign - 1);
1659 file_offset += addr - tmp;
1660 s->sh_offset = file_offset;
1661 s->sh_addr = addr;
1663 /* update program header infos */
1664 if (ph->p_offset == 0) {
1665 ph->p_offset = file_offset;
1666 ph->p_vaddr = addr;
1667 ph->p_paddr = ph->p_vaddr;
1669 /* update dynamic relocation infos */
1670 if (s->sh_type == SHT_RELX) {
1671 if (rel_size == 0)
1672 rel_addr = addr;
1673 rel_size += s->sh_size;
1675 addr += s->sh_size;
1676 if (s->sh_type != SHT_NOBITS)
1677 file_offset += s->sh_size;
1680 ph->p_filesz = file_offset - ph->p_offset;
1681 ph->p_memsz = addr - ph->p_vaddr;
1682 ph++;
1683 if (j == 0) {
1684 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1685 /* if in the middle of a page, we duplicate the page in
1686 memory so that one copy is RX and the other is RW */
1687 if ((addr & (ELF_PAGE_SIZE - 1)) != 0)
1688 addr += ELF_PAGE_SIZE;
1689 } else {
1690 addr = (addr + ELF_PAGE_SIZE - 1) & ~(ELF_PAGE_SIZE - 1);
1691 file_offset = (file_offset + ELF_PAGE_SIZE - 1) &
1692 ~(ELF_PAGE_SIZE - 1);
1697 /* if interpreter, then add corresponing program header */
1698 if (interp) {
1699 ph = &phdr[0];
1701 ph->p_type = PT_INTERP;
1702 ph->p_offset = interp->sh_offset;
1703 ph->p_vaddr = interp->sh_addr;
1704 ph->p_paddr = ph->p_vaddr;
1705 ph->p_filesz = interp->sh_size;
1706 ph->p_memsz = interp->sh_size;
1707 ph->p_flags = PF_R;
1708 ph->p_align = interp->sh_addralign;
1711 /* if dynamic section, then add corresponing program header */
1712 if (dynamic) {
1713 ElfW(Sym) *sym_end;
1715 ph = &phdr[phnum - 1];
1717 ph->p_type = PT_DYNAMIC;
1718 ph->p_offset = dynamic->sh_offset;
1719 ph->p_vaddr = dynamic->sh_addr;
1720 ph->p_paddr = ph->p_vaddr;
1721 ph->p_filesz = dynamic->sh_size;
1722 ph->p_memsz = dynamic->sh_size;
1723 ph->p_flags = PF_R | PF_W;
1724 ph->p_align = dynamic->sh_addralign;
1726 /* put GOT dynamic section address */
1727 put32(s1->got->data, dynamic->sh_addr);
1729 /* relocate the PLT */
1730 if (file_type == TCC_OUTPUT_EXE) {
1731 uint8_t *p, *p_end;
1733 p = s1->plt->data;
1734 p_end = p + s1->plt->data_offset;
1735 if (p < p_end) {
1736 #if defined(TCC_TARGET_I386)
1737 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1738 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1739 p += 16;
1740 while (p < p_end) {
1741 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1742 p += 16;
1744 #elif defined(TCC_TARGET_X86_64)
1745 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1746 put32(p + 2, get32(p + 2) + x);
1747 put32(p + 8, get32(p + 8) + x - 6);
1748 p += 16;
1749 while (p < p_end) {
1750 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1751 p += 16;
1753 #elif defined(TCC_TARGET_ARM)
1754 int x;
1755 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1756 p +=16;
1757 while (p < p_end) {
1758 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1759 p += 16;
1761 #elif defined(TCC_TARGET_C67)
1762 /* XXX: TODO */
1763 #else
1764 #error unsupported CPU
1765 #endif
1769 /* relocate symbols in .dynsym */
1770 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
1771 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
1772 sym < sym_end;
1773 sym++) {
1774 if (sym->st_shndx == SHN_UNDEF) {
1775 /* relocate to the PLT if the symbol corresponds
1776 to a PLT entry */
1777 if (sym->st_value)
1778 sym->st_value += s1->plt->sh_addr;
1779 } else if (sym->st_shndx < SHN_LORESERVE) {
1780 /* do symbol relocation */
1781 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
1785 /* put dynamic section entries */
1786 dynamic->data_offset = saved_dynamic_data_offset;
1787 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
1788 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
1789 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
1790 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
1791 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
1792 #ifdef TCC_TARGET_X86_64
1793 put_dt(dynamic, DT_RELA, rel_addr);
1794 put_dt(dynamic, DT_RELASZ, rel_size);
1795 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
1796 #else
1797 put_dt(dynamic, DT_REL, rel_addr);
1798 put_dt(dynamic, DT_RELSZ, rel_size);
1799 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
1800 #endif
1801 if (do_debug)
1802 put_dt(dynamic, DT_DEBUG, 0);
1803 put_dt(dynamic, DT_NULL, 0);
1806 ehdr.e_phentsize = sizeof(ElfW(Phdr));
1807 ehdr.e_phnum = phnum;
1808 ehdr.e_phoff = sizeof(ElfW(Ehdr));
1811 /* all other sections come after */
1812 for(i = 1; i < s1->nb_sections; i++) {
1813 s = s1->sections[i];
1814 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
1815 continue;
1816 section_order[sh_order_index++] = i;
1818 file_offset = (file_offset + s->sh_addralign - 1) &
1819 ~(s->sh_addralign - 1);
1820 s->sh_offset = file_offset;
1821 if (s->sh_type != SHT_NOBITS)
1822 file_offset += s->sh_size;
1825 /* if building executable or DLL, then relocate each section
1826 except the GOT which is already relocated */
1827 if (file_type != TCC_OUTPUT_OBJ) {
1828 relocate_syms(s1, 0);
1830 if (s1->nb_errors != 0) {
1831 fail:
1832 ret = -1;
1833 goto the_end;
1836 /* relocate sections */
1837 /* XXX: ignore sections with allocated relocations ? */
1838 for(i = 1; i < s1->nb_sections; i++) {
1839 s = s1->sections[i];
1840 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
1841 relocate_section(s1, s);
1844 /* relocate relocation entries if the relocation tables are
1845 allocated in the executable */
1846 for(i = 1; i < s1->nb_sections; i++) {
1847 s = s1->sections[i];
1848 if ((s->sh_flags & SHF_ALLOC) &&
1849 s->sh_type == SHT_RELX) {
1850 relocate_rel(s1, s);
1854 /* get entry point address */
1855 if (file_type == TCC_OUTPUT_EXE)
1856 ehdr.e_entry = (unsigned long)tcc_get_symbol_err(s1, "_start");
1857 else
1858 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
1861 /* write elf file */
1862 if (file_type == TCC_OUTPUT_OBJ)
1863 mode = 0666;
1864 else
1865 mode = 0777;
1866 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
1867 if (fd < 0) {
1868 error_noabort("could not write '%s'", filename);
1869 goto fail;
1871 f = fdopen(fd, "wb");
1872 if (verbose)
1873 printf("<- %s\n", filename);
1875 #ifdef TCC_TARGET_COFF
1876 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
1877 tcc_output_coff(s1, f);
1878 } else
1879 #endif
1880 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1881 sort_syms(s1, symtab_section);
1883 /* align to 4 */
1884 file_offset = (file_offset + 3) & -4;
1886 /* fill header */
1887 ehdr.e_ident[0] = ELFMAG0;
1888 ehdr.e_ident[1] = ELFMAG1;
1889 ehdr.e_ident[2] = ELFMAG2;
1890 ehdr.e_ident[3] = ELFMAG3;
1891 ehdr.e_ident[4] = TCC_ELFCLASS;
1892 ehdr.e_ident[5] = ELFDATA2LSB;
1893 ehdr.e_ident[6] = EV_CURRENT;
1894 #ifdef __FreeBSD__
1895 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
1896 #endif
1897 #ifdef TCC_TARGET_ARM
1898 #ifdef TCC_ARM_EABI
1899 ehdr.e_ident[EI_OSABI] = 0;
1900 ehdr.e_flags = 4 << 24;
1901 #else
1902 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
1903 #endif
1904 #endif
1905 switch(file_type) {
1906 default:
1907 case TCC_OUTPUT_EXE:
1908 ehdr.e_type = ET_EXEC;
1909 break;
1910 case TCC_OUTPUT_DLL:
1911 ehdr.e_type = ET_DYN;
1912 break;
1913 case TCC_OUTPUT_OBJ:
1914 ehdr.e_type = ET_REL;
1915 break;
1917 ehdr.e_machine = EM_TCC_TARGET;
1918 ehdr.e_version = EV_CURRENT;
1919 ehdr.e_shoff = file_offset;
1920 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
1921 ehdr.e_shentsize = sizeof(ElfW(Shdr));
1922 ehdr.e_shnum = shnum;
1923 ehdr.e_shstrndx = shnum - 1;
1925 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
1926 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
1927 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1929 for(i=1;i<s1->nb_sections;i++) {
1930 s = s1->sections[section_order[i]];
1931 if (s->sh_type != SHT_NOBITS) {
1932 while (offset < s->sh_offset) {
1933 fputc(0, f);
1934 offset++;
1936 size = s->sh_size;
1937 fwrite(s->data, 1, size, f);
1938 offset += size;
1942 /* output section headers */
1943 while (offset < ehdr.e_shoff) {
1944 fputc(0, f);
1945 offset++;
1948 for(i=0;i<s1->nb_sections;i++) {
1949 sh = &shdr;
1950 memset(sh, 0, sizeof(ElfW(Shdr)));
1951 s = s1->sections[i];
1952 if (s) {
1953 sh->sh_name = s->sh_name;
1954 sh->sh_type = s->sh_type;
1955 sh->sh_flags = s->sh_flags;
1956 sh->sh_entsize = s->sh_entsize;
1957 sh->sh_info = s->sh_info;
1958 if (s->link)
1959 sh->sh_link = s->link->sh_num;
1960 sh->sh_addralign = s->sh_addralign;
1961 sh->sh_addr = s->sh_addr;
1962 sh->sh_offset = s->sh_offset;
1963 sh->sh_size = s->sh_size;
1965 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
1967 } else {
1968 tcc_output_binary(s1, f, section_order);
1970 fclose(f);
1972 ret = 0;
1973 the_end:
1974 tcc_free(s1->symtab_to_dynsym);
1975 tcc_free(section_order);
1976 tcc_free(phdr);
1977 tcc_free(s1->got_offsets);
1978 return ret;
1981 int tcc_output_file(TCCState *s, const char *filename)
1983 int ret;
1984 #ifdef TCC_TARGET_PE
1985 if (s->output_type != TCC_OUTPUT_OBJ) {
1986 ret = pe_output_file(s, filename);
1987 } else
1988 #endif
1990 ret = elf_output_file(s, filename);
1992 return ret;
1995 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
1997 void *data;
1999 data = tcc_malloc(size);
2000 lseek(fd, file_offset, SEEK_SET);
2001 read(fd, data, size);
2002 return data;
2005 typedef struct SectionMergeInfo {
2006 Section *s; /* corresponding existing section */
2007 unsigned long offset; /* offset of the new section in the existing section */
2008 uint8_t new_section; /* true if section 's' was added */
2009 uint8_t link_once; /* true if link once section */
2010 } SectionMergeInfo;
2012 /* load an object file and merge it with current files */
2013 /* XXX: handle correctly stab (debug) info */
2014 static int tcc_load_object_file(TCCState *s1,
2015 int fd, unsigned long file_offset)
2017 ElfW(Ehdr) ehdr;
2018 ElfW(Shdr) *shdr, *sh;
2019 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2020 unsigned char *strsec, *strtab;
2021 int *old_to_new_syms;
2022 char *sh_name, *name;
2023 SectionMergeInfo *sm_table, *sm;
2024 ElfW(Sym) *sym, *symtab;
2025 ElfW_Rel *rel, *rel_end;
2026 Section *s;
2028 int stab_index;
2029 int stabstr_index;
2031 stab_index = stabstr_index = 0;
2033 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2034 goto fail1;
2035 if (ehdr.e_ident[0] != ELFMAG0 ||
2036 ehdr.e_ident[1] != ELFMAG1 ||
2037 ehdr.e_ident[2] != ELFMAG2 ||
2038 ehdr.e_ident[3] != ELFMAG3)
2039 goto fail1;
2040 /* test if object file */
2041 if (ehdr.e_type != ET_REL)
2042 goto fail1;
2043 /* test CPU specific stuff */
2044 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2045 ehdr.e_machine != EM_TCC_TARGET) {
2046 fail1:
2047 error_noabort("invalid object file");
2048 return -1;
2050 /* read sections */
2051 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2052 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2053 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2055 /* load section names */
2056 sh = &shdr[ehdr.e_shstrndx];
2057 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2059 /* load symtab and strtab */
2060 old_to_new_syms = NULL;
2061 symtab = NULL;
2062 strtab = NULL;
2063 nb_syms = 0;
2064 for(i = 1; i < ehdr.e_shnum; i++) {
2065 sh = &shdr[i];
2066 if (sh->sh_type == SHT_SYMTAB) {
2067 if (symtab) {
2068 error_noabort("object must contain only one symtab");
2069 fail:
2070 ret = -1;
2071 goto the_end;
2073 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2074 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2075 sm_table[i].s = symtab_section;
2077 /* now load strtab */
2078 sh = &shdr[sh->sh_link];
2079 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2083 /* now examine each section and try to merge its content with the
2084 ones in memory */
2085 for(i = 1; i < ehdr.e_shnum; i++) {
2086 /* no need to examine section name strtab */
2087 if (i == ehdr.e_shstrndx)
2088 continue;
2089 sh = &shdr[i];
2090 sh_name = strsec + sh->sh_name;
2091 /* ignore sections types we do not handle */
2092 if (sh->sh_type != SHT_PROGBITS &&
2093 sh->sh_type != SHT_RELX &&
2094 #ifdef TCC_ARM_EABI
2095 sh->sh_type != SHT_ARM_EXIDX &&
2096 #endif
2097 sh->sh_type != SHT_NOBITS &&
2098 strcmp(sh_name, ".stabstr")
2100 continue;
2101 if (sh->sh_addralign < 1)
2102 sh->sh_addralign = 1;
2103 /* find corresponding section, if any */
2104 for(j = 1; j < s1->nb_sections;j++) {
2105 s = s1->sections[j];
2106 if (!strcmp(s->name, sh_name)) {
2107 if (!strncmp(sh_name, ".gnu.linkonce",
2108 sizeof(".gnu.linkonce") - 1)) {
2109 /* if a 'linkonce' section is already present, we
2110 do not add it again. It is a little tricky as
2111 symbols can still be defined in
2112 it. */
2113 sm_table[i].link_once = 1;
2114 goto next;
2115 } else {
2116 goto found;
2120 /* not found: create new section */
2121 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2122 /* take as much info as possible from the section. sh_link and
2123 sh_info will be updated later */
2124 s->sh_addralign = sh->sh_addralign;
2125 s->sh_entsize = sh->sh_entsize;
2126 sm_table[i].new_section = 1;
2127 found:
2128 if (sh->sh_type != s->sh_type) {
2129 error_noabort("invalid section type");
2130 goto fail;
2133 /* align start of section */
2134 offset = s->data_offset;
2136 if (0 == strcmp(sh_name, ".stab")) {
2137 stab_index = i;
2138 goto no_align;
2140 if (0 == strcmp(sh_name, ".stabstr")) {
2141 stabstr_index = i;
2142 goto no_align;
2145 size = sh->sh_addralign - 1;
2146 offset = (offset + size) & ~size;
2147 if (sh->sh_addralign > s->sh_addralign)
2148 s->sh_addralign = sh->sh_addralign;
2149 s->data_offset = offset;
2150 no_align:
2151 sm_table[i].offset = offset;
2152 sm_table[i].s = s;
2153 /* concatenate sections */
2154 size = sh->sh_size;
2155 if (sh->sh_type != SHT_NOBITS) {
2156 unsigned char *ptr;
2157 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2158 ptr = section_ptr_add(s, size);
2159 read(fd, ptr, size);
2160 } else {
2161 s->data_offset += size;
2163 next: ;
2166 /* //gr relocate stab strings */
2167 if (stab_index && stabstr_index) {
2168 Stab_Sym *a, *b;
2169 unsigned o;
2170 s = sm_table[stab_index].s;
2171 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2172 b = (Stab_Sym *)(s->data + s->data_offset);
2173 o = sm_table[stabstr_index].offset;
2174 while (a < b)
2175 a->n_strx += o, a++;
2178 /* second short pass to update sh_link and sh_info fields of new
2179 sections */
2180 for(i = 1; i < ehdr.e_shnum; i++) {
2181 s = sm_table[i].s;
2182 if (!s || !sm_table[i].new_section)
2183 continue;
2184 sh = &shdr[i];
2185 if (sh->sh_link > 0)
2186 s->link = sm_table[sh->sh_link].s;
2187 if (sh->sh_type == SHT_RELX) {
2188 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2189 /* update backward link */
2190 s1->sections[s->sh_info]->reloc = s;
2193 sm = sm_table;
2195 /* resolve symbols */
2196 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2198 sym = symtab + 1;
2199 for(i = 1; i < nb_syms; i++, sym++) {
2200 if (sym->st_shndx != SHN_UNDEF &&
2201 sym->st_shndx < SHN_LORESERVE) {
2202 sm = &sm_table[sym->st_shndx];
2203 if (sm->link_once) {
2204 /* if a symbol is in a link once section, we use the
2205 already defined symbol. It is very important to get
2206 correct relocations */
2207 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2208 name = strtab + sym->st_name;
2209 sym_index = find_elf_sym(symtab_section, name);
2210 if (sym_index)
2211 old_to_new_syms[i] = sym_index;
2213 continue;
2215 /* if no corresponding section added, no need to add symbol */
2216 if (!sm->s)
2217 continue;
2218 /* convert section number */
2219 sym->st_shndx = sm->s->sh_num;
2220 /* offset value */
2221 sym->st_value += sm->offset;
2223 /* add symbol */
2224 name = strtab + sym->st_name;
2225 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2226 sym->st_info, sym->st_other,
2227 sym->st_shndx, name);
2228 old_to_new_syms[i] = sym_index;
2231 /* third pass to patch relocation entries */
2232 for(i = 1; i < ehdr.e_shnum; i++) {
2233 s = sm_table[i].s;
2234 if (!s)
2235 continue;
2236 sh = &shdr[i];
2237 offset = sm_table[i].offset;
2238 switch(s->sh_type) {
2239 case SHT_RELX:
2240 /* take relocation offset information */
2241 offseti = sm_table[sh->sh_info].offset;
2242 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2243 for(rel = (ElfW_Rel *)(s->data + offset);
2244 rel < rel_end;
2245 rel++) {
2246 int type;
2247 unsigned sym_index;
2248 /* convert symbol index */
2249 type = ELFW(R_TYPE)(rel->r_info);
2250 sym_index = ELFW(R_SYM)(rel->r_info);
2251 /* NOTE: only one symtab assumed */
2252 if (sym_index >= nb_syms)
2253 goto invalid_reloc;
2254 sym_index = old_to_new_syms[sym_index];
2255 /* ignore link_once in rel section. */
2256 if (!sym_index && !sm->link_once) {
2257 invalid_reloc:
2258 error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2259 i, strsec + sh->sh_name, rel->r_offset);
2260 goto fail;
2262 rel->r_info = ELFW(R_INFO)(sym_index, type);
2263 /* offset the relocation offset */
2264 rel->r_offset += offseti;
2266 break;
2267 default:
2268 break;
2272 ret = 0;
2273 the_end:
2274 tcc_free(symtab);
2275 tcc_free(strtab);
2276 tcc_free(old_to_new_syms);
2277 tcc_free(sm_table);
2278 tcc_free(strsec);
2279 tcc_free(shdr);
2280 return ret;
2283 #define ARMAG "!<arch>\012" /* For COFF and a.out archives */
2285 typedef struct ArchiveHeader {
2286 char ar_name[16]; /* name of this member */
2287 char ar_date[12]; /* file mtime */
2288 char ar_uid[6]; /* owner uid; printed as decimal */
2289 char ar_gid[6]; /* owner gid; printed as decimal */
2290 char ar_mode[8]; /* file mode, printed as octal */
2291 char ar_size[10]; /* file size, printed as decimal */
2292 char ar_fmag[2]; /* should contain ARFMAG */
2293 } ArchiveHeader;
2295 static int get_be32(const uint8_t *b)
2297 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2300 /* load only the objects which resolve undefined symbols */
2301 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2303 int i, bound, nsyms, sym_index, off, ret;
2304 uint8_t *data;
2305 const char *ar_names, *p;
2306 const uint8_t *ar_index;
2307 ElfW(Sym) *sym;
2309 data = tcc_malloc(size);
2310 if (read(fd, data, size) != size)
2311 goto fail;
2312 nsyms = get_be32(data);
2313 ar_index = data + 4;
2314 ar_names = ar_index + nsyms * 4;
2316 do {
2317 bound = 0;
2318 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2319 sym_index = find_elf_sym(symtab_section, p);
2320 if(sym_index) {
2321 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2322 if(sym->st_shndx == SHN_UNDEF) {
2323 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2324 #if 0
2325 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2326 #endif
2327 ++bound;
2328 lseek(fd, off, SEEK_SET);
2329 if(tcc_load_object_file(s1, fd, off) < 0) {
2330 fail:
2331 ret = -1;
2332 goto the_end;
2337 } while(bound);
2338 ret = 0;
2339 the_end:
2340 tcc_free(data);
2341 return ret;
2344 /* load a '.a' file */
2345 static int tcc_load_archive(TCCState *s1, int fd)
2347 ArchiveHeader hdr;
2348 char ar_size[11];
2349 char ar_name[17];
2350 char magic[8];
2351 int size, len, i;
2352 unsigned long file_offset;
2354 /* skip magic which was already checked */
2355 read(fd, magic, sizeof(magic));
2357 for(;;) {
2358 len = read(fd, &hdr, sizeof(hdr));
2359 if (len == 0)
2360 break;
2361 if (len != sizeof(hdr)) {
2362 error_noabort("invalid archive");
2363 return -1;
2365 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2366 ar_size[sizeof(hdr.ar_size)] = '\0';
2367 size = strtol(ar_size, NULL, 0);
2368 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2369 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2370 if (ar_name[i] != ' ')
2371 break;
2373 ar_name[i + 1] = '\0';
2374 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2375 file_offset = lseek(fd, 0, SEEK_CUR);
2376 /* align to even */
2377 size = (size + 1) & ~1;
2378 if (!strcmp(ar_name, "/")) {
2379 /* coff symbol table : we handle it */
2380 if(s1->alacarte_link)
2381 return tcc_load_alacarte(s1, fd, size);
2382 } else if (!strcmp(ar_name, "//") ||
2383 !strcmp(ar_name, "__.SYMDEF") ||
2384 !strcmp(ar_name, "__.SYMDEF/") ||
2385 !strcmp(ar_name, "ARFILENAMES/")) {
2386 /* skip symbol table or archive names */
2387 } else {
2388 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2389 return -1;
2391 lseek(fd, file_offset + size, SEEK_SET);
2393 return 0;
2396 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2397 is referenced by the user (so it should be added as DT_NEEDED in
2398 the generated ELF file) */
2399 static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2401 ElfW(Ehdr) ehdr;
2402 ElfW(Shdr) *shdr, *sh, *sh1;
2403 int i, j, nb_syms, nb_dts, sym_bind, ret;
2404 ElfW(Sym) *sym, *dynsym;
2405 ElfW(Dyn) *dt, *dynamic;
2406 unsigned char *dynstr;
2407 const char *name, *soname;
2408 DLLReference *dllref;
2410 read(fd, &ehdr, sizeof(ehdr));
2412 /* test CPU specific stuff */
2413 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2414 ehdr.e_machine != EM_TCC_TARGET) {
2415 error_noabort("bad architecture");
2416 return -1;
2419 /* read sections */
2420 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2422 /* load dynamic section and dynamic symbols */
2423 nb_syms = 0;
2424 nb_dts = 0;
2425 dynamic = NULL;
2426 dynsym = NULL; /* avoid warning */
2427 dynstr = NULL; /* avoid warning */
2428 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2429 switch(sh->sh_type) {
2430 case SHT_DYNAMIC:
2431 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2432 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2433 break;
2434 case SHT_DYNSYM:
2435 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2436 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2437 sh1 = &shdr[sh->sh_link];
2438 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2439 break;
2440 default:
2441 break;
2445 /* compute the real library name */
2446 soname = tcc_basename(filename);
2448 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2449 if (dt->d_tag == DT_SONAME) {
2450 soname = dynstr + dt->d_un.d_val;
2454 /* if the dll is already loaded, do not load it */
2455 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2456 dllref = s1->loaded_dlls[i];
2457 if (!strcmp(soname, dllref->name)) {
2458 /* but update level if needed */
2459 if (level < dllref->level)
2460 dllref->level = level;
2461 ret = 0;
2462 goto the_end;
2466 // printf("loading dll '%s'\n", soname);
2468 /* add the dll and its level */
2469 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2470 dllref->level = level;
2471 strcpy(dllref->name, soname);
2472 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2474 /* add dynamic symbols in dynsym_section */
2475 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2476 sym_bind = ELFW(ST_BIND)(sym->st_info);
2477 if (sym_bind == STB_LOCAL)
2478 continue;
2479 name = dynstr + sym->st_name;
2480 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2481 sym->st_info, sym->st_other, sym->st_shndx, name);
2484 /* load all referenced DLLs */
2485 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2486 switch(dt->d_tag) {
2487 case DT_NEEDED:
2488 name = dynstr + dt->d_un.d_val;
2489 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2490 dllref = s1->loaded_dlls[j];
2491 if (!strcmp(name, dllref->name))
2492 goto already_loaded;
2494 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2495 error_noabort("referenced dll '%s' not found", name);
2496 ret = -1;
2497 goto the_end;
2499 already_loaded:
2500 break;
2503 ret = 0;
2504 the_end:
2505 tcc_free(dynstr);
2506 tcc_free(dynsym);
2507 tcc_free(dynamic);
2508 tcc_free(shdr);
2509 return ret;
2512 #define LD_TOK_NAME 256
2513 #define LD_TOK_EOF (-1)
2515 /* return next ld script token */
2516 static int ld_next(TCCState *s1, char *name, int name_size)
2518 int c;
2519 char *q;
2521 redo:
2522 switch(ch) {
2523 case ' ':
2524 case '\t':
2525 case '\f':
2526 case '\v':
2527 case '\r':
2528 case '\n':
2529 inp();
2530 goto redo;
2531 case '/':
2532 minp();
2533 if (ch == '*') {
2534 file->buf_ptr = parse_comment(file->buf_ptr);
2535 ch = file->buf_ptr[0];
2536 goto redo;
2537 } else {
2538 q = name;
2539 *q++ = '/';
2540 goto parse_name;
2542 break;
2543 /* case 'a' ... 'z': */
2544 case 'a':
2545 case 'b':
2546 case 'c':
2547 case 'd':
2548 case 'e':
2549 case 'f':
2550 case 'g':
2551 case 'h':
2552 case 'i':
2553 case 'j':
2554 case 'k':
2555 case 'l':
2556 case 'm':
2557 case 'n':
2558 case 'o':
2559 case 'p':
2560 case 'q':
2561 case 'r':
2562 case 's':
2563 case 't':
2564 case 'u':
2565 case 'v':
2566 case 'w':
2567 case 'x':
2568 case 'y':
2569 case 'z':
2570 /* case 'A' ... 'z': */
2571 case 'A':
2572 case 'B':
2573 case 'C':
2574 case 'D':
2575 case 'E':
2576 case 'F':
2577 case 'G':
2578 case 'H':
2579 case 'I':
2580 case 'J':
2581 case 'K':
2582 case 'L':
2583 case 'M':
2584 case 'N':
2585 case 'O':
2586 case 'P':
2587 case 'Q':
2588 case 'R':
2589 case 'S':
2590 case 'T':
2591 case 'U':
2592 case 'V':
2593 case 'W':
2594 case 'X':
2595 case 'Y':
2596 case 'Z':
2597 case '_':
2598 case '\\':
2599 case '.':
2600 case '$':
2601 case '~':
2602 q = name;
2603 parse_name:
2604 for(;;) {
2605 if (!((ch >= 'a' && ch <= 'z') ||
2606 (ch >= 'A' && ch <= 'Z') ||
2607 (ch >= '0' && ch <= '9') ||
2608 strchr("/.-_+=$:\\,~", ch)))
2609 break;
2610 if ((q - name) < name_size - 1) {
2611 *q++ = ch;
2613 minp();
2615 *q = '\0';
2616 c = LD_TOK_NAME;
2617 break;
2618 case CH_EOF:
2619 c = LD_TOK_EOF;
2620 break;
2621 default:
2622 c = ch;
2623 inp();
2624 break;
2626 #if 0
2627 printf("tok=%c %d\n", c, c);
2628 if (c == LD_TOK_NAME)
2629 printf(" name=%s\n", name);
2630 #endif
2631 return c;
2634 static int ld_add_file_list(TCCState *s1, int as_needed)
2636 char filename[1024];
2637 int t, ret;
2639 t = ld_next(s1, filename, sizeof(filename));
2640 if (t != '(')
2641 expect("(");
2642 t = ld_next(s1, filename, sizeof(filename));
2643 for(;;) {
2644 if (t == LD_TOK_EOF) {
2645 error_noabort("unexpected end of file");
2646 return -1;
2647 } else if (t == ')') {
2648 break;
2649 } else if (t != LD_TOK_NAME) {
2650 error_noabort("filename expected");
2651 return -1;
2653 if (!strcmp(filename, "AS_NEEDED")) {
2654 ret = ld_add_file_list(s1, 1);
2655 if (ret)
2656 return ret;
2657 } else {
2658 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2659 if (!as_needed)
2660 tcc_add_file(s1, filename);
2662 t = ld_next(s1, filename, sizeof(filename));
2663 if (t == ',') {
2664 t = ld_next(s1, filename, sizeof(filename));
2667 return 0;
2670 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
2671 files */
2672 static int tcc_load_ldscript(TCCState *s1)
2674 char cmd[64];
2675 char filename[1024];
2676 int t, ret;
2678 ch = file->buf_ptr[0];
2679 ch = handle_eob();
2680 for(;;) {
2681 t = ld_next(s1, cmd, sizeof(cmd));
2682 if (t == LD_TOK_EOF)
2683 return 0;
2684 else if (t != LD_TOK_NAME)
2685 return -1;
2686 if (!strcmp(cmd, "INPUT") ||
2687 !strcmp(cmd, "GROUP")) {
2688 ret = ld_add_file_list(s1, 0);
2689 if (ret)
2690 return ret;
2691 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
2692 !strcmp(cmd, "TARGET")) {
2693 /* ignore some commands */
2694 t = ld_next(s1, cmd, sizeof(cmd));
2695 if (t != '(')
2696 expect("(");
2697 for(;;) {
2698 t = ld_next(s1, filename, sizeof(filename));
2699 if (t == LD_TOK_EOF) {
2700 error_noabort("unexpected end of file");
2701 return -1;
2702 } else if (t == ')') {
2703 break;
2706 } else {
2707 return -1;
2710 return 0;