tccgen: 32bits: fix PTR +/- long long
[tinycc.git] / tccelf.c
blobe6468b2abbaa4f08d0cf5ab74487281ecfc50e05
1 /*
2 * ELF file handling for TCC
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 /* Define this to get some debug output during relocation processing. */
24 #undef DEBUG_RELOC
26 /* XXX: avoid static variable */
27 static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */
29 ST_FUNC int put_elf_str(Section *s, const char *sym)
31 int offset, len;
32 char *ptr;
34 len = strlen(sym) + 1;
35 offset = s->data_offset;
36 ptr = section_ptr_add(s, len);
37 memcpy(ptr, sym, len);
38 return offset;
41 /* elf symbol hashing function */
42 static unsigned long elf_hash(const unsigned char *name)
44 unsigned long h = 0, g;
46 while (*name) {
47 h = (h << 4) + *name++;
48 g = h & 0xf0000000;
49 if (g)
50 h ^= g >> 24;
51 h &= ~g;
53 return h;
56 /* rebuild hash table of section s */
57 /* NOTE: we do factorize the hash table code to go faster */
58 static void rebuild_hash(Section *s, unsigned int nb_buckets)
60 ElfW(Sym) *sym;
61 int *ptr, *hash, nb_syms, sym_index, h;
62 unsigned char *strtab;
64 strtab = s->link->data;
65 nb_syms = s->data_offset / sizeof(ElfW(Sym));
67 s->hash->data_offset = 0;
68 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
69 ptr[0] = nb_buckets;
70 ptr[1] = nb_syms;
71 ptr += 2;
72 hash = ptr;
73 memset(hash, 0, (nb_buckets + 1) * sizeof(int));
74 ptr += nb_buckets + 1;
76 sym = (ElfW(Sym) *)s->data + 1;
77 for(sym_index = 1; sym_index < nb_syms; sym_index++) {
78 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
79 h = elf_hash(strtab + sym->st_name) % nb_buckets;
80 *ptr = hash[h];
81 hash[h] = sym_index;
82 } else {
83 *ptr = 0;
85 ptr++;
86 sym++;
90 /* return the symbol number */
91 ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size,
92 int info, int other, int shndx, const char *name)
94 int name_offset, sym_index;
95 int nbuckets, h;
96 ElfW(Sym) *sym;
97 Section *hs;
99 sym = section_ptr_add(s, sizeof(ElfW(Sym)));
100 if (name)
101 name_offset = put_elf_str(s->link, name);
102 else
103 name_offset = 0;
104 /* XXX: endianness */
105 sym->st_name = name_offset;
106 sym->st_value = value;
107 sym->st_size = size;
108 sym->st_info = info;
109 sym->st_other = other;
110 sym->st_shndx = shndx;
111 sym_index = sym - (ElfW(Sym) *)s->data;
112 hs = s->hash;
113 if (hs) {
114 int *ptr, *base;
115 ptr = section_ptr_add(hs, sizeof(int));
116 base = (int *)hs->data;
117 /* only add global or weak symbols */
118 if (ELFW(ST_BIND)(info) != STB_LOCAL) {
119 /* add another hashing entry */
120 nbuckets = base[0];
121 h = elf_hash((unsigned char *) name) % nbuckets;
122 *ptr = base[2 + h];
123 base[2 + h] = sym_index;
124 base[1]++;
125 /* we resize the hash table */
126 hs->nb_hashed_syms++;
127 if (hs->nb_hashed_syms > 2 * nbuckets) {
128 rebuild_hash(s, 2 * nbuckets);
130 } else {
131 *ptr = 0;
132 base[1]++;
135 return sym_index;
138 /* find global ELF symbol 'name' and return its index. Return 0 if not
139 found. */
140 ST_FUNC int find_elf_sym(Section *s, const char *name)
142 ElfW(Sym) *sym;
143 Section *hs;
144 int nbuckets, sym_index, h;
145 const char *name1;
147 hs = s->hash;
148 if (!hs)
149 return 0;
150 nbuckets = ((int *)hs->data)[0];
151 h = elf_hash((unsigned char *) name) % nbuckets;
152 sym_index = ((int *)hs->data)[2 + h];
153 while (sym_index != 0) {
154 sym = &((ElfW(Sym) *)s->data)[sym_index];
155 name1 = (char *) s->link->data + sym->st_name;
156 if (!strcmp(name, name1))
157 return sym_index;
158 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
160 return 0;
163 /* return elf symbol value, signal error if 'err' is nonzero */
164 ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err)
166 int sym_index;
167 ElfW(Sym) *sym;
169 sym_index = find_elf_sym(s->symtab, name);
170 sym = &((ElfW(Sym) *)s->symtab->data)[sym_index];
171 if (!sym_index || sym->st_shndx == SHN_UNDEF) {
172 if (err)
173 tcc_error("%s not defined", name);
174 return 0;
176 return sym->st_value;
179 /* return elf symbol value */
180 LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
182 return (void*)(uintptr_t)get_elf_sym_addr(s, name, 0);
185 #if defined TCC_IS_NATIVE || defined TCC_TARGET_PE
186 /* return elf symbol value or error */
187 ST_FUNC void* tcc_get_symbol_err(TCCState *s, const char *name)
189 return (void*)(uintptr_t)get_elf_sym_addr(s, name, 1);
191 #endif
193 /* add an elf symbol : check if it is already defined and patch
194 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
195 ST_FUNC int add_elf_sym(Section *s, addr_t value, unsigned long size,
196 int info, int other, int sh_num, const char *name)
198 ElfW(Sym) *esym;
199 int sym_bind, sym_index, sym_type, esym_bind;
200 unsigned char sym_vis, esym_vis, new_vis;
202 sym_bind = ELFW(ST_BIND)(info);
203 sym_type = ELFW(ST_TYPE)(info);
204 sym_vis = ELFW(ST_VISIBILITY)(other);
206 if (sym_bind != STB_LOCAL) {
207 /* we search global or weak symbols */
208 sym_index = find_elf_sym(s, name);
209 if (!sym_index)
210 goto do_def;
211 esym = &((ElfW(Sym) *)s->data)[sym_index];
212 if (esym->st_shndx != SHN_UNDEF) {
213 esym_bind = ELFW(ST_BIND)(esym->st_info);
214 /* propagate the most constraining visibility */
215 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
216 esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
217 if (esym_vis == STV_DEFAULT) {
218 new_vis = sym_vis;
219 } else if (sym_vis == STV_DEFAULT) {
220 new_vis = esym_vis;
221 } else {
222 new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
224 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
225 | new_vis;
226 other = esym->st_other; /* in case we have to patch esym */
227 if (sh_num == SHN_UNDEF) {
228 /* ignore adding of undefined symbol if the
229 corresponding symbol is already defined */
230 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
231 /* global overrides weak, so patch */
232 goto do_patch;
233 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
234 /* weak is ignored if already global */
235 } else if (sym_bind == STB_WEAK && esym_bind == STB_WEAK) {
236 /* keep first-found weak definition, ignore subsequents */
237 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
238 /* ignore hidden symbols after */
239 } else if ((esym->st_shndx == SHN_COMMON
240 || esym->st_shndx == bss_section->sh_num)
241 && (sh_num < SHN_LORESERVE
242 && sh_num != bss_section->sh_num)) {
243 /* data symbol gets precedence over common/bss */
244 goto do_patch;
245 } else if (sh_num == SHN_COMMON || sh_num == bss_section->sh_num) {
246 /* data symbol keeps precedence over common/bss */
247 } else if (s == tcc_state->dynsymtab_section) {
248 /* we accept that two DLL define the same symbol */
249 } else {
250 #if 0
251 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
252 sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
253 #endif
254 tcc_error_noabort("'%s' defined twice", name);
256 } else {
257 do_patch:
258 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
259 esym->st_shndx = sh_num;
260 new_undef_sym = 1;
261 esym->st_value = value;
262 esym->st_size = size;
263 esym->st_other = other;
265 } else {
266 do_def:
267 sym_index = put_elf_sym(s, value, size,
268 ELFW(ST_INFO)(sym_bind, sym_type), other,
269 sh_num, name);
271 return sym_index;
274 /* put relocation */
275 ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset,
276 int type, int symbol, addr_t addend)
278 char buf[256];
279 Section *sr;
280 ElfW_Rel *rel;
282 sr = s->reloc;
283 if (!sr) {
284 /* if no relocation section, create it */
285 snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
286 /* if the symtab is allocated, then we consider the relocation
287 are also */
288 sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
289 sr->sh_entsize = sizeof(ElfW_Rel);
290 sr->link = symtab;
291 sr->sh_info = s->sh_num;
292 s->reloc = sr;
294 rel = section_ptr_add(sr, sizeof(ElfW_Rel));
295 rel->r_offset = offset;
296 rel->r_info = ELFW(R_INFO)(symbol, type);
297 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
298 rel->r_addend = addend;
299 #else
300 if (addend)
301 tcc_error("non-zero addend on REL architecture");
302 #endif
305 ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
306 int type, int symbol)
308 put_elf_reloca(symtab, s, offset, type, symbol, 0);
311 /* put stab debug information */
313 ST_FUNC void put_stabs(const char *str, int type, int other, int desc,
314 unsigned long value)
316 Stab_Sym *sym;
318 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
319 if (str) {
320 sym->n_strx = put_elf_str(stabstr_section, str);
321 } else {
322 sym->n_strx = 0;
324 sym->n_type = type;
325 sym->n_other = other;
326 sym->n_desc = desc;
327 sym->n_value = value;
330 ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc,
331 unsigned long value, Section *sec, int sym_index)
333 put_stabs(str, type, other, desc, value);
334 put_elf_reloc(symtab_section, stab_section,
335 stab_section->data_offset - sizeof(unsigned int),
336 R_DATA_32, sym_index);
339 ST_FUNC void put_stabn(int type, int other, int desc, int value)
341 put_stabs(NULL, type, other, desc, value);
344 ST_FUNC void put_stabd(int type, int other, int desc)
346 put_stabs(NULL, type, other, desc, 0);
349 /* Browse each elem of type <type> in section <sec> starting at elem <startoff>
350 using variable <elem> */
351 #define for_each_elem(sec, startoff, elem, type) \
352 for (elem = (type *) sec->data + startoff; \
353 elem < (type *) (sec->data + sec->data_offset); elem++)
355 /* In an ELF file symbol table, the local symbols must appear below
356 the global and weak ones. Since TCC cannot sort it while generating
357 the code, we must do it after. All the relocation tables are also
358 modified to take into account the symbol table sorting */
359 static void sort_syms(TCCState *s1, Section *s)
361 int *old_to_new_syms;
362 ElfW(Sym) *new_syms;
363 int nb_syms, i;
364 ElfW(Sym) *p, *q;
365 ElfW_Rel *rel;
366 Section *sr;
367 int type, sym_index;
369 nb_syms = s->data_offset / sizeof(ElfW(Sym));
370 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
371 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
373 /* first pass for local symbols */
374 p = (ElfW(Sym) *)s->data;
375 q = new_syms;
376 for(i = 0; i < nb_syms; i++) {
377 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
378 old_to_new_syms[i] = q - new_syms;
379 *q++ = *p;
381 p++;
383 /* save the number of local symbols in section header */
384 s->sh_info = q - new_syms;
386 /* then second pass for non local symbols */
387 p = (ElfW(Sym) *)s->data;
388 for(i = 0; i < nb_syms; i++) {
389 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
390 old_to_new_syms[i] = q - new_syms;
391 *q++ = *p;
393 p++;
396 /* we copy the new symbols to the old */
397 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
398 tcc_free(new_syms);
400 /* now we modify all the relocations */
401 for(i = 1; i < s1->nb_sections; i++) {
402 sr = s1->sections[i];
403 if (sr->sh_type == SHT_RELX && sr->link == s) {
404 for_each_elem(sr, 0, rel, ElfW_Rel) {
405 sym_index = ELFW(R_SYM)(rel->r_info);
406 type = ELFW(R_TYPE)(rel->r_info);
407 sym_index = old_to_new_syms[sym_index];
408 rel->r_info = ELFW(R_INFO)(sym_index, type);
413 tcc_free(old_to_new_syms);
416 /* relocate common symbols in the .bss section */
417 ST_FUNC void relocate_common_syms(void)
419 ElfW(Sym) *sym;
420 unsigned long offset, align;
422 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
423 if (sym->st_shndx == SHN_COMMON) {
424 /* align symbol */
425 align = sym->st_value;
426 offset = bss_section->data_offset;
427 offset = (offset + align - 1) & -align;
428 sym->st_value = offset;
429 sym->st_shndx = bss_section->sh_num;
430 offset += sym->st_size;
431 bss_section->data_offset = offset;
436 /* relocate symbol table, resolve undefined symbols if do_resolve is
437 true and output error if undefined symbol. */
438 ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
440 ElfW(Sym) *sym, *esym;
441 int sym_bind, sh_num, sym_index;
442 const char *name;
444 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
445 sh_num = sym->st_shndx;
446 if (sh_num == SHN_UNDEF) {
447 name = (char *) strtab_section->data + sym->st_name;
448 /* Use ld.so to resolve symbol for us (for tcc -run) */
449 if (do_resolve) {
450 #if defined TCC_IS_NATIVE && !defined _WIN32
451 void *addr;
452 name = (char *) symtab_section->link->data + sym->st_name;
453 addr = dlsym(RTLD_DEFAULT, name);
454 if (addr) {
455 sym->st_value = (addr_t)addr;
456 #ifdef DEBUG_RELOC
457 printf ("relocate_sym: %s -> 0x%lx\n", name, sym->st_value);
458 #endif
459 goto found;
461 #endif
462 } else if (s1->dynsym) {
463 /* if dynamic symbol exist, then use it */
464 sym_index = find_elf_sym(s1->dynsym, name);
465 if (sym_index) {
466 esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
467 sym->st_value = esym->st_value;
468 goto found;
471 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
472 it */
473 if (!strcmp(name, "_fp_hw"))
474 goto found;
475 /* only weak symbols are accepted to be undefined. Their
476 value is zero */
477 sym_bind = ELFW(ST_BIND)(sym->st_info);
478 if (sym_bind == STB_WEAK) {
479 sym->st_value = 0;
480 } else {
481 tcc_error_noabort("undefined symbol '%s'", name);
483 } else if (sh_num < SHN_LORESERVE) {
484 /* add section base */
485 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
487 found: ;
491 /* relocate a given section (CPU dependent) by applying the relocations
492 in the associated relocation section */
493 ST_FUNC void relocate_section(TCCState *s1, Section *s)
495 Section *sr = s->reloc;
496 ElfW_Rel *rel;
497 ElfW(Sym) *sym;
498 int type, sym_index;
499 unsigned char *ptr;
500 addr_t val, addr;
501 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
502 ElfW_Rel *qrel = (ElfW_Rel *) sr->data; /* ptr to next reloc entry reused */
503 int esym_index;
504 #endif
506 for_each_elem(sr, 0, rel, ElfW_Rel) {
507 ptr = s->data + rel->r_offset;
509 sym_index = ELFW(R_SYM)(rel->r_info);
510 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
511 val = sym->st_value;
512 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
513 val += rel->r_addend;
514 #endif
515 type = ELFW(R_TYPE)(rel->r_info);
516 addr = s->sh_addr + rel->r_offset;
518 /* CPU specific */
519 switch(type) {
520 #if defined(TCC_TARGET_I386)
521 case R_386_32:
522 if (s1->output_type == TCC_OUTPUT_DLL) {
523 esym_index = s1->symtab_to_dynsym[sym_index];
524 qrel->r_offset = rel->r_offset;
525 if (esym_index) {
526 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
527 qrel++;
528 break;
529 } else {
530 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
531 qrel++;
534 write32le(ptr, read32le(ptr) + val);
535 break;
536 case R_386_PC32:
537 if (s1->output_type == TCC_OUTPUT_DLL) {
538 /* DLL relocation */
539 esym_index = s1->symtab_to_dynsym[sym_index];
540 if (esym_index) {
541 qrel->r_offset = rel->r_offset;
542 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
543 qrel++;
544 break;
547 write32le(ptr, read32le(ptr) + val - addr);
548 break;
549 case R_386_PLT32:
550 write32le(ptr, read32le(ptr) + val - addr);
551 break;
552 case R_386_GLOB_DAT:
553 case R_386_JMP_SLOT:
554 write32le(ptr, val);
555 break;
556 case R_386_GOTPC:
557 write32le(ptr, read32le(ptr) + s1->got->sh_addr - addr);
558 break;
559 case R_386_GOTOFF:
560 write32le(ptr, read32le(ptr) + val - s1->got->sh_addr);
561 break;
562 case R_386_GOT32:
563 case R_386_GOT32X:
564 /* we load the got offset */
565 write32le(ptr, read32le(ptr) + s1->sym_attrs[sym_index].got_offset);
566 break;
567 case R_386_16:
568 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
569 output_file:
570 tcc_error("can only produce 16-bit binary files");
572 write16le(ptr, read16le(ptr) + val);
573 break;
574 case R_386_PC16:
575 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
576 goto output_file;
577 write16le(ptr, read16le(ptr) + val - addr);
578 break;
580 #ifdef TCC_TARGET_PE
581 case R_386_RELATIVE: /* handled in pe_relocate_rva() */
582 break;
583 #endif
584 case R_386_COPY:
585 /* This reloction must copy initialized data from the library
586 to the program .bss segment. Currently made like for ARM
587 (to remove noise of defaukt case). Is this true?
589 break;
591 default:
592 fprintf(stderr,"FIXME: handle reloc type %d at %x [%p] to %x\n",
593 type, (unsigned)addr, ptr, (unsigned)val);
594 break;
595 #elif defined(TCC_TARGET_ARM)
596 case R_ARM_PC24:
597 case R_ARM_CALL:
598 case R_ARM_JUMP24:
599 case R_ARM_PLT32:
601 int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko;
602 x = (*(int *) ptr) & 0xffffff;
603 if (sym->st_shndx == SHN_UNDEF)
604 val = s1->plt->sh_addr;
605 #ifdef DEBUG_RELOC
606 printf ("reloc %d: x=0x%x val=0x%x ", type, x, val);
607 #endif
608 (*(int *)ptr) &= 0xff000000;
609 if (x & 0x800000)
610 x -= 0x1000000;
611 x <<= 2;
612 blx_avail = (TCC_ARM_VERSION >= 5);
613 is_thumb = val & 1;
614 is_bl = (*(unsigned *) ptr) >> 24 == 0xeb;
615 is_call = (type == R_ARM_CALL || (type == R_ARM_PC24 && is_bl));
616 x += val - addr;
617 #ifdef DEBUG_RELOC
618 printf (" newx=0x%x name=%s\n", x,
619 (char *) symtab_section->link->data + sym->st_name);
620 #endif
621 h = x & 2;
622 th_ko = (x & 3) && (!blx_avail || !is_call);
623 if (th_ko || x >= 0x2000000 || x < -0x2000000)
624 tcc_error("can't relocate value at %x,%d",addr, type);
625 x >>= 2;
626 x &= 0xffffff;
627 /* Only reached if blx is avail and it is a call */
628 if (is_thumb) {
629 x |= h << 24;
630 (*(int *)ptr) = 0xfa << 24; /* bl -> blx */
632 (*(int *) ptr) |= x;
634 break;
635 /* Since these relocations only concern Thumb-2 and blx instruction was
636 introduced before Thumb-2, we can assume blx is available and not
637 guard its use */
638 case R_ARM_THM_PC22:
639 case R_ARM_THM_JUMP24:
641 int x, hi, lo, s, j1, j2, i1, i2, imm10, imm11;
642 int to_thumb, is_call, to_plt, blx_bit = 1 << 12;
643 Section *plt;
645 /* weak reference */
646 if (sym->st_shndx == SHN_UNDEF &&
647 ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
648 break;
650 /* Get initial offset */
651 hi = (*(uint16_t *)ptr);
652 lo = (*(uint16_t *)(ptr+2));
653 s = (hi >> 10) & 1;
654 j1 = (lo >> 13) & 1;
655 j2 = (lo >> 11) & 1;
656 i1 = (j1 ^ s) ^ 1;
657 i2 = (j2 ^ s) ^ 1;
658 imm10 = hi & 0x3ff;
659 imm11 = lo & 0x7ff;
660 x = (s << 24) | (i1 << 23) | (i2 << 22) |
661 (imm10 << 12) | (imm11 << 1);
662 if (x & 0x01000000)
663 x -= 0x02000000;
665 /* Relocation infos */
666 to_thumb = val & 1;
667 plt = s1->plt;
668 to_plt = (val >= plt->sh_addr) &&
669 (val < plt->sh_addr + plt->data_offset);
670 is_call = (type == R_ARM_THM_PC22);
672 /* Compute final offset */
673 if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */
674 x -= 4;
675 x += val - addr;
676 if (!to_thumb && is_call) {
677 blx_bit = 0; /* bl -> blx */
678 x = (x + 3) & -4; /* Compute offset from aligned PC */
681 /* Check that relocation is possible
682 * offset must not be out of range
683 * if target is to be entered in arm mode:
684 - bit 1 must not set
685 - instruction must be a call (bl) or a jump to PLT */
686 if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
687 if (to_thumb || (val & 2) || (!is_call && !to_plt))
688 tcc_error("can't relocate value at %x,%d",addr, type);
690 /* Compute and store final offset */
691 s = (x >> 24) & 1;
692 i1 = (x >> 23) & 1;
693 i2 = (x >> 22) & 1;
694 j1 = s ^ (i1 ^ 1);
695 j2 = s ^ (i2 ^ 1);
696 imm10 = (x >> 12) & 0x3ff;
697 imm11 = (x >> 1) & 0x7ff;
698 (*(uint16_t *)ptr) = (uint16_t) ((hi & 0xf800) |
699 (s << 10) | imm10);
700 (*(uint16_t *)(ptr+2)) = (uint16_t) ((lo & 0xc000) |
701 (j1 << 13) | blx_bit | (j2 << 11) |
702 imm11);
704 break;
705 case R_ARM_MOVT_ABS:
706 case R_ARM_MOVW_ABS_NC:
708 int x, imm4, imm12;
709 if (type == R_ARM_MOVT_ABS)
710 val >>= 16;
711 imm12 = val & 0xfff;
712 imm4 = (val >> 12) & 0xf;
713 x = (imm4 << 16) | imm12;
714 if (type == R_ARM_THM_MOVT_ABS)
715 *(int *)ptr |= x;
716 else
717 *(int *)ptr += x;
719 break;
720 case R_ARM_THM_MOVT_ABS:
721 case R_ARM_THM_MOVW_ABS_NC:
723 int x, i, imm4, imm3, imm8;
724 if (type == R_ARM_THM_MOVT_ABS)
725 val >>= 16;
726 imm8 = val & 0xff;
727 imm3 = (val >> 8) & 0x7;
728 i = (val >> 11) & 1;
729 imm4 = (val >> 12) & 0xf;
730 x = (imm3 << 28) | (imm8 << 16) | (i << 10) | imm4;
731 if (type == R_ARM_THM_MOVT_ABS)
732 *(int *)ptr |= x;
733 else
734 *(int *)ptr += x;
736 break;
737 case R_ARM_PREL31:
739 int x;
740 x = (*(int *)ptr) & 0x7fffffff;
741 (*(int *)ptr) &= 0x80000000;
742 x = (x * 2) / 2;
743 x += val - addr;
744 if((x^(x>>1))&0x40000000)
745 tcc_error("can't relocate value at %x,%d",addr, type);
746 (*(int *)ptr) |= x & 0x7fffffff;
748 case R_ARM_ABS32:
749 *(int *)ptr += val;
750 break;
751 case R_ARM_REL32:
752 *(int *)ptr += val - addr;
753 break;
754 case R_ARM_GOTPC:
755 *(int *)ptr += s1->got->sh_addr - addr;
756 break;
757 case R_ARM_GOTOFF:
758 *(int *)ptr += val - s1->got->sh_addr;
759 break;
760 case R_ARM_GOT32:
761 /* we load the got offset */
762 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
763 break;
764 case R_ARM_COPY:
765 break;
766 case R_ARM_V4BX:
767 /* trade Thumb support for ARMv4 support */
768 if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
769 *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
770 break;
771 case R_ARM_GLOB_DAT:
772 case R_ARM_JUMP_SLOT:
773 *(addr_t *)ptr = val;
774 break;
775 case R_ARM_NONE:
776 /* Nothing to do. Normally used to indicate a dependency
777 on a certain symbol (like for exception handling under EABI). */
778 break;
779 #ifdef TCC_TARGET_PE
780 case R_ARM_RELATIVE: /* handled in pe_relocate_rva() */
781 break;
782 #endif
783 default:
784 fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
785 type, (unsigned)addr, ptr, (unsigned)val);
786 break;
787 #elif defined(TCC_TARGET_ARM64)
788 case R_AARCH64_ABS64:
789 write64le(ptr, val);
790 break;
791 case R_AARCH64_ABS32:
792 write32le(ptr, val);
793 break;
794 case R_AARCH64_MOVW_UABS_G0_NC:
795 write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
796 (val & 0xffff) << 5));
797 break;
798 case R_AARCH64_MOVW_UABS_G1_NC:
799 write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
800 (val >> 16 & 0xffff) << 5));
801 break;
802 case R_AARCH64_MOVW_UABS_G2_NC:
803 write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
804 (val >> 32 & 0xffff) << 5));
805 break;
806 case R_AARCH64_MOVW_UABS_G3:
807 write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
808 (val >> 48 & 0xffff) << 5));
809 break;
810 case R_AARCH64_ADR_PREL_PG_HI21: {
811 uint64_t off = (val >> 12) - (addr >> 12);
812 if ((off + ((uint64_t)1 << 20)) >> 21)
813 tcc_error("R_AARCH64_ADR_PREL_PG_HI21 relocation failed");
814 write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
815 (off & 0x1ffffc) << 3 | (off & 3) << 29));
816 break;
818 case R_AARCH64_ADD_ABS_LO12_NC:
819 write32le(ptr, ((read32le(ptr) & 0xffc003ff) |
820 (val & 0xfff) << 10));
821 break;
822 case R_AARCH64_JUMP26:
823 case R_AARCH64_CALL26:
824 /* This check must match the one in build_got_entries, testing
825 if we really need a PLT slot. */
826 if (sym->st_shndx == SHN_UNDEF)
827 /* We've put the PLT slot offset into r_addend when generating
828 it, and that's what we must use as relocation value (adjusted
829 by section offset of course). */
830 val = s1->plt->sh_addr + rel->r_addend;
831 #ifdef DEBUG_RELOC
832 printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, val,
833 (char *) symtab_section->link->data + sym->st_name);
834 #endif
835 if (((val - addr) + ((uint64_t)1 << 27)) & ~(uint64_t)0xffffffc)
837 tcc_error("R_AARCH64_(JUMP|CALL)26 relocation failed (val=%lx, addr=%lx)", addr, val);
839 write32le(ptr, (0x14000000 |
840 (uint32_t)(type == R_AARCH64_CALL26) << 31 |
841 ((val - addr) >> 2 & 0x3ffffff)));
842 break;
843 case R_AARCH64_ADR_GOT_PAGE: {
844 uint64_t off =
845 (((s1->got->sh_addr +
846 s1->sym_attrs[sym_index].got_offset) >> 12) - (addr >> 12));
847 if ((off + ((uint64_t)1 << 20)) >> 21)
848 tcc_error("R_AARCH64_ADR_GOT_PAGE relocation failed");
849 write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
850 (off & 0x1ffffc) << 3 | (off & 3) << 29));
851 break;
853 case R_AARCH64_LD64_GOT_LO12_NC:
854 write32le(ptr,
855 ((read32le(ptr) & 0xfff803ff) |
856 ((s1->got->sh_addr +
857 s1->sym_attrs[sym_index].got_offset) & 0xff8) << 7));
858 break;
859 case R_AARCH64_COPY:
860 break;
861 case R_AARCH64_GLOB_DAT:
862 case R_AARCH64_JUMP_SLOT:
863 /* They don't need addend */
864 #ifdef DEBUG_RELOC
865 printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr,
866 val - rel->r_addend,
867 (char *) symtab_section->link->data + sym->st_name);
868 #endif
869 write64le(ptr, val - rel->r_addend);
870 break;
871 default:
872 fprintf(stderr, "FIXME: handle reloc type %x at %x [%p] to %x\n",
873 type, (unsigned)addr, ptr, (unsigned)val);
874 break;
875 #elif defined(TCC_TARGET_C67)
876 case R_C60_32:
877 *(int *)ptr += val;
878 break;
879 case R_C60LO16:
881 uint32_t orig;
883 /* put the low 16 bits of the absolute address
884 add to what is already there */
886 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
887 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
889 /* patch both at once - assumes always in pairs Low - High */
891 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
892 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
894 break;
895 case R_C60HI16:
896 break;
897 default:
898 fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
899 type, (unsigned)addr, ptr, (unsigned)val);
900 break;
901 #elif defined(TCC_TARGET_X86_64)
902 case R_X86_64_64:
903 if (s1->output_type == TCC_OUTPUT_DLL) {
904 esym_index = s1->symtab_to_dynsym[sym_index];
905 qrel->r_offset = rel->r_offset;
906 if (esym_index) {
907 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_64);
908 qrel->r_addend = rel->r_addend;
909 qrel++;
910 break;
911 } else {
912 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
913 qrel->r_addend = read64le(ptr) + val;
914 qrel++;
917 write64le(ptr, read64le(ptr) + val);
918 break;
919 case R_X86_64_32:
920 case R_X86_64_32S:
921 if (s1->output_type == TCC_OUTPUT_DLL) {
922 /* XXX: this logic may depend on TCC's codegen
923 now TCC uses R_X86_64_32 even for a 64bit pointer */
924 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
925 /* Use sign extension! */
926 qrel->r_addend = (int)read32le(ptr) + val;
927 qrel++;
929 write32le(ptr, read32le(ptr) + val);
930 break;
932 case R_X86_64_PC32:
933 if (s1->output_type == TCC_OUTPUT_DLL) {
934 /* DLL relocation */
935 esym_index = s1->symtab_to_dynsym[sym_index];
936 if (esym_index) {
937 qrel->r_offset = rel->r_offset;
938 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
939 /* Use sign extension! */
940 qrel->r_addend = (int)read32le(ptr) + rel->r_addend;
941 qrel++;
942 break;
945 goto plt32pc32;
947 case R_X86_64_PLT32:
948 /* We've put the PLT slot offset into r_addend when generating
949 it, and that's what we must use as relocation value (adjusted
950 by section offset of course). */
951 val = s1->plt->sh_addr + rel->r_addend;
952 /* fallthrough. */
954 plt32pc32:
956 long long diff;
957 diff = (long long)val - addr;
958 if (diff < -2147483648LL || diff > 2147483647LL) {
959 tcc_error("internal error: relocation failed");
961 write32le(ptr, read32le(ptr) + diff);
963 break;
964 case R_X86_64_GLOB_DAT:
965 case R_X86_64_JUMP_SLOT:
966 /* They don't need addend */
967 write64le(ptr, val - rel->r_addend);
968 break;
969 case R_X86_64_GOTPCREL:
970 case R_X86_64_GOTPCRELX:
971 case R_X86_64_REX_GOTPCRELX:
972 write32le(ptr, read32le(ptr) +
973 (s1->got->sh_addr - addr +
974 s1->sym_attrs[sym_index].got_offset - 4));
975 break;
976 case R_X86_64_GOTTPOFF:
977 write32le(ptr, read32le(ptr) + val - s1->got->sh_addr);
978 break;
979 case R_X86_64_GOT32:
980 /* we load the got offset */
981 write32le(ptr, read32le(ptr) + s1->sym_attrs[sym_index].got_offset);
982 break;
983 #ifdef TCC_TARGET_PE
984 case R_X86_64_RELATIVE: /* handled in pe_relocate_rva() */
985 break;
986 #endif
988 #else
989 #error unsupported processor
990 #endif
993 /* if the relocation is allocated, we change its symbol table */
994 if (sr->sh_flags & SHF_ALLOC)
995 sr->link = s1->dynsym;
998 /* relocate relocation table in 'sr' */
999 static void relocate_rel(TCCState *s1, Section *sr)
1001 Section *s;
1002 ElfW_Rel *rel;
1004 s = s1->sections[sr->sh_info];
1005 for_each_elem(sr, 0, rel, ElfW_Rel)
1006 rel->r_offset += s->sh_addr;
1009 /* count the number of dynamic relocations so that we can reserve
1010 their space */
1011 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
1013 ElfW_Rel *rel;
1014 int sym_index, esym_index, type, count;
1016 count = 0;
1017 for_each_elem(sr, 0, rel, ElfW_Rel) {
1018 sym_index = ELFW(R_SYM)(rel->r_info);
1019 type = ELFW(R_TYPE)(rel->r_info);
1020 switch(type) {
1021 #if defined(TCC_TARGET_I386)
1022 case R_386_32:
1023 #elif defined(TCC_TARGET_X86_64)
1024 case R_X86_64_32:
1025 case R_X86_64_32S:
1026 case R_X86_64_64:
1027 #endif
1028 count++;
1029 break;
1030 #if defined(TCC_TARGET_I386)
1031 case R_386_PC32:
1032 #elif defined(TCC_TARGET_X86_64)
1033 case R_X86_64_PC32:
1034 #endif
1035 esym_index = s1->symtab_to_dynsym[sym_index];
1036 if (esym_index)
1037 count++;
1038 break;
1039 default:
1040 break;
1043 if (count) {
1044 /* allocate the section */
1045 sr->sh_flags |= SHF_ALLOC;
1046 sr->sh_size = count * sizeof(ElfW_Rel);
1048 return count;
1051 static struct sym_attr *alloc_sym_attr(TCCState *s1, int index)
1053 int n;
1054 struct sym_attr *tab;
1056 if (index >= s1->nb_sym_attrs) {
1057 /* find immediately bigger power of 2 and reallocate array */
1058 n = 1;
1059 while (index >= n)
1060 n *= 2;
1061 tab = tcc_realloc(s1->sym_attrs, n * sizeof(*s1->sym_attrs));
1062 s1->sym_attrs = tab;
1063 memset(s1->sym_attrs + s1->nb_sym_attrs, 0,
1064 (n - s1->nb_sym_attrs) * sizeof(*s1->sym_attrs));
1065 s1->nb_sym_attrs = n;
1067 return &s1->sym_attrs[index];
1070 static void build_got(TCCState *s1)
1072 unsigned char *ptr;
1074 /* if no got, then create it */
1075 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
1076 s1->got->sh_entsize = 4;
1077 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
1078 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
1079 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
1080 #if PTR_SIZE == 4
1081 /* keep space for _DYNAMIC pointer, if present */
1082 write32le(ptr, 0);
1083 /* two dummy got entries */
1084 write32le(ptr + 4, 0);
1085 write32le(ptr + 8, 0);
1086 #else
1087 /* keep space for _DYNAMIC pointer, if present */
1088 write32le(ptr, 0);
1089 write32le(ptr + 4, 0);
1090 /* two dummy got entries */
1091 write32le(ptr + 8, 0);
1092 write32le(ptr + 12, 0);
1093 write32le(ptr + 16, 0);
1094 write32le(ptr + 20, 0);
1095 #endif
1098 /* put a got or plt entry corresponding to a symbol in symtab_section. 'size'
1099 and 'info' can be modifed if more precise info comes from the DLL.
1100 Returns offset of GOT or PLT slot. */
1101 static unsigned long put_got_entry(TCCState *s1,
1102 int reloc_type, unsigned long size, int info,
1103 int sym_index)
1105 int index, need_plt_entry;
1106 const char *name;
1107 ElfW(Sym) *sym;
1108 unsigned long offset;
1109 int *ptr;
1110 struct sym_attr *symattr;
1112 if (!s1->got)
1113 build_got(s1);
1115 need_plt_entry =
1116 #ifdef TCC_TARGET_X86_64
1117 (reloc_type == R_X86_64_JUMP_SLOT);
1118 #elif defined(TCC_TARGET_I386)
1119 (reloc_type == R_386_JMP_SLOT);
1120 #elif defined(TCC_TARGET_ARM)
1121 (reloc_type == R_ARM_JUMP_SLOT);
1122 #elif defined(TCC_TARGET_ARM64)
1123 (reloc_type == R_AARCH64_JUMP_SLOT);
1124 #else
1126 #endif
1128 if (need_plt_entry && !s1->plt) {
1129 /* add PLT */
1130 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1131 SHF_ALLOC | SHF_EXECINSTR);
1132 s1->plt->sh_entsize = 4;
1135 /* If a got/plt entry already exists for that symbol, no need to add one */
1136 if (sym_index < s1->nb_sym_attrs) {
1137 if (need_plt_entry && s1->sym_attrs[sym_index].plt_offset)
1138 return s1->sym_attrs[sym_index].plt_offset;
1139 else if (!need_plt_entry && s1->sym_attrs[sym_index].got_offset)
1140 return s1->sym_attrs[sym_index].got_offset;
1143 symattr = alloc_sym_attr(s1, sym_index);
1145 /* Only store the GOT offset if it's not generated for the PLT entry. */
1146 if (!need_plt_entry)
1147 symattr->got_offset = s1->got->data_offset;
1149 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1150 name = (char *) symtab_section->link->data + sym->st_name;
1151 offset = sym->st_value;
1152 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1153 if (need_plt_entry) {
1154 Section *plt;
1155 uint8_t *p;
1156 int modrm;
1157 unsigned long relofs;
1159 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1160 modrm = 0x25;
1161 #else
1162 /* if we build a DLL, we add a %ebx offset */
1163 if (s1->output_type == TCC_OUTPUT_DLL)
1164 modrm = 0xa3;
1165 else
1166 modrm = 0x25;
1167 #endif
1169 /* add a PLT entry */
1170 plt = s1->plt;
1171 if (plt->data_offset == 0) {
1172 /* first plt entry */
1173 p = section_ptr_add(plt, 16);
1174 p[0] = 0xff; /* pushl got + PTR_SIZE */
1175 p[1] = modrm + 0x10;
1176 write32le(p + 2, PTR_SIZE);
1177 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1178 p[7] = modrm;
1179 write32le(p + 8, PTR_SIZE * 2);
1182 /* The PLT slot refers to the relocation entry it needs
1183 via offset. The reloc entry is created below, so its
1184 offset is the current data_offset. */
1185 relofs = s1->got->reloc ? s1->got->reloc->data_offset : 0;
1186 symattr->plt_offset = plt->data_offset;
1187 p = section_ptr_add(plt, 16);
1188 p[0] = 0xff; /* jmp *(got + x) */
1189 p[1] = modrm;
1190 write32le(p + 2, s1->got->data_offset);
1191 p[6] = 0x68; /* push $xxx */
1192 #ifdef TCC_TARGET_X86_64
1193 /* On x86-64, the relocation is referred to by _index_. */
1194 write32le(p + 7, relofs / sizeof (ElfW_Rel));
1195 #else
1196 write32le(p + 7, relofs);
1197 #endif
1198 p[11] = 0xe9; /* jmp plt_start */
1199 write32le(p + 12, -(plt->data_offset));
1201 /* If this was an UNDEF symbol set the offset in the
1202 dynsymtab to the PLT slot, so that PC32 relocs to it
1203 can be resolved. */
1204 if (sym->st_shndx == SHN_UNDEF)
1205 offset = plt->data_offset - 16;
1207 #elif defined(TCC_TARGET_ARM)
1208 if (need_plt_entry) {
1209 Section *plt;
1210 uint8_t *p;
1212 /* if we build a DLL, we add a %ebx offset */
1213 if (s1->output_type == TCC_OUTPUT_DLL)
1214 tcc_error("DLLs unimplemented!");
1216 /* add a PLT entry */
1217 plt = s1->plt;
1218 if (plt->data_offset == 0) {
1219 /* first plt entry */
1220 p = section_ptr_add(plt, 16);
1221 write32le(p, 0xe52de004); /* push {lr} */
1222 write32le(p+4, 0xe59fe010); /* ldr lr, [pc, #16] */
1223 write32le(p+8, 0xe08fe00e); /* add lr, pc, lr */
1224 write32le(p+12, 0xe5bef008); /* ldr pc, [lr, #8]! */
1227 symattr->plt_offset = plt->data_offset;
1228 if (symattr->plt_thumb_stub) {
1229 p = section_ptr_add(plt, 20);
1230 write32le(p, 0x4778); /* bx pc */
1231 write32le(p+2, 0x46c0); /* nop */
1232 p += 4;
1233 } else
1234 p = section_ptr_add(plt, 16);
1235 write32le(p, 0xe59fc004); /* ldr ip, [pc, #4] ; GOT entry offset */
1236 write32le(p+4, 0xe08fc00c); /* add ip, pc, ip ; addr of GOT entry */
1237 write32le(p+8, 0xe59cf000); /* ldr pc, [ip] ; jump to GOT entry */
1238 write32le(p+12, s1->got->data_offset); /* GOT entry off once patched */
1240 /* the symbol is modified so that it will be relocated to
1241 the PLT */
1242 if (sym->st_shndx == SHN_UNDEF)
1243 offset = plt->data_offset - 16;
1245 #elif defined(TCC_TARGET_ARM64)
1246 if (need_plt_entry) {
1247 Section *plt;
1248 uint8_t *p;
1250 if (s1->output_type == TCC_OUTPUT_DLL)
1251 tcc_error("DLLs unimplemented!");
1253 plt = s1->plt;
1254 if (plt->data_offset == 0)
1255 section_ptr_add(plt, 32);
1256 symattr->plt_offset = plt->data_offset;
1257 p = section_ptr_add(plt, 16);
1258 write32le(p, s1->got->data_offset);
1259 write32le(p + 4, (uint64_t)s1->got->data_offset >> 32);
1261 if (sym->st_shndx == SHN_UNDEF)
1262 offset = plt->data_offset - 16;
1264 #elif defined(TCC_TARGET_C67)
1265 if (s1->dynsym) {
1266 tcc_error("C67 got not implemented");
1268 #else
1269 #error unsupported CPU
1270 #endif
1271 if (s1->dynsym) {
1272 /* XXX This might generate multiple syms for name. */
1273 index = put_elf_sym(s1->dynsym, offset,
1274 size, info, 0, sym->st_shndx, name);
1275 /* Create the relocation (it's against the GOT for PLT
1276 and GOT relocs). */
1277 put_elf_reloc(s1->dynsym, s1->got,
1278 s1->got->data_offset,
1279 reloc_type, index);
1280 } else {
1281 /* Without .dynsym (i.e. static link or memory output) we
1282 still need relocs against the generated got, so as to fill
1283 the entries with the symbol values (determined later). */
1284 put_elf_reloc(symtab_section, s1->got,
1285 s1->got->data_offset,
1286 reloc_type, sym_index);
1288 /* And now create the GOT slot itself. */
1289 ptr = section_ptr_add(s1->got, PTR_SIZE);
1290 *ptr = 0;
1291 if (need_plt_entry)
1292 return symattr->plt_offset;
1293 else
1294 return symattr->got_offset;
1297 /* build GOT and PLT entries */
1298 ST_FUNC void build_got_entries(TCCState *s1)
1300 Section *s;
1301 ElfW_Rel *rel;
1302 ElfW(Sym) *sym;
1303 int i, type, reloc_type, sym_index;
1305 for(i = 1; i < s1->nb_sections; i++) {
1306 s = s1->sections[i];
1307 if (s->sh_type != SHT_RELX)
1308 continue;
1309 /* no need to handle got relocations */
1310 if (s->link != symtab_section)
1311 continue;
1312 for_each_elem(s, 0, rel, ElfW_Rel) {
1313 type = ELFW(R_TYPE)(rel->r_info);
1314 switch(type) {
1315 #if defined(TCC_TARGET_I386)
1316 case R_386_GOT32:
1317 case R_386_GOT32X:
1318 case R_386_GOTOFF:
1319 case R_386_GOTPC:
1320 case R_386_PLT32:
1321 if (!s1->got)
1322 build_got(s1);
1323 if (type == R_386_GOT32 || type == R_386_GOT32X ||
1324 type == R_386_PLT32) {
1325 sym_index = ELFW(R_SYM)(rel->r_info);
1326 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1327 /* look at the symbol got offset. If none, then add one */
1328 if (type == R_386_GOT32 || type == R_386_GOT32X)
1329 reloc_type = R_386_GLOB_DAT;
1330 else
1331 reloc_type = R_386_JMP_SLOT;
1332 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1333 sym_index);
1335 break;
1336 #elif defined(TCC_TARGET_ARM)
1337 case R_ARM_PC24:
1338 case R_ARM_CALL:
1339 case R_ARM_JUMP24:
1340 case R_ARM_GOT32:
1341 case R_ARM_GOTOFF:
1342 case R_ARM_GOTPC:
1343 case R_ARM_PLT32:
1344 if (!s1->got)
1345 build_got(s1);
1346 sym_index = ELFW(R_SYM)(rel->r_info);
1347 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1348 if (type != R_ARM_GOTOFF && type != R_ARM_GOTPC
1349 && sym->st_shndx == SHN_UNDEF) {
1350 unsigned long ofs;
1351 /* look at the symbol got offset. If none, then add one */
1352 if (type == R_ARM_GOT32)
1353 reloc_type = R_ARM_GLOB_DAT;
1354 else
1355 reloc_type = R_ARM_JUMP_SLOT;
1356 ofs = put_got_entry(s1, reloc_type, sym->st_size,
1357 sym->st_info, sym_index);
1358 #ifdef DEBUG_RELOC
1359 printf ("maybegot: %s, %d, %d --> ofs=0x%x\n",
1360 (char *) symtab_section->link->data + sym->st_name,
1361 type, sym->st_shndx, ofs);
1362 #endif
1363 if (type != R_ARM_GOT32) {
1364 addr_t *ptr = (addr_t*)(s1->sections[s->sh_info]->data
1365 + rel->r_offset);
1366 /* x must be signed! */
1367 int x = *ptr & 0xffffff;
1368 x = (x << 8) >> 8;
1369 x <<= 2;
1370 x += ofs;
1371 x >>= 2;
1372 #ifdef DEBUG_RELOC
1373 printf ("insn=0x%x --> 0x%x (x==0x%x)\n", *ptr,
1374 (*ptr & 0xff000000) | x, x);
1375 #endif
1376 *ptr = (*ptr & 0xff000000) | x;
1379 break;
1380 case R_ARM_THM_JUMP24:
1381 sym_index = ELFW(R_SYM)(rel->r_info);
1382 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1383 /* We are relocating a jump from thumb code to arm code */
1384 if (sym->st_shndx != SHN_UNDEF && !(sym->st_value & 1)) {
1385 int index;
1386 uint8_t *p;
1387 char *name, buf[1024];
1388 Section *text_section;
1390 name = (char *) symtab_section->link->data + sym->st_name;
1391 text_section = s1->sections[sym->st_shndx];
1392 /* Modify reloc to target a thumb stub to switch to ARM */
1393 snprintf(buf, sizeof(buf), "%s_from_thumb", name);
1394 index = put_elf_sym(symtab_section,
1395 text_section->data_offset + 1,
1396 sym->st_size, sym->st_info, 0,
1397 sym->st_shndx, buf);
1398 rel->r_info = ELFW(R_INFO)(index, type);
1399 /* Create a thumb stub fonction to switch to ARM mode */
1400 put_elf_reloc(symtab_section, text_section,
1401 text_section->data_offset + 4, R_ARM_JUMP24,
1402 sym_index);
1403 p = section_ptr_add(text_section, 8);
1404 write32le(p, 0x4778); /* bx pc */
1405 write32le(p+2, 0x46c0); /* nop */
1406 write32le(p+4, 0xeafffffe); /* b $sym */
1408 #elif defined(TCC_TARGET_ARM64)
1409 //xx Other cases may be required here:
1410 case R_AARCH64_ADR_GOT_PAGE:
1411 case R_AARCH64_LD64_GOT_LO12_NC:
1412 if (!s1->got)
1413 build_got(s1);
1414 sym_index = ELFW(R_SYM)(rel->r_info);
1415 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1416 reloc_type = R_AARCH64_GLOB_DAT;
1417 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1418 sym_index);
1419 break;
1421 case R_AARCH64_JUMP26:
1422 case R_AARCH64_CALL26:
1423 if (!s1->got)
1424 build_got(s1);
1425 sym_index = ELFW(R_SYM)(rel->r_info);
1426 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1427 if (sym->st_shndx == SHN_UNDEF) {
1428 unsigned long ofs;
1429 reloc_type = R_AARCH64_JUMP_SLOT;
1430 ofs = put_got_entry(s1, reloc_type, sym->st_size,
1431 sym->st_info, sym_index);
1432 /* We store the place of the generated PLT slot
1433 in our addend. */
1434 rel->r_addend += ofs;
1436 break;
1437 #elif defined(TCC_TARGET_C67)
1438 case R_C60_GOT32:
1439 case R_C60_GOTOFF:
1440 case R_C60_GOTPC:
1441 case R_C60_PLT32:
1442 if (!s1->got)
1443 build_got(s1);
1444 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1445 sym_index = ELFW(R_SYM)(rel->r_info);
1446 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1447 /* look at the symbol got offset. If none, then add one */
1448 if (type == R_C60_GOT32)
1449 reloc_type = R_C60_GLOB_DAT;
1450 else
1451 reloc_type = R_C60_JMP_SLOT;
1452 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1453 sym_index);
1455 break;
1456 #elif defined(TCC_TARGET_X86_64)
1457 case R_X86_64_GOT32:
1458 case R_X86_64_GOTTPOFF:
1459 case R_X86_64_GOTPCREL:
1460 case R_X86_64_GOTPCRELX:
1461 case R_X86_64_REX_GOTPCRELX:
1462 case R_X86_64_PLT32:
1463 sym_index = ELFW(R_SYM)(rel->r_info);
1464 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1465 if (type == R_X86_64_PLT32 &&
1466 ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT)
1468 rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32);
1469 break;
1472 if (!s1->got) {
1473 build_got(s1);
1474 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1476 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1477 type == R_X86_64_GOTPCRELX ||
1478 type == R_X86_64_REX_GOTPCRELX ||
1479 type == R_X86_64_PLT32) {
1480 unsigned long ofs;
1481 /* look at the symbol got offset. If none, then add one */
1482 if (type == R_X86_64_PLT32)
1483 reloc_type = R_X86_64_JUMP_SLOT;
1484 else
1485 reloc_type = R_X86_64_GLOB_DAT;
1486 ofs = put_got_entry(s1, reloc_type, sym->st_size,
1487 sym->st_info, sym_index);
1488 if (type == R_X86_64_PLT32)
1489 /* We store the place of the generated PLT slot
1490 in our addend. */
1491 rel->r_addend += ofs;
1493 break;
1494 #else
1495 #error unsupported CPU
1496 #endif
1497 default:
1498 break;
1504 ST_FUNC Section *new_symtab(TCCState *s1,
1505 const char *symtab_name, int sh_type, int sh_flags,
1506 const char *strtab_name,
1507 const char *hash_name, int hash_sh_flags)
1509 Section *symtab, *strtab, *hash;
1510 int *ptr, nb_buckets;
1512 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1513 symtab->sh_entsize = sizeof(ElfW(Sym));
1514 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1515 put_elf_str(strtab, "");
1516 symtab->link = strtab;
1517 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1519 nb_buckets = 1;
1521 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1522 hash->sh_entsize = sizeof(int);
1523 symtab->hash = hash;
1524 hash->link = symtab;
1526 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1527 ptr[0] = nb_buckets;
1528 ptr[1] = 1;
1529 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1530 return symtab;
1533 /* put dynamic tag */
1534 static void put_dt(Section *dynamic, int dt, addr_t val)
1536 ElfW(Dyn) *dyn;
1537 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1538 dyn->d_tag = dt;
1539 dyn->d_un.d_val = val;
1542 static void add_init_array_defines(TCCState *s1, const char *section_name)
1544 Section *s;
1545 long end_offset;
1546 char sym_start[1024];
1547 char sym_end[1024];
1549 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1550 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1552 s = find_section(s1, section_name);
1553 if (!s) {
1554 end_offset = 0;
1555 s = data_section;
1556 } else {
1557 end_offset = s->data_offset;
1560 add_elf_sym(symtab_section,
1561 0, 0,
1562 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1563 s->sh_num, sym_start);
1564 add_elf_sym(symtab_section,
1565 end_offset, 0,
1566 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1567 s->sh_num, sym_end);
1570 static int tcc_add_support(TCCState *s1, const char *filename)
1572 char buf[1024];
1573 snprintf(buf, sizeof(buf), "%s/"TCC_ARCH_DIR"%s", s1->tcc_lib_path, filename);
1574 return tcc_add_file(s1, buf);
1577 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1579 #ifdef CONFIG_TCC_BCHECK
1580 addr_t *ptr;
1581 int sym_index;
1583 if (0 == s1->do_bounds_check)
1584 return;
1585 /* XXX: add an object file to do that */
1586 ptr = section_ptr_add(bounds_section, sizeof(*ptr));
1587 *ptr = 0;
1588 add_elf_sym(symtab_section, 0, 0,
1589 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1590 bounds_section->sh_num, "__bounds_start");
1591 /* pull bcheck.o from libtcc1.a */
1592 sym_index = add_elf_sym(symtab_section, 0, 0,
1593 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1594 SHN_UNDEF, "__bound_init");
1595 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1596 /* add 'call __bound_init()' in .init section */
1597 Section *init_section = find_section(s1, ".init");
1598 unsigned char *pinit = section_ptr_add(init_section, 5);
1599 pinit[0] = 0xe8;
1600 write32le(pinit + 1, -4);
1601 put_elf_reloc(symtab_section, init_section,
1602 init_section->data_offset - 4, R_386_PC32, sym_index);
1603 /* R_386_PC32 = R_X86_64_PC32 = 2 */
1605 #endif
1608 /* add tcc runtime libraries */
1609 ST_FUNC void tcc_add_runtime(TCCState *s1)
1611 tcc_add_bcheck(s1);
1612 tcc_add_pragma_libs(s1);
1613 /* add libc */
1614 if (!s1->nostdlib) {
1615 tcc_add_library(s1, "c");
1616 #ifdef CONFIG_USE_LIBGCC
1617 if (!s1->static_link) {
1618 tcc_add_file(s1, TCC_LIBGCC);
1620 #endif
1621 tcc_add_support(s1, "libtcc1.a");
1622 /* add crt end if not memory output */
1623 if (s1->output_type != TCC_OUTPUT_MEMORY)
1624 tcc_add_crt(s1, "crtn.o");
1628 /* add various standard linker symbols (must be done after the
1629 sections are filled (for example after allocating common
1630 symbols)) */
1631 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1633 char buf[1024];
1634 int i;
1635 Section *s;
1637 add_elf_sym(symtab_section,
1638 text_section->data_offset, 0,
1639 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1640 text_section->sh_num, "_etext");
1641 add_elf_sym(symtab_section,
1642 data_section->data_offset, 0,
1643 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1644 data_section->sh_num, "_edata");
1645 add_elf_sym(symtab_section,
1646 bss_section->data_offset, 0,
1647 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1648 bss_section->sh_num, "_end");
1649 /* horrible new standard ldscript defines */
1650 add_init_array_defines(s1, ".preinit_array");
1651 add_init_array_defines(s1, ".init_array");
1652 add_init_array_defines(s1, ".fini_array");
1654 /* add start and stop symbols for sections whose name can be
1655 expressed in C */
1656 for(i = 1; i < s1->nb_sections; i++) {
1657 s = s1->sections[i];
1658 if (s->sh_type == SHT_PROGBITS &&
1659 (s->sh_flags & SHF_ALLOC)) {
1660 const char *p;
1661 int ch;
1663 /* check if section name can be expressed in C */
1664 p = s->name;
1665 for(;;) {
1666 ch = *p;
1667 if (!ch)
1668 break;
1669 if (!isid(ch) && !isnum(ch))
1670 goto next_sec;
1671 p++;
1673 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1674 add_elf_sym(symtab_section,
1675 0, 0,
1676 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1677 s->sh_num, buf);
1678 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1679 add_elf_sym(symtab_section,
1680 s->data_offset, 0,
1681 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1682 s->sh_num, buf);
1684 next_sec: ;
1688 static void tcc_output_binary(TCCState *s1, FILE *f,
1689 const int *sec_order)
1691 Section *s;
1692 int i, offset, size;
1694 offset = 0;
1695 for(i=1;i<s1->nb_sections;i++) {
1696 s = s1->sections[sec_order[i]];
1697 if (s->sh_type != SHT_NOBITS &&
1698 (s->sh_flags & SHF_ALLOC)) {
1699 while (offset < s->sh_offset) {
1700 fputc(0, f);
1701 offset++;
1703 size = s->sh_size;
1704 fwrite(s->data, 1, size, f);
1705 offset += size;
1710 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1711 #define HAVE_PHDR 1
1712 #define EXTRA_RELITEMS 14
1714 /* move the relocation value from .dynsym to .got */
1715 static void patch_dynsym_undef(TCCState *s1, Section *s)
1717 uint32_t *gotd = (void *)s1->got->data;
1718 ElfW(Sym) *sym;
1720 gotd += 3; /* dummy entries in .got */
1721 /* relocate symbols in .dynsym */
1722 for_each_elem(s, 1, sym, ElfW(Sym)) {
1723 if (sym->st_shndx == SHN_UNDEF) {
1724 *gotd++ = sym->st_value + 6; /* XXX 6 is magic ? */
1725 sym->st_value = 0;
1729 #else
1730 #define HAVE_PHDR 1
1731 #define EXTRA_RELITEMS 9
1733 /* zero plt offsets of weak symbols in .dynsym */
1734 static void patch_dynsym_undef(TCCState *s1, Section *s)
1736 ElfW(Sym) *sym;
1738 for_each_elem(s, 1, sym, ElfW(Sym))
1739 if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
1740 sym->st_value = 0;
1742 #endif
1744 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1746 int sym_index = ELFW(R_SYM) (rel->r_info);
1747 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1748 unsigned long offset;
1750 if (sym_index >= s1->nb_sym_attrs)
1751 return;
1752 offset = s1->sym_attrs[sym_index].got_offset;
1753 section_reserve(s1->got, offset + PTR_SIZE);
1754 #ifdef TCC_TARGET_X86_64
1755 /* only works for x86-64 */
1756 write32le(s1->got->data + offset + 4, sym->st_value >> 32);
1757 #endif
1758 write32le(s1->got->data + offset, sym->st_value & 0xffffffff);
1761 /* Perform relocation to GOT or PLT entries */
1762 ST_FUNC void fill_got(TCCState *s1)
1764 Section *s;
1765 ElfW_Rel *rel;
1766 int i;
1768 for(i = 1; i < s1->nb_sections; i++) {
1769 s = s1->sections[i];
1770 if (s->sh_type != SHT_RELX)
1771 continue;
1772 /* no need to handle got relocations */
1773 if (s->link != symtab_section)
1774 continue;
1775 for_each_elem(s, 0, rel, ElfW_Rel) {
1776 switch (ELFW(R_TYPE) (rel->r_info)) {
1777 case R_X86_64_GOT32:
1778 case R_X86_64_GOTPCREL:
1779 case R_X86_64_GOTPCRELX:
1780 case R_X86_64_REX_GOTPCRELX:
1781 case R_X86_64_PLT32:
1782 fill_got_entry(s1, rel);
1783 break;
1789 /* Bind symbols of executable: resolve undefined symbols from exported symbols
1790 in shared libraries and export non local defined symbols to shared libraries
1791 if -rdynamic switch was given on command line */
1792 static void bind_exe_dynsyms(TCCState *s1)
1794 const char *name;
1795 int sym_index, index;
1796 ElfW(Sym) *sym, *esym;
1797 int type;
1799 /* Resolve undefined symbols from dynamic symbols. When there is a match:
1800 - if STT_FUNC or STT_GNU_IFUNC symbol -> add it in PLT
1801 - if STT_OBJECT symbol -> add it in .bss section with suitable reloc */
1802 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
1803 if (sym->st_shndx == SHN_UNDEF) {
1804 name = (char *) symtab_section->link->data + sym->st_name;
1805 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1806 if (sym_index) {
1807 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1808 type = ELFW(ST_TYPE)(esym->st_info);
1809 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1810 /* Indirect functions shall have STT_FUNC type in executable
1811 * dynsym section. Indeed, a dlsym call following a lazy
1812 * resolution would pick the symbol value from the
1813 * executable dynsym entry which would contain the address
1814 * of the function wanted by the caller of dlsym instead of
1815 * the address of the function that would return that
1816 * address */
1817 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1818 ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC),
1819 sym - (ElfW(Sym) *)symtab_section->data);
1820 } else if (type == STT_OBJECT) {
1821 unsigned long offset;
1822 ElfW(Sym) *dynsym;
1823 offset = bss_section->data_offset;
1824 /* XXX: which alignment ? */
1825 offset = (offset + 16 - 1) & -16;
1826 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1827 esym->st_info, 0, bss_section->sh_num,
1828 name);
1829 /* Ensure R_COPY works for weak symbol aliases */
1830 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1831 for_each_elem(s1->dynsymtab_section, 1, dynsym, ElfW(Sym)) {
1832 if ((dynsym->st_value == esym->st_value)
1833 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1834 char *dynname = (char *) s1->dynsymtab_section->link->data
1835 + dynsym->st_name;
1836 put_elf_sym(s1->dynsym, offset, dynsym->st_size,
1837 dynsym->st_info, 0,
1838 bss_section->sh_num, dynname);
1839 break;
1843 put_elf_reloc(s1->dynsym, bss_section,
1844 offset, R_COPY, index);
1845 offset += esym->st_size;
1846 bss_section->data_offset = offset;
1848 } else {
1849 /* STB_WEAK undefined symbols are accepted */
1850 /* XXX: _fp_hw seems to be part of the ABI, so we ignore it */
1851 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1852 !strcmp(name, "_fp_hw")) {
1853 } else {
1854 tcc_error_noabort("undefined symbol '%s'", name);
1857 } else if (s1->rdynamic && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1858 /* if -rdynamic option, then export all non local symbols */
1859 name = (char *) symtab_section->link->data + sym->st_name;
1860 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, sym->st_info,
1861 0, sym->st_shndx, name);
1866 /* Bind symbols of libraries: export non local symbols of executable that
1867 resolve undefined symbols of shared libraries */
1868 static void bind_libs_dynsyms(TCCState *s1)
1870 const char *name;
1871 int sym_index;
1872 ElfW(Sym) *sym, *esym;
1874 /* now look at unresolved dynamic symbols and export
1875 corresponding symbol */
1876 for_each_elem(s1->dynsymtab_section, 1, esym, ElfW(Sym)) {
1877 name = (char *) s1->dynsymtab_section->link->data + esym->st_name;
1878 sym_index = find_elf_sym(symtab_section, name);
1879 if (sym_index) {
1880 /* XXX: avoid adding a symbol if already present because of
1881 -rdynamic ? */
1882 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1883 if (sym->st_shndx != SHN_UNDEF)
1884 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1885 sym->st_info, 0, sym->st_shndx, name);
1886 } else if (esym->st_shndx == SHN_UNDEF) {
1887 /* weak symbols can stay undefined */
1888 if (ELFW(ST_BIND)(esym->st_info) != STB_WEAK)
1889 tcc_warning("undefined dynamic symbol '%s'", name);
1894 /* Export all non local symbols (for shared libraries) */
1895 static void export_global_syms(TCCState *s1)
1897 int nb_syms, dynindex, index;
1898 const char *name;
1899 ElfW(Sym) *sym;
1901 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1902 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1903 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
1904 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1905 name = (char *) symtab_section->link->data + sym->st_name;
1906 dynindex = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1907 sym->st_info, 0, sym->st_shndx, name);
1908 index = sym - (ElfW(Sym) *) symtab_section->data;
1909 s1->symtab_to_dynsym[index] = dynindex;
1914 /* relocate the PLT: compute addresses and offsets in the PLT now that final
1915 address for PLT and GOT are known (see fill_program_header) */
1916 ST_FUNC void relocate_plt(TCCState *s1)
1918 uint8_t *p, *p_end;
1920 if (!s1->plt)
1921 return;
1923 p = s1->plt->data;
1924 p_end = p + s1->plt->data_offset;
1925 if (p < p_end) {
1926 #if defined(TCC_TARGET_I386)
1927 write32le(p + 2, read32le(p + 2) + s1->got->sh_addr);
1928 write32le(p + 8, read32le(p + 8) + s1->got->sh_addr);
1929 p += 16;
1930 while (p < p_end) {
1931 write32le(p + 2, read32le(p + 2) + s1->got->sh_addr);
1932 p += 16;
1934 #elif defined(TCC_TARGET_X86_64)
1935 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1936 write32le(p + 2, read32le(p + 2) + x);
1937 write32le(p + 8, read32le(p + 8) + x - 6);
1938 p += 16;
1939 while (p < p_end) {
1940 write32le(p + 2, read32le(p + 2) + x + s1->plt->data - p);
1941 p += 16;
1943 #elif defined(TCC_TARGET_ARM)
1944 int x;
1945 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1946 p += 16;
1947 while (p < p_end) {
1948 if (read32le(p) == 0x46c04778) /* PLT Thumb stub present */
1949 p += 4;
1950 write32le(p + 12, x + read32le(p + 12) + s1->plt->data - p);
1951 p += 16;
1953 #elif defined(TCC_TARGET_ARM64)
1954 uint64_t plt = s1->plt->sh_addr;
1955 uint64_t got = s1->got->sh_addr;
1956 uint64_t off = (got >> 12) - (plt >> 12);
1957 if ((off + ((uint32_t)1 << 20)) >> 21)
1958 tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", off, got, plt);
1959 write32le(p, 0xa9bf7bf0); // stp x16,x30,[sp,#-16]!
1960 write32le(p + 4, (0x90000010 | // adrp x16,...
1961 (off & 0x1ffffc) << 3 | (off & 3) << 29));
1962 write32le(p + 8, (0xf9400211 | // ldr x17,[x16,#...]
1963 (got & 0xff8) << 7));
1964 write32le(p + 12, (0x91000210 | // add x16,x16,#...
1965 (got & 0xfff) << 10));
1966 write32le(p + 16, 0xd61f0220); // br x17
1967 write32le(p + 20, 0xd503201f); // nop
1968 write32le(p + 24, 0xd503201f); // nop
1969 write32le(p + 28, 0xd503201f); // nop
1970 p += 32;
1971 while (p < p_end) {
1972 uint64_t pc = plt + (p - s1->plt->data);
1973 uint64_t addr = got + read64le(p);
1974 uint64_t off = (addr >> 12) - (pc >> 12);
1975 if ((off + ((uint32_t)1 << 20)) >> 21)
1976 tcc_error("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", off, addr, pc);
1977 write32le(p, (0x90000010 | // adrp x16,...
1978 (off & 0x1ffffc) << 3 | (off & 3) << 29));
1979 write32le(p + 4, (0xf9400211 | // ldr x17,[x16,#...]
1980 (addr & 0xff8) << 7));
1981 write32le(p + 8, (0x91000210 | // add x16,x16,#...
1982 (addr & 0xfff) << 10));
1983 write32le(p + 12, 0xd61f0220); // br x17
1984 p += 16;
1986 #elif defined(TCC_TARGET_C67)
1987 /* XXX: TODO */
1988 #else
1989 #error unsupported CPU
1990 #endif
1994 /* Allocate strings for section names and decide if an unallocated section
1995 should be output.
1997 NOTE: the strsec section comes last, so its size is also correct ! */
1998 static void alloc_sec_names(TCCState *s1, int file_type, Section *strsec)
2000 int i;
2001 Section *s;
2003 /* Allocate strings for section names */
2004 for(i = 1; i < s1->nb_sections; i++) {
2005 s = s1->sections[i];
2006 s->sh_name = put_elf_str(strsec, s->name);
2007 /* when generating a DLL, we include relocations but we may
2008 patch them */
2009 if (file_type == TCC_OUTPUT_DLL &&
2010 s->sh_type == SHT_RELX &&
2011 !(s->sh_flags & SHF_ALLOC)) {
2012 /* gr: avoid bogus relocs for empty (debug) sections */
2013 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
2014 prepare_dynamic_rel(s1, s);
2015 else if (s1->do_debug)
2016 s->sh_size = s->data_offset;
2017 } else if (s1->do_debug ||
2018 file_type == TCC_OUTPUT_OBJ ||
2019 (s->sh_flags & SHF_ALLOC) ||
2020 i == (s1->nb_sections - 1)) {
2021 /* we output all sections if debug or object file */
2022 s->sh_size = s->data_offset;
2027 /* Info to be copied in dynamic section */
2028 struct dyn_inf {
2029 Section *dynamic;
2030 Section *dynstr;
2031 unsigned long dyn_rel_off;
2032 addr_t rel_addr;
2033 addr_t rel_size;
2034 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2035 addr_t bss_addr;
2036 addr_t bss_size;
2037 #endif
2040 /* Assign sections to segments and decide how are sections laid out when loaded
2041 in memory. This function also fills corresponding program headers. */
2042 static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
2043 Section *interp, Section* strsec,
2044 struct dyn_inf *dyninf, int *sec_order)
2046 int i, j, k, file_type, sh_order_index, file_offset;
2047 unsigned long s_align;
2048 long long tmp;
2049 addr_t addr;
2050 ElfW(Phdr) *ph;
2051 Section *s;
2053 file_type = s1->output_type;
2054 sh_order_index = 1;
2055 file_offset = 0;
2056 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
2057 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2058 s_align = ELF_PAGE_SIZE;
2059 if (s1->section_align)
2060 s_align = s1->section_align;
2062 if (phnum > 0) {
2063 if (s1->has_text_addr) {
2064 int a_offset, p_offset;
2065 addr = s1->text_addr;
2066 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
2067 ELF_PAGE_SIZE */
2068 a_offset = (int) (addr & (s_align - 1));
2069 p_offset = file_offset & (s_align - 1);
2070 if (a_offset < p_offset)
2071 a_offset += s_align;
2072 file_offset += (a_offset - p_offset);
2073 } else {
2074 if (file_type == TCC_OUTPUT_DLL)
2075 addr = 0;
2076 else
2077 addr = ELF_START_ADDR;
2078 /* compute address after headers */
2079 addr += (file_offset & (s_align - 1));
2082 ph = &phdr[0];
2083 /* Leave one program headers for the program interpreter and one for
2084 the program header table itself if needed. These are done later as
2085 they require section layout to be done first. */
2086 if (interp)
2087 ph += 1 + HAVE_PHDR;
2089 /* dynamic relocation table information, for .dynamic section */
2090 dyninf->rel_addr = dyninf->rel_size = 0;
2091 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2092 dyninf->bss_addr = dyninf->bss_size = 0;
2093 #endif
2095 for(j = 0; j < 2; j++) {
2096 ph->p_type = PT_LOAD;
2097 if (j == 0)
2098 ph->p_flags = PF_R | PF_X;
2099 else
2100 ph->p_flags = PF_R | PF_W;
2101 ph->p_align = s_align;
2103 /* Decide the layout of sections loaded in memory. This must
2104 be done before program headers are filled since they contain
2105 info about the layout. We do the following ordering: interp,
2106 symbol tables, relocations, progbits, nobits */
2107 /* XXX: do faster and simpler sorting */
2108 for(k = 0; k < 5; k++) {
2109 for(i = 1; i < s1->nb_sections; i++) {
2110 s = s1->sections[i];
2111 /* compute if section should be included */
2112 if (j == 0) {
2113 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
2114 SHF_ALLOC)
2115 continue;
2116 } else {
2117 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
2118 (SHF_ALLOC | SHF_WRITE))
2119 continue;
2121 if (s == interp) {
2122 if (k != 0)
2123 continue;
2124 } else if (s->sh_type == SHT_DYNSYM ||
2125 s->sh_type == SHT_STRTAB ||
2126 s->sh_type == SHT_HASH) {
2127 if (k != 1)
2128 continue;
2129 } else if (s->sh_type == SHT_RELX) {
2130 if (k != 2)
2131 continue;
2132 } else if (s->sh_type == SHT_NOBITS) {
2133 if (k != 4)
2134 continue;
2135 } else {
2136 if (k != 3)
2137 continue;
2139 sec_order[sh_order_index++] = i;
2141 /* section matches: we align it and add its size */
2142 tmp = addr;
2143 addr = (addr + s->sh_addralign - 1) &
2144 ~(s->sh_addralign - 1);
2145 file_offset += (int) ( addr - tmp );
2146 s->sh_offset = file_offset;
2147 s->sh_addr = addr;
2149 /* update program header infos */
2150 if (ph->p_offset == 0) {
2151 ph->p_offset = file_offset;
2152 ph->p_vaddr = addr;
2153 ph->p_paddr = ph->p_vaddr;
2155 /* update dynamic relocation infos */
2156 if (s->sh_type == SHT_RELX) {
2157 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2158 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) {
2159 dyninf->rel_addr = addr;
2160 dyninf->rel_size += s->sh_size; /* XXX only first rel. */
2162 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) {
2163 dyninf->bss_addr = addr;
2164 dyninf->bss_size = s->sh_size; /* XXX only first rel. */
2166 #else
2167 if (dyninf->rel_size == 0)
2168 dyninf->rel_addr = addr;
2169 dyninf->rel_size += s->sh_size;
2170 #endif
2172 addr += s->sh_size;
2173 if (s->sh_type != SHT_NOBITS)
2174 file_offset += s->sh_size;
2177 if (j == 0) {
2178 /* Make the first PT_LOAD segment include the program
2179 headers itself (and the ELF header as well), it'll
2180 come out with same memory use but will make various
2181 tools like binutils strip work better. */
2182 ph->p_offset &= ~(ph->p_align - 1);
2183 ph->p_vaddr &= ~(ph->p_align - 1);
2184 ph->p_paddr &= ~(ph->p_align - 1);
2186 ph->p_filesz = file_offset - ph->p_offset;
2187 ph->p_memsz = addr - ph->p_vaddr;
2188 ph++;
2189 if (j == 0) {
2190 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2191 /* if in the middle of a page, we duplicate the page in
2192 memory so that one copy is RX and the other is RW */
2193 if ((addr & (s_align - 1)) != 0)
2194 addr += s_align;
2195 } else {
2196 addr = (addr + s_align - 1) & ~(s_align - 1);
2197 file_offset = (file_offset + s_align - 1) & ~(s_align - 1);
2203 /* all other sections come after */
2204 for(i = 1; i < s1->nb_sections; i++) {
2205 s = s1->sections[i];
2206 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2207 continue;
2208 sec_order[sh_order_index++] = i;
2210 file_offset = (file_offset + s->sh_addralign - 1) &
2211 ~(s->sh_addralign - 1);
2212 s->sh_offset = file_offset;
2213 if (s->sh_type != SHT_NOBITS)
2214 file_offset += s->sh_size;
2217 return file_offset;
2220 static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp,
2221 Section *dynamic)
2223 ElfW(Phdr) *ph;
2225 /* if interpreter, then add corresponding program header */
2226 if (interp) {
2227 ph = &phdr[0];
2229 if (HAVE_PHDR)
2231 int len = phnum * sizeof(ElfW(Phdr));
2233 ph->p_type = PT_PHDR;
2234 ph->p_offset = sizeof(ElfW(Ehdr));
2235 ph->p_vaddr = interp->sh_addr - len;
2236 ph->p_paddr = ph->p_vaddr;
2237 ph->p_filesz = ph->p_memsz = len;
2238 ph->p_flags = PF_R | PF_X;
2239 ph->p_align = 4; /* interp->sh_addralign; */
2240 ph++;
2243 ph->p_type = PT_INTERP;
2244 ph->p_offset = interp->sh_offset;
2245 ph->p_vaddr = interp->sh_addr;
2246 ph->p_paddr = ph->p_vaddr;
2247 ph->p_filesz = interp->sh_size;
2248 ph->p_memsz = interp->sh_size;
2249 ph->p_flags = PF_R;
2250 ph->p_align = interp->sh_addralign;
2253 /* if dynamic section, then add corresponding program header */
2254 if (dynamic) {
2255 ph = &phdr[phnum - 1];
2257 ph->p_type = PT_DYNAMIC;
2258 ph->p_offset = dynamic->sh_offset;
2259 ph->p_vaddr = dynamic->sh_addr;
2260 ph->p_paddr = ph->p_vaddr;
2261 ph->p_filesz = dynamic->sh_size;
2262 ph->p_memsz = dynamic->sh_size;
2263 ph->p_flags = PF_R | PF_W;
2264 ph->p_align = dynamic->sh_addralign;
2268 /* Fill the dynamic section with tags describing the address and size of
2269 sections */
2270 static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
2272 Section *dynamic;
2274 dynamic = dyninf->dynamic;
2276 /* put dynamic section entries */
2277 dynamic->data_offset = dyninf->dyn_rel_off;
2278 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
2279 put_dt(dynamic, DT_STRTAB, dyninf->dynstr->sh_addr);
2280 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2281 put_dt(dynamic, DT_STRSZ, dyninf->dynstr->data_offset);
2282 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2283 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
2284 put_dt(dynamic, DT_RELA, dyninf->rel_addr);
2285 put_dt(dynamic, DT_RELASZ, dyninf->rel_size);
2286 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2287 #else
2288 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2289 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2290 put_dt(dynamic, DT_PLTRELSZ, dyninf->rel_size);
2291 put_dt(dynamic, DT_JMPREL, dyninf->rel_addr);
2292 put_dt(dynamic, DT_PLTREL, DT_REL);
2293 put_dt(dynamic, DT_REL, dyninf->bss_addr);
2294 put_dt(dynamic, DT_RELSZ, dyninf->bss_size);
2295 #else
2296 put_dt(dynamic, DT_REL, dyninf->rel_addr);
2297 put_dt(dynamic, DT_RELSZ, dyninf->rel_size);
2298 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2299 #endif
2300 #endif
2301 if (s1->do_debug)
2302 put_dt(dynamic, DT_DEBUG, 0);
2303 put_dt(dynamic, DT_NULL, 0);
2306 /* Relocate remaining sections and symbols (that is those not related to
2307 dynamic linking) */
2308 static int final_sections_reloc(TCCState *s1)
2310 int i;
2311 Section *s;
2313 relocate_syms(s1, 0);
2315 if (s1->nb_errors != 0)
2316 return -1;
2318 /* relocate sections */
2319 /* XXX: ignore sections with allocated relocations ? */
2320 for(i = 1; i < s1->nb_sections; i++) {
2321 s = s1->sections[i];
2322 #ifdef TCC_TARGET_I386
2323 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
2324 /* On X86 gdb 7.3 works in any case but gdb 6.6 will crash if SHF_ALLOC
2325 checking is removed */
2326 #else
2327 if (s->reloc && s != s1->got)
2328 /* On X86_64 gdb 7.3 will crash if SHF_ALLOC checking is present */
2329 #endif
2330 relocate_section(s1, s);
2333 /* relocate relocation entries if the relocation tables are
2334 allocated in the executable */
2335 for(i = 1; i < s1->nb_sections; i++) {
2336 s = s1->sections[i];
2337 if ((s->sh_flags & SHF_ALLOC) &&
2338 s->sh_type == SHT_RELX) {
2339 relocate_rel(s1, s);
2342 return 0;
2345 /* Create an ELF file on disk.
2346 This function handle ELF specific layout requirements */
2347 static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
2348 int file_offset, int *sec_order)
2350 int i, shnum, offset, size, file_type;
2351 Section *s;
2352 ElfW(Ehdr) ehdr;
2353 ElfW(Shdr) shdr, *sh;
2355 file_type = s1->output_type;
2356 shnum = s1->nb_sections;
2358 memset(&ehdr, 0, sizeof(ehdr));
2360 if (phnum > 0) {
2361 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2362 ehdr.e_phnum = phnum;
2363 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2366 /* align to 4 */
2367 file_offset = (file_offset + 3) & -4;
2369 /* fill header */
2370 ehdr.e_ident[0] = ELFMAG0;
2371 ehdr.e_ident[1] = ELFMAG1;
2372 ehdr.e_ident[2] = ELFMAG2;
2373 ehdr.e_ident[3] = ELFMAG3;
2374 ehdr.e_ident[4] = ELFCLASSW;
2375 ehdr.e_ident[5] = ELFDATA2LSB;
2376 ehdr.e_ident[6] = EV_CURRENT;
2377 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2378 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2379 #endif
2380 #ifdef TCC_TARGET_ARM
2381 #ifdef TCC_ARM_EABI
2382 ehdr.e_ident[EI_OSABI] = 0;
2383 ehdr.e_flags = EF_ARM_EABI_VER4;
2384 if (file_type == TCC_OUTPUT_EXE || file_type == TCC_OUTPUT_DLL)
2385 ehdr.e_flags |= EF_ARM_HASENTRY;
2386 if (s1->float_abi == ARM_HARD_FLOAT)
2387 ehdr.e_flags |= EF_ARM_VFP_FLOAT;
2388 else
2389 ehdr.e_flags |= EF_ARM_SOFT_FLOAT;
2390 #else
2391 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2392 #endif
2393 #endif
2394 switch(file_type) {
2395 default:
2396 case TCC_OUTPUT_EXE:
2397 ehdr.e_type = ET_EXEC;
2398 ehdr.e_entry = get_elf_sym_addr(s1, "_start", 1);
2399 break;
2400 case TCC_OUTPUT_DLL:
2401 ehdr.e_type = ET_DYN;
2402 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2403 break;
2404 case TCC_OUTPUT_OBJ:
2405 ehdr.e_type = ET_REL;
2406 break;
2408 ehdr.e_machine = EM_TCC_TARGET;
2409 ehdr.e_version = EV_CURRENT;
2410 ehdr.e_shoff = file_offset;
2411 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2412 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2413 ehdr.e_shnum = shnum;
2414 ehdr.e_shstrndx = shnum - 1;
2416 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2417 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2418 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2420 sort_syms(s1, symtab_section);
2421 for(i = 1; i < s1->nb_sections; i++) {
2422 s = s1->sections[sec_order[i]];
2423 if (s->sh_type != SHT_NOBITS) {
2424 if (s->sh_type == SHT_DYNSYM)
2425 patch_dynsym_undef(s1, s);
2426 while (offset < s->sh_offset) {
2427 fputc(0, f);
2428 offset++;
2430 size = s->sh_size;
2431 if (size)
2432 fwrite(s->data, 1, size, f);
2433 offset += size;
2437 /* output section headers */
2438 while (offset < ehdr.e_shoff) {
2439 fputc(0, f);
2440 offset++;
2443 for(i = 0; i < s1->nb_sections; i++) {
2444 sh = &shdr;
2445 memset(sh, 0, sizeof(ElfW(Shdr)));
2446 s = s1->sections[i];
2447 if (s) {
2448 sh->sh_name = s->sh_name;
2449 sh->sh_type = s->sh_type;
2450 sh->sh_flags = s->sh_flags;
2451 sh->sh_entsize = s->sh_entsize;
2452 sh->sh_info = s->sh_info;
2453 if (s->link)
2454 sh->sh_link = s->link->sh_num;
2455 sh->sh_addralign = s->sh_addralign;
2456 sh->sh_addr = s->sh_addr;
2457 sh->sh_offset = s->sh_offset;
2458 sh->sh_size = s->sh_size;
2460 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2464 /* Write an elf, coff or "binary" file */
2465 static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum,
2466 ElfW(Phdr) *phdr, int file_offset, int *sec_order)
2468 int fd, mode, file_type;
2469 FILE *f;
2471 file_type = s1->output_type;
2472 if (file_type == TCC_OUTPUT_OBJ)
2473 mode = 0666;
2474 else
2475 mode = 0777;
2476 unlink(filename);
2477 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2478 if (fd < 0) {
2479 tcc_error_noabort("could not write '%s'", filename);
2480 return -1;
2482 f = fdopen(fd, "wb");
2483 if (s1->verbose)
2484 printf("<- %s\n", filename);
2486 #ifdef TCC_TARGET_COFF
2487 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF)
2488 tcc_output_coff(s1, f);
2489 else
2490 #endif
2491 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
2492 tcc_output_elf(s1, f, phnum, phdr, file_offset, sec_order);
2493 else
2494 tcc_output_binary(s1, f, sec_order);
2495 fclose(f);
2497 return 0;
2500 /* Output an elf, coff or binary file */
2501 /* XXX: suppress unneeded sections */
2502 static int elf_output_file(TCCState *s1, const char *filename)
2504 int i, ret, phnum, shnum, file_type, file_offset, *sec_order;
2505 struct dyn_inf dyninf;
2506 ElfW(Phdr) *phdr;
2507 ElfW(Sym) *sym;
2508 Section *strsec, *interp, *dynamic, *dynstr;
2510 file_type = s1->output_type;
2511 s1->nb_errors = 0;
2513 /* if linking, also link in runtime libraries (libc, libgcc, etc.) */
2514 if (file_type != TCC_OUTPUT_OBJ) {
2515 tcc_add_runtime(s1);
2518 phdr = NULL;
2519 sec_order = NULL;
2520 interp = dynamic = dynstr = NULL; /* avoid warning */
2521 dyninf.dyn_rel_off = 0; /* avoid warning */
2523 if (file_type != TCC_OUTPUT_OBJ) {
2524 relocate_common_syms();
2526 tcc_add_linker_symbols(s1);
2528 if (!s1->static_link) {
2529 if (file_type == TCC_OUTPUT_EXE) {
2530 char *ptr;
2531 /* allow override the dynamic loader */
2532 const char *elfint = getenv("LD_SO");
2533 if (elfint == NULL)
2534 elfint = DEFAULT_ELFINTERP(s1);
2535 /* add interpreter section only if executable */
2536 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
2537 interp->sh_addralign = 1;
2538 ptr = section_ptr_add(interp, 1 + strlen(elfint));
2539 strcpy(ptr, elfint);
2542 /* add dynamic symbol table */
2543 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
2544 ".dynstr",
2545 ".hash", SHF_ALLOC);
2546 dynstr = s1->dynsym->link;
2548 /* add dynamic section */
2549 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
2550 SHF_ALLOC | SHF_WRITE);
2551 dynamic->link = dynstr;
2552 dynamic->sh_entsize = sizeof(ElfW(Dyn));
2554 build_got(s1);
2556 if (file_type == TCC_OUTPUT_EXE) {
2557 bind_exe_dynsyms(s1);
2559 if (s1->nb_errors) {
2560 ret = -1;
2561 goto the_end;
2564 bind_libs_dynsyms(s1);
2565 } else /* shared library case: simply export all global symbols */
2566 export_global_syms(s1);
2568 build_got_entries(s1);
2570 /* add a list of needed dlls */
2571 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2572 DLLReference *dllref = s1->loaded_dlls[i];
2573 if (dllref->level == 0)
2574 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
2577 if (s1->rpath)
2578 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
2580 /* XXX: currently, since we do not handle PIC code, we
2581 must relocate the readonly segments */
2582 if (file_type == TCC_OUTPUT_DLL) {
2583 if (s1->soname)
2584 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
2585 put_dt(dynamic, DT_TEXTREL, 0);
2588 if (s1->symbolic)
2589 put_dt(dynamic, DT_SYMBOLIC, 0);
2591 /* add necessary space for other entries */
2592 dyninf.dyn_rel_off = dynamic->data_offset;
2593 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
2594 } else {
2595 /* still need to build got entries in case of static link */
2596 build_got_entries(s1);
2600 /* we add a section for symbols */
2601 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
2602 put_elf_str(strsec, "");
2604 /* compute number of sections */
2605 shnum = s1->nb_sections;
2607 /* this array is used to reorder sections in the output file */
2608 sec_order = tcc_malloc(sizeof(int) * shnum);
2609 sec_order[0] = 0;
2611 /* compute number of program headers */
2612 switch(file_type) {
2613 default:
2614 case TCC_OUTPUT_OBJ:
2615 phnum = 0;
2616 break;
2617 case TCC_OUTPUT_EXE:
2618 if (!s1->static_link)
2619 phnum = 4 + HAVE_PHDR;
2620 else
2621 phnum = 2;
2622 break;
2623 case TCC_OUTPUT_DLL:
2624 phnum = 3;
2625 break;
2628 /* Allocate strings for section names */
2629 alloc_sec_names(s1, file_type, strsec);
2631 /* allocate program segment headers */
2632 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
2634 /* compute section to program header mapping */
2635 file_offset = layout_sections(s1, phdr, phnum, interp, strsec, &dyninf,
2636 sec_order);
2638 /* Fill remaining program header and finalize relocation related to dynamic
2639 linking. */
2640 if (phnum > 0) {
2641 fill_unloadable_phdr(phdr, phnum, interp, dynamic);
2642 if (dynamic) {
2643 dyninf.dynamic = dynamic;
2644 dyninf.dynstr = dynstr;
2646 fill_dynamic(s1, &dyninf);
2648 /* put in GOT the dynamic section address and relocate PLT */
2649 write32le(s1->got->data, dynamic->sh_addr);
2650 if (file_type == TCC_OUTPUT_EXE
2651 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2652 || file_type == TCC_OUTPUT_DLL
2653 #endif
2655 relocate_plt(s1);
2657 /* relocate symbols in .dynsym now that final addresses are known */
2658 for_each_elem(s1->dynsym, 1, sym, ElfW(Sym)) {
2659 if (sym->st_shndx == SHN_UNDEF) {
2660 /* relocate to PLT if symbol corresponds to a PLT entry,
2661 but not if it's a weak symbol */
2662 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
2663 sym->st_value = 0;
2664 else if (sym->st_value)
2665 sym->st_value += s1->plt->sh_addr;
2666 } else if (sym->st_shndx < SHN_LORESERVE) {
2667 /* do symbol relocation */
2668 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
2674 /* if building executable or DLL, then relocate each section
2675 except the GOT which is already relocated */
2676 if (file_type != TCC_OUTPUT_OBJ) {
2677 ret = final_sections_reloc(s1);
2678 if (ret)
2679 goto the_end;
2682 /* Perform relocation to GOT or PLT entries */
2683 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2684 fill_got(s1);
2686 /* Create the ELF file with name 'filename' */
2687 ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order);
2688 the_end:
2689 tcc_free(s1->symtab_to_dynsym);
2690 tcc_free(sec_order);
2691 tcc_free(phdr);
2692 tcc_free(s1->sym_attrs);
2693 s1->sym_attrs = NULL;
2694 return ret;
2697 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2699 int ret;
2700 #ifdef TCC_TARGET_PE
2701 if (s->output_type != TCC_OUTPUT_OBJ) {
2702 ret = pe_output_file(s, filename);
2703 } else
2704 #endif
2705 ret = elf_output_file(s, filename);
2706 return ret;
2709 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2711 void *data;
2713 data = tcc_malloc(size);
2714 lseek(fd, file_offset, SEEK_SET);
2715 read(fd, data, size);
2716 return data;
2719 typedef struct SectionMergeInfo {
2720 Section *s; /* corresponding existing section */
2721 unsigned long offset; /* offset of the new section in the existing section */
2722 uint8_t new_section; /* true if section 's' was added */
2723 uint8_t link_once; /* true if link once section */
2724 } SectionMergeInfo;
2726 ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h)
2728 int size = read(fd, h, sizeof *h);
2729 if (size == sizeof *h && 0 == memcmp(h, ELFMAG, 4)) {
2730 if (h->e_type == ET_REL)
2731 return AFF_BINTYPE_REL;
2732 if (h->e_type == ET_DYN)
2733 return AFF_BINTYPE_DYN;
2734 } else if (size >= 8) {
2735 if (0 == memcmp(h, ARMAG, 8))
2736 return AFF_BINTYPE_AR;
2737 #ifdef TCC_TARGET_COFF
2738 if (((struct filehdr*)h)->f_magic == COFF_C67_MAGIC)
2739 return AFF_BINTYPE_C67;
2740 #endif
2742 return 0;
2745 /* load an object file and merge it with current files */
2746 /* XXX: handle correctly stab (debug) info */
2747 ST_FUNC int tcc_load_object_file(TCCState *s1,
2748 int fd, unsigned long file_offset)
2750 ElfW(Ehdr) ehdr;
2751 ElfW(Shdr) *shdr, *sh;
2752 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2753 unsigned char *strsec, *strtab;
2754 int *old_to_new_syms;
2755 char *sh_name, *name;
2756 SectionMergeInfo *sm_table, *sm;
2757 ElfW(Sym) *sym, *symtab;
2758 ElfW_Rel *rel;
2759 Section *s;
2761 int stab_index;
2762 int stabstr_index;
2764 stab_index = stabstr_index = 0;
2766 lseek(fd, file_offset, SEEK_SET);
2767 if (tcc_object_type(fd, &ehdr) != AFF_BINTYPE_REL)
2768 goto fail1;
2769 /* test CPU specific stuff */
2770 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2771 ehdr.e_machine != EM_TCC_TARGET) {
2772 fail1:
2773 tcc_error_noabort("invalid object file");
2774 return -1;
2776 /* read sections */
2777 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2778 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2779 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2781 /* load section names */
2782 sh = &shdr[ehdr.e_shstrndx];
2783 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2785 /* load symtab and strtab */
2786 old_to_new_syms = NULL;
2787 symtab = NULL;
2788 strtab = NULL;
2789 nb_syms = 0;
2790 for(i = 1; i < ehdr.e_shnum; i++) {
2791 sh = &shdr[i];
2792 if (sh->sh_type == SHT_SYMTAB) {
2793 if (symtab) {
2794 tcc_error_noabort("object must contain only one symtab");
2795 fail:
2796 ret = -1;
2797 goto the_end;
2799 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2800 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2801 sm_table[i].s = symtab_section;
2803 /* now load strtab */
2804 sh = &shdr[sh->sh_link];
2805 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2809 /* now examine each section and try to merge its content with the
2810 ones in memory */
2811 for(i = 1; i < ehdr.e_shnum; i++) {
2812 /* no need to examine section name strtab */
2813 if (i == ehdr.e_shstrndx)
2814 continue;
2815 sh = &shdr[i];
2816 sh_name = (char *) strsec + sh->sh_name;
2817 /* ignore sections types we do not handle */
2818 if (sh->sh_type != SHT_PROGBITS &&
2819 sh->sh_type != SHT_RELX &&
2820 #ifdef TCC_ARM_EABI
2821 sh->sh_type != SHT_ARM_EXIDX &&
2822 #endif
2823 sh->sh_type != SHT_NOBITS &&
2824 sh->sh_type != SHT_PREINIT_ARRAY &&
2825 sh->sh_type != SHT_INIT_ARRAY &&
2826 sh->sh_type != SHT_FINI_ARRAY &&
2827 strcmp(sh_name, ".stabstr")
2829 continue;
2830 if (sh->sh_addralign < 1)
2831 sh->sh_addralign = 1;
2832 /* find corresponding section, if any */
2833 for(j = 1; j < s1->nb_sections;j++) {
2834 s = s1->sections[j];
2835 if (!strcmp(s->name, sh_name)) {
2836 if (!strncmp(sh_name, ".gnu.linkonce",
2837 sizeof(".gnu.linkonce") - 1)) {
2838 /* if a 'linkonce' section is already present, we
2839 do not add it again. It is a little tricky as
2840 symbols can still be defined in
2841 it. */
2842 sm_table[i].link_once = 1;
2843 goto next;
2844 } else {
2845 goto found;
2849 /* not found: create new section */
2850 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2851 /* take as much info as possible from the section. sh_link and
2852 sh_info will be updated later */
2853 s->sh_addralign = sh->sh_addralign;
2854 s->sh_entsize = sh->sh_entsize;
2855 sm_table[i].new_section = 1;
2856 found:
2857 if (sh->sh_type != s->sh_type) {
2858 tcc_error_noabort("invalid section type");
2859 goto fail;
2862 /* align start of section */
2863 offset = s->data_offset;
2865 if (0 == strcmp(sh_name, ".stab")) {
2866 stab_index = i;
2867 goto no_align;
2869 if (0 == strcmp(sh_name, ".stabstr")) {
2870 stabstr_index = i;
2871 goto no_align;
2874 size = sh->sh_addralign - 1;
2875 offset = (offset + size) & ~size;
2876 if (sh->sh_addralign > s->sh_addralign)
2877 s->sh_addralign = sh->sh_addralign;
2878 s->data_offset = offset;
2879 no_align:
2880 sm_table[i].offset = offset;
2881 sm_table[i].s = s;
2882 /* concatenate sections */
2883 size = sh->sh_size;
2884 if (sh->sh_type != SHT_NOBITS) {
2885 unsigned char *ptr;
2886 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2887 ptr = section_ptr_add(s, size);
2888 read(fd, ptr, size);
2889 } else {
2890 s->data_offset += size;
2892 next: ;
2895 /* gr relocate stab strings */
2896 if (stab_index && stabstr_index) {
2897 Stab_Sym *a, *b;
2898 unsigned o;
2899 s = sm_table[stab_index].s;
2900 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2901 b = (Stab_Sym *)(s->data + s->data_offset);
2902 o = sm_table[stabstr_index].offset;
2903 while (a < b)
2904 a->n_strx += o, a++;
2907 /* second short pass to update sh_link and sh_info fields of new
2908 sections */
2909 for(i = 1; i < ehdr.e_shnum; i++) {
2910 s = sm_table[i].s;
2911 if (!s || !sm_table[i].new_section)
2912 continue;
2913 sh = &shdr[i];
2914 if (sh->sh_link > 0)
2915 s->link = sm_table[sh->sh_link].s;
2916 if (sh->sh_type == SHT_RELX) {
2917 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2918 /* update backward link */
2919 s1->sections[s->sh_info]->reloc = s;
2922 sm = sm_table;
2924 /* resolve symbols */
2925 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2927 sym = symtab + 1;
2928 for(i = 1; i < nb_syms; i++, sym++) {
2929 if (sym->st_shndx != SHN_UNDEF &&
2930 sym->st_shndx < SHN_LORESERVE) {
2931 sm = &sm_table[sym->st_shndx];
2932 if (sm->link_once) {
2933 /* if a symbol is in a link once section, we use the
2934 already defined symbol. It is very important to get
2935 correct relocations */
2936 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2937 name = (char *) strtab + sym->st_name;
2938 sym_index = find_elf_sym(symtab_section, name);
2939 if (sym_index)
2940 old_to_new_syms[i] = sym_index;
2942 continue;
2944 /* if no corresponding section added, no need to add symbol */
2945 if (!sm->s)
2946 continue;
2947 /* convert section number */
2948 sym->st_shndx = sm->s->sh_num;
2949 /* offset value */
2950 sym->st_value += sm->offset;
2952 /* add symbol */
2953 name = (char *) strtab + sym->st_name;
2954 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2955 sym->st_info, sym->st_other,
2956 sym->st_shndx, name);
2957 old_to_new_syms[i] = sym_index;
2960 /* third pass to patch relocation entries */
2961 for(i = 1; i < ehdr.e_shnum; i++) {
2962 s = sm_table[i].s;
2963 if (!s)
2964 continue;
2965 sh = &shdr[i];
2966 offset = sm_table[i].offset;
2967 switch(s->sh_type) {
2968 case SHT_RELX:
2969 /* take relocation offset information */
2970 offseti = sm_table[sh->sh_info].offset;
2971 for_each_elem(s, (offset / sizeof(*rel)), rel, ElfW_Rel) {
2972 int type;
2973 unsigned sym_index;
2974 /* convert symbol index */
2975 type = ELFW(R_TYPE)(rel->r_info);
2976 sym_index = ELFW(R_SYM)(rel->r_info);
2977 /* NOTE: only one symtab assumed */
2978 if (sym_index >= nb_syms)
2979 goto invalid_reloc;
2980 sym_index = old_to_new_syms[sym_index];
2981 /* ignore link_once in rel section. */
2982 if (!sym_index && !sm->link_once
2983 #ifdef TCC_TARGET_ARM
2984 && type != R_ARM_V4BX
2985 #endif
2987 invalid_reloc:
2988 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2989 i, strsec + sh->sh_name, rel->r_offset);
2990 goto fail;
2992 rel->r_info = ELFW(R_INFO)(sym_index, type);
2993 /* offset the relocation offset */
2994 rel->r_offset += offseti;
2995 #ifdef TCC_TARGET_ARM
2996 /* Jumps and branches from a Thumb code to a PLT entry need
2997 special handling since PLT entries are ARM code.
2998 Unconditional bl instructions referencing PLT entries are
2999 handled by converting these instructions into blx
3000 instructions. Other case of instructions referencing a PLT
3001 entry require to add a Thumb stub before the PLT entry to
3002 switch to ARM mode. We set bit plt_thumb_stub of the
3003 attribute of a symbol to indicate such a case. */
3004 if (type == R_ARM_THM_JUMP24)
3005 alloc_sym_attr(s1, sym_index)->plt_thumb_stub = 1;
3006 #endif
3008 break;
3009 default:
3010 break;
3014 ret = 0;
3015 the_end:
3016 tcc_free(symtab);
3017 tcc_free(strtab);
3018 tcc_free(old_to_new_syms);
3019 tcc_free(sm_table);
3020 tcc_free(strsec);
3021 tcc_free(shdr);
3022 return ret;
3025 typedef struct ArchiveHeader {
3026 char ar_name[16]; /* name of this member */
3027 char ar_date[12]; /* file mtime */
3028 char ar_uid[6]; /* owner uid; printed as decimal */
3029 char ar_gid[6]; /* owner gid; printed as decimal */
3030 char ar_mode[8]; /* file mode, printed as octal */
3031 char ar_size[10]; /* file size, printed as decimal */
3032 char ar_fmag[2]; /* should contain ARFMAG */
3033 } ArchiveHeader;
3035 static int get_be32(const uint8_t *b)
3037 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
3040 /* load only the objects which resolve undefined symbols */
3041 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
3043 int i, bound, nsyms, sym_index, off, ret;
3044 uint8_t *data;
3045 const char *ar_names, *p;
3046 const uint8_t *ar_index;
3047 ElfW(Sym) *sym;
3049 data = tcc_malloc(size);
3050 if (read(fd, data, size) != size)
3051 goto fail;
3052 nsyms = get_be32(data);
3053 ar_index = data + 4;
3054 ar_names = (char *) ar_index + nsyms * 4;
3056 do {
3057 bound = 0;
3058 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
3059 sym_index = find_elf_sym(symtab_section, p);
3060 if(sym_index) {
3061 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
3062 if(sym->st_shndx == SHN_UNDEF) {
3063 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
3064 ++bound;
3065 if(tcc_load_object_file(s1, fd, off) < 0) {
3066 fail:
3067 ret = -1;
3068 goto the_end;
3073 } while(bound);
3074 ret = 0;
3075 the_end:
3076 tcc_free(data);
3077 return ret;
3080 /* load a '.a' file */
3081 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
3083 ArchiveHeader hdr;
3084 char ar_size[11];
3085 char ar_name[17];
3086 char magic[8];
3087 int size, len, i;
3088 unsigned long file_offset;
3090 /* skip magic which was already checked */
3091 read(fd, magic, sizeof(magic));
3093 for(;;) {
3094 len = read(fd, &hdr, sizeof(hdr));
3095 if (len == 0)
3096 break;
3097 if (len != sizeof(hdr)) {
3098 tcc_error_noabort("invalid archive");
3099 return -1;
3101 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
3102 ar_size[sizeof(hdr.ar_size)] = '\0';
3103 size = strtol(ar_size, NULL, 0);
3104 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
3105 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
3106 if (ar_name[i] != ' ')
3107 break;
3109 ar_name[i + 1] = '\0';
3110 file_offset = lseek(fd, 0, SEEK_CUR);
3111 /* align to even */
3112 size = (size + 1) & ~1;
3113 if (!strcmp(ar_name, "/")) {
3114 /* coff symbol table : we handle it */
3115 if(s1->alacarte_link)
3116 return tcc_load_alacarte(s1, fd, size);
3117 } else {
3118 ElfW(Ehdr) ehdr;
3119 if (tcc_object_type(fd, &ehdr) == AFF_BINTYPE_REL) {
3120 if (tcc_load_object_file(s1, fd, file_offset) < 0)
3121 return -1;
3124 lseek(fd, file_offset + size, SEEK_SET);
3126 return 0;
3129 #ifndef TCC_TARGET_PE
3130 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
3131 is referenced by the user (so it should be added as DT_NEEDED in
3132 the generated ELF file) */
3133 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
3135 ElfW(Ehdr) ehdr;
3136 ElfW(Shdr) *shdr, *sh, *sh1;
3137 int i, j, nb_syms, nb_dts, sym_bind, ret;
3138 ElfW(Sym) *sym, *dynsym;
3139 ElfW(Dyn) *dt, *dynamic;
3140 unsigned char *dynstr;
3141 const char *name, *soname;
3142 DLLReference *dllref;
3144 read(fd, &ehdr, sizeof(ehdr));
3146 /* test CPU specific stuff */
3147 if (ehdr.e_ident[5] != ELFDATA2LSB ||
3148 ehdr.e_machine != EM_TCC_TARGET) {
3149 tcc_error_noabort("bad architecture");
3150 return -1;
3153 /* read sections */
3154 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
3156 /* load dynamic section and dynamic symbols */
3157 nb_syms = 0;
3158 nb_dts = 0;
3159 dynamic = NULL;
3160 dynsym = NULL; /* avoid warning */
3161 dynstr = NULL; /* avoid warning */
3162 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
3163 switch(sh->sh_type) {
3164 case SHT_DYNAMIC:
3165 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
3166 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
3167 break;
3168 case SHT_DYNSYM:
3169 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
3170 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
3171 sh1 = &shdr[sh->sh_link];
3172 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
3173 break;
3174 default:
3175 break;
3179 /* compute the real library name */
3180 soname = tcc_basename(filename);
3182 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
3183 if (dt->d_tag == DT_SONAME) {
3184 soname = (char *) dynstr + dt->d_un.d_val;
3188 /* if the dll is already loaded, do not load it */
3189 for(i = 0; i < s1->nb_loaded_dlls; i++) {
3190 dllref = s1->loaded_dlls[i];
3191 if (!strcmp(soname, dllref->name)) {
3192 /* but update level if needed */
3193 if (level < dllref->level)
3194 dllref->level = level;
3195 ret = 0;
3196 goto the_end;
3200 /* add the dll and its level */
3201 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
3202 dllref->level = level;
3203 strcpy(dllref->name, soname);
3204 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
3206 /* add dynamic symbols in dynsym_section */
3207 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
3208 sym_bind = ELFW(ST_BIND)(sym->st_info);
3209 if (sym_bind == STB_LOCAL)
3210 continue;
3211 name = (char *) dynstr + sym->st_name;
3212 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
3213 sym->st_info, sym->st_other, sym->st_shndx, name);
3216 /* load all referenced DLLs */
3217 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
3218 switch(dt->d_tag) {
3219 case DT_NEEDED:
3220 name = (char *) dynstr + dt->d_un.d_val;
3221 for(j = 0; j < s1->nb_loaded_dlls; j++) {
3222 dllref = s1->loaded_dlls[j];
3223 if (!strcmp(name, dllref->name))
3224 goto already_loaded;
3226 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
3227 tcc_error_noabort("referenced dll '%s' not found", name);
3228 ret = -1;
3229 goto the_end;
3231 already_loaded:
3232 break;
3235 ret = 0;
3236 the_end:
3237 tcc_free(dynstr);
3238 tcc_free(dynsym);
3239 tcc_free(dynamic);
3240 tcc_free(shdr);
3241 return ret;
3244 #define LD_TOK_NAME 256
3245 #define LD_TOK_EOF (-1)
3247 /* return next ld script token */
3248 static int ld_next(TCCState *s1, char *name, int name_size)
3250 int c;
3251 char *q;
3253 redo:
3254 switch(ch) {
3255 case ' ':
3256 case '\t':
3257 case '\f':
3258 case '\v':
3259 case '\r':
3260 case '\n':
3261 inp();
3262 goto redo;
3263 case '/':
3264 minp();
3265 if (ch == '*') {
3266 file->buf_ptr = parse_comment(file->buf_ptr);
3267 ch = file->buf_ptr[0];
3268 goto redo;
3269 } else {
3270 q = name;
3271 *q++ = '/';
3272 goto parse_name;
3274 break;
3275 case '\\':
3276 ch = handle_eob();
3277 if (ch != '\\')
3278 goto redo;
3279 /* fall through */
3280 /* case 'a' ... 'z': */
3281 case 'a':
3282 case 'b':
3283 case 'c':
3284 case 'd':
3285 case 'e':
3286 case 'f':
3287 case 'g':
3288 case 'h':
3289 case 'i':
3290 case 'j':
3291 case 'k':
3292 case 'l':
3293 case 'm':
3294 case 'n':
3295 case 'o':
3296 case 'p':
3297 case 'q':
3298 case 'r':
3299 case 's':
3300 case 't':
3301 case 'u':
3302 case 'v':
3303 case 'w':
3304 case 'x':
3305 case 'y':
3306 case 'z':
3307 /* case 'A' ... 'z': */
3308 case 'A':
3309 case 'B':
3310 case 'C':
3311 case 'D':
3312 case 'E':
3313 case 'F':
3314 case 'G':
3315 case 'H':
3316 case 'I':
3317 case 'J':
3318 case 'K':
3319 case 'L':
3320 case 'M':
3321 case 'N':
3322 case 'O':
3323 case 'P':
3324 case 'Q':
3325 case 'R':
3326 case 'S':
3327 case 'T':
3328 case 'U':
3329 case 'V':
3330 case 'W':
3331 case 'X':
3332 case 'Y':
3333 case 'Z':
3334 case '_':
3335 case '.':
3336 case '$':
3337 case '~':
3338 q = name;
3339 parse_name:
3340 for(;;) {
3341 if (!((ch >= 'a' && ch <= 'z') ||
3342 (ch >= 'A' && ch <= 'Z') ||
3343 (ch >= '0' && ch <= '9') ||
3344 strchr("/.-_+=$:\\,~", ch)))
3345 break;
3346 if ((q - name) < name_size - 1) {
3347 *q++ = ch;
3349 minp();
3351 *q = '\0';
3352 c = LD_TOK_NAME;
3353 break;
3354 case CH_EOF:
3355 c = LD_TOK_EOF;
3356 break;
3357 default:
3358 c = ch;
3359 inp();
3360 break;
3362 return c;
3365 static int ld_add_file(TCCState *s1, const char filename[])
3367 int ret;
3369 ret = tcc_add_file_internal(s1, filename, AFF_TYPE_BIN);
3370 if (ret)
3371 ret = tcc_add_dll(s1, filename, 0);
3372 return ret;
3375 static inline int new_undef_syms(void)
3377 int ret = 0;
3378 ret = new_undef_sym;
3379 new_undef_sym = 0;
3380 return ret;
3383 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
3385 char filename[1024], libname[1024];
3386 int t, group, nblibs = 0, ret = 0;
3387 char **libs = NULL;
3389 group = !strcmp(cmd, "GROUP");
3390 if (!as_needed)
3391 new_undef_syms();
3392 t = ld_next(s1, filename, sizeof(filename));
3393 if (t != '(')
3394 expect("(");
3395 t = ld_next(s1, filename, sizeof(filename));
3396 for(;;) {
3397 libname[0] = '\0';
3398 if (t == LD_TOK_EOF) {
3399 tcc_error_noabort("unexpected end of file");
3400 ret = -1;
3401 goto lib_parse_error;
3402 } else if (t == ')') {
3403 break;
3404 } else if (t == '-') {
3405 t = ld_next(s1, filename, sizeof(filename));
3406 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
3407 tcc_error_noabort("library name expected");
3408 ret = -1;
3409 goto lib_parse_error;
3411 pstrcpy(libname, sizeof libname, &filename[1]);
3412 if (s1->static_link) {
3413 snprintf(filename, sizeof filename, "lib%s.a", libname);
3414 } else {
3415 snprintf(filename, sizeof filename, "lib%s.so", libname);
3417 } else if (t != LD_TOK_NAME) {
3418 tcc_error_noabort("filename expected");
3419 ret = -1;
3420 goto lib_parse_error;
3422 if (!strcmp(filename, "AS_NEEDED")) {
3423 ret = ld_add_file_list(s1, cmd, 1);
3424 if (ret)
3425 goto lib_parse_error;
3426 } else {
3427 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3428 if (!as_needed) {
3429 ret = ld_add_file(s1, filename);
3430 if (ret)
3431 goto lib_parse_error;
3432 if (group) {
3433 /* Add the filename *and* the libname to avoid future conversions */
3434 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
3435 if (libname[0] != '\0')
3436 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
3440 t = ld_next(s1, filename, sizeof(filename));
3441 if (t == ',') {
3442 t = ld_next(s1, filename, sizeof(filename));
3445 if (group && !as_needed) {
3446 while (new_undef_syms()) {
3447 int i;
3449 for (i = 0; i < nblibs; i ++)
3450 ld_add_file(s1, libs[i]);
3453 lib_parse_error:
3454 dynarray_reset(&libs, &nblibs);
3455 return ret;
3458 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3459 files */
3460 ST_FUNC int tcc_load_ldscript(TCCState *s1)
3462 char cmd[64];
3463 char filename[1024];
3464 int t, ret;
3466 ch = handle_eob();
3467 for(;;) {
3468 t = ld_next(s1, cmd, sizeof(cmd));
3469 if (t == LD_TOK_EOF)
3470 return 0;
3471 else if (t != LD_TOK_NAME)
3472 return -1;
3473 if (!strcmp(cmd, "INPUT") ||
3474 !strcmp(cmd, "GROUP")) {
3475 ret = ld_add_file_list(s1, cmd, 0);
3476 if (ret)
3477 return ret;
3478 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3479 !strcmp(cmd, "TARGET")) {
3480 /* ignore some commands */
3481 t = ld_next(s1, cmd, sizeof(cmd));
3482 if (t != '(')
3483 expect("(");
3484 for(;;) {
3485 t = ld_next(s1, filename, sizeof(filename));
3486 if (t == LD_TOK_EOF) {
3487 tcc_error_noabort("unexpected end of file");
3488 return -1;
3489 } else if (t == ')') {
3490 break;
3493 } else {
3494 return -1;
3497 return 0;
3499 #endif /* !TCC_TARGET_PE */