Revert "-fnormalize-inc-dirs"
[tinycc.git] / tccelf.c
blob0aa70144459f62fc4d24b8d709d7381bd357e354
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 && (sh_num < SHN_LORESERVE || sh_num == SHN_COMMON)) {
241 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
242 No idea if this is the correct solution ... */
243 goto do_patch;
244 } else if (s == tcc_state->dynsymtab_section) {
245 /* we accept that two DLL define the same symbol */
246 } else {
247 #if 0
248 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
249 sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
250 #endif
251 tcc_error_noabort("'%s' defined twice... may be -fcommon is needed?", name);
253 } else {
254 do_patch:
255 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
256 esym->st_shndx = sh_num;
257 new_undef_sym = 1;
258 esym->st_value = value;
259 esym->st_size = size;
260 esym->st_other = other;
262 } else {
263 do_def:
264 sym_index = put_elf_sym(s, value, size,
265 ELFW(ST_INFO)(sym_bind, sym_type), other,
266 sh_num, name);
268 return sym_index;
271 /* put relocation */
272 ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset,
273 int type, int symbol, addr_t addend)
275 char buf[256];
276 Section *sr;
277 ElfW_Rel *rel;
279 sr = s->reloc;
280 if (!sr) {
281 /* if no relocation section, create it */
282 snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
283 /* if the symtab is allocated, then we consider the relocation
284 are also */
285 sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
286 sr->sh_entsize = sizeof(ElfW_Rel);
287 sr->link = symtab;
288 sr->sh_info = s->sh_num;
289 s->reloc = sr;
291 rel = section_ptr_add(sr, sizeof(ElfW_Rel));
292 rel->r_offset = offset;
293 rel->r_info = ELFW(R_INFO)(symbol, type);
294 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
295 rel->r_addend = addend;
296 #else
297 if (addend)
298 tcc_error("non-zero addend on REL architecture");
299 #endif
302 ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
303 int type, int symbol)
305 put_elf_reloca(symtab, s, offset, type, symbol, 0);
308 /* put stab debug information */
310 ST_FUNC void put_stabs(const char *str, int type, int other, int desc,
311 unsigned long value)
313 Stab_Sym *sym;
315 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
316 if (str) {
317 sym->n_strx = put_elf_str(stabstr_section, str);
318 } else {
319 sym->n_strx = 0;
321 sym->n_type = type;
322 sym->n_other = other;
323 sym->n_desc = desc;
324 sym->n_value = value;
327 ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc,
328 unsigned long value, Section *sec, int sym_index)
330 put_stabs(str, type, other, desc, value);
331 put_elf_reloc(symtab_section, stab_section,
332 stab_section->data_offset - sizeof(unsigned int),
333 R_DATA_32, sym_index);
336 ST_FUNC void put_stabn(int type, int other, int desc, int value)
338 put_stabs(NULL, type, other, desc, value);
341 ST_FUNC void put_stabd(int type, int other, int desc)
343 put_stabs(NULL, type, other, desc, 0);
346 /* Browse each elem of type <type> in section <sec> starting at elem <startoff>
347 using variable <elem> */
348 #define for_each_elem(sec, startoff, elem, type) \
349 for (elem = (type *) sec->data + startoff; \
350 elem < (type *) (sec->data + sec->data_offset); elem++)
352 /* In an ELF file symbol table, the local symbols must appear below
353 the global and weak ones. Since TCC cannot sort it while generating
354 the code, we must do it after. All the relocation tables are also
355 modified to take into account the symbol table sorting */
356 static void sort_syms(TCCState *s1, Section *s)
358 int *old_to_new_syms;
359 ElfW(Sym) *new_syms;
360 int nb_syms, i;
361 ElfW(Sym) *p, *q;
362 ElfW_Rel *rel;
363 Section *sr;
364 int type, sym_index;
366 nb_syms = s->data_offset / sizeof(ElfW(Sym));
367 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
368 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
370 /* first pass for local symbols */
371 p = (ElfW(Sym) *)s->data;
372 q = new_syms;
373 for(i = 0; i < nb_syms; i++) {
374 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
375 old_to_new_syms[i] = q - new_syms;
376 *q++ = *p;
378 p++;
380 /* save the number of local symbols in section header */
381 s->sh_info = q - new_syms;
383 /* then second pass for non local symbols */
384 p = (ElfW(Sym) *)s->data;
385 for(i = 0; i < nb_syms; i++) {
386 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
387 old_to_new_syms[i] = q - new_syms;
388 *q++ = *p;
390 p++;
393 /* we copy the new symbols to the old */
394 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
395 tcc_free(new_syms);
397 /* now we modify all the relocations */
398 for(i = 1; i < s1->nb_sections; i++) {
399 sr = s1->sections[i];
400 if (sr->sh_type == SHT_RELX && sr->link == s) {
401 for_each_elem(sr, 0, rel, ElfW_Rel) {
402 sym_index = ELFW(R_SYM)(rel->r_info);
403 type = ELFW(R_TYPE)(rel->r_info);
404 sym_index = old_to_new_syms[sym_index];
405 rel->r_info = ELFW(R_INFO)(sym_index, type);
410 tcc_free(old_to_new_syms);
413 /* relocate common symbols in the .bss section */
414 ST_FUNC void relocate_common_syms(void)
416 ElfW(Sym) *sym;
417 unsigned long offset, align;
419 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
420 if (sym->st_shndx == SHN_COMMON) {
421 /* align symbol */
422 align = sym->st_value;
423 offset = bss_section->data_offset;
424 offset = (offset + align - 1) & -align;
425 sym->st_value = offset;
426 sym->st_shndx = bss_section->sh_num;
427 offset += sym->st_size;
428 bss_section->data_offset = offset;
433 /* relocate symbol table, resolve undefined symbols if do_resolve is
434 true and output error if undefined symbol. */
435 ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
437 ElfW(Sym) *sym, *esym;
438 int sym_bind, sh_num, sym_index;
439 const char *name;
441 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
442 sh_num = sym->st_shndx;
443 if (sh_num == SHN_UNDEF) {
444 name = (char *) strtab_section->data + sym->st_name;
445 /* Use ld.so to resolve symbol for us (for tcc -run) */
446 if (do_resolve) {
447 #if defined TCC_IS_NATIVE && !defined _WIN32
448 void *addr;
449 name = (char *) symtab_section->link->data + sym->st_name;
450 addr = resolve_sym(s1, name);
451 if (addr) {
452 sym->st_value = (addr_t)addr;
453 #ifdef DEBUG_RELOC
454 printf ("relocate_sym: %s -> 0x%lx\n", name, sym->st_value);
455 #endif
456 goto found;
458 #endif
459 } else if (s1->dynsym) {
460 /* if dynamic symbol exist, then use it */
461 sym_index = find_elf_sym(s1->dynsym, name);
462 if (sym_index) {
463 esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
464 sym->st_value = esym->st_value;
465 goto found;
468 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
469 it */
470 if (!strcmp(name, "_fp_hw"))
471 goto found;
472 /* only weak symbols are accepted to be undefined. Their
473 value is zero */
474 sym_bind = ELFW(ST_BIND)(sym->st_info);
475 if (sym_bind == STB_WEAK) {
476 sym->st_value = 0;
477 } else {
478 tcc_error_noabort("undefined symbol '%s'", name);
480 } else if (sh_num < SHN_LORESERVE) {
481 /* add section base */
482 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
484 found: ;
488 /* relocate a given section (CPU dependent) by applying the relocations
489 in the associated relocation section */
490 ST_FUNC void relocate_section(TCCState *s1, Section *s)
492 Section *sr = s->reloc;
493 ElfW_Rel *rel;
494 ElfW(Sym) *sym;
495 int type, sym_index;
496 unsigned char *ptr;
497 addr_t val, addr;
498 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
499 ElfW_Rel *qrel = (ElfW_Rel *) sr->data; /* ptr to next reloc entry reused */
500 int esym_index;
501 #endif
503 for_each_elem(sr, 0, rel, ElfW_Rel) {
504 ptr = s->data + rel->r_offset;
506 sym_index = ELFW(R_SYM)(rel->r_info);
507 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
508 val = sym->st_value;
509 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
510 val += rel->r_addend;
511 #endif
512 type = ELFW(R_TYPE)(rel->r_info);
513 addr = s->sh_addr + rel->r_offset;
515 /* CPU specific */
516 switch(type) {
517 #if defined(TCC_TARGET_I386)
518 case R_386_32:
519 if (s1->output_type == TCC_OUTPUT_DLL) {
520 esym_index = s1->symtab_to_dynsym[sym_index];
521 qrel->r_offset = rel->r_offset;
522 if (esym_index) {
523 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
524 qrel++;
525 break;
526 } else {
527 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
528 qrel++;
531 write32le(ptr, read32le(ptr) + val);
532 break;
533 case R_386_PC32:
534 if (s1->output_type == TCC_OUTPUT_DLL) {
535 /* DLL relocation */
536 esym_index = s1->symtab_to_dynsym[sym_index];
537 if (esym_index) {
538 qrel->r_offset = rel->r_offset;
539 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
540 qrel++;
541 break;
544 write32le(ptr, read32le(ptr) + val - addr);
545 break;
546 case R_386_PLT32:
547 write32le(ptr, read32le(ptr) + val - addr);
548 break;
549 case R_386_GLOB_DAT:
550 case R_386_JMP_SLOT:
551 write32le(ptr, val);
552 break;
553 case R_386_GOTPC:
554 write32le(ptr, read32le(ptr) + s1->got->sh_addr - addr);
555 break;
556 case R_386_GOTOFF:
557 write32le(ptr, read32le(ptr) + val - s1->got->sh_addr);
558 break;
559 case R_386_GOT32:
560 case R_386_GOT32X:
561 /* we load the got offset */
562 write32le(ptr, read32le(ptr) + s1->sym_attrs[sym_index].got_offset);
563 break;
564 case R_386_16:
565 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
566 output_file:
567 tcc_error("can only produce 16-bit binary files");
569 write16le(ptr, read16le(ptr) + val);
570 break;
571 case R_386_PC16:
572 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
573 goto output_file;
574 write16le(ptr, read16le(ptr) + val - addr);
575 break;
576 case R_386_RELATIVE:
577 /* do nothing */
578 break;
579 case R_386_COPY:
580 /* This reloction must copy initialized data from the library
581 to the program .bss segment. Currently made like for ARM
582 (to remove noise of defaukt case). Is this true?
584 break;
585 default:
586 fprintf(stderr,"FIXME: handle reloc type %d at %x [%p] to %x\n",
587 type, (unsigned)addr, ptr, (unsigned)val);
588 break;
589 #elif defined(TCC_TARGET_ARM)
590 case R_ARM_PC24:
591 case R_ARM_CALL:
592 case R_ARM_JUMP24:
593 case R_ARM_PLT32:
595 int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko;
596 x = (*(int *) ptr) & 0xffffff;
597 if (sym->st_shndx == SHN_UNDEF)
598 val = s1->plt->sh_addr;
599 #ifdef DEBUG_RELOC
600 printf ("reloc %d: x=0x%x val=0x%x ", type, x, val);
601 #endif
602 (*(int *)ptr) &= 0xff000000;
603 if (x & 0x800000)
604 x -= 0x1000000;
605 x <<= 2;
606 blx_avail = (TCC_ARM_VERSION >= 5);
607 is_thumb = val & 1;
608 is_bl = (*(unsigned *) ptr) >> 24 == 0xeb;
609 is_call = (type == R_ARM_CALL || (type == R_ARM_PC24 && is_bl));
610 x += val - addr;
611 #ifdef DEBUG_RELOC
612 printf (" newx=0x%x name=%s\n", x,
613 (char *) symtab_section->link->data + sym->st_name);
614 #endif
615 h = x & 2;
616 th_ko = (x & 3) && (!blx_avail || !is_call);
617 if (th_ko || x >= 0x2000000 || x < -0x2000000)
618 tcc_error("can't relocate value at %x,%d",addr, type);
619 x >>= 2;
620 x &= 0xffffff;
621 /* Only reached if blx is avail and it is a call */
622 if (is_thumb) {
623 x |= h << 24;
624 (*(int *)ptr) = 0xfa << 24; /* bl -> blx */
626 (*(int *) ptr) |= x;
628 break;
629 /* Since these relocations only concern Thumb-2 and blx instruction was
630 introduced before Thumb-2, we can assume blx is available and not
631 guard its use */
632 case R_ARM_THM_PC22:
633 case R_ARM_THM_JUMP24:
635 int x, hi, lo, s, j1, j2, i1, i2, imm10, imm11;
636 int to_thumb, is_call, to_plt, blx_bit = 1 << 12;
637 Section *plt;
639 /* weak reference */
640 if (sym->st_shndx == SHN_UNDEF &&
641 ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
642 break;
644 /* Get initial offset */
645 hi = (*(uint16_t *)ptr);
646 lo = (*(uint16_t *)(ptr+2));
647 s = (hi >> 10) & 1;
648 j1 = (lo >> 13) & 1;
649 j2 = (lo >> 11) & 1;
650 i1 = (j1 ^ s) ^ 1;
651 i2 = (j2 ^ s) ^ 1;
652 imm10 = hi & 0x3ff;
653 imm11 = lo & 0x7ff;
654 x = (s << 24) | (i1 << 23) | (i2 << 22) |
655 (imm10 << 12) | (imm11 << 1);
656 if (x & 0x01000000)
657 x -= 0x02000000;
659 /* Relocation infos */
660 to_thumb = val & 1;
661 plt = s1->plt;
662 to_plt = (val >= plt->sh_addr) &&
663 (val < plt->sh_addr + plt->data_offset);
664 is_call = (type == R_ARM_THM_PC22);
666 /* Compute final offset */
667 if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */
668 x -= 4;
669 x += val - addr;
670 if (!to_thumb && is_call) {
671 blx_bit = 0; /* bl -> blx */
672 x = (x + 3) & -4; /* Compute offset from aligned PC */
675 /* Check that relocation is possible
676 * offset must not be out of range
677 * if target is to be entered in arm mode:
678 - bit 1 must not set
679 - instruction must be a call (bl) or a jump to PLT */
680 if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
681 if (to_thumb || (val & 2) || (!is_call && !to_plt))
682 tcc_error("can't relocate value at %x,%d",addr, type);
684 /* Compute and store final offset */
685 s = (x >> 24) & 1;
686 i1 = (x >> 23) & 1;
687 i2 = (x >> 22) & 1;
688 j1 = s ^ (i1 ^ 1);
689 j2 = s ^ (i2 ^ 1);
690 imm10 = (x >> 12) & 0x3ff;
691 imm11 = (x >> 1) & 0x7ff;
692 (*(uint16_t *)ptr) = (uint16_t) ((hi & 0xf800) |
693 (s << 10) | imm10);
694 (*(uint16_t *)(ptr+2)) = (uint16_t) ((lo & 0xc000) |
695 (j1 << 13) | blx_bit | (j2 << 11) |
696 imm11);
698 break;
699 case R_ARM_MOVT_ABS:
700 case R_ARM_MOVW_ABS_NC:
702 int x, imm4, imm12;
703 if (type == R_ARM_MOVT_ABS)
704 val >>= 16;
705 imm12 = val & 0xfff;
706 imm4 = (val >> 12) & 0xf;
707 x = (imm4 << 16) | imm12;
708 if (type == R_ARM_THM_MOVT_ABS)
709 *(int *)ptr |= x;
710 else
711 *(int *)ptr += x;
713 break;
714 case R_ARM_THM_MOVT_ABS:
715 case R_ARM_THM_MOVW_ABS_NC:
717 int x, i, imm4, imm3, imm8;
718 if (type == R_ARM_THM_MOVT_ABS)
719 val >>= 16;
720 imm8 = val & 0xff;
721 imm3 = (val >> 8) & 0x7;
722 i = (val >> 11) & 1;
723 imm4 = (val >> 12) & 0xf;
724 x = (imm3 << 28) | (imm8 << 16) | (i << 10) | imm4;
725 if (type == R_ARM_THM_MOVT_ABS)
726 *(int *)ptr |= x;
727 else
728 *(int *)ptr += x;
730 break;
731 case R_ARM_PREL31:
733 int x;
734 x = (*(int *)ptr) & 0x7fffffff;
735 (*(int *)ptr) &= 0x80000000;
736 x = (x * 2) / 2;
737 x += val - addr;
738 if((x^(x>>1))&0x40000000)
739 tcc_error("can't relocate value at %x,%d",addr, type);
740 (*(int *)ptr) |= x & 0x7fffffff;
742 case R_ARM_ABS32:
743 *(int *)ptr += val;
744 break;
745 case R_ARM_REL32:
746 *(int *)ptr += val - addr;
747 break;
748 case R_ARM_GOTPC:
749 *(int *)ptr += s1->got->sh_addr - addr;
750 break;
751 case R_ARM_GOTOFF:
752 *(int *)ptr += val - s1->got->sh_addr;
753 break;
754 case R_ARM_GOT32:
755 /* we load the got offset */
756 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
757 break;
758 case R_ARM_COPY:
759 break;
760 case R_ARM_V4BX:
761 /* trade Thumb support for ARMv4 support */
762 if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
763 *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
764 break;
765 case R_ARM_GLOB_DAT:
766 case R_ARM_JUMP_SLOT:
767 *(addr_t *)ptr = val;
768 break;
769 case R_ARM_NONE:
770 /* Nothing to do. Normally used to indicate a dependency
771 on a certain symbol (like for exception handling under EABI). */
772 break;
773 default:
774 fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
775 type, (unsigned)addr, ptr, (unsigned)val);
776 break;
777 #elif defined(TCC_TARGET_ARM64)
778 case R_AARCH64_ABS64:
779 write64le(ptr, val);
780 break;
781 case R_AARCH64_ABS32:
782 write32le(ptr, val);
783 break;
784 case R_AARCH64_MOVW_UABS_G0_NC:
785 write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
786 (val & 0xffff) << 5));
787 break;
788 case R_AARCH64_MOVW_UABS_G1_NC:
789 write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
790 (val >> 16 & 0xffff) << 5));
791 break;
792 case R_AARCH64_MOVW_UABS_G2_NC:
793 write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
794 (val >> 32 & 0xffff) << 5));
795 break;
796 case R_AARCH64_MOVW_UABS_G3:
797 write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
798 (val >> 48 & 0xffff) << 5));
799 break;
800 case R_AARCH64_ADR_PREL_PG_HI21: {
801 uint64_t off = (val >> 12) - (addr >> 12);
802 if ((off + ((uint64_t)1 << 20)) >> 21)
803 tcc_error("R_AARCH64_ADR_PREL_PG_HI21 relocation failed");
804 write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
805 (off & 0x1ffffc) << 3 | (off & 3) << 29));
806 break;
808 case R_AARCH64_ADD_ABS_LO12_NC:
809 write32le(ptr, ((read32le(ptr) & 0xffc003ff) |
810 (val & 0xfff) << 10));
811 break;
812 case R_AARCH64_JUMP26:
813 case R_AARCH64_CALL26:
814 /* This check must match the one in build_got_entries, testing
815 if we really need a PLT slot. */
816 if (sym->st_shndx == SHN_UNDEF)
817 /* We've put the PLT slot offset into r_addend when generating
818 it, and that's what we must use as relocation value (adjusted
819 by section offset of course). */
820 val = s1->plt->sh_addr + rel->r_addend;
821 #ifdef DEBUG_RELOC
822 printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, val,
823 (char *) symtab_section->link->data + sym->st_name);
824 #endif
825 if (((val - addr) + ((uint64_t)1 << 27)) & ~(uint64_t)0xffffffc)
827 tcc_error("R_AARCH64_(JUMP|CALL)26 relocation failed (val=%lx, addr=%lx)", addr, val);
829 write32le(ptr, (0x14000000 |
830 (uint32_t)(type == R_AARCH64_CALL26) << 31 |
831 ((val - addr) >> 2 & 0x3ffffff)));
832 break;
833 case R_AARCH64_ADR_GOT_PAGE: {
834 uint64_t off =
835 (((s1->got->sh_addr +
836 s1->sym_attrs[sym_index].got_offset) >> 12) - (addr >> 12));
837 if ((off + ((uint64_t)1 << 20)) >> 21)
838 tcc_error("R_AARCH64_ADR_GOT_PAGE relocation failed");
839 write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
840 (off & 0x1ffffc) << 3 | (off & 3) << 29));
841 break;
843 case R_AARCH64_LD64_GOT_LO12_NC:
844 write32le(ptr,
845 ((read32le(ptr) & 0xfff803ff) |
846 ((s1->got->sh_addr +
847 s1->sym_attrs[sym_index].got_offset) & 0xff8) << 7));
848 break;
849 case R_AARCH64_COPY:
850 break;
851 case R_AARCH64_GLOB_DAT:
852 case R_AARCH64_JUMP_SLOT:
853 /* They don't need addend */
854 #ifdef DEBUG_RELOC
855 printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr,
856 val - rel->r_addend,
857 (char *) symtab_section->link->data + sym->st_name);
858 #endif
859 write64le(ptr, val - rel->r_addend);
860 break;
861 default:
862 fprintf(stderr, "FIXME: handle reloc type %x at %x [%p] to %x\n",
863 type, (unsigned)addr, ptr, (unsigned)val);
864 break;
865 #elif defined(TCC_TARGET_C67)
866 case R_C60_32:
867 *(int *)ptr += val;
868 break;
869 case R_C60LO16:
871 uint32_t orig;
873 /* put the low 16 bits of the absolute address
874 add to what is already there */
876 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
877 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
879 /* patch both at once - assumes always in pairs Low - High */
881 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
882 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
884 break;
885 case R_C60HI16:
886 break;
887 default:
888 fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
889 type, (unsigned)addr, ptr, (unsigned)val);
890 break;
891 #elif defined(TCC_TARGET_X86_64)
892 case R_X86_64_64:
893 if (s1->output_type == TCC_OUTPUT_DLL) {
894 esym_index = s1->symtab_to_dynsym[sym_index];
895 qrel->r_offset = rel->r_offset;
896 if (esym_index) {
897 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_64);
898 qrel->r_addend = rel->r_addend;
899 qrel++;
900 break;
901 } else {
902 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
903 qrel->r_addend = read64le(ptr) + val;
904 qrel++;
907 write64le(ptr, read64le(ptr) + val);
908 break;
909 case R_X86_64_32:
910 case R_X86_64_32S:
911 if (s1->output_type == TCC_OUTPUT_DLL) {
912 /* XXX: this logic may depend on TCC's codegen
913 now TCC uses R_X86_64_32 even for a 64bit pointer */
914 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
915 /* Use sign extension! */
916 qrel->r_addend = (int)read32le(ptr) + val;
917 qrel++;
919 write32le(ptr, read32le(ptr) + val);
920 break;
922 case R_X86_64_PC32:
923 if (s1->output_type == TCC_OUTPUT_DLL) {
924 /* DLL relocation */
925 esym_index = s1->symtab_to_dynsym[sym_index];
926 if (esym_index) {
927 qrel->r_offset = rel->r_offset;
928 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
929 /* Use sign extension! */
930 qrel->r_addend = (int)read32le(ptr) + rel->r_addend;
931 qrel++;
932 break;
935 goto plt32pc32;
937 case R_X86_64_PLT32:
938 /* We've put the PLT slot offset into r_addend when generating
939 it, and that's what we must use as relocation value (adjusted
940 by section offset of course). */
941 val = s1->plt->sh_addr + rel->r_addend;
942 /* fallthrough. */
944 plt32pc32:
946 long long diff;
947 diff = (long long)val - addr;
948 if (diff < -2147483648LL || diff > 2147483647LL) {
949 tcc_error("internal error: relocation failed");
951 write32le(ptr, read32le(ptr) + diff);
953 break;
954 case R_X86_64_GLOB_DAT:
955 case R_X86_64_JUMP_SLOT:
956 /* They don't need addend */
957 write64le(ptr, val - rel->r_addend);
958 break;
959 case R_X86_64_GOTPCREL:
960 case R_X86_64_GOTPCRELX:
961 case R_X86_64_REX_GOTPCRELX:
962 write32le(ptr, read32le(ptr) +
963 (s1->got->sh_addr - addr +
964 s1->sym_attrs[sym_index].got_offset - 4));
965 break;
966 case R_X86_64_GOTTPOFF:
967 write32le(ptr, read32le(ptr) + val - s1->got->sh_addr);
968 break;
969 case R_X86_64_GOT32:
970 /* we load the got offset */
971 write32le(ptr, read32le(ptr) + s1->sym_attrs[sym_index].got_offset);
972 break;
973 #else
974 #error unsupported processor
975 #endif
978 /* if the relocation is allocated, we change its symbol table */
979 if (sr->sh_flags & SHF_ALLOC)
980 sr->link = s1->dynsym;
983 /* relocate relocation table in 'sr' */
984 static void relocate_rel(TCCState *s1, Section *sr)
986 Section *s;
987 ElfW_Rel *rel;
989 s = s1->sections[sr->sh_info];
990 for_each_elem(sr, 0, rel, ElfW_Rel)
991 rel->r_offset += s->sh_addr;
994 /* count the number of dynamic relocations so that we can reserve
995 their space */
996 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
998 ElfW_Rel *rel;
999 int sym_index, esym_index, type, count;
1001 count = 0;
1002 for_each_elem(sr, 0, rel, ElfW_Rel) {
1003 sym_index = ELFW(R_SYM)(rel->r_info);
1004 type = ELFW(R_TYPE)(rel->r_info);
1005 switch(type) {
1006 #if defined(TCC_TARGET_I386)
1007 case R_386_32:
1008 #elif defined(TCC_TARGET_X86_64)
1009 case R_X86_64_32:
1010 case R_X86_64_32S:
1011 case R_X86_64_64:
1012 #endif
1013 count++;
1014 break;
1015 #if defined(TCC_TARGET_I386)
1016 case R_386_PC32:
1017 #elif defined(TCC_TARGET_X86_64)
1018 case R_X86_64_PC32:
1019 #endif
1020 esym_index = s1->symtab_to_dynsym[sym_index];
1021 if (esym_index)
1022 count++;
1023 break;
1024 default:
1025 break;
1028 if (count) {
1029 /* allocate the section */
1030 sr->sh_flags |= SHF_ALLOC;
1031 sr->sh_size = count * sizeof(ElfW_Rel);
1033 return count;
1036 static struct sym_attr *alloc_sym_attr(TCCState *s1, int index)
1038 int n;
1039 struct sym_attr *tab;
1041 if (index >= s1->nb_sym_attrs) {
1042 /* find immediately bigger power of 2 and reallocate array */
1043 n = 1;
1044 while (index >= n)
1045 n *= 2;
1046 tab = tcc_realloc(s1->sym_attrs, n * sizeof(*s1->sym_attrs));
1047 s1->sym_attrs = tab;
1048 memset(s1->sym_attrs + s1->nb_sym_attrs, 0,
1049 (n - s1->nb_sym_attrs) * sizeof(*s1->sym_attrs));
1050 s1->nb_sym_attrs = n;
1052 return &s1->sym_attrs[index];
1055 static void build_got(TCCState *s1)
1057 unsigned char *ptr;
1059 /* if no got, then create it */
1060 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
1061 s1->got->sh_entsize = 4;
1062 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
1063 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
1064 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
1065 #if PTR_SIZE == 4
1066 /* keep space for _DYNAMIC pointer, if present */
1067 write32le(ptr, 0);
1068 /* two dummy got entries */
1069 write32le(ptr + 4, 0);
1070 write32le(ptr + 8, 0);
1071 #else
1072 /* keep space for _DYNAMIC pointer, if present */
1073 write32le(ptr, 0);
1074 write32le(ptr + 4, 0);
1075 /* two dummy got entries */
1076 write32le(ptr + 8, 0);
1077 write32le(ptr + 12, 0);
1078 write32le(ptr + 16, 0);
1079 write32le(ptr + 20, 0);
1080 #endif
1083 /* put a got or plt entry corresponding to a symbol in symtab_section. 'size'
1084 and 'info' can be modifed if more precise info comes from the DLL.
1085 Returns offset of GOT or PLT slot. */
1086 static unsigned long put_got_entry(TCCState *s1,
1087 int reloc_type, unsigned long size, int info,
1088 int sym_index)
1090 int index, need_plt_entry;
1091 const char *name;
1092 ElfW(Sym) *sym;
1093 unsigned long offset;
1094 int *ptr;
1095 struct sym_attr *symattr;
1097 if (!s1->got)
1098 build_got(s1);
1100 need_plt_entry =
1101 #ifdef TCC_TARGET_X86_64
1102 (reloc_type == R_X86_64_JUMP_SLOT);
1103 #elif defined(TCC_TARGET_I386)
1104 (reloc_type == R_386_JMP_SLOT);
1105 #elif defined(TCC_TARGET_ARM)
1106 (reloc_type == R_ARM_JUMP_SLOT);
1107 #elif defined(TCC_TARGET_ARM64)
1108 (reloc_type == R_AARCH64_JUMP_SLOT);
1109 #else
1111 #endif
1113 if (need_plt_entry && !s1->plt) {
1114 /* add PLT */
1115 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1116 SHF_ALLOC | SHF_EXECINSTR);
1117 s1->plt->sh_entsize = 4;
1120 /* If a got/plt entry already exists for that symbol, no need to add one */
1121 if (sym_index < s1->nb_sym_attrs) {
1122 if (need_plt_entry && s1->sym_attrs[sym_index].plt_offset)
1123 return s1->sym_attrs[sym_index].plt_offset;
1124 else if (!need_plt_entry && s1->sym_attrs[sym_index].got_offset)
1125 return s1->sym_attrs[sym_index].got_offset;
1128 symattr = alloc_sym_attr(s1, sym_index);
1130 /* Only store the GOT offset if it's not generated for the PLT entry. */
1131 if (!need_plt_entry)
1132 symattr->got_offset = s1->got->data_offset;
1134 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1135 name = (char *) symtab_section->link->data + sym->st_name;
1136 offset = sym->st_value;
1137 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1138 if (need_plt_entry) {
1139 Section *plt;
1140 uint8_t *p;
1141 int modrm;
1142 unsigned long relofs;
1144 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1145 modrm = 0x25;
1146 #else
1147 /* if we build a DLL, we add a %ebx offset */
1148 if (s1->output_type == TCC_OUTPUT_DLL)
1149 modrm = 0xa3;
1150 else
1151 modrm = 0x25;
1152 #endif
1154 /* add a PLT entry */
1155 plt = s1->plt;
1156 if (plt->data_offset == 0) {
1157 /* first plt entry */
1158 p = section_ptr_add(plt, 16);
1159 p[0] = 0xff; /* pushl got + PTR_SIZE */
1160 p[1] = modrm + 0x10;
1161 write32le(p + 2, PTR_SIZE);
1162 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1163 p[7] = modrm;
1164 write32le(p + 8, PTR_SIZE * 2);
1167 /* The PLT slot refers to the relocation entry it needs
1168 via offset. The reloc entry is created below, so its
1169 offset is the current data_offset. */
1170 relofs = s1->got->reloc ? s1->got->reloc->data_offset : 0;
1171 symattr->plt_offset = plt->data_offset;
1172 p = section_ptr_add(plt, 16);
1173 p[0] = 0xff; /* jmp *(got + x) */
1174 p[1] = modrm;
1175 write32le(p + 2, s1->got->data_offset);
1176 p[6] = 0x68; /* push $xxx */
1177 #ifdef TCC_TARGET_X86_64
1178 /* On x86-64, the relocation is referred to by _index_. */
1179 write32le(p + 7, relofs / sizeof (ElfW_Rel));
1180 #else
1181 write32le(p + 7, relofs);
1182 #endif
1183 p[11] = 0xe9; /* jmp plt_start */
1184 write32le(p + 12, -(plt->data_offset));
1186 /* If this was an UNDEF symbol set the offset in the
1187 dynsymtab to the PLT slot, so that PC32 relocs to it
1188 can be resolved. */
1189 if (sym->st_shndx == SHN_UNDEF)
1190 offset = plt->data_offset - 16;
1192 #elif defined(TCC_TARGET_ARM)
1193 if (need_plt_entry) {
1194 Section *plt;
1195 uint8_t *p;
1197 /* if we build a DLL, we add a %ebx offset */
1198 if (s1->output_type == TCC_OUTPUT_DLL)
1199 tcc_error("DLLs unimplemented!");
1201 /* add a PLT entry */
1202 plt = s1->plt;
1203 if (plt->data_offset == 0) {
1204 /* first plt entry */
1205 p = section_ptr_add(plt, 16);
1206 write32le(p, 0xe52de004); /* push {lr} */
1207 write32le(p+4, 0xe59fe010); /* ldr lr, [pc, #16] */
1208 write32le(p+8, 0xe08fe00e); /* add lr, pc, lr */
1209 write32le(p+12, 0xe5bef008); /* ldr pc, [lr, #8]! */
1212 symattr->plt_offset = plt->data_offset;
1213 if (symattr->plt_thumb_stub) {
1214 p = section_ptr_add(plt, 20);
1215 write32le(p, 0x4778); /* bx pc */
1216 write32le(p+2, 0x46c0); /* nop */
1217 p += 4;
1218 } else
1219 p = section_ptr_add(plt, 16);
1220 write32le(p, 0xe59fc004); /* ldr ip, [pc, #4] ; GOT entry offset */
1221 write32le(p+4, 0xe08fc00c); /* add ip, pc, ip ; addr of GOT entry */
1222 write32le(p+8, 0xe59cf000); /* ldr pc, [ip] ; jump to GOT entry */
1223 write32le(p+12, s1->got->data_offset); /* GOT entry off once patched */
1225 /* the symbol is modified so that it will be relocated to
1226 the PLT */
1227 if (sym->st_shndx == SHN_UNDEF)
1228 offset = plt->data_offset - 16;
1230 #elif defined(TCC_TARGET_ARM64)
1231 if (need_plt_entry) {
1232 Section *plt;
1233 uint8_t *p;
1235 if (s1->output_type == TCC_OUTPUT_DLL)
1236 tcc_error("DLLs unimplemented!");
1238 plt = s1->plt;
1239 if (plt->data_offset == 0)
1240 section_ptr_add(plt, 32);
1241 symattr->plt_offset = plt->data_offset;
1242 p = section_ptr_add(plt, 16);
1243 write32le(p, s1->got->data_offset);
1244 write32le(p + 4, (uint64_t)s1->got->data_offset >> 32);
1246 if (sym->st_shndx == SHN_UNDEF)
1247 offset = plt->data_offset - 16;
1249 #elif defined(TCC_TARGET_C67)
1250 if (s1->dynsym) {
1251 tcc_error("C67 got not implemented");
1253 #else
1254 #error unsupported CPU
1255 #endif
1256 if (s1->dynsym) {
1257 /* XXX This might generate multiple syms for name. */
1258 index = put_elf_sym(s1->dynsym, offset,
1259 size, info, 0, sym->st_shndx, name);
1260 /* Create the relocation (it's against the GOT for PLT
1261 and GOT relocs). */
1262 put_elf_reloc(s1->dynsym, s1->got,
1263 s1->got->data_offset,
1264 reloc_type, index);
1265 } else {
1266 /* Without .dynsym (i.e. static link or memory output) we
1267 still need relocs against the generated got, so as to fill
1268 the entries with the symbol values (determined later). */
1269 put_elf_reloc(symtab_section, s1->got,
1270 s1->got->data_offset,
1271 reloc_type, sym_index);
1273 /* And now create the GOT slot itself. */
1274 ptr = section_ptr_add(s1->got, PTR_SIZE);
1275 *ptr = 0;
1276 if (need_plt_entry)
1277 return symattr->plt_offset;
1278 else
1279 return symattr->got_offset;
1282 /* build GOT and PLT entries */
1283 ST_FUNC void build_got_entries(TCCState *s1)
1285 Section *s;
1286 ElfW_Rel *rel;
1287 ElfW(Sym) *sym;
1288 int i, type, reloc_type, sym_index;
1290 for(i = 1; i < s1->nb_sections; i++) {
1291 s = s1->sections[i];
1292 if (s->sh_type != SHT_RELX)
1293 continue;
1294 /* no need to handle got relocations */
1295 if (s->link != symtab_section)
1296 continue;
1297 for_each_elem(s, 0, rel, ElfW_Rel) {
1298 type = ELFW(R_TYPE)(rel->r_info);
1299 switch(type) {
1300 #if defined(TCC_TARGET_I386)
1301 case R_386_GOT32:
1302 case R_386_GOT32X:
1303 case R_386_GOTOFF:
1304 case R_386_GOTPC:
1305 case R_386_PLT32:
1306 if (!s1->got)
1307 build_got(s1);
1308 if (type == R_386_GOT32 || type == R_386_GOT32X ||
1309 type == R_386_PLT32) {
1310 sym_index = ELFW(R_SYM)(rel->r_info);
1311 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1312 /* look at the symbol got offset. If none, then add one */
1313 if (type == R_386_GOT32 || type == R_386_GOT32X)
1314 reloc_type = R_386_GLOB_DAT;
1315 else
1316 reloc_type = R_386_JMP_SLOT;
1317 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1318 sym_index);
1320 break;
1321 #elif defined(TCC_TARGET_ARM)
1322 case R_ARM_PC24:
1323 case R_ARM_CALL:
1324 case R_ARM_JUMP24:
1325 case R_ARM_GOT32:
1326 case R_ARM_GOTOFF:
1327 case R_ARM_GOTPC:
1328 case R_ARM_PLT32:
1329 if (!s1->got)
1330 build_got(s1);
1331 sym_index = ELFW(R_SYM)(rel->r_info);
1332 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1333 if (type != R_ARM_GOTOFF && type != R_ARM_GOTPC
1334 && sym->st_shndx == SHN_UNDEF) {
1335 unsigned long ofs;
1336 /* look at the symbol got offset. If none, then add one */
1337 if (type == R_ARM_GOT32)
1338 reloc_type = R_ARM_GLOB_DAT;
1339 else
1340 reloc_type = R_ARM_JUMP_SLOT;
1341 ofs = put_got_entry(s1, reloc_type, sym->st_size,
1342 sym->st_info, sym_index);
1343 #ifdef DEBUG_RELOC
1344 printf ("maybegot: %s, %d, %d --> ofs=0x%x\n",
1345 (char *) symtab_section->link->data + sym->st_name,
1346 type, sym->st_shndx, ofs);
1347 #endif
1348 if (type != R_ARM_GOT32) {
1349 addr_t *ptr = (addr_t*)(s1->sections[s->sh_info]->data
1350 + rel->r_offset);
1351 /* x must be signed! */
1352 int x = *ptr & 0xffffff;
1353 x = (x << 8) >> 8;
1354 x <<= 2;
1355 x += ofs;
1356 x >>= 2;
1357 #ifdef DEBUG_RELOC
1358 printf ("insn=0x%x --> 0x%x (x==0x%x)\n", *ptr,
1359 (*ptr & 0xff000000) | x, x);
1360 #endif
1361 *ptr = (*ptr & 0xff000000) | x;
1364 break;
1365 case R_ARM_THM_JUMP24:
1366 sym_index = ELFW(R_SYM)(rel->r_info);
1367 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1368 /* We are relocating a jump from thumb code to arm code */
1369 if (sym->st_shndx != SHN_UNDEF && !(sym->st_value & 1)) {
1370 int index;
1371 uint8_t *p;
1372 char *name, buf[1024];
1373 Section *text_section;
1375 name = (char *) symtab_section->link->data + sym->st_name;
1376 text_section = s1->sections[sym->st_shndx];
1377 /* Modify reloc to target a thumb stub to switch to ARM */
1378 snprintf(buf, sizeof(buf), "%s_from_thumb", name);
1379 index = put_elf_sym(symtab_section,
1380 text_section->data_offset + 1,
1381 sym->st_size, sym->st_info, 0,
1382 sym->st_shndx, buf);
1383 rel->r_info = ELFW(R_INFO)(index, type);
1384 /* Create a thumb stub fonction to switch to ARM mode */
1385 put_elf_reloc(symtab_section, text_section,
1386 text_section->data_offset + 4, R_ARM_JUMP24,
1387 sym_index);
1388 p = section_ptr_add(text_section, 8);
1389 write32le(p, 0x4778); /* bx pc */
1390 write32le(p+2, 0x46c0); /* nop */
1391 write32le(p+4, 0xeafffffe); /* b $sym */
1393 #elif defined(TCC_TARGET_ARM64)
1394 //xx Other cases may be required here:
1395 case R_AARCH64_ADR_GOT_PAGE:
1396 case R_AARCH64_LD64_GOT_LO12_NC:
1397 if (!s1->got)
1398 build_got(s1);
1399 sym_index = ELFW(R_SYM)(rel->r_info);
1400 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1401 reloc_type = R_AARCH64_GLOB_DAT;
1402 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1403 sym_index);
1404 break;
1406 case R_AARCH64_JUMP26:
1407 case R_AARCH64_CALL26:
1408 if (!s1->got)
1409 build_got(s1);
1410 sym_index = ELFW(R_SYM)(rel->r_info);
1411 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1412 if (sym->st_shndx == SHN_UNDEF) {
1413 unsigned long ofs;
1414 reloc_type = R_AARCH64_JUMP_SLOT;
1415 ofs = put_got_entry(s1, reloc_type, sym->st_size,
1416 sym->st_info, sym_index);
1417 /* We store the place of the generated PLT slot
1418 in our addend. */
1419 rel->r_addend += ofs;
1421 break;
1422 #elif defined(TCC_TARGET_C67)
1423 case R_C60_GOT32:
1424 case R_C60_GOTOFF:
1425 case R_C60_GOTPC:
1426 case R_C60_PLT32:
1427 if (!s1->got)
1428 build_got(s1);
1429 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1430 sym_index = ELFW(R_SYM)(rel->r_info);
1431 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1432 /* look at the symbol got offset. If none, then add one */
1433 if (type == R_C60_GOT32)
1434 reloc_type = R_C60_GLOB_DAT;
1435 else
1436 reloc_type = R_C60_JMP_SLOT;
1437 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1438 sym_index);
1440 break;
1441 #elif defined(TCC_TARGET_X86_64)
1442 case R_X86_64_GOT32:
1443 case R_X86_64_GOTTPOFF:
1444 case R_X86_64_GOTPCREL:
1445 case R_X86_64_GOTPCRELX:
1446 case R_X86_64_REX_GOTPCRELX:
1447 case R_X86_64_PLT32:
1448 sym_index = ELFW(R_SYM)(rel->r_info);
1449 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1450 if (type == R_X86_64_PLT32 &&
1451 ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT)
1453 rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32);
1454 break;
1457 if (!s1->got) {
1458 build_got(s1);
1459 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1461 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1462 type == R_X86_64_GOTPCRELX ||
1463 type == R_X86_64_REX_GOTPCRELX ||
1464 type == R_X86_64_PLT32) {
1465 unsigned long ofs;
1466 /* look at the symbol got offset. If none, then add one */
1467 if (type == R_X86_64_PLT32)
1468 reloc_type = R_X86_64_JUMP_SLOT;
1469 else
1470 reloc_type = R_X86_64_GLOB_DAT;
1471 ofs = put_got_entry(s1, reloc_type, sym->st_size,
1472 sym->st_info, sym_index);
1473 if (type == R_X86_64_PLT32)
1474 /* We store the place of the generated PLT slot
1475 in our addend. */
1476 rel->r_addend += ofs;
1478 break;
1479 #else
1480 #error unsupported CPU
1481 #endif
1482 default:
1483 break;
1489 ST_FUNC Section *new_symtab(TCCState *s1,
1490 const char *symtab_name, int sh_type, int sh_flags,
1491 const char *strtab_name,
1492 const char *hash_name, int hash_sh_flags)
1494 Section *symtab, *strtab, *hash;
1495 int *ptr, nb_buckets;
1497 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1498 symtab->sh_entsize = sizeof(ElfW(Sym));
1499 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1500 put_elf_str(strtab, "");
1501 symtab->link = strtab;
1502 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1504 nb_buckets = 1;
1506 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1507 hash->sh_entsize = sizeof(int);
1508 symtab->hash = hash;
1509 hash->link = symtab;
1511 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1512 ptr[0] = nb_buckets;
1513 ptr[1] = 1;
1514 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1515 return symtab;
1518 /* put dynamic tag */
1519 static void put_dt(Section *dynamic, int dt, addr_t val)
1521 ElfW(Dyn) *dyn;
1522 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1523 dyn->d_tag = dt;
1524 dyn->d_un.d_val = val;
1527 static void add_init_array_defines(TCCState *s1, const char *section_name)
1529 Section *s;
1530 long end_offset;
1531 char sym_start[1024];
1532 char sym_end[1024];
1534 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1535 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1537 s = find_section(s1, section_name);
1538 if (!s) {
1539 end_offset = 0;
1540 s = data_section;
1541 } else {
1542 end_offset = s->data_offset;
1545 add_elf_sym(symtab_section,
1546 0, 0,
1547 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1548 s->sh_num, sym_start);
1549 add_elf_sym(symtab_section,
1550 end_offset, 0,
1551 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1552 s->sh_num, sym_end);
1555 static int tcc_add_support(TCCState *s1, const char *filename)
1557 char buf[1024];
1558 snprintf(buf, sizeof(buf), "%s/"TCC_ARCH_DIR"%s", s1->tcc_lib_path, filename);
1559 return tcc_add_file(s1, buf);
1562 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1564 #ifdef CONFIG_TCC_BCHECK
1565 addr_t *ptr;
1566 int sym_index;
1568 if (0 == s1->do_bounds_check)
1569 return;
1570 /* XXX: add an object file to do that */
1571 ptr = section_ptr_add(bounds_section, sizeof(*ptr));
1572 *ptr = 0;
1573 add_elf_sym(symtab_section, 0, 0,
1574 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1575 bounds_section->sh_num, "__bounds_start");
1576 /* pull bcheck.o from libtcc1.a */
1577 sym_index = add_elf_sym(symtab_section, 0, 0,
1578 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1579 SHN_UNDEF, "__bound_init");
1580 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1581 /* add 'call __bound_init()' in .init section */
1582 Section *init_section = find_section(s1, ".init");
1583 unsigned char *pinit = section_ptr_add(init_section, 5);
1584 pinit[0] = 0xe8;
1585 write32le(pinit + 1, -4);
1586 put_elf_reloc(symtab_section, init_section,
1587 init_section->data_offset - 4, R_386_PC32, sym_index);
1588 /* R_386_PC32 = R_X86_64_PC32 = 2 */
1590 #endif
1593 /* add tcc runtime libraries */
1594 ST_FUNC void tcc_add_runtime(TCCState *s1)
1596 tcc_add_bcheck(s1);
1597 tcc_add_pragma_libs(s1);
1598 /* add libc */
1599 if (!s1->nostdlib) {
1600 tcc_add_library(s1, "c");
1601 #ifdef CONFIG_USE_LIBGCC
1602 if (!s1->static_link) {
1603 tcc_add_file(s1, TCC_LIBGCC);
1605 #endif
1606 tcc_add_support(s1, "libtcc1.a");
1607 /* add crt end if not memory output */
1608 if (s1->output_type != TCC_OUTPUT_MEMORY)
1609 tcc_add_crt(s1, "crtn.o");
1613 /* add various standard linker symbols (must be done after the
1614 sections are filled (for example after allocating common
1615 symbols)) */
1616 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1618 char buf[1024];
1619 int i;
1620 Section *s;
1622 add_elf_sym(symtab_section,
1623 text_section->data_offset, 0,
1624 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1625 text_section->sh_num, "_etext");
1626 add_elf_sym(symtab_section,
1627 data_section->data_offset, 0,
1628 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1629 data_section->sh_num, "_edata");
1630 add_elf_sym(symtab_section,
1631 bss_section->data_offset, 0,
1632 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1633 bss_section->sh_num, "_end");
1634 /* horrible new standard ldscript defines */
1635 add_init_array_defines(s1, ".preinit_array");
1636 add_init_array_defines(s1, ".init_array");
1637 add_init_array_defines(s1, ".fini_array");
1639 /* add start and stop symbols for sections whose name can be
1640 expressed in C */
1641 for(i = 1; i < s1->nb_sections; i++) {
1642 s = s1->sections[i];
1643 if (s->sh_type == SHT_PROGBITS &&
1644 (s->sh_flags & SHF_ALLOC)) {
1645 const char *p;
1646 int ch;
1648 /* check if section name can be expressed in C */
1649 p = s->name;
1650 for(;;) {
1651 ch = *p;
1652 if (!ch)
1653 break;
1654 if (!isid(ch) && !isnum(ch))
1655 goto next_sec;
1656 p++;
1658 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1659 add_elf_sym(symtab_section,
1660 0, 0,
1661 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1662 s->sh_num, buf);
1663 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1664 add_elf_sym(symtab_section,
1665 s->data_offset, 0,
1666 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1667 s->sh_num, buf);
1669 next_sec: ;
1673 static void tcc_output_binary(TCCState *s1, FILE *f,
1674 const int *sec_order)
1676 Section *s;
1677 int i, offset, size;
1679 offset = 0;
1680 for(i=1;i<s1->nb_sections;i++) {
1681 s = s1->sections[sec_order[i]];
1682 if (s->sh_type != SHT_NOBITS &&
1683 (s->sh_flags & SHF_ALLOC)) {
1684 while (offset < s->sh_offset) {
1685 fputc(0, f);
1686 offset++;
1688 size = s->sh_size;
1689 fwrite(s->data, 1, size, f);
1690 offset += size;
1695 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1696 #define HAVE_PHDR 1
1697 #define EXTRA_RELITEMS 14
1699 /* move the relocation value from .dynsym to .got */
1700 static void patch_dynsym_undef(TCCState *s1, Section *s)
1702 uint32_t *gotd = (void *)s1->got->data;
1703 ElfW(Sym) *sym;
1705 gotd += 3; /* dummy entries in .got */
1706 /* relocate symbols in .dynsym */
1707 for_each_elem(s, 1, sym, ElfW(Sym)) {
1708 if (sym->st_shndx == SHN_UNDEF) {
1709 *gotd++ = sym->st_value + 6; /* XXX 6 is magic ? */
1710 sym->st_value = 0;
1714 #else
1715 #define HAVE_PHDR 1
1716 #define EXTRA_RELITEMS 9
1718 /* zero plt offsets of weak symbols in .dynsym */
1719 static void patch_dynsym_undef(TCCState *s1, Section *s)
1721 ElfW(Sym) *sym;
1723 for_each_elem(s, 1, sym, ElfW(Sym))
1724 if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
1725 sym->st_value = 0;
1727 #endif
1729 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1731 int sym_index = ELFW(R_SYM) (rel->r_info);
1732 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1733 unsigned long offset;
1735 if (sym_index >= s1->nb_sym_attrs)
1736 return;
1737 offset = s1->sym_attrs[sym_index].got_offset;
1738 section_reserve(s1->got, offset + PTR_SIZE);
1739 #ifdef TCC_TARGET_X86_64
1740 /* only works for x86-64 */
1741 write32le(s1->got->data + offset + 4, sym->st_value >> 32);
1742 #endif
1743 write32le(s1->got->data + offset, sym->st_value & 0xffffffff);
1746 /* Perform relocation to GOT or PLT entries */
1747 ST_FUNC void fill_got(TCCState *s1)
1749 Section *s;
1750 ElfW_Rel *rel;
1751 int i;
1753 for(i = 1; i < s1->nb_sections; i++) {
1754 s = s1->sections[i];
1755 if (s->sh_type != SHT_RELX)
1756 continue;
1757 /* no need to handle got relocations */
1758 if (s->link != symtab_section)
1759 continue;
1760 for_each_elem(s, 0, rel, ElfW_Rel) {
1761 switch (ELFW(R_TYPE) (rel->r_info)) {
1762 case R_X86_64_GOT32:
1763 case R_X86_64_GOTPCREL:
1764 case R_X86_64_GOTPCRELX:
1765 case R_X86_64_REX_GOTPCRELX:
1766 case R_X86_64_PLT32:
1767 fill_got_entry(s1, rel);
1768 break;
1774 /* Bind symbols of executable: resolve undefined symbols from exported symbols
1775 in shared libraries and export non local defined symbols to shared libraries
1776 if -rdynamic switch was given on command line */
1777 static void bind_exe_dynsyms(TCCState *s1)
1779 const char *name;
1780 int sym_index, index;
1781 ElfW(Sym) *sym, *esym;
1782 int type;
1784 /* Resolve undefined symbols from dynamic symbols. When there is a match:
1785 - if STT_FUNC or STT_GNU_IFUNC symbol -> add it in PLT
1786 - if STT_OBJECT symbol -> add it in .bss section with suitable reloc */
1787 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
1788 if (sym->st_shndx == SHN_UNDEF) {
1789 name = (char *) symtab_section->link->data + sym->st_name;
1790 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1791 if (sym_index) {
1792 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1793 type = ELFW(ST_TYPE)(esym->st_info);
1794 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1795 /* Indirect functions shall have STT_FUNC type in executable
1796 * dynsym section. Indeed, a dlsym call following a lazy
1797 * resolution would pick the symbol value from the
1798 * executable dynsym entry which would contain the address
1799 * of the function wanted by the caller of dlsym instead of
1800 * the address of the function that would return that
1801 * address */
1802 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1803 ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC),
1804 sym - (ElfW(Sym) *)symtab_section->data);
1805 } else if (type == STT_OBJECT) {
1806 unsigned long offset;
1807 ElfW(Sym) *dynsym;
1808 offset = bss_section->data_offset;
1809 /* XXX: which alignment ? */
1810 offset = (offset + 16 - 1) & -16;
1811 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1812 esym->st_info, 0, bss_section->sh_num,
1813 name);
1814 /* Ensure R_COPY works for weak symbol aliases */
1815 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1816 for_each_elem(s1->dynsymtab_section, 1, dynsym, ElfW(Sym)) {
1817 if ((dynsym->st_value == esym->st_value)
1818 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1819 char *dynname = (char *) s1->dynsymtab_section->link->data
1820 + dynsym->st_name;
1821 put_elf_sym(s1->dynsym, offset, dynsym->st_size,
1822 dynsym->st_info, 0,
1823 bss_section->sh_num, dynname);
1824 break;
1828 put_elf_reloc(s1->dynsym, bss_section,
1829 offset, R_COPY, index);
1830 offset += esym->st_size;
1831 bss_section->data_offset = offset;
1833 } else {
1834 /* STB_WEAK undefined symbols are accepted */
1835 /* XXX: _fp_hw seems to be part of the ABI, so we ignore it */
1836 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1837 !strcmp(name, "_fp_hw")) {
1838 } else {
1839 tcc_error_noabort("undefined symbol '%s'", name);
1842 } else if (s1->rdynamic && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1843 /* if -rdynamic option, then export all non local symbols */
1844 name = (char *) symtab_section->link->data + sym->st_name;
1845 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, sym->st_info,
1846 0, sym->st_shndx, name);
1851 /* Bind symbols of libraries: export non local symbols of executable that
1852 resolve undefined symbols of shared libraries */
1853 static void bind_libs_dynsyms(TCCState *s1)
1855 const char *name;
1856 int sym_index;
1857 ElfW(Sym) *sym, *esym;
1859 /* now look at unresolved dynamic symbols and export
1860 corresponding symbol */
1861 for_each_elem(s1->dynsymtab_section, 1, esym, ElfW(Sym)) {
1862 name = (char *) s1->dynsymtab_section->link->data + esym->st_name;
1863 sym_index = find_elf_sym(symtab_section, name);
1864 if (sym_index) {
1865 /* XXX: avoid adding a symbol if already present because of
1866 -rdynamic ? */
1867 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1868 if (sym->st_shndx != SHN_UNDEF)
1869 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1870 sym->st_info, 0, sym->st_shndx, name);
1871 } else if (esym->st_shndx == SHN_UNDEF) {
1872 /* weak symbols can stay undefined */
1873 if (ELFW(ST_BIND)(esym->st_info) != STB_WEAK)
1874 tcc_warning("undefined dynamic symbol '%s'", name);
1879 /* Export all non local symbols (for shared libraries) */
1880 static void export_global_syms(TCCState *s1)
1882 int nb_syms, dynindex, index;
1883 const char *name;
1884 ElfW(Sym) *sym;
1886 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1887 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1888 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
1889 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1890 name = (char *) symtab_section->link->data + sym->st_name;
1891 dynindex = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1892 sym->st_info, 0, sym->st_shndx, name);
1893 index = sym - (ElfW(Sym) *) symtab_section->data;
1894 s1->symtab_to_dynsym[index] = dynindex;
1899 /* relocate the PLT: compute addresses and offsets in the PLT now that final
1900 address for PLT and GOT are known (see fill_program_header) */
1901 ST_FUNC void relocate_plt(TCCState *s1)
1903 uint8_t *p, *p_end;
1905 if (!s1->plt)
1906 return;
1908 p = s1->plt->data;
1909 p_end = p + s1->plt->data_offset;
1910 if (p < p_end) {
1911 #if defined(TCC_TARGET_I386)
1912 write32le(p + 2, read32le(p + 2) + s1->got->sh_addr);
1913 write32le(p + 8, read32le(p + 8) + s1->got->sh_addr);
1914 p += 16;
1915 while (p < p_end) {
1916 write32le(p + 2, read32le(p + 2) + s1->got->sh_addr);
1917 p += 16;
1919 #elif defined(TCC_TARGET_X86_64)
1920 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1921 write32le(p + 2, read32le(p + 2) + x);
1922 write32le(p + 8, read32le(p + 8) + x - 6);
1923 p += 16;
1924 while (p < p_end) {
1925 write32le(p + 2, read32le(p + 2) + x + s1->plt->data - p);
1926 p += 16;
1928 #elif defined(TCC_TARGET_ARM)
1929 int x;
1930 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1931 p += 16;
1932 while (p < p_end) {
1933 if (read32le(p) == 0x46c04778) /* PLT Thumb stub present */
1934 p += 4;
1935 write32le(p + 12, x + read32le(p + 12) + s1->plt->data - p);
1936 p += 16;
1938 #elif defined(TCC_TARGET_ARM64)
1939 uint64_t plt = s1->plt->sh_addr;
1940 uint64_t got = s1->got->sh_addr;
1941 uint64_t off = (got >> 12) - (plt >> 12);
1942 if ((off + ((uint32_t)1 << 20)) >> 21)
1943 tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", off, got, plt);
1944 write32le(p, 0xa9bf7bf0); // stp x16,x30,[sp,#-16]!
1945 write32le(p + 4, (0x90000010 | // adrp x16,...
1946 (off & 0x1ffffc) << 3 | (off & 3) << 29));
1947 write32le(p + 8, (0xf9400211 | // ldr x17,[x16,#...]
1948 (got & 0xff8) << 7));
1949 write32le(p + 12, (0x91000210 | // add x16,x16,#...
1950 (got & 0xfff) << 10));
1951 write32le(p + 16, 0xd61f0220); // br x17
1952 write32le(p + 20, 0xd503201f); // nop
1953 write32le(p + 24, 0xd503201f); // nop
1954 write32le(p + 28, 0xd503201f); // nop
1955 p += 32;
1956 while (p < p_end) {
1957 uint64_t pc = plt + (p - s1->plt->data);
1958 uint64_t addr = got + read64le(p);
1959 uint64_t off = (addr >> 12) - (pc >> 12);
1960 if ((off + ((uint32_t)1 << 20)) >> 21)
1961 tcc_error("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", off, addr, pc);
1962 write32le(p, (0x90000010 | // adrp x16,...
1963 (off & 0x1ffffc) << 3 | (off & 3) << 29));
1964 write32le(p + 4, (0xf9400211 | // ldr x17,[x16,#...]
1965 (addr & 0xff8) << 7));
1966 write32le(p + 8, (0x91000210 | // add x16,x16,#...
1967 (addr & 0xfff) << 10));
1968 write32le(p + 12, 0xd61f0220); // br x17
1969 p += 16;
1971 #elif defined(TCC_TARGET_C67)
1972 /* XXX: TODO */
1973 #else
1974 #error unsupported CPU
1975 #endif
1979 /* Allocate strings for section names and decide if an unallocated section
1980 should be output.
1982 NOTE: the strsec section comes last, so its size is also correct ! */
1983 static void alloc_sec_names(TCCState *s1, int file_type, Section *strsec)
1985 int i;
1986 Section *s;
1988 /* Allocate strings for section names */
1989 for(i = 1; i < s1->nb_sections; i++) {
1990 s = s1->sections[i];
1991 s->sh_name = put_elf_str(strsec, s->name);
1992 /* when generating a DLL, we include relocations but we may
1993 patch them */
1994 if (file_type == TCC_OUTPUT_DLL &&
1995 s->sh_type == SHT_RELX &&
1996 !(s->sh_flags & SHF_ALLOC)) {
1997 /* gr: avoid bogus relocs for empty (debug) sections */
1998 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1999 prepare_dynamic_rel(s1, s);
2000 else if (s1->do_debug)
2001 s->sh_size = s->data_offset;
2002 } else if (s1->do_debug ||
2003 file_type == TCC_OUTPUT_OBJ ||
2004 (s->sh_flags & SHF_ALLOC) ||
2005 i == (s1->nb_sections - 1)) {
2006 /* we output all sections if debug or object file */
2007 s->sh_size = s->data_offset;
2012 /* Info to be copied in dynamic section */
2013 struct dyn_inf {
2014 Section *dynamic;
2015 Section *dynstr;
2016 unsigned long dyn_rel_off;
2017 addr_t rel_addr;
2018 addr_t rel_size;
2019 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2020 addr_t bss_addr;
2021 addr_t bss_size;
2022 #endif
2025 /* Assign sections to segments and decide how are sections laid out when loaded
2026 in memory. This function also fills corresponding program headers. */
2027 static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
2028 Section *interp, Section* strsec,
2029 struct dyn_inf *dyninf, int *sec_order)
2031 int i, j, k, file_type, sh_order_index, file_offset;
2032 unsigned long s_align;
2033 long long tmp;
2034 addr_t addr;
2035 ElfW(Phdr) *ph;
2036 Section *s;
2038 file_type = s1->output_type;
2039 sh_order_index = 1;
2040 file_offset = 0;
2041 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
2042 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2043 s_align = ELF_PAGE_SIZE;
2044 if (s1->section_align)
2045 s_align = s1->section_align;
2047 if (phnum > 0) {
2048 if (s1->has_text_addr) {
2049 int a_offset, p_offset;
2050 addr = s1->text_addr;
2051 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
2052 ELF_PAGE_SIZE */
2053 a_offset = (int) (addr & (s_align - 1));
2054 p_offset = file_offset & (s_align - 1);
2055 if (a_offset < p_offset)
2056 a_offset += s_align;
2057 file_offset += (a_offset - p_offset);
2058 } else {
2059 if (file_type == TCC_OUTPUT_DLL)
2060 addr = 0;
2061 else
2062 addr = ELF_START_ADDR;
2063 /* compute address after headers */
2064 addr += (file_offset & (s_align - 1));
2067 ph = &phdr[0];
2068 /* Leave one program headers for the program interpreter and one for
2069 the program header table itself if needed. These are done later as
2070 they require section layout to be done first. */
2071 if (interp)
2072 ph += 1 + HAVE_PHDR;
2074 /* dynamic relocation table information, for .dynamic section */
2075 dyninf->rel_addr = dyninf->rel_size = 0;
2076 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2077 dyninf->bss_addr = dyninf->bss_size = 0;
2078 #endif
2080 for(j = 0; j < 2; j++) {
2081 ph->p_type = PT_LOAD;
2082 if (j == 0)
2083 ph->p_flags = PF_R | PF_X;
2084 else
2085 ph->p_flags = PF_R | PF_W;
2086 ph->p_align = s_align;
2088 /* Decide the layout of sections loaded in memory. This must
2089 be done before program headers are filled since they contain
2090 info about the layout. We do the following ordering: interp,
2091 symbol tables, relocations, progbits, nobits */
2092 /* XXX: do faster and simpler sorting */
2093 for(k = 0; k < 5; k++) {
2094 for(i = 1; i < s1->nb_sections; i++) {
2095 s = s1->sections[i];
2096 /* compute if section should be included */
2097 if (j == 0) {
2098 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
2099 SHF_ALLOC)
2100 continue;
2101 } else {
2102 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
2103 (SHF_ALLOC | SHF_WRITE))
2104 continue;
2106 if (s == interp) {
2107 if (k != 0)
2108 continue;
2109 } else if (s->sh_type == SHT_DYNSYM ||
2110 s->sh_type == SHT_STRTAB ||
2111 s->sh_type == SHT_HASH) {
2112 if (k != 1)
2113 continue;
2114 } else if (s->sh_type == SHT_RELX) {
2115 if (k != 2)
2116 continue;
2117 } else if (s->sh_type == SHT_NOBITS) {
2118 if (k != 4)
2119 continue;
2120 } else {
2121 if (k != 3)
2122 continue;
2124 sec_order[sh_order_index++] = i;
2126 /* section matches: we align it and add its size */
2127 tmp = addr;
2128 addr = (addr + s->sh_addralign - 1) &
2129 ~(s->sh_addralign - 1);
2130 file_offset += (int) ( addr - tmp );
2131 s->sh_offset = file_offset;
2132 s->sh_addr = addr;
2134 /* update program header infos */
2135 if (ph->p_offset == 0) {
2136 ph->p_offset = file_offset;
2137 ph->p_vaddr = addr;
2138 ph->p_paddr = ph->p_vaddr;
2140 /* update dynamic relocation infos */
2141 if (s->sh_type == SHT_RELX) {
2142 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2143 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) {
2144 dyninf->rel_addr = addr;
2145 dyninf->rel_size += s->sh_size; /* XXX only first rel. */
2147 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) {
2148 dyninf->bss_addr = addr;
2149 dyninf->bss_size = s->sh_size; /* XXX only first rel. */
2151 #else
2152 if (dyninf->rel_size == 0)
2153 dyninf->rel_addr = addr;
2154 dyninf->rel_size += s->sh_size;
2155 #endif
2157 addr += s->sh_size;
2158 if (s->sh_type != SHT_NOBITS)
2159 file_offset += s->sh_size;
2162 if (j == 0) {
2163 /* Make the first PT_LOAD segment include the program
2164 headers itself (and the ELF header as well), it'll
2165 come out with same memory use but will make various
2166 tools like binutils strip work better. */
2167 ph->p_offset &= ~(ph->p_align - 1);
2168 ph->p_vaddr &= ~(ph->p_align - 1);
2169 ph->p_paddr &= ~(ph->p_align - 1);
2171 ph->p_filesz = file_offset - ph->p_offset;
2172 ph->p_memsz = addr - ph->p_vaddr;
2173 ph++;
2174 if (j == 0) {
2175 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2176 /* if in the middle of a page, we duplicate the page in
2177 memory so that one copy is RX and the other is RW */
2178 if ((addr & (s_align - 1)) != 0)
2179 addr += s_align;
2180 } else {
2181 addr = (addr + s_align - 1) & ~(s_align - 1);
2182 file_offset = (file_offset + s_align - 1) & ~(s_align - 1);
2188 /* all other sections come after */
2189 for(i = 1; i < s1->nb_sections; i++) {
2190 s = s1->sections[i];
2191 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2192 continue;
2193 sec_order[sh_order_index++] = i;
2195 file_offset = (file_offset + s->sh_addralign - 1) &
2196 ~(s->sh_addralign - 1);
2197 s->sh_offset = file_offset;
2198 if (s->sh_type != SHT_NOBITS)
2199 file_offset += s->sh_size;
2202 return file_offset;
2205 static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp,
2206 Section *dynamic)
2208 ElfW(Phdr) *ph;
2210 /* if interpreter, then add corresponding program header */
2211 if (interp) {
2212 ph = &phdr[0];
2214 if (HAVE_PHDR)
2216 int len = phnum * sizeof(ElfW(Phdr));
2218 ph->p_type = PT_PHDR;
2219 ph->p_offset = sizeof(ElfW(Ehdr));
2220 ph->p_vaddr = interp->sh_addr - len;
2221 ph->p_paddr = ph->p_vaddr;
2222 ph->p_filesz = ph->p_memsz = len;
2223 ph->p_flags = PF_R | PF_X;
2224 ph->p_align = 4; /* interp->sh_addralign; */
2225 ph++;
2228 ph->p_type = PT_INTERP;
2229 ph->p_offset = interp->sh_offset;
2230 ph->p_vaddr = interp->sh_addr;
2231 ph->p_paddr = ph->p_vaddr;
2232 ph->p_filesz = interp->sh_size;
2233 ph->p_memsz = interp->sh_size;
2234 ph->p_flags = PF_R;
2235 ph->p_align = interp->sh_addralign;
2238 /* if dynamic section, then add corresponding program header */
2239 if (dynamic) {
2240 ph = &phdr[phnum - 1];
2242 ph->p_type = PT_DYNAMIC;
2243 ph->p_offset = dynamic->sh_offset;
2244 ph->p_vaddr = dynamic->sh_addr;
2245 ph->p_paddr = ph->p_vaddr;
2246 ph->p_filesz = dynamic->sh_size;
2247 ph->p_memsz = dynamic->sh_size;
2248 ph->p_flags = PF_R | PF_W;
2249 ph->p_align = dynamic->sh_addralign;
2253 /* Fill the dynamic section with tags describing the address and size of
2254 sections */
2255 static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
2257 Section *dynamic;
2259 dynamic = dyninf->dynamic;
2261 /* put dynamic section entries */
2262 dynamic->data_offset = dyninf->dyn_rel_off;
2263 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
2264 put_dt(dynamic, DT_STRTAB, dyninf->dynstr->sh_addr);
2265 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2266 put_dt(dynamic, DT_STRSZ, dyninf->dynstr->data_offset);
2267 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2268 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
2269 put_dt(dynamic, DT_RELA, dyninf->rel_addr);
2270 put_dt(dynamic, DT_RELASZ, dyninf->rel_size);
2271 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2272 #else
2273 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2274 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2275 put_dt(dynamic, DT_PLTRELSZ, dyninf->rel_size);
2276 put_dt(dynamic, DT_JMPREL, dyninf->rel_addr);
2277 put_dt(dynamic, DT_PLTREL, DT_REL);
2278 put_dt(dynamic, DT_REL, dyninf->bss_addr);
2279 put_dt(dynamic, DT_RELSZ, dyninf->bss_size);
2280 #else
2281 put_dt(dynamic, DT_REL, dyninf->rel_addr);
2282 put_dt(dynamic, DT_RELSZ, dyninf->rel_size);
2283 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2284 #endif
2285 #endif
2286 if (s1->do_debug)
2287 put_dt(dynamic, DT_DEBUG, 0);
2288 put_dt(dynamic, DT_NULL, 0);
2291 /* Relocate remaining sections and symbols (that is those not related to
2292 dynamic linking) */
2293 static int final_sections_reloc(TCCState *s1)
2295 int i;
2296 Section *s;
2298 relocate_syms(s1, 0);
2300 if (s1->nb_errors != 0)
2301 return -1;
2303 /* relocate sections */
2304 /* XXX: ignore sections with allocated relocations ? */
2305 for(i = 1; i < s1->nb_sections; i++) {
2306 s = s1->sections[i];
2307 #ifdef TCC_TARGET_I386
2308 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
2309 /* On X86 gdb 7.3 works in any case but gdb 6.6 will crash if SHF_ALLOC
2310 checking is removed */
2311 #else
2312 if (s->reloc && s != s1->got)
2313 /* On X86_64 gdb 7.3 will crash if SHF_ALLOC checking is present */
2314 #endif
2315 relocate_section(s1, s);
2318 /* relocate relocation entries if the relocation tables are
2319 allocated in the executable */
2320 for(i = 1; i < s1->nb_sections; i++) {
2321 s = s1->sections[i];
2322 if ((s->sh_flags & SHF_ALLOC) &&
2323 s->sh_type == SHT_RELX) {
2324 relocate_rel(s1, s);
2327 return 0;
2330 /* Create an ELF file on disk.
2331 This function handle ELF specific layout requirements */
2332 static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
2333 int file_offset, int *sec_order)
2335 int i, shnum, offset, size, file_type;
2336 Section *s;
2337 ElfW(Ehdr) ehdr;
2338 ElfW(Shdr) shdr, *sh;
2340 file_type = s1->output_type;
2341 shnum = s1->nb_sections;
2343 memset(&ehdr, 0, sizeof(ehdr));
2345 if (phnum > 0) {
2346 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2347 ehdr.e_phnum = phnum;
2348 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2351 /* align to 4 */
2352 file_offset = (file_offset + 3) & -4;
2354 /* fill header */
2355 ehdr.e_ident[0] = ELFMAG0;
2356 ehdr.e_ident[1] = ELFMAG1;
2357 ehdr.e_ident[2] = ELFMAG2;
2358 ehdr.e_ident[3] = ELFMAG3;
2359 ehdr.e_ident[4] = ELFCLASSW;
2360 ehdr.e_ident[5] = ELFDATA2LSB;
2361 ehdr.e_ident[6] = EV_CURRENT;
2362 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2363 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2364 #endif
2365 #ifdef TCC_TARGET_ARM
2366 #ifdef TCC_ARM_EABI
2367 ehdr.e_ident[EI_OSABI] = 0;
2368 ehdr.e_flags = EF_ARM_EABI_VER4;
2369 if (file_type == TCC_OUTPUT_EXE || file_type == TCC_OUTPUT_DLL)
2370 ehdr.e_flags |= EF_ARM_HASENTRY;
2371 if (s1->float_abi == ARM_HARD_FLOAT)
2372 ehdr.e_flags |= EF_ARM_VFP_FLOAT;
2373 else
2374 ehdr.e_flags |= EF_ARM_SOFT_FLOAT;
2375 #else
2376 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2377 #endif
2378 #endif
2379 switch(file_type) {
2380 default:
2381 case TCC_OUTPUT_EXE:
2382 ehdr.e_type = ET_EXEC;
2383 ehdr.e_entry = get_elf_sym_addr(s1, "_start", 1);
2384 break;
2385 case TCC_OUTPUT_DLL:
2386 ehdr.e_type = ET_DYN;
2387 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2388 break;
2389 case TCC_OUTPUT_OBJ:
2390 ehdr.e_type = ET_REL;
2391 break;
2393 ehdr.e_machine = EM_TCC_TARGET;
2394 ehdr.e_version = EV_CURRENT;
2395 ehdr.e_shoff = file_offset;
2396 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2397 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2398 ehdr.e_shnum = shnum;
2399 ehdr.e_shstrndx = shnum - 1;
2401 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2402 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2403 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2405 sort_syms(s1, symtab_section);
2406 for(i = 1; i < s1->nb_sections; i++) {
2407 s = s1->sections[sec_order[i]];
2408 if (s->sh_type != SHT_NOBITS) {
2409 if (s->sh_type == SHT_DYNSYM)
2410 patch_dynsym_undef(s1, s);
2411 while (offset < s->sh_offset) {
2412 fputc(0, f);
2413 offset++;
2415 size = s->sh_size;
2416 if (size)
2417 fwrite(s->data, 1, size, f);
2418 offset += size;
2422 /* output section headers */
2423 while (offset < ehdr.e_shoff) {
2424 fputc(0, f);
2425 offset++;
2428 for(i = 0; i < s1->nb_sections; i++) {
2429 sh = &shdr;
2430 memset(sh, 0, sizeof(ElfW(Shdr)));
2431 s = s1->sections[i];
2432 if (s) {
2433 sh->sh_name = s->sh_name;
2434 sh->sh_type = s->sh_type;
2435 sh->sh_flags = s->sh_flags;
2436 sh->sh_entsize = s->sh_entsize;
2437 sh->sh_info = s->sh_info;
2438 if (s->link)
2439 sh->sh_link = s->link->sh_num;
2440 sh->sh_addralign = s->sh_addralign;
2441 sh->sh_addr = s->sh_addr;
2442 sh->sh_offset = s->sh_offset;
2443 sh->sh_size = s->sh_size;
2445 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2449 /* Write an elf, coff or "binary" file */
2450 static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum,
2451 ElfW(Phdr) *phdr, int file_offset, int *sec_order)
2453 int fd, mode, file_type;
2454 FILE *f;
2456 file_type = s1->output_type;
2457 if (file_type == TCC_OUTPUT_OBJ)
2458 mode = 0666;
2459 else
2460 mode = 0777;
2461 unlink(filename);
2462 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2463 if (fd < 0) {
2464 tcc_error_noabort("could not write '%s'", filename);
2465 return -1;
2467 f = fdopen(fd, "wb");
2468 if (s1->verbose)
2469 printf("<- %s\n", filename);
2471 #ifdef TCC_TARGET_COFF
2472 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF)
2473 tcc_output_coff(s1, f);
2474 else
2475 #endif
2476 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
2477 tcc_output_elf(s1, f, phnum, phdr, file_offset, sec_order);
2478 else
2479 tcc_output_binary(s1, f, sec_order);
2480 fclose(f);
2482 return 0;
2485 /* Output an elf, coff or binary file */
2486 /* XXX: suppress unneeded sections */
2487 static int elf_output_file(TCCState *s1, const char *filename)
2489 int i, ret, phnum, shnum, file_type, file_offset, *sec_order;
2490 struct dyn_inf dyninf;
2491 ElfW(Phdr) *phdr;
2492 ElfW(Sym) *sym;
2493 Section *strsec, *interp, *dynamic, *dynstr;
2495 file_type = s1->output_type;
2496 s1->nb_errors = 0;
2498 /* if linking, also link in runtime libraries (libc, libgcc, etc.) */
2499 if (file_type != TCC_OUTPUT_OBJ) {
2500 tcc_add_runtime(s1);
2503 phdr = NULL;
2504 sec_order = NULL;
2505 interp = dynamic = dynstr = NULL; /* avoid warning */
2506 dyninf.dyn_rel_off = 0; /* avoid warning */
2508 if (file_type != TCC_OUTPUT_OBJ) {
2509 relocate_common_syms();
2511 tcc_add_linker_symbols(s1);
2513 if (!s1->static_link) {
2514 if (file_type == TCC_OUTPUT_EXE) {
2515 char *ptr;
2516 /* allow override the dynamic loader */
2517 const char *elfint = getenv("LD_SO");
2518 if (elfint == NULL)
2519 elfint = DEFAULT_ELFINTERP(s1);
2520 /* add interpreter section only if executable */
2521 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
2522 interp->sh_addralign = 1;
2523 ptr = section_ptr_add(interp, 1 + strlen(elfint));
2524 strcpy(ptr, elfint);
2527 /* add dynamic symbol table */
2528 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
2529 ".dynstr",
2530 ".hash", SHF_ALLOC);
2531 dynstr = s1->dynsym->link;
2533 /* add dynamic section */
2534 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
2535 SHF_ALLOC | SHF_WRITE);
2536 dynamic->link = dynstr;
2537 dynamic->sh_entsize = sizeof(ElfW(Dyn));
2539 build_got(s1);
2541 if (file_type == TCC_OUTPUT_EXE) {
2542 bind_exe_dynsyms(s1);
2544 if (s1->nb_errors) {
2545 ret = -1;
2546 goto the_end;
2549 bind_libs_dynsyms(s1);
2550 } else /* shared library case: simply export all global symbols */
2551 export_global_syms(s1);
2553 build_got_entries(s1);
2555 /* add a list of needed dlls */
2556 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2557 DLLReference *dllref = s1->loaded_dlls[i];
2558 if (dllref->level == 0)
2559 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
2562 if (s1->rpath)
2563 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
2565 /* XXX: currently, since we do not handle PIC code, we
2566 must relocate the readonly segments */
2567 if (file_type == TCC_OUTPUT_DLL) {
2568 if (s1->soname)
2569 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
2570 put_dt(dynamic, DT_TEXTREL, 0);
2573 if (s1->symbolic)
2574 put_dt(dynamic, DT_SYMBOLIC, 0);
2576 /* add necessary space for other entries */
2577 dyninf.dyn_rel_off = dynamic->data_offset;
2578 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
2579 } else {
2580 /* still need to build got entries in case of static link */
2581 build_got_entries(s1);
2585 /* we add a section for symbols */
2586 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
2587 put_elf_str(strsec, "");
2589 /* compute number of sections */
2590 shnum = s1->nb_sections;
2592 /* this array is used to reorder sections in the output file */
2593 sec_order = tcc_malloc(sizeof(int) * shnum);
2594 sec_order[0] = 0;
2596 /* compute number of program headers */
2597 switch(file_type) {
2598 default:
2599 case TCC_OUTPUT_OBJ:
2600 phnum = 0;
2601 break;
2602 case TCC_OUTPUT_EXE:
2603 if (!s1->static_link)
2604 phnum = 4 + HAVE_PHDR;
2605 else
2606 phnum = 2;
2607 break;
2608 case TCC_OUTPUT_DLL:
2609 phnum = 3;
2610 break;
2613 /* Allocate strings for section names */
2614 alloc_sec_names(s1, file_type, strsec);
2616 /* allocate program segment headers */
2617 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
2619 /* compute section to program header mapping */
2620 file_offset = layout_sections(s1, phdr, phnum, interp, strsec, &dyninf,
2621 sec_order);
2623 /* Fill remaining program header and finalize relocation related to dynamic
2624 linking. */
2625 if (phnum > 0) {
2626 fill_unloadable_phdr(phdr, phnum, interp, dynamic);
2627 if (dynamic) {
2628 dyninf.dynamic = dynamic;
2629 dyninf.dynstr = dynstr;
2631 fill_dynamic(s1, &dyninf);
2633 /* put in GOT the dynamic section address and relocate PLT */
2634 write32le(s1->got->data, dynamic->sh_addr);
2635 if (file_type == TCC_OUTPUT_EXE
2636 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2637 || file_type == TCC_OUTPUT_DLL
2638 #endif
2640 relocate_plt(s1);
2642 /* relocate symbols in .dynsym now that final addresses are known */
2643 for_each_elem(s1->dynsym, 1, sym, ElfW(Sym)) {
2644 if (sym->st_shndx == SHN_UNDEF) {
2645 /* relocate to PLT if symbol corresponds to a PLT entry,
2646 but not if it's a weak symbol */
2647 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
2648 sym->st_value = 0;
2649 else if (sym->st_value)
2650 sym->st_value += s1->plt->sh_addr;
2651 } else if (sym->st_shndx < SHN_LORESERVE) {
2652 /* do symbol relocation */
2653 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
2659 /* if building executable or DLL, then relocate each section
2660 except the GOT which is already relocated */
2661 if (file_type != TCC_OUTPUT_OBJ) {
2662 ret = final_sections_reloc(s1);
2663 if (ret)
2664 goto the_end;
2667 /* Perform relocation to GOT or PLT entries */
2668 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2669 fill_got(s1);
2671 /* Create the ELF file with name 'filename' */
2672 ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order);
2673 the_end:
2674 tcc_free(s1->symtab_to_dynsym);
2675 tcc_free(sec_order);
2676 tcc_free(phdr);
2677 tcc_free(s1->sym_attrs);
2678 s1->sym_attrs = NULL;
2679 return ret;
2682 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2684 int ret;
2685 #ifdef TCC_TARGET_PE
2686 if (s->output_type != TCC_OUTPUT_OBJ) {
2687 ret = pe_output_file(s, filename);
2688 } else
2689 #endif
2690 ret = elf_output_file(s, filename);
2691 return ret;
2694 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2696 void *data;
2698 data = tcc_malloc(size);
2699 lseek(fd, file_offset, SEEK_SET);
2700 read(fd, data, size);
2701 return data;
2704 typedef struct SectionMergeInfo {
2705 Section *s; /* corresponding existing section */
2706 unsigned long offset; /* offset of the new section in the existing section */
2707 uint8_t new_section; /* true if section 's' was added */
2708 uint8_t link_once; /* true if link once section */
2709 } SectionMergeInfo;
2711 ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h)
2713 int size = read(fd, h, sizeof *h);
2714 if (size == sizeof *h && 0 == memcmp(h, ELFMAG, 4)) {
2715 if (h->e_type == ET_REL)
2716 return AFF_BINTYPE_REL;
2717 if (h->e_type == ET_DYN)
2718 return AFF_BINTYPE_DYN;
2719 } else if (size >= 8) {
2720 if (0 == memcmp(h, ARMAG, 8))
2721 return AFF_BINTYPE_AR;
2722 #ifdef TCC_TARGET_COFF
2723 if (((struct filehdr*)h)->f_magic == COFF_C67_MAGIC)
2724 return AFF_BINTYPE_C67;
2725 #endif
2727 return 0;
2730 /* load an object file and merge it with current files */
2731 /* XXX: handle correctly stab (debug) info */
2732 ST_FUNC int tcc_load_object_file(TCCState *s1,
2733 int fd, unsigned long file_offset)
2735 ElfW(Ehdr) ehdr;
2736 ElfW(Shdr) *shdr, *sh;
2737 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2738 unsigned char *strsec, *strtab;
2739 int *old_to_new_syms;
2740 char *sh_name, *name;
2741 SectionMergeInfo *sm_table, *sm;
2742 ElfW(Sym) *sym, *symtab;
2743 ElfW_Rel *rel;
2744 Section *s;
2746 int stab_index;
2747 int stabstr_index;
2749 stab_index = stabstr_index = 0;
2751 lseek(fd, file_offset, SEEK_SET);
2752 if (tcc_object_type(fd, &ehdr) != AFF_BINTYPE_REL)
2753 goto fail1;
2754 /* test CPU specific stuff */
2755 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2756 ehdr.e_machine != EM_TCC_TARGET) {
2757 fail1:
2758 tcc_error_noabort("invalid object file");
2759 return -1;
2761 /* read sections */
2762 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2763 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2764 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2766 /* load section names */
2767 sh = &shdr[ehdr.e_shstrndx];
2768 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2770 /* load symtab and strtab */
2771 old_to_new_syms = NULL;
2772 symtab = NULL;
2773 strtab = NULL;
2774 nb_syms = 0;
2775 for(i = 1; i < ehdr.e_shnum; i++) {
2776 sh = &shdr[i];
2777 if (sh->sh_type == SHT_SYMTAB) {
2778 if (symtab) {
2779 tcc_error_noabort("object must contain only one symtab");
2780 fail:
2781 ret = -1;
2782 goto the_end;
2784 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2785 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2786 sm_table[i].s = symtab_section;
2788 /* now load strtab */
2789 sh = &shdr[sh->sh_link];
2790 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2794 /* now examine each section and try to merge its content with the
2795 ones in memory */
2796 for(i = 1; i < ehdr.e_shnum; i++) {
2797 /* no need to examine section name strtab */
2798 if (i == ehdr.e_shstrndx)
2799 continue;
2800 sh = &shdr[i];
2801 sh_name = (char *) strsec + sh->sh_name;
2802 /* ignore sections types we do not handle */
2803 if (sh->sh_type != SHT_PROGBITS &&
2804 sh->sh_type != SHT_RELX &&
2805 #ifdef TCC_ARM_EABI
2806 sh->sh_type != SHT_ARM_EXIDX &&
2807 #endif
2808 sh->sh_type != SHT_NOBITS &&
2809 sh->sh_type != SHT_PREINIT_ARRAY &&
2810 sh->sh_type != SHT_INIT_ARRAY &&
2811 sh->sh_type != SHT_FINI_ARRAY &&
2812 strcmp(sh_name, ".stabstr")
2814 continue;
2815 if (sh->sh_addralign < 1)
2816 sh->sh_addralign = 1;
2817 /* find corresponding section, if any */
2818 for(j = 1; j < s1->nb_sections;j++) {
2819 s = s1->sections[j];
2820 if (!strcmp(s->name, sh_name)) {
2821 if (!strncmp(sh_name, ".gnu.linkonce",
2822 sizeof(".gnu.linkonce") - 1)) {
2823 /* if a 'linkonce' section is already present, we
2824 do not add it again. It is a little tricky as
2825 symbols can still be defined in
2826 it. */
2827 sm_table[i].link_once = 1;
2828 goto next;
2829 } else {
2830 goto found;
2834 /* not found: create new section */
2835 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2836 /* take as much info as possible from the section. sh_link and
2837 sh_info will be updated later */
2838 s->sh_addralign = sh->sh_addralign;
2839 s->sh_entsize = sh->sh_entsize;
2840 sm_table[i].new_section = 1;
2841 found:
2842 if (sh->sh_type != s->sh_type) {
2843 tcc_error_noabort("invalid section type");
2844 goto fail;
2847 /* align start of section */
2848 offset = s->data_offset;
2850 if (0 == strcmp(sh_name, ".stab")) {
2851 stab_index = i;
2852 goto no_align;
2854 if (0 == strcmp(sh_name, ".stabstr")) {
2855 stabstr_index = i;
2856 goto no_align;
2859 size = sh->sh_addralign - 1;
2860 offset = (offset + size) & ~size;
2861 if (sh->sh_addralign > s->sh_addralign)
2862 s->sh_addralign = sh->sh_addralign;
2863 s->data_offset = offset;
2864 no_align:
2865 sm_table[i].offset = offset;
2866 sm_table[i].s = s;
2867 /* concatenate sections */
2868 size = sh->sh_size;
2869 if (sh->sh_type != SHT_NOBITS) {
2870 unsigned char *ptr;
2871 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2872 ptr = section_ptr_add(s, size);
2873 read(fd, ptr, size);
2874 } else {
2875 s->data_offset += size;
2877 next: ;
2880 /* gr relocate stab strings */
2881 if (stab_index && stabstr_index) {
2882 Stab_Sym *a, *b;
2883 unsigned o;
2884 s = sm_table[stab_index].s;
2885 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2886 b = (Stab_Sym *)(s->data + s->data_offset);
2887 o = sm_table[stabstr_index].offset;
2888 while (a < b)
2889 a->n_strx += o, a++;
2892 /* second short pass to update sh_link and sh_info fields of new
2893 sections */
2894 for(i = 1; i < ehdr.e_shnum; i++) {
2895 s = sm_table[i].s;
2896 if (!s || !sm_table[i].new_section)
2897 continue;
2898 sh = &shdr[i];
2899 if (sh->sh_link > 0)
2900 s->link = sm_table[sh->sh_link].s;
2901 if (sh->sh_type == SHT_RELX) {
2902 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2903 /* update backward link */
2904 s1->sections[s->sh_info]->reloc = s;
2907 sm = sm_table;
2909 /* resolve symbols */
2910 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2912 sym = symtab + 1;
2913 for(i = 1; i < nb_syms; i++, sym++) {
2914 if (sym->st_shndx != SHN_UNDEF &&
2915 sym->st_shndx < SHN_LORESERVE) {
2916 sm = &sm_table[sym->st_shndx];
2917 if (sm->link_once) {
2918 /* if a symbol is in a link once section, we use the
2919 already defined symbol. It is very important to get
2920 correct relocations */
2921 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2922 name = (char *) strtab + sym->st_name;
2923 sym_index = find_elf_sym(symtab_section, name);
2924 if (sym_index)
2925 old_to_new_syms[i] = sym_index;
2927 continue;
2929 /* if no corresponding section added, no need to add symbol */
2930 if (!sm->s)
2931 continue;
2932 /* convert section number */
2933 sym->st_shndx = sm->s->sh_num;
2934 /* offset value */
2935 sym->st_value += sm->offset;
2937 /* add symbol */
2938 name = (char *) strtab + sym->st_name;
2939 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2940 sym->st_info, sym->st_other,
2941 sym->st_shndx, name);
2942 old_to_new_syms[i] = sym_index;
2945 /* third pass to patch relocation entries */
2946 for(i = 1; i < ehdr.e_shnum; i++) {
2947 s = sm_table[i].s;
2948 if (!s)
2949 continue;
2950 sh = &shdr[i];
2951 offset = sm_table[i].offset;
2952 switch(s->sh_type) {
2953 case SHT_RELX:
2954 /* take relocation offset information */
2955 offseti = sm_table[sh->sh_info].offset;
2956 for_each_elem(s, (offset / sizeof(*rel)), rel, ElfW_Rel) {
2957 int type;
2958 unsigned sym_index;
2959 /* convert symbol index */
2960 type = ELFW(R_TYPE)(rel->r_info);
2961 sym_index = ELFW(R_SYM)(rel->r_info);
2962 /* NOTE: only one symtab assumed */
2963 if (sym_index >= nb_syms)
2964 goto invalid_reloc;
2965 sym_index = old_to_new_syms[sym_index];
2966 /* ignore link_once in rel section. */
2967 if (!sym_index && !sm->link_once
2968 #ifdef TCC_TARGET_ARM
2969 && type != R_ARM_V4BX
2970 #endif
2972 invalid_reloc:
2973 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2974 i, strsec + sh->sh_name, rel->r_offset);
2975 goto fail;
2977 rel->r_info = ELFW(R_INFO)(sym_index, type);
2978 /* offset the relocation offset */
2979 rel->r_offset += offseti;
2980 #ifdef TCC_TARGET_ARM
2981 /* Jumps and branches from a Thumb code to a PLT entry need
2982 special handling since PLT entries are ARM code.
2983 Unconditional bl instructions referencing PLT entries are
2984 handled by converting these instructions into blx
2985 instructions. Other case of instructions referencing a PLT
2986 entry require to add a Thumb stub before the PLT entry to
2987 switch to ARM mode. We set bit plt_thumb_stub of the
2988 attribute of a symbol to indicate such a case. */
2989 if (type == R_ARM_THM_JUMP24)
2990 alloc_sym_attr(s1, sym_index)->plt_thumb_stub = 1;
2991 #endif
2993 break;
2994 default:
2995 break;
2999 ret = 0;
3000 the_end:
3001 tcc_free(symtab);
3002 tcc_free(strtab);
3003 tcc_free(old_to_new_syms);
3004 tcc_free(sm_table);
3005 tcc_free(strsec);
3006 tcc_free(shdr);
3007 return ret;
3010 typedef struct ArchiveHeader {
3011 char ar_name[16]; /* name of this member */
3012 char ar_date[12]; /* file mtime */
3013 char ar_uid[6]; /* owner uid; printed as decimal */
3014 char ar_gid[6]; /* owner gid; printed as decimal */
3015 char ar_mode[8]; /* file mode, printed as octal */
3016 char ar_size[10]; /* file size, printed as decimal */
3017 char ar_fmag[2]; /* should contain ARFMAG */
3018 } ArchiveHeader;
3020 static int get_be32(const uint8_t *b)
3022 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
3025 /* load only the objects which resolve undefined symbols */
3026 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
3028 int i, bound, nsyms, sym_index, off, ret;
3029 uint8_t *data;
3030 const char *ar_names, *p;
3031 const uint8_t *ar_index;
3032 ElfW(Sym) *sym;
3034 data = tcc_malloc(size);
3035 if (read(fd, data, size) != size)
3036 goto fail;
3037 nsyms = get_be32(data);
3038 ar_index = data + 4;
3039 ar_names = (char *) ar_index + nsyms * 4;
3041 do {
3042 bound = 0;
3043 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
3044 sym_index = find_elf_sym(symtab_section, p);
3045 if(sym_index) {
3046 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
3047 if(sym->st_shndx == SHN_UNDEF) {
3048 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
3049 ++bound;
3050 if(tcc_load_object_file(s1, fd, off) < 0) {
3051 fail:
3052 ret = -1;
3053 goto the_end;
3058 } while(bound);
3059 ret = 0;
3060 the_end:
3061 tcc_free(data);
3062 return ret;
3065 /* load a '.a' file */
3066 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
3068 ArchiveHeader hdr;
3069 char ar_size[11];
3070 char ar_name[17];
3071 char magic[8];
3072 int size, len, i;
3073 unsigned long file_offset;
3075 /* skip magic which was already checked */
3076 read(fd, magic, sizeof(magic));
3078 for(;;) {
3079 len = read(fd, &hdr, sizeof(hdr));
3080 if (len == 0)
3081 break;
3082 if (len != sizeof(hdr)) {
3083 tcc_error_noabort("invalid archive");
3084 return -1;
3086 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
3087 ar_size[sizeof(hdr.ar_size)] = '\0';
3088 size = strtol(ar_size, NULL, 0);
3089 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
3090 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
3091 if (ar_name[i] != ' ')
3092 break;
3094 ar_name[i + 1] = '\0';
3095 file_offset = lseek(fd, 0, SEEK_CUR);
3096 /* align to even */
3097 size = (size + 1) & ~1;
3098 if (!strcmp(ar_name, "/")) {
3099 /* coff symbol table : we handle it */
3100 if(s1->alacarte_link)
3101 return tcc_load_alacarte(s1, fd, size);
3102 } else {
3103 ElfW(Ehdr) ehdr;
3104 if (tcc_object_type(fd, &ehdr) == AFF_BINTYPE_REL) {
3105 if (tcc_load_object_file(s1, fd, file_offset) < 0)
3106 return -1;
3109 lseek(fd, file_offset + size, SEEK_SET);
3111 return 0;
3114 #ifndef TCC_TARGET_PE
3115 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
3116 is referenced by the user (so it should be added as DT_NEEDED in
3117 the generated ELF file) */
3118 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
3120 ElfW(Ehdr) ehdr;
3121 ElfW(Shdr) *shdr, *sh, *sh1;
3122 int i, j, nb_syms, nb_dts, sym_bind, ret;
3123 ElfW(Sym) *sym, *dynsym;
3124 ElfW(Dyn) *dt, *dynamic;
3125 unsigned char *dynstr;
3126 const char *name, *soname;
3127 DLLReference *dllref;
3129 read(fd, &ehdr, sizeof(ehdr));
3131 /* test CPU specific stuff */
3132 if (ehdr.e_ident[5] != ELFDATA2LSB ||
3133 ehdr.e_machine != EM_TCC_TARGET) {
3134 tcc_error_noabort("bad architecture");
3135 return -1;
3138 /* read sections */
3139 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
3141 /* load dynamic section and dynamic symbols */
3142 nb_syms = 0;
3143 nb_dts = 0;
3144 dynamic = NULL;
3145 dynsym = NULL; /* avoid warning */
3146 dynstr = NULL; /* avoid warning */
3147 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
3148 switch(sh->sh_type) {
3149 case SHT_DYNAMIC:
3150 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
3151 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
3152 break;
3153 case SHT_DYNSYM:
3154 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
3155 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
3156 sh1 = &shdr[sh->sh_link];
3157 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
3158 break;
3159 default:
3160 break;
3164 /* compute the real library name */
3165 soname = tcc_basename(filename);
3167 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
3168 if (dt->d_tag == DT_SONAME) {
3169 soname = (char *) dynstr + dt->d_un.d_val;
3173 /* if the dll is already loaded, do not load it */
3174 for(i = 0; i < s1->nb_loaded_dlls; i++) {
3175 dllref = s1->loaded_dlls[i];
3176 if (!strcmp(soname, dllref->name)) {
3177 /* but update level if needed */
3178 if (level < dllref->level)
3179 dllref->level = level;
3180 ret = 0;
3181 goto the_end;
3185 /* add the dll and its level */
3186 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
3187 dllref->level = level;
3188 strcpy(dllref->name, soname);
3189 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
3191 /* add dynamic symbols in dynsym_section */
3192 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
3193 sym_bind = ELFW(ST_BIND)(sym->st_info);
3194 if (sym_bind == STB_LOCAL)
3195 continue;
3196 name = (char *) dynstr + sym->st_name;
3197 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
3198 sym->st_info, sym->st_other, sym->st_shndx, name);
3201 /* load all referenced DLLs */
3202 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
3203 switch(dt->d_tag) {
3204 case DT_NEEDED:
3205 name = (char *) dynstr + dt->d_un.d_val;
3206 for(j = 0; j < s1->nb_loaded_dlls; j++) {
3207 dllref = s1->loaded_dlls[j];
3208 if (!strcmp(name, dllref->name))
3209 goto already_loaded;
3211 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
3212 tcc_error_noabort("referenced dll '%s' not found", name);
3213 ret = -1;
3214 goto the_end;
3216 already_loaded:
3217 break;
3220 ret = 0;
3221 the_end:
3222 tcc_free(dynstr);
3223 tcc_free(dynsym);
3224 tcc_free(dynamic);
3225 tcc_free(shdr);
3226 return ret;
3229 #define LD_TOK_NAME 256
3230 #define LD_TOK_EOF (-1)
3232 /* return next ld script token */
3233 static int ld_next(TCCState *s1, char *name, int name_size)
3235 int c;
3236 char *q;
3238 redo:
3239 switch(ch) {
3240 case ' ':
3241 case '\t':
3242 case '\f':
3243 case '\v':
3244 case '\r':
3245 case '\n':
3246 inp();
3247 goto redo;
3248 case '/':
3249 minp();
3250 if (ch == '*') {
3251 file->buf_ptr = parse_comment(file->buf_ptr);
3252 ch = file->buf_ptr[0];
3253 goto redo;
3254 } else {
3255 q = name;
3256 *q++ = '/';
3257 goto parse_name;
3259 break;
3260 case '\\':
3261 ch = handle_eob();
3262 if (ch != '\\')
3263 goto redo;
3264 /* fall through */
3265 /* case 'a' ... 'z': */
3266 case 'a':
3267 case 'b':
3268 case 'c':
3269 case 'd':
3270 case 'e':
3271 case 'f':
3272 case 'g':
3273 case 'h':
3274 case 'i':
3275 case 'j':
3276 case 'k':
3277 case 'l':
3278 case 'm':
3279 case 'n':
3280 case 'o':
3281 case 'p':
3282 case 'q':
3283 case 'r':
3284 case 's':
3285 case 't':
3286 case 'u':
3287 case 'v':
3288 case 'w':
3289 case 'x':
3290 case 'y':
3291 case 'z':
3292 /* case 'A' ... 'z': */
3293 case 'A':
3294 case 'B':
3295 case 'C':
3296 case 'D':
3297 case 'E':
3298 case 'F':
3299 case 'G':
3300 case 'H':
3301 case 'I':
3302 case 'J':
3303 case 'K':
3304 case 'L':
3305 case 'M':
3306 case 'N':
3307 case 'O':
3308 case 'P':
3309 case 'Q':
3310 case 'R':
3311 case 'S':
3312 case 'T':
3313 case 'U':
3314 case 'V':
3315 case 'W':
3316 case 'X':
3317 case 'Y':
3318 case 'Z':
3319 case '_':
3320 case '.':
3321 case '$':
3322 case '~':
3323 q = name;
3324 parse_name:
3325 for(;;) {
3326 if (!((ch >= 'a' && ch <= 'z') ||
3327 (ch >= 'A' && ch <= 'Z') ||
3328 (ch >= '0' && ch <= '9') ||
3329 strchr("/.-_+=$:\\,~", ch)))
3330 break;
3331 if ((q - name) < name_size - 1) {
3332 *q++ = ch;
3334 minp();
3336 *q = '\0';
3337 c = LD_TOK_NAME;
3338 break;
3339 case CH_EOF:
3340 c = LD_TOK_EOF;
3341 break;
3342 default:
3343 c = ch;
3344 inp();
3345 break;
3347 return c;
3350 static int ld_add_file(TCCState *s1, const char filename[])
3352 int ret;
3354 ret = tcc_add_file_internal(s1, filename, AFF_TYPE_BIN);
3355 if (ret)
3356 ret = tcc_add_dll(s1, filename, 0);
3357 return ret;
3360 static inline int new_undef_syms(void)
3362 int ret = 0;
3363 ret = new_undef_sym;
3364 new_undef_sym = 0;
3365 return ret;
3368 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
3370 char filename[1024], libname[1024];
3371 int t, group, nblibs = 0, ret = 0;
3372 char **libs = NULL;
3374 group = !strcmp(cmd, "GROUP");
3375 if (!as_needed)
3376 new_undef_syms();
3377 t = ld_next(s1, filename, sizeof(filename));
3378 if (t != '(')
3379 expect("(");
3380 t = ld_next(s1, filename, sizeof(filename));
3381 for(;;) {
3382 libname[0] = '\0';
3383 if (t == LD_TOK_EOF) {
3384 tcc_error_noabort("unexpected end of file");
3385 ret = -1;
3386 goto lib_parse_error;
3387 } else if (t == ')') {
3388 break;
3389 } else if (t == '-') {
3390 t = ld_next(s1, filename, sizeof(filename));
3391 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
3392 tcc_error_noabort("library name expected");
3393 ret = -1;
3394 goto lib_parse_error;
3396 pstrcpy(libname, sizeof libname, &filename[1]);
3397 if (s1->static_link) {
3398 snprintf(filename, sizeof filename, "lib%s.a", libname);
3399 } else {
3400 snprintf(filename, sizeof filename, "lib%s.so", libname);
3402 } else if (t != LD_TOK_NAME) {
3403 tcc_error_noabort("filename expected");
3404 ret = -1;
3405 goto lib_parse_error;
3407 if (!strcmp(filename, "AS_NEEDED")) {
3408 ret = ld_add_file_list(s1, cmd, 1);
3409 if (ret)
3410 goto lib_parse_error;
3411 } else {
3412 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3413 if (!as_needed) {
3414 ret = ld_add_file(s1, filename);
3415 if (ret)
3416 goto lib_parse_error;
3417 if (group) {
3418 /* Add the filename *and* the libname to avoid future conversions */
3419 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
3420 if (libname[0] != '\0')
3421 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
3425 t = ld_next(s1, filename, sizeof(filename));
3426 if (t == ',') {
3427 t = ld_next(s1, filename, sizeof(filename));
3430 if (group && !as_needed) {
3431 while (new_undef_syms()) {
3432 int i;
3434 for (i = 0; i < nblibs; i ++)
3435 ld_add_file(s1, libs[i]);
3438 lib_parse_error:
3439 dynarray_reset(&libs, &nblibs);
3440 return ret;
3443 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3444 files */
3445 ST_FUNC int tcc_load_ldscript(TCCState *s1)
3447 char cmd[64];
3448 char filename[1024];
3449 int t, ret;
3451 ch = handle_eob();
3452 for(;;) {
3453 t = ld_next(s1, cmd, sizeof(cmd));
3454 if (t == LD_TOK_EOF)
3455 return 0;
3456 else if (t != LD_TOK_NAME)
3457 return -1;
3458 if (!strcmp(cmd, "INPUT") ||
3459 !strcmp(cmd, "GROUP")) {
3460 ret = ld_add_file_list(s1, cmd, 0);
3461 if (ret)
3462 return ret;
3463 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3464 !strcmp(cmd, "TARGET")) {
3465 /* ignore some commands */
3466 t = ld_next(s1, cmd, sizeof(cmd));
3467 if (t != '(')
3468 expect("(");
3469 for(;;) {
3470 t = ld_next(s1, filename, sizeof(filename));
3471 if (t == LD_TOK_EOF) {
3472 tcc_error_noabort("unexpected end of file");
3473 return -1;
3474 } else if (t == ')') {
3475 break;
3478 } else {
3479 return -1;
3482 return 0;
3484 #endif /* !TCC_TARGET_PE */