lib/libtcc1.c: cleanup
[tinycc.git] / tccelf.c
blob9ed2484edab2a021214c5801adc67559b533e6ad
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 /********************************************************/
27 /* global variables */
29 ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */
30 ST_DATA Section *cur_text_section; /* current section where function code is generated */
31 #ifdef CONFIG_TCC_ASM
32 ST_DATA Section *last_text_section; /* to handle .previous asm directive */
33 #endif
34 #ifdef CONFIG_TCC_BCHECK
35 /* bound check related sections */
36 ST_DATA Section *bounds_section; /* contains global data bound description */
37 ST_DATA Section *lbounds_section; /* contains local data bound description */
38 #endif
39 /* symbol sections */
40 ST_DATA Section *symtab_section, *strtab_section;
41 /* debug sections */
42 ST_DATA Section *stab_section, *stabstr_section;
44 /* XXX: avoid static variable */
45 static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */
47 /* ------------------------------------------------------------------------- */
49 ST_FUNC void tccelf_new(TCCState *s)
51 /* no section zero */
52 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
54 /* create standard sections */
55 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
56 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
57 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
59 /* symbols are always generated for linking stage */
60 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
61 ".strtab",
62 ".hashtab", SHF_PRIVATE);
63 strtab_section = symtab_section->link;
64 s->symtab = symtab_section;
66 /* private symbol table for dynamic symbols */
67 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
68 ".dynstrtab",
69 ".dynhashtab", SHF_PRIVATE);
72 #ifdef CONFIG_TCC_BCHECK
73 ST_FUNC void tccelf_bounds_new(TCCState *s)
75 /* create bounds sections */
76 bounds_section = new_section(s, ".bounds",
77 SHT_PROGBITS, SHF_ALLOC);
78 lbounds_section = new_section(s, ".lbounds",
79 SHT_PROGBITS, SHF_ALLOC);
81 #endif
83 ST_FUNC void tccelf_stab_new(TCCState *s)
85 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
86 stab_section->sh_entsize = sizeof(Stab_Sym);
87 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
88 put_elf_str(stabstr_section, "");
89 stab_section->link = stabstr_section;
90 /* put first entry */
91 put_stabs("", 0, 0, 0, 0);
94 static void free_section(Section *s)
96 tcc_free(s->data);
99 ST_FUNC void tccelf_delete(TCCState *s1)
101 int i;
103 /* free all sections */
104 for(i = 1; i < s1->nb_sections; i++)
105 free_section(s1->sections[i]);
106 dynarray_reset(&s1->sections, &s1->nb_sections);
108 for(i = 0; i < s1->nb_priv_sections; i++)
109 free_section(s1->priv_sections[i]);
110 dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections);
112 /* free any loaded DLLs */
113 #ifdef TCC_IS_NATIVE
114 for ( i = 0; i < s1->nb_loaded_dlls; i++) {
115 DLLReference *ref = s1->loaded_dlls[i];
116 if ( ref->handle )
117 # ifdef _WIN32
118 FreeLibrary((HMODULE)ref->handle);
119 # else
120 dlclose(ref->handle);
121 # endif
123 #endif
124 /* free loaded dlls array */
125 dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
128 ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
130 Section *sec;
132 sec = tcc_mallocz(sizeof(Section) + strlen(name));
133 strcpy(sec->name, name);
134 sec->sh_type = sh_type;
135 sec->sh_flags = sh_flags;
136 switch(sh_type) {
137 case SHT_HASH:
138 case SHT_REL:
139 case SHT_RELA:
140 case SHT_DYNSYM:
141 case SHT_SYMTAB:
142 case SHT_DYNAMIC:
143 sec->sh_addralign = 4;
144 break;
145 case SHT_STRTAB:
146 sec->sh_addralign = 1;
147 break;
148 default:
149 sec->sh_addralign = PTR_SIZE; /* gcc/pcc default aligment */
150 break;
153 if (sh_flags & SHF_PRIVATE) {
154 dynarray_add((void ***)&s1->priv_sections, &s1->nb_priv_sections, sec);
155 } else {
156 sec->sh_num = s1->nb_sections;
157 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
160 return sec;
163 /* realloc section and set its content to zero */
164 ST_FUNC void section_realloc(Section *sec, unsigned long new_size)
166 unsigned long size;
167 unsigned char *data;
169 size = sec->data_allocated;
170 if (size == 0)
171 size = 1;
172 while (size < new_size)
173 size = size * 2;
174 data = tcc_realloc(sec->data, size);
175 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
176 sec->data = data;
177 sec->data_allocated = size;
180 /* reserve at least 'size' bytes in section 'sec' from
181 sec->data_offset. */
182 ST_FUNC void *section_ptr_add(Section *sec, addr_t size)
184 size_t offset, offset1;
186 offset = sec->data_offset;
187 offset1 = offset + size;
188 if (offset1 > sec->data_allocated)
189 section_realloc(sec, offset1);
190 sec->data_offset = offset1;
191 return sec->data + offset;
194 /* reserve at least 'size' bytes from section start */
195 ST_FUNC void section_reserve(Section *sec, unsigned long size)
197 if (size > sec->data_allocated)
198 section_realloc(sec, size);
199 if (size > sec->data_offset)
200 sec->data_offset = size;
203 /* return a reference to a section, and create it if it does not
204 exists */
205 ST_FUNC Section *find_section(TCCState *s1, const char *name)
207 Section *sec;
208 int i;
209 for(i = 1; i < s1->nb_sections; i++) {
210 sec = s1->sections[i];
211 if (!strcmp(name, sec->name))
212 return sec;
214 /* sections are created as PROGBITS */
215 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
218 /* ------------------------------------------------------------------------- */
220 ST_FUNC int put_elf_str(Section *s, const char *sym)
222 int offset, len;
223 char *ptr;
225 len = strlen(sym) + 1;
226 offset = s->data_offset;
227 ptr = section_ptr_add(s, len);
228 memcpy(ptr, sym, len);
229 return offset;
232 /* elf symbol hashing function */
233 static unsigned long elf_hash(const unsigned char *name)
235 unsigned long h = 0, g;
237 while (*name) {
238 h = (h << 4) + *name++;
239 g = h & 0xf0000000;
240 if (g)
241 h ^= g >> 24;
242 h &= ~g;
244 return h;
247 /* rebuild hash table of section s */
248 /* NOTE: we do factorize the hash table code to go faster */
249 static void rebuild_hash(Section *s, unsigned int nb_buckets)
251 ElfW(Sym) *sym;
252 int *ptr, *hash, nb_syms, sym_index, h;
253 unsigned char *strtab;
255 strtab = s->link->data;
256 nb_syms = s->data_offset / sizeof(ElfW(Sym));
258 s->hash->data_offset = 0;
259 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
260 ptr[0] = nb_buckets;
261 ptr[1] = nb_syms;
262 ptr += 2;
263 hash = ptr;
264 memset(hash, 0, (nb_buckets + 1) * sizeof(int));
265 ptr += nb_buckets + 1;
267 sym = (ElfW(Sym) *)s->data + 1;
268 for(sym_index = 1; sym_index < nb_syms; sym_index++) {
269 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
270 h = elf_hash(strtab + sym->st_name) % nb_buckets;
271 *ptr = hash[h];
272 hash[h] = sym_index;
273 } else {
274 *ptr = 0;
276 ptr++;
277 sym++;
281 /* return the symbol number */
282 ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size,
283 int info, int other, int shndx, const char *name)
285 int name_offset, sym_index;
286 int nbuckets, h;
287 ElfW(Sym) *sym;
288 Section *hs;
290 sym = section_ptr_add(s, sizeof(ElfW(Sym)));
291 if (name)
292 name_offset = put_elf_str(s->link, name);
293 else
294 name_offset = 0;
295 /* XXX: endianness */
296 sym->st_name = name_offset;
297 sym->st_value = value;
298 sym->st_size = size;
299 sym->st_info = info;
300 sym->st_other = other;
301 sym->st_shndx = shndx;
302 sym_index = sym - (ElfW(Sym) *)s->data;
303 hs = s->hash;
304 if (hs) {
305 int *ptr, *base;
306 ptr = section_ptr_add(hs, sizeof(int));
307 base = (int *)hs->data;
308 /* only add global or weak symbols */
309 if (ELFW(ST_BIND)(info) != STB_LOCAL) {
310 /* add another hashing entry */
311 nbuckets = base[0];
312 h = elf_hash((unsigned char *) name) % nbuckets;
313 *ptr = base[2 + h];
314 base[2 + h] = sym_index;
315 base[1]++;
316 /* we resize the hash table */
317 hs->nb_hashed_syms++;
318 if (hs->nb_hashed_syms > 2 * nbuckets) {
319 rebuild_hash(s, 2 * nbuckets);
321 } else {
322 *ptr = 0;
323 base[1]++;
326 return sym_index;
329 /* find global ELF symbol 'name' and return its index. Return 0 if not
330 found. */
331 ST_FUNC int find_elf_sym(Section *s, const char *name)
333 ElfW(Sym) *sym;
334 Section *hs;
335 int nbuckets, sym_index, h;
336 const char *name1;
338 hs = s->hash;
339 if (!hs)
340 return 0;
341 nbuckets = ((int *)hs->data)[0];
342 h = elf_hash((unsigned char *) name) % nbuckets;
343 sym_index = ((int *)hs->data)[2 + h];
344 while (sym_index != 0) {
345 sym = &((ElfW(Sym) *)s->data)[sym_index];
346 name1 = (char *) s->link->data + sym->st_name;
347 if (!strcmp(name, name1))
348 return sym_index;
349 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
351 return 0;
354 /* return elf symbol value, signal error if 'err' is nonzero */
355 ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err)
357 int sym_index;
358 ElfW(Sym) *sym;
360 sym_index = find_elf_sym(s->symtab, name);
361 sym = &((ElfW(Sym) *)s->symtab->data)[sym_index];
362 if (!sym_index || sym->st_shndx == SHN_UNDEF) {
363 if (err)
364 tcc_error("%s not defined", name);
365 return 0;
367 return sym->st_value;
370 /* return elf symbol value */
371 LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
373 return (void*)(uintptr_t)get_elf_sym_addr(s, name, 0);
376 #if defined TCC_IS_NATIVE || defined TCC_TARGET_PE
377 /* return elf symbol value or error */
378 ST_FUNC void* tcc_get_symbol_err(TCCState *s, const char *name)
380 return (void*)(uintptr_t)get_elf_sym_addr(s, name, 1);
382 #endif
384 /* add an elf symbol : check if it is already defined and patch
385 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
386 ST_FUNC int add_elf_sym(Section *s, addr_t value, unsigned long size,
387 int info, int other, int sh_num, const char *name)
389 ElfW(Sym) *esym;
390 int sym_bind, sym_index, sym_type, esym_bind;
391 unsigned char sym_vis, esym_vis, new_vis;
393 sym_bind = ELFW(ST_BIND)(info);
394 sym_type = ELFW(ST_TYPE)(info);
395 sym_vis = ELFW(ST_VISIBILITY)(other);
397 if (sym_bind != STB_LOCAL) {
398 /* we search global or weak symbols */
399 sym_index = find_elf_sym(s, name);
400 if (!sym_index)
401 goto do_def;
402 esym = &((ElfW(Sym) *)s->data)[sym_index];
403 if (esym->st_shndx != SHN_UNDEF) {
404 esym_bind = ELFW(ST_BIND)(esym->st_info);
405 /* propagate the most constraining visibility */
406 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
407 esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
408 if (esym_vis == STV_DEFAULT) {
409 new_vis = sym_vis;
410 } else if (sym_vis == STV_DEFAULT) {
411 new_vis = esym_vis;
412 } else {
413 new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
415 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
416 | new_vis;
417 other = esym->st_other; /* in case we have to patch esym */
418 if (sh_num == SHN_UNDEF) {
419 /* ignore adding of undefined symbol if the
420 corresponding symbol is already defined */
421 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
422 /* global overrides weak, so patch */
423 goto do_patch;
424 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
425 /* weak is ignored if already global */
426 } else if (sym_bind == STB_WEAK && esym_bind == STB_WEAK) {
427 /* keep first-found weak definition, ignore subsequents */
428 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
429 /* ignore hidden symbols after */
430 } else if ((esym->st_shndx == SHN_COMMON
431 || esym->st_shndx == bss_section->sh_num)
432 && (sh_num < SHN_LORESERVE
433 && sh_num != bss_section->sh_num)) {
434 /* data symbol gets precedence over common/bss */
435 goto do_patch;
436 } else if (sh_num == SHN_COMMON || sh_num == bss_section->sh_num) {
437 /* data symbol keeps precedence over common/bss */
438 } else if (s == tcc_state->dynsymtab_section) {
439 /* we accept that two DLL define the same symbol */
440 } else {
441 #if 0
442 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
443 sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
444 #endif
445 tcc_error_noabort("'%s' defined twice", name);
447 } else {
448 do_patch:
449 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
450 esym->st_shndx = sh_num;
451 new_undef_sym = 1;
452 esym->st_value = value;
453 esym->st_size = size;
454 esym->st_other = other;
456 } else {
457 do_def:
458 sym_index = put_elf_sym(s, value, size,
459 ELFW(ST_INFO)(sym_bind, sym_type), other,
460 sh_num, name);
462 return sym_index;
465 /* put relocation */
466 ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset,
467 int type, int symbol, addr_t addend)
469 char buf[256];
470 Section *sr;
471 ElfW_Rel *rel;
473 sr = s->reloc;
474 if (!sr) {
475 /* if no relocation section, create it */
476 snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
477 /* if the symtab is allocated, then we consider the relocation
478 are also */
479 sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
480 sr->sh_entsize = sizeof(ElfW_Rel);
481 sr->link = symtab;
482 sr->sh_info = s->sh_num;
483 s->reloc = sr;
485 rel = section_ptr_add(sr, sizeof(ElfW_Rel));
486 rel->r_offset = offset;
487 rel->r_info = ELFW(R_INFO)(symbol, type);
488 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
489 rel->r_addend = addend;
490 #else
491 if (addend)
492 tcc_error("non-zero addend on REL architecture");
493 #endif
496 ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
497 int type, int symbol)
499 put_elf_reloca(symtab, s, offset, type, symbol, 0);
502 /* put stab debug information */
504 ST_FUNC void put_stabs(const char *str, int type, int other, int desc,
505 unsigned long value)
507 Stab_Sym *sym;
509 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
510 if (str) {
511 sym->n_strx = put_elf_str(stabstr_section, str);
512 } else {
513 sym->n_strx = 0;
515 sym->n_type = type;
516 sym->n_other = other;
517 sym->n_desc = desc;
518 sym->n_value = value;
521 ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc,
522 unsigned long value, Section *sec, int sym_index)
524 put_stabs(str, type, other, desc, value);
525 put_elf_reloc(symtab_section, stab_section,
526 stab_section->data_offset - sizeof(unsigned int),
527 R_DATA_32, sym_index);
530 ST_FUNC void put_stabn(int type, int other, int desc, int value)
532 put_stabs(NULL, type, other, desc, value);
535 ST_FUNC void put_stabd(int type, int other, int desc)
537 put_stabs(NULL, type, other, desc, 0);
540 /* Browse each elem of type <type> in section <sec> starting at elem <startoff>
541 using variable <elem> */
542 #define for_each_elem(sec, startoff, elem, type) \
543 for (elem = (type *) sec->data + startoff; \
544 elem < (type *) (sec->data + sec->data_offset); elem++)
546 /* In an ELF file symbol table, the local symbols must appear below
547 the global and weak ones. Since TCC cannot sort it while generating
548 the code, we must do it after. All the relocation tables are also
549 modified to take into account the symbol table sorting */
550 static void sort_syms(TCCState *s1, Section *s)
552 int *old_to_new_syms;
553 ElfW(Sym) *new_syms;
554 int nb_syms, i;
555 ElfW(Sym) *p, *q;
556 ElfW_Rel *rel;
557 Section *sr;
558 int type, sym_index;
560 nb_syms = s->data_offset / sizeof(ElfW(Sym));
561 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
562 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
564 /* first pass for local symbols */
565 p = (ElfW(Sym) *)s->data;
566 q = new_syms;
567 for(i = 0; i < nb_syms; i++) {
568 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
569 old_to_new_syms[i] = q - new_syms;
570 *q++ = *p;
572 p++;
574 /* save the number of local symbols in section header */
575 s->sh_info = q - new_syms;
577 /* then second pass for non local symbols */
578 p = (ElfW(Sym) *)s->data;
579 for(i = 0; i < nb_syms; i++) {
580 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
581 old_to_new_syms[i] = q - new_syms;
582 *q++ = *p;
584 p++;
587 /* we copy the new symbols to the old */
588 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
589 tcc_free(new_syms);
591 /* now we modify all the relocations */
592 for(i = 1; i < s1->nb_sections; i++) {
593 sr = s1->sections[i];
594 if (sr->sh_type == SHT_RELX && sr->link == s) {
595 for_each_elem(sr, 0, rel, ElfW_Rel) {
596 sym_index = ELFW(R_SYM)(rel->r_info);
597 type = ELFW(R_TYPE)(rel->r_info);
598 sym_index = old_to_new_syms[sym_index];
599 rel->r_info = ELFW(R_INFO)(sym_index, type);
604 tcc_free(old_to_new_syms);
607 /* relocate common symbols in the .bss section */
608 ST_FUNC void relocate_common_syms(void)
610 ElfW(Sym) *sym;
611 unsigned long offset, align;
613 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
614 if (sym->st_shndx == SHN_COMMON) {
615 /* align symbol */
616 align = sym->st_value;
617 offset = bss_section->data_offset;
618 offset = (offset + align - 1) & -align;
619 sym->st_value = offset;
620 sym->st_shndx = bss_section->sh_num;
621 offset += sym->st_size;
622 bss_section->data_offset = offset;
627 /* relocate symbol table, resolve undefined symbols if do_resolve is
628 true and output error if undefined symbol. */
629 ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
631 ElfW(Sym) *sym, *esym;
632 int sym_bind, sh_num, sym_index;
633 const char *name;
635 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
636 sh_num = sym->st_shndx;
637 if (sh_num == SHN_UNDEF) {
638 name = (char *) strtab_section->data + sym->st_name;
639 /* Use ld.so to resolve symbol for us (for tcc -run) */
640 if (do_resolve) {
641 #if defined TCC_IS_NATIVE && !defined TCC_TARGET_PE
642 void *addr;
643 name = (char *) symtab_section->link->data + sym->st_name;
644 addr = dlsym(RTLD_DEFAULT, name);
645 if (addr) {
646 sym->st_value = (addr_t)addr;
647 #ifdef DEBUG_RELOC
648 printf ("relocate_sym: %s -> 0x%lx\n", name, sym->st_value);
649 #endif
650 goto found;
652 #endif
653 } else if (s1->dynsym) {
654 /* if dynamic symbol exist, then use it */
655 sym_index = find_elf_sym(s1->dynsym, name);
656 if (sym_index) {
657 esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
658 sym->st_value = esym->st_value;
659 goto found;
662 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
663 it */
664 if (!strcmp(name, "_fp_hw"))
665 goto found;
666 /* only weak symbols are accepted to be undefined. Their
667 value is zero */
668 sym_bind = ELFW(ST_BIND)(sym->st_info);
669 if (sym_bind == STB_WEAK) {
670 sym->st_value = 0;
671 } else {
672 tcc_error_noabort("undefined symbol '%s'", name);
674 } else if (sh_num < SHN_LORESERVE) {
675 /* add section base */
676 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
678 found: ;
682 /* relocate a given section (CPU dependent) by applying the relocations
683 in the associated relocation section */
684 ST_FUNC void relocate_section(TCCState *s1, Section *s)
686 Section *sr = s->reloc;
687 ElfW_Rel *rel;
688 ElfW(Sym) *sym;
689 int type, sym_index;
690 unsigned char *ptr;
691 addr_t val, addr;
692 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
693 ElfW_Rel *qrel = (ElfW_Rel *) sr->data; /* ptr to next reloc entry reused */
694 int esym_index;
695 #endif
697 for_each_elem(sr, 0, rel, ElfW_Rel) {
698 ptr = s->data + rel->r_offset;
700 sym_index = ELFW(R_SYM)(rel->r_info);
701 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
702 val = sym->st_value;
703 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
704 val += rel->r_addend;
705 #endif
706 type = ELFW(R_TYPE)(rel->r_info);
707 addr = s->sh_addr + rel->r_offset;
709 /* CPU specific */
710 switch(type) {
711 #if defined(TCC_TARGET_I386)
712 case R_386_32:
713 if (s1->output_type == TCC_OUTPUT_DLL) {
714 esym_index = s1->symtab_to_dynsym[sym_index];
715 qrel->r_offset = rel->r_offset;
716 if (esym_index) {
717 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
718 qrel++;
719 break;
720 } else {
721 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
722 qrel++;
725 write32le(ptr, read32le(ptr) + val);
726 break;
727 case R_386_PC32:
728 if (s1->output_type == TCC_OUTPUT_DLL) {
729 /* DLL relocation */
730 esym_index = s1->symtab_to_dynsym[sym_index];
731 if (esym_index) {
732 qrel->r_offset = rel->r_offset;
733 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
734 qrel++;
735 break;
738 write32le(ptr, read32le(ptr) + val - addr);
739 break;
740 case R_386_PLT32:
741 write32le(ptr, read32le(ptr) + val - addr);
742 break;
743 case R_386_GLOB_DAT:
744 case R_386_JMP_SLOT:
745 write32le(ptr, val);
746 break;
747 case R_386_GOTPC:
748 write32le(ptr, read32le(ptr) + s1->got->sh_addr - addr);
749 break;
750 case R_386_GOTOFF:
751 write32le(ptr, read32le(ptr) + val - s1->got->sh_addr);
752 break;
753 case R_386_GOT32:
754 case R_386_GOT32X:
755 /* we load the got offset */
756 write32le(ptr, read32le(ptr) + s1->sym_attrs[sym_index].got_offset);
757 break;
758 case R_386_16:
759 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
760 output_file:
761 tcc_error("can only produce 16-bit binary files");
763 write16le(ptr, read16le(ptr) + val);
764 break;
765 case R_386_PC16:
766 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
767 goto output_file;
768 write16le(ptr, read16le(ptr) + val - addr);
769 break;
771 #ifdef TCC_TARGET_PE
772 case R_386_RELATIVE: /* handled in pe_relocate_rva() */
773 break;
774 #endif
775 case R_386_COPY:
776 /* This reloction must copy initialized data from the library
777 to the program .bss segment. Currently made like for ARM
778 (to remove noise of defaukt case). Is this true?
780 break;
782 default:
783 fprintf(stderr,"FIXME: handle reloc type %d at %x [%p] to %x\n",
784 type, (unsigned)addr, ptr, (unsigned)val);
785 break;
786 #elif defined(TCC_TARGET_ARM)
787 case R_ARM_PC24:
788 case R_ARM_CALL:
789 case R_ARM_JUMP24:
790 case R_ARM_PLT32:
792 int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko;
793 x = (*(int *) ptr) & 0xffffff;
794 if (sym->st_shndx == SHN_UNDEF)
795 val = s1->plt->sh_addr;
796 #ifdef DEBUG_RELOC
797 printf ("reloc %d: x=0x%x val=0x%x ", type, x, val);
798 #endif
799 (*(int *)ptr) &= 0xff000000;
800 if (x & 0x800000)
801 x -= 0x1000000;
802 x <<= 2;
803 blx_avail = (TCC_ARM_VERSION >= 5);
804 is_thumb = val & 1;
805 is_bl = (*(unsigned *) ptr) >> 24 == 0xeb;
806 is_call = (type == R_ARM_CALL || (type == R_ARM_PC24 && is_bl));
807 x += val - addr;
808 #ifdef DEBUG_RELOC
809 printf (" newx=0x%x name=%s\n", x,
810 (char *) symtab_section->link->data + sym->st_name);
811 #endif
812 h = x & 2;
813 th_ko = (x & 3) && (!blx_avail || !is_call);
814 if (th_ko || x >= 0x2000000 || x < -0x2000000)
815 tcc_error("can't relocate value at %x,%d",addr, type);
816 x >>= 2;
817 x &= 0xffffff;
818 /* Only reached if blx is avail and it is a call */
819 if (is_thumb) {
820 x |= h << 24;
821 (*(int *)ptr) = 0xfa << 24; /* bl -> blx */
823 (*(int *) ptr) |= x;
825 break;
826 /* Since these relocations only concern Thumb-2 and blx instruction was
827 introduced before Thumb-2, we can assume blx is available and not
828 guard its use */
829 case R_ARM_THM_PC22:
830 case R_ARM_THM_JUMP24:
832 int x, hi, lo, s, j1, j2, i1, i2, imm10, imm11;
833 int to_thumb, is_call, to_plt, blx_bit = 1 << 12;
834 Section *plt;
836 /* weak reference */
837 if (sym->st_shndx == SHN_UNDEF &&
838 ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
839 break;
841 /* Get initial offset */
842 hi = (*(uint16_t *)ptr);
843 lo = (*(uint16_t *)(ptr+2));
844 s = (hi >> 10) & 1;
845 j1 = (lo >> 13) & 1;
846 j2 = (lo >> 11) & 1;
847 i1 = (j1 ^ s) ^ 1;
848 i2 = (j2 ^ s) ^ 1;
849 imm10 = hi & 0x3ff;
850 imm11 = lo & 0x7ff;
851 x = (s << 24) | (i1 << 23) | (i2 << 22) |
852 (imm10 << 12) | (imm11 << 1);
853 if (x & 0x01000000)
854 x -= 0x02000000;
856 /* Relocation infos */
857 to_thumb = val & 1;
858 plt = s1->plt;
859 to_plt = (val >= plt->sh_addr) &&
860 (val < plt->sh_addr + plt->data_offset);
861 is_call = (type == R_ARM_THM_PC22);
863 /* Compute final offset */
864 if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */
865 x -= 4;
866 x += val - addr;
867 if (!to_thumb && is_call) {
868 blx_bit = 0; /* bl -> blx */
869 x = (x + 3) & -4; /* Compute offset from aligned PC */
872 /* Check that relocation is possible
873 * offset must not be out of range
874 * if target is to be entered in arm mode:
875 - bit 1 must not set
876 - instruction must be a call (bl) or a jump to PLT */
877 if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
878 if (to_thumb || (val & 2) || (!is_call && !to_plt))
879 tcc_error("can't relocate value at %x,%d",addr, type);
881 /* Compute and store final offset */
882 s = (x >> 24) & 1;
883 i1 = (x >> 23) & 1;
884 i2 = (x >> 22) & 1;
885 j1 = s ^ (i1 ^ 1);
886 j2 = s ^ (i2 ^ 1);
887 imm10 = (x >> 12) & 0x3ff;
888 imm11 = (x >> 1) & 0x7ff;
889 (*(uint16_t *)ptr) = (uint16_t) ((hi & 0xf800) |
890 (s << 10) | imm10);
891 (*(uint16_t *)(ptr+2)) = (uint16_t) ((lo & 0xc000) |
892 (j1 << 13) | blx_bit | (j2 << 11) |
893 imm11);
895 break;
896 case R_ARM_MOVT_ABS:
897 case R_ARM_MOVW_ABS_NC:
899 int x, imm4, imm12;
900 if (type == R_ARM_MOVT_ABS)
901 val >>= 16;
902 imm12 = val & 0xfff;
903 imm4 = (val >> 12) & 0xf;
904 x = (imm4 << 16) | imm12;
905 if (type == R_ARM_THM_MOVT_ABS)
906 *(int *)ptr |= x;
907 else
908 *(int *)ptr += x;
910 break;
911 case R_ARM_THM_MOVT_ABS:
912 case R_ARM_THM_MOVW_ABS_NC:
914 int x, i, imm4, imm3, imm8;
915 if (type == R_ARM_THM_MOVT_ABS)
916 val >>= 16;
917 imm8 = val & 0xff;
918 imm3 = (val >> 8) & 0x7;
919 i = (val >> 11) & 1;
920 imm4 = (val >> 12) & 0xf;
921 x = (imm3 << 28) | (imm8 << 16) | (i << 10) | imm4;
922 if (type == R_ARM_THM_MOVT_ABS)
923 *(int *)ptr |= x;
924 else
925 *(int *)ptr += x;
927 break;
928 case R_ARM_PREL31:
930 int x;
931 x = (*(int *)ptr) & 0x7fffffff;
932 (*(int *)ptr) &= 0x80000000;
933 x = (x * 2) / 2;
934 x += val - addr;
935 if((x^(x>>1))&0x40000000)
936 tcc_error("can't relocate value at %x,%d",addr, type);
937 (*(int *)ptr) |= x & 0x7fffffff;
939 case R_ARM_ABS32:
940 *(int *)ptr += val;
941 break;
942 case R_ARM_REL32:
943 *(int *)ptr += val - addr;
944 break;
945 case R_ARM_GOTPC:
946 *(int *)ptr += s1->got->sh_addr - addr;
947 break;
948 case R_ARM_GOTOFF:
949 *(int *)ptr += val - s1->got->sh_addr;
950 break;
951 case R_ARM_GOT32:
952 /* we load the got offset */
953 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
954 break;
955 case R_ARM_COPY:
956 break;
957 case R_ARM_V4BX:
958 /* trade Thumb support for ARMv4 support */
959 if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
960 *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
961 break;
962 case R_ARM_GLOB_DAT:
963 case R_ARM_JUMP_SLOT:
964 *(addr_t *)ptr = val;
965 break;
966 case R_ARM_NONE:
967 /* Nothing to do. Normally used to indicate a dependency
968 on a certain symbol (like for exception handling under EABI). */
969 break;
970 #ifdef TCC_TARGET_PE
971 case R_ARM_RELATIVE: /* handled in pe_relocate_rva() */
972 break;
973 #endif
974 default:
975 fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
976 type, (unsigned)addr, ptr, (unsigned)val);
977 break;
978 #elif defined(TCC_TARGET_ARM64)
979 case R_AARCH64_ABS64:
980 write64le(ptr, val);
981 break;
982 case R_AARCH64_ABS32:
983 write32le(ptr, val);
984 break;
985 case R_AARCH64_PREL32:
986 write32le(ptr, val - addr);
987 break;
988 case R_AARCH64_MOVW_UABS_G0_NC:
989 write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
990 (val & 0xffff) << 5));
991 break;
992 case R_AARCH64_MOVW_UABS_G1_NC:
993 write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
994 (val >> 16 & 0xffff) << 5));
995 break;
996 case R_AARCH64_MOVW_UABS_G2_NC:
997 write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
998 (val >> 32 & 0xffff) << 5));
999 break;
1000 case R_AARCH64_MOVW_UABS_G3:
1001 write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
1002 (val >> 48 & 0xffff) << 5));
1003 break;
1004 case R_AARCH64_ADR_PREL_PG_HI21: {
1005 uint64_t off = (val >> 12) - (addr >> 12);
1006 if ((off + ((uint64_t)1 << 20)) >> 21)
1007 tcc_error("R_AARCH64_ADR_PREL_PG_HI21 relocation failed");
1008 write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
1009 (off & 0x1ffffc) << 3 | (off & 3) << 29));
1010 break;
1012 case R_AARCH64_ADD_ABS_LO12_NC:
1013 write32le(ptr, ((read32le(ptr) & 0xffc003ff) |
1014 (val & 0xfff) << 10));
1015 break;
1016 case R_AARCH64_JUMP26:
1017 case R_AARCH64_CALL26:
1018 /* This check must match the one in build_got_entries, testing
1019 if we really need a PLT slot. */
1020 if (sym->st_shndx == SHN_UNDEF ||
1021 s1->output_type == TCC_OUTPUT_MEMORY)
1022 /* We've put the PLT slot offset into r_addend when generating
1023 it, and that's what we must use as relocation value (adjusted
1024 by section offset of course). */
1025 val = s1->plt->sh_addr + rel->r_addend;
1026 #ifdef DEBUG_RELOC
1027 printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, val,
1028 (char *) symtab_section->link->data + sym->st_name);
1029 #endif
1030 if (((val - addr) + ((uint64_t)1 << 27)) & ~(uint64_t)0xffffffc)
1032 tcc_error("R_AARCH64_(JUMP|CALL)26 relocation failed (val=%lx, addr=%lx)", addr, val);
1034 write32le(ptr, (0x14000000 |
1035 (uint32_t)(type == R_AARCH64_CALL26) << 31 |
1036 ((val - addr) >> 2 & 0x3ffffff)));
1037 break;
1038 case R_AARCH64_ADR_GOT_PAGE: {
1039 uint64_t off =
1040 (((s1->got->sh_addr +
1041 s1->sym_attrs[sym_index].got_offset) >> 12) - (addr >> 12));
1042 if ((off + ((uint64_t)1 << 20)) >> 21)
1043 tcc_error("R_AARCH64_ADR_GOT_PAGE relocation failed");
1044 write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
1045 (off & 0x1ffffc) << 3 | (off & 3) << 29));
1046 break;
1048 case R_AARCH64_LD64_GOT_LO12_NC:
1049 write32le(ptr,
1050 ((read32le(ptr) & 0xfff803ff) |
1051 ((s1->got->sh_addr +
1052 s1->sym_attrs[sym_index].got_offset) & 0xff8) << 7));
1053 break;
1054 case R_AARCH64_COPY:
1055 break;
1056 case R_AARCH64_GLOB_DAT:
1057 case R_AARCH64_JUMP_SLOT:
1058 /* They don't need addend */
1059 #ifdef DEBUG_RELOC
1060 printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr,
1061 val - rel->r_addend,
1062 (char *) symtab_section->link->data + sym->st_name);
1063 #endif
1064 write64le(ptr, val - rel->r_addend);
1065 break;
1066 default:
1067 fprintf(stderr, "FIXME: handle reloc type %x at %x [%p] to %x\n",
1068 type, (unsigned)addr, ptr, (unsigned)val);
1069 break;
1070 #elif defined(TCC_TARGET_C67)
1071 case R_C60_32:
1072 *(int *)ptr += val;
1073 break;
1074 case R_C60LO16:
1076 uint32_t orig;
1078 /* put the low 16 bits of the absolute address
1079 add to what is already there */
1081 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
1082 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
1084 /* patch both at once - assumes always in pairs Low - High */
1086 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
1087 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
1089 break;
1090 case R_C60HI16:
1091 break;
1092 default:
1093 fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
1094 type, (unsigned)addr, ptr, (unsigned)val);
1095 break;
1096 #elif defined(TCC_TARGET_X86_64)
1097 case R_X86_64_64:
1098 if (s1->output_type == TCC_OUTPUT_DLL) {
1099 esym_index = s1->symtab_to_dynsym[sym_index];
1100 qrel->r_offset = rel->r_offset;
1101 if (esym_index) {
1102 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_64);
1103 qrel->r_addend = rel->r_addend;
1104 qrel++;
1105 break;
1106 } else {
1107 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
1108 qrel->r_addend = read64le(ptr) + val;
1109 qrel++;
1112 write64le(ptr, read64le(ptr) + val);
1113 break;
1114 case R_X86_64_32:
1115 case R_X86_64_32S:
1116 if (s1->output_type == TCC_OUTPUT_DLL) {
1117 /* XXX: this logic may depend on TCC's codegen
1118 now TCC uses R_X86_64_32 even for a 64bit pointer */
1119 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
1120 /* Use sign extension! */
1121 qrel->r_addend = (int)read32le(ptr) + val;
1122 qrel++;
1124 write32le(ptr, read32le(ptr) + val);
1125 break;
1127 case R_X86_64_PC32:
1128 if (s1->output_type == TCC_OUTPUT_DLL) {
1129 /* DLL relocation */
1130 esym_index = s1->symtab_to_dynsym[sym_index];
1131 if (esym_index) {
1132 qrel->r_offset = rel->r_offset;
1133 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
1134 /* Use sign extension! */
1135 qrel->r_addend = (int)read32le(ptr) + rel->r_addend;
1136 qrel++;
1137 break;
1140 goto plt32pc32;
1142 case R_X86_64_PLT32:
1143 /* We've put the PLT slot offset into r_addend when generating
1144 it, and that's what we must use as relocation value (adjusted
1145 by section offset of course). */
1146 val = s1->plt->sh_addr + rel->r_addend;
1147 /* fallthrough. */
1149 plt32pc32:
1151 long long diff;
1152 diff = (long long)val - addr;
1153 if (diff < -2147483648LL || diff > 2147483647LL) {
1154 tcc_error("internal error: relocation failed");
1156 write32le(ptr, read32le(ptr) + diff);
1158 break;
1159 case R_X86_64_GLOB_DAT:
1160 case R_X86_64_JUMP_SLOT:
1161 /* They don't need addend */
1162 write64le(ptr, val - rel->r_addend);
1163 break;
1164 case R_X86_64_GOTPCREL:
1165 case R_X86_64_GOTPCRELX:
1166 case R_X86_64_REX_GOTPCRELX:
1167 write32le(ptr, read32le(ptr) +
1168 (s1->got->sh_addr - addr +
1169 s1->sym_attrs[sym_index].got_offset - 4));
1170 break;
1171 case R_X86_64_GOTTPOFF:
1172 write32le(ptr, read32le(ptr) + val - s1->got->sh_addr);
1173 break;
1174 case R_X86_64_GOT32:
1175 /* we load the got offset */
1176 write32le(ptr, read32le(ptr) + s1->sym_attrs[sym_index].got_offset);
1177 break;
1178 #ifdef TCC_TARGET_PE
1179 case R_X86_64_RELATIVE: /* handled in pe_relocate_rva() */
1180 break;
1181 #endif
1183 #else
1184 #error unsupported processor
1185 #endif
1188 /* if the relocation is allocated, we change its symbol table */
1189 if (sr->sh_flags & SHF_ALLOC)
1190 sr->link = s1->dynsym;
1193 /* relocate relocation table in 'sr' */
1194 static void relocate_rel(TCCState *s1, Section *sr)
1196 Section *s;
1197 ElfW_Rel *rel;
1199 s = s1->sections[sr->sh_info];
1200 for_each_elem(sr, 0, rel, ElfW_Rel)
1201 rel->r_offset += s->sh_addr;
1204 /* count the number of dynamic relocations so that we can reserve
1205 their space */
1206 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
1208 ElfW_Rel *rel;
1209 int sym_index, esym_index, type, count;
1211 count = 0;
1212 for_each_elem(sr, 0, rel, ElfW_Rel) {
1213 sym_index = ELFW(R_SYM)(rel->r_info);
1214 type = ELFW(R_TYPE)(rel->r_info);
1215 switch(type) {
1216 #if defined(TCC_TARGET_I386)
1217 case R_386_32:
1218 #elif defined(TCC_TARGET_X86_64)
1219 case R_X86_64_32:
1220 case R_X86_64_32S:
1221 case R_X86_64_64:
1222 #endif
1223 count++;
1224 break;
1225 #if defined(TCC_TARGET_I386)
1226 case R_386_PC32:
1227 #elif defined(TCC_TARGET_X86_64)
1228 case R_X86_64_PC32:
1229 #endif
1230 esym_index = s1->symtab_to_dynsym[sym_index];
1231 if (esym_index)
1232 count++;
1233 break;
1234 default:
1235 break;
1238 if (count) {
1239 /* allocate the section */
1240 sr->sh_flags |= SHF_ALLOC;
1241 sr->sh_size = count * sizeof(ElfW_Rel);
1243 return count;
1246 static struct sym_attr *alloc_sym_attr(TCCState *s1, int index)
1248 int n;
1249 struct sym_attr *tab;
1251 if (index >= s1->nb_sym_attrs) {
1252 /* find immediately bigger power of 2 and reallocate array */
1253 n = 1;
1254 while (index >= n)
1255 n *= 2;
1256 tab = tcc_realloc(s1->sym_attrs, n * sizeof(*s1->sym_attrs));
1257 s1->sym_attrs = tab;
1258 memset(s1->sym_attrs + s1->nb_sym_attrs, 0,
1259 (n - s1->nb_sym_attrs) * sizeof(*s1->sym_attrs));
1260 s1->nb_sym_attrs = n;
1262 return &s1->sym_attrs[index];
1265 static void build_got(TCCState *s1)
1267 unsigned char *ptr;
1269 /* if no got, then create it */
1270 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
1271 s1->got->sh_entsize = 4;
1272 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
1273 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
1274 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
1275 #if PTR_SIZE == 4
1276 /* keep space for _DYNAMIC pointer, if present */
1277 write32le(ptr, 0);
1278 /* two dummy got entries */
1279 write32le(ptr + 4, 0);
1280 write32le(ptr + 8, 0);
1281 #else
1282 /* keep space for _DYNAMIC pointer, if present */
1283 write32le(ptr, 0);
1284 write32le(ptr + 4, 0);
1285 /* two dummy got entries */
1286 write32le(ptr + 8, 0);
1287 write32le(ptr + 12, 0);
1288 write32le(ptr + 16, 0);
1289 write32le(ptr + 20, 0);
1290 #endif
1293 /* put a got or plt entry corresponding to a symbol in symtab_section. 'size'
1294 and 'info' can be modifed if more precise info comes from the DLL.
1295 Returns offset of GOT or PLT slot. */
1296 static unsigned long put_got_entry(TCCState *s1,
1297 int reloc_type, unsigned long size, int info,
1298 int sym_index)
1300 int index, need_plt_entry;
1301 const char *name;
1302 ElfW(Sym) *sym;
1303 unsigned long offset;
1304 int *ptr;
1305 struct sym_attr *symattr;
1307 if (!s1->got)
1308 build_got(s1);
1310 need_plt_entry =
1311 #ifdef TCC_TARGET_X86_64
1312 (reloc_type == R_X86_64_JUMP_SLOT);
1313 #elif defined(TCC_TARGET_I386)
1314 (reloc_type == R_386_JMP_SLOT);
1315 #elif defined(TCC_TARGET_ARM)
1316 (reloc_type == R_ARM_JUMP_SLOT);
1317 #elif defined(TCC_TARGET_ARM64)
1318 (reloc_type == R_AARCH64_JUMP_SLOT);
1319 #else
1321 #endif
1323 if (need_plt_entry && !s1->plt) {
1324 /* add PLT */
1325 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1326 SHF_ALLOC | SHF_EXECINSTR);
1327 s1->plt->sh_entsize = 4;
1330 /* If a got/plt entry already exists for that symbol, no need to add one */
1331 if (sym_index < s1->nb_sym_attrs) {
1332 if (need_plt_entry && s1->sym_attrs[sym_index].plt_offset)
1333 return s1->sym_attrs[sym_index].plt_offset;
1334 else if (!need_plt_entry && s1->sym_attrs[sym_index].got_offset)
1335 return s1->sym_attrs[sym_index].got_offset;
1338 symattr = alloc_sym_attr(s1, sym_index);
1340 /* Only store the GOT offset if it's not generated for the PLT entry. */
1341 if (!need_plt_entry)
1342 symattr->got_offset = s1->got->data_offset;
1344 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1345 name = (char *) symtab_section->link->data + sym->st_name;
1346 offset = sym->st_value;
1347 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1348 if (need_plt_entry) {
1349 Section *plt;
1350 uint8_t *p;
1351 int modrm;
1352 unsigned long relofs;
1354 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1355 modrm = 0x25;
1356 #else
1357 /* if we build a DLL, we add a %ebx offset */
1358 if (s1->output_type == TCC_OUTPUT_DLL)
1359 modrm = 0xa3;
1360 else
1361 modrm = 0x25;
1362 #endif
1364 /* add a PLT entry */
1365 plt = s1->plt;
1366 if (plt->data_offset == 0) {
1367 /* first plt entry */
1368 p = section_ptr_add(plt, 16);
1369 p[0] = 0xff; /* pushl got + PTR_SIZE */
1370 p[1] = modrm + 0x10;
1371 write32le(p + 2, PTR_SIZE);
1372 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1373 p[7] = modrm;
1374 write32le(p + 8, PTR_SIZE * 2);
1377 /* The PLT slot refers to the relocation entry it needs
1378 via offset. The reloc entry is created below, so its
1379 offset is the current data_offset. */
1380 relofs = s1->got->reloc ? s1->got->reloc->data_offset : 0;
1381 symattr->plt_offset = plt->data_offset;
1382 p = section_ptr_add(plt, 16);
1383 p[0] = 0xff; /* jmp *(got + x) */
1384 p[1] = modrm;
1385 write32le(p + 2, s1->got->data_offset);
1386 p[6] = 0x68; /* push $xxx */
1387 #ifdef TCC_TARGET_X86_64
1388 /* On x86-64, the relocation is referred to by _index_. */
1389 write32le(p + 7, relofs / sizeof (ElfW_Rel));
1390 #else
1391 write32le(p + 7, relofs);
1392 #endif
1393 p[11] = 0xe9; /* jmp plt_start */
1394 write32le(p + 12, -(plt->data_offset));
1396 /* If this was an UNDEF symbol set the offset in the
1397 dynsymtab to the PLT slot, so that PC32 relocs to it
1398 can be resolved. */
1399 if (sym->st_shndx == SHN_UNDEF)
1400 offset = plt->data_offset - 16;
1402 #elif defined(TCC_TARGET_ARM)
1403 if (need_plt_entry) {
1404 Section *plt;
1405 uint8_t *p;
1407 /* if we build a DLL, we add a %ebx offset */
1408 if (s1->output_type == TCC_OUTPUT_DLL)
1409 tcc_error("DLLs unimplemented!");
1411 /* add a PLT entry */
1412 plt = s1->plt;
1413 if (plt->data_offset == 0) {
1414 /* first plt entry */
1415 p = section_ptr_add(plt, 16);
1416 write32le(p, 0xe52de004); /* push {lr} */
1417 write32le(p+4, 0xe59fe010); /* ldr lr, [pc, #16] */
1418 write32le(p+8, 0xe08fe00e); /* add lr, pc, lr */
1419 write32le(p+12, 0xe5bef008); /* ldr pc, [lr, #8]! */
1422 symattr->plt_offset = plt->data_offset;
1423 if (symattr->plt_thumb_stub) {
1424 p = section_ptr_add(plt, 20);
1425 write32le(p, 0x4778); /* bx pc */
1426 write32le(p+2, 0x46c0); /* nop */
1427 p += 4;
1428 } else
1429 p = section_ptr_add(plt, 16);
1430 write32le(p, 0xe59fc004); /* ldr ip, [pc, #4] ; GOT entry offset */
1431 write32le(p+4, 0xe08fc00c); /* add ip, pc, ip ; addr of GOT entry */
1432 write32le(p+8, 0xe59cf000); /* ldr pc, [ip] ; jump to GOT entry */
1433 write32le(p+12, s1->got->data_offset); /* GOT entry off once patched */
1435 /* the symbol is modified so that it will be relocated to
1436 the PLT */
1437 if (sym->st_shndx == SHN_UNDEF)
1438 offset = plt->data_offset - 16;
1440 #elif defined(TCC_TARGET_ARM64)
1441 if (need_plt_entry) {
1442 Section *plt;
1443 uint8_t *p;
1445 if (s1->output_type == TCC_OUTPUT_DLL)
1446 tcc_error("DLLs unimplemented!");
1448 plt = s1->plt;
1449 if (plt->data_offset == 0)
1450 section_ptr_add(plt, 32);
1451 symattr->plt_offset = plt->data_offset;
1452 p = section_ptr_add(plt, 16);
1453 write32le(p, s1->got->data_offset);
1454 write32le(p + 4, (uint64_t)s1->got->data_offset >> 32);
1456 if (sym->st_shndx == SHN_UNDEF)
1457 offset = plt->data_offset - 16;
1459 #elif defined(TCC_TARGET_C67)
1460 if (s1->dynsym) {
1461 tcc_error("C67 got not implemented");
1463 #else
1464 #error unsupported CPU
1465 #endif
1466 if (s1->dynsym) {
1467 /* XXX This might generate multiple syms for name. */
1468 index = put_elf_sym(s1->dynsym, offset,
1469 size, info, 0, sym->st_shndx, name);
1470 /* Create the relocation (it's against the GOT for PLT
1471 and GOT relocs). */
1472 put_elf_reloc(s1->dynsym, s1->got,
1473 s1->got->data_offset,
1474 reloc_type, index);
1475 } else {
1476 /* Without .dynsym (i.e. static link or memory output) we
1477 still need relocs against the generated got, so as to fill
1478 the entries with the symbol values (determined later). */
1479 put_elf_reloc(symtab_section, s1->got,
1480 s1->got->data_offset,
1481 reloc_type, sym_index);
1483 /* And now create the GOT slot itself. */
1484 ptr = section_ptr_add(s1->got, PTR_SIZE);
1485 *ptr = 0;
1486 if (need_plt_entry)
1487 return symattr->plt_offset;
1488 else
1489 return symattr->got_offset;
1492 /* build GOT and PLT entries */
1493 ST_FUNC void build_got_entries(TCCState *s1)
1495 Section *s;
1496 ElfW_Rel *rel;
1497 ElfW(Sym) *sym;
1498 int i, type, reloc_type, sym_index;
1500 for(i = 1; i < s1->nb_sections; i++) {
1501 s = s1->sections[i];
1502 if (s->sh_type != SHT_RELX)
1503 continue;
1504 /* no need to handle got relocations */
1505 if (s->link != symtab_section)
1506 continue;
1507 for_each_elem(s, 0, rel, ElfW_Rel) {
1508 type = ELFW(R_TYPE)(rel->r_info);
1509 switch(type) {
1510 #if defined(TCC_TARGET_I386)
1511 case R_386_GOT32:
1512 case R_386_GOT32X:
1513 case R_386_GOTOFF:
1514 case R_386_GOTPC:
1515 case R_386_PLT32:
1516 if (!s1->got)
1517 build_got(s1);
1518 if (type == R_386_GOT32 || type == R_386_GOT32X ||
1519 type == R_386_PLT32) {
1520 sym_index = ELFW(R_SYM)(rel->r_info);
1521 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1522 /* look at the symbol got offset. If none, then add one */
1523 if (type == R_386_GOT32 || type == R_386_GOT32X)
1524 reloc_type = R_386_GLOB_DAT;
1525 else
1526 reloc_type = R_386_JMP_SLOT;
1527 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1528 sym_index);
1530 break;
1531 #elif defined(TCC_TARGET_ARM)
1532 case R_ARM_PC24:
1533 case R_ARM_CALL:
1534 case R_ARM_JUMP24:
1535 case R_ARM_GOT32:
1536 case R_ARM_GOTOFF:
1537 case R_ARM_GOTPC:
1538 case R_ARM_PLT32:
1539 if (!s1->got)
1540 build_got(s1);
1541 sym_index = ELFW(R_SYM)(rel->r_info);
1542 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1543 if (type != R_ARM_GOTOFF && type != R_ARM_GOTPC
1544 && sym->st_shndx == SHN_UNDEF) {
1545 unsigned long ofs;
1546 /* look at the symbol got offset. If none, then add one */
1547 if (type == R_ARM_GOT32)
1548 reloc_type = R_ARM_GLOB_DAT;
1549 else
1550 reloc_type = R_ARM_JUMP_SLOT;
1551 ofs = put_got_entry(s1, reloc_type, sym->st_size,
1552 sym->st_info, sym_index);
1553 #ifdef DEBUG_RELOC
1554 printf ("maybegot: %s, %d, %d --> ofs=0x%x\n",
1555 (char *) symtab_section->link->data + sym->st_name,
1556 type, sym->st_shndx, ofs);
1557 #endif
1558 if (type != R_ARM_GOT32) {
1559 addr_t *ptr = (addr_t*)(s1->sections[s->sh_info]->data
1560 + rel->r_offset);
1561 /* x must be signed! */
1562 int x = *ptr & 0xffffff;
1563 x = (x << 8) >> 8;
1564 x <<= 2;
1565 x += ofs;
1566 x >>= 2;
1567 #ifdef DEBUG_RELOC
1568 printf ("insn=0x%x --> 0x%x (x==0x%x)\n", *ptr,
1569 (*ptr & 0xff000000) | x, x);
1570 #endif
1571 *ptr = (*ptr & 0xff000000) | x;
1574 break;
1575 case R_ARM_THM_JUMP24:
1576 sym_index = ELFW(R_SYM)(rel->r_info);
1577 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1578 /* We are relocating a jump from thumb code to arm code */
1579 if (sym->st_shndx != SHN_UNDEF && !(sym->st_value & 1)) {
1580 int index;
1581 uint8_t *p;
1582 char *name, buf[1024];
1583 Section *text_section;
1585 name = (char *) symtab_section->link->data + sym->st_name;
1586 text_section = s1->sections[sym->st_shndx];
1587 /* Modify reloc to target a thumb stub to switch to ARM */
1588 snprintf(buf, sizeof(buf), "%s_from_thumb", name);
1589 index = put_elf_sym(symtab_section,
1590 text_section->data_offset + 1,
1591 sym->st_size, sym->st_info, 0,
1592 sym->st_shndx, buf);
1593 rel->r_info = ELFW(R_INFO)(index, type);
1594 /* Create a thumb stub fonction to switch to ARM mode */
1595 put_elf_reloc(symtab_section, text_section,
1596 text_section->data_offset + 4, R_ARM_JUMP24,
1597 sym_index);
1598 p = section_ptr_add(text_section, 8);
1599 write32le(p, 0x4778); /* bx pc */
1600 write32le(p+2, 0x46c0); /* nop */
1601 write32le(p+4, 0xeafffffe); /* b $sym */
1603 #elif defined(TCC_TARGET_ARM64)
1604 //xx Other cases may be required here:
1605 case R_AARCH64_ADR_GOT_PAGE:
1606 case R_AARCH64_LD64_GOT_LO12_NC:
1607 if (!s1->got)
1608 build_got(s1);
1609 sym_index = ELFW(R_SYM)(rel->r_info);
1610 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1611 reloc_type = R_AARCH64_GLOB_DAT;
1612 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1613 sym_index);
1614 break;
1616 case R_AARCH64_JUMP26:
1617 case R_AARCH64_CALL26:
1618 if (!s1->got)
1619 build_got(s1);
1620 sym_index = ELFW(R_SYM)(rel->r_info);
1621 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1622 if (sym->st_shndx == SHN_UNDEF ||
1623 s1->output_type == TCC_OUTPUT_MEMORY) {
1624 unsigned long ofs;
1625 reloc_type = R_AARCH64_JUMP_SLOT;
1626 ofs = put_got_entry(s1, reloc_type, sym->st_size,
1627 sym->st_info, sym_index);
1628 /* We store the place of the generated PLT slot
1629 in our addend. */
1630 rel->r_addend += ofs;
1632 break;
1633 #elif defined(TCC_TARGET_C67)
1634 case R_C60_GOT32:
1635 case R_C60_GOTOFF:
1636 case R_C60_GOTPC:
1637 case R_C60_PLT32:
1638 if (!s1->got)
1639 build_got(s1);
1640 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1641 sym_index = ELFW(R_SYM)(rel->r_info);
1642 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1643 /* look at the symbol got offset. If none, then add one */
1644 if (type == R_C60_GOT32)
1645 reloc_type = R_C60_GLOB_DAT;
1646 else
1647 reloc_type = R_C60_JMP_SLOT;
1648 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1649 sym_index);
1651 break;
1652 #elif defined(TCC_TARGET_X86_64)
1653 case R_X86_64_GOT32:
1654 case R_X86_64_GOTTPOFF:
1655 case R_X86_64_GOTPCREL:
1656 case R_X86_64_GOTPCRELX:
1657 case R_X86_64_REX_GOTPCRELX:
1658 case R_X86_64_PLT32:
1659 sym_index = ELFW(R_SYM)(rel->r_info);
1660 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1661 if (type == R_X86_64_PLT32 &&
1662 ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT)
1664 rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32);
1665 break;
1668 if (!s1->got) {
1669 build_got(s1);
1670 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1672 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1673 type == R_X86_64_GOTPCRELX ||
1674 type == R_X86_64_REX_GOTPCRELX ||
1675 type == R_X86_64_PLT32) {
1676 unsigned long ofs;
1677 /* look at the symbol got offset. If none, then add one */
1678 if (type == R_X86_64_PLT32)
1679 reloc_type = R_X86_64_JUMP_SLOT;
1680 else
1681 reloc_type = R_X86_64_GLOB_DAT;
1682 ofs = put_got_entry(s1, reloc_type, sym->st_size,
1683 sym->st_info, sym_index);
1684 if (type == R_X86_64_PLT32)
1685 /* We store the place of the generated PLT slot
1686 in our addend. */
1687 rel->r_addend += ofs;
1689 break;
1690 #else
1691 #error unsupported CPU
1692 #endif
1693 default:
1694 break;
1700 ST_FUNC Section *new_symtab(TCCState *s1,
1701 const char *symtab_name, int sh_type, int sh_flags,
1702 const char *strtab_name,
1703 const char *hash_name, int hash_sh_flags)
1705 Section *symtab, *strtab, *hash;
1706 int *ptr, nb_buckets;
1708 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1709 symtab->sh_entsize = sizeof(ElfW(Sym));
1710 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1711 put_elf_str(strtab, "");
1712 symtab->link = strtab;
1713 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1715 nb_buckets = 1;
1717 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1718 hash->sh_entsize = sizeof(int);
1719 symtab->hash = hash;
1720 hash->link = symtab;
1722 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1723 ptr[0] = nb_buckets;
1724 ptr[1] = 1;
1725 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1726 return symtab;
1729 /* put dynamic tag */
1730 static void put_dt(Section *dynamic, int dt, addr_t val)
1732 ElfW(Dyn) *dyn;
1733 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1734 dyn->d_tag = dt;
1735 dyn->d_un.d_val = val;
1738 #ifndef TCC_TARGET_PE
1739 static void add_init_array_defines(TCCState *s1, const char *section_name)
1741 Section *s;
1742 long end_offset;
1743 char sym_start[1024];
1744 char sym_end[1024];
1746 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1747 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1749 s = find_section(s1, section_name);
1750 if (!s) {
1751 end_offset = 0;
1752 s = data_section;
1753 } else {
1754 end_offset = s->data_offset;
1757 add_elf_sym(symtab_section,
1758 0, 0,
1759 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1760 s->sh_num, sym_start);
1761 add_elf_sym(symtab_section,
1762 end_offset, 0,
1763 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1764 s->sh_num, sym_end);
1766 #endif
1768 static int tcc_add_support(TCCState *s1, const char *filename)
1770 char buf[1024];
1771 snprintf(buf, sizeof(buf), "%s/"TCC_ARCH_DIR"%s", s1->tcc_lib_path, filename);
1772 return tcc_add_file(s1, buf);
1775 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1777 #ifdef CONFIG_TCC_BCHECK
1778 addr_t *ptr;
1779 int sym_index;
1781 if (0 == s1->do_bounds_check)
1782 return;
1783 /* XXX: add an object file to do that */
1784 ptr = section_ptr_add(bounds_section, sizeof(*ptr));
1785 *ptr = 0;
1786 add_elf_sym(symtab_section, 0, 0,
1787 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1788 bounds_section->sh_num, "__bounds_start");
1789 /* pull bcheck.o from libtcc1.a */
1790 sym_index = add_elf_sym(symtab_section, 0, 0,
1791 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1792 SHN_UNDEF, "__bound_init");
1793 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1794 /* add 'call __bound_init()' in .init section */
1795 Section *init_section = find_section(s1, ".init");
1796 unsigned char *pinit = section_ptr_add(init_section, 5);
1797 pinit[0] = 0xe8;
1798 write32le(pinit + 1, -4);
1799 put_elf_reloc(symtab_section, init_section,
1800 init_section->data_offset - 4, R_386_PC32, sym_index);
1801 /* R_386_PC32 = R_X86_64_PC32 = 2 */
1803 #endif
1806 /* add tcc runtime libraries */
1807 ST_FUNC void tcc_add_runtime(TCCState *s1)
1809 tcc_add_bcheck(s1);
1810 tcc_add_pragma_libs(s1);
1811 /* add libc */
1812 if (!s1->nostdlib) {
1813 tcc_add_library_err(s1, "c");
1814 #ifdef CONFIG_USE_LIBGCC
1815 if (!s1->static_link) {
1816 tcc_add_file(s1, TCC_LIBGCC);
1818 #endif
1819 tcc_add_support(s1, "libtcc1.a");
1820 /* add crt end if not memory output */
1821 if (s1->output_type != TCC_OUTPUT_MEMORY)
1822 tcc_add_crt(s1, "crtn.o");
1826 /* add various standard linker symbols (must be done after the
1827 sections are filled (for example after allocating common
1828 symbols)) */
1829 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1831 char buf[1024];
1832 int i;
1833 Section *s;
1835 add_elf_sym(symtab_section,
1836 text_section->data_offset, 0,
1837 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1838 text_section->sh_num, "_etext");
1839 add_elf_sym(symtab_section,
1840 data_section->data_offset, 0,
1841 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1842 data_section->sh_num, "_edata");
1843 add_elf_sym(symtab_section,
1844 bss_section->data_offset, 0,
1845 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1846 bss_section->sh_num, "_end");
1847 #ifndef TCC_TARGET_PE
1848 /* horrible new standard ldscript defines */
1849 add_init_array_defines(s1, ".preinit_array");
1850 add_init_array_defines(s1, ".init_array");
1851 add_init_array_defines(s1, ".fini_array");
1852 #endif
1854 /* add start and stop symbols for sections whose name can be
1855 expressed in C */
1856 for(i = 1; i < s1->nb_sections; i++) {
1857 s = s1->sections[i];
1858 if (s->sh_type == SHT_PROGBITS &&
1859 (s->sh_flags & SHF_ALLOC)) {
1860 const char *p;
1861 int ch;
1863 /* check if section name can be expressed in C */
1864 p = s->name;
1865 for(;;) {
1866 ch = *p;
1867 if (!ch)
1868 break;
1869 if (!isid(ch) && !isnum(ch))
1870 goto next_sec;
1871 p++;
1873 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1874 add_elf_sym(symtab_section,
1875 0, 0,
1876 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1877 s->sh_num, buf);
1878 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1879 add_elf_sym(symtab_section,
1880 s->data_offset, 0,
1881 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1882 s->sh_num, buf);
1884 next_sec: ;
1888 static void tcc_output_binary(TCCState *s1, FILE *f,
1889 const int *sec_order)
1891 Section *s;
1892 int i, offset, size;
1894 offset = 0;
1895 for(i=1;i<s1->nb_sections;i++) {
1896 s = s1->sections[sec_order[i]];
1897 if (s->sh_type != SHT_NOBITS &&
1898 (s->sh_flags & SHF_ALLOC)) {
1899 while (offset < s->sh_offset) {
1900 fputc(0, f);
1901 offset++;
1903 size = s->sh_size;
1904 fwrite(s->data, 1, size, f);
1905 offset += size;
1910 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1911 #define HAVE_PHDR 1
1912 #define EXTRA_RELITEMS 14
1914 /* move the relocation value from .dynsym to .got */
1915 static void patch_dynsym_undef(TCCState *s1, Section *s)
1917 uint32_t *gotd = (void *)s1->got->data;
1918 ElfW(Sym) *sym;
1920 gotd += 3; /* dummy entries in .got */
1921 /* relocate symbols in .dynsym */
1922 for_each_elem(s, 1, sym, ElfW(Sym)) {
1923 if (sym->st_shndx == SHN_UNDEF) {
1924 *gotd++ = sym->st_value + 6; /* XXX 6 is magic ? */
1925 sym->st_value = 0;
1929 #else
1930 #define HAVE_PHDR 1
1931 #define EXTRA_RELITEMS 9
1933 /* zero plt offsets of weak symbols in .dynsym */
1934 static void patch_dynsym_undef(TCCState *s1, Section *s)
1936 ElfW(Sym) *sym;
1938 for_each_elem(s, 1, sym, ElfW(Sym))
1939 if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
1940 sym->st_value = 0;
1942 #endif
1944 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1946 int sym_index = ELFW(R_SYM) (rel->r_info);
1947 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1948 unsigned long offset;
1950 if (sym_index >= s1->nb_sym_attrs)
1951 return;
1952 offset = s1->sym_attrs[sym_index].got_offset;
1953 section_reserve(s1->got, offset + PTR_SIZE);
1954 #ifdef TCC_TARGET_X86_64
1955 /* only works for x86-64 */
1956 write32le(s1->got->data + offset + 4, sym->st_value >> 32);
1957 #endif
1958 write32le(s1->got->data + offset, sym->st_value & 0xffffffff);
1961 /* Perform relocation to GOT or PLT entries */
1962 ST_FUNC void fill_got(TCCState *s1)
1964 Section *s;
1965 ElfW_Rel *rel;
1966 int i;
1968 for(i = 1; i < s1->nb_sections; i++) {
1969 s = s1->sections[i];
1970 if (s->sh_type != SHT_RELX)
1971 continue;
1972 /* no need to handle got relocations */
1973 if (s->link != symtab_section)
1974 continue;
1975 for_each_elem(s, 0, rel, ElfW_Rel) {
1976 switch (ELFW(R_TYPE) (rel->r_info)) {
1977 case R_X86_64_GOT32:
1978 case R_X86_64_GOTPCREL:
1979 case R_X86_64_GOTPCRELX:
1980 case R_X86_64_REX_GOTPCRELX:
1981 case R_X86_64_PLT32:
1982 fill_got_entry(s1, rel);
1983 break;
1989 /* Bind symbols of executable: resolve undefined symbols from exported symbols
1990 in shared libraries and export non local defined symbols to shared libraries
1991 if -rdynamic switch was given on command line */
1992 static void bind_exe_dynsyms(TCCState *s1)
1994 const char *name;
1995 int sym_index, index;
1996 ElfW(Sym) *sym, *esym;
1997 int type;
1999 /* Resolve undefined symbols from dynamic symbols. When there is a match:
2000 - if STT_FUNC or STT_GNU_IFUNC symbol -> add it in PLT
2001 - if STT_OBJECT symbol -> add it in .bss section with suitable reloc */
2002 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
2003 if (sym->st_shndx == SHN_UNDEF) {
2004 name = (char *) symtab_section->link->data + sym->st_name;
2005 sym_index = find_elf_sym(s1->dynsymtab_section, name);
2006 if (sym_index) {
2007 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
2008 type = ELFW(ST_TYPE)(esym->st_info);
2009 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
2010 /* Indirect functions shall have STT_FUNC type in executable
2011 * dynsym section. Indeed, a dlsym call following a lazy
2012 * resolution would pick the symbol value from the
2013 * executable dynsym entry which would contain the address
2014 * of the function wanted by the caller of dlsym instead of
2015 * the address of the function that would return that
2016 * address */
2017 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
2018 ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC),
2019 sym - (ElfW(Sym) *)symtab_section->data);
2020 } else if (type == STT_OBJECT) {
2021 unsigned long offset;
2022 ElfW(Sym) *dynsym;
2023 offset = bss_section->data_offset;
2024 /* XXX: which alignment ? */
2025 offset = (offset + 16 - 1) & -16;
2026 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
2027 esym->st_info, 0, bss_section->sh_num,
2028 name);
2029 /* Ensure R_COPY works for weak symbol aliases */
2030 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
2031 for_each_elem(s1->dynsymtab_section, 1, dynsym, ElfW(Sym)) {
2032 if ((dynsym->st_value == esym->st_value)
2033 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
2034 char *dynname = (char *) s1->dynsymtab_section->link->data
2035 + dynsym->st_name;
2036 put_elf_sym(s1->dynsym, offset, dynsym->st_size,
2037 dynsym->st_info, 0,
2038 bss_section->sh_num, dynname);
2039 break;
2043 put_elf_reloc(s1->dynsym, bss_section,
2044 offset, R_COPY, index);
2045 offset += esym->st_size;
2046 bss_section->data_offset = offset;
2048 } else {
2049 /* STB_WEAK undefined symbols are accepted */
2050 /* XXX: _fp_hw seems to be part of the ABI, so we ignore it */
2051 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
2052 !strcmp(name, "_fp_hw")) {
2053 } else {
2054 tcc_error_noabort("undefined symbol '%s'", name);
2057 } else if (s1->rdynamic && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2058 /* if -rdynamic option, then export all non local symbols */
2059 name = (char *) symtab_section->link->data + sym->st_name;
2060 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, sym->st_info,
2061 0, sym->st_shndx, name);
2066 /* Bind symbols of libraries: export non local symbols of executable that
2067 resolve undefined symbols of shared libraries */
2068 static void bind_libs_dynsyms(TCCState *s1)
2070 const char *name;
2071 int sym_index;
2072 ElfW(Sym) *sym, *esym;
2074 /* now look at unresolved dynamic symbols and export
2075 corresponding symbol */
2076 for_each_elem(s1->dynsymtab_section, 1, esym, ElfW(Sym)) {
2077 name = (char *) s1->dynsymtab_section->link->data + esym->st_name;
2078 sym_index = find_elf_sym(symtab_section, name);
2079 if (sym_index) {
2080 /* XXX: avoid adding a symbol if already present because of
2081 -rdynamic ? */
2082 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2083 if (sym->st_shndx != SHN_UNDEF)
2084 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
2085 sym->st_info, 0, sym->st_shndx, name);
2086 } else if (esym->st_shndx == SHN_UNDEF) {
2087 /* weak symbols can stay undefined */
2088 if (ELFW(ST_BIND)(esym->st_info) != STB_WEAK)
2089 tcc_warning("undefined dynamic symbol '%s'", name);
2094 /* Export all non local symbols (for shared libraries) */
2095 static void export_global_syms(TCCState *s1)
2097 int nb_syms, dynindex, index;
2098 const char *name;
2099 ElfW(Sym) *sym;
2101 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
2102 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
2103 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
2104 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2105 name = (char *) symtab_section->link->data + sym->st_name;
2106 dynindex = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
2107 sym->st_info, 0, sym->st_shndx, name);
2108 index = sym - (ElfW(Sym) *) symtab_section->data;
2109 s1->symtab_to_dynsym[index] = dynindex;
2114 /* relocate the PLT: compute addresses and offsets in the PLT now that final
2115 address for PLT and GOT are known (see fill_program_header) */
2116 ST_FUNC void relocate_plt(TCCState *s1)
2118 uint8_t *p, *p_end;
2120 if (!s1->plt)
2121 return;
2123 p = s1->plt->data;
2124 p_end = p + s1->plt->data_offset;
2125 if (p < p_end) {
2126 #if defined(TCC_TARGET_I386)
2127 write32le(p + 2, read32le(p + 2) + s1->got->sh_addr);
2128 write32le(p + 8, read32le(p + 8) + s1->got->sh_addr);
2129 p += 16;
2130 while (p < p_end) {
2131 write32le(p + 2, read32le(p + 2) + s1->got->sh_addr);
2132 p += 16;
2134 #elif defined(TCC_TARGET_X86_64)
2135 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
2136 write32le(p + 2, read32le(p + 2) + x);
2137 write32le(p + 8, read32le(p + 8) + x - 6);
2138 p += 16;
2139 while (p < p_end) {
2140 write32le(p + 2, read32le(p + 2) + x + s1->plt->data - p);
2141 p += 16;
2143 #elif defined(TCC_TARGET_ARM)
2144 int x;
2145 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
2146 p += 16;
2147 while (p < p_end) {
2148 if (read32le(p) == 0x46c04778) /* PLT Thumb stub present */
2149 p += 4;
2150 write32le(p + 12, x + read32le(p + 12) + s1->plt->data - p);
2151 p += 16;
2153 #elif defined(TCC_TARGET_ARM64)
2154 uint64_t plt = s1->plt->sh_addr;
2155 uint64_t got = s1->got->sh_addr;
2156 uint64_t off = (got >> 12) - (plt >> 12);
2157 if ((off + ((uint32_t)1 << 20)) >> 21)
2158 tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", off, got, plt);
2159 write32le(p, 0xa9bf7bf0); // stp x16,x30,[sp,#-16]!
2160 write32le(p + 4, (0x90000010 | // adrp x16,...
2161 (off & 0x1ffffc) << 3 | (off & 3) << 29));
2162 write32le(p + 8, (0xf9400211 | // ldr x17,[x16,#...]
2163 (got & 0xff8) << 7));
2164 write32le(p + 12, (0x91000210 | // add x16,x16,#...
2165 (got & 0xfff) << 10));
2166 write32le(p + 16, 0xd61f0220); // br x17
2167 write32le(p + 20, 0xd503201f); // nop
2168 write32le(p + 24, 0xd503201f); // nop
2169 write32le(p + 28, 0xd503201f); // nop
2170 p += 32;
2171 while (p < p_end) {
2172 uint64_t pc = plt + (p - s1->plt->data);
2173 uint64_t addr = got + read64le(p);
2174 uint64_t off = (addr >> 12) - (pc >> 12);
2175 if ((off + ((uint32_t)1 << 20)) >> 21)
2176 tcc_error("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", off, addr, pc);
2177 write32le(p, (0x90000010 | // adrp x16,...
2178 (off & 0x1ffffc) << 3 | (off & 3) << 29));
2179 write32le(p + 4, (0xf9400211 | // ldr x17,[x16,#...]
2180 (addr & 0xff8) << 7));
2181 write32le(p + 8, (0x91000210 | // add x16,x16,#...
2182 (addr & 0xfff) << 10));
2183 write32le(p + 12, 0xd61f0220); // br x17
2184 p += 16;
2186 #elif defined(TCC_TARGET_C67)
2187 /* XXX: TODO */
2188 #else
2189 #error unsupported CPU
2190 #endif
2194 /* Allocate strings for section names and decide if an unallocated section
2195 should be output.
2197 NOTE: the strsec section comes last, so its size is also correct ! */
2198 static void alloc_sec_names(TCCState *s1, int file_type, Section *strsec)
2200 int i;
2201 Section *s;
2203 /* Allocate strings for section names */
2204 for(i = 1; i < s1->nb_sections; i++) {
2205 s = s1->sections[i];
2206 s->sh_name = put_elf_str(strsec, s->name);
2207 /* when generating a DLL, we include relocations but we may
2208 patch them */
2209 if (file_type == TCC_OUTPUT_DLL &&
2210 s->sh_type == SHT_RELX &&
2211 !(s->sh_flags & SHF_ALLOC)) {
2212 /* gr: avoid bogus relocs for empty (debug) sections */
2213 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
2214 prepare_dynamic_rel(s1, s);
2215 else if (s1->do_debug)
2216 s->sh_size = s->data_offset;
2217 } else if (s1->do_debug ||
2218 file_type == TCC_OUTPUT_OBJ ||
2219 (s->sh_flags & SHF_ALLOC) ||
2220 i == (s1->nb_sections - 1)) {
2221 /* we output all sections if debug or object file */
2222 s->sh_size = s->data_offset;
2227 /* Info to be copied in dynamic section */
2228 struct dyn_inf {
2229 Section *dynamic;
2230 Section *dynstr;
2231 unsigned long dyn_rel_off;
2232 addr_t rel_addr;
2233 addr_t rel_size;
2234 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2235 addr_t bss_addr;
2236 addr_t bss_size;
2237 #endif
2240 /* Assign sections to segments and decide how are sections laid out when loaded
2241 in memory. This function also fills corresponding program headers. */
2242 static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
2243 Section *interp, Section* strsec,
2244 struct dyn_inf *dyninf, int *sec_order)
2246 int i, j, k, file_type, sh_order_index, file_offset;
2247 unsigned long s_align;
2248 long long tmp;
2249 addr_t addr;
2250 ElfW(Phdr) *ph;
2251 Section *s;
2253 file_type = s1->output_type;
2254 sh_order_index = 1;
2255 file_offset = 0;
2256 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
2257 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2258 s_align = ELF_PAGE_SIZE;
2259 if (s1->section_align)
2260 s_align = s1->section_align;
2262 if (phnum > 0) {
2263 if (s1->has_text_addr) {
2264 int a_offset, p_offset;
2265 addr = s1->text_addr;
2266 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
2267 ELF_PAGE_SIZE */
2268 a_offset = (int) (addr & (s_align - 1));
2269 p_offset = file_offset & (s_align - 1);
2270 if (a_offset < p_offset)
2271 a_offset += s_align;
2272 file_offset += (a_offset - p_offset);
2273 } else {
2274 if (file_type == TCC_OUTPUT_DLL)
2275 addr = 0;
2276 else
2277 addr = ELF_START_ADDR;
2278 /* compute address after headers */
2279 addr += (file_offset & (s_align - 1));
2282 ph = &phdr[0];
2283 /* Leave one program headers for the program interpreter and one for
2284 the program header table itself if needed. These are done later as
2285 they require section layout to be done first. */
2286 if (interp)
2287 ph += 1 + HAVE_PHDR;
2289 /* dynamic relocation table information, for .dynamic section */
2290 dyninf->rel_addr = dyninf->rel_size = 0;
2291 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2292 dyninf->bss_addr = dyninf->bss_size = 0;
2293 #endif
2295 for(j = 0; j < 2; j++) {
2296 ph->p_type = PT_LOAD;
2297 if (j == 0)
2298 ph->p_flags = PF_R | PF_X;
2299 else
2300 ph->p_flags = PF_R | PF_W;
2301 ph->p_align = s_align;
2303 /* Decide the layout of sections loaded in memory. This must
2304 be done before program headers are filled since they contain
2305 info about the layout. We do the following ordering: interp,
2306 symbol tables, relocations, progbits, nobits */
2307 /* XXX: do faster and simpler sorting */
2308 for(k = 0; k < 5; k++) {
2309 for(i = 1; i < s1->nb_sections; i++) {
2310 s = s1->sections[i];
2311 /* compute if section should be included */
2312 if (j == 0) {
2313 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
2314 SHF_ALLOC)
2315 continue;
2316 } else {
2317 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
2318 (SHF_ALLOC | SHF_WRITE))
2319 continue;
2321 if (s == interp) {
2322 if (k != 0)
2323 continue;
2324 } else if (s->sh_type == SHT_DYNSYM ||
2325 s->sh_type == SHT_STRTAB ||
2326 s->sh_type == SHT_HASH) {
2327 if (k != 1)
2328 continue;
2329 } else if (s->sh_type == SHT_RELX) {
2330 if (k != 2)
2331 continue;
2332 } else if (s->sh_type == SHT_NOBITS) {
2333 if (k != 4)
2334 continue;
2335 } else {
2336 if (k != 3)
2337 continue;
2339 sec_order[sh_order_index++] = i;
2341 /* section matches: we align it and add its size */
2342 tmp = addr;
2343 addr = (addr + s->sh_addralign - 1) &
2344 ~(s->sh_addralign - 1);
2345 file_offset += (int) ( addr - tmp );
2346 s->sh_offset = file_offset;
2347 s->sh_addr = addr;
2349 /* update program header infos */
2350 if (ph->p_offset == 0) {
2351 ph->p_offset = file_offset;
2352 ph->p_vaddr = addr;
2353 ph->p_paddr = ph->p_vaddr;
2355 /* update dynamic relocation infos */
2356 if (s->sh_type == SHT_RELX) {
2357 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2358 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) {
2359 dyninf->rel_addr = addr;
2360 dyninf->rel_size += s->sh_size; /* XXX only first rel. */
2362 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) {
2363 dyninf->bss_addr = addr;
2364 dyninf->bss_size = s->sh_size; /* XXX only first rel. */
2366 #else
2367 if (dyninf->rel_size == 0)
2368 dyninf->rel_addr = addr;
2369 dyninf->rel_size += s->sh_size;
2370 #endif
2372 addr += s->sh_size;
2373 if (s->sh_type != SHT_NOBITS)
2374 file_offset += s->sh_size;
2377 if (j == 0) {
2378 /* Make the first PT_LOAD segment include the program
2379 headers itself (and the ELF header as well), it'll
2380 come out with same memory use but will make various
2381 tools like binutils strip work better. */
2382 ph->p_offset &= ~(ph->p_align - 1);
2383 ph->p_vaddr &= ~(ph->p_align - 1);
2384 ph->p_paddr &= ~(ph->p_align - 1);
2386 ph->p_filesz = file_offset - ph->p_offset;
2387 ph->p_memsz = addr - ph->p_vaddr;
2388 ph++;
2389 if (j == 0) {
2390 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2391 /* if in the middle of a page, we duplicate the page in
2392 memory so that one copy is RX and the other is RW */
2393 if ((addr & (s_align - 1)) != 0)
2394 addr += s_align;
2395 } else {
2396 addr = (addr + s_align - 1) & ~(s_align - 1);
2397 file_offset = (file_offset + s_align - 1) & ~(s_align - 1);
2403 /* all other sections come after */
2404 for(i = 1; i < s1->nb_sections; i++) {
2405 s = s1->sections[i];
2406 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2407 continue;
2408 sec_order[sh_order_index++] = i;
2410 file_offset = (file_offset + s->sh_addralign - 1) &
2411 ~(s->sh_addralign - 1);
2412 s->sh_offset = file_offset;
2413 if (s->sh_type != SHT_NOBITS)
2414 file_offset += s->sh_size;
2417 return file_offset;
2420 static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp,
2421 Section *dynamic)
2423 ElfW(Phdr) *ph;
2425 /* if interpreter, then add corresponding program header */
2426 if (interp) {
2427 ph = &phdr[0];
2429 if (HAVE_PHDR)
2431 int len = phnum * sizeof(ElfW(Phdr));
2433 ph->p_type = PT_PHDR;
2434 ph->p_offset = sizeof(ElfW(Ehdr));
2435 ph->p_vaddr = interp->sh_addr - len;
2436 ph->p_paddr = ph->p_vaddr;
2437 ph->p_filesz = ph->p_memsz = len;
2438 ph->p_flags = PF_R | PF_X;
2439 ph->p_align = 4; /* interp->sh_addralign; */
2440 ph++;
2443 ph->p_type = PT_INTERP;
2444 ph->p_offset = interp->sh_offset;
2445 ph->p_vaddr = interp->sh_addr;
2446 ph->p_paddr = ph->p_vaddr;
2447 ph->p_filesz = interp->sh_size;
2448 ph->p_memsz = interp->sh_size;
2449 ph->p_flags = PF_R;
2450 ph->p_align = interp->sh_addralign;
2453 /* if dynamic section, then add corresponding program header */
2454 if (dynamic) {
2455 ph = &phdr[phnum - 1];
2457 ph->p_type = PT_DYNAMIC;
2458 ph->p_offset = dynamic->sh_offset;
2459 ph->p_vaddr = dynamic->sh_addr;
2460 ph->p_paddr = ph->p_vaddr;
2461 ph->p_filesz = dynamic->sh_size;
2462 ph->p_memsz = dynamic->sh_size;
2463 ph->p_flags = PF_R | PF_W;
2464 ph->p_align = dynamic->sh_addralign;
2468 /* Fill the dynamic section with tags describing the address and size of
2469 sections */
2470 static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
2472 Section *dynamic;
2474 dynamic = dyninf->dynamic;
2476 /* put dynamic section entries */
2477 dynamic->data_offset = dyninf->dyn_rel_off;
2478 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
2479 put_dt(dynamic, DT_STRTAB, dyninf->dynstr->sh_addr);
2480 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2481 put_dt(dynamic, DT_STRSZ, dyninf->dynstr->data_offset);
2482 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2483 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
2484 put_dt(dynamic, DT_RELA, dyninf->rel_addr);
2485 put_dt(dynamic, DT_RELASZ, dyninf->rel_size);
2486 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2487 #else
2488 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2489 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2490 put_dt(dynamic, DT_PLTRELSZ, dyninf->rel_size);
2491 put_dt(dynamic, DT_JMPREL, dyninf->rel_addr);
2492 put_dt(dynamic, DT_PLTREL, DT_REL);
2493 put_dt(dynamic, DT_REL, dyninf->bss_addr);
2494 put_dt(dynamic, DT_RELSZ, dyninf->bss_size);
2495 #else
2496 put_dt(dynamic, DT_REL, dyninf->rel_addr);
2497 put_dt(dynamic, DT_RELSZ, dyninf->rel_size);
2498 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2499 #endif
2500 #endif
2501 if (s1->do_debug)
2502 put_dt(dynamic, DT_DEBUG, 0);
2503 put_dt(dynamic, DT_NULL, 0);
2506 /* Relocate remaining sections and symbols (that is those not related to
2507 dynamic linking) */
2508 static int final_sections_reloc(TCCState *s1)
2510 int i;
2511 Section *s;
2513 relocate_syms(s1, 0);
2515 if (s1->nb_errors != 0)
2516 return -1;
2518 /* relocate sections */
2519 /* XXX: ignore sections with allocated relocations ? */
2520 for(i = 1; i < s1->nb_sections; i++) {
2521 s = s1->sections[i];
2522 #ifdef TCC_TARGET_I386
2523 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
2524 /* On X86 gdb 7.3 works in any case but gdb 6.6 will crash if SHF_ALLOC
2525 checking is removed */
2526 #else
2527 if (s->reloc && s != s1->got)
2528 /* On X86_64 gdb 7.3 will crash if SHF_ALLOC checking is present */
2529 #endif
2530 relocate_section(s1, s);
2533 /* relocate relocation entries if the relocation tables are
2534 allocated in the executable */
2535 for(i = 1; i < s1->nb_sections; i++) {
2536 s = s1->sections[i];
2537 if ((s->sh_flags & SHF_ALLOC) &&
2538 s->sh_type == SHT_RELX) {
2539 relocate_rel(s1, s);
2542 return 0;
2545 /* Create an ELF file on disk.
2546 This function handle ELF specific layout requirements */
2547 static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
2548 int file_offset, int *sec_order)
2550 int i, shnum, offset, size, file_type;
2551 Section *s;
2552 ElfW(Ehdr) ehdr;
2553 ElfW(Shdr) shdr, *sh;
2555 file_type = s1->output_type;
2556 shnum = s1->nb_sections;
2558 memset(&ehdr, 0, sizeof(ehdr));
2560 if (phnum > 0) {
2561 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2562 ehdr.e_phnum = phnum;
2563 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2566 /* align to 4 */
2567 file_offset = (file_offset + 3) & -4;
2569 /* fill header */
2570 ehdr.e_ident[0] = ELFMAG0;
2571 ehdr.e_ident[1] = ELFMAG1;
2572 ehdr.e_ident[2] = ELFMAG2;
2573 ehdr.e_ident[3] = ELFMAG3;
2574 ehdr.e_ident[4] = ELFCLASSW;
2575 ehdr.e_ident[5] = ELFDATA2LSB;
2576 ehdr.e_ident[6] = EV_CURRENT;
2577 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2578 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2579 #endif
2580 #ifdef TCC_TARGET_ARM
2581 #ifdef TCC_ARM_EABI
2582 ehdr.e_ident[EI_OSABI] = 0;
2583 ehdr.e_flags = EF_ARM_EABI_VER4;
2584 if (file_type == TCC_OUTPUT_EXE || file_type == TCC_OUTPUT_DLL)
2585 ehdr.e_flags |= EF_ARM_HASENTRY;
2586 if (s1->float_abi == ARM_HARD_FLOAT)
2587 ehdr.e_flags |= EF_ARM_VFP_FLOAT;
2588 else
2589 ehdr.e_flags |= EF_ARM_SOFT_FLOAT;
2590 #else
2591 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2592 #endif
2593 #endif
2594 switch(file_type) {
2595 default:
2596 case TCC_OUTPUT_EXE:
2597 ehdr.e_type = ET_EXEC;
2598 ehdr.e_entry = get_elf_sym_addr(s1, "_start", 1);
2599 break;
2600 case TCC_OUTPUT_DLL:
2601 ehdr.e_type = ET_DYN;
2602 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2603 break;
2604 case TCC_OUTPUT_OBJ:
2605 ehdr.e_type = ET_REL;
2606 break;
2608 ehdr.e_machine = EM_TCC_TARGET;
2609 ehdr.e_version = EV_CURRENT;
2610 ehdr.e_shoff = file_offset;
2611 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2612 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2613 ehdr.e_shnum = shnum;
2614 ehdr.e_shstrndx = shnum - 1;
2616 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2617 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2618 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2620 sort_syms(s1, symtab_section);
2621 for(i = 1; i < s1->nb_sections; i++) {
2622 s = s1->sections[sec_order[i]];
2623 if (s->sh_type != SHT_NOBITS) {
2624 if (s->sh_type == SHT_DYNSYM)
2625 patch_dynsym_undef(s1, s);
2626 while (offset < s->sh_offset) {
2627 fputc(0, f);
2628 offset++;
2630 size = s->sh_size;
2631 if (size)
2632 fwrite(s->data, 1, size, f);
2633 offset += size;
2637 /* output section headers */
2638 while (offset < ehdr.e_shoff) {
2639 fputc(0, f);
2640 offset++;
2643 for(i = 0; i < s1->nb_sections; i++) {
2644 sh = &shdr;
2645 memset(sh, 0, sizeof(ElfW(Shdr)));
2646 s = s1->sections[i];
2647 if (s) {
2648 sh->sh_name = s->sh_name;
2649 sh->sh_type = s->sh_type;
2650 sh->sh_flags = s->sh_flags;
2651 sh->sh_entsize = s->sh_entsize;
2652 sh->sh_info = s->sh_info;
2653 if (s->link)
2654 sh->sh_link = s->link->sh_num;
2655 sh->sh_addralign = s->sh_addralign;
2656 sh->sh_addr = s->sh_addr;
2657 sh->sh_offset = s->sh_offset;
2658 sh->sh_size = s->sh_size;
2660 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2664 /* Write an elf, coff or "binary" file */
2665 static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum,
2666 ElfW(Phdr) *phdr, int file_offset, int *sec_order)
2668 int fd, mode, file_type;
2669 FILE *f;
2671 file_type = s1->output_type;
2672 if (file_type == TCC_OUTPUT_OBJ)
2673 mode = 0666;
2674 else
2675 mode = 0777;
2676 unlink(filename);
2677 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2678 if (fd < 0) {
2679 tcc_error_noabort("could not write '%s'", filename);
2680 return -1;
2682 f = fdopen(fd, "wb");
2683 if (s1->verbose)
2684 printf("<- %s\n", filename);
2686 #ifdef TCC_TARGET_COFF
2687 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF)
2688 tcc_output_coff(s1, f);
2689 else
2690 #endif
2691 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
2692 tcc_output_elf(s1, f, phnum, phdr, file_offset, sec_order);
2693 else
2694 tcc_output_binary(s1, f, sec_order);
2695 fclose(f);
2697 return 0;
2700 /* Output an elf, coff or binary file */
2701 /* XXX: suppress unneeded sections */
2702 static int elf_output_file(TCCState *s1, const char *filename)
2704 int i, ret, phnum, shnum, file_type, file_offset, *sec_order;
2705 struct dyn_inf dyninf;
2706 ElfW(Phdr) *phdr;
2707 ElfW(Sym) *sym;
2708 Section *strsec, *interp, *dynamic, *dynstr;
2710 file_type = s1->output_type;
2711 s1->nb_errors = 0;
2713 /* if linking, also link in runtime libraries (libc, libgcc, etc.) */
2714 if (file_type != TCC_OUTPUT_OBJ) {
2715 tcc_add_runtime(s1);
2718 phdr = NULL;
2719 sec_order = NULL;
2720 interp = dynamic = dynstr = NULL; /* avoid warning */
2721 dyninf.dyn_rel_off = 0; /* avoid warning */
2723 if (file_type != TCC_OUTPUT_OBJ) {
2724 relocate_common_syms();
2726 tcc_add_linker_symbols(s1);
2728 if (!s1->static_link) {
2729 if (file_type == TCC_OUTPUT_EXE) {
2730 char *ptr;
2731 /* allow override the dynamic loader */
2732 const char *elfint = getenv("LD_SO");
2733 if (elfint == NULL)
2734 elfint = DEFAULT_ELFINTERP(s1);
2735 /* add interpreter section only if executable */
2736 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
2737 interp->sh_addralign = 1;
2738 ptr = section_ptr_add(interp, 1 + strlen(elfint));
2739 strcpy(ptr, elfint);
2742 /* add dynamic symbol table */
2743 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
2744 ".dynstr",
2745 ".hash", SHF_ALLOC);
2746 dynstr = s1->dynsym->link;
2748 /* add dynamic section */
2749 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
2750 SHF_ALLOC | SHF_WRITE);
2751 dynamic->link = dynstr;
2752 dynamic->sh_entsize = sizeof(ElfW(Dyn));
2754 build_got(s1);
2756 if (file_type == TCC_OUTPUT_EXE) {
2757 bind_exe_dynsyms(s1);
2759 if (s1->nb_errors) {
2760 ret = -1;
2761 goto the_end;
2764 bind_libs_dynsyms(s1);
2765 } else /* shared library case: simply export all global symbols */
2766 export_global_syms(s1);
2768 build_got_entries(s1);
2770 /* add a list of needed dlls */
2771 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2772 DLLReference *dllref = s1->loaded_dlls[i];
2773 if (dllref->level == 0)
2774 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
2777 if (s1->rpath)
2778 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
2780 /* XXX: currently, since we do not handle PIC code, we
2781 must relocate the readonly segments */
2782 if (file_type == TCC_OUTPUT_DLL) {
2783 if (s1->soname)
2784 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
2785 put_dt(dynamic, DT_TEXTREL, 0);
2788 if (s1->symbolic)
2789 put_dt(dynamic, DT_SYMBOLIC, 0);
2791 /* add necessary space for other entries */
2792 dyninf.dyn_rel_off = dynamic->data_offset;
2793 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
2794 } else {
2795 /* still need to build got entries in case of static link */
2796 build_got_entries(s1);
2800 /* we add a section for symbols */
2801 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
2802 put_elf_str(strsec, "");
2804 /* compute number of sections */
2805 shnum = s1->nb_sections;
2807 /* this array is used to reorder sections in the output file */
2808 sec_order = tcc_malloc(sizeof(int) * shnum);
2809 sec_order[0] = 0;
2811 /* compute number of program headers */
2812 switch(file_type) {
2813 default:
2814 case TCC_OUTPUT_OBJ:
2815 phnum = 0;
2816 break;
2817 case TCC_OUTPUT_EXE:
2818 if (!s1->static_link)
2819 phnum = 4 + HAVE_PHDR;
2820 else
2821 phnum = 2;
2822 break;
2823 case TCC_OUTPUT_DLL:
2824 phnum = 3;
2825 break;
2828 /* Allocate strings for section names */
2829 alloc_sec_names(s1, file_type, strsec);
2831 /* allocate program segment headers */
2832 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
2834 /* compute section to program header mapping */
2835 file_offset = layout_sections(s1, phdr, phnum, interp, strsec, &dyninf,
2836 sec_order);
2838 /* Fill remaining program header and finalize relocation related to dynamic
2839 linking. */
2840 if (phnum > 0) {
2841 fill_unloadable_phdr(phdr, phnum, interp, dynamic);
2842 if (dynamic) {
2843 dyninf.dynamic = dynamic;
2844 dyninf.dynstr = dynstr;
2846 fill_dynamic(s1, &dyninf);
2848 /* put in GOT the dynamic section address and relocate PLT */
2849 write32le(s1->got->data, dynamic->sh_addr);
2850 if (file_type == TCC_OUTPUT_EXE
2851 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2852 || file_type == TCC_OUTPUT_DLL
2853 #endif
2855 relocate_plt(s1);
2857 /* relocate symbols in .dynsym now that final addresses are known */
2858 for_each_elem(s1->dynsym, 1, sym, ElfW(Sym)) {
2859 if (sym->st_shndx == SHN_UNDEF) {
2860 /* relocate to PLT if symbol corresponds to a PLT entry,
2861 but not if it's a weak symbol */
2862 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
2863 sym->st_value = 0;
2864 else if (sym->st_value)
2865 sym->st_value += s1->plt->sh_addr;
2866 } else if (sym->st_shndx < SHN_LORESERVE) {
2867 /* do symbol relocation */
2868 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
2874 /* if building executable or DLL, then relocate each section
2875 except the GOT which is already relocated */
2876 if (file_type != TCC_OUTPUT_OBJ) {
2877 ret = final_sections_reloc(s1);
2878 if (ret)
2879 goto the_end;
2882 /* Perform relocation to GOT or PLT entries */
2883 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2884 fill_got(s1);
2886 /* Create the ELF file with name 'filename' */
2887 ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order);
2888 the_end:
2889 tcc_free(s1->symtab_to_dynsym);
2890 tcc_free(sec_order);
2891 tcc_free(phdr);
2892 tcc_free(s1->sym_attrs);
2893 s1->sym_attrs = NULL;
2894 return ret;
2897 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2899 int ret;
2900 #ifdef TCC_TARGET_PE
2901 if (s->output_type != TCC_OUTPUT_OBJ) {
2902 ret = pe_output_file(s, filename);
2903 } else
2904 #endif
2905 ret = elf_output_file(s, filename);
2906 return ret;
2909 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2911 void *data;
2913 data = tcc_malloc(size);
2914 lseek(fd, file_offset, SEEK_SET);
2915 read(fd, data, size);
2916 return data;
2919 typedef struct SectionMergeInfo {
2920 Section *s; /* corresponding existing section */
2921 unsigned long offset; /* offset of the new section in the existing section */
2922 uint8_t new_section; /* true if section 's' was added */
2923 uint8_t link_once; /* true if link once section */
2924 } SectionMergeInfo;
2926 ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h)
2928 int size = read(fd, h, sizeof *h);
2929 if (size == sizeof *h && 0 == memcmp(h, ELFMAG, 4)) {
2930 if (h->e_type == ET_REL)
2931 return AFF_BINTYPE_REL;
2932 if (h->e_type == ET_DYN)
2933 return AFF_BINTYPE_DYN;
2934 } else if (size >= 8) {
2935 if (0 == memcmp(h, ARMAG, 8))
2936 return AFF_BINTYPE_AR;
2937 #ifdef TCC_TARGET_COFF
2938 if (((struct filehdr*)h)->f_magic == COFF_C67_MAGIC)
2939 return AFF_BINTYPE_C67;
2940 #endif
2942 return 0;
2945 /* load an object file and merge it with current files */
2946 /* XXX: handle correctly stab (debug) info */
2947 ST_FUNC int tcc_load_object_file(TCCState *s1,
2948 int fd, unsigned long file_offset)
2950 ElfW(Ehdr) ehdr;
2951 ElfW(Shdr) *shdr, *sh;
2952 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2953 unsigned char *strsec, *strtab;
2954 int *old_to_new_syms;
2955 char *sh_name, *name;
2956 SectionMergeInfo *sm_table, *sm;
2957 ElfW(Sym) *sym, *symtab;
2958 ElfW_Rel *rel;
2959 Section *s;
2961 int stab_index;
2962 int stabstr_index;
2964 stab_index = stabstr_index = 0;
2966 lseek(fd, file_offset, SEEK_SET);
2967 if (tcc_object_type(fd, &ehdr) != AFF_BINTYPE_REL)
2968 goto fail1;
2969 /* test CPU specific stuff */
2970 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2971 ehdr.e_machine != EM_TCC_TARGET) {
2972 fail1:
2973 tcc_error_noabort("invalid object file");
2974 return -1;
2976 /* read sections */
2977 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2978 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2979 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2981 /* load section names */
2982 sh = &shdr[ehdr.e_shstrndx];
2983 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2985 /* load symtab and strtab */
2986 old_to_new_syms = NULL;
2987 symtab = NULL;
2988 strtab = NULL;
2989 nb_syms = 0;
2990 for(i = 1; i < ehdr.e_shnum; i++) {
2991 sh = &shdr[i];
2992 if (sh->sh_type == SHT_SYMTAB) {
2993 if (symtab) {
2994 tcc_error_noabort("object must contain only one symtab");
2995 fail:
2996 ret = -1;
2997 goto the_end;
2999 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
3000 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
3001 sm_table[i].s = symtab_section;
3003 /* now load strtab */
3004 sh = &shdr[sh->sh_link];
3005 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
3009 /* now examine each section and try to merge its content with the
3010 ones in memory */
3011 for(i = 1; i < ehdr.e_shnum; i++) {
3012 /* no need to examine section name strtab */
3013 if (i == ehdr.e_shstrndx)
3014 continue;
3015 sh = &shdr[i];
3016 sh_name = (char *) strsec + sh->sh_name;
3017 /* ignore sections types we do not handle */
3018 if (sh->sh_type != SHT_PROGBITS &&
3019 sh->sh_type != SHT_RELX &&
3020 #ifdef TCC_ARM_EABI
3021 sh->sh_type != SHT_ARM_EXIDX &&
3022 #endif
3023 sh->sh_type != SHT_NOBITS &&
3024 sh->sh_type != SHT_PREINIT_ARRAY &&
3025 sh->sh_type != SHT_INIT_ARRAY &&
3026 sh->sh_type != SHT_FINI_ARRAY &&
3027 strcmp(sh_name, ".stabstr")
3029 continue;
3030 if (sh->sh_addralign < 1)
3031 sh->sh_addralign = 1;
3032 /* find corresponding section, if any */
3033 for(j = 1; j < s1->nb_sections;j++) {
3034 s = s1->sections[j];
3035 if (!strcmp(s->name, sh_name)) {
3036 if (!strncmp(sh_name, ".gnu.linkonce",
3037 sizeof(".gnu.linkonce") - 1)) {
3038 /* if a 'linkonce' section is already present, we
3039 do not add it again. It is a little tricky as
3040 symbols can still be defined in
3041 it. */
3042 sm_table[i].link_once = 1;
3043 goto next;
3044 } else {
3045 goto found;
3049 /* not found: create new section */
3050 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
3051 /* take as much info as possible from the section. sh_link and
3052 sh_info will be updated later */
3053 s->sh_addralign = sh->sh_addralign;
3054 s->sh_entsize = sh->sh_entsize;
3055 sm_table[i].new_section = 1;
3056 found:
3057 if (sh->sh_type != s->sh_type) {
3058 tcc_error_noabort("invalid section type");
3059 goto fail;
3062 /* align start of section */
3063 offset = s->data_offset;
3065 if (0 == strcmp(sh_name, ".stab")) {
3066 stab_index = i;
3067 goto no_align;
3069 if (0 == strcmp(sh_name, ".stabstr")) {
3070 stabstr_index = i;
3071 goto no_align;
3074 size = sh->sh_addralign - 1;
3075 offset = (offset + size) & ~size;
3076 if (sh->sh_addralign > s->sh_addralign)
3077 s->sh_addralign = sh->sh_addralign;
3078 s->data_offset = offset;
3079 no_align:
3080 sm_table[i].offset = offset;
3081 sm_table[i].s = s;
3082 /* concatenate sections */
3083 size = sh->sh_size;
3084 if (sh->sh_type != SHT_NOBITS) {
3085 unsigned char *ptr;
3086 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
3087 ptr = section_ptr_add(s, size);
3088 read(fd, ptr, size);
3089 } else {
3090 s->data_offset += size;
3092 next: ;
3095 /* gr relocate stab strings */
3096 if (stab_index && stabstr_index) {
3097 Stab_Sym *a, *b;
3098 unsigned o;
3099 s = sm_table[stab_index].s;
3100 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
3101 b = (Stab_Sym *)(s->data + s->data_offset);
3102 o = sm_table[stabstr_index].offset;
3103 while (a < b)
3104 a->n_strx += o, a++;
3107 /* second short pass to update sh_link and sh_info fields of new
3108 sections */
3109 for(i = 1; i < ehdr.e_shnum; i++) {
3110 s = sm_table[i].s;
3111 if (!s || !sm_table[i].new_section)
3112 continue;
3113 sh = &shdr[i];
3114 if (sh->sh_link > 0)
3115 s->link = sm_table[sh->sh_link].s;
3116 if (sh->sh_type == SHT_RELX) {
3117 s->sh_info = sm_table[sh->sh_info].s->sh_num;
3118 /* update backward link */
3119 s1->sections[s->sh_info]->reloc = s;
3122 sm = sm_table;
3124 /* resolve symbols */
3125 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
3127 sym = symtab + 1;
3128 for(i = 1; i < nb_syms; i++, sym++) {
3129 if (sym->st_shndx != SHN_UNDEF &&
3130 sym->st_shndx < SHN_LORESERVE) {
3131 sm = &sm_table[sym->st_shndx];
3132 if (sm->link_once) {
3133 /* if a symbol is in a link once section, we use the
3134 already defined symbol. It is very important to get
3135 correct relocations */
3136 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
3137 name = (char *) strtab + sym->st_name;
3138 sym_index = find_elf_sym(symtab_section, name);
3139 if (sym_index)
3140 old_to_new_syms[i] = sym_index;
3142 continue;
3144 /* if no corresponding section added, no need to add symbol */
3145 if (!sm->s)
3146 continue;
3147 /* convert section number */
3148 sym->st_shndx = sm->s->sh_num;
3149 /* offset value */
3150 sym->st_value += sm->offset;
3152 /* add symbol */
3153 name = (char *) strtab + sym->st_name;
3154 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
3155 sym->st_info, sym->st_other,
3156 sym->st_shndx, name);
3157 old_to_new_syms[i] = sym_index;
3160 /* third pass to patch relocation entries */
3161 for(i = 1; i < ehdr.e_shnum; i++) {
3162 s = sm_table[i].s;
3163 if (!s)
3164 continue;
3165 sh = &shdr[i];
3166 offset = sm_table[i].offset;
3167 switch(s->sh_type) {
3168 case SHT_RELX:
3169 /* take relocation offset information */
3170 offseti = sm_table[sh->sh_info].offset;
3171 for_each_elem(s, (offset / sizeof(*rel)), rel, ElfW_Rel) {
3172 int type;
3173 unsigned sym_index;
3174 /* convert symbol index */
3175 type = ELFW(R_TYPE)(rel->r_info);
3176 sym_index = ELFW(R_SYM)(rel->r_info);
3177 /* NOTE: only one symtab assumed */
3178 if (sym_index >= nb_syms)
3179 goto invalid_reloc;
3180 sym_index = old_to_new_syms[sym_index];
3181 /* ignore link_once in rel section. */
3182 if (!sym_index && !sm->link_once
3183 #ifdef TCC_TARGET_ARM
3184 && type != R_ARM_V4BX
3185 #endif
3187 invalid_reloc:
3188 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
3189 i, strsec + sh->sh_name, rel->r_offset);
3190 goto fail;
3192 rel->r_info = ELFW(R_INFO)(sym_index, type);
3193 /* offset the relocation offset */
3194 rel->r_offset += offseti;
3195 #ifdef TCC_TARGET_ARM
3196 /* Jumps and branches from a Thumb code to a PLT entry need
3197 special handling since PLT entries are ARM code.
3198 Unconditional bl instructions referencing PLT entries are
3199 handled by converting these instructions into blx
3200 instructions. Other case of instructions referencing a PLT
3201 entry require to add a Thumb stub before the PLT entry to
3202 switch to ARM mode. We set bit plt_thumb_stub of the
3203 attribute of a symbol to indicate such a case. */
3204 if (type == R_ARM_THM_JUMP24)
3205 alloc_sym_attr(s1, sym_index)->plt_thumb_stub = 1;
3206 #endif
3208 break;
3209 default:
3210 break;
3214 ret = 0;
3215 the_end:
3216 tcc_free(symtab);
3217 tcc_free(strtab);
3218 tcc_free(old_to_new_syms);
3219 tcc_free(sm_table);
3220 tcc_free(strsec);
3221 tcc_free(shdr);
3222 return ret;
3225 typedef struct ArchiveHeader {
3226 char ar_name[16]; /* name of this member */
3227 char ar_date[12]; /* file mtime */
3228 char ar_uid[6]; /* owner uid; printed as decimal */
3229 char ar_gid[6]; /* owner gid; printed as decimal */
3230 char ar_mode[8]; /* file mode, printed as octal */
3231 char ar_size[10]; /* file size, printed as decimal */
3232 char ar_fmag[2]; /* should contain ARFMAG */
3233 } ArchiveHeader;
3235 static int get_be32(const uint8_t *b)
3237 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
3240 static long get_be64(const uint8_t *b)
3242 long long ret = get_be32(b);
3243 ret = (ret << 32) | (unsigned)get_be32(b+4);
3244 return (long)ret;
3247 /* load only the objects which resolve undefined symbols */
3248 static int tcc_load_alacarte(TCCState *s1, int fd, int size, int entrysize)
3250 long i, bound, nsyms, sym_index, off, ret;
3251 uint8_t *data;
3252 const char *ar_names, *p;
3253 const uint8_t *ar_index;
3254 ElfW(Sym) *sym;
3256 data = tcc_malloc(size);
3257 if (read(fd, data, size) != size)
3258 goto fail;
3259 nsyms = entrysize == 4 ? get_be32(data) : get_be64(data);
3260 ar_index = data + entrysize;
3261 ar_names = (char *) ar_index + nsyms * entrysize;
3263 do {
3264 bound = 0;
3265 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
3266 sym_index = find_elf_sym(symtab_section, p);
3267 if(sym_index) {
3268 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
3269 if(sym->st_shndx == SHN_UNDEF) {
3270 off = (entrysize == 4
3271 ? get_be32(ar_index + i * 4)
3272 : get_be64(ar_index + i * 8))
3273 + sizeof(ArchiveHeader);
3274 ++bound;
3275 if(tcc_load_object_file(s1, fd, off) < 0) {
3276 fail:
3277 ret = -1;
3278 goto the_end;
3283 } while(bound);
3284 ret = 0;
3285 the_end:
3286 tcc_free(data);
3287 return ret;
3290 /* load a '.a' file */
3291 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
3293 ArchiveHeader hdr;
3294 char ar_size[11];
3295 char ar_name[17];
3296 char magic[8];
3297 int size, len, i;
3298 unsigned long file_offset;
3300 /* skip magic which was already checked */
3301 read(fd, magic, sizeof(magic));
3303 for(;;) {
3304 len = read(fd, &hdr, sizeof(hdr));
3305 if (len == 0)
3306 break;
3307 if (len != sizeof(hdr)) {
3308 tcc_error_noabort("invalid archive");
3309 return -1;
3311 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
3312 ar_size[sizeof(hdr.ar_size)] = '\0';
3313 size = strtol(ar_size, NULL, 0);
3314 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
3315 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
3316 if (ar_name[i] != ' ')
3317 break;
3319 ar_name[i + 1] = '\0';
3320 file_offset = lseek(fd, 0, SEEK_CUR);
3321 /* align to even */
3322 size = (size + 1) & ~1;
3323 if (!strcmp(ar_name, "/")) {
3324 /* coff symbol table : we handle it */
3325 if(s1->alacarte_link)
3326 return tcc_load_alacarte(s1, fd, size, 4);
3327 } else if (!strcmp(ar_name, "/SYM64/")) {
3328 if(s1->alacarte_link)
3329 return tcc_load_alacarte(s1, fd, size, 8);
3330 } else {
3331 ElfW(Ehdr) ehdr;
3332 if (tcc_object_type(fd, &ehdr) == AFF_BINTYPE_REL) {
3333 if (tcc_load_object_file(s1, fd, file_offset) < 0)
3334 return -1;
3337 lseek(fd, file_offset + size, SEEK_SET);
3339 return 0;
3342 #ifndef TCC_TARGET_PE
3343 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
3344 is referenced by the user (so it should be added as DT_NEEDED in
3345 the generated ELF file) */
3346 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
3348 ElfW(Ehdr) ehdr;
3349 ElfW(Shdr) *shdr, *sh, *sh1;
3350 int i, j, nb_syms, nb_dts, sym_bind, ret;
3351 ElfW(Sym) *sym, *dynsym;
3352 ElfW(Dyn) *dt, *dynamic;
3353 unsigned char *dynstr;
3354 const char *name, *soname;
3355 DLLReference *dllref;
3357 read(fd, &ehdr, sizeof(ehdr));
3359 /* test CPU specific stuff */
3360 if (ehdr.e_ident[5] != ELFDATA2LSB ||
3361 ehdr.e_machine != EM_TCC_TARGET) {
3362 tcc_error_noabort("bad architecture");
3363 return -1;
3366 /* read sections */
3367 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
3369 /* load dynamic section and dynamic symbols */
3370 nb_syms = 0;
3371 nb_dts = 0;
3372 dynamic = NULL;
3373 dynsym = NULL; /* avoid warning */
3374 dynstr = NULL; /* avoid warning */
3375 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
3376 switch(sh->sh_type) {
3377 case SHT_DYNAMIC:
3378 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
3379 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
3380 break;
3381 case SHT_DYNSYM:
3382 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
3383 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
3384 sh1 = &shdr[sh->sh_link];
3385 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
3386 break;
3387 default:
3388 break;
3392 /* compute the real library name */
3393 soname = tcc_basename(filename);
3395 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
3396 if (dt->d_tag == DT_SONAME) {
3397 soname = (char *) dynstr + dt->d_un.d_val;
3401 /* if the dll is already loaded, do not load it */
3402 for(i = 0; i < s1->nb_loaded_dlls; i++) {
3403 dllref = s1->loaded_dlls[i];
3404 if (!strcmp(soname, dllref->name)) {
3405 /* but update level if needed */
3406 if (level < dllref->level)
3407 dllref->level = level;
3408 ret = 0;
3409 goto the_end;
3413 /* add the dll and its level */
3414 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
3415 dllref->level = level;
3416 strcpy(dllref->name, soname);
3417 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
3419 /* add dynamic symbols in dynsym_section */
3420 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
3421 sym_bind = ELFW(ST_BIND)(sym->st_info);
3422 if (sym_bind == STB_LOCAL)
3423 continue;
3424 name = (char *) dynstr + sym->st_name;
3425 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
3426 sym->st_info, sym->st_other, sym->st_shndx, name);
3429 /* load all referenced DLLs */
3430 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
3431 switch(dt->d_tag) {
3432 case DT_NEEDED:
3433 name = (char *) dynstr + dt->d_un.d_val;
3434 for(j = 0; j < s1->nb_loaded_dlls; j++) {
3435 dllref = s1->loaded_dlls[j];
3436 if (!strcmp(name, dllref->name))
3437 goto already_loaded;
3439 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
3440 tcc_error_noabort("referenced dll '%s' not found", name);
3441 ret = -1;
3442 goto the_end;
3444 already_loaded:
3445 break;
3448 ret = 0;
3449 the_end:
3450 tcc_free(dynstr);
3451 tcc_free(dynsym);
3452 tcc_free(dynamic);
3453 tcc_free(shdr);
3454 return ret;
3457 #define LD_TOK_NAME 256
3458 #define LD_TOK_EOF (-1)
3460 /* return next ld script token */
3461 static int ld_next(TCCState *s1, char *name, int name_size)
3463 int c;
3464 char *q;
3466 redo:
3467 switch(ch) {
3468 case ' ':
3469 case '\t':
3470 case '\f':
3471 case '\v':
3472 case '\r':
3473 case '\n':
3474 inp();
3475 goto redo;
3476 case '/':
3477 minp();
3478 if (ch == '*') {
3479 file->buf_ptr = parse_comment(file->buf_ptr);
3480 ch = file->buf_ptr[0];
3481 goto redo;
3482 } else {
3483 q = name;
3484 *q++ = '/';
3485 goto parse_name;
3487 break;
3488 case '\\':
3489 ch = handle_eob();
3490 if (ch != '\\')
3491 goto redo;
3492 /* fall through */
3493 /* case 'a' ... 'z': */
3494 case 'a':
3495 case 'b':
3496 case 'c':
3497 case 'd':
3498 case 'e':
3499 case 'f':
3500 case 'g':
3501 case 'h':
3502 case 'i':
3503 case 'j':
3504 case 'k':
3505 case 'l':
3506 case 'm':
3507 case 'n':
3508 case 'o':
3509 case 'p':
3510 case 'q':
3511 case 'r':
3512 case 's':
3513 case 't':
3514 case 'u':
3515 case 'v':
3516 case 'w':
3517 case 'x':
3518 case 'y':
3519 case 'z':
3520 /* case 'A' ... 'z': */
3521 case 'A':
3522 case 'B':
3523 case 'C':
3524 case 'D':
3525 case 'E':
3526 case 'F':
3527 case 'G':
3528 case 'H':
3529 case 'I':
3530 case 'J':
3531 case 'K':
3532 case 'L':
3533 case 'M':
3534 case 'N':
3535 case 'O':
3536 case 'P':
3537 case 'Q':
3538 case 'R':
3539 case 'S':
3540 case 'T':
3541 case 'U':
3542 case 'V':
3543 case 'W':
3544 case 'X':
3545 case 'Y':
3546 case 'Z':
3547 case '_':
3548 case '.':
3549 case '$':
3550 case '~':
3551 q = name;
3552 parse_name:
3553 for(;;) {
3554 if (!((ch >= 'a' && ch <= 'z') ||
3555 (ch >= 'A' && ch <= 'Z') ||
3556 (ch >= '0' && ch <= '9') ||
3557 strchr("/.-_+=$:\\,~", ch)))
3558 break;
3559 if ((q - name) < name_size - 1) {
3560 *q++ = ch;
3562 minp();
3564 *q = '\0';
3565 c = LD_TOK_NAME;
3566 break;
3567 case CH_EOF:
3568 c = LD_TOK_EOF;
3569 break;
3570 default:
3571 c = ch;
3572 inp();
3573 break;
3575 return c;
3578 static int ld_add_file(TCCState *s1, const char filename[])
3580 int ret;
3582 ret = tcc_add_file_internal(s1, filename, AFF_TYPE_BIN);
3583 if (ret)
3584 ret = tcc_add_dll(s1, filename, 0);
3585 return ret;
3588 static inline int new_undef_syms(void)
3590 int ret = 0;
3591 ret = new_undef_sym;
3592 new_undef_sym = 0;
3593 return ret;
3596 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
3598 char filename[1024], libname[1024];
3599 int t, group, nblibs = 0, ret = 0;
3600 char **libs = NULL;
3602 group = !strcmp(cmd, "GROUP");
3603 if (!as_needed)
3604 new_undef_syms();
3605 t = ld_next(s1, filename, sizeof(filename));
3606 if (t != '(')
3607 expect("(");
3608 t = ld_next(s1, filename, sizeof(filename));
3609 for(;;) {
3610 libname[0] = '\0';
3611 if (t == LD_TOK_EOF) {
3612 tcc_error_noabort("unexpected end of file");
3613 ret = -1;
3614 goto lib_parse_error;
3615 } else if (t == ')') {
3616 break;
3617 } else if (t == '-') {
3618 t = ld_next(s1, filename, sizeof(filename));
3619 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
3620 tcc_error_noabort("library name expected");
3621 ret = -1;
3622 goto lib_parse_error;
3624 pstrcpy(libname, sizeof libname, &filename[1]);
3625 if (s1->static_link) {
3626 snprintf(filename, sizeof filename, "lib%s.a", libname);
3627 } else {
3628 snprintf(filename, sizeof filename, "lib%s.so", libname);
3630 } else if (t != LD_TOK_NAME) {
3631 tcc_error_noabort("filename expected");
3632 ret = -1;
3633 goto lib_parse_error;
3635 if (!strcmp(filename, "AS_NEEDED")) {
3636 ret = ld_add_file_list(s1, cmd, 1);
3637 if (ret)
3638 goto lib_parse_error;
3639 } else {
3640 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3641 if (!as_needed) {
3642 ret = ld_add_file(s1, filename);
3643 if (ret)
3644 goto lib_parse_error;
3645 if (group) {
3646 /* Add the filename *and* the libname to avoid future conversions */
3647 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
3648 if (libname[0] != '\0')
3649 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
3653 t = ld_next(s1, filename, sizeof(filename));
3654 if (t == ',') {
3655 t = ld_next(s1, filename, sizeof(filename));
3658 if (group && !as_needed) {
3659 while (new_undef_syms()) {
3660 int i;
3662 for (i = 0; i < nblibs; i ++)
3663 ld_add_file(s1, libs[i]);
3666 lib_parse_error:
3667 dynarray_reset(&libs, &nblibs);
3668 return ret;
3671 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3672 files */
3673 ST_FUNC int tcc_load_ldscript(TCCState *s1)
3675 char cmd[64];
3676 char filename[1024];
3677 int t, ret;
3679 ch = handle_eob();
3680 for(;;) {
3681 t = ld_next(s1, cmd, sizeof(cmd));
3682 if (t == LD_TOK_EOF)
3683 return 0;
3684 else if (t != LD_TOK_NAME)
3685 return -1;
3686 if (!strcmp(cmd, "INPUT") ||
3687 !strcmp(cmd, "GROUP")) {
3688 ret = ld_add_file_list(s1, cmd, 0);
3689 if (ret)
3690 return ret;
3691 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3692 !strcmp(cmd, "TARGET")) {
3693 /* ignore some commands */
3694 t = ld_next(s1, cmd, sizeof(cmd));
3695 if (t != '(')
3696 expect("(");
3697 for(;;) {
3698 t = ld_next(s1, filename, sizeof(filename));
3699 if (t == LD_TOK_EOF) {
3700 tcc_error_noabort("unexpected end of file");
3701 return -1;
3702 } else if (t == ')') {
3703 break;
3706 } else {
3707 return -1;
3710 return 0;
3712 #endif /* !TCC_TARGET_PE */