Generate PLT thumb stub only when necessary
[tinycc.git] / tccelf.c
blobe8af18a9c6ec20b010ba26936ba769e232f8411b
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 #endif
621 if ((x & 3) || x >= 0x4000000 || x < -0x4000000)
622 if (!(x & 3) || !blx_avail || !is_call)
623 tcc_error("can't relocate value at %x",addr);
624 x >>= 2;
625 x &= 0xffffff;
626 /* Only reached if blx is avail and it is a call */
627 if (is_thumb) {
628 x |= h << 24;
629 (*(int *)ptr) = 0xfa << 24; /* bl -> blx */
631 (*(int *)ptr) |= x;
633 break;
634 /* Since these relocations only concern Thumb-2 and blx instruction was
635 introduced before Thumb-2, we can assume blx is available and not
636 guard its use */
637 case R_ARM_THM_CALL:
638 case R_ARM_THM_JUMP24:
640 int x, hi, lo, s, j1, j2, i1, i2, imm10, imm11;
641 int to_thumb, is_call, to_plt, blx_bit = 1 << 12;
642 Section *plt;
644 /* weak reference */
645 if (sym->st_shndx == SHN_UNDEF &&
646 ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
647 break;
649 /* Get initial offset */
650 hi = (*(uint16_t *)ptr);
651 lo = (*(uint16_t *)(ptr+2));
652 s = (hi >> 10) & 1;
653 j1 = (lo >> 13) & 1;
654 j2 = (lo >> 11) & 1;
655 i1 = (j1 ^ s) ^ 1;
656 i2 = (j2 ^ s) ^ 1;
657 imm10 = hi & 0x3ff;
658 imm11 = lo & 0x7ff;
659 x = (s << 24) | (i1 << 23) | (i2 << 22) |
660 (imm10 << 12) | (imm11 << 1);
661 if (x & 0x01000000)
662 x -= 0x02000000;
664 /* Relocation infos */
665 to_thumb = val & 1;
666 plt = s1->plt;
667 to_plt = (val >= plt->sh_addr) &&
668 (val < plt->sh_addr + plt->data_offset);
669 is_call = (type == R_ARM_THM_CALL);
671 /* Compute final offset */
672 if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */
673 x -= 4;
674 x += val - addr;
675 if (!to_thumb && is_call) {
676 blx_bit = 0; /* bl -> blx */
677 x = (x + 3) & -4; /* Compute offset from aligned PC */
680 /* Check that relocation is possible
681 * offset must not be out of range
682 * if target is to be entered in arm mode:
683 - bit 1 must not set
684 - instruction must be a call (bl) or a jump to PLT */
685 if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
686 if (to_thumb || (val & 2) || (!is_call && !to_plt))
687 tcc_error("can't relocate value at %x",addr);
689 /* Compute and store final offset */
690 s = (x >> 24) & 1;
691 i1 = (x >> 23) & 1;
692 i2 = (x >> 22) & 1;
693 j1 = s ^ (i1 ^ 1);
694 j2 = s ^ (i2 ^ 1);
695 imm10 = (x >> 12) & 0x3ff;
696 imm11 = (x >> 1) & 0x7ff;
697 (*(uint16_t *)ptr) = (uint16_t) ((hi & 0xf800) |
698 (s << 10) | imm10);
699 (*(uint16_t *)(ptr+2)) = (uint16_t) ((lo & 0xc000) |
700 (j1 << 13) | blx_bit | (j2 << 11) |
701 imm11);
703 break;
704 case R_ARM_MOVT_ABS:
705 case R_ARM_MOVW_ABS_NC:
707 int x, imm4, imm12;
708 if (type == R_ARM_MOVT_ABS)
709 val >>= 16;
710 imm12 = val & 0xfff;
711 imm4 = (val >> 12) & 0xf;
712 x = (imm4 << 16) | imm12;
713 if (type == R_ARM_THM_MOVT_ABS)
714 *(int *)ptr |= x;
715 else
716 *(int *)ptr += x;
718 break;
719 case R_ARM_THM_MOVT_ABS:
720 case R_ARM_THM_MOVW_ABS_NC:
722 int x, i, imm4, imm3, imm8;
723 if (type == R_ARM_THM_MOVT_ABS)
724 val >>= 16;
725 imm8 = val & 0xff;
726 imm3 = (val >> 8) & 0x7;
727 i = (val >> 11) & 1;
728 imm4 = (val >> 12) & 0xf;
729 x = (imm3 << 28) | (imm8 << 16) | (i << 10) | imm4;
730 if (type == R_ARM_THM_MOVT_ABS)
731 *(int *)ptr |= x;
732 else
733 *(int *)ptr += x;
735 break;
736 case R_ARM_PREL31:
738 int x;
739 x = (*(int *)ptr) & 0x7fffffff;
740 (*(int *)ptr) &= 0x80000000;
741 x = (x * 2) / 2;
742 x += val - addr;
743 if((x^(x>>1))&0x40000000)
744 tcc_error("can't relocate value at %x",addr);
745 (*(int *)ptr) |= x & 0x7fffffff;
747 case R_ARM_ABS32:
748 *(int *)ptr += val;
749 break;
750 case R_ARM_REL32:
751 *(int *)ptr += val - addr;
752 break;
753 case R_ARM_BASE_PREL:
754 *(int *)ptr += s1->got->sh_addr - addr;
755 break;
756 case R_ARM_GOTOFF32:
757 *(int *)ptr += val - s1->got->sh_addr;
758 break;
759 case R_ARM_GOT_BREL:
760 /* we load the got offset */
761 *(int *)ptr += s1->sym_infos[sym_index].got_offset << 1;
762 break;
763 case R_ARM_COPY:
764 break;
765 case R_ARM_V4BX:
766 /* trade Thumb support for ARMv4 support */
767 if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
768 *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
769 break;
770 default:
771 fprintf(stderr,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
772 type, (unsigned)addr, (unsigned)(uplong)ptr, (unsigned)val);
773 break;
774 #elif defined(TCC_TARGET_C67)
775 case R_C60_32:
776 *(int *)ptr += val;
777 break;
778 case R_C60LO16:
780 uint32_t orig;
782 /* put the low 16 bits of the absolute address */
783 // add to what is already there
785 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
786 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
788 //patch both at once - assumes always in pairs Low - High
790 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
791 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
793 break;
794 case R_C60HI16:
795 break;
796 default:
797 fprintf(stderr,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
798 type, (unsigned)addr, (unsigned)(uplong)ptr, (unsigned)val);
799 break;
800 #elif defined(TCC_TARGET_X86_64)
801 case R_X86_64_64:
802 if (s1->output_type == TCC_OUTPUT_DLL) {
803 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
804 qrel->r_addend = *(long long *)ptr + val;
805 qrel++;
807 *(long long *)ptr += val;
808 break;
809 case R_X86_64_32:
810 case R_X86_64_32S:
811 if (s1->output_type == TCC_OUTPUT_DLL) {
812 /* XXX: this logic may depend on TCC's codegen
813 now TCC uses R_X86_64_32 even for a 64bit pointer */
814 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
815 qrel->r_addend = *(int *)ptr + val;
816 qrel++;
818 *(int *)ptr += val;
819 break;
821 case R_X86_64_PC32:
822 if (s1->output_type == TCC_OUTPUT_DLL) {
823 /* DLL relocation */
824 esym_index = s1->symtab_to_dynsym[sym_index];
825 if (esym_index) {
826 qrel->r_offset = rel->r_offset;
827 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
828 qrel->r_addend = *(int *)ptr;
829 qrel++;
830 break;
833 /* fall through */
834 case R_X86_64_PLT32: {
835 long long diff;
836 diff = (long long)val - addr;
837 if (diff <= -2147483647 || diff > 2147483647) {
838 #ifndef TCC_TARGET_PE
839 /* XXX: naive support for over 32bit jump */
840 if (s1->output_type == TCC_OUTPUT_MEMORY) {
841 val = (add_jmp_table(s1, val - rel->r_addend) +
842 rel->r_addend);
843 diff = val - addr;
845 #endif
846 if (diff <= -2147483647 || diff > 2147483647) {
847 tcc_error("internal error: relocation failed");
850 *(int *)ptr += diff;
852 break;
853 case R_X86_64_GLOB_DAT:
854 case R_X86_64_JUMP_SLOT:
855 /* They don't need addend */
856 *(int *)ptr = val - rel->r_addend;
857 break;
858 case R_X86_64_GOTPCREL:
859 #ifndef TCC_TARGET_PE
860 if (s1->output_type == TCC_OUTPUT_MEMORY) {
861 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
862 *(int *)ptr += val - addr;
863 break;
865 #endif
866 *(int *)ptr += (s1->got->sh_addr - addr +
867 (s1->sym_infos[sym_index].got_offset << 1) - 4);
868 break;
869 case R_X86_64_GOTTPOFF:
870 *(int *)ptr += val - s1->got->sh_addr;
871 break;
872 case R_X86_64_GOT32:
873 /* we load the got offset */
874 *(int *)ptr += s1->sym_infos[sym_index].got_offset << 1;
875 break;
876 #else
877 #error unsupported processor
878 #endif
881 /* if the relocation is allocated, we change its symbol table */
882 if (sr->sh_flags & SHF_ALLOC)
883 sr->link = s1->dynsym;
886 /* relocate relocation table in 'sr' */
887 static void relocate_rel(TCCState *s1, Section *sr)
889 Section *s;
890 ElfW_Rel *rel, *rel_end;
892 s = s1->sections[sr->sh_info];
893 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
894 for(rel = (ElfW_Rel *)sr->data;
895 rel < rel_end;
896 rel++) {
897 rel->r_offset += s->sh_addr;
901 /* count the number of dynamic relocations so that we can reserve
902 their space */
903 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
905 ElfW_Rel *rel, *rel_end;
906 int sym_index, esym_index, type, count;
908 count = 0;
909 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
910 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
911 sym_index = ELFW(R_SYM)(rel->r_info);
912 type = ELFW(R_TYPE)(rel->r_info);
913 switch(type) {
914 #if defined(TCC_TARGET_I386)
915 case R_386_32:
916 #elif defined(TCC_TARGET_X86_64)
917 case R_X86_64_32:
918 case R_X86_64_32S:
919 case R_X86_64_64:
920 #endif
921 count++;
922 break;
923 #if defined(TCC_TARGET_I386)
924 case R_386_PC32:
925 #elif defined(TCC_TARGET_X86_64)
926 case R_X86_64_PC32:
927 #endif
928 esym_index = s1->symtab_to_dynsym[sym_index];
929 if (esym_index)
930 count++;
931 break;
932 default:
933 break;
936 if (count) {
937 /* allocate the section */
938 sr->sh_flags |= SHF_ALLOC;
939 sr->sh_size = count * sizeof(ElfW_Rel);
941 return count;
944 static void put_sym_info(TCCState *s1, int index)
946 int n;
947 typeof(s1->sym_infos) tab;
949 if (index >= s1->nb_sym_infos) {
950 /* find immediately bigger power of 2 and reallocate array */
951 n = 1;
952 while (index >= n)
953 n *= 2;
954 tab = tcc_realloc(s1->sym_infos, n * sizeof(unsigned long));
955 s1->sym_infos = tab;
956 memset(s1->sym_infos + s1->nb_sym_infos, 0,
957 (n - s1->nb_sym_infos) * sizeof(unsigned long));
958 s1->nb_sym_infos = n;
962 #ifdef TCC_TARGET_ARM
963 static void put_plt_thumb_stub(TCCState *s1, int index, unsigned char bit)
965 put_sym_info(s1, index);
966 s1->sym_infos[index].plt_thumb_stub = bit;
968 #endif
970 static void put_got_offset(TCCState *s1, int index, unsigned long val)
972 put_sym_info(s1, index);
973 s1->sym_infos[index].got_offset = val >> 1;
976 /* XXX: suppress that */
977 static void put32(unsigned char *p, uint32_t val)
979 p[0] = val;
980 p[1] = val >> 8;
981 p[2] = val >> 16;
982 p[3] = val >> 24;
985 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
986 defined(TCC_TARGET_X86_64)
987 static uint32_t get32(unsigned char *p)
989 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
991 #endif
993 static void build_got(TCCState *s1)
995 unsigned char *ptr;
997 /* if no got, then create it */
998 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
999 s1->got->sh_entsize = 4;
1000 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
1001 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
1002 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
1003 #if PTR_SIZE == 4
1004 /* keep space for _DYNAMIC pointer, if present */
1005 put32(ptr, 0);
1006 /* two dummy got entries */
1007 put32(ptr + 4, 0);
1008 put32(ptr + 8, 0);
1009 #else
1010 /* keep space for _DYNAMIC pointer, if present */
1011 put32(ptr, 0);
1012 put32(ptr + 4, 0);
1013 /* two dummy got entries */
1014 put32(ptr + 8, 0);
1015 put32(ptr + 12, 0);
1016 put32(ptr + 16, 0);
1017 put32(ptr + 20, 0);
1018 #endif
1021 /* put a got entry corresponding to a symbol in symtab_section. 'size'
1022 and 'info' can be modifed if more precise info comes from the DLL */
1023 static void put_got_entry(TCCState *s1,
1024 int reloc_type, unsigned long size, int info,
1025 int sym_index)
1027 int index;
1028 const char *name;
1029 ElfW(Sym) *sym;
1030 unsigned long offset;
1031 int *ptr;
1033 if (!s1->got)
1034 build_got(s1);
1036 /* if a got entry already exists for that symbol, no need to add one */
1037 if (sym_index < s1->nb_sym_infos &&
1038 s1->sym_infos[sym_index].got_offset << 1)
1039 return;
1041 put_got_offset(s1, sym_index, s1->got->data_offset);
1043 if (s1->dynsym) {
1044 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1045 name = symtab_section->link->data + sym->st_name;
1046 offset = sym->st_value;
1047 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1048 if (reloc_type ==
1049 #ifdef TCC_TARGET_X86_64
1050 R_X86_64_JUMP_SLOT
1051 #else
1052 R_386_JMP_SLOT
1053 #endif
1055 Section *plt;
1056 uint8_t *p;
1057 int modrm;
1059 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1060 modrm = 0x25;
1061 #else
1062 /* if we build a DLL, we add a %ebx offset */
1063 if (s1->output_type == TCC_OUTPUT_DLL)
1064 modrm = 0xa3;
1065 else
1066 modrm = 0x25;
1067 #endif
1069 /* add a PLT entry */
1070 plt = s1->plt;
1071 if (plt->data_offset == 0) {
1072 /* first plt entry */
1073 p = section_ptr_add(plt, 16);
1074 p[0] = 0xff; /* pushl got + PTR_SIZE */
1075 p[1] = modrm + 0x10;
1076 put32(p + 2, PTR_SIZE);
1077 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1078 p[7] = modrm;
1079 put32(p + 8, PTR_SIZE * 2);
1082 p = section_ptr_add(plt, 16);
1083 p[0] = 0xff; /* jmp *(got + x) */
1084 p[1] = modrm;
1085 put32(p + 2, s1->got->data_offset);
1086 p[6] = 0x68; /* push $xxx */
1087 put32(p + 7, (plt->data_offset - 32) >> 1);
1088 p[11] = 0xe9; /* jmp plt_start */
1089 put32(p + 12, -(plt->data_offset));
1091 /* the symbol is modified so that it will be relocated to
1092 the PLT */
1093 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
1094 if (s1->output_type == TCC_OUTPUT_EXE)
1095 #endif
1096 offset = plt->data_offset - 16;
1098 #elif defined(TCC_TARGET_ARM)
1099 if (reloc_type == R_ARM_JUMP_SLOT) {
1100 Section *plt;
1101 uint8_t *p;
1103 /* if we build a DLL, we add a %ebx offset */
1104 if (s1->output_type == TCC_OUTPUT_DLL)
1105 tcc_error("DLLs unimplemented!");
1107 /* add a PLT entry */
1108 plt = s1->plt;
1109 if (plt->data_offset == 0) {
1110 /* first plt entry */
1111 p = section_ptr_add(plt, 16);
1112 put32(p , 0xe52de004);
1113 put32(p + 4, 0xe59fe010);
1114 put32(p + 8, 0xe08fe00e);
1115 put32(p + 12, 0xe5bef008);
1118 if (s1->sym_infos[sym_index].plt_thumb_stub) {
1119 p = section_ptr_add(plt, 20);
1120 put32(p , 0x4778); // bx pc
1121 put32(p+2, 0x46c0); // nop
1122 p += 4;
1123 } else
1124 p = section_ptr_add(plt, 16);
1125 put32(p , 0xe59fc004); // ldr ip, [pc, #4] // offset in GOT
1126 put32(p+4, 0xe08fc00c); // add ip, pc, ip // absolute address or offset
1127 put32(p+8, 0xe59cf000); // ldr pc, [ip] // load absolute address or load offset
1128 put32(p+12, s1->got->data_offset);
1130 /* the symbol is modified so that it will be relocated to
1131 the PLT */
1132 if (s1->output_type == TCC_OUTPUT_EXE)
1133 offset = plt->data_offset - 16;
1135 #elif defined(TCC_TARGET_C67)
1136 tcc_error("C67 got not implemented");
1137 #else
1138 #error unsupported CPU
1139 #endif
1140 index = put_elf_sym(s1->dynsym, offset,
1141 size, info, 0, sym->st_shndx, name);
1142 /* put a got entry */
1143 put_elf_reloc(s1->dynsym, s1->got,
1144 s1->got->data_offset,
1145 reloc_type, index);
1147 ptr = section_ptr_add(s1->got, PTR_SIZE);
1148 *ptr = 0;
1151 /* build GOT and PLT entries */
1152 ST_FUNC void build_got_entries(TCCState *s1)
1154 Section *s;
1155 ElfW_Rel *rel, *rel_end;
1156 ElfW(Sym) *sym;
1157 int i, type, reloc_type, sym_index;
1159 for(i = 1; i < s1->nb_sections; i++) {
1160 s = s1->sections[i];
1161 if (s->sh_type != SHT_RELX)
1162 continue;
1163 /* no need to handle got relocations */
1164 if (s->link != symtab_section)
1165 continue;
1166 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1167 for(rel = (ElfW_Rel *)s->data;
1168 rel < rel_end;
1169 rel++) {
1170 type = ELFW(R_TYPE)(rel->r_info);
1171 switch(type) {
1172 #if defined(TCC_TARGET_I386)
1173 case R_386_GOT32:
1174 case R_386_GOTOFF:
1175 case R_386_GOTPC:
1176 case R_386_PLT32:
1177 if (!s1->got)
1178 build_got(s1);
1179 if (type == R_386_GOT32 || type == R_386_PLT32) {
1180 sym_index = ELFW(R_SYM)(rel->r_info);
1181 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1182 /* look at the symbol got offset. If none, then add one */
1183 if (type == R_386_GOT32)
1184 reloc_type = R_386_GLOB_DAT;
1185 else
1186 reloc_type = R_386_JMP_SLOT;
1187 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1188 sym_index);
1190 break;
1191 #elif defined(TCC_TARGET_ARM)
1192 case R_ARM_GOT_BREL:
1193 case R_ARM_GOTOFF32:
1194 case R_ARM_BASE_PREL:
1195 case R_ARM_PLT32:
1196 if (!s1->got)
1197 build_got(s1);
1198 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1199 sym_index = ELFW(R_SYM)(rel->r_info);
1200 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1201 /* look at the symbol got offset. If none, then add one */
1202 if (type == R_ARM_GOT_BREL)
1203 reloc_type = R_ARM_GLOB_DAT;
1204 else
1205 reloc_type = R_ARM_JUMP_SLOT;
1206 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1207 sym_index);
1209 break;
1210 #elif defined(TCC_TARGET_C67)
1211 case R_C60_GOT32:
1212 case R_C60_GOTOFF:
1213 case R_C60_GOTPC:
1214 case R_C60_PLT32:
1215 if (!s1->got)
1216 build_got(s1);
1217 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1218 sym_index = ELFW(R_SYM)(rel->r_info);
1219 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1220 /* look at the symbol got offset. If none, then add one */
1221 if (type == R_C60_GOT32)
1222 reloc_type = R_C60_GLOB_DAT;
1223 else
1224 reloc_type = R_C60_JMP_SLOT;
1225 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1226 sym_index);
1228 break;
1229 #elif defined(TCC_TARGET_X86_64)
1230 case R_X86_64_GOT32:
1231 case R_X86_64_GOTTPOFF:
1232 case R_X86_64_GOTPCREL:
1233 case R_X86_64_PLT32:
1234 if (!s1->got)
1235 build_got(s1);
1236 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1237 type == R_X86_64_PLT32) {
1238 sym_index = ELFW(R_SYM)(rel->r_info);
1239 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1240 /* look at the symbol got offset. If none, then add one */
1241 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1242 reloc_type = R_X86_64_GLOB_DAT;
1243 else
1244 reloc_type = R_X86_64_JUMP_SLOT;
1245 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1246 sym_index);
1248 break;
1249 #else
1250 #error unsupported CPU
1251 #endif
1252 default:
1253 break;
1259 ST_FUNC Section *new_symtab(TCCState *s1,
1260 const char *symtab_name, int sh_type, int sh_flags,
1261 const char *strtab_name,
1262 const char *hash_name, int hash_sh_flags)
1264 Section *symtab, *strtab, *hash;
1265 int *ptr, nb_buckets;
1267 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1268 symtab->sh_entsize = sizeof(ElfW(Sym));
1269 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1270 put_elf_str(strtab, "");
1271 symtab->link = strtab;
1272 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1274 nb_buckets = 1;
1276 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1277 hash->sh_entsize = sizeof(int);
1278 symtab->hash = hash;
1279 hash->link = symtab;
1281 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1282 ptr[0] = nb_buckets;
1283 ptr[1] = 1;
1284 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1285 return symtab;
1288 /* put dynamic tag */
1289 static void put_dt(Section *dynamic, int dt, uplong val)
1291 ElfW(Dyn) *dyn;
1292 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1293 dyn->d_tag = dt;
1294 dyn->d_un.d_val = val;
1297 static void add_init_array_defines(TCCState *s1, const char *section_name)
1299 Section *s;
1300 long end_offset;
1301 char sym_start[1024];
1302 char sym_end[1024];
1304 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1305 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1307 s = find_section(s1, section_name);
1308 if (!s) {
1309 end_offset = 0;
1310 s = data_section;
1311 } else {
1312 end_offset = s->data_offset;
1315 add_elf_sym(symtab_section,
1316 0, 0,
1317 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1318 s->sh_num, sym_start);
1319 add_elf_sym(symtab_section,
1320 end_offset, 0,
1321 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1322 s->sh_num, sym_end);
1325 static int tcc_add_support(TCCState *s1, const char *filename)
1327 char buf[1024];
1328 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, filename);
1329 return tcc_add_file(s1, buf);
1332 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1334 #ifdef CONFIG_TCC_BCHECK
1335 unsigned long *ptr;
1336 Section *init_section;
1337 unsigned char *pinit;
1338 int sym_index;
1340 if (0 == s1->do_bounds_check)
1341 return;
1343 /* XXX: add an object file to do that */
1344 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1345 *ptr = 0;
1346 add_elf_sym(symtab_section, 0, 0,
1347 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1348 bounds_section->sh_num, "__bounds_start");
1349 /* add bound check code */
1350 #ifndef TCC_TARGET_PE
1351 tcc_add_support(s1, "bcheck.o");
1352 #endif
1353 #ifdef TCC_TARGET_I386
1354 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1355 /* add 'call __bound_init()' in .init section */
1356 init_section = find_section(s1, ".init");
1357 pinit = section_ptr_add(init_section, 5);
1358 pinit[0] = 0xe8;
1359 put32(pinit + 1, -4);
1360 sym_index = find_elf_sym(symtab_section, "__bound_init");
1361 put_elf_reloc(symtab_section, init_section,
1362 init_section->data_offset - 4, R_386_PC32, sym_index);
1364 #endif
1365 #endif
1368 /* add tcc runtime libraries */
1369 ST_FUNC void tcc_add_runtime(TCCState *s1)
1371 tcc_add_bcheck(s1);
1373 /* add libc */
1374 if (!s1->nostdlib) {
1375 tcc_add_library(s1, "c");
1376 #ifdef CONFIG_USE_LIBGCC
1377 tcc_add_file(s1, TCC_LIBGCC);
1378 #elif !defined WITHOUT_LIBTCC
1379 tcc_add_support(s1, "libtcc1.a");
1380 #endif
1381 /* add crt end if not memory output */
1382 if (s1->output_type != TCC_OUTPUT_MEMORY)
1383 tcc_add_crt(s1, "crtn.o");
1387 /* add various standard linker symbols (must be done after the
1388 sections are filled (for example after allocating common
1389 symbols)) */
1390 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1392 char buf[1024];
1393 int i;
1394 Section *s;
1396 add_elf_sym(symtab_section,
1397 text_section->data_offset, 0,
1398 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1399 text_section->sh_num, "_etext");
1400 add_elf_sym(symtab_section,
1401 data_section->data_offset, 0,
1402 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1403 data_section->sh_num, "_edata");
1404 add_elf_sym(symtab_section,
1405 bss_section->data_offset, 0,
1406 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1407 bss_section->sh_num, "_end");
1408 /* horrible new standard ldscript defines */
1409 add_init_array_defines(s1, ".preinit_array");
1410 add_init_array_defines(s1, ".init_array");
1411 add_init_array_defines(s1, ".fini_array");
1413 /* add start and stop symbols for sections whose name can be
1414 expressed in C */
1415 for(i = 1; i < s1->nb_sections; i++) {
1416 s = s1->sections[i];
1417 if (s->sh_type == SHT_PROGBITS &&
1418 (s->sh_flags & SHF_ALLOC)) {
1419 const char *p;
1420 int ch;
1422 /* check if section name can be expressed in C */
1423 p = s->name;
1424 for(;;) {
1425 ch = *p;
1426 if (!ch)
1427 break;
1428 if (!isid(ch) && !isnum(ch))
1429 goto next_sec;
1430 p++;
1432 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1433 add_elf_sym(symtab_section,
1434 0, 0,
1435 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1436 s->sh_num, buf);
1437 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1438 add_elf_sym(symtab_section,
1439 s->data_offset, 0,
1440 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1441 s->sh_num, buf);
1443 next_sec: ;
1447 static void tcc_output_binary(TCCState *s1, FILE *f,
1448 const int *section_order)
1450 Section *s;
1451 int i, offset, size;
1453 offset = 0;
1454 for(i=1;i<s1->nb_sections;i++) {
1455 s = s1->sections[section_order[i]];
1456 if (s->sh_type != SHT_NOBITS &&
1457 (s->sh_flags & SHF_ALLOC)) {
1458 while (offset < s->sh_offset) {
1459 fputc(0, f);
1460 offset++;
1462 size = s->sh_size;
1463 fwrite(s->data, 1, size, f);
1464 offset += size;
1469 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1470 #define HAVE_PHDR 1
1471 #define EXTRA_RELITEMS 14
1473 /* move the relocation value from .dynsym to .got */
1474 void patch_dynsym_undef(TCCState *s1, Section *s)
1476 uint32_t *gotd = (void *)s1->got->data;
1477 ElfW(Sym) *sym, *sym_end;
1479 gotd += 3; // dummy entries in .got
1480 /* relocate symbols in .dynsym */
1481 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1482 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1483 if (sym->st_shndx == SHN_UNDEF) {
1484 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1485 sym->st_value = 0;
1489 #else
1490 #define HAVE_PHDR 0
1491 #define EXTRA_RELITEMS 9
1493 /* zero plt offsets of weak symbols in .dynsym */
1494 void patch_dynsym_undef(TCCState *s1, Section *s)
1496 ElfW(Sym) *sym, *sym_end;
1498 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1499 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++)
1500 if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
1501 sym->st_value = 0;
1503 #endif
1505 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1507 int sym_index = ELFW(R_SYM) (rel->r_info);
1508 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1509 unsigned long offset;
1511 if (sym_index >= s1->nb_sym_infos)
1512 return;
1513 offset = s1->sym_infos[sym_index].got_offset << 1;
1514 section_reserve(s1->got, offset + PTR_SIZE);
1515 #ifdef TCC_TARGET_X86_64
1516 /* only works for x86-64 */
1517 put32(s1->got->data + offset + 4, sym->st_value >> 32);
1518 #endif
1519 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1522 ST_FUNC void fill_got(TCCState *s1)
1524 Section *s;
1525 ElfW_Rel *rel, *rel_end;
1526 int i;
1528 for(i = 1; i < s1->nb_sections; i++) {
1529 s = s1->sections[i];
1530 if (s->sh_type != SHT_RELX)
1531 continue;
1532 /* no need to handle got relocations */
1533 if (s->link != symtab_section)
1534 continue;
1535 rel_end = (ElfW_Rel *) (s->data + s->data_offset);
1536 for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
1537 switch (ELFW(R_TYPE) (rel->r_info)) {
1538 case R_X86_64_GOT32:
1539 case R_X86_64_GOTPCREL:
1540 case R_X86_64_PLT32:
1541 fill_got_entry(s1, rel);
1542 break;
1549 /* output an ELF file */
1550 /* XXX: suppress unneeded sections */
1551 static int elf_output_file(TCCState *s1, const char *filename)
1553 ElfW(Ehdr) ehdr;
1554 FILE *f;
1555 int fd, mode, ret;
1556 int *section_order;
1557 int shnum, i, phnum, file_offset, offset, size, j, sh_order_index, k;
1558 long long tmp;
1559 uplong addr;
1560 Section *strsec, *s;
1561 ElfW(Shdr) shdr, *sh;
1562 ElfW(Phdr) *phdr, *ph;
1563 Section *interp, *dynamic, *dynstr;
1564 unsigned long saved_dynamic_data_offset;
1565 ElfW(Sym) *sym;
1566 int type, file_type;
1567 uplong rel_addr, rel_size;
1568 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1569 uplong bss_addr, bss_size;
1570 #endif
1572 file_type = s1->output_type;
1573 s1->nb_errors = 0;
1575 if (file_type != TCC_OUTPUT_OBJ) {
1576 tcc_add_runtime(s1);
1579 phdr = NULL;
1580 section_order = NULL;
1581 interp = NULL;
1582 dynamic = NULL;
1583 dynstr = NULL; /* avoid warning */
1584 saved_dynamic_data_offset = 0; /* avoid warning */
1586 if (file_type != TCC_OUTPUT_OBJ) {
1587 relocate_common_syms();
1589 tcc_add_linker_symbols(s1);
1591 if (!s1->static_link) {
1592 const char *name;
1593 int sym_index, index;
1594 ElfW(Sym) *esym, *sym_end;
1596 if (file_type == TCC_OUTPUT_EXE) {
1597 char *ptr;
1598 /* allow override the dynamic loader */
1599 const char *elfint = getenv("LD_SO");
1600 if (elfint == NULL)
1601 elfint = CONFIG_TCC_ELFINTERP;
1602 /* add interpreter section only if executable */
1603 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1604 interp->sh_addralign = 1;
1605 ptr = section_ptr_add(interp, 1+strlen(elfint));
1606 strcpy(ptr, elfint);
1609 /* add dynamic symbol table */
1610 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1611 ".dynstr",
1612 ".hash", SHF_ALLOC);
1613 dynstr = s1->dynsym->link;
1615 /* add dynamic section */
1616 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1617 SHF_ALLOC | SHF_WRITE);
1618 dynamic->link = dynstr;
1619 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1621 /* add PLT */
1622 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1623 SHF_ALLOC | SHF_EXECINSTR);
1624 s1->plt->sh_entsize = 4;
1626 build_got(s1);
1628 /* scan for undefined symbols and see if they are in the
1629 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1630 is found, then we add it in the PLT. If a symbol
1631 STT_OBJECT is found, we add it in the .bss section with
1632 a suitable relocation */
1633 sym_end = (ElfW(Sym) *)(symtab_section->data +
1634 symtab_section->data_offset);
1635 if (file_type == TCC_OUTPUT_EXE) {
1636 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1637 sym < sym_end;
1638 sym++) {
1639 if (sym->st_shndx == SHN_UNDEF) {
1640 name = symtab_section->link->data + sym->st_name;
1641 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1642 if (sym_index) {
1643 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1644 type = ELFW(ST_TYPE)(esym->st_info);
1645 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1646 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1647 ELFW(ST_INFO)(STB_GLOBAL,type),
1648 sym - (ElfW(Sym) *)symtab_section->data);
1649 } else if (type == STT_OBJECT) {
1650 unsigned long offset;
1651 ElfW(Sym) *dynsym, *dynsym_end;
1652 offset = bss_section->data_offset;
1653 /* XXX: which alignment ? */
1654 offset = (offset + 16 - 1) & -16;
1655 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1656 esym->st_info, 0,
1657 bss_section->sh_num, name);
1658 // Ensure R_COPY works for weak symbol aliases
1659 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1660 dynsym_end = (ElfW(Sym) *)
1661 (s1->dynsymtab_section->data +
1662 s1->dynsymtab_section->data_offset);
1663 for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1664 dynsym < dynsym_end; dynsym++) {
1665 if ((dynsym->st_value == esym->st_value)
1666 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1667 char *dynname;
1668 dynname = s1->dynsymtab_section->link->data
1669 + dynsym->st_name;
1670 put_elf_sym(s1->dynsym, offset,
1671 dynsym->st_size,
1672 dynsym->st_info, 0,
1673 bss_section->sh_num,
1674 dynname);
1675 break;
1679 put_elf_reloc(s1->dynsym, bss_section,
1680 offset, R_COPY, index);
1681 offset += esym->st_size;
1682 bss_section->data_offset = offset;
1684 } else {
1685 /* STB_WEAK undefined symbols are accepted */
1686 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1687 it */
1688 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1689 !strcmp(name, "_fp_hw")) {
1690 } else {
1691 tcc_error_noabort("undefined symbol '%s'", name);
1694 } else if (s1->rdynamic &&
1695 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1696 /* if -rdynamic option, then export all non
1697 local symbols */
1698 name = symtab_section->link->data + sym->st_name;
1699 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1700 sym->st_info, 0,
1701 sym->st_shndx, name);
1705 if (s1->nb_errors)
1706 goto fail;
1708 /* now look at unresolved dynamic symbols and export
1709 corresponding symbol */
1710 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1711 s1->dynsymtab_section->data_offset);
1712 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1713 esym < sym_end;
1714 esym++) {
1715 if (esym->st_shndx == SHN_UNDEF) {
1716 name = s1->dynsymtab_section->link->data + esym->st_name;
1717 sym_index = find_elf_sym(symtab_section, name);
1718 if (sym_index) {
1719 /* XXX: avoid adding a symbol if already
1720 present because of -rdynamic ? */
1721 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1722 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1723 sym->st_info, 0,
1724 sym->st_shndx, name);
1725 } else {
1726 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1727 /* weak symbols can stay undefined */
1728 } else {
1729 tcc_warning("undefined dynamic symbol '%s'", name);
1734 } else {
1735 int nb_syms;
1736 /* shared library case : we simply export all the global symbols */
1737 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1738 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1739 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1740 sym < sym_end;
1741 sym++) {
1742 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1743 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1744 if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
1745 ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
1746 && sym->st_shndx == SHN_UNDEF) {
1747 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1748 sym->st_info,
1749 sym - (ElfW(Sym) *)symtab_section->data);
1751 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1752 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1753 sym->st_info,
1754 sym - (ElfW(Sym) *)symtab_section->data);
1756 else
1757 #endif
1759 name = symtab_section->link->data + sym->st_name;
1760 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1761 sym->st_info, 0,
1762 sym->st_shndx, name);
1763 s1->symtab_to_dynsym[sym -
1764 (ElfW(Sym) *)symtab_section->data] =
1765 index;
1771 build_got_entries(s1);
1773 /* add a list of needed dlls */
1774 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1775 DLLReference *dllref = s1->loaded_dlls[i];
1776 if (dllref->level == 0)
1777 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1780 if (s1->rpath)
1781 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1783 /* XXX: currently, since we do not handle PIC code, we
1784 must relocate the readonly segments */
1785 if (file_type == TCC_OUTPUT_DLL) {
1786 if (s1->soname)
1787 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1788 put_dt(dynamic, DT_TEXTREL, 0);
1791 if (s1->symbolic)
1792 put_dt(dynamic, DT_SYMBOLIC, 0);
1794 /* add necessary space for other entries */
1795 saved_dynamic_data_offset = dynamic->data_offset;
1796 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1797 } else {
1798 /* still need to build got entries in case of static link */
1799 build_got_entries(s1);
1803 memset(&ehdr, 0, sizeof(ehdr));
1805 /* we add a section for symbols */
1806 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1807 put_elf_str(strsec, "");
1809 /* compute number of sections */
1810 shnum = s1->nb_sections;
1812 /* this array is used to reorder sections in the output file */
1813 section_order = tcc_malloc(sizeof(int) * shnum);
1814 section_order[0] = 0;
1815 sh_order_index = 1;
1817 /* compute number of program headers */
1818 switch(file_type) {
1819 default:
1820 case TCC_OUTPUT_OBJ:
1821 phnum = 0;
1822 break;
1823 case TCC_OUTPUT_EXE:
1824 if (!s1->static_link)
1825 phnum = 4 + HAVE_PHDR;
1826 else
1827 phnum = 2;
1828 break;
1829 case TCC_OUTPUT_DLL:
1830 phnum = 3;
1831 break;
1834 /* allocate strings for section names and decide if an unallocated
1835 section should be output */
1836 /* NOTE: the strsec section comes last, so its size is also
1837 correct ! */
1838 for(i = 1; i < s1->nb_sections; i++) {
1839 s = s1->sections[i];
1840 s->sh_name = put_elf_str(strsec, s->name);
1841 #if 0 //gr
1842 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1843 s->sh_flags,
1844 s->sh_type,
1845 s->sh_info,
1846 s->name,
1847 s->reloc ? s->reloc->name : "n"
1849 #endif
1850 /* when generating a DLL, we include relocations but we may
1851 patch them */
1852 if (file_type == TCC_OUTPUT_DLL &&
1853 s->sh_type == SHT_RELX &&
1854 !(s->sh_flags & SHF_ALLOC)) {
1855 /* //gr: avoid bogus relocs for empty (debug) sections */
1856 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1857 prepare_dynamic_rel(s1, s);
1858 else if (s1->do_debug)
1859 s->sh_size = s->data_offset;
1860 } else if (s1->do_debug ||
1861 file_type == TCC_OUTPUT_OBJ ||
1862 (s->sh_flags & SHF_ALLOC) ||
1863 i == (s1->nb_sections - 1)) {
1864 /* we output all sections if debug or object file */
1865 s->sh_size = s->data_offset;
1869 /* allocate program segment headers */
1870 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1872 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1873 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1874 } else {
1875 file_offset = 0;
1877 if (phnum > 0) {
1878 /* compute section to program header mapping */
1879 if (s1->has_text_addr) {
1880 int a_offset, p_offset;
1881 addr = s1->text_addr;
1882 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1883 ELF_PAGE_SIZE */
1884 a_offset = (int) (addr & (s1->section_align - 1));
1885 p_offset = file_offset & (s1->section_align - 1);
1886 if (a_offset < p_offset)
1887 a_offset += s1->section_align;
1888 file_offset += (a_offset - p_offset);
1889 } else {
1890 if (file_type == TCC_OUTPUT_DLL)
1891 addr = 0;
1892 else
1893 addr = ELF_START_ADDR;
1894 /* compute address after headers */
1895 addr += (file_offset & (s1->section_align - 1));
1898 /* dynamic relocation table information, for .dynamic section */
1899 rel_size = 0;
1900 rel_addr = 0;
1902 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1903 bss_addr = bss_size = 0;
1904 #endif
1905 /* leave one program header for the program interpreter */
1906 ph = &phdr[0];
1907 if (interp)
1908 ph += 1 + HAVE_PHDR;
1910 for(j = 0; j < 2; j++) {
1911 ph->p_type = PT_LOAD;
1912 if (j == 0)
1913 ph->p_flags = PF_R | PF_X;
1914 else
1915 ph->p_flags = PF_R | PF_W;
1916 ph->p_align = s1->section_align;
1918 /* we do the following ordering: interp, symbol tables,
1919 relocations, progbits, nobits */
1920 /* XXX: do faster and simpler sorting */
1921 for(k = 0; k < 5; k++) {
1922 for(i = 1; i < s1->nb_sections; i++) {
1923 s = s1->sections[i];
1924 /* compute if section should be included */
1925 if (j == 0) {
1926 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1927 SHF_ALLOC)
1928 continue;
1929 } else {
1930 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1931 (SHF_ALLOC | SHF_WRITE))
1932 continue;
1934 if (s == interp) {
1935 if (k != 0)
1936 continue;
1937 } else if (s->sh_type == SHT_DYNSYM ||
1938 s->sh_type == SHT_STRTAB ||
1939 s->sh_type == SHT_HASH) {
1940 if (k != 1)
1941 continue;
1942 } else if (s->sh_type == SHT_RELX) {
1943 if (k != 2)
1944 continue;
1945 } else if (s->sh_type == SHT_NOBITS) {
1946 if (k != 4)
1947 continue;
1948 } else {
1949 if (k != 3)
1950 continue;
1952 section_order[sh_order_index++] = i;
1954 /* section matches: we align it and add its size */
1955 tmp = addr;
1956 addr = (addr + s->sh_addralign - 1) &
1957 ~(s->sh_addralign - 1);
1958 file_offset += (int) ( addr - tmp );
1959 s->sh_offset = file_offset;
1960 s->sh_addr = addr;
1962 /* update program header infos */
1963 if (ph->p_offset == 0) {
1964 ph->p_offset = file_offset;
1965 ph->p_vaddr = addr;
1966 ph->p_paddr = ph->p_vaddr;
1968 /* update dynamic relocation infos */
1969 if (s->sh_type == SHT_RELX) {
1970 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1971 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1972 rel_addr = addr;
1973 rel_size += s->sh_size; // XXX only first rel.
1975 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1976 bss_addr = addr;
1977 bss_size = s->sh_size; // XXX only first rel.
1979 #else
1980 if (rel_size == 0)
1981 rel_addr = addr;
1982 rel_size += s->sh_size;
1983 #endif
1985 addr += s->sh_size;
1986 if (s->sh_type != SHT_NOBITS)
1987 file_offset += s->sh_size;
1990 ph->p_filesz = file_offset - ph->p_offset;
1991 ph->p_memsz = addr - ph->p_vaddr;
1992 ph++;
1993 if (j == 0) {
1994 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1995 /* if in the middle of a page, we duplicate the page in
1996 memory so that one copy is RX and the other is RW */
1997 if ((addr & (s1->section_align - 1)) != 0)
1998 addr += s1->section_align;
1999 } else {
2000 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
2001 file_offset = (file_offset + s1->section_align - 1) &
2002 ~(s1->section_align - 1);
2007 /* if interpreter, then add corresponing program header */
2008 if (interp) {
2009 ph = &phdr[0];
2011 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2013 int len = phnum * sizeof(ElfW(Phdr));
2015 ph->p_type = PT_PHDR;
2016 ph->p_offset = sizeof(ElfW(Ehdr));
2017 ph->p_vaddr = interp->sh_addr - len;
2018 ph->p_paddr = ph->p_vaddr;
2019 ph->p_filesz = ph->p_memsz = len;
2020 ph->p_flags = PF_R | PF_X;
2021 ph->p_align = 4; // interp->sh_addralign;
2022 ph++;
2024 #endif
2026 ph->p_type = PT_INTERP;
2027 ph->p_offset = interp->sh_offset;
2028 ph->p_vaddr = interp->sh_addr;
2029 ph->p_paddr = ph->p_vaddr;
2030 ph->p_filesz = interp->sh_size;
2031 ph->p_memsz = interp->sh_size;
2032 ph->p_flags = PF_R;
2033 ph->p_align = interp->sh_addralign;
2036 /* if dynamic section, then add corresponing program header */
2037 if (dynamic) {
2038 ElfW(Sym) *sym_end;
2040 ph = &phdr[phnum - 1];
2042 ph->p_type = PT_DYNAMIC;
2043 ph->p_offset = dynamic->sh_offset;
2044 ph->p_vaddr = dynamic->sh_addr;
2045 ph->p_paddr = ph->p_vaddr;
2046 ph->p_filesz = dynamic->sh_size;
2047 ph->p_memsz = dynamic->sh_size;
2048 ph->p_flags = PF_R | PF_W;
2049 ph->p_align = dynamic->sh_addralign;
2051 /* put GOT dynamic section address */
2052 put32(s1->got->data, dynamic->sh_addr);
2054 /* relocate the PLT */
2055 if (file_type == TCC_OUTPUT_EXE
2056 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2057 || file_type == TCC_OUTPUT_DLL
2058 #endif
2060 uint8_t *p, *p_end;
2062 p = s1->plt->data;
2063 p_end = p + s1->plt->data_offset;
2064 if (p < p_end) {
2065 #if defined(TCC_TARGET_I386)
2066 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2067 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
2068 p += 16;
2069 while (p < p_end) {
2070 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2071 p += 16;
2073 #elif defined(TCC_TARGET_X86_64)
2074 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
2075 put32(p + 2, get32(p + 2) + x);
2076 put32(p + 8, get32(p + 8) + x - 6);
2077 p += 16;
2078 while (p < p_end) {
2079 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
2080 p += 16;
2082 #elif defined(TCC_TARGET_ARM)
2083 int x;
2084 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
2085 p += 16;
2086 while (p < p_end) {
2087 if (get32(p) == 0x46c04778) /* PLT Thumb stub present */
2088 p += 4;
2089 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
2090 p += 16;
2092 #elif defined(TCC_TARGET_C67)
2093 /* XXX: TODO */
2094 #else
2095 #error unsupported CPU
2096 #endif
2100 /* relocate symbols in .dynsym */
2101 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
2102 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
2103 sym < sym_end;
2104 sym++) {
2105 if (sym->st_shndx == SHN_UNDEF) {
2106 /* relocate to the PLT if the symbol corresponds
2107 to a PLT entry */
2108 if (sym->st_value)
2109 sym->st_value += s1->plt->sh_addr;
2110 } else if (sym->st_shndx < SHN_LORESERVE) {
2111 /* do symbol relocation */
2112 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
2116 /* put dynamic section entries */
2117 dynamic->data_offset = saved_dynamic_data_offset;
2118 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
2119 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
2120 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2121 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
2122 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2123 #ifdef TCC_TARGET_X86_64
2124 put_dt(dynamic, DT_RELA, rel_addr);
2125 put_dt(dynamic, DT_RELASZ, rel_size);
2126 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2127 #else
2128 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2129 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2130 put_dt(dynamic, DT_PLTRELSZ, rel_size);
2131 put_dt(dynamic, DT_JMPREL, rel_addr);
2132 put_dt(dynamic, DT_PLTREL, DT_REL);
2133 put_dt(dynamic, DT_REL, bss_addr);
2134 put_dt(dynamic, DT_RELSZ, bss_size);
2135 #else
2136 put_dt(dynamic, DT_REL, rel_addr);
2137 put_dt(dynamic, DT_RELSZ, rel_size);
2138 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2139 #endif
2140 #endif
2141 if (s1->do_debug)
2142 put_dt(dynamic, DT_DEBUG, 0);
2143 put_dt(dynamic, DT_NULL, 0);
2146 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2147 ehdr.e_phnum = phnum;
2148 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2151 /* all other sections come after */
2152 for(i = 1; i < s1->nb_sections; i++) {
2153 s = s1->sections[i];
2154 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2155 continue;
2156 section_order[sh_order_index++] = i;
2158 file_offset = (file_offset + s->sh_addralign - 1) &
2159 ~(s->sh_addralign - 1);
2160 s->sh_offset = file_offset;
2161 if (s->sh_type != SHT_NOBITS)
2162 file_offset += s->sh_size;
2165 /* if building executable or DLL, then relocate each section
2166 except the GOT which is already relocated */
2167 if (file_type != TCC_OUTPUT_OBJ) {
2168 relocate_syms(s1, 0);
2170 if (s1->nb_errors != 0) {
2171 fail:
2172 ret = -1;
2173 goto the_end;
2176 /* relocate sections */
2177 /* XXX: ignore sections with allocated relocations ? */
2178 for(i = 1; i < s1->nb_sections; i++) {
2179 s = s1->sections[i];
2180 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
2181 relocate_section(s1, s);
2184 /* relocate relocation entries if the relocation tables are
2185 allocated in the executable */
2186 for(i = 1; i < s1->nb_sections; i++) {
2187 s = s1->sections[i];
2188 if ((s->sh_flags & SHF_ALLOC) &&
2189 s->sh_type == SHT_RELX) {
2190 relocate_rel(s1, s);
2194 /* get entry point address */
2195 if (file_type == TCC_OUTPUT_EXE)
2196 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
2197 else
2198 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2200 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2201 fill_got(s1);
2203 /* write elf file */
2204 if (file_type == TCC_OUTPUT_OBJ)
2205 mode = 0666;
2206 else
2207 mode = 0777;
2208 unlink(filename);
2209 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2210 if (fd < 0) {
2211 tcc_error_noabort("could not write '%s'", filename);
2212 goto fail;
2214 f = fdopen(fd, "wb");
2215 if (s1->verbose)
2216 printf("<- %s\n", filename);
2218 #ifdef TCC_TARGET_COFF
2219 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2220 tcc_output_coff(s1, f);
2221 } else
2222 #endif
2223 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2224 sort_syms(s1, symtab_section);
2226 /* align to 4 */
2227 file_offset = (file_offset + 3) & -4;
2229 /* fill header */
2230 ehdr.e_ident[0] = ELFMAG0;
2231 ehdr.e_ident[1] = ELFMAG1;
2232 ehdr.e_ident[2] = ELFMAG2;
2233 ehdr.e_ident[3] = ELFMAG3;
2234 ehdr.e_ident[4] = ELFCLASSW;
2235 ehdr.e_ident[5] = ELFDATA2LSB;
2236 ehdr.e_ident[6] = EV_CURRENT;
2237 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2238 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2239 #endif
2240 #ifdef TCC_TARGET_ARM
2241 #ifdef TCC_ARM_EABI
2242 ehdr.e_ident[EI_OSABI] = 0;
2243 ehdr.e_flags = 4 << 24;
2244 #else
2245 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2246 #endif
2247 #endif
2248 switch(file_type) {
2249 default:
2250 case TCC_OUTPUT_EXE:
2251 ehdr.e_type = ET_EXEC;
2252 break;
2253 case TCC_OUTPUT_DLL:
2254 ehdr.e_type = ET_DYN;
2255 break;
2256 case TCC_OUTPUT_OBJ:
2257 ehdr.e_type = ET_REL;
2258 break;
2260 ehdr.e_machine = EM_TCC_TARGET;
2261 ehdr.e_version = EV_CURRENT;
2262 ehdr.e_shoff = file_offset;
2263 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2264 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2265 ehdr.e_shnum = shnum;
2266 ehdr.e_shstrndx = shnum - 1;
2268 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2269 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2270 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2272 for(i=1;i<s1->nb_sections;i++) {
2273 s = s1->sections[section_order[i]];
2274 if (s->sh_type != SHT_NOBITS) {
2275 if (s->sh_type == SHT_DYNSYM)
2276 patch_dynsym_undef(s1, s);
2277 while (offset < s->sh_offset) {
2278 fputc(0, f);
2279 offset++;
2281 size = s->sh_size;
2282 fwrite(s->data, 1, size, f);
2283 offset += size;
2287 /* output section headers */
2288 while (offset < ehdr.e_shoff) {
2289 fputc(0, f);
2290 offset++;
2293 for(i=0;i<s1->nb_sections;i++) {
2294 sh = &shdr;
2295 memset(sh, 0, sizeof(ElfW(Shdr)));
2296 s = s1->sections[i];
2297 if (s) {
2298 sh->sh_name = s->sh_name;
2299 sh->sh_type = s->sh_type;
2300 sh->sh_flags = s->sh_flags;
2301 sh->sh_entsize = s->sh_entsize;
2302 sh->sh_info = s->sh_info;
2303 if (s->link)
2304 sh->sh_link = s->link->sh_num;
2305 sh->sh_addralign = s->sh_addralign;
2306 sh->sh_addr = s->sh_addr;
2307 sh->sh_offset = s->sh_offset;
2308 sh->sh_size = s->sh_size;
2310 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2312 } else {
2313 tcc_output_binary(s1, f, section_order);
2315 fclose(f);
2317 ret = 0;
2318 the_end:
2319 tcc_free(s1->symtab_to_dynsym);
2320 tcc_free(section_order);
2321 tcc_free(phdr);
2322 tcc_free(s1->sym_infos);
2323 return ret;
2326 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2328 int ret;
2329 #ifdef TCC_TARGET_PE
2330 if (s->output_type != TCC_OUTPUT_OBJ) {
2331 ret = pe_output_file(s, filename);
2332 } else
2333 #endif
2335 ret = elf_output_file(s, filename);
2337 return ret;
2340 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2342 void *data;
2344 data = tcc_malloc(size);
2345 lseek(fd, file_offset, SEEK_SET);
2346 read(fd, data, size);
2347 return data;
2350 typedef struct SectionMergeInfo {
2351 Section *s; /* corresponding existing section */
2352 unsigned long offset; /* offset of the new section in the existing section */
2353 uint8_t new_section; /* true if section 's' was added */
2354 uint8_t link_once; /* true if link once section */
2355 } SectionMergeInfo;
2357 /* load an object file and merge it with current files */
2358 /* XXX: handle correctly stab (debug) info */
2359 ST_FUNC int tcc_load_object_file(TCCState *s1,
2360 int fd, unsigned long file_offset)
2362 ElfW(Ehdr) ehdr;
2363 ElfW(Shdr) *shdr, *sh;
2364 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2365 unsigned char *strsec, *strtab;
2366 int *old_to_new_syms;
2367 char *sh_name, *name;
2368 SectionMergeInfo *sm_table, *sm;
2369 ElfW(Sym) *sym, *symtab;
2370 ElfW_Rel *rel, *rel_end;
2371 Section *s;
2373 int stab_index;
2374 int stabstr_index;
2376 stab_index = stabstr_index = 0;
2378 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2379 goto fail1;
2380 if (ehdr.e_ident[0] != ELFMAG0 ||
2381 ehdr.e_ident[1] != ELFMAG1 ||
2382 ehdr.e_ident[2] != ELFMAG2 ||
2383 ehdr.e_ident[3] != ELFMAG3)
2384 goto fail1;
2385 /* test if object file */
2386 if (ehdr.e_type != ET_REL)
2387 goto fail1;
2388 /* test CPU specific stuff */
2389 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2390 ehdr.e_machine != EM_TCC_TARGET) {
2391 fail1:
2392 tcc_error_noabort("invalid object file");
2393 return -1;
2395 /* read sections */
2396 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2397 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2398 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2400 /* load section names */
2401 sh = &shdr[ehdr.e_shstrndx];
2402 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2404 /* load symtab and strtab */
2405 old_to_new_syms = NULL;
2406 symtab = NULL;
2407 strtab = NULL;
2408 nb_syms = 0;
2409 for(i = 1; i < ehdr.e_shnum; i++) {
2410 sh = &shdr[i];
2411 if (sh->sh_type == SHT_SYMTAB) {
2412 if (symtab) {
2413 tcc_error_noabort("object must contain only one symtab");
2414 fail:
2415 ret = -1;
2416 goto the_end;
2418 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2419 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2420 sm_table[i].s = symtab_section;
2422 /* now load strtab */
2423 sh = &shdr[sh->sh_link];
2424 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2428 /* now examine each section and try to merge its content with the
2429 ones in memory */
2430 for(i = 1; i < ehdr.e_shnum; i++) {
2431 /* no need to examine section name strtab */
2432 if (i == ehdr.e_shstrndx)
2433 continue;
2434 sh = &shdr[i];
2435 sh_name = strsec + sh->sh_name;
2436 /* ignore sections types we do not handle */
2437 if (sh->sh_type != SHT_PROGBITS &&
2438 sh->sh_type != SHT_RELX &&
2439 #ifdef TCC_ARM_EABI
2440 sh->sh_type != SHT_ARM_EXIDX &&
2441 #endif
2442 sh->sh_type != SHT_NOBITS &&
2443 sh->sh_type != SHT_PREINIT_ARRAY &&
2444 sh->sh_type != SHT_INIT_ARRAY &&
2445 sh->sh_type != SHT_FINI_ARRAY &&
2446 strcmp(sh_name, ".stabstr")
2448 continue;
2449 if (sh->sh_addralign < 1)
2450 sh->sh_addralign = 1;
2451 /* find corresponding section, if any */
2452 for(j = 1; j < s1->nb_sections;j++) {
2453 s = s1->sections[j];
2454 if (!strcmp(s->name, sh_name)) {
2455 if (!strncmp(sh_name, ".gnu.linkonce",
2456 sizeof(".gnu.linkonce") - 1)) {
2457 /* if a 'linkonce' section is already present, we
2458 do not add it again. It is a little tricky as
2459 symbols can still be defined in
2460 it. */
2461 sm_table[i].link_once = 1;
2462 goto next;
2463 } else {
2464 goto found;
2468 /* not found: create new section */
2469 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2470 /* take as much info as possible from the section. sh_link and
2471 sh_info will be updated later */
2472 s->sh_addralign = sh->sh_addralign;
2473 s->sh_entsize = sh->sh_entsize;
2474 sm_table[i].new_section = 1;
2475 found:
2476 if (sh->sh_type != s->sh_type) {
2477 tcc_error_noabort("invalid section type");
2478 goto fail;
2481 /* align start of section */
2482 offset = s->data_offset;
2484 if (0 == strcmp(sh_name, ".stab")) {
2485 stab_index = i;
2486 goto no_align;
2488 if (0 == strcmp(sh_name, ".stabstr")) {
2489 stabstr_index = i;
2490 goto no_align;
2493 size = sh->sh_addralign - 1;
2494 offset = (offset + size) & ~size;
2495 if (sh->sh_addralign > s->sh_addralign)
2496 s->sh_addralign = sh->sh_addralign;
2497 s->data_offset = offset;
2498 no_align:
2499 sm_table[i].offset = offset;
2500 sm_table[i].s = s;
2501 /* concatenate sections */
2502 size = sh->sh_size;
2503 if (sh->sh_type != SHT_NOBITS) {
2504 unsigned char *ptr;
2505 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2506 ptr = section_ptr_add(s, size);
2507 read(fd, ptr, size);
2508 } else {
2509 s->data_offset += size;
2511 next: ;
2514 /* //gr relocate stab strings */
2515 if (stab_index && stabstr_index) {
2516 Stab_Sym *a, *b;
2517 unsigned o;
2518 s = sm_table[stab_index].s;
2519 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2520 b = (Stab_Sym *)(s->data + s->data_offset);
2521 o = sm_table[stabstr_index].offset;
2522 while (a < b)
2523 a->n_strx += o, a++;
2526 /* second short pass to update sh_link and sh_info fields of new
2527 sections */
2528 for(i = 1; i < ehdr.e_shnum; i++) {
2529 s = sm_table[i].s;
2530 if (!s || !sm_table[i].new_section)
2531 continue;
2532 sh = &shdr[i];
2533 if (sh->sh_link > 0)
2534 s->link = sm_table[sh->sh_link].s;
2535 if (sh->sh_type == SHT_RELX) {
2536 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2537 /* update backward link */
2538 s1->sections[s->sh_info]->reloc = s;
2541 sm = sm_table;
2543 /* resolve symbols */
2544 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2546 sym = symtab + 1;
2547 for(i = 1; i < nb_syms; i++, sym++) {
2548 if (sym->st_shndx != SHN_UNDEF &&
2549 sym->st_shndx < SHN_LORESERVE) {
2550 sm = &sm_table[sym->st_shndx];
2551 if (sm->link_once) {
2552 /* if a symbol is in a link once section, we use the
2553 already defined symbol. It is very important to get
2554 correct relocations */
2555 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2556 name = strtab + sym->st_name;
2557 sym_index = find_elf_sym(symtab_section, name);
2558 if (sym_index)
2559 old_to_new_syms[i] = sym_index;
2561 continue;
2563 /* if no corresponding section added, no need to add symbol */
2564 if (!sm->s)
2565 continue;
2566 /* convert section number */
2567 sym->st_shndx = sm->s->sh_num;
2568 /* offset value */
2569 sym->st_value += sm->offset;
2571 /* add symbol */
2572 name = strtab + sym->st_name;
2573 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2574 sym->st_info, sym->st_other,
2575 sym->st_shndx, name);
2576 old_to_new_syms[i] = sym_index;
2579 /* third pass to patch relocation entries */
2580 for(i = 1; i < ehdr.e_shnum; i++) {
2581 s = sm_table[i].s;
2582 if (!s)
2583 continue;
2584 sh = &shdr[i];
2585 offset = sm_table[i].offset;
2586 switch(s->sh_type) {
2587 case SHT_RELX:
2588 /* take relocation offset information */
2589 offseti = sm_table[sh->sh_info].offset;
2590 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2591 for(rel = (ElfW_Rel *)(s->data + offset);
2592 rel < rel_end;
2593 rel++) {
2594 int type;
2595 unsigned sym_index;
2596 /* convert symbol index */
2597 type = ELFW(R_TYPE)(rel->r_info);
2598 sym_index = ELFW(R_SYM)(rel->r_info);
2599 /* NOTE: only one symtab assumed */
2600 if (sym_index >= nb_syms)
2601 goto invalid_reloc;
2602 sym_index = old_to_new_syms[sym_index];
2603 /* ignore link_once in rel section. */
2604 if (!sym_index && !sm->link_once
2605 #ifdef TCC_TARGET_ARM
2606 && type != R_ARM_V4BX
2607 #endif
2609 invalid_reloc:
2610 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2611 i, strsec + sh->sh_name, rel->r_offset);
2612 goto fail;
2614 rel->r_info = ELFW(R_INFO)(sym_index, type);
2615 /* offset the relocation offset */
2616 rel->r_offset += offseti;
2617 #ifdef TCC_TARGET_ARM
2618 /* Jumps and branches from a Thumb code to a PLT entry need
2619 special handling since PLT entries are ARM code.
2620 Unconditional bl instructions referencing PLT entries are
2621 handled by converting these instructions into blx
2622 instructions. Other case of instructions referencing a PLT
2623 entry require to add a Thumb stub before the PLT entry to
2624 switch to ARM mode. We set bit 0 of the got offset of a
2625 symbol to indicate such a case. */
2626 if (type == R_ARM_THM_JUMP24) {
2627 put_plt_thumb_stub(s1, sym_index, 1);
2629 #endif
2631 break;
2632 default:
2633 break;
2637 ret = 0;
2638 the_end:
2639 tcc_free(symtab);
2640 tcc_free(strtab);
2641 tcc_free(old_to_new_syms);
2642 tcc_free(sm_table);
2643 tcc_free(strsec);
2644 tcc_free(shdr);
2645 return ret;
2648 typedef struct ArchiveHeader {
2649 char ar_name[16]; /* name of this member */
2650 char ar_date[12]; /* file mtime */
2651 char ar_uid[6]; /* owner uid; printed as decimal */
2652 char ar_gid[6]; /* owner gid; printed as decimal */
2653 char ar_mode[8]; /* file mode, printed as octal */
2654 char ar_size[10]; /* file size, printed as decimal */
2655 char ar_fmag[2]; /* should contain ARFMAG */
2656 } ArchiveHeader;
2658 static int get_be32(const uint8_t *b)
2660 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2663 /* load only the objects which resolve undefined symbols */
2664 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2666 int i, bound, nsyms, sym_index, off, ret;
2667 uint8_t *data;
2668 const char *ar_names, *p;
2669 const uint8_t *ar_index;
2670 ElfW(Sym) *sym;
2672 data = tcc_malloc(size);
2673 if (read(fd, data, size) != size)
2674 goto fail;
2675 nsyms = get_be32(data);
2676 ar_index = data + 4;
2677 ar_names = ar_index + nsyms * 4;
2679 do {
2680 bound = 0;
2681 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2682 sym_index = find_elf_sym(symtab_section, p);
2683 if(sym_index) {
2684 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2685 if(sym->st_shndx == SHN_UNDEF) {
2686 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2687 #if 0
2688 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2689 #endif
2690 ++bound;
2691 lseek(fd, off, SEEK_SET);
2692 if(tcc_load_object_file(s1, fd, off) < 0) {
2693 fail:
2694 ret = -1;
2695 goto the_end;
2700 } while(bound);
2701 ret = 0;
2702 the_end:
2703 tcc_free(data);
2704 return ret;
2707 /* load a '.a' file */
2708 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2710 ArchiveHeader hdr;
2711 char ar_size[11];
2712 char ar_name[17];
2713 char magic[8];
2714 int size, len, i;
2715 unsigned long file_offset;
2717 /* skip magic which was already checked */
2718 read(fd, magic, sizeof(magic));
2720 for(;;) {
2721 len = read(fd, &hdr, sizeof(hdr));
2722 if (len == 0)
2723 break;
2724 if (len != sizeof(hdr)) {
2725 tcc_error_noabort("invalid archive");
2726 return -1;
2728 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2729 ar_size[sizeof(hdr.ar_size)] = '\0';
2730 size = strtol(ar_size, NULL, 0);
2731 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2732 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2733 if (ar_name[i] != ' ')
2734 break;
2736 ar_name[i + 1] = '\0';
2737 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2738 file_offset = lseek(fd, 0, SEEK_CUR);
2739 /* align to even */
2740 size = (size + 1) & ~1;
2741 if (!strcmp(ar_name, "/")) {
2742 /* coff symbol table : we handle it */
2743 if(s1->alacarte_link)
2744 return tcc_load_alacarte(s1, fd, size);
2745 } else if (!strcmp(ar_name, "//") ||
2746 !strcmp(ar_name, "__.SYMDEF") ||
2747 !strcmp(ar_name, "__.SYMDEF/") ||
2748 !strcmp(ar_name, "ARFILENAMES/")) {
2749 /* skip symbol table or archive names */
2750 } else {
2751 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2752 return -1;
2754 lseek(fd, file_offset + size, SEEK_SET);
2756 return 0;
2759 #ifndef TCC_TARGET_PE
2760 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2761 is referenced by the user (so it should be added as DT_NEEDED in
2762 the generated ELF file) */
2763 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2765 ElfW(Ehdr) ehdr;
2766 ElfW(Shdr) *shdr, *sh, *sh1;
2767 int i, j, nb_syms, nb_dts, sym_bind, ret;
2768 ElfW(Sym) *sym, *dynsym;
2769 ElfW(Dyn) *dt, *dynamic;
2770 unsigned char *dynstr;
2771 const char *name, *soname;
2772 DLLReference *dllref;
2774 read(fd, &ehdr, sizeof(ehdr));
2776 /* test CPU specific stuff */
2777 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2778 ehdr.e_machine != EM_TCC_TARGET) {
2779 tcc_error_noabort("bad architecture");
2780 return -1;
2783 /* read sections */
2784 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2786 /* load dynamic section and dynamic symbols */
2787 nb_syms = 0;
2788 nb_dts = 0;
2789 dynamic = NULL;
2790 dynsym = NULL; /* avoid warning */
2791 dynstr = NULL; /* avoid warning */
2792 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2793 switch(sh->sh_type) {
2794 case SHT_DYNAMIC:
2795 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2796 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2797 break;
2798 case SHT_DYNSYM:
2799 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2800 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2801 sh1 = &shdr[sh->sh_link];
2802 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2803 break;
2804 default:
2805 break;
2809 /* compute the real library name */
2810 soname = tcc_basename(filename);
2812 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2813 if (dt->d_tag == DT_SONAME) {
2814 soname = dynstr + dt->d_un.d_val;
2818 /* if the dll is already loaded, do not load it */
2819 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2820 dllref = s1->loaded_dlls[i];
2821 if (!strcmp(soname, dllref->name)) {
2822 /* but update level if needed */
2823 if (level < dllref->level)
2824 dllref->level = level;
2825 ret = 0;
2826 goto the_end;
2830 // printf("loading dll '%s'\n", soname);
2832 /* add the dll and its level */
2833 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2834 dllref->level = level;
2835 strcpy(dllref->name, soname);
2836 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2838 /* add dynamic symbols in dynsym_section */
2839 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2840 sym_bind = ELFW(ST_BIND)(sym->st_info);
2841 if (sym_bind == STB_LOCAL)
2842 continue;
2843 name = dynstr + sym->st_name;
2844 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2845 sym->st_info, sym->st_other, sym->st_shndx, name);
2848 /* load all referenced DLLs */
2849 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2850 switch(dt->d_tag) {
2851 case DT_NEEDED:
2852 name = dynstr + dt->d_un.d_val;
2853 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2854 dllref = s1->loaded_dlls[j];
2855 if (!strcmp(name, dllref->name))
2856 goto already_loaded;
2858 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2859 tcc_error_noabort("referenced dll '%s' not found", name);
2860 ret = -1;
2861 goto the_end;
2863 already_loaded:
2864 break;
2867 ret = 0;
2868 the_end:
2869 tcc_free(dynstr);
2870 tcc_free(dynsym);
2871 tcc_free(dynamic);
2872 tcc_free(shdr);
2873 return ret;
2876 #define LD_TOK_NAME 256
2877 #define LD_TOK_EOF (-1)
2879 /* return next ld script token */
2880 static int ld_next(TCCState *s1, char *name, int name_size)
2882 int c;
2883 char *q;
2885 redo:
2886 switch(ch) {
2887 case ' ':
2888 case '\t':
2889 case '\f':
2890 case '\v':
2891 case '\r':
2892 case '\n':
2893 inp();
2894 goto redo;
2895 case '/':
2896 minp();
2897 if (ch == '*') {
2898 file->buf_ptr = parse_comment(file->buf_ptr);
2899 ch = file->buf_ptr[0];
2900 goto redo;
2901 } else {
2902 q = name;
2903 *q++ = '/';
2904 goto parse_name;
2906 break;
2907 /* case 'a' ... 'z': */
2908 case 'a':
2909 case 'b':
2910 case 'c':
2911 case 'd':
2912 case 'e':
2913 case 'f':
2914 case 'g':
2915 case 'h':
2916 case 'i':
2917 case 'j':
2918 case 'k':
2919 case 'l':
2920 case 'm':
2921 case 'n':
2922 case 'o':
2923 case 'p':
2924 case 'q':
2925 case 'r':
2926 case 's':
2927 case 't':
2928 case 'u':
2929 case 'v':
2930 case 'w':
2931 case 'x':
2932 case 'y':
2933 case 'z':
2934 /* case 'A' ... 'z': */
2935 case 'A':
2936 case 'B':
2937 case 'C':
2938 case 'D':
2939 case 'E':
2940 case 'F':
2941 case 'G':
2942 case 'H':
2943 case 'I':
2944 case 'J':
2945 case 'K':
2946 case 'L':
2947 case 'M':
2948 case 'N':
2949 case 'O':
2950 case 'P':
2951 case 'Q':
2952 case 'R':
2953 case 'S':
2954 case 'T':
2955 case 'U':
2956 case 'V':
2957 case 'W':
2958 case 'X':
2959 case 'Y':
2960 case 'Z':
2961 case '_':
2962 case '\\':
2963 case '.':
2964 case '$':
2965 case '~':
2966 q = name;
2967 parse_name:
2968 for(;;) {
2969 if (!((ch >= 'a' && ch <= 'z') ||
2970 (ch >= 'A' && ch <= 'Z') ||
2971 (ch >= '0' && ch <= '9') ||
2972 strchr("/.-_+=$:\\,~", ch)))
2973 break;
2974 if ((q - name) < name_size - 1) {
2975 *q++ = ch;
2977 minp();
2979 *q = '\0';
2980 c = LD_TOK_NAME;
2981 break;
2982 case CH_EOF:
2983 c = LD_TOK_EOF;
2984 break;
2985 default:
2986 c = ch;
2987 inp();
2988 break;
2990 #if 0
2991 printf("tok=%c %d\n", c, c);
2992 if (c == LD_TOK_NAME)
2993 printf(" name=%s\n", name);
2994 #endif
2995 return c;
2999 * Extract the file name from the library name
3001 * /!\ No test on filename capacity, be careful
3003 static void libname_to_filename(TCCState *s1, const char libname[], char filename[])
3005 if (!s1->static_link) {
3006 sprintf(filename, "lib%s.so", libname);
3007 } else {
3008 sprintf(filename, "lib%s.a", libname);
3012 static int ld_add_file(TCCState *s1, const char filename[])
3014 int ret;
3016 ret = tcc_add_file_internal(s1, filename, 0);
3017 if (ret)
3018 ret = tcc_add_dll(s1, filename, 0);
3019 return ret;
3022 static inline int new_undef_syms(void)
3024 int ret = 0;
3025 ret = new_undef_sym;
3026 new_undef_sym = 0;
3027 return ret;
3030 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
3032 char filename[1024], libname[1024];
3033 int t, group, nblibs = 0, ret = 0;
3034 char **libs = NULL;
3036 group = !strcmp(cmd, "GROUP");
3037 if (!as_needed)
3038 new_undef_syms();
3039 t = ld_next(s1, filename, sizeof(filename));
3040 if (t != '(')
3041 expect("(");
3042 t = ld_next(s1, filename, sizeof(filename));
3043 for(;;) {
3044 libname[0] = '\0';
3045 if (t == LD_TOK_EOF) {
3046 tcc_error_noabort("unexpected end of file");
3047 ret = -1;
3048 goto lib_parse_error;
3049 } else if (t == ')') {
3050 break;
3051 } else if (t == '-') {
3052 t = ld_next(s1, filename, sizeof(filename));
3053 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
3054 tcc_error_noabort("library name expected");
3055 ret = -1;
3056 goto lib_parse_error;
3058 strcpy(libname, &filename[1]);
3059 libname_to_filename(s1, libname, filename);
3060 } else if (t != LD_TOK_NAME) {
3061 tcc_error_noabort("filename expected");
3062 ret = -1;
3063 goto lib_parse_error;
3065 if (!strcmp(filename, "AS_NEEDED")) {
3066 ret = ld_add_file_list(s1, cmd, 1);
3067 if (ret)
3068 goto lib_parse_error;
3069 } else {
3070 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3071 if (!as_needed) {
3072 ret = ld_add_file(s1, filename);
3073 if (ret)
3074 goto lib_parse_error;
3075 if (group) {
3076 /* Add the filename *and* the libname to avoid future conversions */
3077 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
3078 if (libname[0] != '\0')
3079 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
3083 t = ld_next(s1, filename, sizeof(filename));
3084 if (t == ',') {
3085 t = ld_next(s1, filename, sizeof(filename));
3088 if (group && !as_needed) {
3089 while (new_undef_syms()) {
3090 int i;
3092 for (i = 0; i < nblibs; i ++)
3093 ld_add_file(s1, libs[i]);
3096 lib_parse_error:
3097 dynarray_reset(&libs, &nblibs);
3098 return ret;
3101 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3102 files */
3103 ST_FUNC int tcc_load_ldscript(TCCState *s1)
3105 char cmd[64];
3106 char filename[1024];
3107 int t, ret;
3109 ch = file->buf_ptr[0];
3110 ch = handle_eob();
3111 for(;;) {
3112 t = ld_next(s1, cmd, sizeof(cmd));
3113 if (t == LD_TOK_EOF)
3114 return 0;
3115 else if (t != LD_TOK_NAME)
3116 return -1;
3117 if (!strcmp(cmd, "INPUT") ||
3118 !strcmp(cmd, "GROUP")) {
3119 ret = ld_add_file_list(s1, cmd, 0);
3120 if (ret)
3121 return ret;
3122 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3123 !strcmp(cmd, "TARGET")) {
3124 /* ignore some commands */
3125 t = ld_next(s1, cmd, sizeof(cmd));
3126 if (t != '(')
3127 expect("(");
3128 for(;;) {
3129 t = ld_next(s1, filename, sizeof(filename));
3130 if (t == LD_TOK_EOF) {
3131 tcc_error_noabort("unexpected end of file");
3132 return -1;
3133 } else if (t == ')') {
3134 break;
3137 } else {
3138 return -1;
3141 return 0;
3143 #endif /* ndef TCC_TARGET_PE */