Improve comments for symbol export and binding
[tinycc.git] / tccelf.c
blob2721133c59832d6bb10db08807a846d75f7d0f57
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 sym_index = find_elf_sym(s, name);
398 esym = &((ElfW(Sym) *)s->data)[sym_index];
399 if (sym_index && esym->st_value == value && esym->st_size == size
400 && esym->st_info == info && esym->st_other == other
401 && esym->st_shndx == sh_num)
402 return sym_index;
404 if (sym_bind != STB_LOCAL) {
405 /* we search global or weak symbols */
406 if (!sym_index)
407 goto do_def;
408 if (esym->st_shndx != SHN_UNDEF) {
409 esym_bind = ELFW(ST_BIND)(esym->st_info);
410 /* propagate the most constraining visibility */
411 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
412 esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
413 if (esym_vis == STV_DEFAULT) {
414 new_vis = sym_vis;
415 } else if (sym_vis == STV_DEFAULT) {
416 new_vis = esym_vis;
417 } else {
418 new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
420 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
421 | new_vis;
422 other = esym->st_other; /* in case we have to patch esym */
423 if (sh_num == SHN_UNDEF) {
424 /* ignore adding of undefined symbol if the
425 corresponding symbol is already defined */
426 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
427 /* global overrides weak, so patch */
428 goto do_patch;
429 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
430 /* weak is ignored if already global */
431 } else if (sym_bind == STB_WEAK && esym_bind == STB_WEAK) {
432 /* keep first-found weak definition, ignore subsequents */
433 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
434 /* ignore hidden symbols after */
435 } else if ((esym->st_shndx == SHN_COMMON
436 || esym->st_shndx == bss_section->sh_num)
437 && (sh_num < SHN_LORESERVE
438 && sh_num != bss_section->sh_num)) {
439 /* data symbol gets precedence over common/bss */
440 goto do_patch;
441 } else if (sh_num == SHN_COMMON || sh_num == bss_section->sh_num) {
442 /* data symbol keeps precedence over common/bss */
443 } else if (s == tcc_state->dynsymtab_section) {
444 /* we accept that two DLL define the same symbol */
445 } else {
446 #if 0
447 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
448 sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
449 #endif
450 tcc_error_noabort("'%s' defined twice", name);
452 } else {
453 do_patch:
454 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
455 esym->st_shndx = sh_num;
456 new_undef_sym = 1;
457 esym->st_value = value;
458 esym->st_size = size;
459 esym->st_other = other;
461 } else {
462 do_def:
463 sym_index = put_elf_sym(s, value, size,
464 ELFW(ST_INFO)(sym_bind, sym_type), other,
465 sh_num, name);
467 return sym_index;
470 /* put relocation */
471 ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset,
472 int type, int symbol, addr_t addend)
474 char buf[256];
475 Section *sr;
476 ElfW_Rel *rel;
478 sr = s->reloc;
479 if (!sr) {
480 /* if no relocation section, create it */
481 snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
482 /* if the symtab is allocated, then we consider the relocation
483 are also */
484 sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
485 sr->sh_entsize = sizeof(ElfW_Rel);
486 sr->link = symtab;
487 sr->sh_info = s->sh_num;
488 s->reloc = sr;
490 rel = section_ptr_add(sr, sizeof(ElfW_Rel));
491 rel->r_offset = offset;
492 rel->r_info = ELFW(R_INFO)(symbol, type);
493 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
494 rel->r_addend = addend;
495 #else
496 if (addend)
497 tcc_error("non-zero addend on REL architecture");
498 #endif
501 ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
502 int type, int symbol)
504 put_elf_reloca(symtab, s, offset, type, symbol, 0);
507 /* put stab debug information */
509 ST_FUNC void put_stabs(const char *str, int type, int other, int desc,
510 unsigned long value)
512 Stab_Sym *sym;
514 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
515 if (str) {
516 sym->n_strx = put_elf_str(stabstr_section, str);
517 } else {
518 sym->n_strx = 0;
520 sym->n_type = type;
521 sym->n_other = other;
522 sym->n_desc = desc;
523 sym->n_value = value;
526 ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc,
527 unsigned long value, Section *sec, int sym_index)
529 put_stabs(str, type, other, desc, value);
530 put_elf_reloc(symtab_section, stab_section,
531 stab_section->data_offset - sizeof(unsigned int),
532 R_DATA_32, sym_index);
535 ST_FUNC void put_stabn(int type, int other, int desc, int value)
537 put_stabs(NULL, type, other, desc, value);
540 ST_FUNC void put_stabd(int type, int other, int desc)
542 put_stabs(NULL, type, other, desc, 0);
545 /* Browse each elem of type <type> in section <sec> starting at elem <startoff>
546 using variable <elem> */
547 #define for_each_elem(sec, startoff, elem, type) \
548 for (elem = (type *) sec->data + startoff; \
549 elem < (type *) (sec->data + sec->data_offset); elem++)
551 /* In an ELF file symbol table, the local symbols must appear below
552 the global and weak ones. Since TCC cannot sort it while generating
553 the code, we must do it after. All the relocation tables are also
554 modified to take into account the symbol table sorting */
555 static void sort_syms(TCCState *s1, Section *s)
557 int *old_to_new_syms;
558 ElfW(Sym) *new_syms;
559 int nb_syms, i;
560 ElfW(Sym) *p, *q;
561 ElfW_Rel *rel;
562 Section *sr;
563 int type, sym_index;
565 nb_syms = s->data_offset / sizeof(ElfW(Sym));
566 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
567 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
569 /* first pass for local symbols */
570 p = (ElfW(Sym) *)s->data;
571 q = new_syms;
572 for(i = 0; i < nb_syms; i++) {
573 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
574 old_to_new_syms[i] = q - new_syms;
575 *q++ = *p;
577 p++;
579 /* save the number of local symbols in section header */
580 s->sh_info = q - new_syms;
582 /* then second pass for non local symbols */
583 p = (ElfW(Sym) *)s->data;
584 for(i = 0; i < nb_syms; i++) {
585 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
586 old_to_new_syms[i] = q - new_syms;
587 *q++ = *p;
589 p++;
592 /* we copy the new symbols to the old */
593 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
594 tcc_free(new_syms);
596 /* now we modify all the relocations */
597 for(i = 1; i < s1->nb_sections; i++) {
598 sr = s1->sections[i];
599 if (sr->sh_type == SHT_RELX && sr->link == s) {
600 for_each_elem(sr, 0, rel, ElfW_Rel) {
601 sym_index = ELFW(R_SYM)(rel->r_info);
602 type = ELFW(R_TYPE)(rel->r_info);
603 sym_index = old_to_new_syms[sym_index];
604 rel->r_info = ELFW(R_INFO)(sym_index, type);
609 tcc_free(old_to_new_syms);
612 /* relocate common symbols in the .bss section */
613 ST_FUNC void relocate_common_syms(void)
615 ElfW(Sym) *sym;
616 unsigned long offset, align;
618 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
619 if (sym->st_shndx == SHN_COMMON) {
620 /* align symbol */
621 align = sym->st_value;
622 offset = bss_section->data_offset;
623 offset = (offset + align - 1) & -align;
624 sym->st_value = offset;
625 sym->st_shndx = bss_section->sh_num;
626 offset += sym->st_size;
627 bss_section->data_offset = offset;
632 /* relocate symbol table, resolve undefined symbols if do_resolve is
633 true and output error if undefined symbol. */
634 ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
636 ElfW(Sym) *sym, *esym;
637 int sym_bind, sh_num, sym_index;
638 const char *name;
640 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
641 sh_num = sym->st_shndx;
642 if (sh_num == SHN_UNDEF) {
643 name = (char *) strtab_section->data + sym->st_name;
644 /* Use ld.so to resolve symbol for us (for tcc -run) */
645 if (do_resolve) {
646 #if defined TCC_IS_NATIVE && !defined TCC_TARGET_PE
647 void *addr;
648 name = (char *) symtab_section->link->data + sym->st_name;
649 addr = dlsym(RTLD_DEFAULT, name);
650 if (addr) {
651 sym->st_value = (addr_t)addr;
652 #ifdef DEBUG_RELOC
653 printf ("relocate_sym: %s -> 0x%lx\n", name, sym->st_value);
654 #endif
655 goto found;
657 #endif
658 } else if (s1->dynsym) {
659 /* if dynamic symbol exist, then use it */
660 sym_index = find_elf_sym(s1->dynsym, name);
661 if (sym_index) {
662 esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
663 sym->st_value = esym->st_value;
664 goto found;
667 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
668 it */
669 if (!strcmp(name, "_fp_hw"))
670 goto found;
671 /* only weak symbols are accepted to be undefined. Their
672 value is zero */
673 sym_bind = ELFW(ST_BIND)(sym->st_info);
674 if (sym_bind == STB_WEAK) {
675 sym->st_value = 0;
676 } else {
677 tcc_error_noabort("undefined symbol '%s'", name);
679 } else if (sh_num < SHN_LORESERVE) {
680 /* add section base */
681 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
683 found: ;
687 /* relocate a given section (CPU dependent) by applying the relocations
688 in the associated relocation section */
689 ST_FUNC void relocate_section(TCCState *s1, Section *s)
691 Section *sr = s->reloc;
692 ElfW_Rel *rel;
693 ElfW(Sym) *sym;
694 int type, sym_index;
695 unsigned char *ptr;
696 addr_t val, addr;
697 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
698 ElfW_Rel *qrel = (ElfW_Rel *) sr->data; /* ptr to next reloc entry reused */
699 int esym_index;
700 #endif
702 for_each_elem(sr, 0, rel, ElfW_Rel) {
703 ptr = s->data + rel->r_offset;
705 sym_index = ELFW(R_SYM)(rel->r_info);
706 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
707 val = sym->st_value;
708 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
709 val += rel->r_addend;
710 #endif
711 type = ELFW(R_TYPE)(rel->r_info);
712 addr = s->sh_addr + rel->r_offset;
714 /* CPU specific */
715 switch(type) {
716 #if defined(TCC_TARGET_I386)
717 case R_386_32:
718 if (s1->output_type == TCC_OUTPUT_DLL) {
719 esym_index = s1->symtab_to_dynsym[sym_index];
720 qrel->r_offset = rel->r_offset;
721 if (esym_index) {
722 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
723 qrel++;
724 break;
725 } else {
726 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
727 qrel++;
730 add32le(ptr, val);
731 break;
732 case R_386_PC32:
733 if (s1->output_type == TCC_OUTPUT_DLL) {
734 /* DLL relocation */
735 esym_index = s1->symtab_to_dynsym[sym_index];
736 if (esym_index) {
737 qrel->r_offset = rel->r_offset;
738 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
739 qrel++;
740 break;
743 add32le(ptr, val - addr);
744 break;
745 case R_386_PLT32:
746 add32le(ptr, val - addr);
747 break;
748 case R_386_GLOB_DAT:
749 case R_386_JMP_SLOT:
750 write32le(ptr, val);
751 break;
752 case R_386_GOTPC:
753 add32le(ptr, s1->got->sh_addr - addr);
754 break;
755 case R_386_GOTOFF:
756 add32le(ptr, val - s1->got->sh_addr);
757 break;
758 case R_386_GOT32:
759 case R_386_GOT32X:
760 /* we load the got offset */
761 add32le(ptr, s1->sym_attrs[sym_index].got_offset);
762 break;
763 case R_386_16:
764 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
765 output_file:
766 tcc_error("can only produce 16-bit binary files");
768 write16le(ptr, read16le(ptr) + val);
769 break;
770 case R_386_PC16:
771 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
772 goto output_file;
773 write16le(ptr, read16le(ptr) + val - addr);
774 break;
776 #ifdef TCC_TARGET_PE
777 case R_386_RELATIVE: /* handled in pe_relocate_rva() */
778 break;
779 #endif
780 case R_386_COPY:
781 /* This reloction must copy initialized data from the library
782 to the program .bss segment. Currently made like for ARM
783 (to remove noise of defaukt case). Is this true?
785 break;
787 default:
788 fprintf(stderr,"FIXME: handle reloc type %d at %x [%p] to %x\n",
789 type, (unsigned)addr, ptr, (unsigned)val);
790 break;
791 #elif defined(TCC_TARGET_ARM)
792 case R_ARM_PC24:
793 case R_ARM_CALL:
794 case R_ARM_JUMP24:
795 case R_ARM_PLT32:
797 int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko;
798 x = (*(int *) ptr) & 0xffffff;
799 if (sym->st_shndx == SHN_UNDEF
800 || s1->output_type == TCC_OUTPUT_MEMORY)
801 val = s1->plt->sh_addr;
802 #ifdef DEBUG_RELOC
803 printf ("reloc %d: x=0x%x val=0x%x ", type, x, val);
804 #endif
805 (*(int *)ptr) &= 0xff000000;
806 if (x & 0x800000)
807 x -= 0x1000000;
808 x <<= 2;
809 blx_avail = (TCC_ARM_VERSION >= 5);
810 is_thumb = val & 1;
811 is_bl = (*(unsigned *) ptr) >> 24 == 0xeb;
812 is_call = (type == R_ARM_CALL || (type == R_ARM_PC24 && is_bl));
813 x += val - addr;
814 #ifdef DEBUG_RELOC
815 printf (" newx=0x%x name=%s\n", x,
816 (char *) symtab_section->link->data + sym->st_name);
817 #endif
818 h = x & 2;
819 th_ko = (x & 3) && (!blx_avail || !is_call);
820 if (th_ko || x >= 0x2000000 || x < -0x2000000)
821 tcc_error("can't relocate value at %x,%d",addr, type);
822 x >>= 2;
823 x &= 0xffffff;
824 /* Only reached if blx is avail and it is a call */
825 if (is_thumb) {
826 x |= h << 24;
827 (*(int *)ptr) = 0xfa << 24; /* bl -> blx */
829 (*(int *) ptr) |= x;
831 break;
832 /* Since these relocations only concern Thumb-2 and blx instruction was
833 introduced before Thumb-2, we can assume blx is available and not
834 guard its use */
835 case R_ARM_THM_PC22:
836 case R_ARM_THM_JUMP24:
838 int x, hi, lo, s, j1, j2, i1, i2, imm10, imm11;
839 int to_thumb, is_call, to_plt, blx_bit = 1 << 12;
840 Section *plt;
842 /* weak reference */
843 if (sym->st_shndx == SHN_UNDEF &&
844 ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
845 break;
847 /* Get initial offset */
848 hi = (*(uint16_t *)ptr);
849 lo = (*(uint16_t *)(ptr+2));
850 s = (hi >> 10) & 1;
851 j1 = (lo >> 13) & 1;
852 j2 = (lo >> 11) & 1;
853 i1 = (j1 ^ s) ^ 1;
854 i2 = (j2 ^ s) ^ 1;
855 imm10 = hi & 0x3ff;
856 imm11 = lo & 0x7ff;
857 x = (s << 24) | (i1 << 23) | (i2 << 22) |
858 (imm10 << 12) | (imm11 << 1);
859 if (x & 0x01000000)
860 x -= 0x02000000;
862 /* Relocation infos */
863 to_thumb = val & 1;
864 plt = s1->plt;
865 to_plt = (val >= plt->sh_addr) &&
866 (val < plt->sh_addr + plt->data_offset);
867 is_call = (type == R_ARM_THM_PC22);
869 /* Compute final offset */
870 if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */
871 x -= 4;
872 x += val - addr;
873 if (!to_thumb && is_call) {
874 blx_bit = 0; /* bl -> blx */
875 x = (x + 3) & -4; /* Compute offset from aligned PC */
878 /* Check that relocation is possible
879 * offset must not be out of range
880 * if target is to be entered in arm mode:
881 - bit 1 must not set
882 - instruction must be a call (bl) or a jump to PLT */
883 if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
884 if (to_thumb || (val & 2) || (!is_call && !to_plt))
885 tcc_error("can't relocate value at %x,%d",addr, type);
887 /* Compute and store final offset */
888 s = (x >> 24) & 1;
889 i1 = (x >> 23) & 1;
890 i2 = (x >> 22) & 1;
891 j1 = s ^ (i1 ^ 1);
892 j2 = s ^ (i2 ^ 1);
893 imm10 = (x >> 12) & 0x3ff;
894 imm11 = (x >> 1) & 0x7ff;
895 (*(uint16_t *)ptr) = (uint16_t) ((hi & 0xf800) |
896 (s << 10) | imm10);
897 (*(uint16_t *)(ptr+2)) = (uint16_t) ((lo & 0xc000) |
898 (j1 << 13) | blx_bit | (j2 << 11) |
899 imm11);
901 break;
902 case R_ARM_MOVT_ABS:
903 case R_ARM_MOVW_ABS_NC:
905 int x, imm4, imm12;
906 if (type == R_ARM_MOVT_ABS)
907 val >>= 16;
908 imm12 = val & 0xfff;
909 imm4 = (val >> 12) & 0xf;
910 x = (imm4 << 16) | imm12;
911 if (type == R_ARM_THM_MOVT_ABS)
912 *(int *)ptr |= x;
913 else
914 *(int *)ptr += x;
916 break;
917 case R_ARM_THM_MOVT_ABS:
918 case R_ARM_THM_MOVW_ABS_NC:
920 int x, i, imm4, imm3, imm8;
921 if (type == R_ARM_THM_MOVT_ABS)
922 val >>= 16;
923 imm8 = val & 0xff;
924 imm3 = (val >> 8) & 0x7;
925 i = (val >> 11) & 1;
926 imm4 = (val >> 12) & 0xf;
927 x = (imm3 << 28) | (imm8 << 16) | (i << 10) | imm4;
928 if (type == R_ARM_THM_MOVT_ABS)
929 *(int *)ptr |= x;
930 else
931 *(int *)ptr += x;
933 break;
934 case R_ARM_PREL31:
936 int x;
937 x = (*(int *)ptr) & 0x7fffffff;
938 (*(int *)ptr) &= 0x80000000;
939 x = (x * 2) / 2;
940 x += val - addr;
941 if((x^(x>>1))&0x40000000)
942 tcc_error("can't relocate value at %x,%d",addr, type);
943 (*(int *)ptr) |= x & 0x7fffffff;
945 case R_ARM_ABS32:
946 *(int *)ptr += val;
947 break;
948 case R_ARM_REL32:
949 *(int *)ptr += val - addr;
950 break;
951 case R_ARM_GOTPC:
952 *(int *)ptr += s1->got->sh_addr - addr;
953 break;
954 case R_ARM_GOTOFF:
955 *(int *)ptr += val - s1->got->sh_addr;
956 break;
957 case R_ARM_GOT32:
958 /* we load the got offset */
959 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
960 break;
961 case R_ARM_COPY:
962 break;
963 case R_ARM_V4BX:
964 /* trade Thumb support for ARMv4 support */
965 if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
966 *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
967 break;
968 case R_ARM_GLOB_DAT:
969 case R_ARM_JUMP_SLOT:
970 *(addr_t *)ptr = val;
971 break;
972 case R_ARM_NONE:
973 /* Nothing to do. Normally used to indicate a dependency
974 on a certain symbol (like for exception handling under EABI). */
975 break;
976 #ifdef TCC_TARGET_PE
977 case R_ARM_RELATIVE: /* handled in pe_relocate_rva() */
978 break;
979 #endif
980 default:
981 fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
982 type, (unsigned)addr, ptr, (unsigned)val);
983 break;
984 #elif defined(TCC_TARGET_ARM64)
985 case R_AARCH64_ABS64:
986 write64le(ptr, val);
987 break;
988 case R_AARCH64_ABS32:
989 write32le(ptr, val);
990 break;
991 case R_AARCH64_PREL32:
992 write32le(ptr, val - addr);
993 break;
994 case R_AARCH64_MOVW_UABS_G0_NC:
995 write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
996 (val & 0xffff) << 5));
997 break;
998 case R_AARCH64_MOVW_UABS_G1_NC:
999 write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
1000 (val >> 16 & 0xffff) << 5));
1001 break;
1002 case R_AARCH64_MOVW_UABS_G2_NC:
1003 write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
1004 (val >> 32 & 0xffff) << 5));
1005 break;
1006 case R_AARCH64_MOVW_UABS_G3:
1007 write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
1008 (val >> 48 & 0xffff) << 5));
1009 break;
1010 case R_AARCH64_ADR_PREL_PG_HI21: {
1011 uint64_t off = (val >> 12) - (addr >> 12);
1012 if ((off + ((uint64_t)1 << 20)) >> 21)
1013 tcc_error("R_AARCH64_ADR_PREL_PG_HI21 relocation failed");
1014 write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
1015 (off & 0x1ffffc) << 3 | (off & 3) << 29));
1016 break;
1018 case R_AARCH64_ADD_ABS_LO12_NC:
1019 write32le(ptr, ((read32le(ptr) & 0xffc003ff) |
1020 (val & 0xfff) << 10));
1021 break;
1022 case R_AARCH64_JUMP26:
1023 case R_AARCH64_CALL26:
1024 /* This check must match the one in build_got_entries, testing
1025 if we really need a PLT slot. */
1026 if (sym->st_shndx == SHN_UNDEF ||
1027 s1->output_type == TCC_OUTPUT_MEMORY)
1028 /* We've put the PLT slot offset into r_addend when generating
1029 it, and that's what we must use as relocation value (adjusted
1030 by section offset of course). */
1031 val = s1->plt->sh_addr + rel->r_addend;
1032 #ifdef DEBUG_RELOC
1033 printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, val,
1034 (char *) symtab_section->link->data + sym->st_name);
1035 #endif
1036 if (((val - addr) + ((uint64_t)1 << 27)) & ~(uint64_t)0xffffffc)
1038 tcc_error("R_AARCH64_(JUMP|CALL)26 relocation failed (val=%lx, addr=%lx)", addr, val);
1040 write32le(ptr, (0x14000000 |
1041 (uint32_t)(type == R_AARCH64_CALL26) << 31 |
1042 ((val - addr) >> 2 & 0x3ffffff)));
1043 break;
1044 case R_AARCH64_ADR_GOT_PAGE: {
1045 uint64_t off =
1046 (((s1->got->sh_addr +
1047 s1->sym_attrs[sym_index].got_offset) >> 12) - (addr >> 12));
1048 if ((off + ((uint64_t)1 << 20)) >> 21)
1049 tcc_error("R_AARCH64_ADR_GOT_PAGE relocation failed");
1050 write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
1051 (off & 0x1ffffc) << 3 | (off & 3) << 29));
1052 break;
1054 case R_AARCH64_LD64_GOT_LO12_NC:
1055 write32le(ptr,
1056 ((read32le(ptr) & 0xfff803ff) |
1057 ((s1->got->sh_addr +
1058 s1->sym_attrs[sym_index].got_offset) & 0xff8) << 7));
1059 break;
1060 case R_AARCH64_COPY:
1061 break;
1062 case R_AARCH64_GLOB_DAT:
1063 case R_AARCH64_JUMP_SLOT:
1064 /* They don't need addend */
1065 #ifdef DEBUG_RELOC
1066 printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr,
1067 val - rel->r_addend,
1068 (char *) symtab_section->link->data + sym->st_name);
1069 #endif
1070 write64le(ptr, val - rel->r_addend);
1071 break;
1072 default:
1073 fprintf(stderr, "FIXME: handle reloc type %x at %x [%p] to %x\n",
1074 type, (unsigned)addr, ptr, (unsigned)val);
1075 break;
1076 #elif defined(TCC_TARGET_C67)
1077 case R_C60_32:
1078 *(int *)ptr += val;
1079 break;
1080 case R_C60LO16:
1082 uint32_t orig;
1084 /* put the low 16 bits of the absolute address
1085 add to what is already there */
1087 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
1088 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
1090 /* patch both at once - assumes always in pairs Low - High */
1092 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
1093 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
1095 break;
1096 case R_C60HI16:
1097 break;
1098 default:
1099 fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
1100 type, (unsigned)addr, ptr, (unsigned)val);
1101 break;
1102 #elif defined(TCC_TARGET_X86_64)
1103 case R_X86_64_64:
1104 if (s1->output_type == TCC_OUTPUT_DLL) {
1105 esym_index = s1->symtab_to_dynsym[sym_index];
1106 qrel->r_offset = rel->r_offset;
1107 if (esym_index) {
1108 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_64);
1109 qrel->r_addend = rel->r_addend;
1110 qrel++;
1111 break;
1112 } else {
1113 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
1114 qrel->r_addend = read64le(ptr) + val;
1115 qrel++;
1118 add64le(ptr, val);
1119 break;
1120 case R_X86_64_32:
1121 case R_X86_64_32S:
1122 if (s1->output_type == TCC_OUTPUT_DLL) {
1123 /* XXX: this logic may depend on TCC's codegen
1124 now TCC uses R_X86_64_32 even for a 64bit pointer */
1125 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
1126 /* Use sign extension! */
1127 qrel->r_addend = (int)read32le(ptr) + val;
1128 qrel++;
1130 add32le(ptr, val);
1131 break;
1133 case R_X86_64_PC32:
1134 if (s1->output_type == TCC_OUTPUT_DLL) {
1135 /* DLL relocation */
1136 esym_index = s1->symtab_to_dynsym[sym_index];
1137 if (esym_index) {
1138 qrel->r_offset = rel->r_offset;
1139 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
1140 /* Use sign extension! */
1141 qrel->r_addend = (int)read32le(ptr) + rel->r_addend;
1142 qrel++;
1143 break;
1146 goto plt32pc32;
1148 case R_X86_64_PLT32:
1149 /* We've put the PLT slot offset into r_addend when generating
1150 it, and that's what we must use as relocation value (adjusted
1151 by section offset of course). */
1152 val = s1->plt->sh_addr + rel->r_addend;
1153 /* fallthrough. */
1155 plt32pc32:
1157 long long diff;
1158 diff = (long long)val - addr;
1159 if (diff < -2147483648LL || diff > 2147483647LL) {
1160 tcc_error("internal error: relocation failed");
1162 add32le(ptr, diff);
1164 break;
1165 case R_X86_64_GLOB_DAT:
1166 case R_X86_64_JUMP_SLOT:
1167 /* They don't need addend */
1168 write64le(ptr, val - rel->r_addend);
1169 break;
1170 case R_X86_64_GOTPCREL:
1171 case R_X86_64_GOTPCRELX:
1172 case R_X86_64_REX_GOTPCRELX:
1173 add32le(ptr, s1->got->sh_addr - addr
1174 + s1->sym_attrs[sym_index].got_offset - 4);
1175 break;
1176 case R_X86_64_GOTTPOFF:
1177 add32le(ptr, val - s1->got->sh_addr);
1178 break;
1179 case R_X86_64_GOT32:
1180 /* we load the got offset */
1181 add32le(ptr, s1->sym_attrs[sym_index].got_offset);
1182 break;
1183 #ifdef TCC_TARGET_PE
1184 case R_X86_64_RELATIVE: /* handled in pe_relocate_rva() */
1185 break;
1186 #endif
1188 #else
1189 #error unsupported processor
1190 #endif
1193 /* if the relocation is allocated, we change its symbol table */
1194 if (sr->sh_flags & SHF_ALLOC)
1195 sr->link = s1->dynsym;
1198 /* relocate relocation table in 'sr' */
1199 static void relocate_rel(TCCState *s1, Section *sr)
1201 Section *s;
1202 ElfW_Rel *rel;
1204 s = s1->sections[sr->sh_info];
1205 for_each_elem(sr, 0, rel, ElfW_Rel)
1206 rel->r_offset += s->sh_addr;
1209 /* count the number of dynamic relocations so that we can reserve
1210 their space */
1211 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
1213 ElfW_Rel *rel;
1214 int sym_index, esym_index, type, count;
1216 count = 0;
1217 for_each_elem(sr, 0, rel, ElfW_Rel) {
1218 sym_index = ELFW(R_SYM)(rel->r_info);
1219 type = ELFW(R_TYPE)(rel->r_info);
1220 switch(type) {
1221 #if defined(TCC_TARGET_I386)
1222 case R_386_32:
1223 #elif defined(TCC_TARGET_X86_64)
1224 case R_X86_64_32:
1225 case R_X86_64_32S:
1226 case R_X86_64_64:
1227 #endif
1228 count++;
1229 break;
1230 #if defined(TCC_TARGET_I386)
1231 case R_386_PC32:
1232 #elif defined(TCC_TARGET_X86_64)
1233 case R_X86_64_PC32:
1234 #endif
1235 esym_index = s1->symtab_to_dynsym[sym_index];
1236 if (esym_index)
1237 count++;
1238 break;
1239 default:
1240 break;
1243 if (count) {
1244 /* allocate the section */
1245 sr->sh_flags |= SHF_ALLOC;
1246 sr->sh_size = count * sizeof(ElfW_Rel);
1248 return count;
1251 static struct sym_attr *alloc_sym_attr(TCCState *s1, int index)
1253 int n;
1254 struct sym_attr *tab;
1256 if (index >= s1->nb_sym_attrs) {
1257 /* find immediately bigger power of 2 and reallocate array */
1258 n = 1;
1259 while (index >= n)
1260 n *= 2;
1261 tab = tcc_realloc(s1->sym_attrs, n * sizeof(*s1->sym_attrs));
1262 s1->sym_attrs = tab;
1263 memset(s1->sym_attrs + s1->nb_sym_attrs, 0,
1264 (n - s1->nb_sym_attrs) * sizeof(*s1->sym_attrs));
1265 s1->nb_sym_attrs = n;
1267 return &s1->sym_attrs[index];
1270 static void build_got(TCCState *s1)
1272 unsigned char *ptr;
1274 /* if no got, then create it */
1275 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
1276 s1->got->sh_entsize = 4;
1277 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
1278 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
1279 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
1280 #if PTR_SIZE == 4
1281 /* keep space for _DYNAMIC pointer, if present */
1282 write32le(ptr, 0);
1283 /* two dummy got entries */
1284 write32le(ptr + 4, 0);
1285 write32le(ptr + 8, 0);
1286 #else
1287 /* keep space for _DYNAMIC pointer, if present */
1288 write32le(ptr, 0);
1289 write32le(ptr + 4, 0);
1290 /* two dummy got entries */
1291 write32le(ptr + 8, 0);
1292 write32le(ptr + 12, 0);
1293 write32le(ptr + 16, 0);
1294 write32le(ptr + 20, 0);
1295 #endif
1298 /* put a got or plt entry corresponding to a symbol in symtab_section. 'size'
1299 and 'info' can be modifed if more precise info comes from the DLL.
1300 Returns offset of GOT or PLT slot. */
1301 static unsigned long put_got_entry(TCCState *s1,
1302 int reloc_type, unsigned long size, int info,
1303 int sym_index)
1305 int index, need_plt_entry;
1306 const char *name;
1307 ElfW(Sym) *sym;
1308 unsigned long offset;
1309 int *ptr;
1310 struct sym_attr *symattr;
1312 if (!s1->got)
1313 build_got(s1);
1315 need_plt_entry =
1316 #ifdef TCC_TARGET_X86_64
1317 (reloc_type == R_X86_64_JUMP_SLOT);
1318 #elif defined(TCC_TARGET_I386)
1319 (reloc_type == R_386_JMP_SLOT);
1320 #elif defined(TCC_TARGET_ARM)
1321 (reloc_type == R_ARM_JUMP_SLOT);
1322 #elif defined(TCC_TARGET_ARM64)
1323 (reloc_type == R_AARCH64_JUMP_SLOT);
1324 #else
1326 #endif
1328 if (need_plt_entry && !s1->plt) {
1329 /* add PLT */
1330 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1331 SHF_ALLOC | SHF_EXECINSTR);
1332 s1->plt->sh_entsize = 4;
1335 /* If a got/plt entry already exists for that symbol, no need to add one */
1336 if (sym_index < s1->nb_sym_attrs) {
1337 if (need_plt_entry && s1->sym_attrs[sym_index].plt_offset)
1338 return s1->sym_attrs[sym_index].plt_offset;
1339 else if (!need_plt_entry && s1->sym_attrs[sym_index].got_offset)
1340 return s1->sym_attrs[sym_index].got_offset;
1343 symattr = alloc_sym_attr(s1, sym_index);
1345 /* Only store the GOT offset if it's not generated for the PLT entry. */
1346 if (!need_plt_entry)
1347 symattr->got_offset = s1->got->data_offset;
1349 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1350 name = (char *) symtab_section->link->data + sym->st_name;
1351 offset = sym->st_value;
1352 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1353 if (need_plt_entry) {
1354 Section *plt;
1355 uint8_t *p;
1356 int modrm;
1357 unsigned long relofs;
1359 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1360 modrm = 0x25;
1361 #else
1362 /* if we build a DLL, we add a %ebx offset */
1363 if (s1->output_type == TCC_OUTPUT_DLL)
1364 modrm = 0xa3;
1365 else
1366 modrm = 0x25;
1367 #endif
1369 /* add a PLT entry */
1370 plt = s1->plt;
1371 if (plt->data_offset == 0) {
1372 /* first plt entry */
1373 p = section_ptr_add(plt, 16);
1374 p[0] = 0xff; /* pushl got + PTR_SIZE */
1375 p[1] = modrm + 0x10;
1376 write32le(p + 2, PTR_SIZE);
1377 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1378 p[7] = modrm;
1379 write32le(p + 8, PTR_SIZE * 2);
1382 /* The PLT slot refers to the relocation entry it needs
1383 via offset. The reloc entry is created below, so its
1384 offset is the current data_offset. */
1385 relofs = s1->got->reloc ? s1->got->reloc->data_offset : 0;
1386 symattr->plt_offset = plt->data_offset;
1387 p = section_ptr_add(plt, 16);
1388 p[0] = 0xff; /* jmp *(got + x) */
1389 p[1] = modrm;
1390 write32le(p + 2, s1->got->data_offset);
1391 p[6] = 0x68; /* push $xxx */
1392 #ifdef TCC_TARGET_X86_64
1393 /* On x86-64, the relocation is referred to by _index_. */
1394 write32le(p + 7, relofs / sizeof (ElfW_Rel));
1395 #else
1396 write32le(p + 7, relofs);
1397 #endif
1398 p[11] = 0xe9; /* jmp plt_start */
1399 write32le(p + 12, -(plt->data_offset));
1401 /* If this was an UNDEF symbol set the offset in the
1402 dynsymtab to the PLT slot, so that PC32 relocs to it
1403 can be resolved. */
1404 if (sym->st_shndx == SHN_UNDEF)
1405 offset = plt->data_offset - 16;
1407 #elif defined(TCC_TARGET_ARM)
1408 if (need_plt_entry) {
1409 Section *plt;
1410 uint8_t *p;
1412 /* if we build a DLL, we add a %ebx offset */
1413 if (s1->output_type == TCC_OUTPUT_DLL)
1414 tcc_error("DLLs unimplemented!");
1416 /* add a PLT entry */
1417 plt = s1->plt;
1418 if (plt->data_offset == 0) {
1419 /* first plt entry */
1420 p = section_ptr_add(plt, 16);
1421 write32le(p, 0xe52de004); /* push {lr} */
1422 write32le(p+4, 0xe59fe010); /* ldr lr, [pc, #16] */
1423 write32le(p+8, 0xe08fe00e); /* add lr, pc, lr */
1424 write32le(p+12, 0xe5bef008); /* ldr pc, [lr, #8]! */
1427 symattr->plt_offset = plt->data_offset;
1428 if (symattr->plt_thumb_stub) {
1429 p = section_ptr_add(plt, 20);
1430 write32le(p, 0x4778); /* bx pc */
1431 write32le(p+2, 0x46c0); /* nop */
1432 p += 4;
1433 } else
1434 p = section_ptr_add(plt, 16);
1435 write32le(p, 0xe59fc004); /* ldr ip, [pc, #4] ; GOT entry offset */
1436 write32le(p+4, 0xe08fc00c); /* add ip, pc, ip ; addr of GOT entry */
1437 write32le(p+8, 0xe59cf000); /* ldr pc, [ip] ; jump to GOT entry */
1438 write32le(p+12, s1->got->data_offset); /* GOT entry off once patched */
1440 /* the symbol is modified so that it will be relocated to
1441 the PLT */
1442 if (sym->st_shndx == SHN_UNDEF)
1443 offset = plt->data_offset - 16;
1445 #elif defined(TCC_TARGET_ARM64)
1446 if (need_plt_entry) {
1447 Section *plt;
1448 uint8_t *p;
1450 if (s1->output_type == TCC_OUTPUT_DLL)
1451 tcc_error("DLLs unimplemented!");
1453 plt = s1->plt;
1454 if (plt->data_offset == 0)
1455 section_ptr_add(plt, 32);
1456 symattr->plt_offset = plt->data_offset;
1457 p = section_ptr_add(plt, 16);
1458 write32le(p, s1->got->data_offset);
1459 write32le(p + 4, (uint64_t)s1->got->data_offset >> 32);
1461 if (sym->st_shndx == SHN_UNDEF)
1462 offset = plt->data_offset - 16;
1464 #elif defined(TCC_TARGET_C67)
1465 if (s1->dynsym) {
1466 tcc_error("C67 got not implemented");
1468 #else
1469 #error unsupported CPU
1470 #endif
1471 if (s1->dynsym) {
1472 /* XXX This might generate multiple syms for name. */
1473 index = put_elf_sym(s1->dynsym, offset,
1474 size, info, 0, sym->st_shndx, name);
1475 /* Create the relocation (it's against the GOT for PLT
1476 and GOT relocs). */
1477 put_elf_reloc(s1->dynsym, s1->got,
1478 s1->got->data_offset,
1479 reloc_type, index);
1480 } else {
1481 /* Without .dynsym (i.e. static link or memory output) we
1482 still need relocs against the generated got, so as to fill
1483 the entries with the symbol values (determined later). */
1484 put_elf_reloc(symtab_section, s1->got,
1485 s1->got->data_offset,
1486 reloc_type, sym_index);
1488 /* And now create the GOT slot itself. */
1489 ptr = section_ptr_add(s1->got, PTR_SIZE);
1490 *ptr = 0;
1491 if (need_plt_entry)
1492 return symattr->plt_offset;
1493 else
1494 return symattr->got_offset;
1497 /* build GOT and PLT entries */
1498 ST_FUNC void build_got_entries(TCCState *s1)
1500 Section *s;
1501 ElfW_Rel *rel;
1502 ElfW(Sym) *sym;
1503 int i, type, reloc_type, sym_index;
1505 for(i = 1; i < s1->nb_sections; i++) {
1506 s = s1->sections[i];
1507 if (s->sh_type != SHT_RELX)
1508 continue;
1509 /* no need to handle got relocations */
1510 if (s->link != symtab_section)
1511 continue;
1512 for_each_elem(s, 0, rel, ElfW_Rel) {
1513 type = ELFW(R_TYPE)(rel->r_info);
1514 switch(type) {
1515 #if defined(TCC_TARGET_I386)
1516 case R_386_GOT32:
1517 case R_386_GOT32X:
1518 case R_386_GOTOFF:
1519 case R_386_GOTPC:
1520 case R_386_PLT32:
1521 if (!s1->got)
1522 build_got(s1);
1523 if (type == R_386_GOT32 || type == R_386_GOT32X ||
1524 type == R_386_PLT32) {
1525 sym_index = ELFW(R_SYM)(rel->r_info);
1526 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1527 /* look at the symbol got offset. If none, then add one */
1528 if (type == R_386_GOT32 || type == R_386_GOT32X)
1529 reloc_type = R_386_GLOB_DAT;
1530 else
1531 reloc_type = R_386_JMP_SLOT;
1532 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1533 sym_index);
1535 break;
1536 #elif defined(TCC_TARGET_ARM)
1537 case R_ARM_PC24:
1538 case R_ARM_CALL:
1539 case R_ARM_JUMP24:
1540 case R_ARM_GOT32:
1541 case R_ARM_GOTOFF:
1542 case R_ARM_GOTPC:
1543 case R_ARM_PLT32:
1544 if (!s1->got)
1545 build_got(s1);
1546 sym_index = ELFW(R_SYM)(rel->r_info);
1547 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1548 if (type != R_ARM_GOTOFF && type != R_ARM_GOTPC
1549 && (sym->st_shndx == SHN_UNDEF
1550 || s1->output_type == TCC_OUTPUT_MEMORY)) {
1551 unsigned long ofs;
1552 /* look at the symbol got offset. If none, then add one */
1553 if (type == R_ARM_GOT32)
1554 reloc_type = R_ARM_GLOB_DAT;
1555 else
1556 reloc_type = R_ARM_JUMP_SLOT;
1557 ofs = put_got_entry(s1, reloc_type, sym->st_size,
1558 sym->st_info, sym_index);
1559 #ifdef DEBUG_RELOC
1560 printf ("maybegot: %s, %d, %d --> ofs=0x%x\n",
1561 (char *) symtab_section->link->data + sym->st_name,
1562 type, sym->st_shndx, ofs);
1563 #endif
1564 if (type != R_ARM_GOT32) {
1565 addr_t *ptr = (addr_t*)(s1->sections[s->sh_info]->data
1566 + rel->r_offset);
1567 /* x must be signed! */
1568 int x = *ptr & 0xffffff;
1569 x = (x << 8) >> 8;
1570 x <<= 2;
1571 x += ofs;
1572 x >>= 2;
1573 #ifdef DEBUG_RELOC
1574 printf ("insn=0x%x --> 0x%x (x==0x%x)\n", *ptr,
1575 (*ptr & 0xff000000) | x, x);
1576 #endif
1577 *ptr = (*ptr & 0xff000000) | x;
1580 break;
1581 case R_ARM_THM_JUMP24:
1582 sym_index = ELFW(R_SYM)(rel->r_info);
1583 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1584 /* We are relocating a jump from thumb code to arm code */
1585 if (sym->st_shndx != SHN_UNDEF && !(sym->st_value & 1)) {
1586 int index;
1587 uint8_t *p;
1588 char *name, buf[1024];
1589 Section *text_section;
1591 name = (char *) symtab_section->link->data + sym->st_name;
1592 text_section = s1->sections[sym->st_shndx];
1593 /* Modify reloc to target a thumb stub to switch to ARM */
1594 snprintf(buf, sizeof(buf), "%s_from_thumb", name);
1595 index = put_elf_sym(symtab_section,
1596 text_section->data_offset + 1,
1597 sym->st_size, sym->st_info, 0,
1598 sym->st_shndx, buf);
1599 rel->r_info = ELFW(R_INFO)(index, type);
1600 /* Create a thumb stub fonction to switch to ARM mode */
1601 put_elf_reloc(symtab_section, text_section,
1602 text_section->data_offset + 4, R_ARM_JUMP24,
1603 sym_index);
1604 p = section_ptr_add(text_section, 8);
1605 write32le(p, 0x4778); /* bx pc */
1606 write32le(p+2, 0x46c0); /* nop */
1607 write32le(p+4, 0xeafffffe); /* b $sym */
1609 #elif defined(TCC_TARGET_ARM64)
1610 //xx Other cases may be required here:
1611 case R_AARCH64_ADR_GOT_PAGE:
1612 case R_AARCH64_LD64_GOT_LO12_NC:
1613 if (!s1->got)
1614 build_got(s1);
1615 sym_index = ELFW(R_SYM)(rel->r_info);
1616 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1617 reloc_type = R_AARCH64_GLOB_DAT;
1618 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1619 sym_index);
1620 break;
1622 case R_AARCH64_JUMP26:
1623 case R_AARCH64_CALL26:
1624 if (!s1->got)
1625 build_got(s1);
1626 sym_index = ELFW(R_SYM)(rel->r_info);
1627 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1628 if (sym->st_shndx == SHN_UNDEF ||
1629 s1->output_type == TCC_OUTPUT_MEMORY) {
1630 unsigned long ofs;
1631 reloc_type = R_AARCH64_JUMP_SLOT;
1632 ofs = put_got_entry(s1, reloc_type, sym->st_size,
1633 sym->st_info, sym_index);
1634 /* We store the place of the generated PLT slot
1635 in our addend. */
1636 rel->r_addend += ofs;
1638 break;
1639 #elif defined(TCC_TARGET_C67)
1640 case R_C60_GOT32:
1641 case R_C60_GOTOFF:
1642 case R_C60_GOTPC:
1643 case R_C60_PLT32:
1644 if (!s1->got)
1645 build_got(s1);
1646 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1647 sym_index = ELFW(R_SYM)(rel->r_info);
1648 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1649 /* look at the symbol got offset. If none, then add one */
1650 if (type == R_C60_GOT32)
1651 reloc_type = R_C60_GLOB_DAT;
1652 else
1653 reloc_type = R_C60_JMP_SLOT;
1654 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1655 sym_index);
1657 break;
1658 #elif defined(TCC_TARGET_X86_64)
1659 case R_X86_64_GOT32:
1660 case R_X86_64_GOTTPOFF:
1661 case R_X86_64_GOTPCREL:
1662 case R_X86_64_GOTPCRELX:
1663 case R_X86_64_REX_GOTPCRELX:
1664 case R_X86_64_PLT32:
1665 sym_index = ELFW(R_SYM)(rel->r_info);
1666 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1667 if (type == R_X86_64_PLT32 &&
1668 ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT)
1670 rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32);
1671 break;
1674 if (!s1->got) {
1675 build_got(s1);
1676 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1678 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1679 type == R_X86_64_GOTPCRELX ||
1680 type == R_X86_64_REX_GOTPCRELX ||
1681 type == R_X86_64_PLT32) {
1682 unsigned long ofs;
1683 /* look at the symbol got offset. If none, then add one */
1684 if (type == R_X86_64_PLT32)
1685 reloc_type = R_X86_64_JUMP_SLOT;
1686 else
1687 reloc_type = R_X86_64_GLOB_DAT;
1688 ofs = put_got_entry(s1, reloc_type, sym->st_size,
1689 sym->st_info, sym_index);
1690 if (type == R_X86_64_PLT32)
1691 /* We store the place of the generated PLT slot
1692 in our addend. */
1693 rel->r_addend += ofs;
1695 break;
1696 #else
1697 #error unsupported CPU
1698 #endif
1699 default:
1700 break;
1706 ST_FUNC Section *new_symtab(TCCState *s1,
1707 const char *symtab_name, int sh_type, int sh_flags,
1708 const char *strtab_name,
1709 const char *hash_name, int hash_sh_flags)
1711 Section *symtab, *strtab, *hash;
1712 int *ptr, nb_buckets;
1714 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1715 symtab->sh_entsize = sizeof(ElfW(Sym));
1716 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1717 put_elf_str(strtab, "");
1718 symtab->link = strtab;
1719 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1721 nb_buckets = 1;
1723 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1724 hash->sh_entsize = sizeof(int);
1725 symtab->hash = hash;
1726 hash->link = symtab;
1728 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1729 ptr[0] = nb_buckets;
1730 ptr[1] = 1;
1731 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1732 return symtab;
1735 /* put dynamic tag */
1736 static void put_dt(Section *dynamic, int dt, addr_t val)
1738 ElfW(Dyn) *dyn;
1739 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1740 dyn->d_tag = dt;
1741 dyn->d_un.d_val = val;
1744 #ifndef TCC_TARGET_PE
1745 static void add_init_array_defines(TCCState *s1, const char *section_name)
1747 Section *s;
1748 long end_offset;
1749 char sym_start[1024];
1750 char sym_end[1024];
1752 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1753 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1755 s = find_section(s1, section_name);
1756 if (!s) {
1757 end_offset = 0;
1758 s = data_section;
1759 } else {
1760 end_offset = s->data_offset;
1763 add_elf_sym(symtab_section,
1764 0, 0,
1765 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1766 s->sh_num, sym_start);
1767 add_elf_sym(symtab_section,
1768 end_offset, 0,
1769 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1770 s->sh_num, sym_end);
1772 #endif
1774 static int tcc_add_support(TCCState *s1, const char *filename)
1776 char buf[1024];
1777 snprintf(buf, sizeof(buf), "%s/"TCC_ARCH_DIR"%s", s1->tcc_lib_path, filename);
1778 return tcc_add_file(s1, buf);
1781 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1783 #ifdef CONFIG_TCC_BCHECK
1784 addr_t *ptr;
1785 int sym_index;
1787 if (0 == s1->do_bounds_check)
1788 return;
1789 /* XXX: add an object file to do that */
1790 ptr = section_ptr_add(bounds_section, sizeof(*ptr));
1791 *ptr = 0;
1792 add_elf_sym(symtab_section, 0, 0,
1793 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1794 bounds_section->sh_num, "__bounds_start");
1795 /* pull bcheck.o from libtcc1.a */
1796 sym_index = add_elf_sym(symtab_section, 0, 0,
1797 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1798 SHN_UNDEF, "__bound_init");
1799 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1800 /* add 'call __bound_init()' in .init section */
1801 Section *init_section = find_section(s1, ".init");
1802 unsigned char *pinit = section_ptr_add(init_section, 5);
1803 pinit[0] = 0xe8;
1804 write32le(pinit + 1, -4);
1805 put_elf_reloc(symtab_section, init_section,
1806 init_section->data_offset - 4, R_386_PC32, sym_index);
1807 /* R_386_PC32 = R_X86_64_PC32 = 2 */
1809 #endif
1812 /* add tcc runtime libraries */
1813 ST_FUNC void tcc_add_runtime(TCCState *s1)
1815 tcc_add_bcheck(s1);
1816 tcc_add_pragma_libs(s1);
1817 /* add libc */
1818 if (!s1->nostdlib) {
1819 tcc_add_library_err(s1, "c");
1820 #ifdef CONFIG_USE_LIBGCC
1821 if (!s1->static_link) {
1822 tcc_add_file(s1, TCC_LIBGCC);
1824 #endif
1825 tcc_add_support(s1, "libtcc1.a");
1826 /* add crt end if not memory output */
1827 if (s1->output_type != TCC_OUTPUT_MEMORY)
1828 tcc_add_crt(s1, "crtn.o");
1832 /* add various standard linker symbols (must be done after the
1833 sections are filled (for example after allocating common
1834 symbols)) */
1835 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1837 char buf[1024];
1838 int i;
1839 Section *s;
1841 add_elf_sym(symtab_section,
1842 text_section->data_offset, 0,
1843 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1844 text_section->sh_num, "_etext");
1845 add_elf_sym(symtab_section,
1846 data_section->data_offset, 0,
1847 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1848 data_section->sh_num, "_edata");
1849 add_elf_sym(symtab_section,
1850 bss_section->data_offset, 0,
1851 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1852 bss_section->sh_num, "_end");
1853 #ifndef TCC_TARGET_PE
1854 /* horrible new standard ldscript defines */
1855 add_init_array_defines(s1, ".preinit_array");
1856 add_init_array_defines(s1, ".init_array");
1857 add_init_array_defines(s1, ".fini_array");
1858 #endif
1860 /* add start and stop symbols for sections whose name can be
1861 expressed in C */
1862 for(i = 1; i < s1->nb_sections; i++) {
1863 s = s1->sections[i];
1864 if (s->sh_type == SHT_PROGBITS &&
1865 (s->sh_flags & SHF_ALLOC)) {
1866 const char *p;
1867 int ch;
1869 /* check if section name can be expressed in C */
1870 p = s->name;
1871 for(;;) {
1872 ch = *p;
1873 if (!ch)
1874 break;
1875 if (!isid(ch) && !isnum(ch))
1876 goto next_sec;
1877 p++;
1879 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1880 add_elf_sym(symtab_section,
1881 0, 0,
1882 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1883 s->sh_num, buf);
1884 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1885 add_elf_sym(symtab_section,
1886 s->data_offset, 0,
1887 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1888 s->sh_num, buf);
1890 next_sec: ;
1894 static void tcc_output_binary(TCCState *s1, FILE *f,
1895 const int *sec_order)
1897 Section *s;
1898 int i, offset, size;
1900 offset = 0;
1901 for(i=1;i<s1->nb_sections;i++) {
1902 s = s1->sections[sec_order[i]];
1903 if (s->sh_type != SHT_NOBITS &&
1904 (s->sh_flags & SHF_ALLOC)) {
1905 while (offset < s->sh_offset) {
1906 fputc(0, f);
1907 offset++;
1909 size = s->sh_size;
1910 fwrite(s->data, 1, size, f);
1911 offset += size;
1916 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1917 #define HAVE_PHDR 1
1918 #define EXTRA_RELITEMS 14
1920 /* move the relocation value from .dynsym to .got */
1921 static void patch_dynsym_undef(TCCState *s1, Section *s)
1923 uint32_t *gotd = (void *)s1->got->data;
1924 ElfW(Sym) *sym;
1926 gotd += 3; /* dummy entries in .got */
1927 /* relocate symbols in .dynsym */
1928 for_each_elem(s, 1, sym, ElfW(Sym)) {
1929 if (sym->st_shndx == SHN_UNDEF) {
1930 *gotd++ = sym->st_value + 6; /* XXX 6 is magic ? */
1931 sym->st_value = 0;
1935 #else
1936 #define HAVE_PHDR 1
1937 #define EXTRA_RELITEMS 9
1939 /* zero plt offsets of weak symbols in .dynsym */
1940 static void patch_dynsym_undef(TCCState *s1, Section *s)
1942 ElfW(Sym) *sym;
1944 for_each_elem(s, 1, sym, ElfW(Sym))
1945 if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
1946 sym->st_value = 0;
1948 #endif
1950 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1952 int sym_index = ELFW(R_SYM) (rel->r_info);
1953 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1954 unsigned long offset;
1956 if (sym_index >= s1->nb_sym_attrs)
1957 return;
1958 offset = s1->sym_attrs[sym_index].got_offset;
1959 section_reserve(s1->got, offset + PTR_SIZE);
1960 #ifdef TCC_TARGET_X86_64
1961 /* only works for x86-64 */
1962 write32le(s1->got->data + offset + 4, sym->st_value >> 32);
1963 #endif
1964 write32le(s1->got->data + offset, sym->st_value & 0xffffffff);
1967 /* Perform relocation to GOT or PLT entries */
1968 ST_FUNC void fill_got(TCCState *s1)
1970 Section *s;
1971 ElfW_Rel *rel;
1972 int i;
1974 for(i = 1; i < s1->nb_sections; i++) {
1975 s = s1->sections[i];
1976 if (s->sh_type != SHT_RELX)
1977 continue;
1978 /* no need to handle got relocations */
1979 if (s->link != symtab_section)
1980 continue;
1981 for_each_elem(s, 0, rel, ElfW_Rel) {
1982 switch (ELFW(R_TYPE) (rel->r_info)) {
1983 case R_X86_64_GOT32:
1984 case R_X86_64_GOTPCREL:
1985 case R_X86_64_GOTPCRELX:
1986 case R_X86_64_REX_GOTPCRELX:
1987 case R_X86_64_PLT32:
1988 fill_got_entry(s1, rel);
1989 break;
1995 /* Bind symbols of executable: resolve undefined symbols from exported symbols
1996 in shared libraries and export non local defined symbols to shared libraries
1997 if -rdynamic switch was given on command line */
1998 static void bind_exe_dynsyms(TCCState *s1)
2000 const char *name;
2001 int sym_index, index;
2002 ElfW(Sym) *sym, *esym;
2003 int type;
2005 /* Resolve undefined symbols from dynamic symbols. When there is a match:
2006 - if STT_FUNC or STT_GNU_IFUNC symbol -> add it in PLT
2007 - if STT_OBJECT symbol -> add it in .bss section with suitable reloc */
2008 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
2009 if (sym->st_shndx == SHN_UNDEF) {
2010 name = (char *) symtab_section->link->data + sym->st_name;
2011 sym_index = find_elf_sym(s1->dynsymtab_section, name);
2012 if (sym_index) {
2013 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
2014 type = ELFW(ST_TYPE)(esym->st_info);
2015 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
2016 /* Indirect functions shall have STT_FUNC type in executable
2017 * dynsym section. Indeed, a dlsym call following a lazy
2018 * resolution would pick the symbol value from the
2019 * executable dynsym entry which would contain the address
2020 * of the function wanted by the caller of dlsym instead of
2021 * the address of the function that would return that
2022 * address */
2023 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
2024 ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC),
2025 sym - (ElfW(Sym) *)symtab_section->data);
2026 } else if (type == STT_OBJECT) {
2027 unsigned long offset;
2028 ElfW(Sym) *dynsym;
2029 offset = bss_section->data_offset;
2030 /* XXX: which alignment ? */
2031 offset = (offset + 16 - 1) & -16;
2032 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
2033 esym->st_info, 0, bss_section->sh_num,
2034 name);
2035 /* Ensure R_COPY works for weak symbol aliases */
2036 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
2037 for_each_elem(s1->dynsymtab_section, 1, dynsym, ElfW(Sym)) {
2038 if ((dynsym->st_value == esym->st_value)
2039 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
2040 char *dynname = (char *) s1->dynsymtab_section->link->data
2041 + dynsym->st_name;
2042 put_elf_sym(s1->dynsym, offset, dynsym->st_size,
2043 dynsym->st_info, 0,
2044 bss_section->sh_num, dynname);
2045 break;
2049 put_elf_reloc(s1->dynsym, bss_section,
2050 offset, R_COPY, index);
2051 offset += esym->st_size;
2052 bss_section->data_offset = offset;
2054 } else {
2055 /* STB_WEAK undefined symbols are accepted */
2056 /* XXX: _fp_hw seems to be part of the ABI, so we ignore it */
2057 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
2058 !strcmp(name, "_fp_hw")) {
2059 } else {
2060 tcc_error_noabort("undefined symbol '%s'", name);
2063 } else if (s1->rdynamic && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2064 /* if -rdynamic option, then export all non local symbols */
2065 name = (char *) symtab_section->link->data + sym->st_name;
2066 add_elf_sym(s1->dynsym, sym->st_value, sym->st_size, sym->st_info,
2067 0, sym->st_shndx, name);
2072 /* Bind symbols of libraries: export all non local symbols of executable that
2073 are referenced by shared libraries. The reason is that the dynamic loader
2074 search symbol first in executable and then in libraries. Therefore a
2075 reference to a symbol already defined by a library can still be resolved by
2076 a symbol in the executable. */
2077 static void bind_libs_dynsyms(TCCState *s1)
2079 const char *name;
2080 int sym_index;
2081 ElfW(Sym) *sym, *esym;
2083 for_each_elem(s1->dynsymtab_section, 1, esym, ElfW(Sym)) {
2084 name = (char *) s1->dynsymtab_section->link->data + esym->st_name;
2085 sym_index = find_elf_sym(symtab_section, name);
2086 /* XXX: avoid adding a symbol if already present because of
2087 -rdynamic ? */
2088 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2089 if (sym_index && sym->st_shndx != SHN_UNDEF)
2090 add_elf_sym(s1->dynsym, sym->st_value, sym->st_size, sym->st_info,
2091 0, sym->st_shndx, name);
2092 else if (esym->st_shndx == SHN_UNDEF) {
2093 /* weak symbols can stay undefined */
2094 if (ELFW(ST_BIND)(esym->st_info) != STB_WEAK)
2095 tcc_warning("undefined dynamic symbol '%s'", name);
2100 /* Export all non local symbols. This is used by shared libraries so that the
2101 non local symbols they define can resolve a reference in another shared
2102 library or in the executable. Correspondingly, it allows undefined local
2103 symbols to be resolved by other shared libraries or by the executable. */
2104 static void export_global_syms(TCCState *s1)
2106 int nb_syms, dynindex, index;
2107 const char *name;
2108 ElfW(Sym) *sym;
2110 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
2111 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
2112 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
2113 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2114 name = (char *) symtab_section->link->data + sym->st_name;
2115 dynindex = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
2116 sym->st_info, 0, sym->st_shndx, name);
2117 index = sym - (ElfW(Sym) *) symtab_section->data;
2118 s1->symtab_to_dynsym[index] = dynindex;
2123 /* relocate the PLT: compute addresses and offsets in the PLT now that final
2124 address for PLT and GOT are known (see fill_program_header) */
2125 ST_FUNC void relocate_plt(TCCState *s1)
2127 uint8_t *p, *p_end;
2129 if (!s1->plt)
2130 return;
2132 p = s1->plt->data;
2133 p_end = p + s1->plt->data_offset;
2134 if (p < p_end) {
2135 #if defined(TCC_TARGET_I386)
2136 add32le(p + 2, s1->got->sh_addr);
2137 add32le(p + 8, s1->got->sh_addr);
2138 p += 16;
2139 while (p < p_end) {
2140 add32le(p + 2, s1->got->sh_addr);
2141 p += 16;
2143 #elif defined(TCC_TARGET_X86_64)
2144 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
2145 add32le(p + 2, x);
2146 add32le(p + 8, x - 6);
2147 p += 16;
2148 while (p < p_end) {
2149 add32le(p + 2, x + s1->plt->data - p);
2150 p += 16;
2152 #elif defined(TCC_TARGET_ARM)
2153 int x = s1->got->sh_addr - s1->plt->sh_addr - 12;
2154 p += 16;
2155 while (p < p_end) {
2156 if (read32le(p) == 0x46c04778) /* PLT Thumb stub present */
2157 p += 4;
2158 add32le(p + 12, x + s1->plt->data - p);
2159 p += 16;
2161 #elif defined(TCC_TARGET_ARM64)
2162 uint64_t plt = s1->plt->sh_addr;
2163 uint64_t got = s1->got->sh_addr;
2164 uint64_t off = (got >> 12) - (plt >> 12);
2165 if ((off + ((uint32_t)1 << 20)) >> 21)
2166 tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", off, got, plt);
2167 write32le(p, 0xa9bf7bf0); // stp x16,x30,[sp,#-16]!
2168 write32le(p + 4, (0x90000010 | // adrp x16,...
2169 (off & 0x1ffffc) << 3 | (off & 3) << 29));
2170 write32le(p + 8, (0xf9400211 | // ldr x17,[x16,#...]
2171 (got & 0xff8) << 7));
2172 write32le(p + 12, (0x91000210 | // add x16,x16,#...
2173 (got & 0xfff) << 10));
2174 write32le(p + 16, 0xd61f0220); // br x17
2175 write32le(p + 20, 0xd503201f); // nop
2176 write32le(p + 24, 0xd503201f); // nop
2177 write32le(p + 28, 0xd503201f); // nop
2178 p += 32;
2179 while (p < p_end) {
2180 uint64_t pc = plt + (p - s1->plt->data);
2181 uint64_t addr = got + read64le(p);
2182 uint64_t off = (addr >> 12) - (pc >> 12);
2183 if ((off + ((uint32_t)1 << 20)) >> 21)
2184 tcc_error("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", off, addr, pc);
2185 write32le(p, (0x90000010 | // adrp x16,...
2186 (off & 0x1ffffc) << 3 | (off & 3) << 29));
2187 write32le(p + 4, (0xf9400211 | // ldr x17,[x16,#...]
2188 (addr & 0xff8) << 7));
2189 write32le(p + 8, (0x91000210 | // add x16,x16,#...
2190 (addr & 0xfff) << 10));
2191 write32le(p + 12, 0xd61f0220); // br x17
2192 p += 16;
2194 #elif defined(TCC_TARGET_C67)
2195 /* XXX: TODO */
2196 #else
2197 #error unsupported CPU
2198 #endif
2202 /* Allocate strings for section names and decide if an unallocated section
2203 should be output.
2205 NOTE: the strsec section comes last, so its size is also correct ! */
2206 static void alloc_sec_names(TCCState *s1, int file_type, Section *strsec)
2208 int i;
2209 Section *s;
2211 /* Allocate strings for section names */
2212 for(i = 1; i < s1->nb_sections; i++) {
2213 s = s1->sections[i];
2214 s->sh_name = put_elf_str(strsec, s->name);
2215 /* when generating a DLL, we include relocations but we may
2216 patch them */
2217 if (file_type == TCC_OUTPUT_DLL &&
2218 s->sh_type == SHT_RELX &&
2219 !(s->sh_flags & SHF_ALLOC)) {
2220 /* gr: avoid bogus relocs for empty (debug) sections */
2221 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
2222 prepare_dynamic_rel(s1, s);
2223 else if (s1->do_debug)
2224 s->sh_size = s->data_offset;
2225 } else if (s1->do_debug ||
2226 file_type == TCC_OUTPUT_OBJ ||
2227 (s->sh_flags & SHF_ALLOC) ||
2228 i == (s1->nb_sections - 1)) {
2229 /* we output all sections if debug or object file */
2230 s->sh_size = s->data_offset;
2235 /* Info to be copied in dynamic section */
2236 struct dyn_inf {
2237 Section *dynamic;
2238 Section *dynstr;
2239 unsigned long dyn_rel_off;
2240 addr_t rel_addr;
2241 addr_t rel_size;
2242 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2243 addr_t bss_addr;
2244 addr_t bss_size;
2245 #endif
2248 /* Assign sections to segments and decide how are sections laid out when loaded
2249 in memory. This function also fills corresponding program headers. */
2250 static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
2251 Section *interp, Section* strsec,
2252 struct dyn_inf *dyninf, int *sec_order)
2254 int i, j, k, file_type, sh_order_index, file_offset;
2255 unsigned long s_align;
2256 long long tmp;
2257 addr_t addr;
2258 ElfW(Phdr) *ph;
2259 Section *s;
2261 file_type = s1->output_type;
2262 sh_order_index = 1;
2263 file_offset = 0;
2264 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
2265 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2266 s_align = ELF_PAGE_SIZE;
2267 if (s1->section_align)
2268 s_align = s1->section_align;
2270 if (phnum > 0) {
2271 if (s1->has_text_addr) {
2272 int a_offset, p_offset;
2273 addr = s1->text_addr;
2274 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
2275 ELF_PAGE_SIZE */
2276 a_offset = (int) (addr & (s_align - 1));
2277 p_offset = file_offset & (s_align - 1);
2278 if (a_offset < p_offset)
2279 a_offset += s_align;
2280 file_offset += (a_offset - p_offset);
2281 } else {
2282 if (file_type == TCC_OUTPUT_DLL)
2283 addr = 0;
2284 else
2285 addr = ELF_START_ADDR;
2286 /* compute address after headers */
2287 addr += (file_offset & (s_align - 1));
2290 ph = &phdr[0];
2291 /* Leave one program headers for the program interpreter and one for
2292 the program header table itself if needed. These are done later as
2293 they require section layout to be done first. */
2294 if (interp)
2295 ph += 1 + HAVE_PHDR;
2297 /* dynamic relocation table information, for .dynamic section */
2298 dyninf->rel_addr = dyninf->rel_size = 0;
2299 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2300 dyninf->bss_addr = dyninf->bss_size = 0;
2301 #endif
2303 for(j = 0; j < 2; j++) {
2304 ph->p_type = PT_LOAD;
2305 if (j == 0)
2306 ph->p_flags = PF_R | PF_X;
2307 else
2308 ph->p_flags = PF_R | PF_W;
2309 ph->p_align = s_align;
2311 /* Decide the layout of sections loaded in memory. This must
2312 be done before program headers are filled since they contain
2313 info about the layout. We do the following ordering: interp,
2314 symbol tables, relocations, progbits, nobits */
2315 /* XXX: do faster and simpler sorting */
2316 for(k = 0; k < 5; k++) {
2317 for(i = 1; i < s1->nb_sections; i++) {
2318 s = s1->sections[i];
2319 /* compute if section should be included */
2320 if (j == 0) {
2321 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
2322 SHF_ALLOC)
2323 continue;
2324 } else {
2325 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
2326 (SHF_ALLOC | SHF_WRITE))
2327 continue;
2329 if (s == interp) {
2330 if (k != 0)
2331 continue;
2332 } else if (s->sh_type == SHT_DYNSYM ||
2333 s->sh_type == SHT_STRTAB ||
2334 s->sh_type == SHT_HASH) {
2335 if (k != 1)
2336 continue;
2337 } else if (s->sh_type == SHT_RELX) {
2338 if (k != 2)
2339 continue;
2340 } else if (s->sh_type == SHT_NOBITS) {
2341 if (k != 4)
2342 continue;
2343 } else {
2344 if (k != 3)
2345 continue;
2347 sec_order[sh_order_index++] = i;
2349 /* section matches: we align it and add its size */
2350 tmp = addr;
2351 addr = (addr + s->sh_addralign - 1) &
2352 ~(s->sh_addralign - 1);
2353 file_offset += (int) ( addr - tmp );
2354 s->sh_offset = file_offset;
2355 s->sh_addr = addr;
2357 /* update program header infos */
2358 if (ph->p_offset == 0) {
2359 ph->p_offset = file_offset;
2360 ph->p_vaddr = addr;
2361 ph->p_paddr = ph->p_vaddr;
2363 /* update dynamic relocation infos */
2364 if (s->sh_type == SHT_RELX) {
2365 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2366 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) {
2367 dyninf->rel_addr = addr;
2368 dyninf->rel_size += s->sh_size; /* XXX only first rel. */
2370 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) {
2371 dyninf->bss_addr = addr;
2372 dyninf->bss_size = s->sh_size; /* XXX only first rel. */
2374 #else
2375 if (dyninf->rel_size == 0)
2376 dyninf->rel_addr = addr;
2377 dyninf->rel_size += s->sh_size;
2378 #endif
2380 addr += s->sh_size;
2381 if (s->sh_type != SHT_NOBITS)
2382 file_offset += s->sh_size;
2385 if (j == 0) {
2386 /* Make the first PT_LOAD segment include the program
2387 headers itself (and the ELF header as well), it'll
2388 come out with same memory use but will make various
2389 tools like binutils strip work better. */
2390 ph->p_offset &= ~(ph->p_align - 1);
2391 ph->p_vaddr &= ~(ph->p_align - 1);
2392 ph->p_paddr &= ~(ph->p_align - 1);
2394 ph->p_filesz = file_offset - ph->p_offset;
2395 ph->p_memsz = addr - ph->p_vaddr;
2396 ph++;
2397 if (j == 0) {
2398 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2399 /* if in the middle of a page, we duplicate the page in
2400 memory so that one copy is RX and the other is RW */
2401 if ((addr & (s_align - 1)) != 0)
2402 addr += s_align;
2403 } else {
2404 addr = (addr + s_align - 1) & ~(s_align - 1);
2405 file_offset = (file_offset + s_align - 1) & ~(s_align - 1);
2411 /* all other sections come after */
2412 for(i = 1; i < s1->nb_sections; i++) {
2413 s = s1->sections[i];
2414 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2415 continue;
2416 sec_order[sh_order_index++] = i;
2418 file_offset = (file_offset + s->sh_addralign - 1) &
2419 ~(s->sh_addralign - 1);
2420 s->sh_offset = file_offset;
2421 if (s->sh_type != SHT_NOBITS)
2422 file_offset += s->sh_size;
2425 return file_offset;
2428 static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp,
2429 Section *dynamic)
2431 ElfW(Phdr) *ph;
2433 /* if interpreter, then add corresponding program header */
2434 if (interp) {
2435 ph = &phdr[0];
2437 if (HAVE_PHDR)
2439 int len = phnum * sizeof(ElfW(Phdr));
2441 ph->p_type = PT_PHDR;
2442 ph->p_offset = sizeof(ElfW(Ehdr));
2443 ph->p_vaddr = interp->sh_addr - len;
2444 ph->p_paddr = ph->p_vaddr;
2445 ph->p_filesz = ph->p_memsz = len;
2446 ph->p_flags = PF_R | PF_X;
2447 ph->p_align = 4; /* interp->sh_addralign; */
2448 ph++;
2451 ph->p_type = PT_INTERP;
2452 ph->p_offset = interp->sh_offset;
2453 ph->p_vaddr = interp->sh_addr;
2454 ph->p_paddr = ph->p_vaddr;
2455 ph->p_filesz = interp->sh_size;
2456 ph->p_memsz = interp->sh_size;
2457 ph->p_flags = PF_R;
2458 ph->p_align = interp->sh_addralign;
2461 /* if dynamic section, then add corresponding program header */
2462 if (dynamic) {
2463 ph = &phdr[phnum - 1];
2465 ph->p_type = PT_DYNAMIC;
2466 ph->p_offset = dynamic->sh_offset;
2467 ph->p_vaddr = dynamic->sh_addr;
2468 ph->p_paddr = ph->p_vaddr;
2469 ph->p_filesz = dynamic->sh_size;
2470 ph->p_memsz = dynamic->sh_size;
2471 ph->p_flags = PF_R | PF_W;
2472 ph->p_align = dynamic->sh_addralign;
2476 /* Fill the dynamic section with tags describing the address and size of
2477 sections */
2478 static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
2480 Section *dynamic;
2482 dynamic = dyninf->dynamic;
2484 /* put dynamic section entries */
2485 dynamic->data_offset = dyninf->dyn_rel_off;
2486 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
2487 put_dt(dynamic, DT_STRTAB, dyninf->dynstr->sh_addr);
2488 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2489 put_dt(dynamic, DT_STRSZ, dyninf->dynstr->data_offset);
2490 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2491 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
2492 put_dt(dynamic, DT_RELA, dyninf->rel_addr);
2493 put_dt(dynamic, DT_RELASZ, dyninf->rel_size);
2494 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2495 #else
2496 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2497 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2498 put_dt(dynamic, DT_PLTRELSZ, dyninf->rel_size);
2499 put_dt(dynamic, DT_JMPREL, dyninf->rel_addr);
2500 put_dt(dynamic, DT_PLTREL, DT_REL);
2501 put_dt(dynamic, DT_REL, dyninf->bss_addr);
2502 put_dt(dynamic, DT_RELSZ, dyninf->bss_size);
2503 #else
2504 put_dt(dynamic, DT_REL, dyninf->rel_addr);
2505 put_dt(dynamic, DT_RELSZ, dyninf->rel_size);
2506 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2507 #endif
2508 #endif
2509 if (s1->do_debug)
2510 put_dt(dynamic, DT_DEBUG, 0);
2511 put_dt(dynamic, DT_NULL, 0);
2514 /* Relocate remaining sections and symbols (that is those not related to
2515 dynamic linking) */
2516 static int final_sections_reloc(TCCState *s1)
2518 int i;
2519 Section *s;
2521 relocate_syms(s1, 0);
2523 if (s1->nb_errors != 0)
2524 return -1;
2526 /* relocate sections */
2527 /* XXX: ignore sections with allocated relocations ? */
2528 for(i = 1; i < s1->nb_sections; i++) {
2529 s = s1->sections[i];
2530 #ifdef TCC_TARGET_I386
2531 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
2532 /* On X86 gdb 7.3 works in any case but gdb 6.6 will crash if SHF_ALLOC
2533 checking is removed */
2534 #else
2535 if (s->reloc && s != s1->got)
2536 /* On X86_64 gdb 7.3 will crash if SHF_ALLOC checking is present */
2537 #endif
2538 relocate_section(s1, s);
2541 /* relocate relocation entries if the relocation tables are
2542 allocated in the executable */
2543 for(i = 1; i < s1->nb_sections; i++) {
2544 s = s1->sections[i];
2545 if ((s->sh_flags & SHF_ALLOC) &&
2546 s->sh_type == SHT_RELX) {
2547 relocate_rel(s1, s);
2550 return 0;
2553 /* Create an ELF file on disk.
2554 This function handle ELF specific layout requirements */
2555 static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
2556 int file_offset, int *sec_order)
2558 int i, shnum, offset, size, file_type;
2559 Section *s;
2560 ElfW(Ehdr) ehdr;
2561 ElfW(Shdr) shdr, *sh;
2563 file_type = s1->output_type;
2564 shnum = s1->nb_sections;
2566 memset(&ehdr, 0, sizeof(ehdr));
2568 if (phnum > 0) {
2569 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2570 ehdr.e_phnum = phnum;
2571 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2574 /* align to 4 */
2575 file_offset = (file_offset + 3) & -4;
2577 /* fill header */
2578 ehdr.e_ident[0] = ELFMAG0;
2579 ehdr.e_ident[1] = ELFMAG1;
2580 ehdr.e_ident[2] = ELFMAG2;
2581 ehdr.e_ident[3] = ELFMAG3;
2582 ehdr.e_ident[4] = ELFCLASSW;
2583 ehdr.e_ident[5] = ELFDATA2LSB;
2584 ehdr.e_ident[6] = EV_CURRENT;
2585 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2586 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2587 #endif
2588 #ifdef TCC_TARGET_ARM
2589 #ifdef TCC_ARM_EABI
2590 ehdr.e_ident[EI_OSABI] = 0;
2591 ehdr.e_flags = EF_ARM_EABI_VER4;
2592 if (file_type == TCC_OUTPUT_EXE || file_type == TCC_OUTPUT_DLL)
2593 ehdr.e_flags |= EF_ARM_HASENTRY;
2594 if (s1->float_abi == ARM_HARD_FLOAT)
2595 ehdr.e_flags |= EF_ARM_VFP_FLOAT;
2596 else
2597 ehdr.e_flags |= EF_ARM_SOFT_FLOAT;
2598 #else
2599 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2600 #endif
2601 #endif
2602 switch(file_type) {
2603 default:
2604 case TCC_OUTPUT_EXE:
2605 ehdr.e_type = ET_EXEC;
2606 ehdr.e_entry = get_elf_sym_addr(s1, "_start", 1);
2607 break;
2608 case TCC_OUTPUT_DLL:
2609 ehdr.e_type = ET_DYN;
2610 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2611 break;
2612 case TCC_OUTPUT_OBJ:
2613 ehdr.e_type = ET_REL;
2614 break;
2616 ehdr.e_machine = EM_TCC_TARGET;
2617 ehdr.e_version = EV_CURRENT;
2618 ehdr.e_shoff = file_offset;
2619 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2620 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2621 ehdr.e_shnum = shnum;
2622 ehdr.e_shstrndx = shnum - 1;
2624 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2625 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2626 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2628 sort_syms(s1, symtab_section);
2629 for(i = 1; i < s1->nb_sections; i++) {
2630 s = s1->sections[sec_order[i]];
2631 if (s->sh_type != SHT_NOBITS) {
2632 if (s->sh_type == SHT_DYNSYM)
2633 patch_dynsym_undef(s1, s);
2634 while (offset < s->sh_offset) {
2635 fputc(0, f);
2636 offset++;
2638 size = s->sh_size;
2639 if (size)
2640 fwrite(s->data, 1, size, f);
2641 offset += size;
2645 /* output section headers */
2646 while (offset < ehdr.e_shoff) {
2647 fputc(0, f);
2648 offset++;
2651 for(i = 0; i < s1->nb_sections; i++) {
2652 sh = &shdr;
2653 memset(sh, 0, sizeof(ElfW(Shdr)));
2654 s = s1->sections[i];
2655 if (s) {
2656 sh->sh_name = s->sh_name;
2657 sh->sh_type = s->sh_type;
2658 sh->sh_flags = s->sh_flags;
2659 sh->sh_entsize = s->sh_entsize;
2660 sh->sh_info = s->sh_info;
2661 if (s->link)
2662 sh->sh_link = s->link->sh_num;
2663 sh->sh_addralign = s->sh_addralign;
2664 sh->sh_addr = s->sh_addr;
2665 sh->sh_offset = s->sh_offset;
2666 sh->sh_size = s->sh_size;
2668 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2672 /* Write an elf, coff or "binary" file */
2673 static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum,
2674 ElfW(Phdr) *phdr, int file_offset, int *sec_order)
2676 int fd, mode, file_type;
2677 FILE *f;
2679 file_type = s1->output_type;
2680 if (file_type == TCC_OUTPUT_OBJ)
2681 mode = 0666;
2682 else
2683 mode = 0777;
2684 unlink(filename);
2685 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2686 if (fd < 0) {
2687 tcc_error_noabort("could not write '%s'", filename);
2688 return -1;
2690 f = fdopen(fd, "wb");
2691 if (s1->verbose)
2692 printf("<- %s\n", filename);
2694 #ifdef TCC_TARGET_COFF
2695 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF)
2696 tcc_output_coff(s1, f);
2697 else
2698 #endif
2699 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
2700 tcc_output_elf(s1, f, phnum, phdr, file_offset, sec_order);
2701 else
2702 tcc_output_binary(s1, f, sec_order);
2703 fclose(f);
2705 return 0;
2708 /* Output an elf, coff or binary file */
2709 /* XXX: suppress unneeded sections */
2710 static int elf_output_file(TCCState *s1, const char *filename)
2712 int i, ret, phnum, shnum, file_type, file_offset, *sec_order;
2713 struct dyn_inf dyninf;
2714 ElfW(Phdr) *phdr;
2715 ElfW(Sym) *sym;
2716 Section *strsec, *interp, *dynamic, *dynstr;
2718 file_type = s1->output_type;
2719 s1->nb_errors = 0;
2721 /* if linking, also link in runtime libraries (libc, libgcc, etc.) */
2722 if (file_type != TCC_OUTPUT_OBJ) {
2723 tcc_add_runtime(s1);
2726 phdr = NULL;
2727 sec_order = NULL;
2728 interp = dynamic = dynstr = NULL; /* avoid warning */
2729 dyninf.dyn_rel_off = 0; /* avoid warning */
2731 if (file_type != TCC_OUTPUT_OBJ) {
2732 relocate_common_syms();
2734 tcc_add_linker_symbols(s1);
2736 if (!s1->static_link) {
2737 if (file_type == TCC_OUTPUT_EXE) {
2738 char *ptr;
2739 /* allow override the dynamic loader */
2740 const char *elfint = getenv("LD_SO");
2741 if (elfint == NULL)
2742 elfint = DEFAULT_ELFINTERP(s1);
2743 /* add interpreter section only if executable */
2744 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
2745 interp->sh_addralign = 1;
2746 ptr = section_ptr_add(interp, 1 + strlen(elfint));
2747 strcpy(ptr, elfint);
2750 /* add dynamic symbol table */
2751 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
2752 ".dynstr",
2753 ".hash", SHF_ALLOC);
2754 dynstr = s1->dynsym->link;
2756 /* add dynamic section */
2757 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
2758 SHF_ALLOC | SHF_WRITE);
2759 dynamic->link = dynstr;
2760 dynamic->sh_entsize = sizeof(ElfW(Dyn));
2762 build_got(s1);
2764 if (file_type == TCC_OUTPUT_EXE) {
2765 bind_exe_dynsyms(s1);
2767 if (s1->nb_errors) {
2768 ret = -1;
2769 goto the_end;
2772 bind_libs_dynsyms(s1);
2773 } else /* shared library case: simply export all global symbols */
2774 export_global_syms(s1);
2776 build_got_entries(s1);
2778 /* add a list of needed dlls */
2779 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2780 DLLReference *dllref = s1->loaded_dlls[i];
2781 if (dllref->level == 0)
2782 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
2785 if (s1->rpath)
2786 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
2788 /* XXX: currently, since we do not handle PIC code, we
2789 must relocate the readonly segments */
2790 if (file_type == TCC_OUTPUT_DLL) {
2791 if (s1->soname)
2792 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
2793 put_dt(dynamic, DT_TEXTREL, 0);
2796 if (s1->symbolic)
2797 put_dt(dynamic, DT_SYMBOLIC, 0);
2799 /* add necessary space for other entries */
2800 dyninf.dyn_rel_off = dynamic->data_offset;
2801 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
2802 } else {
2803 /* still need to build got entries in case of static link */
2804 build_got_entries(s1);
2808 /* we add a section for symbols */
2809 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
2810 put_elf_str(strsec, "");
2812 /* compute number of sections */
2813 shnum = s1->nb_sections;
2815 /* this array is used to reorder sections in the output file */
2816 sec_order = tcc_malloc(sizeof(int) * shnum);
2817 sec_order[0] = 0;
2819 /* compute number of program headers */
2820 switch(file_type) {
2821 default:
2822 case TCC_OUTPUT_OBJ:
2823 phnum = 0;
2824 break;
2825 case TCC_OUTPUT_EXE:
2826 if (!s1->static_link)
2827 phnum = 4 + HAVE_PHDR;
2828 else
2829 phnum = 2;
2830 break;
2831 case TCC_OUTPUT_DLL:
2832 phnum = 3;
2833 break;
2836 /* Allocate strings for section names */
2837 alloc_sec_names(s1, file_type, strsec);
2839 /* allocate program segment headers */
2840 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
2842 /* compute section to program header mapping */
2843 file_offset = layout_sections(s1, phdr, phnum, interp, strsec, &dyninf,
2844 sec_order);
2846 /* Fill remaining program header and finalize relocation related to dynamic
2847 linking. */
2848 if (phnum > 0) {
2849 fill_unloadable_phdr(phdr, phnum, interp, dynamic);
2850 if (dynamic) {
2851 dyninf.dynamic = dynamic;
2852 dyninf.dynstr = dynstr;
2854 fill_dynamic(s1, &dyninf);
2856 /* put in GOT the dynamic section address and relocate PLT */
2857 write32le(s1->got->data, dynamic->sh_addr);
2858 if (file_type == TCC_OUTPUT_EXE
2859 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2860 || file_type == TCC_OUTPUT_DLL
2861 #endif
2863 relocate_plt(s1);
2865 /* relocate symbols in .dynsym now that final addresses are known */
2866 for_each_elem(s1->dynsym, 1, sym, ElfW(Sym)) {
2867 if (sym->st_shndx == SHN_UNDEF) {
2868 /* relocate to PLT if symbol corresponds to a PLT entry,
2869 but not if it's a weak symbol */
2870 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
2871 sym->st_value = 0;
2872 else if (sym->st_value)
2873 sym->st_value += s1->plt->sh_addr;
2874 } else if (sym->st_shndx < SHN_LORESERVE) {
2875 /* do symbol relocation */
2876 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
2882 /* if building executable or DLL, then relocate each section
2883 except the GOT which is already relocated */
2884 if (file_type != TCC_OUTPUT_OBJ) {
2885 ret = final_sections_reloc(s1);
2886 if (ret)
2887 goto the_end;
2890 /* Perform relocation to GOT or PLT entries */
2891 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2892 fill_got(s1);
2894 /* Create the ELF file with name 'filename' */
2895 ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order);
2896 the_end:
2897 tcc_free(s1->symtab_to_dynsym);
2898 tcc_free(sec_order);
2899 tcc_free(phdr);
2900 tcc_free(s1->sym_attrs);
2901 s1->sym_attrs = NULL;
2902 return ret;
2905 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2907 int ret;
2908 #ifdef TCC_TARGET_PE
2909 if (s->output_type != TCC_OUTPUT_OBJ) {
2910 ret = pe_output_file(s, filename);
2911 } else
2912 #endif
2913 ret = elf_output_file(s, filename);
2914 return ret;
2917 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2919 void *data;
2921 data = tcc_malloc(size);
2922 lseek(fd, file_offset, SEEK_SET);
2923 read(fd, data, size);
2924 return data;
2927 typedef struct SectionMergeInfo {
2928 Section *s; /* corresponding existing section */
2929 unsigned long offset; /* offset of the new section in the existing section */
2930 uint8_t new_section; /* true if section 's' was added */
2931 uint8_t link_once; /* true if link once section */
2932 } SectionMergeInfo;
2934 ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h)
2936 int size = read(fd, h, sizeof *h);
2937 if (size == sizeof *h && 0 == memcmp(h, ELFMAG, 4)) {
2938 if (h->e_type == ET_REL)
2939 return AFF_BINTYPE_REL;
2940 if (h->e_type == ET_DYN)
2941 return AFF_BINTYPE_DYN;
2942 } else if (size >= 8) {
2943 if (0 == memcmp(h, ARMAG, 8))
2944 return AFF_BINTYPE_AR;
2945 #ifdef TCC_TARGET_COFF
2946 if (((struct filehdr*)h)->f_magic == COFF_C67_MAGIC)
2947 return AFF_BINTYPE_C67;
2948 #endif
2950 return 0;
2953 /* load an object file and merge it with current files */
2954 /* XXX: handle correctly stab (debug) info */
2955 ST_FUNC int tcc_load_object_file(TCCState *s1,
2956 int fd, unsigned long file_offset)
2958 ElfW(Ehdr) ehdr;
2959 ElfW(Shdr) *shdr, *sh;
2960 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2961 unsigned char *strsec, *strtab;
2962 int *old_to_new_syms;
2963 char *sh_name, *name;
2964 SectionMergeInfo *sm_table, *sm;
2965 ElfW(Sym) *sym, *symtab;
2966 ElfW_Rel *rel;
2967 Section *s;
2969 int stab_index;
2970 int stabstr_index;
2972 stab_index = stabstr_index = 0;
2974 lseek(fd, file_offset, SEEK_SET);
2975 if (tcc_object_type(fd, &ehdr) != AFF_BINTYPE_REL)
2976 goto fail1;
2977 /* test CPU specific stuff */
2978 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2979 ehdr.e_machine != EM_TCC_TARGET) {
2980 fail1:
2981 tcc_error_noabort("invalid object file");
2982 return -1;
2984 /* read sections */
2985 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2986 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2987 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2989 /* load section names */
2990 sh = &shdr[ehdr.e_shstrndx];
2991 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2993 /* load symtab and strtab */
2994 old_to_new_syms = NULL;
2995 symtab = NULL;
2996 strtab = NULL;
2997 nb_syms = 0;
2998 for(i = 1; i < ehdr.e_shnum; i++) {
2999 sh = &shdr[i];
3000 if (sh->sh_type == SHT_SYMTAB) {
3001 if (symtab) {
3002 tcc_error_noabort("object must contain only one symtab");
3003 fail:
3004 ret = -1;
3005 goto the_end;
3007 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
3008 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
3009 sm_table[i].s = symtab_section;
3011 /* now load strtab */
3012 sh = &shdr[sh->sh_link];
3013 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
3017 /* now examine each section and try to merge its content with the
3018 ones in memory */
3019 for(i = 1; i < ehdr.e_shnum; i++) {
3020 /* no need to examine section name strtab */
3021 if (i == ehdr.e_shstrndx)
3022 continue;
3023 sh = &shdr[i];
3024 sh_name = (char *) strsec + sh->sh_name;
3025 /* ignore sections types we do not handle */
3026 if (sh->sh_type != SHT_PROGBITS &&
3027 sh->sh_type != SHT_RELX &&
3028 #ifdef TCC_ARM_EABI
3029 sh->sh_type != SHT_ARM_EXIDX &&
3030 #endif
3031 sh->sh_type != SHT_NOBITS &&
3032 sh->sh_type != SHT_PREINIT_ARRAY &&
3033 sh->sh_type != SHT_INIT_ARRAY &&
3034 sh->sh_type != SHT_FINI_ARRAY &&
3035 strcmp(sh_name, ".stabstr")
3037 continue;
3038 if (sh->sh_addralign < 1)
3039 sh->sh_addralign = 1;
3040 /* find corresponding section, if any */
3041 for(j = 1; j < s1->nb_sections;j++) {
3042 s = s1->sections[j];
3043 if (!strcmp(s->name, sh_name)) {
3044 if (!strncmp(sh_name, ".gnu.linkonce",
3045 sizeof(".gnu.linkonce") - 1)) {
3046 /* if a 'linkonce' section is already present, we
3047 do not add it again. It is a little tricky as
3048 symbols can still be defined in
3049 it. */
3050 sm_table[i].link_once = 1;
3051 goto next;
3052 } else {
3053 goto found;
3057 /* not found: create new section */
3058 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags & ~SHF_GROUP);
3059 /* take as much info as possible from the section. sh_link and
3060 sh_info will be updated later */
3061 s->sh_addralign = sh->sh_addralign;
3062 s->sh_entsize = sh->sh_entsize;
3063 sm_table[i].new_section = 1;
3064 found:
3065 if (sh->sh_type != s->sh_type) {
3066 tcc_error_noabort("invalid section type");
3067 goto fail;
3070 /* align start of section */
3071 offset = s->data_offset;
3073 if (0 == strcmp(sh_name, ".stab")) {
3074 stab_index = i;
3075 goto no_align;
3077 if (0 == strcmp(sh_name, ".stabstr")) {
3078 stabstr_index = i;
3079 goto no_align;
3082 size = sh->sh_addralign - 1;
3083 offset = (offset + size) & ~size;
3084 if (sh->sh_addralign > s->sh_addralign)
3085 s->sh_addralign = sh->sh_addralign;
3086 s->data_offset = offset;
3087 no_align:
3088 sm_table[i].offset = offset;
3089 sm_table[i].s = s;
3090 /* concatenate sections */
3091 size = sh->sh_size;
3092 if (sh->sh_type != SHT_NOBITS) {
3093 unsigned char *ptr;
3094 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
3095 ptr = section_ptr_add(s, size);
3096 read(fd, ptr, size);
3097 } else {
3098 s->data_offset += size;
3100 next: ;
3103 /* gr relocate stab strings */
3104 if (stab_index && stabstr_index) {
3105 Stab_Sym *a, *b;
3106 unsigned o;
3107 s = sm_table[stab_index].s;
3108 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
3109 b = (Stab_Sym *)(s->data + s->data_offset);
3110 o = sm_table[stabstr_index].offset;
3111 while (a < b)
3112 a->n_strx += o, a++;
3115 /* second short pass to update sh_link and sh_info fields of new
3116 sections */
3117 for(i = 1; i < ehdr.e_shnum; i++) {
3118 s = sm_table[i].s;
3119 if (!s || !sm_table[i].new_section)
3120 continue;
3121 sh = &shdr[i];
3122 if (sh->sh_link > 0)
3123 s->link = sm_table[sh->sh_link].s;
3124 if (sh->sh_type == SHT_RELX) {
3125 s->sh_info = sm_table[sh->sh_info].s->sh_num;
3126 /* update backward link */
3127 s1->sections[s->sh_info]->reloc = s;
3130 sm = sm_table;
3132 /* resolve symbols */
3133 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
3135 sym = symtab + 1;
3136 for(i = 1; i < nb_syms; i++, sym++) {
3137 if (sym->st_shndx != SHN_UNDEF &&
3138 sym->st_shndx < SHN_LORESERVE) {
3139 sm = &sm_table[sym->st_shndx];
3140 if (sm->link_once) {
3141 /* if a symbol is in a link once section, we use the
3142 already defined symbol. It is very important to get
3143 correct relocations */
3144 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
3145 name = (char *) strtab + sym->st_name;
3146 sym_index = find_elf_sym(symtab_section, name);
3147 if (sym_index)
3148 old_to_new_syms[i] = sym_index;
3150 continue;
3152 /* if no corresponding section added, no need to add symbol */
3153 if (!sm->s)
3154 continue;
3155 /* convert section number */
3156 sym->st_shndx = sm->s->sh_num;
3157 /* offset value */
3158 sym->st_value += sm->offset;
3160 /* add symbol */
3161 name = (char *) strtab + sym->st_name;
3162 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
3163 sym->st_info, sym->st_other,
3164 sym->st_shndx, name);
3165 old_to_new_syms[i] = sym_index;
3168 /* third pass to patch relocation entries */
3169 for(i = 1; i < ehdr.e_shnum; i++) {
3170 s = sm_table[i].s;
3171 if (!s)
3172 continue;
3173 sh = &shdr[i];
3174 offset = sm_table[i].offset;
3175 switch(s->sh_type) {
3176 case SHT_RELX:
3177 /* take relocation offset information */
3178 offseti = sm_table[sh->sh_info].offset;
3179 for_each_elem(s, (offset / sizeof(*rel)), rel, ElfW_Rel) {
3180 int type;
3181 unsigned sym_index;
3182 /* convert symbol index */
3183 type = ELFW(R_TYPE)(rel->r_info);
3184 sym_index = ELFW(R_SYM)(rel->r_info);
3185 /* NOTE: only one symtab assumed */
3186 if (sym_index >= nb_syms)
3187 goto invalid_reloc;
3188 sym_index = old_to_new_syms[sym_index];
3189 /* ignore link_once in rel section. */
3190 if (!sym_index && !sm->link_once
3191 #ifdef TCC_TARGET_ARM
3192 && type != R_ARM_V4BX
3193 #endif
3195 invalid_reloc:
3196 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
3197 i, strsec + sh->sh_name, rel->r_offset);
3198 goto fail;
3200 rel->r_info = ELFW(R_INFO)(sym_index, type);
3201 /* offset the relocation offset */
3202 rel->r_offset += offseti;
3203 #ifdef TCC_TARGET_ARM
3204 /* Jumps and branches from a Thumb code to a PLT entry need
3205 special handling since PLT entries are ARM code.
3206 Unconditional bl instructions referencing PLT entries are
3207 handled by converting these instructions into blx
3208 instructions. Other case of instructions referencing a PLT
3209 entry require to add a Thumb stub before the PLT entry to
3210 switch to ARM mode. We set bit plt_thumb_stub of the
3211 attribute of a symbol to indicate such a case. */
3212 if (type == R_ARM_THM_JUMP24)
3213 alloc_sym_attr(s1, sym_index)->plt_thumb_stub = 1;
3214 #endif
3216 break;
3217 default:
3218 break;
3222 ret = 0;
3223 the_end:
3224 tcc_free(symtab);
3225 tcc_free(strtab);
3226 tcc_free(old_to_new_syms);
3227 tcc_free(sm_table);
3228 tcc_free(strsec);
3229 tcc_free(shdr);
3230 return ret;
3233 typedef struct ArchiveHeader {
3234 char ar_name[16]; /* name of this member */
3235 char ar_date[12]; /* file mtime */
3236 char ar_uid[6]; /* owner uid; printed as decimal */
3237 char ar_gid[6]; /* owner gid; printed as decimal */
3238 char ar_mode[8]; /* file mode, printed as octal */
3239 char ar_size[10]; /* file size, printed as decimal */
3240 char ar_fmag[2]; /* should contain ARFMAG */
3241 } ArchiveHeader;
3243 static int get_be32(const uint8_t *b)
3245 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
3248 static long get_be64(const uint8_t *b)
3250 long long ret = get_be32(b);
3251 ret = (ret << 32) | (unsigned)get_be32(b+4);
3252 return (long)ret;
3255 /* load only the objects which resolve undefined symbols */
3256 static int tcc_load_alacarte(TCCState *s1, int fd, int size, int entrysize)
3258 long i, bound, nsyms, sym_index, off, ret;
3259 uint8_t *data;
3260 const char *ar_names, *p;
3261 const uint8_t *ar_index;
3262 ElfW(Sym) *sym;
3264 data = tcc_malloc(size);
3265 if (read(fd, data, size) != size)
3266 goto fail;
3267 nsyms = entrysize == 4 ? get_be32(data) : get_be64(data);
3268 ar_index = data + entrysize;
3269 ar_names = (char *) ar_index + nsyms * entrysize;
3271 do {
3272 bound = 0;
3273 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
3274 sym_index = find_elf_sym(symtab_section, p);
3275 if(sym_index) {
3276 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
3277 if(sym->st_shndx == SHN_UNDEF) {
3278 off = (entrysize == 4
3279 ? get_be32(ar_index + i * 4)
3280 : get_be64(ar_index + i * 8))
3281 + sizeof(ArchiveHeader);
3282 ++bound;
3283 if(tcc_load_object_file(s1, fd, off) < 0) {
3284 fail:
3285 ret = -1;
3286 goto the_end;
3291 } while(bound);
3292 ret = 0;
3293 the_end:
3294 tcc_free(data);
3295 return ret;
3298 /* load a '.a' file */
3299 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
3301 ArchiveHeader hdr;
3302 char ar_size[11];
3303 char ar_name[17];
3304 char magic[8];
3305 int size, len, i;
3306 unsigned long file_offset;
3308 /* skip magic which was already checked */
3309 read(fd, magic, sizeof(magic));
3311 for(;;) {
3312 len = read(fd, &hdr, sizeof(hdr));
3313 if (len == 0)
3314 break;
3315 if (len != sizeof(hdr)) {
3316 tcc_error_noabort("invalid archive");
3317 return -1;
3319 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
3320 ar_size[sizeof(hdr.ar_size)] = '\0';
3321 size = strtol(ar_size, NULL, 0);
3322 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
3323 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
3324 if (ar_name[i] != ' ')
3325 break;
3327 ar_name[i + 1] = '\0';
3328 file_offset = lseek(fd, 0, SEEK_CUR);
3329 /* align to even */
3330 size = (size + 1) & ~1;
3331 if (!strcmp(ar_name, "/")) {
3332 /* coff symbol table : we handle it */
3333 if(s1->alacarte_link)
3334 return tcc_load_alacarte(s1, fd, size, 4);
3335 } else if (!strcmp(ar_name, "/SYM64/")) {
3336 if(s1->alacarte_link)
3337 return tcc_load_alacarte(s1, fd, size, 8);
3338 } else {
3339 ElfW(Ehdr) ehdr;
3340 if (tcc_object_type(fd, &ehdr) == AFF_BINTYPE_REL) {
3341 if (tcc_load_object_file(s1, fd, file_offset) < 0)
3342 return -1;
3345 lseek(fd, file_offset + size, SEEK_SET);
3347 return 0;
3350 #ifndef TCC_TARGET_PE
3351 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
3352 is referenced by the user (so it should be added as DT_NEEDED in
3353 the generated ELF file) */
3354 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
3356 ElfW(Ehdr) ehdr;
3357 ElfW(Shdr) *shdr, *sh, *sh1;
3358 int i, j, nb_syms, nb_dts, sym_bind, ret;
3359 ElfW(Sym) *sym, *dynsym;
3360 ElfW(Dyn) *dt, *dynamic;
3361 unsigned char *dynstr;
3362 const char *name, *soname;
3363 DLLReference *dllref;
3365 read(fd, &ehdr, sizeof(ehdr));
3367 /* test CPU specific stuff */
3368 if (ehdr.e_ident[5] != ELFDATA2LSB ||
3369 ehdr.e_machine != EM_TCC_TARGET) {
3370 tcc_error_noabort("bad architecture");
3371 return -1;
3374 /* read sections */
3375 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
3377 /* load dynamic section and dynamic symbols */
3378 nb_syms = 0;
3379 nb_dts = 0;
3380 dynamic = NULL;
3381 dynsym = NULL; /* avoid warning */
3382 dynstr = NULL; /* avoid warning */
3383 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
3384 switch(sh->sh_type) {
3385 case SHT_DYNAMIC:
3386 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
3387 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
3388 break;
3389 case SHT_DYNSYM:
3390 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
3391 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
3392 sh1 = &shdr[sh->sh_link];
3393 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
3394 break;
3395 default:
3396 break;
3400 /* compute the real library name */
3401 soname = tcc_basename(filename);
3403 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
3404 if (dt->d_tag == DT_SONAME) {
3405 soname = (char *) dynstr + dt->d_un.d_val;
3409 /* if the dll is already loaded, do not load it */
3410 for(i = 0; i < s1->nb_loaded_dlls; i++) {
3411 dllref = s1->loaded_dlls[i];
3412 if (!strcmp(soname, dllref->name)) {
3413 /* but update level if needed */
3414 if (level < dllref->level)
3415 dllref->level = level;
3416 ret = 0;
3417 goto the_end;
3421 /* add the dll and its level */
3422 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
3423 dllref->level = level;
3424 strcpy(dllref->name, soname);
3425 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
3427 /* add dynamic symbols in dynsym_section */
3428 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
3429 sym_bind = ELFW(ST_BIND)(sym->st_info);
3430 if (sym_bind == STB_LOCAL)
3431 continue;
3432 name = (char *) dynstr + sym->st_name;
3433 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
3434 sym->st_info, sym->st_other, sym->st_shndx, name);
3437 /* load all referenced DLLs */
3438 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
3439 switch(dt->d_tag) {
3440 case DT_NEEDED:
3441 name = (char *) dynstr + dt->d_un.d_val;
3442 for(j = 0; j < s1->nb_loaded_dlls; j++) {
3443 dllref = s1->loaded_dlls[j];
3444 if (!strcmp(name, dllref->name))
3445 goto already_loaded;
3447 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
3448 tcc_error_noabort("referenced dll '%s' not found", name);
3449 ret = -1;
3450 goto the_end;
3452 already_loaded:
3453 break;
3456 ret = 0;
3457 the_end:
3458 tcc_free(dynstr);
3459 tcc_free(dynsym);
3460 tcc_free(dynamic);
3461 tcc_free(shdr);
3462 return ret;
3465 #define LD_TOK_NAME 256
3466 #define LD_TOK_EOF (-1)
3468 /* return next ld script token */
3469 static int ld_next(TCCState *s1, char *name, int name_size)
3471 int c;
3472 char *q;
3474 redo:
3475 switch(ch) {
3476 case ' ':
3477 case '\t':
3478 case '\f':
3479 case '\v':
3480 case '\r':
3481 case '\n':
3482 inp();
3483 goto redo;
3484 case '/':
3485 minp();
3486 if (ch == '*') {
3487 file->buf_ptr = parse_comment(file->buf_ptr);
3488 ch = file->buf_ptr[0];
3489 goto redo;
3490 } else {
3491 q = name;
3492 *q++ = '/';
3493 goto parse_name;
3495 break;
3496 case '\\':
3497 ch = handle_eob();
3498 if (ch != '\\')
3499 goto redo;
3500 /* fall through */
3501 /* case 'a' ... 'z': */
3502 case 'a':
3503 case 'b':
3504 case 'c':
3505 case 'd':
3506 case 'e':
3507 case 'f':
3508 case 'g':
3509 case 'h':
3510 case 'i':
3511 case 'j':
3512 case 'k':
3513 case 'l':
3514 case 'm':
3515 case 'n':
3516 case 'o':
3517 case 'p':
3518 case 'q':
3519 case 'r':
3520 case 's':
3521 case 't':
3522 case 'u':
3523 case 'v':
3524 case 'w':
3525 case 'x':
3526 case 'y':
3527 case 'z':
3528 /* case 'A' ... 'z': */
3529 case 'A':
3530 case 'B':
3531 case 'C':
3532 case 'D':
3533 case 'E':
3534 case 'F':
3535 case 'G':
3536 case 'H':
3537 case 'I':
3538 case 'J':
3539 case 'K':
3540 case 'L':
3541 case 'M':
3542 case 'N':
3543 case 'O':
3544 case 'P':
3545 case 'Q':
3546 case 'R':
3547 case 'S':
3548 case 'T':
3549 case 'U':
3550 case 'V':
3551 case 'W':
3552 case 'X':
3553 case 'Y':
3554 case 'Z':
3555 case '_':
3556 case '.':
3557 case '$':
3558 case '~':
3559 q = name;
3560 parse_name:
3561 for(;;) {
3562 if (!((ch >= 'a' && ch <= 'z') ||
3563 (ch >= 'A' && ch <= 'Z') ||
3564 (ch >= '0' && ch <= '9') ||
3565 strchr("/.-_+=$:\\,~", ch)))
3566 break;
3567 if ((q - name) < name_size - 1) {
3568 *q++ = ch;
3570 minp();
3572 *q = '\0';
3573 c = LD_TOK_NAME;
3574 break;
3575 case CH_EOF:
3576 c = LD_TOK_EOF;
3577 break;
3578 default:
3579 c = ch;
3580 inp();
3581 break;
3583 return c;
3586 static int ld_add_file(TCCState *s1, const char filename[])
3588 int ret;
3590 ret = tcc_add_file_internal(s1, filename, AFF_TYPE_BIN);
3591 if (ret)
3592 ret = tcc_add_dll(s1, filename, 0);
3593 return ret;
3596 static inline int new_undef_syms(void)
3598 int ret = 0;
3599 ret = new_undef_sym;
3600 new_undef_sym = 0;
3601 return ret;
3604 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
3606 char filename[1024], libname[1024];
3607 int t, group, nblibs = 0, ret = 0;
3608 char **libs = NULL;
3610 group = !strcmp(cmd, "GROUP");
3611 if (!as_needed)
3612 new_undef_syms();
3613 t = ld_next(s1, filename, sizeof(filename));
3614 if (t != '(')
3615 expect("(");
3616 t = ld_next(s1, filename, sizeof(filename));
3617 for(;;) {
3618 libname[0] = '\0';
3619 if (t == LD_TOK_EOF) {
3620 tcc_error_noabort("unexpected end of file");
3621 ret = -1;
3622 goto lib_parse_error;
3623 } else if (t == ')') {
3624 break;
3625 } else if (t == '-') {
3626 t = ld_next(s1, filename, sizeof(filename));
3627 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
3628 tcc_error_noabort("library name expected");
3629 ret = -1;
3630 goto lib_parse_error;
3632 pstrcpy(libname, sizeof libname, &filename[1]);
3633 if (s1->static_link) {
3634 snprintf(filename, sizeof filename, "lib%s.a", libname);
3635 } else {
3636 snprintf(filename, sizeof filename, "lib%s.so", libname);
3638 } else if (t != LD_TOK_NAME) {
3639 tcc_error_noabort("filename expected");
3640 ret = -1;
3641 goto lib_parse_error;
3643 if (!strcmp(filename, "AS_NEEDED")) {
3644 ret = ld_add_file_list(s1, cmd, 1);
3645 if (ret)
3646 goto lib_parse_error;
3647 } else {
3648 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3649 if (!as_needed) {
3650 ret = ld_add_file(s1, filename);
3651 if (ret)
3652 goto lib_parse_error;
3653 if (group) {
3654 /* Add the filename *and* the libname to avoid future conversions */
3655 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
3656 if (libname[0] != '\0')
3657 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
3661 t = ld_next(s1, filename, sizeof(filename));
3662 if (t == ',') {
3663 t = ld_next(s1, filename, sizeof(filename));
3666 if (group && !as_needed) {
3667 while (new_undef_syms()) {
3668 int i;
3670 for (i = 0; i < nblibs; i ++)
3671 ld_add_file(s1, libs[i]);
3674 lib_parse_error:
3675 dynarray_reset(&libs, &nblibs);
3676 return ret;
3679 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3680 files */
3681 ST_FUNC int tcc_load_ldscript(TCCState *s1)
3683 char cmd[64];
3684 char filename[1024];
3685 int t, ret;
3687 ch = handle_eob();
3688 for(;;) {
3689 t = ld_next(s1, cmd, sizeof(cmd));
3690 if (t == LD_TOK_EOF)
3691 return 0;
3692 else if (t != LD_TOK_NAME)
3693 return -1;
3694 if (!strcmp(cmd, "INPUT") ||
3695 !strcmp(cmd, "GROUP")) {
3696 ret = ld_add_file_list(s1, cmd, 0);
3697 if (ret)
3698 return ret;
3699 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3700 !strcmp(cmd, "TARGET")) {
3701 /* ignore some commands */
3702 t = ld_next(s1, cmd, sizeof(cmd));
3703 if (t != '(')
3704 expect("(");
3705 for(;;) {
3706 t = ld_next(s1, filename, sizeof(filename));
3707 if (t == LD_TOK_EOF) {
3708 tcc_error_noabort("unexpected end of file");
3709 return -1;
3710 } else if (t == ')') {
3711 break;
3714 } else {
3715 return -1;
3718 return 0;
3720 #endif /* !TCC_TARGET_PE */