Add armv6l to ARM supported processors
[tinycc.git] / tccelf.c
bloba2559eec1200a3295363128653a7375cb34c58a3
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_infos[sym_index].got_offset << 1;
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 >= 0x4000000 || x < -0x4000000)
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 >= 0x4000000 || x < -0x4000000)
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_infos[sym_index].got_offset << 1;
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_infos[sym_index].got_offset << 1) - 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_infos[sym_index].got_offset << 1;
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 void put_sym_info(TCCState *s1, int index)
948 int n;
949 typeof(s1->sym_infos) tab;
951 if (index >= s1->nb_sym_infos) {
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_infos, n * sizeof(unsigned long));
957 s1->sym_infos = tab;
958 memset(s1->sym_infos + s1->nb_sym_infos, 0,
959 (n - s1->nb_sym_infos) * sizeof(unsigned long));
960 s1->nb_sym_infos = n;
964 #ifdef TCC_TARGET_ARM
965 static void put_plt_thumb_stub(TCCState *s1, int index, unsigned char bit)
967 put_sym_info(s1, index);
968 s1->sym_infos[index].plt_thumb_stub = bit;
970 #endif
972 static void put_got_offset(TCCState *s1, int index, unsigned long val)
974 put_sym_info(s1, index);
975 s1->sym_infos[index].got_offset = val >> 1;
978 /* XXX: suppress that */
979 static void put32(unsigned char *p, uint32_t val)
981 p[0] = val;
982 p[1] = val >> 8;
983 p[2] = val >> 16;
984 p[3] = val >> 24;
987 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
988 defined(TCC_TARGET_X86_64)
989 static uint32_t get32(unsigned char *p)
991 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
993 #endif
995 static void build_got(TCCState *s1)
997 unsigned char *ptr;
999 /* if no got, then create it */
1000 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
1001 s1->got->sh_entsize = 4;
1002 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
1003 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
1004 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
1005 #if PTR_SIZE == 4
1006 /* keep space for _DYNAMIC pointer, if present */
1007 put32(ptr, 0);
1008 /* two dummy got entries */
1009 put32(ptr + 4, 0);
1010 put32(ptr + 8, 0);
1011 #else
1012 /* keep space for _DYNAMIC pointer, if present */
1013 put32(ptr, 0);
1014 put32(ptr + 4, 0);
1015 /* two dummy got entries */
1016 put32(ptr + 8, 0);
1017 put32(ptr + 12, 0);
1018 put32(ptr + 16, 0);
1019 put32(ptr + 20, 0);
1020 #endif
1023 /* put a got entry corresponding to a symbol in symtab_section. 'size'
1024 and 'info' can be modifed if more precise info comes from the DLL */
1025 static void put_got_entry(TCCState *s1,
1026 int reloc_type, unsigned long size, int info,
1027 int sym_index)
1029 int index;
1030 const char *name;
1031 ElfW(Sym) *sym;
1032 unsigned long offset;
1033 int *ptr;
1035 if (!s1->got)
1036 build_got(s1);
1038 /* if a got entry already exists for that symbol, no need to add one */
1039 if (sym_index < s1->nb_sym_infos &&
1040 s1->sym_infos[sym_index].got_offset << 1)
1041 return;
1043 put_got_offset(s1, sym_index, s1->got->data_offset);
1045 if (s1->dynsym) {
1046 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1047 name = symtab_section->link->data + sym->st_name;
1048 offset = sym->st_value;
1049 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1050 if (reloc_type ==
1051 #ifdef TCC_TARGET_X86_64
1052 R_X86_64_JUMP_SLOT
1053 #else
1054 R_386_JMP_SLOT
1055 #endif
1057 Section *plt;
1058 uint8_t *p;
1059 int modrm;
1061 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1062 modrm = 0x25;
1063 #else
1064 /* if we build a DLL, we add a %ebx offset */
1065 if (s1->output_type == TCC_OUTPUT_DLL)
1066 modrm = 0xa3;
1067 else
1068 modrm = 0x25;
1069 #endif
1071 /* add a PLT entry */
1072 plt = s1->plt;
1073 if (plt->data_offset == 0) {
1074 /* first plt entry */
1075 p = section_ptr_add(plt, 16);
1076 p[0] = 0xff; /* pushl got + PTR_SIZE */
1077 p[1] = modrm + 0x10;
1078 put32(p + 2, PTR_SIZE);
1079 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1080 p[7] = modrm;
1081 put32(p + 8, PTR_SIZE * 2);
1084 p = section_ptr_add(plt, 16);
1085 p[0] = 0xff; /* jmp *(got + x) */
1086 p[1] = modrm;
1087 put32(p + 2, s1->got->data_offset);
1088 p[6] = 0x68; /* push $xxx */
1089 put32(p + 7, (plt->data_offset - 32) >> 1);
1090 p[11] = 0xe9; /* jmp plt_start */
1091 put32(p + 12, -(plt->data_offset));
1093 /* the symbol is modified so that it will be relocated to
1094 the PLT */
1095 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
1096 if (s1->output_type == TCC_OUTPUT_EXE)
1097 #endif
1098 offset = plt->data_offset - 16;
1100 #elif defined(TCC_TARGET_ARM)
1101 if (reloc_type == R_ARM_JUMP_SLOT) {
1102 Section *plt;
1103 uint8_t *p;
1105 /* if we build a DLL, we add a %ebx offset */
1106 if (s1->output_type == TCC_OUTPUT_DLL)
1107 tcc_error("DLLs unimplemented!");
1109 /* add a PLT entry */
1110 plt = s1->plt;
1111 if (plt->data_offset == 0) {
1112 /* first plt entry */
1113 p = section_ptr_add(plt, 16);
1114 put32(p , 0xe52de004);
1115 put32(p + 4, 0xe59fe010);
1116 put32(p + 8, 0xe08fe00e);
1117 put32(p + 12, 0xe5bef008);
1120 if (s1->sym_infos[sym_index].plt_thumb_stub) {
1121 p = section_ptr_add(plt, 20);
1122 put32(p , 0x4778); // bx pc
1123 put32(p+2, 0x46c0); // nop
1124 p += 4;
1125 } else
1126 p = section_ptr_add(plt, 16);
1127 put32(p , 0xe59fc004); // ldr ip, [pc, #4] // offset in GOT
1128 put32(p+4, 0xe08fc00c); // add ip, pc, ip // absolute address or offset
1129 put32(p+8, 0xe59cf000); // ldr pc, [ip] // load absolute address or load offset
1130 put32(p+12, s1->got->data_offset);
1132 /* the symbol is modified so that it will be relocated to
1133 the PLT */
1134 if (s1->output_type == TCC_OUTPUT_EXE)
1135 offset = plt->data_offset - 16;
1137 #elif defined(TCC_TARGET_C67)
1138 tcc_error("C67 got not implemented");
1139 #else
1140 #error unsupported CPU
1141 #endif
1142 index = put_elf_sym(s1->dynsym, offset,
1143 size, info, 0, sym->st_shndx, name);
1144 /* put a got entry */
1145 put_elf_reloc(s1->dynsym, s1->got,
1146 s1->got->data_offset,
1147 reloc_type, index);
1149 ptr = section_ptr_add(s1->got, PTR_SIZE);
1150 *ptr = 0;
1153 /* build GOT and PLT entries */
1154 ST_FUNC void build_got_entries(TCCState *s1)
1156 Section *s;
1157 ElfW_Rel *rel, *rel_end;
1158 ElfW(Sym) *sym;
1159 int i, type, reloc_type, sym_index;
1161 for(i = 1; i < s1->nb_sections; i++) {
1162 s = s1->sections[i];
1163 if (s->sh_type != SHT_RELX)
1164 continue;
1165 /* no need to handle got relocations */
1166 if (s->link != symtab_section)
1167 continue;
1168 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1169 for(rel = (ElfW_Rel *)s->data;
1170 rel < rel_end;
1171 rel++) {
1172 type = ELFW(R_TYPE)(rel->r_info);
1173 switch(type) {
1174 #if defined(TCC_TARGET_I386)
1175 case R_386_GOT32:
1176 case R_386_GOTOFF:
1177 case R_386_GOTPC:
1178 case R_386_PLT32:
1179 if (!s1->got)
1180 build_got(s1);
1181 if (type == R_386_GOT32 || type == R_386_PLT32) {
1182 sym_index = ELFW(R_SYM)(rel->r_info);
1183 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1184 /* look at the symbol got offset. If none, then add one */
1185 if (type == R_386_GOT32)
1186 reloc_type = R_386_GLOB_DAT;
1187 else
1188 reloc_type = R_386_JMP_SLOT;
1189 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1190 sym_index);
1192 break;
1193 #elif defined(TCC_TARGET_ARM)
1194 case R_ARM_GOT_BREL:
1195 case R_ARM_GOTOFF32:
1196 case R_ARM_BASE_PREL:
1197 case R_ARM_PLT32:
1198 if (!s1->got)
1199 build_got(s1);
1200 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1201 sym_index = ELFW(R_SYM)(rel->r_info);
1202 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1203 /* look at the symbol got offset. If none, then add one */
1204 if (type == R_ARM_GOT_BREL)
1205 reloc_type = R_ARM_GLOB_DAT;
1206 else
1207 reloc_type = R_ARM_JUMP_SLOT;
1208 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1209 sym_index);
1211 break;
1212 #elif defined(TCC_TARGET_C67)
1213 case R_C60_GOT32:
1214 case R_C60_GOTOFF:
1215 case R_C60_GOTPC:
1216 case R_C60_PLT32:
1217 if (!s1->got)
1218 build_got(s1);
1219 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1220 sym_index = ELFW(R_SYM)(rel->r_info);
1221 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1222 /* look at the symbol got offset. If none, then add one */
1223 if (type == R_C60_GOT32)
1224 reloc_type = R_C60_GLOB_DAT;
1225 else
1226 reloc_type = R_C60_JMP_SLOT;
1227 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1228 sym_index);
1230 break;
1231 #elif defined(TCC_TARGET_X86_64)
1232 case R_X86_64_GOT32:
1233 case R_X86_64_GOTTPOFF:
1234 case R_X86_64_GOTPCREL:
1235 case R_X86_64_PLT32:
1236 if (!s1->got)
1237 build_got(s1);
1238 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1239 type == R_X86_64_PLT32) {
1240 sym_index = ELFW(R_SYM)(rel->r_info);
1241 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1242 /* look at the symbol got offset. If none, then add one */
1243 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1244 reloc_type = R_X86_64_GLOB_DAT;
1245 else
1246 reloc_type = R_X86_64_JUMP_SLOT;
1247 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1248 sym_index);
1250 break;
1251 #else
1252 #error unsupported CPU
1253 #endif
1254 default:
1255 break;
1261 ST_FUNC Section *new_symtab(TCCState *s1,
1262 const char *symtab_name, int sh_type, int sh_flags,
1263 const char *strtab_name,
1264 const char *hash_name, int hash_sh_flags)
1266 Section *symtab, *strtab, *hash;
1267 int *ptr, nb_buckets;
1269 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1270 symtab->sh_entsize = sizeof(ElfW(Sym));
1271 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1272 put_elf_str(strtab, "");
1273 symtab->link = strtab;
1274 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1276 nb_buckets = 1;
1278 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1279 hash->sh_entsize = sizeof(int);
1280 symtab->hash = hash;
1281 hash->link = symtab;
1283 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1284 ptr[0] = nb_buckets;
1285 ptr[1] = 1;
1286 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1287 return symtab;
1290 /* put dynamic tag */
1291 static void put_dt(Section *dynamic, int dt, uplong val)
1293 ElfW(Dyn) *dyn;
1294 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1295 dyn->d_tag = dt;
1296 dyn->d_un.d_val = val;
1299 static void add_init_array_defines(TCCState *s1, const char *section_name)
1301 Section *s;
1302 long end_offset;
1303 char sym_start[1024];
1304 char sym_end[1024];
1306 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1307 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1309 s = find_section(s1, section_name);
1310 if (!s) {
1311 end_offset = 0;
1312 s = data_section;
1313 } else {
1314 end_offset = s->data_offset;
1317 add_elf_sym(symtab_section,
1318 0, 0,
1319 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1320 s->sh_num, sym_start);
1321 add_elf_sym(symtab_section,
1322 end_offset, 0,
1323 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1324 s->sh_num, sym_end);
1327 static int tcc_add_support(TCCState *s1, const char *filename)
1329 char buf[1024];
1330 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, filename);
1331 return tcc_add_file(s1, buf);
1334 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1336 #ifdef CONFIG_TCC_BCHECK
1337 unsigned long *ptr;
1338 Section *init_section;
1339 unsigned char *pinit;
1340 int sym_index;
1342 if (0 == s1->do_bounds_check)
1343 return;
1345 /* XXX: add an object file to do that */
1346 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1347 *ptr = 0;
1348 add_elf_sym(symtab_section, 0, 0,
1349 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1350 bounds_section->sh_num, "__bounds_start");
1351 /* add bound check code */
1352 #ifndef TCC_TARGET_PE
1353 tcc_add_support(s1, "bcheck.o");
1354 #endif
1355 #ifdef TCC_TARGET_I386
1356 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1357 /* add 'call __bound_init()' in .init section */
1358 init_section = find_section(s1, ".init");
1359 pinit = section_ptr_add(init_section, 5);
1360 pinit[0] = 0xe8;
1361 put32(pinit + 1, -4);
1362 sym_index = find_elf_sym(symtab_section, "__bound_init");
1363 put_elf_reloc(symtab_section, init_section,
1364 init_section->data_offset - 4, R_386_PC32, sym_index);
1366 #endif
1367 #endif
1370 /* add tcc runtime libraries */
1371 ST_FUNC void tcc_add_runtime(TCCState *s1)
1373 tcc_add_bcheck(s1);
1375 /* add libc */
1376 if (!s1->nostdlib) {
1377 tcc_add_library(s1, "c");
1378 #ifdef CONFIG_USE_LIBGCC
1379 tcc_add_file(s1, TCC_LIBGCC);
1380 #elif !defined WITHOUT_LIBTCC
1381 tcc_add_support(s1, "libtcc1.a");
1382 #endif
1383 /* add crt end if not memory output */
1384 if (s1->output_type != TCC_OUTPUT_MEMORY)
1385 tcc_add_crt(s1, "crtn.o");
1389 /* add various standard linker symbols (must be done after the
1390 sections are filled (for example after allocating common
1391 symbols)) */
1392 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1394 char buf[1024];
1395 int i;
1396 Section *s;
1398 add_elf_sym(symtab_section,
1399 text_section->data_offset, 0,
1400 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1401 text_section->sh_num, "_etext");
1402 add_elf_sym(symtab_section,
1403 data_section->data_offset, 0,
1404 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1405 data_section->sh_num, "_edata");
1406 add_elf_sym(symtab_section,
1407 bss_section->data_offset, 0,
1408 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1409 bss_section->sh_num, "_end");
1410 /* horrible new standard ldscript defines */
1411 add_init_array_defines(s1, ".preinit_array");
1412 add_init_array_defines(s1, ".init_array");
1413 add_init_array_defines(s1, ".fini_array");
1415 /* add start and stop symbols for sections whose name can be
1416 expressed in C */
1417 for(i = 1; i < s1->nb_sections; i++) {
1418 s = s1->sections[i];
1419 if (s->sh_type == SHT_PROGBITS &&
1420 (s->sh_flags & SHF_ALLOC)) {
1421 const char *p;
1422 int ch;
1424 /* check if section name can be expressed in C */
1425 p = s->name;
1426 for(;;) {
1427 ch = *p;
1428 if (!ch)
1429 break;
1430 if (!isid(ch) && !isnum(ch))
1431 goto next_sec;
1432 p++;
1434 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1435 add_elf_sym(symtab_section,
1436 0, 0,
1437 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1438 s->sh_num, buf);
1439 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1440 add_elf_sym(symtab_section,
1441 s->data_offset, 0,
1442 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1443 s->sh_num, buf);
1445 next_sec: ;
1449 static void tcc_output_binary(TCCState *s1, FILE *f,
1450 const int *section_order)
1452 Section *s;
1453 int i, offset, size;
1455 offset = 0;
1456 for(i=1;i<s1->nb_sections;i++) {
1457 s = s1->sections[section_order[i]];
1458 if (s->sh_type != SHT_NOBITS &&
1459 (s->sh_flags & SHF_ALLOC)) {
1460 while (offset < s->sh_offset) {
1461 fputc(0, f);
1462 offset++;
1464 size = s->sh_size;
1465 fwrite(s->data, 1, size, f);
1466 offset += size;
1471 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1472 #define HAVE_PHDR 1
1473 #define EXTRA_RELITEMS 14
1475 /* move the relocation value from .dynsym to .got */
1476 void patch_dynsym_undef(TCCState *s1, Section *s)
1478 uint32_t *gotd = (void *)s1->got->data;
1479 ElfW(Sym) *sym, *sym_end;
1481 gotd += 3; // dummy entries in .got
1482 /* relocate symbols in .dynsym */
1483 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1484 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1485 if (sym->st_shndx == SHN_UNDEF) {
1486 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1487 sym->st_value = 0;
1491 #else
1492 #define HAVE_PHDR 0
1493 #define EXTRA_RELITEMS 9
1495 /* zero plt offsets of weak symbols in .dynsym */
1496 void patch_dynsym_undef(TCCState *s1, Section *s)
1498 ElfW(Sym) *sym, *sym_end;
1500 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1501 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++)
1502 if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
1503 sym->st_value = 0;
1505 #endif
1507 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1509 int sym_index = ELFW(R_SYM) (rel->r_info);
1510 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1511 unsigned long offset;
1513 if (sym_index >= s1->nb_sym_infos)
1514 return;
1515 offset = s1->sym_infos[sym_index].got_offset << 1;
1516 section_reserve(s1->got, offset + PTR_SIZE);
1517 #ifdef TCC_TARGET_X86_64
1518 /* only works for x86-64 */
1519 put32(s1->got->data + offset + 4, sym->st_value >> 32);
1520 #endif
1521 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1524 ST_FUNC void fill_got(TCCState *s1)
1526 Section *s;
1527 ElfW_Rel *rel, *rel_end;
1528 int i;
1530 for(i = 1; i < s1->nb_sections; i++) {
1531 s = s1->sections[i];
1532 if (s->sh_type != SHT_RELX)
1533 continue;
1534 /* no need to handle got relocations */
1535 if (s->link != symtab_section)
1536 continue;
1537 rel_end = (ElfW_Rel *) (s->data + s->data_offset);
1538 for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
1539 switch (ELFW(R_TYPE) (rel->r_info)) {
1540 case R_X86_64_GOT32:
1541 case R_X86_64_GOTPCREL:
1542 case R_X86_64_PLT32:
1543 fill_got_entry(s1, rel);
1544 break;
1551 /* output an ELF file */
1552 /* XXX: suppress unneeded sections */
1553 static int elf_output_file(TCCState *s1, const char *filename)
1555 ElfW(Ehdr) ehdr;
1556 FILE *f;
1557 int fd, mode, ret;
1558 int *section_order;
1559 int shnum, i, phnum, file_offset, offset, size, j, sh_order_index, k;
1560 long long tmp;
1561 uplong addr;
1562 Section *strsec, *s;
1563 ElfW(Shdr) shdr, *sh;
1564 ElfW(Phdr) *phdr, *ph;
1565 Section *interp, *dynamic, *dynstr;
1566 unsigned long saved_dynamic_data_offset;
1567 ElfW(Sym) *sym;
1568 int type, file_type;
1569 uplong rel_addr, rel_size;
1570 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1571 uplong bss_addr, bss_size;
1572 #endif
1574 file_type = s1->output_type;
1575 s1->nb_errors = 0;
1577 if (file_type != TCC_OUTPUT_OBJ) {
1578 tcc_add_runtime(s1);
1581 phdr = NULL;
1582 section_order = NULL;
1583 interp = NULL;
1584 dynamic = NULL;
1585 dynstr = NULL; /* avoid warning */
1586 saved_dynamic_data_offset = 0; /* avoid warning */
1588 if (file_type != TCC_OUTPUT_OBJ) {
1589 relocate_common_syms();
1591 tcc_add_linker_symbols(s1);
1593 if (!s1->static_link) {
1594 const char *name;
1595 int sym_index, index;
1596 ElfW(Sym) *esym, *sym_end;
1598 if (file_type == TCC_OUTPUT_EXE) {
1599 char *ptr;
1600 /* allow override the dynamic loader */
1601 const char *elfint = getenv("LD_SO");
1602 if (elfint == NULL)
1603 elfint = CONFIG_TCC_ELFINTERP;
1604 /* add interpreter section only if executable */
1605 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1606 interp->sh_addralign = 1;
1607 ptr = section_ptr_add(interp, 1+strlen(elfint));
1608 strcpy(ptr, elfint);
1611 /* add dynamic symbol table */
1612 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1613 ".dynstr",
1614 ".hash", SHF_ALLOC);
1615 dynstr = s1->dynsym->link;
1617 /* add dynamic section */
1618 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1619 SHF_ALLOC | SHF_WRITE);
1620 dynamic->link = dynstr;
1621 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1623 /* add PLT */
1624 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1625 SHF_ALLOC | SHF_EXECINSTR);
1626 s1->plt->sh_entsize = 4;
1628 build_got(s1);
1630 /* scan for undefined symbols and see if they are in the
1631 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1632 is found, then we add it in the PLT. If a symbol
1633 STT_OBJECT is found, we add it in the .bss section with
1634 a suitable relocation */
1635 sym_end = (ElfW(Sym) *)(symtab_section->data +
1636 symtab_section->data_offset);
1637 if (file_type == TCC_OUTPUT_EXE) {
1638 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1639 sym < sym_end;
1640 sym++) {
1641 if (sym->st_shndx == SHN_UNDEF) {
1642 name = symtab_section->link->data + sym->st_name;
1643 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1644 if (sym_index) {
1645 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1646 type = ELFW(ST_TYPE)(esym->st_info);
1647 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1648 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1649 ELFW(ST_INFO)(STB_GLOBAL,type),
1650 sym - (ElfW(Sym) *)symtab_section->data);
1651 } else if (type == STT_OBJECT) {
1652 unsigned long offset;
1653 ElfW(Sym) *dynsym, *dynsym_end;
1654 offset = bss_section->data_offset;
1655 /* XXX: which alignment ? */
1656 offset = (offset + 16 - 1) & -16;
1657 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1658 esym->st_info, 0,
1659 bss_section->sh_num, name);
1660 // Ensure R_COPY works for weak symbol aliases
1661 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1662 dynsym_end = (ElfW(Sym) *)
1663 (s1->dynsymtab_section->data +
1664 s1->dynsymtab_section->data_offset);
1665 for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1666 dynsym < dynsym_end; dynsym++) {
1667 if ((dynsym->st_value == esym->st_value)
1668 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1669 char *dynname;
1670 dynname = s1->dynsymtab_section->link->data
1671 + dynsym->st_name;
1672 put_elf_sym(s1->dynsym, offset,
1673 dynsym->st_size,
1674 dynsym->st_info, 0,
1675 bss_section->sh_num,
1676 dynname);
1677 break;
1681 put_elf_reloc(s1->dynsym, bss_section,
1682 offset, R_COPY, index);
1683 offset += esym->st_size;
1684 bss_section->data_offset = offset;
1686 } else {
1687 /* STB_WEAK undefined symbols are accepted */
1688 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1689 it */
1690 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1691 !strcmp(name, "_fp_hw")) {
1692 } else {
1693 tcc_error_noabort("undefined symbol '%s'", name);
1696 } else if (s1->rdynamic &&
1697 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1698 /* if -rdynamic option, then export all non
1699 local symbols */
1700 name = symtab_section->link->data + sym->st_name;
1701 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1702 sym->st_info, 0,
1703 sym->st_shndx, name);
1707 if (s1->nb_errors)
1708 goto fail;
1710 /* now look at unresolved dynamic symbols and export
1711 corresponding symbol */
1712 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1713 s1->dynsymtab_section->data_offset);
1714 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1715 esym < sym_end;
1716 esym++) {
1717 if (esym->st_shndx == SHN_UNDEF) {
1718 name = s1->dynsymtab_section->link->data + esym->st_name;
1719 sym_index = find_elf_sym(symtab_section, name);
1720 if (sym_index) {
1721 /* XXX: avoid adding a symbol if already
1722 present because of -rdynamic ? */
1723 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1724 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1725 sym->st_info, 0,
1726 sym->st_shndx, name);
1727 } else {
1728 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1729 /* weak symbols can stay undefined */
1730 } else {
1731 tcc_warning("undefined dynamic symbol '%s'", name);
1736 } else {
1737 int nb_syms;
1738 /* shared library case : we simply export all the global symbols */
1739 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1740 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1741 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1742 sym < sym_end;
1743 sym++) {
1744 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1745 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1746 if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
1747 ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
1748 && sym->st_shndx == SHN_UNDEF) {
1749 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1750 sym->st_info,
1751 sym - (ElfW(Sym) *)symtab_section->data);
1753 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1754 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1755 sym->st_info,
1756 sym - (ElfW(Sym) *)symtab_section->data);
1758 else
1759 #endif
1761 name = symtab_section->link->data + sym->st_name;
1762 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1763 sym->st_info, 0,
1764 sym->st_shndx, name);
1765 s1->symtab_to_dynsym[sym -
1766 (ElfW(Sym) *)symtab_section->data] =
1767 index;
1773 build_got_entries(s1);
1775 /* add a list of needed dlls */
1776 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1777 DLLReference *dllref = s1->loaded_dlls[i];
1778 if (dllref->level == 0)
1779 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1782 if (s1->rpath)
1783 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1785 /* XXX: currently, since we do not handle PIC code, we
1786 must relocate the readonly segments */
1787 if (file_type == TCC_OUTPUT_DLL) {
1788 if (s1->soname)
1789 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1790 put_dt(dynamic, DT_TEXTREL, 0);
1793 if (s1->symbolic)
1794 put_dt(dynamic, DT_SYMBOLIC, 0);
1796 /* add necessary space for other entries */
1797 saved_dynamic_data_offset = dynamic->data_offset;
1798 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1799 } else {
1800 /* still need to build got entries in case of static link */
1801 build_got_entries(s1);
1805 memset(&ehdr, 0, sizeof(ehdr));
1807 /* we add a section for symbols */
1808 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1809 put_elf_str(strsec, "");
1811 /* compute number of sections */
1812 shnum = s1->nb_sections;
1814 /* this array is used to reorder sections in the output file */
1815 section_order = tcc_malloc(sizeof(int) * shnum);
1816 section_order[0] = 0;
1817 sh_order_index = 1;
1819 /* compute number of program headers */
1820 switch(file_type) {
1821 default:
1822 case TCC_OUTPUT_OBJ:
1823 phnum = 0;
1824 break;
1825 case TCC_OUTPUT_EXE:
1826 if (!s1->static_link)
1827 phnum = 4 + HAVE_PHDR;
1828 else
1829 phnum = 2;
1830 break;
1831 case TCC_OUTPUT_DLL:
1832 phnum = 3;
1833 break;
1836 /* allocate strings for section names and decide if an unallocated
1837 section should be output */
1838 /* NOTE: the strsec section comes last, so its size is also
1839 correct ! */
1840 for(i = 1; i < s1->nb_sections; i++) {
1841 s = s1->sections[i];
1842 s->sh_name = put_elf_str(strsec, s->name);
1843 #if 0 //gr
1844 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1845 s->sh_flags,
1846 s->sh_type,
1847 s->sh_info,
1848 s->name,
1849 s->reloc ? s->reloc->name : "n"
1851 #endif
1852 /* when generating a DLL, we include relocations but we may
1853 patch them */
1854 if (file_type == TCC_OUTPUT_DLL &&
1855 s->sh_type == SHT_RELX &&
1856 !(s->sh_flags & SHF_ALLOC)) {
1857 /* //gr: avoid bogus relocs for empty (debug) sections */
1858 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1859 prepare_dynamic_rel(s1, s);
1860 else if (s1->do_debug)
1861 s->sh_size = s->data_offset;
1862 } else if (s1->do_debug ||
1863 file_type == TCC_OUTPUT_OBJ ||
1864 (s->sh_flags & SHF_ALLOC) ||
1865 i == (s1->nb_sections - 1)) {
1866 /* we output all sections if debug or object file */
1867 s->sh_size = s->data_offset;
1871 /* allocate program segment headers */
1872 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1874 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1875 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1876 } else {
1877 file_offset = 0;
1879 if (phnum > 0) {
1880 /* compute section to program header mapping */
1881 if (s1->has_text_addr) {
1882 int a_offset, p_offset;
1883 addr = s1->text_addr;
1884 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1885 ELF_PAGE_SIZE */
1886 a_offset = (int) (addr & (s1->section_align - 1));
1887 p_offset = file_offset & (s1->section_align - 1);
1888 if (a_offset < p_offset)
1889 a_offset += s1->section_align;
1890 file_offset += (a_offset - p_offset);
1891 } else {
1892 if (file_type == TCC_OUTPUT_DLL)
1893 addr = 0;
1894 else
1895 addr = ELF_START_ADDR;
1896 /* compute address after headers */
1897 addr += (file_offset & (s1->section_align - 1));
1900 /* dynamic relocation table information, for .dynamic section */
1901 rel_size = 0;
1902 rel_addr = 0;
1904 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1905 bss_addr = bss_size = 0;
1906 #endif
1907 /* leave one program header for the program interpreter */
1908 ph = &phdr[0];
1909 if (interp)
1910 ph += 1 + HAVE_PHDR;
1912 for(j = 0; j < 2; j++) {
1913 ph->p_type = PT_LOAD;
1914 if (j == 0)
1915 ph->p_flags = PF_R | PF_X;
1916 else
1917 ph->p_flags = PF_R | PF_W;
1918 ph->p_align = s1->section_align;
1920 /* we do the following ordering: interp, symbol tables,
1921 relocations, progbits, nobits */
1922 /* XXX: do faster and simpler sorting */
1923 for(k = 0; k < 5; k++) {
1924 for(i = 1; i < s1->nb_sections; i++) {
1925 s = s1->sections[i];
1926 /* compute if section should be included */
1927 if (j == 0) {
1928 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1929 SHF_ALLOC)
1930 continue;
1931 } else {
1932 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1933 (SHF_ALLOC | SHF_WRITE))
1934 continue;
1936 if (s == interp) {
1937 if (k != 0)
1938 continue;
1939 } else if (s->sh_type == SHT_DYNSYM ||
1940 s->sh_type == SHT_STRTAB ||
1941 s->sh_type == SHT_HASH) {
1942 if (k != 1)
1943 continue;
1944 } else if (s->sh_type == SHT_RELX) {
1945 if (k != 2)
1946 continue;
1947 } else if (s->sh_type == SHT_NOBITS) {
1948 if (k != 4)
1949 continue;
1950 } else {
1951 if (k != 3)
1952 continue;
1954 section_order[sh_order_index++] = i;
1956 /* section matches: we align it and add its size */
1957 tmp = addr;
1958 addr = (addr + s->sh_addralign - 1) &
1959 ~(s->sh_addralign - 1);
1960 file_offset += (int) ( addr - tmp );
1961 s->sh_offset = file_offset;
1962 s->sh_addr = addr;
1964 /* update program header infos */
1965 if (ph->p_offset == 0) {
1966 ph->p_offset = file_offset;
1967 ph->p_vaddr = addr;
1968 ph->p_paddr = ph->p_vaddr;
1970 /* update dynamic relocation infos */
1971 if (s->sh_type == SHT_RELX) {
1972 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1973 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1974 rel_addr = addr;
1975 rel_size += s->sh_size; // XXX only first rel.
1977 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1978 bss_addr = addr;
1979 bss_size = s->sh_size; // XXX only first rel.
1981 #else
1982 if (rel_size == 0)
1983 rel_addr = addr;
1984 rel_size += s->sh_size;
1985 #endif
1987 addr += s->sh_size;
1988 if (s->sh_type != SHT_NOBITS)
1989 file_offset += s->sh_size;
1992 ph->p_filesz = file_offset - ph->p_offset;
1993 ph->p_memsz = addr - ph->p_vaddr;
1994 ph++;
1995 if (j == 0) {
1996 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1997 /* if in the middle of a page, we duplicate the page in
1998 memory so that one copy is RX and the other is RW */
1999 if ((addr & (s1->section_align - 1)) != 0)
2000 addr += s1->section_align;
2001 } else {
2002 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
2003 file_offset = (file_offset + s1->section_align - 1) &
2004 ~(s1->section_align - 1);
2009 /* if interpreter, then add corresponing program header */
2010 if (interp) {
2011 ph = &phdr[0];
2013 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2015 int len = phnum * sizeof(ElfW(Phdr));
2017 ph->p_type = PT_PHDR;
2018 ph->p_offset = sizeof(ElfW(Ehdr));
2019 ph->p_vaddr = interp->sh_addr - len;
2020 ph->p_paddr = ph->p_vaddr;
2021 ph->p_filesz = ph->p_memsz = len;
2022 ph->p_flags = PF_R | PF_X;
2023 ph->p_align = 4; // interp->sh_addralign;
2024 ph++;
2026 #endif
2028 ph->p_type = PT_INTERP;
2029 ph->p_offset = interp->sh_offset;
2030 ph->p_vaddr = interp->sh_addr;
2031 ph->p_paddr = ph->p_vaddr;
2032 ph->p_filesz = interp->sh_size;
2033 ph->p_memsz = interp->sh_size;
2034 ph->p_flags = PF_R;
2035 ph->p_align = interp->sh_addralign;
2038 /* if dynamic section, then add corresponing program header */
2039 if (dynamic) {
2040 ElfW(Sym) *sym_end;
2042 ph = &phdr[phnum - 1];
2044 ph->p_type = PT_DYNAMIC;
2045 ph->p_offset = dynamic->sh_offset;
2046 ph->p_vaddr = dynamic->sh_addr;
2047 ph->p_paddr = ph->p_vaddr;
2048 ph->p_filesz = dynamic->sh_size;
2049 ph->p_memsz = dynamic->sh_size;
2050 ph->p_flags = PF_R | PF_W;
2051 ph->p_align = dynamic->sh_addralign;
2053 /* put GOT dynamic section address */
2054 put32(s1->got->data, dynamic->sh_addr);
2056 /* relocate the PLT */
2057 if (file_type == TCC_OUTPUT_EXE
2058 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2059 || file_type == TCC_OUTPUT_DLL
2060 #endif
2062 uint8_t *p, *p_end;
2064 p = s1->plt->data;
2065 p_end = p + s1->plt->data_offset;
2066 if (p < p_end) {
2067 #if defined(TCC_TARGET_I386)
2068 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2069 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
2070 p += 16;
2071 while (p < p_end) {
2072 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2073 p += 16;
2075 #elif defined(TCC_TARGET_X86_64)
2076 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
2077 put32(p + 2, get32(p + 2) + x);
2078 put32(p + 8, get32(p + 8) + x - 6);
2079 p += 16;
2080 while (p < p_end) {
2081 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
2082 p += 16;
2084 #elif defined(TCC_TARGET_ARM)
2085 int x;
2086 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
2087 p += 16;
2088 while (p < p_end) {
2089 if (get32(p) == 0x46c04778) /* PLT Thumb stub present */
2090 p += 4;
2091 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
2092 p += 16;
2094 #elif defined(TCC_TARGET_C67)
2095 /* XXX: TODO */
2096 #else
2097 #error unsupported CPU
2098 #endif
2102 /* relocate symbols in .dynsym */
2103 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
2104 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
2105 sym < sym_end;
2106 sym++) {
2107 if (sym->st_shndx == SHN_UNDEF) {
2108 /* relocate to the PLT if the symbol corresponds
2109 to a PLT entry */
2110 if (sym->st_value)
2111 sym->st_value += s1->plt->sh_addr;
2112 } else if (sym->st_shndx < SHN_LORESERVE) {
2113 /* do symbol relocation */
2114 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
2118 /* put dynamic section entries */
2119 dynamic->data_offset = saved_dynamic_data_offset;
2120 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
2121 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
2122 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2123 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
2124 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2125 #ifdef TCC_TARGET_X86_64
2126 put_dt(dynamic, DT_RELA, rel_addr);
2127 put_dt(dynamic, DT_RELASZ, rel_size);
2128 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2129 #else
2130 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2131 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2132 put_dt(dynamic, DT_PLTRELSZ, rel_size);
2133 put_dt(dynamic, DT_JMPREL, rel_addr);
2134 put_dt(dynamic, DT_PLTREL, DT_REL);
2135 put_dt(dynamic, DT_REL, bss_addr);
2136 put_dt(dynamic, DT_RELSZ, bss_size);
2137 #else
2138 put_dt(dynamic, DT_REL, rel_addr);
2139 put_dt(dynamic, DT_RELSZ, rel_size);
2140 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2141 #endif
2142 #endif
2143 if (s1->do_debug)
2144 put_dt(dynamic, DT_DEBUG, 0);
2145 put_dt(dynamic, DT_NULL, 0);
2148 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2149 ehdr.e_phnum = phnum;
2150 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2153 /* all other sections come after */
2154 for(i = 1; i < s1->nb_sections; i++) {
2155 s = s1->sections[i];
2156 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2157 continue;
2158 section_order[sh_order_index++] = i;
2160 file_offset = (file_offset + s->sh_addralign - 1) &
2161 ~(s->sh_addralign - 1);
2162 s->sh_offset = file_offset;
2163 if (s->sh_type != SHT_NOBITS)
2164 file_offset += s->sh_size;
2167 /* if building executable or DLL, then relocate each section
2168 except the GOT which is already relocated */
2169 if (file_type != TCC_OUTPUT_OBJ) {
2170 relocate_syms(s1, 0);
2172 if (s1->nb_errors != 0) {
2173 fail:
2174 ret = -1;
2175 goto the_end;
2178 /* relocate sections */
2179 /* XXX: ignore sections with allocated relocations ? */
2180 for(i = 1; i < s1->nb_sections; i++) {
2181 s = s1->sections[i];
2182 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
2183 relocate_section(s1, s);
2186 /* relocate relocation entries if the relocation tables are
2187 allocated in the executable */
2188 for(i = 1; i < s1->nb_sections; i++) {
2189 s = s1->sections[i];
2190 if ((s->sh_flags & SHF_ALLOC) &&
2191 s->sh_type == SHT_RELX) {
2192 relocate_rel(s1, s);
2196 /* get entry point address */
2197 if (file_type == TCC_OUTPUT_EXE)
2198 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
2199 else
2200 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2202 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2203 fill_got(s1);
2205 /* write elf file */
2206 if (file_type == TCC_OUTPUT_OBJ)
2207 mode = 0666;
2208 else
2209 mode = 0777;
2210 unlink(filename);
2211 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2212 if (fd < 0) {
2213 tcc_error_noabort("could not write '%s'", filename);
2214 goto fail;
2216 f = fdopen(fd, "wb");
2217 if (s1->verbose)
2218 printf("<- %s\n", filename);
2220 #ifdef TCC_TARGET_COFF
2221 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2222 tcc_output_coff(s1, f);
2223 } else
2224 #endif
2225 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2226 sort_syms(s1, symtab_section);
2228 /* align to 4 */
2229 file_offset = (file_offset + 3) & -4;
2231 /* fill header */
2232 ehdr.e_ident[0] = ELFMAG0;
2233 ehdr.e_ident[1] = ELFMAG1;
2234 ehdr.e_ident[2] = ELFMAG2;
2235 ehdr.e_ident[3] = ELFMAG3;
2236 ehdr.e_ident[4] = ELFCLASSW;
2237 ehdr.e_ident[5] = ELFDATA2LSB;
2238 ehdr.e_ident[6] = EV_CURRENT;
2239 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2240 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2241 #endif
2242 #ifdef TCC_TARGET_ARM
2243 #ifdef TCC_ARM_EABI
2244 ehdr.e_ident[EI_OSABI] = 0;
2245 ehdr.e_flags = 4 << 24;
2246 #else
2247 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2248 #endif
2249 #endif
2250 switch(file_type) {
2251 default:
2252 case TCC_OUTPUT_EXE:
2253 ehdr.e_type = ET_EXEC;
2254 break;
2255 case TCC_OUTPUT_DLL:
2256 ehdr.e_type = ET_DYN;
2257 break;
2258 case TCC_OUTPUT_OBJ:
2259 ehdr.e_type = ET_REL;
2260 break;
2262 ehdr.e_machine = EM_TCC_TARGET;
2263 ehdr.e_version = EV_CURRENT;
2264 ehdr.e_shoff = file_offset;
2265 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2266 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2267 ehdr.e_shnum = shnum;
2268 ehdr.e_shstrndx = shnum - 1;
2270 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2271 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2272 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2274 for(i=1;i<s1->nb_sections;i++) {
2275 s = s1->sections[section_order[i]];
2276 if (s->sh_type != SHT_NOBITS) {
2277 if (s->sh_type == SHT_DYNSYM)
2278 patch_dynsym_undef(s1, s);
2279 while (offset < s->sh_offset) {
2280 fputc(0, f);
2281 offset++;
2283 size = s->sh_size;
2284 fwrite(s->data, 1, size, f);
2285 offset += size;
2289 /* output section headers */
2290 while (offset < ehdr.e_shoff) {
2291 fputc(0, f);
2292 offset++;
2295 for(i=0;i<s1->nb_sections;i++) {
2296 sh = &shdr;
2297 memset(sh, 0, sizeof(ElfW(Shdr)));
2298 s = s1->sections[i];
2299 if (s) {
2300 sh->sh_name = s->sh_name;
2301 sh->sh_type = s->sh_type;
2302 sh->sh_flags = s->sh_flags;
2303 sh->sh_entsize = s->sh_entsize;
2304 sh->sh_info = s->sh_info;
2305 if (s->link)
2306 sh->sh_link = s->link->sh_num;
2307 sh->sh_addralign = s->sh_addralign;
2308 sh->sh_addr = s->sh_addr;
2309 sh->sh_offset = s->sh_offset;
2310 sh->sh_size = s->sh_size;
2312 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2314 } else {
2315 tcc_output_binary(s1, f, section_order);
2317 fclose(f);
2319 ret = 0;
2320 the_end:
2321 tcc_free(s1->symtab_to_dynsym);
2322 tcc_free(section_order);
2323 tcc_free(phdr);
2324 tcc_free(s1->sym_infos);
2325 return ret;
2328 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2330 int ret;
2331 #ifdef TCC_TARGET_PE
2332 if (s->output_type != TCC_OUTPUT_OBJ) {
2333 ret = pe_output_file(s, filename);
2334 } else
2335 #endif
2337 ret = elf_output_file(s, filename);
2339 return ret;
2342 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2344 void *data;
2346 data = tcc_malloc(size);
2347 lseek(fd, file_offset, SEEK_SET);
2348 read(fd, data, size);
2349 return data;
2352 typedef struct SectionMergeInfo {
2353 Section *s; /* corresponding existing section */
2354 unsigned long offset; /* offset of the new section in the existing section */
2355 uint8_t new_section; /* true if section 's' was added */
2356 uint8_t link_once; /* true if link once section */
2357 } SectionMergeInfo;
2359 /* load an object file and merge it with current files */
2360 /* XXX: handle correctly stab (debug) info */
2361 ST_FUNC int tcc_load_object_file(TCCState *s1,
2362 int fd, unsigned long file_offset)
2364 ElfW(Ehdr) ehdr;
2365 ElfW(Shdr) *shdr, *sh;
2366 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2367 unsigned char *strsec, *strtab;
2368 int *old_to_new_syms;
2369 char *sh_name, *name;
2370 SectionMergeInfo *sm_table, *sm;
2371 ElfW(Sym) *sym, *symtab;
2372 ElfW_Rel *rel, *rel_end;
2373 Section *s;
2375 int stab_index;
2376 int stabstr_index;
2378 stab_index = stabstr_index = 0;
2380 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2381 goto fail1;
2382 if (ehdr.e_ident[0] != ELFMAG0 ||
2383 ehdr.e_ident[1] != ELFMAG1 ||
2384 ehdr.e_ident[2] != ELFMAG2 ||
2385 ehdr.e_ident[3] != ELFMAG3)
2386 goto fail1;
2387 /* test if object file */
2388 if (ehdr.e_type != ET_REL)
2389 goto fail1;
2390 /* test CPU specific stuff */
2391 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2392 ehdr.e_machine != EM_TCC_TARGET) {
2393 fail1:
2394 tcc_error_noabort("invalid object file");
2395 return -1;
2397 /* read sections */
2398 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2399 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2400 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2402 /* load section names */
2403 sh = &shdr[ehdr.e_shstrndx];
2404 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2406 /* load symtab and strtab */
2407 old_to_new_syms = NULL;
2408 symtab = NULL;
2409 strtab = NULL;
2410 nb_syms = 0;
2411 for(i = 1; i < ehdr.e_shnum; i++) {
2412 sh = &shdr[i];
2413 if (sh->sh_type == SHT_SYMTAB) {
2414 if (symtab) {
2415 tcc_error_noabort("object must contain only one symtab");
2416 fail:
2417 ret = -1;
2418 goto the_end;
2420 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2421 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2422 sm_table[i].s = symtab_section;
2424 /* now load strtab */
2425 sh = &shdr[sh->sh_link];
2426 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2430 /* now examine each section and try to merge its content with the
2431 ones in memory */
2432 for(i = 1; i < ehdr.e_shnum; i++) {
2433 /* no need to examine section name strtab */
2434 if (i == ehdr.e_shstrndx)
2435 continue;
2436 sh = &shdr[i];
2437 sh_name = strsec + sh->sh_name;
2438 /* ignore sections types we do not handle */
2439 if (sh->sh_type != SHT_PROGBITS &&
2440 sh->sh_type != SHT_RELX &&
2441 #ifdef TCC_ARM_EABI
2442 sh->sh_type != SHT_ARM_EXIDX &&
2443 #endif
2444 sh->sh_type != SHT_NOBITS &&
2445 sh->sh_type != SHT_PREINIT_ARRAY &&
2446 sh->sh_type != SHT_INIT_ARRAY &&
2447 sh->sh_type != SHT_FINI_ARRAY &&
2448 strcmp(sh_name, ".stabstr")
2450 continue;
2451 if (sh->sh_addralign < 1)
2452 sh->sh_addralign = 1;
2453 /* find corresponding section, if any */
2454 for(j = 1; j < s1->nb_sections;j++) {
2455 s = s1->sections[j];
2456 if (!strcmp(s->name, sh_name)) {
2457 if (!strncmp(sh_name, ".gnu.linkonce",
2458 sizeof(".gnu.linkonce") - 1)) {
2459 /* if a 'linkonce' section is already present, we
2460 do not add it again. It is a little tricky as
2461 symbols can still be defined in
2462 it. */
2463 sm_table[i].link_once = 1;
2464 goto next;
2465 } else {
2466 goto found;
2470 /* not found: create new section */
2471 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2472 /* take as much info as possible from the section. sh_link and
2473 sh_info will be updated later */
2474 s->sh_addralign = sh->sh_addralign;
2475 s->sh_entsize = sh->sh_entsize;
2476 sm_table[i].new_section = 1;
2477 found:
2478 if (sh->sh_type != s->sh_type) {
2479 tcc_error_noabort("invalid section type");
2480 goto fail;
2483 /* align start of section */
2484 offset = s->data_offset;
2486 if (0 == strcmp(sh_name, ".stab")) {
2487 stab_index = i;
2488 goto no_align;
2490 if (0 == strcmp(sh_name, ".stabstr")) {
2491 stabstr_index = i;
2492 goto no_align;
2495 size = sh->sh_addralign - 1;
2496 offset = (offset + size) & ~size;
2497 if (sh->sh_addralign > s->sh_addralign)
2498 s->sh_addralign = sh->sh_addralign;
2499 s->data_offset = offset;
2500 no_align:
2501 sm_table[i].offset = offset;
2502 sm_table[i].s = s;
2503 /* concatenate sections */
2504 size = sh->sh_size;
2505 if (sh->sh_type != SHT_NOBITS) {
2506 unsigned char *ptr;
2507 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2508 ptr = section_ptr_add(s, size);
2509 read(fd, ptr, size);
2510 } else {
2511 s->data_offset += size;
2513 next: ;
2516 /* //gr relocate stab strings */
2517 if (stab_index && stabstr_index) {
2518 Stab_Sym *a, *b;
2519 unsigned o;
2520 s = sm_table[stab_index].s;
2521 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2522 b = (Stab_Sym *)(s->data + s->data_offset);
2523 o = sm_table[stabstr_index].offset;
2524 while (a < b)
2525 a->n_strx += o, a++;
2528 /* second short pass to update sh_link and sh_info fields of new
2529 sections */
2530 for(i = 1; i < ehdr.e_shnum; i++) {
2531 s = sm_table[i].s;
2532 if (!s || !sm_table[i].new_section)
2533 continue;
2534 sh = &shdr[i];
2535 if (sh->sh_link > 0)
2536 s->link = sm_table[sh->sh_link].s;
2537 if (sh->sh_type == SHT_RELX) {
2538 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2539 /* update backward link */
2540 s1->sections[s->sh_info]->reloc = s;
2543 sm = sm_table;
2545 /* resolve symbols */
2546 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2548 sym = symtab + 1;
2549 for(i = 1; i < nb_syms; i++, sym++) {
2550 if (sym->st_shndx != SHN_UNDEF &&
2551 sym->st_shndx < SHN_LORESERVE) {
2552 sm = &sm_table[sym->st_shndx];
2553 if (sm->link_once) {
2554 /* if a symbol is in a link once section, we use the
2555 already defined symbol. It is very important to get
2556 correct relocations */
2557 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2558 name = strtab + sym->st_name;
2559 sym_index = find_elf_sym(symtab_section, name);
2560 if (sym_index)
2561 old_to_new_syms[i] = sym_index;
2563 continue;
2565 /* if no corresponding section added, no need to add symbol */
2566 if (!sm->s)
2567 continue;
2568 /* convert section number */
2569 sym->st_shndx = sm->s->sh_num;
2570 /* offset value */
2571 sym->st_value += sm->offset;
2573 /* add symbol */
2574 name = strtab + sym->st_name;
2575 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2576 sym->st_info, sym->st_other,
2577 sym->st_shndx, name);
2578 old_to_new_syms[i] = sym_index;
2581 /* third pass to patch relocation entries */
2582 for(i = 1; i < ehdr.e_shnum; i++) {
2583 s = sm_table[i].s;
2584 if (!s)
2585 continue;
2586 sh = &shdr[i];
2587 offset = sm_table[i].offset;
2588 switch(s->sh_type) {
2589 case SHT_RELX:
2590 /* take relocation offset information */
2591 offseti = sm_table[sh->sh_info].offset;
2592 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2593 for(rel = (ElfW_Rel *)(s->data + offset);
2594 rel < rel_end;
2595 rel++) {
2596 int type;
2597 unsigned sym_index;
2598 /* convert symbol index */
2599 type = ELFW(R_TYPE)(rel->r_info);
2600 sym_index = ELFW(R_SYM)(rel->r_info);
2601 /* NOTE: only one symtab assumed */
2602 if (sym_index >= nb_syms)
2603 goto invalid_reloc;
2604 sym_index = old_to_new_syms[sym_index];
2605 /* ignore link_once in rel section. */
2606 if (!sym_index && !sm->link_once
2607 #ifdef TCC_TARGET_ARM
2608 && type != R_ARM_V4BX
2609 #endif
2611 invalid_reloc:
2612 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2613 i, strsec + sh->sh_name, rel->r_offset);
2614 goto fail;
2616 rel->r_info = ELFW(R_INFO)(sym_index, type);
2617 /* offset the relocation offset */
2618 rel->r_offset += offseti;
2619 #ifdef TCC_TARGET_ARM
2620 /* Jumps and branches from a Thumb code to a PLT entry need
2621 special handling since PLT entries are ARM code.
2622 Unconditional bl instructions referencing PLT entries are
2623 handled by converting these instructions into blx
2624 instructions. Other case of instructions referencing a PLT
2625 entry require to add a Thumb stub before the PLT entry to
2626 switch to ARM mode. We set bit 0 of the got offset of a
2627 symbol to indicate such a case. */
2628 if (type == R_ARM_THM_JUMP24) {
2629 put_plt_thumb_stub(s1, sym_index, 1);
2631 #endif
2633 break;
2634 default:
2635 break;
2639 ret = 0;
2640 the_end:
2641 tcc_free(symtab);
2642 tcc_free(strtab);
2643 tcc_free(old_to_new_syms);
2644 tcc_free(sm_table);
2645 tcc_free(strsec);
2646 tcc_free(shdr);
2647 return ret;
2650 typedef struct ArchiveHeader {
2651 char ar_name[16]; /* name of this member */
2652 char ar_date[12]; /* file mtime */
2653 char ar_uid[6]; /* owner uid; printed as decimal */
2654 char ar_gid[6]; /* owner gid; printed as decimal */
2655 char ar_mode[8]; /* file mode, printed as octal */
2656 char ar_size[10]; /* file size, printed as decimal */
2657 char ar_fmag[2]; /* should contain ARFMAG */
2658 } ArchiveHeader;
2660 static int get_be32(const uint8_t *b)
2662 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2665 /* load only the objects which resolve undefined symbols */
2666 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2668 int i, bound, nsyms, sym_index, off, ret;
2669 uint8_t *data;
2670 const char *ar_names, *p;
2671 const uint8_t *ar_index;
2672 ElfW(Sym) *sym;
2674 data = tcc_malloc(size);
2675 if (read(fd, data, size) != size)
2676 goto fail;
2677 nsyms = get_be32(data);
2678 ar_index = data + 4;
2679 ar_names = ar_index + nsyms * 4;
2681 do {
2682 bound = 0;
2683 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2684 sym_index = find_elf_sym(symtab_section, p);
2685 if(sym_index) {
2686 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2687 if(sym->st_shndx == SHN_UNDEF) {
2688 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2689 #if 0
2690 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2691 #endif
2692 ++bound;
2693 lseek(fd, off, SEEK_SET);
2694 if(tcc_load_object_file(s1, fd, off) < 0) {
2695 fail:
2696 ret = -1;
2697 goto the_end;
2702 } while(bound);
2703 ret = 0;
2704 the_end:
2705 tcc_free(data);
2706 return ret;
2709 /* load a '.a' file */
2710 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2712 ArchiveHeader hdr;
2713 char ar_size[11];
2714 char ar_name[17];
2715 char magic[8];
2716 int size, len, i;
2717 unsigned long file_offset;
2719 /* skip magic which was already checked */
2720 read(fd, magic, sizeof(magic));
2722 for(;;) {
2723 len = read(fd, &hdr, sizeof(hdr));
2724 if (len == 0)
2725 break;
2726 if (len != sizeof(hdr)) {
2727 tcc_error_noabort("invalid archive");
2728 return -1;
2730 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2731 ar_size[sizeof(hdr.ar_size)] = '\0';
2732 size = strtol(ar_size, NULL, 0);
2733 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2734 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2735 if (ar_name[i] != ' ')
2736 break;
2738 ar_name[i + 1] = '\0';
2739 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2740 file_offset = lseek(fd, 0, SEEK_CUR);
2741 /* align to even */
2742 size = (size + 1) & ~1;
2743 if (!strcmp(ar_name, "/")) {
2744 /* coff symbol table : we handle it */
2745 if(s1->alacarte_link)
2746 return tcc_load_alacarte(s1, fd, size);
2747 } else if (!strcmp(ar_name, "//") ||
2748 !strcmp(ar_name, "__.SYMDEF") ||
2749 !strcmp(ar_name, "__.SYMDEF/") ||
2750 !strcmp(ar_name, "ARFILENAMES/")) {
2751 /* skip symbol table or archive names */
2752 } else {
2753 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2754 return -1;
2756 lseek(fd, file_offset + size, SEEK_SET);
2758 return 0;
2761 #ifndef TCC_TARGET_PE
2762 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2763 is referenced by the user (so it should be added as DT_NEEDED in
2764 the generated ELF file) */
2765 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2767 ElfW(Ehdr) ehdr;
2768 ElfW(Shdr) *shdr, *sh, *sh1;
2769 int i, j, nb_syms, nb_dts, sym_bind, ret;
2770 ElfW(Sym) *sym, *dynsym;
2771 ElfW(Dyn) *dt, *dynamic;
2772 unsigned char *dynstr;
2773 const char *name, *soname;
2774 DLLReference *dllref;
2776 read(fd, &ehdr, sizeof(ehdr));
2778 /* test CPU specific stuff */
2779 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2780 ehdr.e_machine != EM_TCC_TARGET) {
2781 tcc_error_noabort("bad architecture");
2782 return -1;
2785 /* read sections */
2786 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2788 /* load dynamic section and dynamic symbols */
2789 nb_syms = 0;
2790 nb_dts = 0;
2791 dynamic = NULL;
2792 dynsym = NULL; /* avoid warning */
2793 dynstr = NULL; /* avoid warning */
2794 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2795 switch(sh->sh_type) {
2796 case SHT_DYNAMIC:
2797 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2798 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2799 break;
2800 case SHT_DYNSYM:
2801 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2802 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2803 sh1 = &shdr[sh->sh_link];
2804 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2805 break;
2806 default:
2807 break;
2811 /* compute the real library name */
2812 soname = tcc_basename(filename);
2814 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2815 if (dt->d_tag == DT_SONAME) {
2816 soname = dynstr + dt->d_un.d_val;
2820 /* if the dll is already loaded, do not load it */
2821 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2822 dllref = s1->loaded_dlls[i];
2823 if (!strcmp(soname, dllref->name)) {
2824 /* but update level if needed */
2825 if (level < dllref->level)
2826 dllref->level = level;
2827 ret = 0;
2828 goto the_end;
2832 // printf("loading dll '%s'\n", soname);
2834 /* add the dll and its level */
2835 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2836 dllref->level = level;
2837 strcpy(dllref->name, soname);
2838 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2840 /* add dynamic symbols in dynsym_section */
2841 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2842 sym_bind = ELFW(ST_BIND)(sym->st_info);
2843 if (sym_bind == STB_LOCAL)
2844 continue;
2845 name = dynstr + sym->st_name;
2846 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2847 sym->st_info, sym->st_other, sym->st_shndx, name);
2850 /* load all referenced DLLs */
2851 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2852 switch(dt->d_tag) {
2853 case DT_NEEDED:
2854 name = dynstr + dt->d_un.d_val;
2855 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2856 dllref = s1->loaded_dlls[j];
2857 if (!strcmp(name, dllref->name))
2858 goto already_loaded;
2860 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2861 tcc_error_noabort("referenced dll '%s' not found", name);
2862 ret = -1;
2863 goto the_end;
2865 already_loaded:
2866 break;
2869 ret = 0;
2870 the_end:
2871 tcc_free(dynstr);
2872 tcc_free(dynsym);
2873 tcc_free(dynamic);
2874 tcc_free(shdr);
2875 return ret;
2878 #define LD_TOK_NAME 256
2879 #define LD_TOK_EOF (-1)
2881 /* return next ld script token */
2882 static int ld_next(TCCState *s1, char *name, int name_size)
2884 int c;
2885 char *q;
2887 redo:
2888 switch(ch) {
2889 case ' ':
2890 case '\t':
2891 case '\f':
2892 case '\v':
2893 case '\r':
2894 case '\n':
2895 inp();
2896 goto redo;
2897 case '/':
2898 minp();
2899 if (ch == '*') {
2900 file->buf_ptr = parse_comment(file->buf_ptr);
2901 ch = file->buf_ptr[0];
2902 goto redo;
2903 } else {
2904 q = name;
2905 *q++ = '/';
2906 goto parse_name;
2908 break;
2909 /* case 'a' ... 'z': */
2910 case 'a':
2911 case 'b':
2912 case 'c':
2913 case 'd':
2914 case 'e':
2915 case 'f':
2916 case 'g':
2917 case 'h':
2918 case 'i':
2919 case 'j':
2920 case 'k':
2921 case 'l':
2922 case 'm':
2923 case 'n':
2924 case 'o':
2925 case 'p':
2926 case 'q':
2927 case 'r':
2928 case 's':
2929 case 't':
2930 case 'u':
2931 case 'v':
2932 case 'w':
2933 case 'x':
2934 case 'y':
2935 case 'z':
2936 /* case 'A' ... 'z': */
2937 case 'A':
2938 case 'B':
2939 case 'C':
2940 case 'D':
2941 case 'E':
2942 case 'F':
2943 case 'G':
2944 case 'H':
2945 case 'I':
2946 case 'J':
2947 case 'K':
2948 case 'L':
2949 case 'M':
2950 case 'N':
2951 case 'O':
2952 case 'P':
2953 case 'Q':
2954 case 'R':
2955 case 'S':
2956 case 'T':
2957 case 'U':
2958 case 'V':
2959 case 'W':
2960 case 'X':
2961 case 'Y':
2962 case 'Z':
2963 case '_':
2964 case '\\':
2965 case '.':
2966 case '$':
2967 case '~':
2968 q = name;
2969 parse_name:
2970 for(;;) {
2971 if (!((ch >= 'a' && ch <= 'z') ||
2972 (ch >= 'A' && ch <= 'Z') ||
2973 (ch >= '0' && ch <= '9') ||
2974 strchr("/.-_+=$:\\,~", ch)))
2975 break;
2976 if ((q - name) < name_size - 1) {
2977 *q++ = ch;
2979 minp();
2981 *q = '\0';
2982 c = LD_TOK_NAME;
2983 break;
2984 case CH_EOF:
2985 c = LD_TOK_EOF;
2986 break;
2987 default:
2988 c = ch;
2989 inp();
2990 break;
2992 #if 0
2993 printf("tok=%c %d\n", c, c);
2994 if (c == LD_TOK_NAME)
2995 printf(" name=%s\n", name);
2996 #endif
2997 return c;
3001 * Extract the file name from the library name
3003 * /!\ No test on filename capacity, be careful
3005 static void libname_to_filename(TCCState *s1, const char libname[], char filename[])
3007 if (!s1->static_link) {
3008 sprintf(filename, "lib%s.so", libname);
3009 } else {
3010 sprintf(filename, "lib%s.a", libname);
3014 static int ld_add_file(TCCState *s1, const char filename[])
3016 int ret;
3018 ret = tcc_add_file_internal(s1, filename, 0);
3019 if (ret)
3020 ret = tcc_add_dll(s1, filename, 0);
3021 return ret;
3024 static inline int new_undef_syms(void)
3026 int ret = 0;
3027 ret = new_undef_sym;
3028 new_undef_sym = 0;
3029 return ret;
3032 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
3034 char filename[1024], libname[1024];
3035 int t, group, nblibs = 0, ret = 0;
3036 char **libs = NULL;
3038 group = !strcmp(cmd, "GROUP");
3039 if (!as_needed)
3040 new_undef_syms();
3041 t = ld_next(s1, filename, sizeof(filename));
3042 if (t != '(')
3043 expect("(");
3044 t = ld_next(s1, filename, sizeof(filename));
3045 for(;;) {
3046 libname[0] = '\0';
3047 if (t == LD_TOK_EOF) {
3048 tcc_error_noabort("unexpected end of file");
3049 ret = -1;
3050 goto lib_parse_error;
3051 } else if (t == ')') {
3052 break;
3053 } else if (t == '-') {
3054 t = ld_next(s1, filename, sizeof(filename));
3055 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
3056 tcc_error_noabort("library name expected");
3057 ret = -1;
3058 goto lib_parse_error;
3060 strcpy(libname, &filename[1]);
3061 libname_to_filename(s1, libname, filename);
3062 } else if (t != LD_TOK_NAME) {
3063 tcc_error_noabort("filename expected");
3064 ret = -1;
3065 goto lib_parse_error;
3067 if (!strcmp(filename, "AS_NEEDED")) {
3068 ret = ld_add_file_list(s1, cmd, 1);
3069 if (ret)
3070 goto lib_parse_error;
3071 } else {
3072 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3073 if (!as_needed) {
3074 ret = ld_add_file(s1, filename);
3075 if (ret)
3076 goto lib_parse_error;
3077 if (group) {
3078 /* Add the filename *and* the libname to avoid future conversions */
3079 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
3080 if (libname[0] != '\0')
3081 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
3085 t = ld_next(s1, filename, sizeof(filename));
3086 if (t == ',') {
3087 t = ld_next(s1, filename, sizeof(filename));
3090 if (group && !as_needed) {
3091 while (new_undef_syms()) {
3092 int i;
3094 for (i = 0; i < nblibs; i ++)
3095 ld_add_file(s1, libs[i]);
3098 lib_parse_error:
3099 dynarray_reset(&libs, &nblibs);
3100 return ret;
3103 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3104 files */
3105 ST_FUNC int tcc_load_ldscript(TCCState *s1)
3107 char cmd[64];
3108 char filename[1024];
3109 int t, ret;
3111 ch = file->buf_ptr[0];
3112 ch = handle_eob();
3113 for(;;) {
3114 t = ld_next(s1, cmd, sizeof(cmd));
3115 if (t == LD_TOK_EOF)
3116 return 0;
3117 else if (t != LD_TOK_NAME)
3118 return -1;
3119 if (!strcmp(cmd, "INPUT") ||
3120 !strcmp(cmd, "GROUP")) {
3121 ret = ld_add_file_list(s1, cmd, 0);
3122 if (ret)
3123 return ret;
3124 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3125 !strcmp(cmd, "TARGET")) {
3126 /* ignore some commands */
3127 t = ld_next(s1, cmd, sizeof(cmd));
3128 if (t != '(')
3129 expect("(");
3130 for(;;) {
3131 t = ld_next(s1, filename, sizeof(filename));
3132 if (t == LD_TOK_EOF) {
3133 tcc_error_noabort("unexpected end of file");
3134 return -1;
3135 } else if (t == ')') {
3136 break;
3139 } else {
3140 return -1;
3143 return 0;
3145 #endif /* ndef TCC_TARGET_PE */