Revert "Add predictability in CType initialization."
[tinycc.git] / tccelf.c
blob5fea23a3974a0f63a036a715875a6fd4ec48c5da
1 /*
2 * ELF file handling for TCC
3 *
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "tcc.h"
23 static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */
25 ST_FUNC int put_elf_str(Section *s, const char *sym)
27 int offset, len;
28 char *ptr;
30 len = strlen(sym) + 1;
31 offset = s->data_offset;
32 ptr = section_ptr_add(s, len);
33 memcpy(ptr, sym, len);
34 return offset;
37 /* elf symbol hashing function */
38 static unsigned long elf_hash(const unsigned char *name)
40 unsigned long h = 0, g;
42 while (*name) {
43 h = (h << 4) + *name++;
44 g = h & 0xf0000000;
45 if (g)
46 h ^= g >> 24;
47 h &= ~g;
49 return h;
52 /* rebuild hash table of section s */
53 /* NOTE: we do factorize the hash table code to go faster */
54 static void rebuild_hash(Section *s, unsigned int nb_buckets)
56 ElfW(Sym) *sym;
57 int *ptr, *hash, nb_syms, sym_index, h;
58 char *strtab;
60 strtab = s->link->data;
61 nb_syms = s->data_offset / sizeof(ElfW(Sym));
63 s->hash->data_offset = 0;
64 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
65 ptr[0] = nb_buckets;
66 ptr[1] = nb_syms;
67 ptr += 2;
68 hash = ptr;
69 memset(hash, 0, (nb_buckets + 1) * sizeof(int));
70 ptr += nb_buckets + 1;
72 sym = (ElfW(Sym) *)s->data + 1;
73 for(sym_index = 1; sym_index < nb_syms; sym_index++) {
74 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
75 h = elf_hash(strtab + sym->st_name) % nb_buckets;
76 *ptr = hash[h];
77 hash[h] = sym_index;
78 } else {
79 *ptr = 0;
81 ptr++;
82 sym++;
86 /* return the symbol number */
87 ST_FUNC int put_elf_sym(Section *s, uplong value, unsigned long size,
88 int info, int other, int shndx, const char *name)
90 int name_offset, sym_index;
91 int nbuckets, h;
92 ElfW(Sym) *sym;
93 Section *hs;
95 sym = section_ptr_add(s, sizeof(ElfW(Sym)));
96 if (name)
97 name_offset = put_elf_str(s->link, name);
98 else
99 name_offset = 0;
100 /* XXX: endianness */
101 sym->st_name = name_offset;
102 sym->st_value = value;
103 sym->st_size = size;
104 sym->st_info = info;
105 sym->st_other = other;
106 sym->st_shndx = shndx;
107 sym_index = sym - (ElfW(Sym) *)s->data;
108 hs = s->hash;
109 if (hs) {
110 int *ptr, *base;
111 ptr = section_ptr_add(hs, sizeof(int));
112 base = (int *)hs->data;
113 /* only add global or weak symbols */
114 if (ELFW(ST_BIND)(info) != STB_LOCAL) {
115 /* add another hashing entry */
116 nbuckets = base[0];
117 h = elf_hash(name) % nbuckets;
118 *ptr = base[2 + h];
119 base[2 + h] = sym_index;
120 base[1]++;
121 /* we resize the hash table */
122 hs->nb_hashed_syms++;
123 if (hs->nb_hashed_syms > 2 * nbuckets) {
124 rebuild_hash(s, 2 * nbuckets);
126 } else {
127 *ptr = 0;
128 base[1]++;
131 return sym_index;
134 /* find global ELF symbol 'name' and return its index. Return 0 if not
135 found. */
136 ST_FUNC int find_elf_sym(Section *s, const char *name)
138 ElfW(Sym) *sym;
139 Section *hs;
140 int nbuckets, sym_index, h;
141 const char *name1;
143 hs = s->hash;
144 if (!hs)
145 return 0;
146 nbuckets = ((int *)hs->data)[0];
147 h = elf_hash(name) % nbuckets;
148 sym_index = ((int *)hs->data)[2 + h];
149 while (sym_index != 0) {
150 sym = &((ElfW(Sym) *)s->data)[sym_index];
151 name1 = s->link->data + sym->st_name;
152 if (!strcmp(name, name1))
153 return sym_index;
154 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
156 return 0;
159 /* return elf symbol value, signal error if 'err' is nonzero */
160 static void *get_elf_sym_addr(TCCState *s, const char *name, int err)
162 int sym_index;
163 ElfW(Sym) *sym;
165 sym_index = find_elf_sym(s->symtab, name);
166 sym = &((ElfW(Sym) *)s->symtab->data)[sym_index];
167 if (!sym_index || sym->st_shndx == SHN_UNDEF) {
168 if (err)
169 tcc_error("%s not defined", name);
170 return NULL;
172 return (void*)(uplong)sym->st_value;
175 /* return elf symbol value */
176 LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
178 return get_elf_sym_addr(s, name, 0);
181 /* return elf symbol value or error */
182 ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name)
184 return get_elf_sym_addr(s, name, 1);
187 /* add an elf symbol : check if it is already defined and patch
188 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
189 ST_FUNC int add_elf_sym(Section *s, uplong value, unsigned long size,
190 int info, int other, int sh_num, const char *name)
192 ElfW(Sym) *esym;
193 int sym_bind, sym_index, sym_type, esym_bind;
194 unsigned char sym_vis, esym_vis, new_vis;
196 sym_bind = ELFW(ST_BIND)(info);
197 sym_type = ELFW(ST_TYPE)(info);
198 sym_vis = ELFW(ST_VISIBILITY)(other);
200 if (sym_bind != STB_LOCAL) {
201 /* we search global or weak symbols */
202 sym_index = find_elf_sym(s, name);
203 if (!sym_index)
204 goto do_def;
205 esym = &((ElfW(Sym) *)s->data)[sym_index];
206 if (esym->st_shndx != SHN_UNDEF) {
207 esym_bind = ELFW(ST_BIND)(esym->st_info);
208 /* propagate the most constraining visibility */
209 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
210 esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
211 if (esym_vis == STV_DEFAULT) {
212 new_vis = sym_vis;
213 } else if (sym_vis == STV_DEFAULT) {
214 new_vis = esym_vis;
215 } else {
216 new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
218 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
219 | new_vis;
220 other = esym->st_other; /* in case we have to patch esym */
221 if (sh_num == SHN_UNDEF) {
222 /* ignore adding of undefined symbol if the
223 corresponding symbol is already defined */
224 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
225 /* global overrides weak, so patch */
226 goto do_patch;
227 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
228 /* weak is ignored if already global */
229 } else if (sym_bind == STB_WEAK && esym_bind == STB_WEAK) {
230 /* keep first-found weak definition, ignore subsequents */
231 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
232 /* ignore hidden symbols after */
233 } else if (esym->st_shndx == SHN_COMMON
234 && (sh_num < SHN_LORESERVE || sh_num == SHN_COMMON)) {
235 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
236 No idea if this is the correct solution ... */
237 goto do_patch;
238 } else if (s == tcc_state->dynsymtab_section) {
239 /* we accept that two DLL define the same symbol */
240 } else {
241 #if 1
242 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
243 sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
244 #endif
245 tcc_error_noabort("'%s' defined twice", name);
247 } else {
248 do_patch:
249 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
250 esym->st_shndx = sh_num;
251 new_undef_sym = 1;
252 esym->st_value = value;
253 esym->st_size = size;
254 esym->st_other = other;
256 } else {
257 do_def:
258 sym_index = put_elf_sym(s, value, size,
259 ELFW(ST_INFO)(sym_bind, sym_type), other,
260 sh_num, name);
262 return sym_index;
265 /* put relocation */
266 ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
267 int type, int symbol)
269 char buf[256];
270 Section *sr;
271 ElfW_Rel *rel;
273 sr = s->reloc;
274 if (!sr) {
275 /* if no relocation section, create it */
276 snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
277 /* if the symtab is allocated, then we consider the relocation
278 are also */
279 sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
280 sr->sh_entsize = sizeof(ElfW_Rel);
281 sr->link = symtab;
282 sr->sh_info = s->sh_num;
283 s->reloc = sr;
285 rel = section_ptr_add(sr, sizeof(ElfW_Rel));
286 rel->r_offset = offset;
287 rel->r_info = ELFW(R_INFO)(symbol, type);
288 #ifdef TCC_TARGET_X86_64
289 rel->r_addend = 0;
290 #endif
293 /* put stab debug information */
295 ST_FUNC void put_stabs(const char *str, int type, int other, int desc,
296 unsigned long value)
298 Stab_Sym *sym;
300 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
301 if (str) {
302 sym->n_strx = put_elf_str(stabstr_section, str);
303 } else {
304 sym->n_strx = 0;
306 sym->n_type = type;
307 sym->n_other = other;
308 sym->n_desc = desc;
309 sym->n_value = value;
312 ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc,
313 unsigned long value, Section *sec, int sym_index)
315 put_stabs(str, type, other, desc, value);
316 put_elf_reloc(symtab_section, stab_section,
317 stab_section->data_offset - sizeof(unsigned int),
318 R_DATA_32, sym_index);
321 ST_FUNC void put_stabn(int type, int other, int desc, int value)
323 put_stabs(NULL, type, other, desc, value);
326 ST_FUNC void put_stabd(int type, int other, int desc)
328 put_stabs(NULL, type, other, desc, 0);
331 /* In an ELF file symbol table, the local symbols must appear below
332 the global and weak ones. Since TCC cannot sort it while generating
333 the code, we must do it after. All the relocation tables are also
334 modified to take into account the symbol table sorting */
335 static void sort_syms(TCCState *s1, Section *s)
337 int *old_to_new_syms;
338 ElfW(Sym) *new_syms;
339 int nb_syms, i;
340 ElfW(Sym) *p, *q;
341 ElfW_Rel *rel, *rel_end;
342 Section *sr;
343 int type, sym_index;
345 nb_syms = s->data_offset / sizeof(ElfW(Sym));
346 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
347 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
349 /* first pass for local symbols */
350 p = (ElfW(Sym) *)s->data;
351 q = new_syms;
352 for(i = 0; i < nb_syms; i++) {
353 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
354 old_to_new_syms[i] = q - new_syms;
355 *q++ = *p;
357 p++;
359 /* save the number of local symbols in section header */
360 s->sh_info = q - new_syms;
362 /* then second pass for non local symbols */
363 p = (ElfW(Sym) *)s->data;
364 for(i = 0; i < nb_syms; i++) {
365 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
366 old_to_new_syms[i] = q - new_syms;
367 *q++ = *p;
369 p++;
372 /* we copy the new symbols to the old */
373 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
374 tcc_free(new_syms);
376 /* now we modify all the relocations */
377 for(i = 1; i < s1->nb_sections; i++) {
378 sr = s1->sections[i];
379 if (sr->sh_type == SHT_RELX && sr->link == s) {
380 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
381 for(rel = (ElfW_Rel *)sr->data;
382 rel < rel_end;
383 rel++) {
384 sym_index = ELFW(R_SYM)(rel->r_info);
385 type = ELFW(R_TYPE)(rel->r_info);
386 sym_index = old_to_new_syms[sym_index];
387 rel->r_info = ELFW(R_INFO)(sym_index, type);
392 tcc_free(old_to_new_syms);
395 /* relocate common symbols in the .bss section */
396 ST_FUNC void relocate_common_syms(void)
398 ElfW(Sym) *sym, *sym_end;
399 unsigned long offset, align;
401 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
402 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
403 sym < sym_end;
404 sym++) {
405 if (sym->st_shndx == SHN_COMMON) {
406 /* align symbol */
407 align = sym->st_value;
408 offset = bss_section->data_offset;
409 offset = (offset + align - 1) & -align;
410 sym->st_value = offset;
411 sym->st_shndx = bss_section->sh_num;
412 offset += sym->st_size;
413 bss_section->data_offset = offset;
418 /* relocate symbol table, resolve undefined symbols if do_resolve is
419 true and output error if undefined symbol. */
420 ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
422 ElfW(Sym) *sym, *esym, *sym_end;
423 int sym_bind, sh_num, sym_index;
424 const char *name;
426 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
427 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
428 sym < sym_end;
429 sym++) {
430 sh_num = sym->st_shndx;
431 if (sh_num == SHN_UNDEF) {
432 name = strtab_section->data + sym->st_name;
433 if (do_resolve) {
434 #if !defined TCC_TARGET_PE || !defined _WIN32
435 void *addr;
436 name = symtab_section->link->data + sym->st_name;
437 addr = resolve_sym(s1, name);
438 if (addr) {
439 sym->st_value = (uplong)addr;
440 goto found;
442 #endif
443 } else if (s1->dynsym) {
444 /* if dynamic symbol exist, then use it */
445 sym_index = find_elf_sym(s1->dynsym, name);
446 if (sym_index) {
447 esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
448 sym->st_value = esym->st_value;
449 goto found;
452 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
453 it */
454 if (!strcmp(name, "_fp_hw"))
455 goto found;
456 /* only weak symbols are accepted to be undefined. Their
457 value is zero */
458 sym_bind = ELFW(ST_BIND)(sym->st_info);
459 if (sym_bind == STB_WEAK) {
460 sym->st_value = 0;
461 } else {
462 tcc_error_noabort("undefined symbol '%s'", name);
464 } else if (sh_num < SHN_LORESERVE) {
465 /* add section base */
466 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
468 found: ;
472 #ifndef TCC_TARGET_PE
473 #ifdef TCC_TARGET_X86_64
474 #define JMP_TABLE_ENTRY_SIZE 14
475 static uplong add_jmp_table(TCCState *s1, uplong val)
477 char *p = s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset;
478 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
479 /* jmp *0x0(%rip) */
480 p[0] = 0xff;
481 p[1] = 0x25;
482 *(int *)(p + 2) = 0;
483 *(uplong *)(p + 6) = val;
484 return (uplong)p;
487 static uplong add_got_table(TCCState *s1, uplong val)
489 uplong *p = (uplong *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
490 s1->runtime_plt_and_got_offset += sizeof(uplong);
491 *p = val;
492 return (uplong)p;
494 #elif defined TCC_TARGET_ARM
495 #define JMP_TABLE_ENTRY_SIZE 8
496 static uplong add_jmp_table(TCCState *s1, int val)
498 uint32_t *p = (uint32_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
499 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
500 /* ldr pc, [pc, #-4] */
501 p[0] = 0xE51FF004;
502 p[1] = val;
503 return (uplong)p;
505 #endif
506 #endif
508 /* relocate a given section (CPU dependent) */
509 ST_FUNC void relocate_section(TCCState *s1, Section *s)
511 Section *sr;
512 ElfW_Rel *rel, *rel_end, *qrel;
513 ElfW(Sym) *sym;
514 int type, sym_index;
515 unsigned char *ptr;
516 uplong val, addr;
517 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
518 int esym_index;
519 #endif
521 sr = s->reloc;
522 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
523 qrel = (ElfW_Rel *)sr->data;
524 for(rel = qrel;
525 rel < rel_end;
526 rel++) {
527 ptr = s->data + rel->r_offset;
529 sym_index = ELFW(R_SYM)(rel->r_info);
530 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
531 val = sym->st_value;
532 #ifdef TCC_TARGET_X86_64
533 val += rel->r_addend;
534 #endif
535 type = ELFW(R_TYPE)(rel->r_info);
536 addr = s->sh_addr + rel->r_offset;
538 /* CPU specific */
539 switch(type) {
540 #if defined(TCC_TARGET_I386)
541 case R_386_32:
542 if (s1->output_type == TCC_OUTPUT_DLL) {
543 esym_index = s1->symtab_to_dynsym[sym_index];
544 qrel->r_offset = rel->r_offset;
545 if (esym_index) {
546 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
547 qrel++;
548 break;
549 } else {
550 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
551 qrel++;
554 *(int *)ptr += val;
555 break;
556 case R_386_PC32:
557 if (s1->output_type == TCC_OUTPUT_DLL) {
558 /* DLL relocation */
559 esym_index = s1->symtab_to_dynsym[sym_index];
560 if (esym_index) {
561 qrel->r_offset = rel->r_offset;
562 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
563 qrel++;
564 break;
567 *(int *)ptr += val - addr;
568 break;
569 case R_386_PLT32:
570 *(int *)ptr += val - addr;
571 break;
572 case R_386_GLOB_DAT:
573 case R_386_JMP_SLOT:
574 *(int *)ptr = val;
575 break;
576 case R_386_GOTPC:
577 *(int *)ptr += s1->got->sh_addr - addr;
578 break;
579 case R_386_GOTOFF:
580 *(int *)ptr += val - s1->got->sh_addr;
581 break;
582 case R_386_GOT32:
583 /* we load the got offset */
584 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
585 break;
586 case R_386_16:
587 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
588 output_file:
589 tcc_error("can only produce 16-bit binary files");
591 *(short *)ptr += val;
592 break;
593 case R_386_PC16:
594 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
595 goto output_file;
596 *(short *)ptr += val - addr;
597 break;
598 #elif defined(TCC_TARGET_ARM)
599 case R_ARM_PC24:
600 case R_ARM_CALL:
601 case R_ARM_JUMP24:
602 case R_ARM_PLT32:
604 int x, is_thumb, is_call, h, blx_avail;
605 x = (*(int *)ptr)&0xffffff;
606 (*(int *)ptr) &= 0xff000000;
607 if (x & 0x800000)
608 x -= 0x1000000;
609 x <<= 2;
610 blx_avail = (TCC_ARM_VERSION >= 5);
611 is_thumb = val & 1;
612 is_call = (type == R_ARM_CALL);
613 x += val - addr;
614 h = x & 2;
615 #ifndef TCC_TARGET_PE
616 if ((x & 3) || x >= 0x2000000 || x < -0x2000000)
617 if (!(x & 3) || !blx_avail || !is_call)
618 if (s1->output_type == TCC_OUTPUT_MEMORY) {
619 x += add_jmp_table(s1, val) - val; /* add veneer */
620 is_thumb = 0; /* Veneer uses ARM instructions */
622 #endif
623 if ((x & 3) || x >= 0x2000000 || x < -0x2000000)
624 if (!(x & 3) || !blx_avail || !is_call)
625 tcc_error("can't relocate value at %x",addr);
626 x >>= 2;
627 x &= 0xffffff;
628 /* Only reached if blx is avail and it is a call */
629 if (is_thumb) {
630 x |= h << 24;
631 (*(int *)ptr) = 0xfa << 24; /* bl -> blx */
633 (*(int *)ptr) |= x;
635 break;
636 /* Since these relocations only concern Thumb-2 and blx instruction was
637 introduced before Thumb-2, we can assume blx is available and not
638 guard its use */
639 case R_ARM_THM_CALL:
640 case R_ARM_THM_JUMP24:
642 int x, hi, lo, s, j1, j2, i1, i2, imm10, imm11;
643 int to_thumb, is_call, to_plt, blx_bit = 1 << 12;
644 Section *plt;
646 /* weak reference */
647 if (sym->st_shndx == SHN_UNDEF &&
648 ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
649 break;
651 /* Get initial offset */
652 hi = (*(uint16_t *)ptr);
653 lo = (*(uint16_t *)(ptr+2));
654 s = (hi >> 10) & 1;
655 j1 = (lo >> 13) & 1;
656 j2 = (lo >> 11) & 1;
657 i1 = (j1 ^ s) ^ 1;
658 i2 = (j2 ^ s) ^ 1;
659 imm10 = hi & 0x3ff;
660 imm11 = lo & 0x7ff;
661 x = (s << 24) | (i1 << 23) | (i2 << 22) |
662 (imm10 << 12) | (imm11 << 1);
663 if (x & 0x01000000)
664 x -= 0x02000000;
666 /* Relocation infos */
667 to_thumb = val & 1;
668 plt = s1->plt;
669 to_plt = (val >= plt->sh_addr) &&
670 (val < plt->sh_addr + plt->data_offset);
671 is_call = (type == R_ARM_THM_CALL);
673 /* Compute final offset */
674 if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */
675 x -= 4;
676 x += val - addr;
677 if (!to_thumb && is_call) {
678 blx_bit = 0; /* bl -> blx */
679 x = (x + 3) & -4; /* Compute offset from aligned PC */
682 /* Check that relocation is possible
683 * offset must not be out of range
684 * if target is to be entered in arm mode:
685 - bit 1 must not set
686 - instruction must be a call (bl) or a jump to PLT */
687 if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
688 if (to_thumb || (val & 2) || (!is_call && !to_plt))
689 tcc_error("can't relocate value at %x",addr);
691 /* Compute and store final offset */
692 s = (x >> 24) & 1;
693 i1 = (x >> 23) & 1;
694 i2 = (x >> 22) & 1;
695 j1 = s ^ (i1 ^ 1);
696 j2 = s ^ (i2 ^ 1);
697 imm10 = (x >> 12) & 0x3ff;
698 imm11 = (x >> 1) & 0x7ff;
699 (*(uint16_t *)ptr) = (uint16_t) ((hi & 0xf800) |
700 (s << 10) | imm10);
701 (*(uint16_t *)(ptr+2)) = (uint16_t) ((lo & 0xc000) |
702 (j1 << 13) | blx_bit | (j2 << 11) |
703 imm11);
705 break;
706 case R_ARM_MOVT_ABS:
707 case R_ARM_MOVW_ABS_NC:
709 int x, imm4, imm12;
710 if (type == R_ARM_MOVT_ABS)
711 val >>= 16;
712 imm12 = val & 0xfff;
713 imm4 = (val >> 12) & 0xf;
714 x = (imm4 << 16) | imm12;
715 if (type == R_ARM_THM_MOVT_ABS)
716 *(int *)ptr |= x;
717 else
718 *(int *)ptr += x;
720 break;
721 case R_ARM_THM_MOVT_ABS:
722 case R_ARM_THM_MOVW_ABS_NC:
724 int x, i, imm4, imm3, imm8;
725 if (type == R_ARM_THM_MOVT_ABS)
726 val >>= 16;
727 imm8 = val & 0xff;
728 imm3 = (val >> 8) & 0x7;
729 i = (val >> 11) & 1;
730 imm4 = (val >> 12) & 0xf;
731 x = (imm3 << 28) | (imm8 << 16) | (i << 10) | imm4;
732 if (type == R_ARM_THM_MOVT_ABS)
733 *(int *)ptr |= x;
734 else
735 *(int *)ptr += x;
737 break;
738 case R_ARM_PREL31:
740 int x;
741 x = (*(int *)ptr) & 0x7fffffff;
742 (*(int *)ptr) &= 0x80000000;
743 x = (x * 2) / 2;
744 x += val - addr;
745 if((x^(x>>1))&0x40000000)
746 tcc_error("can't relocate value at %x",addr);
747 (*(int *)ptr) |= x & 0x7fffffff;
749 case R_ARM_ABS32:
750 *(int *)ptr += val;
751 break;
752 case R_ARM_REL32:
753 *(int *)ptr += val - addr;
754 break;
755 case R_ARM_BASE_PREL:
756 *(int *)ptr += s1->got->sh_addr - addr;
757 break;
758 case R_ARM_GOTOFF32:
759 *(int *)ptr += val - s1->got->sh_addr;
760 break;
761 case R_ARM_GOT_BREL:
762 /* we load the got offset */
763 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
764 break;
765 case R_ARM_COPY:
766 break;
767 case R_ARM_V4BX:
768 /* trade Thumb support for ARMv4 support */
769 if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
770 *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
771 break;
772 default:
773 fprintf(stderr,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
774 type, (unsigned)addr, (unsigned)(uplong)ptr, (unsigned)val);
775 break;
776 #elif defined(TCC_TARGET_C67)
777 case R_C60_32:
778 *(int *)ptr += val;
779 break;
780 case R_C60LO16:
782 uint32_t orig;
784 /* put the low 16 bits of the absolute address */
785 // add to what is already there
787 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
788 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
790 //patch both at once - assumes always in pairs Low - High
792 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
793 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
795 break;
796 case R_C60HI16:
797 break;
798 default:
799 fprintf(stderr,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
800 type, (unsigned)addr, (unsigned)(uplong)ptr, (unsigned)val);
801 break;
802 #elif defined(TCC_TARGET_X86_64)
803 case R_X86_64_64:
804 if (s1->output_type == TCC_OUTPUT_DLL) {
805 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
806 qrel->r_addend = *(long long *)ptr + val;
807 qrel++;
809 *(long long *)ptr += val;
810 break;
811 case R_X86_64_32:
812 case R_X86_64_32S:
813 if (s1->output_type == TCC_OUTPUT_DLL) {
814 /* XXX: this logic may depend on TCC's codegen
815 now TCC uses R_X86_64_32 even for a 64bit pointer */
816 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
817 qrel->r_addend = *(int *)ptr + val;
818 qrel++;
820 *(int *)ptr += val;
821 break;
823 case R_X86_64_PC32:
824 if (s1->output_type == TCC_OUTPUT_DLL) {
825 /* DLL relocation */
826 esym_index = s1->symtab_to_dynsym[sym_index];
827 if (esym_index) {
828 qrel->r_offset = rel->r_offset;
829 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
830 qrel->r_addend = *(int *)ptr;
831 qrel++;
832 break;
835 /* fall through */
836 case R_X86_64_PLT32: {
837 long long diff;
838 diff = (long long)val - addr;
839 if (diff <= -2147483647 || diff > 2147483647) {
840 #ifndef TCC_TARGET_PE
841 /* XXX: naive support for over 32bit jump */
842 if (s1->output_type == TCC_OUTPUT_MEMORY) {
843 val = (add_jmp_table(s1, val - rel->r_addend) +
844 rel->r_addend);
845 diff = val - addr;
847 #endif
848 if (diff <= -2147483647 || diff > 2147483647) {
849 tcc_error("internal error: relocation failed");
852 *(int *)ptr += diff;
854 break;
855 case R_X86_64_GLOB_DAT:
856 case R_X86_64_JUMP_SLOT:
857 /* They don't need addend */
858 *(int *)ptr = val - rel->r_addend;
859 break;
860 case R_X86_64_GOTPCREL:
861 #ifndef TCC_TARGET_PE
862 if (s1->output_type == TCC_OUTPUT_MEMORY) {
863 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
864 *(int *)ptr += val - addr;
865 break;
867 #endif
868 *(int *)ptr += (s1->got->sh_addr - addr +
869 s1->sym_attrs[sym_index].got_offset - 4);
870 break;
871 case R_X86_64_GOTTPOFF:
872 *(int *)ptr += val - s1->got->sh_addr;
873 break;
874 case R_X86_64_GOT32:
875 /* we load the got offset */
876 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
877 break;
878 #else
879 #error unsupported processor
880 #endif
883 /* if the relocation is allocated, we change its symbol table */
884 if (sr->sh_flags & SHF_ALLOC)
885 sr->link = s1->dynsym;
888 /* relocate relocation table in 'sr' */
889 static void relocate_rel(TCCState *s1, Section *sr)
891 Section *s;
892 ElfW_Rel *rel, *rel_end;
894 s = s1->sections[sr->sh_info];
895 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
896 for(rel = (ElfW_Rel *)sr->data;
897 rel < rel_end;
898 rel++) {
899 rel->r_offset += s->sh_addr;
903 /* count the number of dynamic relocations so that we can reserve
904 their space */
905 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
907 ElfW_Rel *rel, *rel_end;
908 int sym_index, esym_index, type, count;
910 count = 0;
911 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
912 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
913 sym_index = ELFW(R_SYM)(rel->r_info);
914 type = ELFW(R_TYPE)(rel->r_info);
915 switch(type) {
916 #if defined(TCC_TARGET_I386)
917 case R_386_32:
918 #elif defined(TCC_TARGET_X86_64)
919 case R_X86_64_32:
920 case R_X86_64_32S:
921 case R_X86_64_64:
922 #endif
923 count++;
924 break;
925 #if defined(TCC_TARGET_I386)
926 case R_386_PC32:
927 #elif defined(TCC_TARGET_X86_64)
928 case R_X86_64_PC32:
929 #endif
930 esym_index = s1->symtab_to_dynsym[sym_index];
931 if (esym_index)
932 count++;
933 break;
934 default:
935 break;
938 if (count) {
939 /* allocate the section */
940 sr->sh_flags |= SHF_ALLOC;
941 sr->sh_size = count * sizeof(ElfW_Rel);
943 return count;
946 static struct sym_attr *alloc_sym_attr(TCCState *s1, int index)
948 int n;
949 struct sym_attr *tab;
951 if (index >= s1->nb_sym_attrs) {
952 /* find immediately bigger power of 2 and reallocate array */
953 n = 1;
954 while (index >= n)
955 n *= 2;
956 tab = tcc_realloc(s1->sym_attrs, n * sizeof(*s1->sym_attrs));
957 s1->sym_attrs = tab;
958 memset(s1->sym_attrs + s1->nb_sym_attrs, 0,
959 (n - s1->nb_sym_attrs) * sizeof(*s1->sym_attrs));
960 s1->nb_sym_attrs = n;
962 return &s1->sym_attrs[index];
965 /* XXX: suppress that */
966 static void put32(unsigned char *p, uint32_t val)
968 p[0] = val;
969 p[1] = val >> 8;
970 p[2] = val >> 16;
971 p[3] = val >> 24;
974 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
975 defined(TCC_TARGET_X86_64)
976 static uint32_t get32(unsigned char *p)
978 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
980 #endif
982 static void build_got(TCCState *s1)
984 unsigned char *ptr;
986 /* if no got, then create it */
987 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
988 s1->got->sh_entsize = 4;
989 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
990 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
991 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
992 #if PTR_SIZE == 4
993 /* keep space for _DYNAMIC pointer, if present */
994 put32(ptr, 0);
995 /* two dummy got entries */
996 put32(ptr + 4, 0);
997 put32(ptr + 8, 0);
998 #else
999 /* keep space for _DYNAMIC pointer, if present */
1000 put32(ptr, 0);
1001 put32(ptr + 4, 0);
1002 /* two dummy got entries */
1003 put32(ptr + 8, 0);
1004 put32(ptr + 12, 0);
1005 put32(ptr + 16, 0);
1006 put32(ptr + 20, 0);
1007 #endif
1010 /* put a got entry corresponding to a symbol in symtab_section. 'size'
1011 and 'info' can be modifed if more precise info comes from the DLL */
1012 static void put_got_entry(TCCState *s1,
1013 int reloc_type, unsigned long size, int info,
1014 int sym_index)
1016 int index;
1017 const char *name;
1018 ElfW(Sym) *sym;
1019 unsigned long offset;
1020 int *ptr;
1022 if (!s1->got)
1023 build_got(s1);
1025 /* if a got entry already exists for that symbol, no need to add one */
1026 if (sym_index < s1->nb_sym_attrs &&
1027 s1->sym_attrs[sym_index].got_offset)
1028 return;
1030 alloc_sym_attr(s1, sym_index)->got_offset = s1->got->data_offset;
1032 if (s1->dynsym) {
1033 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1034 name = symtab_section->link->data + sym->st_name;
1035 offset = sym->st_value;
1036 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1037 if (reloc_type ==
1038 #ifdef TCC_TARGET_X86_64
1039 R_X86_64_JUMP_SLOT
1040 #else
1041 R_386_JMP_SLOT
1042 #endif
1044 Section *plt;
1045 uint8_t *p;
1046 int modrm;
1048 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1049 modrm = 0x25;
1050 #else
1051 /* if we build a DLL, we add a %ebx offset */
1052 if (s1->output_type == TCC_OUTPUT_DLL)
1053 modrm = 0xa3;
1054 else
1055 modrm = 0x25;
1056 #endif
1058 /* add a PLT entry */
1059 plt = s1->plt;
1060 if (plt->data_offset == 0) {
1061 /* first plt entry */
1062 p = section_ptr_add(plt, 16);
1063 p[0] = 0xff; /* pushl got + PTR_SIZE */
1064 p[1] = modrm + 0x10;
1065 put32(p + 2, PTR_SIZE);
1066 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1067 p[7] = modrm;
1068 put32(p + 8, PTR_SIZE * 2);
1071 p = section_ptr_add(plt, 16);
1072 p[0] = 0xff; /* jmp *(got + x) */
1073 p[1] = modrm;
1074 put32(p + 2, s1->got->data_offset);
1075 p[6] = 0x68; /* push $xxx */
1076 put32(p + 7, (plt->data_offset - 32) >> 1);
1077 p[11] = 0xe9; /* jmp plt_start */
1078 put32(p + 12, -(plt->data_offset));
1080 /* the symbol is modified so that it will be relocated to
1081 the PLT */
1082 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
1083 if (s1->output_type == TCC_OUTPUT_EXE)
1084 #endif
1085 offset = plt->data_offset - 16;
1087 #elif defined(TCC_TARGET_ARM)
1088 if (reloc_type == R_ARM_JUMP_SLOT) {
1089 Section *plt;
1090 uint8_t *p;
1092 /* if we build a DLL, we add a %ebx offset */
1093 if (s1->output_type == TCC_OUTPUT_DLL)
1094 tcc_error("DLLs unimplemented!");
1096 /* add a PLT entry */
1097 plt = s1->plt;
1098 if (plt->data_offset == 0) {
1099 /* first plt entry */
1100 p = section_ptr_add(plt, 16);
1101 put32(p , 0xe52de004);
1102 put32(p + 4, 0xe59fe010);
1103 put32(p + 8, 0xe08fe00e);
1104 put32(p + 12, 0xe5bef008);
1107 if (s1->sym_attrs[sym_index].plt_thumb_stub) {
1108 p = section_ptr_add(plt, 20);
1109 put32(p , 0x4778); // bx pc
1110 put32(p+2, 0x46c0); // nop
1111 p += 4;
1112 } else
1113 p = section_ptr_add(plt, 16);
1114 put32(p , 0xe59fc004); // ldr ip, [pc, #4] // offset in GOT
1115 put32(p+4, 0xe08fc00c); // add ip, pc, ip // absolute address or offset
1116 put32(p+8, 0xe59cf000); // ldr pc, [ip] // load absolute address or load offset
1117 put32(p+12, s1->got->data_offset);
1119 /* the symbol is modified so that it will be relocated to
1120 the PLT */
1121 if (s1->output_type == TCC_OUTPUT_EXE)
1122 offset = plt->data_offset - 16;
1124 #elif defined(TCC_TARGET_C67)
1125 tcc_error("C67 got not implemented");
1126 #else
1127 #error unsupported CPU
1128 #endif
1129 index = put_elf_sym(s1->dynsym, offset,
1130 size, info, 0, sym->st_shndx, name);
1131 /* put a got entry */
1132 put_elf_reloc(s1->dynsym, s1->got,
1133 s1->got->data_offset,
1134 reloc_type, index);
1136 ptr = section_ptr_add(s1->got, PTR_SIZE);
1137 *ptr = 0;
1140 /* build GOT and PLT entries */
1141 ST_FUNC void build_got_entries(TCCState *s1)
1143 Section *s;
1144 ElfW_Rel *rel, *rel_end;
1145 ElfW(Sym) *sym;
1146 int i, type, reloc_type, sym_index;
1148 for(i = 1; i < s1->nb_sections; i++) {
1149 s = s1->sections[i];
1150 if (s->sh_type != SHT_RELX)
1151 continue;
1152 /* no need to handle got relocations */
1153 if (s->link != symtab_section)
1154 continue;
1155 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1156 for(rel = (ElfW_Rel *)s->data;
1157 rel < rel_end;
1158 rel++) {
1159 type = ELFW(R_TYPE)(rel->r_info);
1160 switch(type) {
1161 #if defined(TCC_TARGET_I386)
1162 case R_386_GOT32:
1163 case R_386_GOTOFF:
1164 case R_386_GOTPC:
1165 case R_386_PLT32:
1166 if (!s1->got)
1167 build_got(s1);
1168 if (type == R_386_GOT32 || type == R_386_PLT32) {
1169 sym_index = ELFW(R_SYM)(rel->r_info);
1170 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1171 /* look at the symbol got offset. If none, then add one */
1172 if (type == R_386_GOT32)
1173 reloc_type = R_386_GLOB_DAT;
1174 else
1175 reloc_type = R_386_JMP_SLOT;
1176 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1177 sym_index);
1179 break;
1180 #elif defined(TCC_TARGET_ARM)
1181 case R_ARM_GOT_BREL:
1182 case R_ARM_GOTOFF32:
1183 case R_ARM_BASE_PREL:
1184 case R_ARM_PLT32:
1185 if (!s1->got)
1186 build_got(s1);
1187 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1188 sym_index = ELFW(R_SYM)(rel->r_info);
1189 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1190 /* look at the symbol got offset. If none, then add one */
1191 if (type == R_ARM_GOT_BREL)
1192 reloc_type = R_ARM_GLOB_DAT;
1193 else
1194 reloc_type = R_ARM_JUMP_SLOT;
1195 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1196 sym_index);
1198 break;
1199 #elif defined(TCC_TARGET_C67)
1200 case R_C60_GOT32:
1201 case R_C60_GOTOFF:
1202 case R_C60_GOTPC:
1203 case R_C60_PLT32:
1204 if (!s1->got)
1205 build_got(s1);
1206 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1207 sym_index = ELFW(R_SYM)(rel->r_info);
1208 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1209 /* look at the symbol got offset. If none, then add one */
1210 if (type == R_C60_GOT32)
1211 reloc_type = R_C60_GLOB_DAT;
1212 else
1213 reloc_type = R_C60_JMP_SLOT;
1214 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1215 sym_index);
1217 break;
1218 #elif defined(TCC_TARGET_X86_64)
1219 case R_X86_64_GOT32:
1220 case R_X86_64_GOTTPOFF:
1221 case R_X86_64_GOTPCREL:
1222 case R_X86_64_PLT32:
1223 if (!s1->got)
1224 build_got(s1);
1225 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1226 type == R_X86_64_PLT32) {
1227 sym_index = ELFW(R_SYM)(rel->r_info);
1228 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1229 /* look at the symbol got offset. If none, then add one */
1230 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1231 reloc_type = R_X86_64_GLOB_DAT;
1232 else
1233 reloc_type = R_X86_64_JUMP_SLOT;
1234 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1235 sym_index);
1237 break;
1238 #else
1239 #error unsupported CPU
1240 #endif
1241 default:
1242 break;
1248 ST_FUNC Section *new_symtab(TCCState *s1,
1249 const char *symtab_name, int sh_type, int sh_flags,
1250 const char *strtab_name,
1251 const char *hash_name, int hash_sh_flags)
1253 Section *symtab, *strtab, *hash;
1254 int *ptr, nb_buckets;
1256 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1257 symtab->sh_entsize = sizeof(ElfW(Sym));
1258 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1259 put_elf_str(strtab, "");
1260 symtab->link = strtab;
1261 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1263 nb_buckets = 1;
1265 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1266 hash->sh_entsize = sizeof(int);
1267 symtab->hash = hash;
1268 hash->link = symtab;
1270 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1271 ptr[0] = nb_buckets;
1272 ptr[1] = 1;
1273 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1274 return symtab;
1277 /* put dynamic tag */
1278 static void put_dt(Section *dynamic, int dt, uplong val)
1280 ElfW(Dyn) *dyn;
1281 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1282 dyn->d_tag = dt;
1283 dyn->d_un.d_val = val;
1286 static void add_init_array_defines(TCCState *s1, const char *section_name)
1288 Section *s;
1289 long end_offset;
1290 char sym_start[1024];
1291 char sym_end[1024];
1293 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1294 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1296 s = find_section(s1, section_name);
1297 if (!s) {
1298 end_offset = 0;
1299 s = data_section;
1300 } else {
1301 end_offset = s->data_offset;
1304 add_elf_sym(symtab_section,
1305 0, 0,
1306 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1307 s->sh_num, sym_start);
1308 add_elf_sym(symtab_section,
1309 end_offset, 0,
1310 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1311 s->sh_num, sym_end);
1314 static int tcc_add_support(TCCState *s1, const char *filename)
1316 char buf[1024];
1317 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, filename);
1318 return tcc_add_file(s1, buf);
1321 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1323 #ifdef CONFIG_TCC_BCHECK
1324 unsigned long *ptr;
1325 Section *init_section;
1326 unsigned char *pinit;
1327 int sym_index;
1329 if (0 == s1->do_bounds_check)
1330 return;
1332 /* XXX: add an object file to do that */
1333 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1334 *ptr = 0;
1335 add_elf_sym(symtab_section, 0, 0,
1336 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1337 bounds_section->sh_num, "__bounds_start");
1338 /* add bound check code */
1339 #ifndef TCC_TARGET_PE
1340 tcc_add_support(s1, "bcheck.o");
1341 #endif
1342 #ifdef TCC_TARGET_I386
1343 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1344 /* add 'call __bound_init()' in .init section */
1345 init_section = find_section(s1, ".init");
1346 pinit = section_ptr_add(init_section, 5);
1347 pinit[0] = 0xe8;
1348 put32(pinit + 1, -4);
1349 sym_index = find_elf_sym(symtab_section, "__bound_init");
1350 put_elf_reloc(symtab_section, init_section,
1351 init_section->data_offset - 4, R_386_PC32, sym_index);
1353 #endif
1354 #endif
1357 /* add tcc runtime libraries */
1358 ST_FUNC void tcc_add_runtime(TCCState *s1)
1360 tcc_add_bcheck(s1);
1362 /* add libc */
1363 if (!s1->nostdlib) {
1364 tcc_add_library(s1, "c");
1365 #ifdef CONFIG_USE_LIBGCC
1366 tcc_add_file(s1, TCC_LIBGCC);
1367 #elif !defined WITHOUT_LIBTCC
1368 tcc_add_support(s1, "libtcc1.a");
1369 #endif
1370 /* add crt end if not memory output */
1371 if (s1->output_type != TCC_OUTPUT_MEMORY)
1372 tcc_add_crt(s1, "crtn.o");
1376 /* add various standard linker symbols (must be done after the
1377 sections are filled (for example after allocating common
1378 symbols)) */
1379 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1381 char buf[1024];
1382 int i;
1383 Section *s;
1385 add_elf_sym(symtab_section,
1386 text_section->data_offset, 0,
1387 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1388 text_section->sh_num, "_etext");
1389 add_elf_sym(symtab_section,
1390 data_section->data_offset, 0,
1391 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1392 data_section->sh_num, "_edata");
1393 add_elf_sym(symtab_section,
1394 bss_section->data_offset, 0,
1395 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1396 bss_section->sh_num, "_end");
1397 /* horrible new standard ldscript defines */
1398 add_init_array_defines(s1, ".preinit_array");
1399 add_init_array_defines(s1, ".init_array");
1400 add_init_array_defines(s1, ".fini_array");
1402 /* add start and stop symbols for sections whose name can be
1403 expressed in C */
1404 for(i = 1; i < s1->nb_sections; i++) {
1405 s = s1->sections[i];
1406 if (s->sh_type == SHT_PROGBITS &&
1407 (s->sh_flags & SHF_ALLOC)) {
1408 const char *p;
1409 int ch;
1411 /* check if section name can be expressed in C */
1412 p = s->name;
1413 for(;;) {
1414 ch = *p;
1415 if (!ch)
1416 break;
1417 if (!isid(ch) && !isnum(ch))
1418 goto next_sec;
1419 p++;
1421 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1422 add_elf_sym(symtab_section,
1423 0, 0,
1424 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1425 s->sh_num, buf);
1426 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1427 add_elf_sym(symtab_section,
1428 s->data_offset, 0,
1429 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1430 s->sh_num, buf);
1432 next_sec: ;
1436 static void tcc_output_binary(TCCState *s1, FILE *f,
1437 const int *section_order)
1439 Section *s;
1440 int i, offset, size;
1442 offset = 0;
1443 for(i=1;i<s1->nb_sections;i++) {
1444 s = s1->sections[section_order[i]];
1445 if (s->sh_type != SHT_NOBITS &&
1446 (s->sh_flags & SHF_ALLOC)) {
1447 while (offset < s->sh_offset) {
1448 fputc(0, f);
1449 offset++;
1451 size = s->sh_size;
1452 fwrite(s->data, 1, size, f);
1453 offset += size;
1458 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1459 #define HAVE_PHDR 1
1460 #define EXTRA_RELITEMS 14
1462 /* move the relocation value from .dynsym to .got */
1463 void patch_dynsym_undef(TCCState *s1, Section *s)
1465 uint32_t *gotd = (void *)s1->got->data;
1466 ElfW(Sym) *sym, *sym_end;
1468 gotd += 3; // dummy entries in .got
1469 /* relocate symbols in .dynsym */
1470 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1471 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1472 if (sym->st_shndx == SHN_UNDEF) {
1473 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1474 sym->st_value = 0;
1478 #else
1479 #define HAVE_PHDR 0
1480 #define EXTRA_RELITEMS 9
1482 /* zero plt offsets of weak symbols in .dynsym */
1483 void patch_dynsym_undef(TCCState *s1, Section *s)
1485 ElfW(Sym) *sym, *sym_end;
1487 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1488 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++)
1489 if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
1490 sym->st_value = 0;
1492 #endif
1494 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1496 int sym_index = ELFW(R_SYM) (rel->r_info);
1497 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1498 unsigned long offset;
1500 if (sym_index >= s1->nb_sym_attrs)
1501 return;
1502 offset = s1->sym_attrs[sym_index].got_offset;
1503 section_reserve(s1->got, offset + PTR_SIZE);
1504 #ifdef TCC_TARGET_X86_64
1505 /* only works for x86-64 */
1506 put32(s1->got->data + offset + 4, sym->st_value >> 32);
1507 #endif
1508 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1511 ST_FUNC void fill_got(TCCState *s1)
1513 Section *s;
1514 ElfW_Rel *rel, *rel_end;
1515 int i;
1517 for(i = 1; i < s1->nb_sections; i++) {
1518 s = s1->sections[i];
1519 if (s->sh_type != SHT_RELX)
1520 continue;
1521 /* no need to handle got relocations */
1522 if (s->link != symtab_section)
1523 continue;
1524 rel_end = (ElfW_Rel *) (s->data + s->data_offset);
1525 for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
1526 switch (ELFW(R_TYPE) (rel->r_info)) {
1527 case R_X86_64_GOT32:
1528 case R_X86_64_GOTPCREL:
1529 case R_X86_64_PLT32:
1530 fill_got_entry(s1, rel);
1531 break;
1538 /* output an ELF file */
1539 /* XXX: suppress unneeded sections */
1540 static int elf_output_file(TCCState *s1, const char *filename)
1542 ElfW(Ehdr) ehdr;
1543 FILE *f;
1544 int fd, mode, ret;
1545 int *section_order;
1546 int shnum, i, phnum, file_offset, offset, size, j, sh_order_index, k;
1547 long long tmp;
1548 uplong addr;
1549 Section *strsec, *s;
1550 ElfW(Shdr) shdr, *sh;
1551 ElfW(Phdr) *phdr, *ph;
1552 Section *interp, *dynamic, *dynstr;
1553 unsigned long saved_dynamic_data_offset;
1554 ElfW(Sym) *sym;
1555 int type, file_type;
1556 uplong rel_addr, rel_size;
1557 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1558 uplong bss_addr, bss_size;
1559 #endif
1561 file_type = s1->output_type;
1562 s1->nb_errors = 0;
1564 if (file_type != TCC_OUTPUT_OBJ) {
1565 tcc_add_runtime(s1);
1568 phdr = NULL;
1569 section_order = NULL;
1570 interp = NULL;
1571 dynamic = NULL;
1572 dynstr = NULL; /* avoid warning */
1573 saved_dynamic_data_offset = 0; /* avoid warning */
1575 if (file_type != TCC_OUTPUT_OBJ) {
1576 relocate_common_syms();
1578 tcc_add_linker_symbols(s1);
1580 if (!s1->static_link) {
1581 const char *name;
1582 int sym_index, index;
1583 ElfW(Sym) *esym, *sym_end;
1585 if (file_type == TCC_OUTPUT_EXE) {
1586 char *ptr;
1587 /* allow override the dynamic loader */
1588 const char *elfint = getenv("LD_SO");
1589 if (elfint == NULL)
1590 elfint = CONFIG_TCC_ELFINTERP;
1591 /* add interpreter section only if executable */
1592 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1593 interp->sh_addralign = 1;
1594 ptr = section_ptr_add(interp, 1+strlen(elfint));
1595 strcpy(ptr, elfint);
1598 /* add dynamic symbol table */
1599 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1600 ".dynstr",
1601 ".hash", SHF_ALLOC);
1602 dynstr = s1->dynsym->link;
1604 /* add dynamic section */
1605 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1606 SHF_ALLOC | SHF_WRITE);
1607 dynamic->link = dynstr;
1608 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1610 /* add PLT */
1611 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1612 SHF_ALLOC | SHF_EXECINSTR);
1613 s1->plt->sh_entsize = 4;
1615 build_got(s1);
1617 /* scan for undefined symbols and see if they are in the
1618 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1619 is found, then we add it in the PLT. If a symbol
1620 STT_OBJECT is found, we add it in the .bss section with
1621 a suitable relocation */
1622 sym_end = (ElfW(Sym) *)(symtab_section->data +
1623 symtab_section->data_offset);
1624 if (file_type == TCC_OUTPUT_EXE) {
1625 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1626 sym < sym_end;
1627 sym++) {
1628 if (sym->st_shndx == SHN_UNDEF) {
1629 name = symtab_section->link->data + sym->st_name;
1630 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1631 if (sym_index) {
1632 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1633 type = ELFW(ST_TYPE)(esym->st_info);
1634 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1635 /* Indirect functions shall have STT_FUNC type
1636 * in executable dynsym section. Indeed, a dlsym
1637 * call following a lazy resolution would pick
1638 * the symbol value from the executable dynsym
1639 * entry which would contain the address of the
1640 * function wanted by the caller of dlsym
1641 * instead of the address of the function that
1642 * would return that address */
1643 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1644 ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC),
1645 sym - (ElfW(Sym) *)symtab_section->data);
1646 } else if (type == STT_OBJECT) {
1647 unsigned long offset;
1648 ElfW(Sym) *dynsym, *dynsym_end;
1649 offset = bss_section->data_offset;
1650 /* XXX: which alignment ? */
1651 offset = (offset + 16 - 1) & -16;
1652 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1653 esym->st_info, 0,
1654 bss_section->sh_num, name);
1655 // Ensure R_COPY works for weak symbol aliases
1656 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1657 dynsym_end = (ElfW(Sym) *)
1658 (s1->dynsymtab_section->data +
1659 s1->dynsymtab_section->data_offset);
1660 for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1661 dynsym < dynsym_end; dynsym++) {
1662 if ((dynsym->st_value == esym->st_value)
1663 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1664 char *dynname;
1665 dynname = s1->dynsymtab_section->link->data
1666 + dynsym->st_name;
1667 put_elf_sym(s1->dynsym, offset,
1668 dynsym->st_size,
1669 dynsym->st_info, 0,
1670 bss_section->sh_num,
1671 dynname);
1672 break;
1676 put_elf_reloc(s1->dynsym, bss_section,
1677 offset, R_COPY, index);
1678 offset += esym->st_size;
1679 bss_section->data_offset = offset;
1681 } else {
1682 /* STB_WEAK undefined symbols are accepted */
1683 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1684 it */
1685 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1686 !strcmp(name, "_fp_hw")) {
1687 } else {
1688 tcc_error_noabort("undefined symbol '%s'", name);
1691 } else if (s1->rdynamic &&
1692 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1693 /* if -rdynamic option, then export all non
1694 local symbols */
1695 name = symtab_section->link->data + sym->st_name;
1696 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1697 sym->st_info, 0,
1698 sym->st_shndx, name);
1702 if (s1->nb_errors)
1703 goto fail;
1705 /* now look at unresolved dynamic symbols and export
1706 corresponding symbol */
1707 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1708 s1->dynsymtab_section->data_offset);
1709 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1710 esym < sym_end;
1711 esym++) {
1712 if (esym->st_shndx == SHN_UNDEF) {
1713 name = s1->dynsymtab_section->link->data + esym->st_name;
1714 sym_index = find_elf_sym(symtab_section, name);
1715 if (sym_index) {
1716 /* XXX: avoid adding a symbol if already
1717 present because of -rdynamic ? */
1718 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1719 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1720 sym->st_info, 0,
1721 sym->st_shndx, name);
1722 } else {
1723 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1724 /* weak symbols can stay undefined */
1725 } else {
1726 tcc_warning("undefined dynamic symbol '%s'", name);
1731 } else {
1732 int nb_syms;
1733 /* shared library case : we simply export all the global symbols */
1734 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1735 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1736 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1737 sym < sym_end;
1738 sym++) {
1739 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1740 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1741 if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
1742 ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
1743 && sym->st_shndx == SHN_UNDEF) {
1744 int visibility = ELFW(ST_BIND)(sym->st_info);
1745 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1746 ELFW(ST_INFO)(visibility,STT_FUNC),
1747 sym - (ElfW(Sym) *)symtab_section->data);
1749 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1750 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1751 sym->st_info,
1752 sym - (ElfW(Sym) *)symtab_section->data);
1754 else
1755 #endif
1757 name = symtab_section->link->data + sym->st_name;
1758 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1759 sym->st_info, 0,
1760 sym->st_shndx, name);
1761 s1->symtab_to_dynsym[sym -
1762 (ElfW(Sym) *)symtab_section->data] =
1763 index;
1769 build_got_entries(s1);
1771 /* add a list of needed dlls */
1772 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1773 DLLReference *dllref = s1->loaded_dlls[i];
1774 if (dllref->level == 0)
1775 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1778 if (s1->rpath)
1779 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1781 /* XXX: currently, since we do not handle PIC code, we
1782 must relocate the readonly segments */
1783 if (file_type == TCC_OUTPUT_DLL) {
1784 if (s1->soname)
1785 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1786 put_dt(dynamic, DT_TEXTREL, 0);
1789 if (s1->symbolic)
1790 put_dt(dynamic, DT_SYMBOLIC, 0);
1792 /* add necessary space for other entries */
1793 saved_dynamic_data_offset = dynamic->data_offset;
1794 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1795 } else {
1796 /* still need to build got entries in case of static link */
1797 build_got_entries(s1);
1801 memset(&ehdr, 0, sizeof(ehdr));
1803 /* we add a section for symbols */
1804 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1805 put_elf_str(strsec, "");
1807 /* compute number of sections */
1808 shnum = s1->nb_sections;
1810 /* this array is used to reorder sections in the output file */
1811 section_order = tcc_malloc(sizeof(int) * shnum);
1812 section_order[0] = 0;
1813 sh_order_index = 1;
1815 /* compute number of program headers */
1816 switch(file_type) {
1817 default:
1818 case TCC_OUTPUT_OBJ:
1819 phnum = 0;
1820 break;
1821 case TCC_OUTPUT_EXE:
1822 if (!s1->static_link)
1823 phnum = 4 + HAVE_PHDR;
1824 else
1825 phnum = 2;
1826 break;
1827 case TCC_OUTPUT_DLL:
1828 phnum = 3;
1829 break;
1832 /* allocate strings for section names and decide if an unallocated
1833 section should be output */
1834 /* NOTE: the strsec section comes last, so its size is also
1835 correct ! */
1836 for(i = 1; i < s1->nb_sections; i++) {
1837 s = s1->sections[i];
1838 s->sh_name = put_elf_str(strsec, s->name);
1839 #if 0 //gr
1840 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1841 s->sh_flags,
1842 s->sh_type,
1843 s->sh_info,
1844 s->name,
1845 s->reloc ? s->reloc->name : "n"
1847 #endif
1848 /* when generating a DLL, we include relocations but we may
1849 patch them */
1850 if (file_type == TCC_OUTPUT_DLL &&
1851 s->sh_type == SHT_RELX &&
1852 !(s->sh_flags & SHF_ALLOC)) {
1853 /* //gr: avoid bogus relocs for empty (debug) sections */
1854 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1855 prepare_dynamic_rel(s1, s);
1856 else if (s1->do_debug)
1857 s->sh_size = s->data_offset;
1858 } else if (s1->do_debug ||
1859 file_type == TCC_OUTPUT_OBJ ||
1860 (s->sh_flags & SHF_ALLOC) ||
1861 i == (s1->nb_sections - 1)) {
1862 /* we output all sections if debug or object file */
1863 s->sh_size = s->data_offset;
1867 /* allocate program segment headers */
1868 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1870 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1871 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1872 } else {
1873 file_offset = 0;
1875 if (phnum > 0) {
1876 /* compute section to program header mapping */
1877 if (s1->has_text_addr) {
1878 int a_offset, p_offset;
1879 addr = s1->text_addr;
1880 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1881 ELF_PAGE_SIZE */
1882 a_offset = (int) (addr & (s1->section_align - 1));
1883 p_offset = file_offset & (s1->section_align - 1);
1884 if (a_offset < p_offset)
1885 a_offset += s1->section_align;
1886 file_offset += (a_offset - p_offset);
1887 } else {
1888 if (file_type == TCC_OUTPUT_DLL)
1889 addr = 0;
1890 else
1891 addr = ELF_START_ADDR;
1892 /* compute address after headers */
1893 addr += (file_offset & (s1->section_align - 1));
1896 /* dynamic relocation table information, for .dynamic section */
1897 rel_size = 0;
1898 rel_addr = 0;
1900 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1901 bss_addr = bss_size = 0;
1902 #endif
1903 /* leave one program header for the program interpreter */
1904 ph = &phdr[0];
1905 if (interp)
1906 ph += 1 + HAVE_PHDR;
1908 for(j = 0; j < 2; j++) {
1909 ph->p_type = PT_LOAD;
1910 if (j == 0)
1911 ph->p_flags = PF_R | PF_X;
1912 else
1913 ph->p_flags = PF_R | PF_W;
1914 ph->p_align = s1->section_align;
1916 /* we do the following ordering: interp, symbol tables,
1917 relocations, progbits, nobits */
1918 /* XXX: do faster and simpler sorting */
1919 for(k = 0; k < 5; k++) {
1920 for(i = 1; i < s1->nb_sections; i++) {
1921 s = s1->sections[i];
1922 /* compute if section should be included */
1923 if (j == 0) {
1924 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1925 SHF_ALLOC)
1926 continue;
1927 } else {
1928 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1929 (SHF_ALLOC | SHF_WRITE))
1930 continue;
1932 if (s == interp) {
1933 if (k != 0)
1934 continue;
1935 } else if (s->sh_type == SHT_DYNSYM ||
1936 s->sh_type == SHT_STRTAB ||
1937 s->sh_type == SHT_HASH) {
1938 if (k != 1)
1939 continue;
1940 } else if (s->sh_type == SHT_RELX) {
1941 if (k != 2)
1942 continue;
1943 } else if (s->sh_type == SHT_NOBITS) {
1944 if (k != 4)
1945 continue;
1946 } else {
1947 if (k != 3)
1948 continue;
1950 section_order[sh_order_index++] = i;
1952 /* section matches: we align it and add its size */
1953 tmp = addr;
1954 addr = (addr + s->sh_addralign - 1) &
1955 ~(s->sh_addralign - 1);
1956 file_offset += (int) ( addr - tmp );
1957 s->sh_offset = file_offset;
1958 s->sh_addr = addr;
1960 /* update program header infos */
1961 if (ph->p_offset == 0) {
1962 ph->p_offset = file_offset;
1963 ph->p_vaddr = addr;
1964 ph->p_paddr = ph->p_vaddr;
1966 /* update dynamic relocation infos */
1967 if (s->sh_type == SHT_RELX) {
1968 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1969 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1970 rel_addr = addr;
1971 rel_size += s->sh_size; // XXX only first rel.
1973 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1974 bss_addr = addr;
1975 bss_size = s->sh_size; // XXX only first rel.
1977 #else
1978 if (rel_size == 0)
1979 rel_addr = addr;
1980 rel_size += s->sh_size;
1981 #endif
1983 addr += s->sh_size;
1984 if (s->sh_type != SHT_NOBITS)
1985 file_offset += s->sh_size;
1988 ph->p_filesz = file_offset - ph->p_offset;
1989 ph->p_memsz = addr - ph->p_vaddr;
1990 ph++;
1991 if (j == 0) {
1992 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1993 /* if in the middle of a page, we duplicate the page in
1994 memory so that one copy is RX and the other is RW */
1995 if ((addr & (s1->section_align - 1)) != 0)
1996 addr += s1->section_align;
1997 } else {
1998 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1999 file_offset = (file_offset + s1->section_align - 1) &
2000 ~(s1->section_align - 1);
2005 /* if interpreter, then add corresponing program header */
2006 if (interp) {
2007 ph = &phdr[0];
2009 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2011 int len = phnum * sizeof(ElfW(Phdr));
2013 ph->p_type = PT_PHDR;
2014 ph->p_offset = sizeof(ElfW(Ehdr));
2015 ph->p_vaddr = interp->sh_addr - len;
2016 ph->p_paddr = ph->p_vaddr;
2017 ph->p_filesz = ph->p_memsz = len;
2018 ph->p_flags = PF_R | PF_X;
2019 ph->p_align = 4; // interp->sh_addralign;
2020 ph++;
2022 #endif
2024 ph->p_type = PT_INTERP;
2025 ph->p_offset = interp->sh_offset;
2026 ph->p_vaddr = interp->sh_addr;
2027 ph->p_paddr = ph->p_vaddr;
2028 ph->p_filesz = interp->sh_size;
2029 ph->p_memsz = interp->sh_size;
2030 ph->p_flags = PF_R;
2031 ph->p_align = interp->sh_addralign;
2034 /* if dynamic section, then add corresponing program header */
2035 if (dynamic) {
2036 ElfW(Sym) *sym_end;
2038 ph = &phdr[phnum - 1];
2040 ph->p_type = PT_DYNAMIC;
2041 ph->p_offset = dynamic->sh_offset;
2042 ph->p_vaddr = dynamic->sh_addr;
2043 ph->p_paddr = ph->p_vaddr;
2044 ph->p_filesz = dynamic->sh_size;
2045 ph->p_memsz = dynamic->sh_size;
2046 ph->p_flags = PF_R | PF_W;
2047 ph->p_align = dynamic->sh_addralign;
2049 /* put GOT dynamic section address */
2050 put32(s1->got->data, dynamic->sh_addr);
2052 /* relocate the PLT */
2053 if (file_type == TCC_OUTPUT_EXE
2054 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2055 || file_type == TCC_OUTPUT_DLL
2056 #endif
2058 uint8_t *p, *p_end;
2060 p = s1->plt->data;
2061 p_end = p + s1->plt->data_offset;
2062 if (p < p_end) {
2063 #if defined(TCC_TARGET_I386)
2064 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2065 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
2066 p += 16;
2067 while (p < p_end) {
2068 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2069 p += 16;
2071 #elif defined(TCC_TARGET_X86_64)
2072 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
2073 put32(p + 2, get32(p + 2) + x);
2074 put32(p + 8, get32(p + 8) + x - 6);
2075 p += 16;
2076 while (p < p_end) {
2077 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
2078 p += 16;
2080 #elif defined(TCC_TARGET_ARM)
2081 int x;
2082 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
2083 p += 16;
2084 while (p < p_end) {
2085 if (get32(p) == 0x46c04778) /* PLT Thumb stub present */
2086 p += 4;
2087 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
2088 p += 16;
2090 #elif defined(TCC_TARGET_C67)
2091 /* XXX: TODO */
2092 #else
2093 #error unsupported CPU
2094 #endif
2098 /* relocate symbols in .dynsym */
2099 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
2100 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
2101 sym < sym_end;
2102 sym++) {
2103 if (sym->st_shndx == SHN_UNDEF) {
2104 /* relocate to the PLT if the symbol corresponds
2105 to a PLT entry */
2106 if (sym->st_value)
2107 sym->st_value += s1->plt->sh_addr;
2108 } else if (sym->st_shndx < SHN_LORESERVE) {
2109 /* do symbol relocation */
2110 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
2114 /* put dynamic section entries */
2115 dynamic->data_offset = saved_dynamic_data_offset;
2116 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
2117 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
2118 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2119 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
2120 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2121 #ifdef TCC_TARGET_X86_64
2122 put_dt(dynamic, DT_RELA, rel_addr);
2123 put_dt(dynamic, DT_RELASZ, rel_size);
2124 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2125 #else
2126 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2127 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2128 put_dt(dynamic, DT_PLTRELSZ, rel_size);
2129 put_dt(dynamic, DT_JMPREL, rel_addr);
2130 put_dt(dynamic, DT_PLTREL, DT_REL);
2131 put_dt(dynamic, DT_REL, bss_addr);
2132 put_dt(dynamic, DT_RELSZ, bss_size);
2133 #else
2134 put_dt(dynamic, DT_REL, rel_addr);
2135 put_dt(dynamic, DT_RELSZ, rel_size);
2136 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2137 #endif
2138 #endif
2139 if (s1->do_debug)
2140 put_dt(dynamic, DT_DEBUG, 0);
2141 put_dt(dynamic, DT_NULL, 0);
2144 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2145 ehdr.e_phnum = phnum;
2146 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2149 /* all other sections come after */
2150 for(i = 1; i < s1->nb_sections; i++) {
2151 s = s1->sections[i];
2152 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2153 continue;
2154 section_order[sh_order_index++] = i;
2156 file_offset = (file_offset + s->sh_addralign - 1) &
2157 ~(s->sh_addralign - 1);
2158 s->sh_offset = file_offset;
2159 if (s->sh_type != SHT_NOBITS)
2160 file_offset += s->sh_size;
2163 /* if building executable or DLL, then relocate each section
2164 except the GOT which is already relocated */
2165 if (file_type != TCC_OUTPUT_OBJ) {
2166 relocate_syms(s1, 0);
2168 if (s1->nb_errors != 0) {
2169 fail:
2170 ret = -1;
2171 goto the_end;
2174 /* relocate sections */
2175 /* XXX: ignore sections with allocated relocations ? */
2176 for(i = 1; i < s1->nb_sections; i++) {
2177 s = s1->sections[i];
2178 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
2179 relocate_section(s1, s);
2182 /* relocate relocation entries if the relocation tables are
2183 allocated in the executable */
2184 for(i = 1; i < s1->nb_sections; i++) {
2185 s = s1->sections[i];
2186 if ((s->sh_flags & SHF_ALLOC) &&
2187 s->sh_type == SHT_RELX) {
2188 relocate_rel(s1, s);
2192 /* get entry point address */
2193 if (file_type == TCC_OUTPUT_EXE)
2194 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
2195 else
2196 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2198 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2199 fill_got(s1);
2201 /* write elf file */
2202 if (file_type == TCC_OUTPUT_OBJ)
2203 mode = 0666;
2204 else
2205 mode = 0777;
2206 unlink(filename);
2207 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2208 if (fd < 0) {
2209 tcc_error_noabort("could not write '%s'", filename);
2210 goto fail;
2212 f = fdopen(fd, "wb");
2213 if (s1->verbose)
2214 printf("<- %s\n", filename);
2216 #ifdef TCC_TARGET_COFF
2217 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2218 tcc_output_coff(s1, f);
2219 } else
2220 #endif
2221 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2222 sort_syms(s1, symtab_section);
2224 /* align to 4 */
2225 file_offset = (file_offset + 3) & -4;
2227 /* fill header */
2228 ehdr.e_ident[0] = ELFMAG0;
2229 ehdr.e_ident[1] = ELFMAG1;
2230 ehdr.e_ident[2] = ELFMAG2;
2231 ehdr.e_ident[3] = ELFMAG3;
2232 ehdr.e_ident[4] = ELFCLASSW;
2233 ehdr.e_ident[5] = ELFDATA2LSB;
2234 ehdr.e_ident[6] = EV_CURRENT;
2235 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2236 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2237 #endif
2238 #ifdef TCC_TARGET_ARM
2239 #ifdef TCC_ARM_EABI
2240 ehdr.e_ident[EI_OSABI] = 0;
2241 ehdr.e_flags = 4 << 24;
2242 #else
2243 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2244 #endif
2245 #endif
2246 switch(file_type) {
2247 default:
2248 case TCC_OUTPUT_EXE:
2249 ehdr.e_type = ET_EXEC;
2250 break;
2251 case TCC_OUTPUT_DLL:
2252 ehdr.e_type = ET_DYN;
2253 break;
2254 case TCC_OUTPUT_OBJ:
2255 ehdr.e_type = ET_REL;
2256 break;
2258 ehdr.e_machine = EM_TCC_TARGET;
2259 ehdr.e_version = EV_CURRENT;
2260 ehdr.e_shoff = file_offset;
2261 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2262 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2263 ehdr.e_shnum = shnum;
2264 ehdr.e_shstrndx = shnum - 1;
2266 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2267 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2268 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2270 for(i=1;i<s1->nb_sections;i++) {
2271 s = s1->sections[section_order[i]];
2272 if (s->sh_type != SHT_NOBITS) {
2273 if (s->sh_type == SHT_DYNSYM)
2274 patch_dynsym_undef(s1, s);
2275 while (offset < s->sh_offset) {
2276 fputc(0, f);
2277 offset++;
2279 size = s->sh_size;
2280 fwrite(s->data, 1, size, f);
2281 offset += size;
2285 /* output section headers */
2286 while (offset < ehdr.e_shoff) {
2287 fputc(0, f);
2288 offset++;
2291 for(i=0;i<s1->nb_sections;i++) {
2292 sh = &shdr;
2293 memset(sh, 0, sizeof(ElfW(Shdr)));
2294 s = s1->sections[i];
2295 if (s) {
2296 sh->sh_name = s->sh_name;
2297 sh->sh_type = s->sh_type;
2298 sh->sh_flags = s->sh_flags;
2299 sh->sh_entsize = s->sh_entsize;
2300 sh->sh_info = s->sh_info;
2301 if (s->link)
2302 sh->sh_link = s->link->sh_num;
2303 sh->sh_addralign = s->sh_addralign;
2304 sh->sh_addr = s->sh_addr;
2305 sh->sh_offset = s->sh_offset;
2306 sh->sh_size = s->sh_size;
2308 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2310 } else {
2311 tcc_output_binary(s1, f, section_order);
2313 fclose(f);
2315 ret = 0;
2316 the_end:
2317 tcc_free(s1->symtab_to_dynsym);
2318 tcc_free(section_order);
2319 tcc_free(phdr);
2320 tcc_free(s1->sym_attrs);
2321 return ret;
2324 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2326 int ret;
2327 #ifdef TCC_TARGET_PE
2328 if (s->output_type != TCC_OUTPUT_OBJ) {
2329 ret = pe_output_file(s, filename);
2330 } else
2331 #endif
2333 ret = elf_output_file(s, filename);
2335 return ret;
2338 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2340 void *data;
2342 data = tcc_malloc(size);
2343 lseek(fd, file_offset, SEEK_SET);
2344 read(fd, data, size);
2345 return data;
2348 typedef struct SectionMergeInfo {
2349 Section *s; /* corresponding existing section */
2350 unsigned long offset; /* offset of the new section in the existing section */
2351 uint8_t new_section; /* true if section 's' was added */
2352 uint8_t link_once; /* true if link once section */
2353 } SectionMergeInfo;
2355 /* load an object file and merge it with current files */
2356 /* XXX: handle correctly stab (debug) info */
2357 ST_FUNC int tcc_load_object_file(TCCState *s1,
2358 int fd, unsigned long file_offset)
2360 ElfW(Ehdr) ehdr;
2361 ElfW(Shdr) *shdr, *sh;
2362 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2363 unsigned char *strsec, *strtab;
2364 int *old_to_new_syms;
2365 char *sh_name, *name;
2366 SectionMergeInfo *sm_table, *sm;
2367 ElfW(Sym) *sym, *symtab;
2368 ElfW_Rel *rel, *rel_end;
2369 Section *s;
2371 int stab_index;
2372 int stabstr_index;
2374 stab_index = stabstr_index = 0;
2376 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2377 goto fail1;
2378 if (ehdr.e_ident[0] != ELFMAG0 ||
2379 ehdr.e_ident[1] != ELFMAG1 ||
2380 ehdr.e_ident[2] != ELFMAG2 ||
2381 ehdr.e_ident[3] != ELFMAG3)
2382 goto fail1;
2383 /* test if object file */
2384 if (ehdr.e_type != ET_REL)
2385 goto fail1;
2386 /* test CPU specific stuff */
2387 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2388 ehdr.e_machine != EM_TCC_TARGET) {
2389 fail1:
2390 tcc_error_noabort("invalid object file");
2391 return -1;
2393 /* read sections */
2394 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2395 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2396 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2398 /* load section names */
2399 sh = &shdr[ehdr.e_shstrndx];
2400 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2402 /* load symtab and strtab */
2403 old_to_new_syms = NULL;
2404 symtab = NULL;
2405 strtab = NULL;
2406 nb_syms = 0;
2407 for(i = 1; i < ehdr.e_shnum; i++) {
2408 sh = &shdr[i];
2409 if (sh->sh_type == SHT_SYMTAB) {
2410 if (symtab) {
2411 tcc_error_noabort("object must contain only one symtab");
2412 fail:
2413 ret = -1;
2414 goto the_end;
2416 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2417 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2418 sm_table[i].s = symtab_section;
2420 /* now load strtab */
2421 sh = &shdr[sh->sh_link];
2422 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2426 /* now examine each section and try to merge its content with the
2427 ones in memory */
2428 for(i = 1; i < ehdr.e_shnum; i++) {
2429 /* no need to examine section name strtab */
2430 if (i == ehdr.e_shstrndx)
2431 continue;
2432 sh = &shdr[i];
2433 sh_name = strsec + sh->sh_name;
2434 /* ignore sections types we do not handle */
2435 if (sh->sh_type != SHT_PROGBITS &&
2436 sh->sh_type != SHT_RELX &&
2437 #ifdef TCC_ARM_EABI
2438 sh->sh_type != SHT_ARM_EXIDX &&
2439 #endif
2440 sh->sh_type != SHT_NOBITS &&
2441 sh->sh_type != SHT_PREINIT_ARRAY &&
2442 sh->sh_type != SHT_INIT_ARRAY &&
2443 sh->sh_type != SHT_FINI_ARRAY &&
2444 strcmp(sh_name, ".stabstr")
2446 continue;
2447 if (sh->sh_addralign < 1)
2448 sh->sh_addralign = 1;
2449 /* find corresponding section, if any */
2450 for(j = 1; j < s1->nb_sections;j++) {
2451 s = s1->sections[j];
2452 if (!strcmp(s->name, sh_name)) {
2453 if (!strncmp(sh_name, ".gnu.linkonce",
2454 sizeof(".gnu.linkonce") - 1)) {
2455 /* if a 'linkonce' section is already present, we
2456 do not add it again. It is a little tricky as
2457 symbols can still be defined in
2458 it. */
2459 sm_table[i].link_once = 1;
2460 goto next;
2461 } else {
2462 goto found;
2466 /* not found: create new section */
2467 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2468 /* take as much info as possible from the section. sh_link and
2469 sh_info will be updated later */
2470 s->sh_addralign = sh->sh_addralign;
2471 s->sh_entsize = sh->sh_entsize;
2472 sm_table[i].new_section = 1;
2473 found:
2474 if (sh->sh_type != s->sh_type) {
2475 tcc_error_noabort("invalid section type");
2476 goto fail;
2479 /* align start of section */
2480 offset = s->data_offset;
2482 if (0 == strcmp(sh_name, ".stab")) {
2483 stab_index = i;
2484 goto no_align;
2486 if (0 == strcmp(sh_name, ".stabstr")) {
2487 stabstr_index = i;
2488 goto no_align;
2491 size = sh->sh_addralign - 1;
2492 offset = (offset + size) & ~size;
2493 if (sh->sh_addralign > s->sh_addralign)
2494 s->sh_addralign = sh->sh_addralign;
2495 s->data_offset = offset;
2496 no_align:
2497 sm_table[i].offset = offset;
2498 sm_table[i].s = s;
2499 /* concatenate sections */
2500 size = sh->sh_size;
2501 if (sh->sh_type != SHT_NOBITS) {
2502 unsigned char *ptr;
2503 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2504 ptr = section_ptr_add(s, size);
2505 read(fd, ptr, size);
2506 } else {
2507 s->data_offset += size;
2509 next: ;
2512 /* //gr relocate stab strings */
2513 if (stab_index && stabstr_index) {
2514 Stab_Sym *a, *b;
2515 unsigned o;
2516 s = sm_table[stab_index].s;
2517 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2518 b = (Stab_Sym *)(s->data + s->data_offset);
2519 o = sm_table[stabstr_index].offset;
2520 while (a < b)
2521 a->n_strx += o, a++;
2524 /* second short pass to update sh_link and sh_info fields of new
2525 sections */
2526 for(i = 1; i < ehdr.e_shnum; i++) {
2527 s = sm_table[i].s;
2528 if (!s || !sm_table[i].new_section)
2529 continue;
2530 sh = &shdr[i];
2531 if (sh->sh_link > 0)
2532 s->link = sm_table[sh->sh_link].s;
2533 if (sh->sh_type == SHT_RELX) {
2534 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2535 /* update backward link */
2536 s1->sections[s->sh_info]->reloc = s;
2539 sm = sm_table;
2541 /* resolve symbols */
2542 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2544 sym = symtab + 1;
2545 for(i = 1; i < nb_syms; i++, sym++) {
2546 if (sym->st_shndx != SHN_UNDEF &&
2547 sym->st_shndx < SHN_LORESERVE) {
2548 sm = &sm_table[sym->st_shndx];
2549 if (sm->link_once) {
2550 /* if a symbol is in a link once section, we use the
2551 already defined symbol. It is very important to get
2552 correct relocations */
2553 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2554 name = strtab + sym->st_name;
2555 sym_index = find_elf_sym(symtab_section, name);
2556 if (sym_index)
2557 old_to_new_syms[i] = sym_index;
2559 continue;
2561 /* if no corresponding section added, no need to add symbol */
2562 if (!sm->s)
2563 continue;
2564 /* convert section number */
2565 sym->st_shndx = sm->s->sh_num;
2566 /* offset value */
2567 sym->st_value += sm->offset;
2569 /* add symbol */
2570 name = strtab + sym->st_name;
2571 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2572 sym->st_info, sym->st_other,
2573 sym->st_shndx, name);
2574 old_to_new_syms[i] = sym_index;
2577 /* third pass to patch relocation entries */
2578 for(i = 1; i < ehdr.e_shnum; i++) {
2579 s = sm_table[i].s;
2580 if (!s)
2581 continue;
2582 sh = &shdr[i];
2583 offset = sm_table[i].offset;
2584 switch(s->sh_type) {
2585 case SHT_RELX:
2586 /* take relocation offset information */
2587 offseti = sm_table[sh->sh_info].offset;
2588 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2589 for(rel = (ElfW_Rel *)(s->data + offset);
2590 rel < rel_end;
2591 rel++) {
2592 int type;
2593 unsigned sym_index;
2594 /* convert symbol index */
2595 type = ELFW(R_TYPE)(rel->r_info);
2596 sym_index = ELFW(R_SYM)(rel->r_info);
2597 /* NOTE: only one symtab assumed */
2598 if (sym_index >= nb_syms)
2599 goto invalid_reloc;
2600 sym_index = old_to_new_syms[sym_index];
2601 /* ignore link_once in rel section. */
2602 if (!sym_index && !sm->link_once
2603 #ifdef TCC_TARGET_ARM
2604 && type != R_ARM_V4BX
2605 #endif
2607 invalid_reloc:
2608 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2609 i, strsec + sh->sh_name, rel->r_offset);
2610 goto fail;
2612 rel->r_info = ELFW(R_INFO)(sym_index, type);
2613 /* offset the relocation offset */
2614 rel->r_offset += offseti;
2615 #ifdef TCC_TARGET_ARM
2616 /* Jumps and branches from a Thumb code to a PLT entry need
2617 special handling since PLT entries are ARM code.
2618 Unconditional bl instructions referencing PLT entries are
2619 handled by converting these instructions into blx
2620 instructions. Other case of instructions referencing a PLT
2621 entry require to add a Thumb stub before the PLT entry to
2622 switch to ARM mode. We set bit 0 of the got offset of a
2623 symbol to indicate such a case. */
2624 if (type == R_ARM_THM_JUMP24)
2625 alloc_sym_attr(s1, sym_index)->plt_thumb_stub = 1;
2626 #endif
2628 break;
2629 default:
2630 break;
2634 ret = 0;
2635 the_end:
2636 tcc_free(symtab);
2637 tcc_free(strtab);
2638 tcc_free(old_to_new_syms);
2639 tcc_free(sm_table);
2640 tcc_free(strsec);
2641 tcc_free(shdr);
2642 return ret;
2645 typedef struct ArchiveHeader {
2646 char ar_name[16]; /* name of this member */
2647 char ar_date[12]; /* file mtime */
2648 char ar_uid[6]; /* owner uid; printed as decimal */
2649 char ar_gid[6]; /* owner gid; printed as decimal */
2650 char ar_mode[8]; /* file mode, printed as octal */
2651 char ar_size[10]; /* file size, printed as decimal */
2652 char ar_fmag[2]; /* should contain ARFMAG */
2653 } ArchiveHeader;
2655 static int get_be32(const uint8_t *b)
2657 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2660 /* load only the objects which resolve undefined symbols */
2661 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2663 int i, bound, nsyms, sym_index, off, ret;
2664 uint8_t *data;
2665 const char *ar_names, *p;
2666 const uint8_t *ar_index;
2667 ElfW(Sym) *sym;
2669 data = tcc_malloc(size);
2670 if (read(fd, data, size) != size)
2671 goto fail;
2672 nsyms = get_be32(data);
2673 ar_index = data + 4;
2674 ar_names = ar_index + nsyms * 4;
2676 do {
2677 bound = 0;
2678 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2679 sym_index = find_elf_sym(symtab_section, p);
2680 if(sym_index) {
2681 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2682 if(sym->st_shndx == SHN_UNDEF) {
2683 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2684 #if 0
2685 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2686 #endif
2687 ++bound;
2688 lseek(fd, off, SEEK_SET);
2689 if(tcc_load_object_file(s1, fd, off) < 0) {
2690 fail:
2691 ret = -1;
2692 goto the_end;
2697 } while(bound);
2698 ret = 0;
2699 the_end:
2700 tcc_free(data);
2701 return ret;
2704 /* load a '.a' file */
2705 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2707 ArchiveHeader hdr;
2708 char ar_size[11];
2709 char ar_name[17];
2710 char magic[8];
2711 int size, len, i;
2712 unsigned long file_offset;
2714 /* skip magic which was already checked */
2715 read(fd, magic, sizeof(magic));
2717 for(;;) {
2718 len = read(fd, &hdr, sizeof(hdr));
2719 if (len == 0)
2720 break;
2721 if (len != sizeof(hdr)) {
2722 tcc_error_noabort("invalid archive");
2723 return -1;
2725 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2726 ar_size[sizeof(hdr.ar_size)] = '\0';
2727 size = strtol(ar_size, NULL, 0);
2728 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2729 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2730 if (ar_name[i] != ' ')
2731 break;
2733 ar_name[i + 1] = '\0';
2734 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2735 file_offset = lseek(fd, 0, SEEK_CUR);
2736 /* align to even */
2737 size = (size + 1) & ~1;
2738 if (!strcmp(ar_name, "/")) {
2739 /* coff symbol table : we handle it */
2740 if(s1->alacarte_link)
2741 return tcc_load_alacarte(s1, fd, size);
2742 } else if (!strcmp(ar_name, "//") ||
2743 !strcmp(ar_name, "__.SYMDEF") ||
2744 !strcmp(ar_name, "__.SYMDEF/") ||
2745 !strcmp(ar_name, "ARFILENAMES/")) {
2746 /* skip symbol table or archive names */
2747 } else {
2748 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2749 return -1;
2751 lseek(fd, file_offset + size, SEEK_SET);
2753 return 0;
2756 #ifndef TCC_TARGET_PE
2757 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2758 is referenced by the user (so it should be added as DT_NEEDED in
2759 the generated ELF file) */
2760 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2762 ElfW(Ehdr) ehdr;
2763 ElfW(Shdr) *shdr, *sh, *sh1;
2764 int i, j, nb_syms, nb_dts, sym_bind, ret;
2765 ElfW(Sym) *sym, *dynsym;
2766 ElfW(Dyn) *dt, *dynamic;
2767 unsigned char *dynstr;
2768 const char *name, *soname;
2769 DLLReference *dllref;
2771 read(fd, &ehdr, sizeof(ehdr));
2773 /* test CPU specific stuff */
2774 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2775 ehdr.e_machine != EM_TCC_TARGET) {
2776 tcc_error_noabort("bad architecture");
2777 return -1;
2780 /* read sections */
2781 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2783 /* load dynamic section and dynamic symbols */
2784 nb_syms = 0;
2785 nb_dts = 0;
2786 dynamic = NULL;
2787 dynsym = NULL; /* avoid warning */
2788 dynstr = NULL; /* avoid warning */
2789 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2790 switch(sh->sh_type) {
2791 case SHT_DYNAMIC:
2792 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2793 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2794 break;
2795 case SHT_DYNSYM:
2796 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2797 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2798 sh1 = &shdr[sh->sh_link];
2799 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2800 break;
2801 default:
2802 break;
2806 /* compute the real library name */
2807 soname = tcc_basename(filename);
2809 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2810 if (dt->d_tag == DT_SONAME) {
2811 soname = dynstr + dt->d_un.d_val;
2815 /* if the dll is already loaded, do not load it */
2816 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2817 dllref = s1->loaded_dlls[i];
2818 if (!strcmp(soname, dllref->name)) {
2819 /* but update level if needed */
2820 if (level < dllref->level)
2821 dllref->level = level;
2822 ret = 0;
2823 goto the_end;
2827 // printf("loading dll '%s'\n", soname);
2829 /* add the dll and its level */
2830 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2831 dllref->level = level;
2832 strcpy(dllref->name, soname);
2833 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2835 /* add dynamic symbols in dynsym_section */
2836 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2837 sym_bind = ELFW(ST_BIND)(sym->st_info);
2838 if (sym_bind == STB_LOCAL)
2839 continue;
2840 name = dynstr + sym->st_name;
2841 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2842 sym->st_info, sym->st_other, sym->st_shndx, name);
2845 /* load all referenced DLLs */
2846 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2847 switch(dt->d_tag) {
2848 case DT_NEEDED:
2849 name = dynstr + dt->d_un.d_val;
2850 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2851 dllref = s1->loaded_dlls[j];
2852 if (!strcmp(name, dllref->name))
2853 goto already_loaded;
2855 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2856 tcc_error_noabort("referenced dll '%s' not found", name);
2857 ret = -1;
2858 goto the_end;
2860 already_loaded:
2861 break;
2864 ret = 0;
2865 the_end:
2866 tcc_free(dynstr);
2867 tcc_free(dynsym);
2868 tcc_free(dynamic);
2869 tcc_free(shdr);
2870 return ret;
2873 #define LD_TOK_NAME 256
2874 #define LD_TOK_EOF (-1)
2876 /* return next ld script token */
2877 static int ld_next(TCCState *s1, char *name, int name_size)
2879 int c;
2880 char *q;
2882 redo:
2883 switch(ch) {
2884 case ' ':
2885 case '\t':
2886 case '\f':
2887 case '\v':
2888 case '\r':
2889 case '\n':
2890 inp();
2891 goto redo;
2892 case '/':
2893 minp();
2894 if (ch == '*') {
2895 file->buf_ptr = parse_comment(file->buf_ptr);
2896 ch = file->buf_ptr[0];
2897 goto redo;
2898 } else {
2899 q = name;
2900 *q++ = '/';
2901 goto parse_name;
2903 break;
2904 /* case 'a' ... 'z': */
2905 case 'a':
2906 case 'b':
2907 case 'c':
2908 case 'd':
2909 case 'e':
2910 case 'f':
2911 case 'g':
2912 case 'h':
2913 case 'i':
2914 case 'j':
2915 case 'k':
2916 case 'l':
2917 case 'm':
2918 case 'n':
2919 case 'o':
2920 case 'p':
2921 case 'q':
2922 case 'r':
2923 case 's':
2924 case 't':
2925 case 'u':
2926 case 'v':
2927 case 'w':
2928 case 'x':
2929 case 'y':
2930 case 'z':
2931 /* case 'A' ... 'z': */
2932 case 'A':
2933 case 'B':
2934 case 'C':
2935 case 'D':
2936 case 'E':
2937 case 'F':
2938 case 'G':
2939 case 'H':
2940 case 'I':
2941 case 'J':
2942 case 'K':
2943 case 'L':
2944 case 'M':
2945 case 'N':
2946 case 'O':
2947 case 'P':
2948 case 'Q':
2949 case 'R':
2950 case 'S':
2951 case 'T':
2952 case 'U':
2953 case 'V':
2954 case 'W':
2955 case 'X':
2956 case 'Y':
2957 case 'Z':
2958 case '_':
2959 case '\\':
2960 case '.':
2961 case '$':
2962 case '~':
2963 q = name;
2964 parse_name:
2965 for(;;) {
2966 if (!((ch >= 'a' && ch <= 'z') ||
2967 (ch >= 'A' && ch <= 'Z') ||
2968 (ch >= '0' && ch <= '9') ||
2969 strchr("/.-_+=$:\\,~", ch)))
2970 break;
2971 if ((q - name) < name_size - 1) {
2972 *q++ = ch;
2974 minp();
2976 *q = '\0';
2977 c = LD_TOK_NAME;
2978 break;
2979 case CH_EOF:
2980 c = LD_TOK_EOF;
2981 break;
2982 default:
2983 c = ch;
2984 inp();
2985 break;
2987 #if 0
2988 printf("tok=%c %d\n", c, c);
2989 if (c == LD_TOK_NAME)
2990 printf(" name=%s\n", name);
2991 #endif
2992 return c;
2995 static int ld_add_file(TCCState *s1, const char filename[])
2997 int ret;
2999 ret = tcc_add_file_internal(s1, filename, 0);
3000 if (ret)
3001 ret = tcc_add_dll(s1, filename, 0);
3002 return ret;
3005 static inline int new_undef_syms(void)
3007 int ret = 0;
3008 ret = new_undef_sym;
3009 new_undef_sym = 0;
3010 return ret;
3013 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
3015 char filename[1024], libname[1024];
3016 int t, group, nblibs = 0, ret = 0;
3017 char **libs = NULL;
3019 group = !strcmp(cmd, "GROUP");
3020 if (!as_needed)
3021 new_undef_syms();
3022 t = ld_next(s1, filename, sizeof(filename));
3023 if (t != '(')
3024 expect("(");
3025 t = ld_next(s1, filename, sizeof(filename));
3026 for(;;) {
3027 libname[0] = '\0';
3028 if (t == LD_TOK_EOF) {
3029 tcc_error_noabort("unexpected end of file");
3030 ret = -1;
3031 goto lib_parse_error;
3032 } else if (t == ')') {
3033 break;
3034 } else if (t == '-') {
3035 t = ld_next(s1, filename, sizeof(filename));
3036 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
3037 tcc_error_noabort("library name expected");
3038 ret = -1;
3039 goto lib_parse_error;
3041 pstrcpy(libname, sizeof libname, &filename[1]);
3042 if (s1->static_link) {
3043 snprintf(filename, sizeof filename, "lib%s.a", libname);
3044 } else {
3045 snprintf(filename, sizeof filename, "lib%s.so", libname);
3047 } else if (t != LD_TOK_NAME) {
3048 tcc_error_noabort("filename expected");
3049 ret = -1;
3050 goto lib_parse_error;
3052 if (!strcmp(filename, "AS_NEEDED")) {
3053 ret = ld_add_file_list(s1, cmd, 1);
3054 if (ret)
3055 goto lib_parse_error;
3056 } else {
3057 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3058 if (!as_needed) {
3059 ret = ld_add_file(s1, filename);
3060 if (ret)
3061 goto lib_parse_error;
3062 if (group) {
3063 /* Add the filename *and* the libname to avoid future conversions */
3064 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
3065 if (libname[0] != '\0')
3066 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
3070 t = ld_next(s1, filename, sizeof(filename));
3071 if (t == ',') {
3072 t = ld_next(s1, filename, sizeof(filename));
3075 if (group && !as_needed) {
3076 while (new_undef_syms()) {
3077 int i;
3079 for (i = 0; i < nblibs; i ++)
3080 ld_add_file(s1, libs[i]);
3083 lib_parse_error:
3084 dynarray_reset(&libs, &nblibs);
3085 return ret;
3088 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3089 files */
3090 ST_FUNC int tcc_load_ldscript(TCCState *s1)
3092 char cmd[64];
3093 char filename[1024];
3094 int t, ret;
3096 ch = file->buf_ptr[0];
3097 ch = handle_eob();
3098 for(;;) {
3099 t = ld_next(s1, cmd, sizeof(cmd));
3100 if (t == LD_TOK_EOF)
3101 return 0;
3102 else if (t != LD_TOK_NAME)
3103 return -1;
3104 if (!strcmp(cmd, "INPUT") ||
3105 !strcmp(cmd, "GROUP")) {
3106 ret = ld_add_file_list(s1, cmd, 0);
3107 if (ret)
3108 return ret;
3109 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3110 !strcmp(cmd, "TARGET")) {
3111 /* ignore some commands */
3112 t = ld_next(s1, cmd, sizeof(cmd));
3113 if (t != '(')
3114 expect("(");
3115 for(;;) {
3116 t = ld_next(s1, filename, sizeof(filename));
3117 if (t == LD_TOK_EOF) {
3118 tcc_error_noabort("unexpected end of file");
3119 return -1;
3120 } else if (t == ')') {
3121 break;
3124 } else {
3125 return -1;
3128 return 0;
3130 #endif /* ndef TCC_TARGET_PE */