Add support of x86-64.
[tinycc.git] / tccelf.c
bloba0c23808d6c8c5bbb1cc65cac43a00c3fd9dc7cd
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 #if defined(TCC_TARGET_I386)
512 int esym_index;
513 #endif
515 sr = s->reloc;
516 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
517 qrel = (ElfW_Rel *)sr->data;
518 for(rel = qrel;
519 rel < rel_end;
520 rel++) {
521 ptr = s->data + rel->r_offset;
523 sym_index = ELFW(R_SYM)(rel->r_info);
524 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
525 val = sym->st_value;
526 #ifdef TCC_TARGET_X86_64
527 /* XXX: not tested */
528 val += rel->r_addend;
529 #endif
530 type = ELFW(R_TYPE)(rel->r_info);
531 addr = s->sh_addr + rel->r_offset;
533 /* CPU specific */
534 switch(type) {
535 #if defined(TCC_TARGET_I386)
536 case R_386_32:
537 if (s1->output_type == TCC_OUTPUT_DLL) {
538 esym_index = s1->symtab_to_dynsym[sym_index];
539 qrel->r_offset = rel->r_offset;
540 if (esym_index) {
541 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
542 qrel++;
543 break;
544 } else {
545 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
546 qrel++;
549 *(int *)ptr += val;
550 break;
551 case R_386_PC32:
552 if (s1->output_type == TCC_OUTPUT_DLL) {
553 /* DLL relocation */
554 esym_index = s1->symtab_to_dynsym[sym_index];
555 if (esym_index) {
556 qrel->r_offset = rel->r_offset;
557 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
558 qrel++;
559 break;
562 *(int *)ptr += val - addr;
563 break;
564 case R_386_PLT32:
565 *(int *)ptr += val - addr;
566 break;
567 case R_386_GLOB_DAT:
568 case R_386_JMP_SLOT:
569 *(int *)ptr = val;
570 break;
571 case R_386_GOTPC:
572 *(int *)ptr += s1->got->sh_addr - addr;
573 break;
574 case R_386_GOTOFF:
575 *(int *)ptr += val - s1->got->sh_addr;
576 break;
577 case R_386_GOT32:
578 /* we load the got offset */
579 *(int *)ptr += s1->got_offsets[sym_index];
580 break;
581 #elif defined(TCC_TARGET_ARM)
582 case R_ARM_PC24:
583 case R_ARM_CALL:
584 case R_ARM_JUMP24:
585 case R_ARM_PLT32:
587 int x;
588 x = (*(int *)ptr)&0xffffff;
589 (*(int *)ptr) &= 0xff000000;
590 if (x & 0x800000)
591 x -= 0x1000000;
592 x *= 4;
593 x += val - addr;
594 if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
595 error("can't relocate value at %x",addr);
596 x >>= 2;
597 x &= 0xffffff;
598 (*(int *)ptr) |= x;
600 break;
601 case R_ARM_PREL31:
603 int x;
604 x = (*(int *)ptr) & 0x7fffffff;
605 (*(int *)ptr) &= 0x80000000;
606 x = (x * 2) / 2;
607 x += val - addr;
608 if((x^(x>>1))&0x40000000)
609 error("can't relocate value at %x",addr);
610 (*(int *)ptr) |= x & 0x7fffffff;
612 case R_ARM_ABS32:
613 *(int *)ptr += val;
614 break;
615 case R_ARM_BASE_PREL:
616 *(int *)ptr += s1->got->sh_addr - addr;
617 break;
618 case R_ARM_GOTOFF32:
619 *(int *)ptr += val - s1->got->sh_addr;
620 break;
621 case R_ARM_GOT_BREL:
622 /* we load the got offset */
623 *(int *)ptr += s1->got_offsets[sym_index];
624 break;
625 case R_ARM_COPY:
626 break;
627 default:
628 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
629 type,addr,(unsigned int )ptr,val);
630 break;
631 #elif defined(TCC_TARGET_C67)
632 case R_C60_32:
633 *(int *)ptr += val;
634 break;
635 case R_C60LO16:
637 uint32_t orig;
639 /* put the low 16 bits of the absolute address */
640 // add to what is already there
642 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
643 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
645 //patch both at once - assumes always in pairs Low - High
647 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
648 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
650 break;
651 case R_C60HI16:
652 break;
653 default:
654 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
655 type,addr,(unsigned int )ptr,val);
656 break;
657 #elif defined(TCC_TARGET_X86_64)
658 case R_X86_64_64:
659 *(long long *)ptr += val;
660 break;
661 case R_X86_64_32:
662 case R_X86_64_32S:
663 *(int *)ptr += val;
664 break;
665 case R_X86_64_PC32: {
666 long diff = val - addr;
667 if (diff < -2147483648 || diff > 2147483647) {
668 /* XXX: naive support for over 32bit jump */
669 if (s1->output_type == TCC_OUTPUT_MEMORY) {
670 val = add_jmp_table(s1, val);
671 diff = val - addr;
673 if (diff <= -2147483647 || diff > 2147483647) {
674 #if 0
675 /* output memory map to debug easily */
676 FILE* fp;
677 char buf[4096];
678 int size;
679 Dl_info di;
680 printf("%ld - %ld = %ld\n", val, addr, diff);
681 dladdr((void *)addr, &di);
682 printf("addr = %lx = %lx+%lx(%s) ptr=%p\n",
683 addr, s->sh_addr, rel->r_offset, di.dli_sname,
684 ptr);
685 fp = fopen("/proc/self/maps", "r");
686 size = fread(buf, 1, 4095, fp);
687 buf[size] = '\0';
688 printf("%s", buf);
689 #endif
690 error("internal error: relocation failed");
693 *(int *)ptr += val - addr;
695 break;
696 case R_X86_64_PLT32:
697 *(int *)ptr += val - addr;
698 break;
699 case R_X86_64_GLOB_DAT:
700 case R_X86_64_JUMP_SLOT:
701 *(int *)ptr = val;
702 break;
703 case R_X86_64_GOTPCREL:
704 *(int *)ptr += s1->got->sh_addr - addr;
705 break;
706 case R_X86_64_GOTTPOFF:
707 *(int *)ptr += val - s1->got->sh_addr;
708 break;
709 case R_X86_64_GOT32:
710 /* we load the got offset */
711 *(int *)ptr += s1->got_offsets[sym_index];
712 break;
713 #else
714 #error unsupported processor
715 #endif
718 /* if the relocation is allocated, we change its symbol table */
719 if (sr->sh_flags & SHF_ALLOC)
720 sr->link = s1->dynsym;
723 /* relocate relocation table in 'sr' */
724 static void relocate_rel(TCCState *s1, Section *sr)
726 Section *s;
727 ElfW_Rel *rel, *rel_end;
729 s = s1->sections[sr->sh_info];
730 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
731 for(rel = (ElfW_Rel *)sr->data;
732 rel < rel_end;
733 rel++) {
734 rel->r_offset += s->sh_addr;
738 /* count the number of dynamic relocations so that we can reserve
739 their space */
740 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
742 ElfW_Rel *rel, *rel_end;
743 int sym_index, esym_index, type, count;
745 count = 0;
746 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
747 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
748 sym_index = ELFW(R_SYM)(rel->r_info);
749 type = ELFW(R_TYPE)(rel->r_info);
750 switch(type) {
751 case R_386_32:
752 count++;
753 break;
754 case R_386_PC32:
755 esym_index = s1->symtab_to_dynsym[sym_index];
756 if (esym_index)
757 count++;
758 break;
759 default:
760 break;
763 if (count) {
764 /* allocate the section */
765 sr->sh_flags |= SHF_ALLOC;
766 sr->sh_size = count * sizeof(ElfW_Rel);
768 return count;
771 static void put_got_offset(TCCState *s1, int index, unsigned long val)
773 int n;
774 unsigned long *tab;
776 if (index >= s1->nb_got_offsets) {
777 /* find immediately bigger power of 2 and reallocate array */
778 n = 1;
779 while (index >= n)
780 n *= 2;
781 tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
782 if (!tab)
783 error("memory full");
784 s1->got_offsets = tab;
785 memset(s1->got_offsets + s1->nb_got_offsets, 0,
786 (n - s1->nb_got_offsets) * sizeof(unsigned long));
787 s1->nb_got_offsets = n;
789 s1->got_offsets[index] = val;
792 /* XXX: suppress that */
793 static void put32(unsigned char *p, uint32_t val)
795 p[0] = val;
796 p[1] = val >> 8;
797 p[2] = val >> 16;
798 p[3] = val >> 24;
801 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
802 defined(TCC_TARGET_X86_64)
803 static uint32_t get32(unsigned char *p)
805 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
807 #endif
809 static void build_got(TCCState *s1)
811 unsigned char *ptr;
813 /* if no got, then create it */
814 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
815 s1->got->sh_entsize = 4;
816 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
817 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
818 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
819 #if PTR_SIZE == 4
820 /* keep space for _DYNAMIC pointer, if present */
821 put32(ptr, 0);
822 /* two dummy got entries */
823 put32(ptr + 4, 0);
824 put32(ptr + 8, 0);
825 #else
826 /* keep space for _DYNAMIC pointer, if present */
827 put32(ptr, 0);
828 put32(ptr + 4, 0);
829 /* two dummy got entries */
830 put32(ptr + 8, 0);
831 put32(ptr + 12, 0);
832 put32(ptr + 16, 0);
833 put32(ptr + 20, 0);
834 #endif
837 /* put a got entry corresponding to a symbol in symtab_section. 'size'
838 and 'info' can be modifed if more precise info comes from the DLL */
839 static void put_got_entry(TCCState *s1,
840 int reloc_type, unsigned long size, int info,
841 int sym_index)
843 int index;
844 const char *name;
845 ElfW(Sym) *sym;
846 unsigned long offset;
847 int *ptr;
849 if (!s1->got)
850 build_got(s1);
852 /* if a got entry already exists for that symbol, no need to add one */
853 if (sym_index < s1->nb_got_offsets &&
854 s1->got_offsets[sym_index] != 0)
855 return;
857 put_got_offset(s1, sym_index, s1->got->data_offset);
859 if (s1->dynsym) {
860 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
861 name = symtab_section->link->data + sym->st_name;
862 offset = sym->st_value;
863 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
864 if (reloc_type ==
865 #ifdef TCC_TARGET_X86_64
866 R_X86_64_JUMP_SLOT
867 #else
868 R_386_JMP_SLOT
869 #endif
871 Section *plt;
872 uint8_t *p;
873 int modrm;
875 /* if we build a DLL, we add a %ebx offset */
876 if (s1->output_type == TCC_OUTPUT_DLL)
877 modrm = 0xa3;
878 else
879 modrm = 0x25;
881 /* add a PLT entry */
882 plt = s1->plt;
883 if (plt->data_offset == 0) {
884 /* first plt entry */
885 p = section_ptr_add(plt, 16);
886 p[0] = 0xff; /* pushl got + PTR_SIZE */
887 p[1] = modrm + 0x10;
888 put32(p + 2, PTR_SIZE);
889 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
890 p[7] = modrm;
891 put32(p + 8, PTR_SIZE * 2);
894 p = section_ptr_add(plt, 16);
895 p[0] = 0xff; /* jmp *(got + x) */
896 p[1] = modrm;
897 put32(p + 2, s1->got->data_offset);
898 p[6] = 0x68; /* push $xxx */
899 put32(p + 7, (plt->data_offset - 32) >> 1);
900 p[11] = 0xe9; /* jmp plt_start */
901 put32(p + 12, -(plt->data_offset));
903 /* the symbol is modified so that it will be relocated to
904 the PLT */
905 if (s1->output_type == TCC_OUTPUT_EXE)
906 offset = plt->data_offset - 16;
908 #elif defined(TCC_TARGET_ARM)
909 if (reloc_type == R_ARM_JUMP_SLOT) {
910 Section *plt;
911 uint8_t *p;
913 /* if we build a DLL, we add a %ebx offset */
914 if (s1->output_type == TCC_OUTPUT_DLL)
915 error("DLLs unimplemented!");
917 /* add a PLT entry */
918 plt = s1->plt;
919 if (plt->data_offset == 0) {
920 /* first plt entry */
921 p = section_ptr_add(plt, 16);
922 put32(p , 0xe52de004);
923 put32(p + 4, 0xe59fe010);
924 put32(p + 8, 0xe08fe00e);
925 put32(p + 12, 0xe5bef008);
928 p = section_ptr_add(plt, 16);
929 put32(p , 0xe59fc004);
930 put32(p+4, 0xe08fc00c);
931 put32(p+8, 0xe59cf000);
932 put32(p+12, s1->got->data_offset);
934 /* the symbol is modified so that it will be relocated to
935 the PLT */
936 if (s1->output_type == TCC_OUTPUT_EXE)
937 offset = plt->data_offset - 16;
939 #elif defined(TCC_TARGET_C67)
940 error("C67 got not implemented");
941 #else
942 #error unsupported CPU
943 #endif
944 index = put_elf_sym(s1->dynsym, offset,
945 size, info, 0, sym->st_shndx, name);
946 /* put a got entry */
947 put_elf_reloc(s1->dynsym, s1->got,
948 s1->got->data_offset,
949 reloc_type, index);
951 ptr = section_ptr_add(s1->got, PTR_SIZE);
952 *ptr = 0;
955 /* build GOT and PLT entries */
956 static void build_got_entries(TCCState *s1)
958 Section *s, *symtab;
959 ElfW_Rel *rel, *rel_end;
960 ElfW(Sym) *sym;
961 int i, type, reloc_type, sym_index;
963 for(i = 1; i < s1->nb_sections; i++) {
964 s = s1->sections[i];
965 if (s->sh_type != SHT_RELX)
966 continue;
967 /* no need to handle got relocations */
968 if (s->link != symtab_section)
969 continue;
970 symtab = s->link;
971 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
972 for(rel = (ElfW_Rel *)s->data;
973 rel < rel_end;
974 rel++) {
975 type = ELFW(R_TYPE)(rel->r_info);
976 switch(type) {
977 #if defined(TCC_TARGET_I386)
978 case R_386_GOT32:
979 case R_386_GOTOFF:
980 case R_386_GOTPC:
981 case R_386_PLT32:
982 if (!s1->got)
983 build_got(s1);
984 if (type == R_386_GOT32 || type == R_386_PLT32) {
985 sym_index = ELFW(R_SYM)(rel->r_info);
986 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
987 /* look at the symbol got offset. If none, then add one */
988 if (type == R_386_GOT32)
989 reloc_type = R_386_GLOB_DAT;
990 else
991 reloc_type = R_386_JMP_SLOT;
992 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
993 sym_index);
995 break;
996 #elif defined(TCC_TARGET_ARM)
997 case R_ARM_GOT_BREL:
998 case R_ARM_GOTOFF32:
999 case R_ARM_BASE_PREL:
1000 case R_ARM_PLT32:
1001 if (!s1->got)
1002 build_got(s1);
1003 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1004 sym_index = ELFW(R_SYM)(rel->r_info);
1005 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1006 /* look at the symbol got offset. If none, then add one */
1007 if (type == R_ARM_GOT_BREL)
1008 reloc_type = R_ARM_GLOB_DAT;
1009 else
1010 reloc_type = R_ARM_JUMP_SLOT;
1011 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1012 sym_index);
1014 break;
1015 #elif defined(TCC_TARGET_C67)
1016 case R_C60_GOT32:
1017 case R_C60_GOTOFF:
1018 case R_C60_GOTPC:
1019 case R_C60_PLT32:
1020 if (!s1->got)
1021 build_got(s1);
1022 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1023 sym_index = ELFW(R_SYM)(rel->r_info);
1024 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1025 /* look at the symbol got offset. If none, then add one */
1026 if (type == R_C60_GOT32)
1027 reloc_type = R_C60_GLOB_DAT;
1028 else
1029 reloc_type = R_C60_JMP_SLOT;
1030 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1031 sym_index);
1033 break;
1034 #elif defined(TCC_TARGET_X86_64)
1035 case R_X86_64_GOT32:
1036 case R_X86_64_GOTTPOFF:
1037 case R_X86_64_GOTPCREL:
1038 case R_X86_64_PLT32:
1039 if (!s1->got)
1040 build_got(s1);
1041 if (type == R_X86_64_GOT32 || type == R_X86_64_PLT32) {
1042 sym_index = ELFW(R_SYM)(rel->r_info);
1043 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1044 /* look at the symbol got offset. If none, then add one */
1045 if (type == R_X86_64_GOT32)
1046 reloc_type = R_X86_64_GLOB_DAT;
1047 else
1048 reloc_type = R_X86_64_JUMP_SLOT;
1049 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1050 sym_index);
1052 break;
1053 #else
1054 #error unsupported CPU
1055 #endif
1056 default:
1057 break;
1063 static Section *new_symtab(TCCState *s1,
1064 const char *symtab_name, int sh_type, int sh_flags,
1065 const char *strtab_name,
1066 const char *hash_name, int hash_sh_flags)
1068 Section *symtab, *strtab, *hash;
1069 int *ptr, nb_buckets;
1071 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1072 symtab->sh_entsize = sizeof(ElfW(Sym));
1073 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1074 put_elf_str(strtab, "");
1075 symtab->link = strtab;
1076 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1078 nb_buckets = 1;
1080 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1081 hash->sh_entsize = sizeof(int);
1082 symtab->hash = hash;
1083 hash->link = symtab;
1085 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1086 ptr[0] = nb_buckets;
1087 ptr[1] = 1;
1088 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1089 return symtab;
1092 /* put dynamic tag */
1093 static void put_dt(Section *dynamic, int dt, unsigned long val)
1095 ElfW(Dyn) *dyn;
1096 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1097 dyn->d_tag = dt;
1098 dyn->d_un.d_val = val;
1101 static void add_init_array_defines(TCCState *s1, const char *section_name)
1103 Section *s;
1104 long end_offset;
1105 char sym_start[1024];
1106 char sym_end[1024];
1108 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1109 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1111 s = find_section(s1, section_name);
1112 if (!s) {
1113 end_offset = 0;
1114 s = data_section;
1115 } else {
1116 end_offset = s->data_offset;
1119 add_elf_sym(symtab_section,
1120 0, 0,
1121 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1122 s->sh_num, sym_start);
1123 add_elf_sym(symtab_section,
1124 end_offset, 0,
1125 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1126 s->sh_num, sym_end);
1129 /* add tcc runtime libraries */
1130 static void tcc_add_runtime(TCCState *s1)
1132 #if defined(CONFIG_TCC_BCHECK) || !defined(CONFIG_USE_LIBGCC)
1133 char buf[1024];
1134 #endif
1136 #ifdef CONFIG_TCC_BCHECK
1137 if (do_bounds_check) {
1138 unsigned long *ptr;
1139 Section *init_section;
1140 unsigned char *pinit;
1141 int sym_index;
1143 /* XXX: add an object file to do that */
1144 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1145 *ptr = 0;
1146 add_elf_sym(symtab_section, 0, 0,
1147 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1148 bounds_section->sh_num, "__bounds_start");
1149 /* add bound check code */
1150 snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "bcheck.o");
1151 tcc_add_file(s1, buf);
1152 #ifdef TCC_TARGET_I386
1153 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1154 /* add 'call __bound_init()' in .init section */
1155 init_section = find_section(s1, ".init");
1156 pinit = section_ptr_add(init_section, 5);
1157 pinit[0] = 0xe8;
1158 put32(pinit + 1, -4);
1159 sym_index = find_elf_sym(symtab_section, "__bound_init");
1160 put_elf_reloc(symtab_section, init_section,
1161 init_section->data_offset - 4, R_386_PC32, sym_index);
1163 #endif
1165 #endif
1166 /* add libc */
1167 if (!s1->nostdlib) {
1168 tcc_add_library(s1, "c");
1170 #ifdef CONFIG_USE_LIBGCC
1171 tcc_add_file(s1, CONFIG_SYSROOT "/lib/libgcc_s.so.1");
1172 #else
1173 snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "libtcc1.a");
1174 tcc_add_file(s1, buf);
1175 #endif
1177 /* add crt end if not memory output */
1178 if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) {
1179 tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
1183 /* add various standard linker symbols (must be done after the
1184 sections are filled (for example after allocating common
1185 symbols)) */
1186 static void tcc_add_linker_symbols(TCCState *s1)
1188 char buf[1024];
1189 int i;
1190 Section *s;
1192 add_elf_sym(symtab_section,
1193 text_section->data_offset, 0,
1194 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1195 text_section->sh_num, "_etext");
1196 add_elf_sym(symtab_section,
1197 data_section->data_offset, 0,
1198 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1199 data_section->sh_num, "_edata");
1200 add_elf_sym(symtab_section,
1201 bss_section->data_offset, 0,
1202 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1203 bss_section->sh_num, "_end");
1204 /* horrible new standard ldscript defines */
1205 add_init_array_defines(s1, ".preinit_array");
1206 add_init_array_defines(s1, ".init_array");
1207 add_init_array_defines(s1, ".fini_array");
1209 /* add start and stop symbols for sections whose name can be
1210 expressed in C */
1211 for(i = 1; i < s1->nb_sections; i++) {
1212 s = s1->sections[i];
1213 if (s->sh_type == SHT_PROGBITS &&
1214 (s->sh_flags & SHF_ALLOC)) {
1215 const char *p;
1216 int ch;
1218 /* check if section name can be expressed in C */
1219 p = s->name;
1220 for(;;) {
1221 ch = *p;
1222 if (!ch)
1223 break;
1224 if (!isid(ch) && !isnum(ch))
1225 goto next_sec;
1226 p++;
1228 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1229 add_elf_sym(symtab_section,
1230 0, 0,
1231 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1232 s->sh_num, buf);
1233 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1234 add_elf_sym(symtab_section,
1235 s->data_offset, 0,
1236 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1237 s->sh_num, buf);
1239 next_sec: ;
1243 /* name of ELF interpreter */
1244 #ifdef __FreeBSD__
1245 static char elf_interp[] = "/usr/libexec/ld-elf.so.1";
1246 #else
1247 #ifdef TCC_ARM_EABI
1248 static char elf_interp[] = "/lib/ld-linux.so.3";
1249 #elif defined(TCC_TARGET_X86_64)
1250 static char elf_interp[] = "/lib/ld-linux-x86-64.so.2";
1251 #else
1252 static char elf_interp[] = "/lib/ld-linux.so.2";
1253 #endif
1254 #endif
1256 static void tcc_output_binary(TCCState *s1, FILE *f,
1257 const int *section_order)
1259 Section *s;
1260 int i, offset, size;
1262 offset = 0;
1263 for(i=1;i<s1->nb_sections;i++) {
1264 s = s1->sections[section_order[i]];
1265 if (s->sh_type != SHT_NOBITS &&
1266 (s->sh_flags & SHF_ALLOC)) {
1267 while (offset < s->sh_offset) {
1268 fputc(0, f);
1269 offset++;
1271 size = s->sh_size;
1272 fwrite(s->data, 1, size, f);
1273 offset += size;
1278 /* output an ELF file */
1279 /* XXX: suppress unneeded sections */
1280 int elf_output_file(TCCState *s1, const char *filename)
1282 ElfW(Ehdr) ehdr;
1283 FILE *f;
1284 int fd, mode, ret;
1285 int *section_order;
1286 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
1287 unsigned long addr;
1288 Section *strsec, *s;
1289 ElfW(Shdr) shdr, *sh;
1290 ElfW(Phdr) *phdr, *ph;
1291 Section *interp, *dynamic, *dynstr;
1292 unsigned long saved_dynamic_data_offset;
1293 ElfW(Sym) *sym;
1294 int type, file_type;
1295 unsigned long rel_addr, rel_size;
1297 file_type = s1->output_type;
1298 s1->nb_errors = 0;
1300 if (file_type != TCC_OUTPUT_OBJ) {
1301 tcc_add_runtime(s1);
1304 phdr = NULL;
1305 section_order = NULL;
1306 interp = NULL;
1307 dynamic = NULL;
1308 dynstr = NULL; /* avoid warning */
1309 saved_dynamic_data_offset = 0; /* avoid warning */
1311 if (file_type != TCC_OUTPUT_OBJ) {
1312 relocate_common_syms();
1314 tcc_add_linker_symbols(s1);
1316 if (!s1->static_link) {
1317 const char *name;
1318 int sym_index, index;
1319 ElfW(Sym) *esym, *sym_end;
1321 if (file_type == TCC_OUTPUT_EXE) {
1322 char *ptr;
1323 /* add interpreter section only if executable */
1324 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1325 interp->sh_addralign = 1;
1326 ptr = section_ptr_add(interp, sizeof(elf_interp));
1327 strcpy(ptr, elf_interp);
1330 /* add dynamic symbol table */
1331 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1332 ".dynstr",
1333 ".hash", SHF_ALLOC);
1334 dynstr = s1->dynsym->link;
1336 /* add dynamic section */
1337 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1338 SHF_ALLOC | SHF_WRITE);
1339 dynamic->link = dynstr;
1340 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1342 /* add PLT */
1343 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1344 SHF_ALLOC | SHF_EXECINSTR);
1345 s1->plt->sh_entsize = 4;
1347 build_got(s1);
1349 /* scan for undefined symbols and see if they are in the
1350 dynamic symbols. If a symbol STT_FUNC is found, then we
1351 add it in the PLT. If a symbol STT_OBJECT is found, we
1352 add it in the .bss section with a suitable relocation */
1353 sym_end = (ElfW(Sym) *)(symtab_section->data +
1354 symtab_section->data_offset);
1355 if (file_type == TCC_OUTPUT_EXE) {
1356 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1357 sym < sym_end;
1358 sym++) {
1359 if (sym->st_shndx == SHN_UNDEF) {
1360 name = symtab_section->link->data + sym->st_name;
1361 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1362 if (sym_index) {
1363 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1364 type = ELFW(ST_TYPE)(esym->st_info);
1365 if (type == STT_FUNC) {
1366 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1367 esym->st_info,
1368 sym - (ElfW(Sym) *)symtab_section->data);
1369 } else if (type == STT_OBJECT) {
1370 unsigned long offset;
1371 offset = bss_section->data_offset;
1372 /* XXX: which alignment ? */
1373 offset = (offset + 16 - 1) & -16;
1374 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1375 esym->st_info, 0,
1376 bss_section->sh_num, name);
1377 put_elf_reloc(s1->dynsym, bss_section,
1378 offset, R_COPY, index);
1379 offset += esym->st_size;
1380 bss_section->data_offset = offset;
1382 } else {
1383 /* STB_WEAK undefined symbols are accepted */
1384 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1385 it */
1386 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1387 !strcmp(name, "_fp_hw")) {
1388 } else {
1389 error_noabort("undefined symbol '%s'", name);
1392 } else if (s1->rdynamic &&
1393 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1394 /* if -rdynamic option, then export all non
1395 local symbols */
1396 name = symtab_section->link->data + sym->st_name;
1397 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1398 sym->st_info, 0,
1399 sym->st_shndx, name);
1403 if (s1->nb_errors)
1404 goto fail;
1406 /* now look at unresolved dynamic symbols and export
1407 corresponding symbol */
1408 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1409 s1->dynsymtab_section->data_offset);
1410 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1411 esym < sym_end;
1412 esym++) {
1413 if (esym->st_shndx == SHN_UNDEF) {
1414 name = s1->dynsymtab_section->link->data + esym->st_name;
1415 sym_index = find_elf_sym(symtab_section, name);
1416 if (sym_index) {
1417 /* XXX: avoid adding a symbol if already
1418 present because of -rdynamic ? */
1419 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1420 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1421 sym->st_info, 0,
1422 sym->st_shndx, name);
1423 } else {
1424 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1425 /* weak symbols can stay undefined */
1426 } else {
1427 warning("undefined dynamic symbol '%s'", name);
1432 } else {
1433 int nb_syms;
1434 /* shared library case : we simply export all the global symbols */
1435 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1436 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1437 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1438 sym < sym_end;
1439 sym++) {
1440 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1441 name = symtab_section->link->data + sym->st_name;
1442 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1443 sym->st_info, 0,
1444 sym->st_shndx, name);
1445 s1->symtab_to_dynsym[sym -
1446 (ElfW(Sym) *)symtab_section->data] =
1447 index;
1452 build_got_entries(s1);
1454 /* add a list of needed dlls */
1455 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1456 DLLReference *dllref = s1->loaded_dlls[i];
1457 if (dllref->level == 0)
1458 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1460 /* XXX: currently, since we do not handle PIC code, we
1461 must relocate the readonly segments */
1462 if (file_type == TCC_OUTPUT_DLL) {
1463 if (s1->soname)
1464 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1465 put_dt(dynamic, DT_TEXTREL, 0);
1468 /* add necessary space for other entries */
1469 saved_dynamic_data_offset = dynamic->data_offset;
1470 dynamic->data_offset += sizeof(ElfW(Dyn)) * 9;
1471 } else {
1472 /* still need to build got entries in case of static link */
1473 build_got_entries(s1);
1477 memset(&ehdr, 0, sizeof(ehdr));
1479 /* we add a section for symbols */
1480 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1481 put_elf_str(strsec, "");
1483 /* compute number of sections */
1484 shnum = s1->nb_sections;
1486 /* this array is used to reorder sections in the output file */
1487 section_order = tcc_malloc(sizeof(int) * shnum);
1488 section_order[0] = 0;
1489 sh_order_index = 1;
1491 /* compute number of program headers */
1492 switch(file_type) {
1493 default:
1494 case TCC_OUTPUT_OBJ:
1495 phnum = 0;
1496 break;
1497 case TCC_OUTPUT_EXE:
1498 if (!s1->static_link)
1499 phnum = 4;
1500 else
1501 phnum = 2;
1502 break;
1503 case TCC_OUTPUT_DLL:
1504 phnum = 3;
1505 break;
1508 /* allocate strings for section names and decide if an unallocated
1509 section should be output */
1510 /* NOTE: the strsec section comes last, so its size is also
1511 correct ! */
1512 for(i = 1; i < s1->nb_sections; i++) {
1513 s = s1->sections[i];
1514 s->sh_name = put_elf_str(strsec, s->name);
1515 #if 0 //gr
1516 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1517 s->sh_flags,
1518 s->sh_type,
1519 s->sh_info,
1520 s->name,
1521 s->reloc ? s->reloc->name : "n"
1523 #endif
1524 /* when generating a DLL, we include relocations but we may
1525 patch them */
1526 if (file_type == TCC_OUTPUT_DLL &&
1527 s->sh_type == SHT_RELX &&
1528 !(s->sh_flags & SHF_ALLOC)) {
1529 /* //gr: avoid bogus relocs for empty (debug) sections */
1530 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1531 prepare_dynamic_rel(s1, s);
1532 else if (do_debug)
1533 s->sh_size = s->data_offset;
1534 } else if (do_debug ||
1535 file_type == TCC_OUTPUT_OBJ ||
1536 (s->sh_flags & SHF_ALLOC) ||
1537 i == (s1->nb_sections - 1)) {
1538 /* we output all sections if debug or object file */
1539 s->sh_size = s->data_offset;
1543 /* allocate program segment headers */
1544 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1546 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1547 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1548 } else {
1549 file_offset = 0;
1551 if (phnum > 0) {
1552 /* compute section to program header mapping */
1553 if (s1->has_text_addr) {
1554 int a_offset, p_offset;
1555 addr = s1->text_addr;
1556 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1557 ELF_PAGE_SIZE */
1558 a_offset = addr & (ELF_PAGE_SIZE - 1);
1559 p_offset = file_offset & (ELF_PAGE_SIZE - 1);
1560 if (a_offset < p_offset)
1561 a_offset += ELF_PAGE_SIZE;
1562 file_offset += (a_offset - p_offset);
1563 } else {
1564 if (file_type == TCC_OUTPUT_DLL)
1565 addr = 0;
1566 else
1567 addr = ELF_START_ADDR;
1568 /* compute address after headers */
1569 addr += (file_offset & (ELF_PAGE_SIZE - 1));
1572 /* dynamic relocation table information, for .dynamic section */
1573 rel_size = 0;
1574 rel_addr = 0;
1576 /* leave one program header for the program interpreter */
1577 ph = &phdr[0];
1578 if (interp)
1579 ph++;
1581 for(j = 0; j < 2; j++) {
1582 ph->p_type = PT_LOAD;
1583 if (j == 0)
1584 ph->p_flags = PF_R | PF_X;
1585 else
1586 ph->p_flags = PF_R | PF_W;
1587 ph->p_align = ELF_PAGE_SIZE;
1589 /* we do the following ordering: interp, symbol tables,
1590 relocations, progbits, nobits */
1591 /* XXX: do faster and simpler sorting */
1592 for(k = 0; k < 5; k++) {
1593 for(i = 1; i < s1->nb_sections; i++) {
1594 s = s1->sections[i];
1595 /* compute if section should be included */
1596 if (j == 0) {
1597 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1598 SHF_ALLOC)
1599 continue;
1600 } else {
1601 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1602 (SHF_ALLOC | SHF_WRITE))
1603 continue;
1605 if (s == interp) {
1606 if (k != 0)
1607 continue;
1608 } else if (s->sh_type == SHT_DYNSYM ||
1609 s->sh_type == SHT_STRTAB ||
1610 s->sh_type == SHT_HASH) {
1611 if (k != 1)
1612 continue;
1613 } else if (s->sh_type == SHT_RELX) {
1614 if (k != 2)
1615 continue;
1616 } else if (s->sh_type == SHT_NOBITS) {
1617 if (k != 4)
1618 continue;
1619 } else {
1620 if (k != 3)
1621 continue;
1623 section_order[sh_order_index++] = i;
1625 /* section matches: we align it and add its size */
1626 tmp = addr;
1627 addr = (addr + s->sh_addralign - 1) &
1628 ~(s->sh_addralign - 1);
1629 file_offset += addr - tmp;
1630 s->sh_offset = file_offset;
1631 s->sh_addr = addr;
1633 /* update program header infos */
1634 if (ph->p_offset == 0) {
1635 ph->p_offset = file_offset;
1636 ph->p_vaddr = addr;
1637 ph->p_paddr = ph->p_vaddr;
1639 /* update dynamic relocation infos */
1640 if (s->sh_type == SHT_RELX) {
1641 if (rel_size == 0)
1642 rel_addr = addr;
1643 rel_size += s->sh_size;
1645 addr += s->sh_size;
1646 if (s->sh_type != SHT_NOBITS)
1647 file_offset += s->sh_size;
1650 ph->p_filesz = file_offset - ph->p_offset;
1651 ph->p_memsz = addr - ph->p_vaddr;
1652 ph++;
1653 if (j == 0) {
1654 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1655 /* if in the middle of a page, we duplicate the page in
1656 memory so that one copy is RX and the other is RW */
1657 if ((addr & (ELF_PAGE_SIZE - 1)) != 0)
1658 addr += ELF_PAGE_SIZE;
1659 } else {
1660 addr = (addr + ELF_PAGE_SIZE - 1) & ~(ELF_PAGE_SIZE - 1);
1661 file_offset = (file_offset + ELF_PAGE_SIZE - 1) &
1662 ~(ELF_PAGE_SIZE - 1);
1667 /* if interpreter, then add corresponing program header */
1668 if (interp) {
1669 ph = &phdr[0];
1671 ph->p_type = PT_INTERP;
1672 ph->p_offset = interp->sh_offset;
1673 ph->p_vaddr = interp->sh_addr;
1674 ph->p_paddr = ph->p_vaddr;
1675 ph->p_filesz = interp->sh_size;
1676 ph->p_memsz = interp->sh_size;
1677 ph->p_flags = PF_R;
1678 ph->p_align = interp->sh_addralign;
1681 /* if dynamic section, then add corresponing program header */
1682 if (dynamic) {
1683 ElfW(Sym) *sym_end;
1685 ph = &phdr[phnum - 1];
1687 ph->p_type = PT_DYNAMIC;
1688 ph->p_offset = dynamic->sh_offset;
1689 ph->p_vaddr = dynamic->sh_addr;
1690 ph->p_paddr = ph->p_vaddr;
1691 ph->p_filesz = dynamic->sh_size;
1692 ph->p_memsz = dynamic->sh_size;
1693 ph->p_flags = PF_R | PF_W;
1694 ph->p_align = dynamic->sh_addralign;
1696 /* put GOT dynamic section address */
1697 put32(s1->got->data, dynamic->sh_addr);
1699 /* relocate the PLT */
1700 if (file_type == TCC_OUTPUT_EXE) {
1701 uint8_t *p, *p_end;
1703 p = s1->plt->data;
1704 p_end = p + s1->plt->data_offset;
1705 if (p < p_end) {
1706 #if defined(TCC_TARGET_I386)
1707 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1708 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1709 p += 16;
1710 while (p < p_end) {
1711 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1712 p += 16;
1714 #elif defined(TCC_TARGET_X86_64)
1715 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1716 put32(p + 2, get32(p + 2) + x);
1717 put32(p + 8, get32(p + 8) + x - 6);
1718 p += 16;
1719 while (p < p_end) {
1720 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1721 p += 16;
1723 #elif defined(TCC_TARGET_ARM)
1724 int x;
1725 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1726 p +=16;
1727 while (p < p_end) {
1728 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1729 p += 16;
1731 #elif defined(TCC_TARGET_C67)
1732 /* XXX: TODO */
1733 #else
1734 #error unsupported CPU
1735 #endif
1739 /* relocate symbols in .dynsym */
1740 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
1741 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
1742 sym < sym_end;
1743 sym++) {
1744 if (sym->st_shndx == SHN_UNDEF) {
1745 /* relocate to the PLT if the symbol corresponds
1746 to a PLT entry */
1747 if (sym->st_value)
1748 sym->st_value += s1->plt->sh_addr;
1749 } else if (sym->st_shndx < SHN_LORESERVE) {
1750 /* do symbol relocation */
1751 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
1755 /* put dynamic section entries */
1756 dynamic->data_offset = saved_dynamic_data_offset;
1757 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
1758 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
1759 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
1760 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
1761 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
1762 #ifdef TCC_TARGET_X86_64
1763 put_dt(dynamic, DT_RELA, rel_addr);
1764 put_dt(dynamic, DT_RELASZ, rel_size);
1765 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
1766 #else
1767 put_dt(dynamic, DT_REL, rel_addr);
1768 put_dt(dynamic, DT_RELSZ, rel_size);
1769 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
1770 #endif
1771 if (do_debug)
1772 put_dt(dynamic, DT_DEBUG, 0);
1773 put_dt(dynamic, DT_NULL, 0);
1776 ehdr.e_phentsize = sizeof(ElfW(Phdr));
1777 ehdr.e_phnum = phnum;
1778 ehdr.e_phoff = sizeof(ElfW(Ehdr));
1781 /* all other sections come after */
1782 for(i = 1; i < s1->nb_sections; i++) {
1783 s = s1->sections[i];
1784 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
1785 continue;
1786 section_order[sh_order_index++] = i;
1788 file_offset = (file_offset + s->sh_addralign - 1) &
1789 ~(s->sh_addralign - 1);
1790 s->sh_offset = file_offset;
1791 if (s->sh_type != SHT_NOBITS)
1792 file_offset += s->sh_size;
1795 /* if building executable or DLL, then relocate each section
1796 except the GOT which is already relocated */
1797 if (file_type != TCC_OUTPUT_OBJ) {
1798 relocate_syms(s1, 0);
1800 if (s1->nb_errors != 0) {
1801 fail:
1802 ret = -1;
1803 goto the_end;
1806 /* relocate sections */
1807 /* XXX: ignore sections with allocated relocations ? */
1808 for(i = 1; i < s1->nb_sections; i++) {
1809 s = s1->sections[i];
1810 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
1811 relocate_section(s1, s);
1814 /* relocate relocation entries if the relocation tables are
1815 allocated in the executable */
1816 for(i = 1; i < s1->nb_sections; i++) {
1817 s = s1->sections[i];
1818 if ((s->sh_flags & SHF_ALLOC) &&
1819 s->sh_type == SHT_RELX) {
1820 relocate_rel(s1, s);
1824 /* get entry point address */
1825 if (file_type == TCC_OUTPUT_EXE)
1826 ehdr.e_entry = (unsigned long)tcc_get_symbol_err(s1, "_start");
1827 else
1828 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
1831 /* write elf file */
1832 if (file_type == TCC_OUTPUT_OBJ)
1833 mode = 0666;
1834 else
1835 mode = 0777;
1836 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
1837 if (fd < 0) {
1838 error_noabort("could not write '%s'", filename);
1839 goto fail;
1841 f = fdopen(fd, "wb");
1842 if (verbose)
1843 printf("<- %s\n", filename);
1845 #ifdef TCC_TARGET_COFF
1846 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
1847 tcc_output_coff(s1, f);
1848 } else
1849 #endif
1850 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1851 sort_syms(s1, symtab_section);
1853 /* align to 4 */
1854 file_offset = (file_offset + 3) & -4;
1856 /* fill header */
1857 ehdr.e_ident[0] = ELFMAG0;
1858 ehdr.e_ident[1] = ELFMAG1;
1859 ehdr.e_ident[2] = ELFMAG2;
1860 ehdr.e_ident[3] = ELFMAG3;
1861 ehdr.e_ident[4] = TCC_ELFCLASS;
1862 ehdr.e_ident[5] = ELFDATA2LSB;
1863 ehdr.e_ident[6] = EV_CURRENT;
1864 #ifdef __FreeBSD__
1865 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
1866 #endif
1867 #ifdef TCC_TARGET_ARM
1868 #ifdef TCC_ARM_EABI
1869 ehdr.e_ident[EI_OSABI] = 0;
1870 ehdr.e_flags = 4 << 24;
1871 #else
1872 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
1873 #endif
1874 #endif
1875 switch(file_type) {
1876 default:
1877 case TCC_OUTPUT_EXE:
1878 ehdr.e_type = ET_EXEC;
1879 break;
1880 case TCC_OUTPUT_DLL:
1881 ehdr.e_type = ET_DYN;
1882 break;
1883 case TCC_OUTPUT_OBJ:
1884 ehdr.e_type = ET_REL;
1885 break;
1887 ehdr.e_machine = EM_TCC_TARGET;
1888 ehdr.e_version = EV_CURRENT;
1889 ehdr.e_shoff = file_offset;
1890 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
1891 ehdr.e_shentsize = sizeof(ElfW(Shdr));
1892 ehdr.e_shnum = shnum;
1893 ehdr.e_shstrndx = shnum - 1;
1895 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
1896 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
1897 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1899 for(i=1;i<s1->nb_sections;i++) {
1900 s = s1->sections[section_order[i]];
1901 if (s->sh_type != SHT_NOBITS) {
1902 while (offset < s->sh_offset) {
1903 fputc(0, f);
1904 offset++;
1906 size = s->sh_size;
1907 fwrite(s->data, 1, size, f);
1908 offset += size;
1912 /* output section headers */
1913 while (offset < ehdr.e_shoff) {
1914 fputc(0, f);
1915 offset++;
1918 for(i=0;i<s1->nb_sections;i++) {
1919 sh = &shdr;
1920 memset(sh, 0, sizeof(ElfW(Shdr)));
1921 s = s1->sections[i];
1922 if (s) {
1923 sh->sh_name = s->sh_name;
1924 sh->sh_type = s->sh_type;
1925 sh->sh_flags = s->sh_flags;
1926 sh->sh_entsize = s->sh_entsize;
1927 sh->sh_info = s->sh_info;
1928 if (s->link)
1929 sh->sh_link = s->link->sh_num;
1930 sh->sh_addralign = s->sh_addralign;
1931 sh->sh_addr = s->sh_addr;
1932 sh->sh_offset = s->sh_offset;
1933 sh->sh_size = s->sh_size;
1935 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
1937 } else {
1938 tcc_output_binary(s1, f, section_order);
1940 fclose(f);
1942 ret = 0;
1943 the_end:
1944 tcc_free(s1->symtab_to_dynsym);
1945 tcc_free(section_order);
1946 tcc_free(phdr);
1947 tcc_free(s1->got_offsets);
1948 return ret;
1951 int tcc_output_file(TCCState *s, const char *filename)
1953 int ret;
1954 #ifdef TCC_TARGET_PE
1955 if (s->output_type != TCC_OUTPUT_OBJ) {
1956 ret = pe_output_file(s, filename);
1957 } else
1958 #endif
1960 ret = elf_output_file(s, filename);
1962 return ret;
1965 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
1967 void *data;
1969 data = tcc_malloc(size);
1970 lseek(fd, file_offset, SEEK_SET);
1971 read(fd, data, size);
1972 return data;
1975 typedef struct SectionMergeInfo {
1976 Section *s; /* corresponding existing section */
1977 unsigned long offset; /* offset of the new section in the existing section */
1978 uint8_t new_section; /* true if section 's' was added */
1979 uint8_t link_once; /* true if link once section */
1980 } SectionMergeInfo;
1982 /* load an object file and merge it with current files */
1983 /* XXX: handle correctly stab (debug) info */
1984 static int tcc_load_object_file(TCCState *s1,
1985 int fd, unsigned long file_offset)
1987 ElfW(Ehdr) ehdr;
1988 ElfW(Shdr) *shdr, *sh;
1989 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
1990 unsigned char *strsec, *strtab;
1991 int *old_to_new_syms;
1992 char *sh_name, *name;
1993 SectionMergeInfo *sm_table, *sm;
1994 ElfW(Sym) *sym, *symtab;
1995 ElfW_Rel *rel, *rel_end;
1996 Section *s;
1998 int stab_index;
1999 int stabstr_index;
2001 stab_index = stabstr_index = 0;
2003 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2004 goto fail1;
2005 if (ehdr.e_ident[0] != ELFMAG0 ||
2006 ehdr.e_ident[1] != ELFMAG1 ||
2007 ehdr.e_ident[2] != ELFMAG2 ||
2008 ehdr.e_ident[3] != ELFMAG3)
2009 goto fail1;
2010 /* test if object file */
2011 if (ehdr.e_type != ET_REL)
2012 goto fail1;
2013 /* test CPU specific stuff */
2014 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2015 ehdr.e_machine != EM_TCC_TARGET) {
2016 fail1:
2017 error_noabort("invalid object file");
2018 return -1;
2020 /* read sections */
2021 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2022 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2023 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2025 /* load section names */
2026 sh = &shdr[ehdr.e_shstrndx];
2027 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2029 /* load symtab and strtab */
2030 old_to_new_syms = NULL;
2031 symtab = NULL;
2032 strtab = NULL;
2033 nb_syms = 0;
2034 for(i = 1; i < ehdr.e_shnum; i++) {
2035 sh = &shdr[i];
2036 if (sh->sh_type == SHT_SYMTAB) {
2037 if (symtab) {
2038 error_noabort("object must contain only one symtab");
2039 fail:
2040 ret = -1;
2041 goto the_end;
2043 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2044 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2045 sm_table[i].s = symtab_section;
2047 /* now load strtab */
2048 sh = &shdr[sh->sh_link];
2049 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2053 /* now examine each section and try to merge its content with the
2054 ones in memory */
2055 for(i = 1; i < ehdr.e_shnum; i++) {
2056 /* no need to examine section name strtab */
2057 if (i == ehdr.e_shstrndx)
2058 continue;
2059 sh = &shdr[i];
2060 sh_name = strsec + sh->sh_name;
2061 /* ignore sections types we do not handle */
2062 if (sh->sh_type != SHT_PROGBITS &&
2063 sh->sh_type != SHT_RELX &&
2064 #ifdef TCC_ARM_EABI
2065 sh->sh_type != SHT_ARM_EXIDX &&
2066 #endif
2067 sh->sh_type != SHT_NOBITS &&
2068 strcmp(sh_name, ".stabstr")
2070 continue;
2071 if (sh->sh_addralign < 1)
2072 sh->sh_addralign = 1;
2073 /* find corresponding section, if any */
2074 for(j = 1; j < s1->nb_sections;j++) {
2075 s = s1->sections[j];
2076 if (!strcmp(s->name, sh_name)) {
2077 if (!strncmp(sh_name, ".gnu.linkonce",
2078 sizeof(".gnu.linkonce") - 1)) {
2079 /* if a 'linkonce' section is already present, we
2080 do not add it again. It is a little tricky as
2081 symbols can still be defined in
2082 it. */
2083 sm_table[i].link_once = 1;
2084 goto next;
2085 } else {
2086 goto found;
2090 /* not found: create new section */
2091 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2092 /* take as much info as possible from the section. sh_link and
2093 sh_info will be updated later */
2094 s->sh_addralign = sh->sh_addralign;
2095 s->sh_entsize = sh->sh_entsize;
2096 sm_table[i].new_section = 1;
2097 found:
2098 if (sh->sh_type != s->sh_type) {
2099 error_noabort("invalid section type");
2100 goto fail;
2103 /* align start of section */
2104 offset = s->data_offset;
2106 if (0 == strcmp(sh_name, ".stab")) {
2107 stab_index = i;
2108 goto no_align;
2110 if (0 == strcmp(sh_name, ".stabstr")) {
2111 stabstr_index = i;
2112 goto no_align;
2115 size = sh->sh_addralign - 1;
2116 offset = (offset + size) & ~size;
2117 if (sh->sh_addralign > s->sh_addralign)
2118 s->sh_addralign = sh->sh_addralign;
2119 s->data_offset = offset;
2120 no_align:
2121 sm_table[i].offset = offset;
2122 sm_table[i].s = s;
2123 /* concatenate sections */
2124 size = sh->sh_size;
2125 if (sh->sh_type != SHT_NOBITS) {
2126 unsigned char *ptr;
2127 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2128 ptr = section_ptr_add(s, size);
2129 read(fd, ptr, size);
2130 } else {
2131 s->data_offset += size;
2133 next: ;
2136 /* //gr relocate stab strings */
2137 if (stab_index && stabstr_index) {
2138 Stab_Sym *a, *b;
2139 unsigned o;
2140 s = sm_table[stab_index].s;
2141 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2142 b = (Stab_Sym *)(s->data + s->data_offset);
2143 o = sm_table[stabstr_index].offset;
2144 while (a < b)
2145 a->n_strx += o, a++;
2148 /* second short pass to update sh_link and sh_info fields of new
2149 sections */
2150 for(i = 1; i < ehdr.e_shnum; i++) {
2151 s = sm_table[i].s;
2152 if (!s || !sm_table[i].new_section)
2153 continue;
2154 sh = &shdr[i];
2155 if (sh->sh_link > 0)
2156 s->link = sm_table[sh->sh_link].s;
2157 if (sh->sh_type == SHT_RELX) {
2158 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2159 /* update backward link */
2160 s1->sections[s->sh_info]->reloc = s;
2163 sm = sm_table;
2165 /* resolve symbols */
2166 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2168 sym = symtab + 1;
2169 for(i = 1; i < nb_syms; i++, sym++) {
2170 if (sym->st_shndx != SHN_UNDEF &&
2171 sym->st_shndx < SHN_LORESERVE) {
2172 sm = &sm_table[sym->st_shndx];
2173 if (sm->link_once) {
2174 /* if a symbol is in a link once section, we use the
2175 already defined symbol. It is very important to get
2176 correct relocations */
2177 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2178 name = strtab + sym->st_name;
2179 sym_index = find_elf_sym(symtab_section, name);
2180 if (sym_index)
2181 old_to_new_syms[i] = sym_index;
2183 continue;
2185 /* if no corresponding section added, no need to add symbol */
2186 if (!sm->s)
2187 continue;
2188 /* convert section number */
2189 sym->st_shndx = sm->s->sh_num;
2190 /* offset value */
2191 sym->st_value += sm->offset;
2193 /* add symbol */
2194 name = strtab + sym->st_name;
2195 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2196 sym->st_info, sym->st_other,
2197 sym->st_shndx, name);
2198 old_to_new_syms[i] = sym_index;
2201 /* third pass to patch relocation entries */
2202 for(i = 1; i < ehdr.e_shnum; i++) {
2203 s = sm_table[i].s;
2204 if (!s)
2205 continue;
2206 sh = &shdr[i];
2207 offset = sm_table[i].offset;
2208 switch(s->sh_type) {
2209 case SHT_RELX:
2210 /* take relocation offset information */
2211 offseti = sm_table[sh->sh_info].offset;
2212 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2213 for(rel = (ElfW_Rel *)(s->data + offset);
2214 rel < rel_end;
2215 rel++) {
2216 int type;
2217 unsigned sym_index;
2218 /* convert symbol index */
2219 type = ELFW(R_TYPE)(rel->r_info);
2220 sym_index = ELFW(R_SYM)(rel->r_info);
2221 /* NOTE: only one symtab assumed */
2222 if (sym_index >= nb_syms)
2223 goto invalid_reloc;
2224 sym_index = old_to_new_syms[sym_index];
2225 /* ignore link_once in rel section. */
2226 if (!sym_index && !sm->link_once) {
2227 invalid_reloc:
2228 error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2229 i, strsec + sh->sh_name, rel->r_offset);
2230 goto fail;
2232 rel->r_info = ELFW(R_INFO)(sym_index, type);
2233 /* offset the relocation offset */
2234 rel->r_offset += offseti;
2236 break;
2237 default:
2238 break;
2242 ret = 0;
2243 the_end:
2244 tcc_free(symtab);
2245 tcc_free(strtab);
2246 tcc_free(old_to_new_syms);
2247 tcc_free(sm_table);
2248 tcc_free(strsec);
2249 tcc_free(shdr);
2250 return ret;
2253 #define ARMAG "!<arch>\012" /* For COFF and a.out archives */
2255 typedef struct ArchiveHeader {
2256 char ar_name[16]; /* name of this member */
2257 char ar_date[12]; /* file mtime */
2258 char ar_uid[6]; /* owner uid; printed as decimal */
2259 char ar_gid[6]; /* owner gid; printed as decimal */
2260 char ar_mode[8]; /* file mode, printed as octal */
2261 char ar_size[10]; /* file size, printed as decimal */
2262 char ar_fmag[2]; /* should contain ARFMAG */
2263 } ArchiveHeader;
2265 static int get_be32(const uint8_t *b)
2267 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2270 /* load only the objects which resolve undefined symbols */
2271 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2273 int i, bound, nsyms, sym_index, off, ret;
2274 uint8_t *data;
2275 const char *ar_names, *p;
2276 const uint8_t *ar_index;
2277 ElfW(Sym) *sym;
2279 data = tcc_malloc(size);
2280 if (read(fd, data, size) != size)
2281 goto fail;
2282 nsyms = get_be32(data);
2283 ar_index = data + 4;
2284 ar_names = ar_index + nsyms * 4;
2286 do {
2287 bound = 0;
2288 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2289 sym_index = find_elf_sym(symtab_section, p);
2290 if(sym_index) {
2291 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2292 if(sym->st_shndx == SHN_UNDEF) {
2293 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2294 #if 0
2295 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2296 #endif
2297 ++bound;
2298 lseek(fd, off, SEEK_SET);
2299 if(tcc_load_object_file(s1, fd, off) < 0) {
2300 fail:
2301 ret = -1;
2302 goto the_end;
2307 } while(bound);
2308 ret = 0;
2309 the_end:
2310 tcc_free(data);
2311 return ret;
2314 /* load a '.a' file */
2315 static int tcc_load_archive(TCCState *s1, int fd)
2317 ArchiveHeader hdr;
2318 char ar_size[11];
2319 char ar_name[17];
2320 char magic[8];
2321 int size, len, i;
2322 unsigned long file_offset;
2324 /* skip magic which was already checked */
2325 read(fd, magic, sizeof(magic));
2327 for(;;) {
2328 len = read(fd, &hdr, sizeof(hdr));
2329 if (len == 0)
2330 break;
2331 if (len != sizeof(hdr)) {
2332 error_noabort("invalid archive");
2333 return -1;
2335 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2336 ar_size[sizeof(hdr.ar_size)] = '\0';
2337 size = strtol(ar_size, NULL, 0);
2338 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2339 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2340 if (ar_name[i] != ' ')
2341 break;
2343 ar_name[i + 1] = '\0';
2344 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2345 file_offset = lseek(fd, 0, SEEK_CUR);
2346 /* align to even */
2347 size = (size + 1) & ~1;
2348 if (!strcmp(ar_name, "/")) {
2349 /* coff symbol table : we handle it */
2350 if(s1->alacarte_link)
2351 return tcc_load_alacarte(s1, fd, size);
2352 } else if (!strcmp(ar_name, "//") ||
2353 !strcmp(ar_name, "__.SYMDEF") ||
2354 !strcmp(ar_name, "__.SYMDEF/") ||
2355 !strcmp(ar_name, "ARFILENAMES/")) {
2356 /* skip symbol table or archive names */
2357 } else {
2358 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2359 return -1;
2361 lseek(fd, file_offset + size, SEEK_SET);
2363 return 0;
2366 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2367 is referenced by the user (so it should be added as DT_NEEDED in
2368 the generated ELF file) */
2369 static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2371 ElfW(Ehdr) ehdr;
2372 ElfW(Shdr) *shdr, *sh, *sh1;
2373 int i, j, nb_syms, nb_dts, sym_bind, ret;
2374 ElfW(Sym) *sym, *dynsym;
2375 ElfW(Dyn) *dt, *dynamic;
2376 unsigned char *dynstr;
2377 const char *name, *soname;
2378 DLLReference *dllref;
2380 read(fd, &ehdr, sizeof(ehdr));
2382 /* test CPU specific stuff */
2383 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2384 ehdr.e_machine != EM_TCC_TARGET) {
2385 error_noabort("bad architecture");
2386 return -1;
2389 /* read sections */
2390 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2392 /* load dynamic section and dynamic symbols */
2393 nb_syms = 0;
2394 nb_dts = 0;
2395 dynamic = NULL;
2396 dynsym = NULL; /* avoid warning */
2397 dynstr = NULL; /* avoid warning */
2398 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2399 switch(sh->sh_type) {
2400 case SHT_DYNAMIC:
2401 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2402 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2403 break;
2404 case SHT_DYNSYM:
2405 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2406 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2407 sh1 = &shdr[sh->sh_link];
2408 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2409 break;
2410 default:
2411 break;
2415 /* compute the real library name */
2416 soname = tcc_basename(filename);
2418 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2419 if (dt->d_tag == DT_SONAME) {
2420 soname = dynstr + dt->d_un.d_val;
2424 /* if the dll is already loaded, do not load it */
2425 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2426 dllref = s1->loaded_dlls[i];
2427 if (!strcmp(soname, dllref->name)) {
2428 /* but update level if needed */
2429 if (level < dllref->level)
2430 dllref->level = level;
2431 ret = 0;
2432 goto the_end;
2436 // printf("loading dll '%s'\n", soname);
2438 /* add the dll and its level */
2439 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2440 dllref->level = level;
2441 strcpy(dllref->name, soname);
2442 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2444 /* add dynamic symbols in dynsym_section */
2445 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2446 sym_bind = ELFW(ST_BIND)(sym->st_info);
2447 if (sym_bind == STB_LOCAL)
2448 continue;
2449 name = dynstr + sym->st_name;
2450 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2451 sym->st_info, sym->st_other, sym->st_shndx, name);
2454 /* load all referenced DLLs */
2455 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2456 switch(dt->d_tag) {
2457 case DT_NEEDED:
2458 name = dynstr + dt->d_un.d_val;
2459 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2460 dllref = s1->loaded_dlls[j];
2461 if (!strcmp(name, dllref->name))
2462 goto already_loaded;
2464 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2465 error_noabort("referenced dll '%s' not found", name);
2466 ret = -1;
2467 goto the_end;
2469 already_loaded:
2470 break;
2473 ret = 0;
2474 the_end:
2475 tcc_free(dynstr);
2476 tcc_free(dynsym);
2477 tcc_free(dynamic);
2478 tcc_free(shdr);
2479 return ret;
2482 #define LD_TOK_NAME 256
2483 #define LD_TOK_EOF (-1)
2485 /* return next ld script token */
2486 static int ld_next(TCCState *s1, char *name, int name_size)
2488 int c;
2489 char *q;
2491 redo:
2492 switch(ch) {
2493 case ' ':
2494 case '\t':
2495 case '\f':
2496 case '\v':
2497 case '\r':
2498 case '\n':
2499 inp();
2500 goto redo;
2501 case '/':
2502 minp();
2503 if (ch == '*') {
2504 file->buf_ptr = parse_comment(file->buf_ptr);
2505 ch = file->buf_ptr[0];
2506 goto redo;
2507 } else {
2508 q = name;
2509 *q++ = '/';
2510 goto parse_name;
2512 break;
2513 /* case 'a' ... 'z': */
2514 case 'a':
2515 case 'b':
2516 case 'c':
2517 case 'd':
2518 case 'e':
2519 case 'f':
2520 case 'g':
2521 case 'h':
2522 case 'i':
2523 case 'j':
2524 case 'k':
2525 case 'l':
2526 case 'm':
2527 case 'n':
2528 case 'o':
2529 case 'p':
2530 case 'q':
2531 case 'r':
2532 case 's':
2533 case 't':
2534 case 'u':
2535 case 'v':
2536 case 'w':
2537 case 'x':
2538 case 'y':
2539 case 'z':
2540 /* case 'A' ... 'z': */
2541 case 'A':
2542 case 'B':
2543 case 'C':
2544 case 'D':
2545 case 'E':
2546 case 'F':
2547 case 'G':
2548 case 'H':
2549 case 'I':
2550 case 'J':
2551 case 'K':
2552 case 'L':
2553 case 'M':
2554 case 'N':
2555 case 'O':
2556 case 'P':
2557 case 'Q':
2558 case 'R':
2559 case 'S':
2560 case 'T':
2561 case 'U':
2562 case 'V':
2563 case 'W':
2564 case 'X':
2565 case 'Y':
2566 case 'Z':
2567 case '_':
2568 case '\\':
2569 case '.':
2570 case '$':
2571 case '~':
2572 q = name;
2573 parse_name:
2574 for(;;) {
2575 if (!((ch >= 'a' && ch <= 'z') ||
2576 (ch >= 'A' && ch <= 'Z') ||
2577 (ch >= '0' && ch <= '9') ||
2578 strchr("/.-_+=$:\\,~", ch)))
2579 break;
2580 if ((q - name) < name_size - 1) {
2581 *q++ = ch;
2583 minp();
2585 *q = '\0';
2586 c = LD_TOK_NAME;
2587 break;
2588 case CH_EOF:
2589 c = LD_TOK_EOF;
2590 break;
2591 default:
2592 c = ch;
2593 inp();
2594 break;
2596 #if 0
2597 printf("tok=%c %d\n", c, c);
2598 if (c == LD_TOK_NAME)
2599 printf(" name=%s\n", name);
2600 #endif
2601 return c;
2604 static int ld_add_file_list(TCCState *s1, int as_needed)
2606 char filename[1024];
2607 int t, ret;
2609 t = ld_next(s1, filename, sizeof(filename));
2610 if (t != '(')
2611 expect("(");
2612 t = ld_next(s1, filename, sizeof(filename));
2613 for(;;) {
2614 if (t == LD_TOK_EOF) {
2615 error_noabort("unexpected end of file");
2616 return -1;
2617 } else if (t == ')') {
2618 break;
2619 } else if (t != LD_TOK_NAME) {
2620 error_noabort("filename expected");
2621 return -1;
2623 if (!strcmp(filename, "AS_NEEDED")) {
2624 ret = ld_add_file_list(s1, 1);
2625 if (ret)
2626 return ret;
2627 } else {
2628 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2629 if (!as_needed)
2630 tcc_add_file(s1, filename);
2632 t = ld_next(s1, filename, sizeof(filename));
2633 if (t == ',') {
2634 t = ld_next(s1, filename, sizeof(filename));
2637 return 0;
2640 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
2641 files */
2642 static int tcc_load_ldscript(TCCState *s1)
2644 char cmd[64];
2645 char filename[1024];
2646 int t, ret;
2648 ch = file->buf_ptr[0];
2649 ch = handle_eob();
2650 for(;;) {
2651 t = ld_next(s1, cmd, sizeof(cmd));
2652 if (t == LD_TOK_EOF)
2653 return 0;
2654 else if (t != LD_TOK_NAME)
2655 return -1;
2656 if (!strcmp(cmd, "INPUT") ||
2657 !strcmp(cmd, "GROUP")) {
2658 ret = ld_add_file_list(s1, 0);
2659 if (ret)
2660 return ret;
2661 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
2662 !strcmp(cmd, "TARGET")) {
2663 /* ignore some commands */
2664 t = ld_next(s1, cmd, sizeof(cmd));
2665 if (t != '(')
2666 expect("(");
2667 for(;;) {
2668 t = ld_next(s1, filename, sizeof(filename));
2669 if (t == LD_TOK_EOF) {
2670 error_noabort("unexpected end of file");
2671 return -1;
2672 } else if (t == ')') {
2673 break;
2676 } else {
2677 return -1;
2680 return 0;