fix UB in constant folding of double -> signed integer conversion
[tinycc.git] / tccelf.c
blobc01854ad47890a8c0f08a4a0c2e9beaef58a3e0c
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 /* elf version information */
30 struct sym_version {
31 char *lib;
32 char *version;
33 int out_index;
34 int prev_same_lib;
37 #define nb_sym_versions s1->nb_sym_versions
38 #define sym_versions s1->sym_versions
39 #define nb_sym_to_version s1->nb_sym_to_version
40 #define sym_to_version s1->sym_to_version
41 #define dt_verneednum s1->dt_verneednum
42 #define versym_section s1->versym_section
43 #define verneed_section s1->verneed_section
45 /* special flag to indicate that the section should not be linked to the other ones */
46 #define SHF_PRIVATE 0x80000000
47 /* section is dynsymtab_section */
48 #define SHF_DYNSYM 0x40000000
50 #ifdef TCC_TARGET_PE
51 #define shf_RELRO SHF_ALLOC
52 static const char rdata[] = ".rdata";
53 #else
54 #define shf_RELRO s1->shf_RELRO
55 static const char rdata[] = ".data.ro";
56 #endif
58 /* ------------------------------------------------------------------------- */
60 ST_FUNC void tccelf_new(TCCState *s)
62 TCCState *s1 = s;
64 #ifndef TCC_TARGET_PE
65 shf_RELRO = SHF_ALLOC;
66 if (s1->output_type != TCC_OUTPUT_MEMORY)
67 shf_RELRO |= SHF_WRITE; /* the ELF loader will set it to RO at runtime */
68 #endif
70 /* no section zero */
71 dynarray_add(&s->sections, &s->nb_sections, NULL);
73 /* create standard sections */
74 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
75 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
76 /* create ro data section (make ro after relocation done with GNU_RELRO) */
77 rodata_section = new_section(s, rdata, SHT_PROGBITS, shf_RELRO);
78 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
79 common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE);
80 common_section->sh_num = SHN_COMMON;
82 /* symbols are always generated for linking stage */
83 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
84 ".strtab",
85 ".hashtab", SHF_PRIVATE);
87 /* private symbol table for dynamic symbols */
88 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE|SHF_DYNSYM,
89 ".dynstrtab",
90 ".dynhashtab", SHF_PRIVATE);
91 get_sym_attr(s, 0, 1);
93 if (s->do_debug) {
94 /* add debug sections */
95 tcc_debug_new(s);
98 #ifdef CONFIG_TCC_BCHECK
99 if (s->do_bounds_check) {
100 /* if bound checking, then add corresponding sections */
101 /* (make ro after relocation done with GNU_RELRO) */
102 bounds_section = new_section(s, ".bounds", SHT_PROGBITS, shf_RELRO);
103 lbounds_section = new_section(s, ".lbounds", SHT_PROGBITS, shf_RELRO);
105 #endif
108 ST_FUNC void free_section(Section *s)
110 if (!s)
111 return;
112 tcc_free(s->data);
113 s->data = NULL;
114 s->data_allocated = s->data_offset = 0;
117 ST_FUNC void tccelf_delete(TCCState *s1)
119 int i;
121 #ifndef ELF_OBJ_ONLY
122 /* free symbol versions */
123 for (i = 0; i < nb_sym_versions; i++) {
124 tcc_free(sym_versions[i].version);
125 tcc_free(sym_versions[i].lib);
127 tcc_free(sym_versions);
128 tcc_free(sym_to_version);
129 #endif
131 /* free all sections */
132 for(i = 1; i < s1->nb_sections; i++)
133 free_section(s1->sections[i]);
134 dynarray_reset(&s1->sections, &s1->nb_sections);
136 for(i = 0; i < s1->nb_priv_sections; i++)
137 free_section(s1->priv_sections[i]);
138 dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections);
140 tcc_free(s1->sym_attrs);
141 symtab_section = NULL; /* for tccrun.c:rt_printline() */
144 /* save section data state */
145 ST_FUNC void tccelf_begin_file(TCCState *s1)
147 Section *s; int i;
148 for (i = 1; i < s1->nb_sections; i++) {
149 s = s1->sections[i];
150 s->sh_offset = s->data_offset;
152 /* disable symbol hashing during compilation */
153 s = s1->symtab, s->reloc = s->hash, s->hash = NULL;
154 #if defined TCC_TARGET_X86_64 && defined TCC_TARGET_PE
155 s1->uw_sym = 0;
156 s1->uw_offs = 0;
157 #endif
160 static void update_relocs(TCCState *s1, Section *s, int *old_to_new_syms, int first_sym);
162 /* At the end of compilation, convert any UNDEF syms to global, and merge
163 with previously existing symbols */
164 ST_FUNC void tccelf_end_file(TCCState *s1)
166 Section *s = s1->symtab;
167 int first_sym, nb_syms, *tr, i;
169 first_sym = s->sh_offset / sizeof (ElfSym);
170 nb_syms = s->data_offset / sizeof (ElfSym) - first_sym;
171 s->data_offset = s->sh_offset;
172 s->link->data_offset = s->link->sh_offset;
173 s->hash = s->reloc, s->reloc = NULL;
174 tr = tcc_mallocz(nb_syms * sizeof *tr);
176 for (i = 0; i < nb_syms; ++i) {
177 ElfSym *sym = (ElfSym*)s->data + first_sym + i;
178 if (sym->st_shndx == SHN_UNDEF) {
179 int sym_bind = ELFW(ST_BIND)(sym->st_info);
180 int sym_type = ELFW(ST_TYPE)(sym->st_info);
181 if (sym_bind == STB_LOCAL)
182 sym_bind = STB_GLOBAL;
183 #ifndef TCC_TARGET_PE
184 if (sym_bind == STB_GLOBAL && s1->output_type == TCC_OUTPUT_OBJ) {
185 /* undefined symbols with STT_FUNC are confusing gnu ld when
186 linking statically to STT_GNU_IFUNC */
187 sym_type = STT_NOTYPE;
189 #endif
190 sym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
192 tr[i] = set_elf_sym(s, sym->st_value, sym->st_size, sym->st_info,
193 sym->st_other, sym->st_shndx, (char*)s->link->data + sym->st_name);
195 /* now update relocations */
196 update_relocs(s1, s, tr, first_sym);
197 tcc_free(tr);
198 /* record text/data/bss output for -bench info */
199 for (i = 0; i < 4; ++i) {
200 s = s1->sections[i + 1];
201 s1->total_output[i] += s->data_offset - s->sh_offset;
205 ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
207 Section *sec;
209 sec = tcc_mallocz(sizeof(Section) + strlen(name));
210 sec->s1 = s1;
211 strcpy(sec->name, name);
212 sec->sh_type = sh_type;
213 sec->sh_flags = sh_flags;
214 switch(sh_type) {
215 case SHT_GNU_versym:
216 sec->sh_addralign = 2;
217 break;
218 case SHT_HASH:
219 case SHT_GNU_HASH:
220 case SHT_REL:
221 case SHT_RELA:
222 case SHT_DYNSYM:
223 case SHT_SYMTAB:
224 case SHT_DYNAMIC:
225 case SHT_GNU_verneed:
226 case SHT_GNU_verdef:
227 sec->sh_addralign = PTR_SIZE;
228 break;
229 case SHT_STRTAB:
230 sec->sh_addralign = 1;
231 break;
232 default:
233 sec->sh_addralign = PTR_SIZE; /* gcc/pcc default alignment */
234 break;
237 if (sh_flags & SHF_PRIVATE) {
238 dynarray_add(&s1->priv_sections, &s1->nb_priv_sections, sec);
239 } else {
240 sec->sh_num = s1->nb_sections;
241 dynarray_add(&s1->sections, &s1->nb_sections, sec);
244 return sec;
247 ST_FUNC void init_symtab(Section *s)
249 int *ptr, nb_buckets = 1;
250 put_elf_str(s->link, "");
251 section_ptr_add(s, sizeof (ElfW(Sym)));
252 ptr = section_ptr_add(s->hash, (2 + nb_buckets + 1) * sizeof(int));
253 ptr[0] = nb_buckets;
254 ptr[1] = 1;
255 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
258 ST_FUNC Section *new_symtab(TCCState *s1,
259 const char *symtab_name, int sh_type, int sh_flags,
260 const char *strtab_name,
261 const char *hash_name, int hash_sh_flags)
263 Section *symtab, *strtab, *hash;
264 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
265 symtab->sh_entsize = sizeof(ElfW(Sym));
266 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
267 symtab->link = strtab;
268 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
269 hash->sh_entsize = sizeof(int);
270 symtab->hash = hash;
271 hash->link = symtab;
272 init_symtab(symtab);
273 return symtab;
276 /* realloc section and set its content to zero */
277 ST_FUNC void section_realloc(Section *sec, unsigned long new_size)
279 unsigned long size;
280 unsigned char *data;
282 size = sec->data_allocated;
283 if (size == 0)
284 size = 1;
285 while (size < new_size)
286 size = size * 2;
287 data = tcc_realloc(sec->data, size);
288 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
289 sec->data = data;
290 sec->data_allocated = size;
293 /* reserve at least 'size' bytes aligned per 'align' in section
294 'sec' from current offset, and return the aligned offset */
295 ST_FUNC size_t section_add(Section *sec, addr_t size, int align)
297 size_t offset, offset1;
299 offset = (sec->data_offset + align - 1) & -align;
300 offset1 = offset + size;
301 if (sec->sh_type != SHT_NOBITS && offset1 > sec->data_allocated)
302 section_realloc(sec, offset1);
303 sec->data_offset = offset1;
304 if (align > sec->sh_addralign)
305 sec->sh_addralign = align;
306 return offset;
309 /* reserve at least 'size' bytes in section 'sec' from
310 sec->data_offset. */
311 ST_FUNC void *section_ptr_add(Section *sec, addr_t size)
313 size_t offset = section_add(sec, size, 1);
314 return sec->data + offset;
317 #ifndef ELF_OBJ_ONLY
318 /* reserve at least 'size' bytes from section start */
319 static void section_reserve(Section *sec, unsigned long size)
321 if (size > sec->data_allocated)
322 section_realloc(sec, size);
323 if (size > sec->data_offset)
324 sec->data_offset = size;
326 #endif
328 static Section *have_section(TCCState *s1, const char *name)
330 Section *sec;
331 int i;
332 for(i = 1; i < s1->nb_sections; i++) {
333 sec = s1->sections[i];
334 if (!strcmp(name, sec->name))
335 return sec;
337 return NULL;
340 /* return a reference to a section, and create it if it does not
341 exists */
342 ST_FUNC Section *find_section(TCCState *s1, const char *name)
344 Section *sec = have_section(s1, name);
345 if (sec)
346 return sec;
347 /* sections are created as PROGBITS */
348 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
351 /* ------------------------------------------------------------------------- */
353 ST_FUNC int put_elf_str(Section *s, const char *sym)
355 int offset, len;
356 char *ptr;
358 len = strlen(sym) + 1;
359 offset = s->data_offset;
360 ptr = section_ptr_add(s, len);
361 memmove(ptr, sym, len);
362 return offset;
365 /* elf symbol hashing function */
366 static ElfW(Word) elf_hash(const unsigned char *name)
368 ElfW(Word) h = 0, g;
370 while (*name) {
371 h = (h << 4) + *name++;
372 g = h & 0xf0000000;
373 if (g)
374 h ^= g >> 24;
375 h &= ~g;
377 return h;
380 /* rebuild hash table of section s */
381 /* NOTE: we do factorize the hash table code to go faster */
382 static void rebuild_hash(Section *s, unsigned int nb_buckets)
384 ElfW(Sym) *sym;
385 int *ptr, *hash, nb_syms, sym_index, h;
386 unsigned char *strtab;
388 strtab = s->link->data;
389 nb_syms = s->data_offset / sizeof(ElfW(Sym));
391 if (!nb_buckets)
392 nb_buckets = ((int*)s->hash->data)[0];
394 s->hash->data_offset = 0;
395 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
396 ptr[0] = nb_buckets;
397 ptr[1] = nb_syms;
398 ptr += 2;
399 hash = ptr;
400 memset(hash, 0, (nb_buckets + 1) * sizeof(int));
401 ptr += nb_buckets + 1;
403 sym = (ElfW(Sym) *)s->data + 1;
404 for(sym_index = 1; sym_index < nb_syms; sym_index++) {
405 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
406 h = elf_hash(strtab + sym->st_name) % nb_buckets;
407 *ptr = hash[h];
408 hash[h] = sym_index;
409 } else {
410 *ptr = 0;
412 ptr++;
413 sym++;
417 /* return the symbol number */
418 ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size,
419 int info, int other, int shndx, const char *name)
421 int name_offset, sym_index;
422 int nbuckets, h;
423 ElfW(Sym) *sym;
424 Section *hs;
426 sym = section_ptr_add(s, sizeof(ElfW(Sym)));
427 if (name && name[0])
428 name_offset = put_elf_str(s->link, name);
429 else
430 name_offset = 0;
431 /* XXX: endianness */
432 sym->st_name = name_offset;
433 sym->st_value = value;
434 sym->st_size = size;
435 sym->st_info = info;
436 sym->st_other = other;
437 sym->st_shndx = shndx;
438 sym_index = sym - (ElfW(Sym) *)s->data;
439 hs = s->hash;
440 if (hs) {
441 int *ptr, *base;
442 ptr = section_ptr_add(hs, sizeof(int));
443 base = (int *)hs->data;
444 /* only add global or weak symbols. */
445 if (ELFW(ST_BIND)(info) != STB_LOCAL) {
446 /* add another hashing entry */
447 nbuckets = base[0];
448 h = elf_hash((unsigned char *)s->link->data + name_offset) % nbuckets;
449 *ptr = base[2 + h];
450 base[2 + h] = sym_index;
451 base[1]++;
452 /* we resize the hash table */
453 hs->nb_hashed_syms++;
454 if (hs->nb_hashed_syms > 2 * nbuckets) {
455 rebuild_hash(s, 2 * nbuckets);
457 } else {
458 *ptr = 0;
459 base[1]++;
462 return sym_index;
465 ST_FUNC int find_elf_sym(Section *s, const char *name)
467 ElfW(Sym) *sym;
468 Section *hs;
469 int nbuckets, sym_index, h;
470 const char *name1;
472 hs = s->hash;
473 if (!hs)
474 return 0;
475 nbuckets = ((int *)hs->data)[0];
476 h = elf_hash((unsigned char *) name) % nbuckets;
477 sym_index = ((int *)hs->data)[2 + h];
478 while (sym_index != 0) {
479 sym = &((ElfW(Sym) *)s->data)[sym_index];
480 name1 = (char *) s->link->data + sym->st_name;
481 if (!strcmp(name, name1))
482 return sym_index;
483 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
485 return 0;
488 /* return elf symbol value, signal error if 'err' is nonzero, decorate
489 name if FORC */
490 ST_FUNC addr_t get_sym_addr(TCCState *s1, const char *name, int err, int forc)
492 int sym_index;
493 ElfW(Sym) *sym;
494 char buf[256];
495 if (forc && s1->leading_underscore
496 #ifdef TCC_TARGET_PE
497 /* win32-32bit stdcall symbols always have _ already */
498 && !strchr(name, '@')
499 #endif
501 buf[0] = '_';
502 pstrcpy(buf + 1, sizeof(buf) - 1, name);
503 name = buf;
505 sym_index = find_elf_sym(s1->symtab, name);
506 sym = &((ElfW(Sym) *)s1->symtab->data)[sym_index];
507 if (!sym_index || sym->st_shndx == SHN_UNDEF) {
508 if (err)
509 tcc_error_noabort("%s not defined", name);
510 return (addr_t)-1;
512 return sym->st_value;
515 /* return elf symbol value */
516 LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
518 addr_t addr = get_sym_addr(s, name, 0, 1);
519 return addr == -1 ? NULL : (void*)(uintptr_t)addr;
522 /* list elf symbol names and values */
523 ST_FUNC void list_elf_symbols(TCCState *s, void *ctx,
524 void (*symbol_cb)(void *ctx, const char *name, const void *val))
526 ElfW(Sym) *sym;
527 Section *symtab;
528 int sym_index, end_sym;
529 const char *name;
530 unsigned char sym_vis, sym_bind;
532 symtab = s->symtab;
533 end_sym = symtab->data_offset / sizeof (ElfSym);
534 for (sym_index = 0; sym_index < end_sym; ++sym_index) {
535 sym = &((ElfW(Sym) *)symtab->data)[sym_index];
536 if (sym->st_value) {
537 name = (char *) symtab->link->data + sym->st_name;
538 sym_bind = ELFW(ST_BIND)(sym->st_info);
539 sym_vis = ELFW(ST_VISIBILITY)(sym->st_other);
540 if (sym_bind == STB_GLOBAL && sym_vis == STV_DEFAULT)
541 symbol_cb(ctx, name, (void*)(uintptr_t)sym->st_value);
546 /* list elf symbol names and values */
547 LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx,
548 void (*symbol_cb)(void *ctx, const char *name, const void *val))
550 list_elf_symbols(s, ctx, symbol_cb);
553 #ifndef ELF_OBJ_ONLY
554 static void
555 version_add (TCCState *s1)
557 int i;
558 ElfW(Sym) *sym;
559 ElfW(Verneed) *vn = NULL;
560 Section *symtab;
561 int sym_index, end_sym, nb_versions = 2, nb_entries = 0;
562 ElfW(Half) *versym;
563 const char *name;
565 if (0 == nb_sym_versions)
566 return;
567 versym_section = new_section(s1, ".gnu.version", SHT_GNU_versym, SHF_ALLOC);
568 versym_section->sh_entsize = sizeof(ElfW(Half));
569 versym_section->link = s1->dynsym;
571 /* add needed symbols */
572 symtab = s1->dynsym;
573 end_sym = symtab->data_offset / sizeof (ElfSym);
574 versym = section_ptr_add(versym_section, end_sym * sizeof(ElfW(Half)));
575 for (sym_index = 1; sym_index < end_sym; ++sym_index) {
576 int dllindex, verndx;
577 sym = &((ElfW(Sym) *)symtab->data)[sym_index];
578 if (sym->st_shndx != SHN_UNDEF)
579 continue; /* defined symbol doesn't need library version */
580 name = (char *) symtab->link->data + sym->st_name;
581 dllindex = find_elf_sym(s1->dynsymtab_section, name);
582 verndx = (dllindex && dllindex < nb_sym_to_version)
583 ? sym_to_version[dllindex] : -1;
584 if (verndx >= 0) {
585 if (!sym_versions[verndx].out_index)
586 sym_versions[verndx].out_index = nb_versions++;
587 versym[sym_index] = sym_versions[verndx].out_index;
590 /* generate verneed section, but not when it will be empty. Some
591 dynamic linkers look at their contents even when DTVERNEEDNUM and
592 section size is zero. */
593 if (nb_versions > 2) {
594 verneed_section = new_section(s1, ".gnu.version_r",
595 SHT_GNU_verneed, SHF_ALLOC);
596 verneed_section->link = s1->dynsym->link;
597 for (i = nb_sym_versions; i-- > 0;) {
598 struct sym_version *sv = &sym_versions[i];
599 int n_same_libs = 0, prev;
600 size_t vnofs;
601 ElfW(Vernaux) *vna = 0;
602 if (sv->out_index < 1)
603 continue;
605 /* make sure that a DT_NEEDED tag is put */
606 /* abitest-tcc fails on older i386-linux with "ld-linux.so.2" DT_NEEDED
607 ret_int_test... Inconsistency detected by ld.so: dl-minimal.c: 148:
608 realloc: Assertion `ptr == alloc_last_block' failed! */
609 if (strcmp(sv->lib, "ld-linux.so.2"))
610 tcc_add_dllref(s1, sv->lib, 0);
612 vnofs = section_add(verneed_section, sizeof(*vn), 1);
613 vn = (ElfW(Verneed)*)(verneed_section->data + vnofs);
614 vn->vn_version = 1;
615 vn->vn_file = put_elf_str(verneed_section->link, sv->lib);
616 vn->vn_aux = sizeof (*vn);
617 do {
618 prev = sv->prev_same_lib;
619 if (sv->out_index > 0) {
620 vna = section_ptr_add(verneed_section, sizeof(*vna));
621 vna->vna_hash = elf_hash ((const unsigned char *)sv->version);
622 vna->vna_flags = 0;
623 vna->vna_other = sv->out_index;
624 sv->out_index = -2;
625 vna->vna_name = put_elf_str(verneed_section->link, sv->version);
626 vna->vna_next = sizeof (*vna);
627 n_same_libs++;
629 if (prev >= 0)
630 sv = &sym_versions[prev];
631 } while(prev >= 0);
632 vna->vna_next = 0;
633 vn = (ElfW(Verneed)*)(verneed_section->data + vnofs);
634 vn->vn_cnt = n_same_libs;
635 vn->vn_next = sizeof(*vn) + n_same_libs * sizeof(*vna);
636 nb_entries++;
638 if (vn)
639 vn->vn_next = 0;
640 verneed_section->sh_info = nb_entries;
642 dt_verneednum = nb_entries;
644 #endif /* ndef ELF_OBJ_ONLY */
646 /* add an elf symbol : check if it is already defined and patch
647 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
648 ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size,
649 int info, int other, int shndx, const char *name)
651 TCCState *s1 = s->s1;
652 ElfW(Sym) *esym;
653 int sym_bind, sym_index, sym_type, esym_bind;
654 unsigned char sym_vis, esym_vis, new_vis;
656 sym_bind = ELFW(ST_BIND)(info);
657 sym_type = ELFW(ST_TYPE)(info);
658 sym_vis = ELFW(ST_VISIBILITY)(other);
660 if (sym_bind != STB_LOCAL) {
661 /* we search global or weak symbols */
662 sym_index = find_elf_sym(s, name);
663 if (!sym_index)
664 goto do_def;
665 esym = &((ElfW(Sym) *)s->data)[sym_index];
666 if (esym->st_value == value && esym->st_size == size && esym->st_info == info
667 && esym->st_other == other && esym->st_shndx == shndx)
668 return sym_index;
669 if (esym->st_shndx != SHN_UNDEF) {
670 esym_bind = ELFW(ST_BIND)(esym->st_info);
671 /* propagate the most constraining visibility */
672 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
673 esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
674 if (esym_vis == STV_DEFAULT) {
675 new_vis = sym_vis;
676 } else if (sym_vis == STV_DEFAULT) {
677 new_vis = esym_vis;
678 } else {
679 new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
681 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
682 | new_vis;
683 if (shndx == SHN_UNDEF) {
684 /* ignore adding of undefined symbol if the
685 corresponding symbol is already defined */
686 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
687 /* global overrides weak, so patch */
688 goto do_patch;
689 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
690 /* weak is ignored if already global */
691 } else if (sym_bind == STB_WEAK && esym_bind == STB_WEAK) {
692 /* keep first-found weak definition, ignore subsequents */
693 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
694 /* ignore hidden symbols after */
695 } else if ((esym->st_shndx == SHN_COMMON
696 || esym->st_shndx == bss_section->sh_num)
697 && (shndx < SHN_LORESERVE
698 && shndx != bss_section->sh_num)) {
699 /* data symbol gets precedence over common/bss */
700 goto do_patch;
701 } else if (shndx == SHN_COMMON || shndx == bss_section->sh_num) {
702 /* data symbol keeps precedence over common/bss */
703 } else if (s->sh_flags & SHF_DYNSYM) {
704 /* we accept that two DLL define the same symbol */
705 } else if (esym->st_other & ST_ASM_SET) {
706 /* If the existing symbol came from an asm .set
707 we can override. */
708 goto do_patch;
709 } else {
710 #if 0
711 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
712 sym_bind, shndx, new_vis, esym_bind, esym->st_shndx, esym_vis);
713 #endif
714 tcc_error_noabort("'%s' defined twice", name);
716 } else {
717 esym->st_other = other;
718 do_patch:
719 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
720 esym->st_shndx = shndx;
721 s1->new_undef_sym = 1;
722 esym->st_value = value;
723 esym->st_size = size;
725 } else {
726 do_def:
727 sym_index = put_elf_sym(s, value, size,
728 ELFW(ST_INFO)(sym_bind, sym_type), other,
729 shndx, name);
731 return sym_index;
734 /* put relocation */
735 ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset,
736 int type, int symbol, addr_t addend)
738 TCCState *s1 = s->s1;
739 char buf[256];
740 Section *sr;
741 ElfW_Rel *rel;
743 sr = s->reloc;
744 if (!sr) {
745 /* if no relocation section, create it */
746 snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
747 /* if the symtab is allocated, then we consider the relocation
748 are also */
749 sr = new_section(s->s1, buf, SHT_RELX, symtab->sh_flags);
750 sr->sh_entsize = sizeof(ElfW_Rel);
751 sr->link = symtab;
752 sr->sh_info = s->sh_num;
753 s->reloc = sr;
755 rel = section_ptr_add(sr, sizeof(ElfW_Rel));
756 rel->r_offset = offset;
757 rel->r_info = ELFW(R_INFO)(symbol, type);
758 #if SHT_RELX == SHT_RELA
759 rel->r_addend = addend;
760 #endif
761 if (SHT_RELX != SHT_RELA && addend)
762 tcc_error_noabort("non-zero addend on REL architecture");
765 ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
766 int type, int symbol)
768 put_elf_reloca(symtab, s, offset, type, symbol, 0);
771 ST_FUNC struct sym_attr *get_sym_attr(TCCState *s1, int index, int alloc)
773 int n;
774 struct sym_attr *tab;
776 if (index >= s1->nb_sym_attrs) {
777 if (!alloc)
778 return s1->sym_attrs;
779 /* find immediately bigger power of 2 and reallocate array */
780 n = 1;
781 while (index >= n)
782 n *= 2;
783 tab = tcc_realloc(s1->sym_attrs, n * sizeof(*s1->sym_attrs));
784 s1->sym_attrs = tab;
785 memset(s1->sym_attrs + s1->nb_sym_attrs, 0,
786 (n - s1->nb_sym_attrs) * sizeof(*s1->sym_attrs));
787 s1->nb_sym_attrs = n;
789 return &s1->sym_attrs[index];
792 static void update_relocs(TCCState *s1, Section *s, int *old_to_new_syms, int first_sym)
794 int i, type, sym_index;
795 Section *sr;
796 ElfW_Rel *rel;
798 for(i = 1; i < s1->nb_sections; i++) {
799 sr = s1->sections[i];
800 if (sr->sh_type == SHT_RELX && sr->link == s) {
801 for_each_elem(sr, 0, rel, ElfW_Rel) {
802 sym_index = ELFW(R_SYM)(rel->r_info);
803 type = ELFW(R_TYPE)(rel->r_info);
804 if ((sym_index -= first_sym) < 0)
805 continue; /* zero sym_index in reloc (can happen with asm) */
806 sym_index = old_to_new_syms[sym_index];
807 rel->r_info = ELFW(R_INFO)(sym_index, type);
813 /* In an ELF file symbol table, the local symbols must appear below
814 the global and weak ones. Since TCC cannot sort it while generating
815 the code, we must do it after. All the relocation tables are also
816 modified to take into account the symbol table sorting */
817 static void sort_syms(TCCState *s1, Section *s)
819 int *old_to_new_syms;
820 ElfW(Sym) *new_syms;
821 int nb_syms, i;
822 ElfW(Sym) *p, *q;
824 nb_syms = s->data_offset / sizeof(ElfW(Sym));
825 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
826 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
828 /* first pass for local symbols */
829 p = (ElfW(Sym) *)s->data;
830 q = new_syms;
831 for(i = 0; i < nb_syms; i++) {
832 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
833 old_to_new_syms[i] = q - new_syms;
834 *q++ = *p;
836 p++;
838 /* save the number of local symbols in section header */
839 if( s->sh_size ) /* this 'if' makes IDA happy */
840 s->sh_info = q - new_syms;
842 /* then second pass for non local symbols */
843 p = (ElfW(Sym) *)s->data;
844 for(i = 0; i < nb_syms; i++) {
845 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
846 old_to_new_syms[i] = q - new_syms;
847 *q++ = *p;
849 p++;
852 /* we copy the new symbols to the old */
853 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
854 tcc_free(new_syms);
856 update_relocs(s1, s, old_to_new_syms, 0);
857 tcc_free(old_to_new_syms);
860 #ifndef ELF_OBJ_ONLY
861 /* See: https://flapenguin.me/elf-dt-gnu-hash */
862 #define ELFCLASS_BITS (PTR_SIZE * 8)
864 static Section *create_gnu_hash(TCCState *s1)
866 int nb_syms, i, ndef, nbuckets, symoffset, bloom_size, bloom_shift;
867 ElfW(Sym) *p;
868 Section *gnu_hash;
869 Section *dynsym = s1->dynsym;
870 Elf32_Word *ptr;
872 gnu_hash = new_section(s1, ".gnu.hash", SHT_GNU_HASH, SHF_ALLOC);
873 gnu_hash->link = dynsym->hash->link;
875 nb_syms = dynsym->data_offset / sizeof(ElfW(Sym));
877 /* count def symbols */
878 ndef = 0;
879 p = (ElfW(Sym) *)dynsym->data;
880 for(i = 0; i < nb_syms; i++, p++)
881 ndef += p->st_shndx != SHN_UNDEF;
883 /* calculate gnu hash sizes and fill header */
884 nbuckets = ndef / 4 + 1;
885 symoffset = nb_syms - ndef;
886 bloom_shift = PTR_SIZE == 8 ? 6 : 5;
887 bloom_size = 1; /* must be power of two */
888 while (ndef >= bloom_size * (1 << (bloom_shift - 3)))
889 bloom_size *= 2;
890 ptr = section_ptr_add(gnu_hash, 4 * 4 +
891 PTR_SIZE * bloom_size +
892 nbuckets * 4 +
893 ndef * 4);
894 ptr[0] = nbuckets;
895 ptr[1] = symoffset;
896 ptr[2] = bloom_size;
897 ptr[3] = bloom_shift;
898 return gnu_hash;
901 static Elf32_Word elf_gnu_hash (const unsigned char *name)
903 Elf32_Word h = 5381;
904 unsigned char c;
906 while ((c = *name++))
907 h = h * 33 + c;
908 return h;
911 static void update_gnu_hash(TCCState *s1, Section *gnu_hash)
913 int *old_to_new_syms;
914 ElfW(Sym) *new_syms;
915 int nb_syms, i, nbuckets, bloom_size, bloom_shift;
916 ElfW(Sym) *p, *q;
917 Section *vs;
918 Section *dynsym = s1->dynsym;
919 Elf32_Word *ptr, *buckets, *chain, *hash;
920 unsigned int *nextbuck;
921 addr_t *bloom;
922 unsigned char *strtab;
923 struct { int first, last; } *buck;
925 strtab = dynsym->link->data;
926 nb_syms = dynsym->data_offset / sizeof(ElfW(Sym));
927 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
928 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
929 hash = tcc_malloc(nb_syms * sizeof(Elf32_Word));
930 nextbuck = tcc_malloc(nb_syms * sizeof(int));
932 /* calculate hashes and copy undefs */
933 p = (ElfW(Sym) *)dynsym->data;
934 q = new_syms;
935 for(i = 0; i < nb_syms; i++, p++) {
936 if (p->st_shndx == SHN_UNDEF) {
937 old_to_new_syms[i] = q - new_syms;
938 *q++ = *p;
940 else
941 hash[i] = elf_gnu_hash(strtab + p->st_name);
944 ptr = (Elf32_Word *) gnu_hash->data;
945 nbuckets = ptr[0];
946 bloom_size = ptr[2];
947 bloom_shift = ptr[3];
948 bloom = (addr_t *) (void *) &ptr[4];
949 buckets = (Elf32_Word*) (void *) &bloom[bloom_size];
950 chain = &buckets[nbuckets];
951 buck = tcc_malloc(nbuckets * sizeof(*buck));
953 if (gnu_hash->data_offset != 4 * 4 +
954 PTR_SIZE * bloom_size +
955 nbuckets * 4 +
956 (nb_syms - (q - new_syms)) * 4)
957 tcc_error_noabort ("gnu_hash size incorrect");
959 /* find buckets */
960 for(i = 0; i < nbuckets; i++)
961 buck[i].first = -1;
963 p = (ElfW(Sym) *)dynsym->data;
964 for(i = 0; i < nb_syms; i++, p++)
965 if (p->st_shndx != SHN_UNDEF) {
966 int bucket = hash[i] % nbuckets;
968 if (buck[bucket].first == -1)
969 buck[bucket].first = buck[bucket].last = i;
970 else {
971 nextbuck[buck[bucket].last] = i;
972 buck[bucket].last = i;
976 /* fill buckets/chains/bloom and sort symbols */
977 p = (ElfW(Sym) *)dynsym->data;
978 for(i = 0; i < nbuckets; i++) {
979 int cur = buck[i].first;
981 if (cur != -1) {
982 buckets[i] = q - new_syms;
983 for (;;) {
984 old_to_new_syms[cur] = q - new_syms;
985 *q++ = p[cur];
986 *chain++ = hash[cur] & ~1;
987 bloom[(hash[cur] / ELFCLASS_BITS) % bloom_size] |=
988 (addr_t)1 << (hash[cur] % ELFCLASS_BITS) |
989 (addr_t)1 << ((hash[cur] >> bloom_shift) % ELFCLASS_BITS);
990 if (cur == buck[i].last)
991 break;
992 cur = nextbuck[cur];
994 chain[-1] |= 1;
998 memcpy(dynsym->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
999 tcc_free(new_syms);
1000 tcc_free(hash);
1001 tcc_free(buck);
1002 tcc_free(nextbuck);
1004 update_relocs(s1, dynsym, old_to_new_syms, 0);
1006 /* modify the versions */
1007 vs = versym_section;
1008 if (vs) {
1009 ElfW(Half) *newver, *versym = (ElfW(Half) *)vs->data;
1011 if (1/*versym*/) {
1012 newver = tcc_malloc(nb_syms * sizeof(*newver));
1013 for (i = 0; i < nb_syms; i++)
1014 newver[old_to_new_syms[i]] = versym[i];
1015 memcpy(vs->data, newver, nb_syms * sizeof(*newver));
1016 tcc_free(newver);
1020 tcc_free(old_to_new_syms);
1022 /* rebuild hash */
1023 ptr = (Elf32_Word *) dynsym->hash->data;
1024 rebuild_hash(dynsym, ptr[0]);
1026 #endif /* ELF_OBJ_ONLY */
1028 /* relocate symbol table, resolve undefined symbols if do_resolve is
1029 true and output error if undefined symbol. */
1030 ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve)
1032 ElfW(Sym) *sym;
1033 int sym_bind, sh_num;
1034 const char *name;
1036 for_each_elem(symtab, 1, sym, ElfW(Sym)) {
1037 sh_num = sym->st_shndx;
1038 if (sh_num == SHN_UNDEF) {
1039 if (do_resolve == 2) /* relocating dynsym */
1040 continue;
1041 name = (char *) s1->symtab->link->data + sym->st_name;
1042 /* Use ld.so to resolve symbol for us (for tcc -run) */
1043 if (do_resolve) {
1044 #if defined TCC_IS_NATIVE && !defined TCC_TARGET_PE
1045 /* dlsym() needs the undecorated name. */
1046 void *addr = dlsym(RTLD_DEFAULT, &name[s1->leading_underscore]);
1047 #if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD || TARGETOS_ANDROID
1048 if (addr == NULL) {
1049 int i;
1050 for (i = 0; i < s1->nb_loaded_dlls; i++)
1051 if ((addr = dlsym(s1->loaded_dlls[i]->handle, name)))
1052 break;
1054 #endif
1055 if (addr) {
1056 sym->st_value = (addr_t) addr;
1057 #ifdef DEBUG_RELOC
1058 printf ("relocate_sym: %s -> 0x%lx\n", name, sym->st_value);
1059 #endif
1060 goto found;
1062 #endif
1063 /* if dynamic symbol exist, it will be used in relocate_section */
1064 } else if (s1->dynsym && find_elf_sym(s1->dynsym, name))
1065 goto found;
1066 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1067 it */
1068 if (!strcmp(name, "_fp_hw"))
1069 goto found;
1070 /* only weak symbols are accepted to be undefined. Their
1071 value is zero */
1072 sym_bind = ELFW(ST_BIND)(sym->st_info);
1073 if (sym_bind == STB_WEAK)
1074 sym->st_value = 0;
1075 else
1076 tcc_error_noabort("undefined symbol '%s'", name);
1078 } else if (sh_num < SHN_LORESERVE) {
1079 /* add section base */
1080 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
1082 found: ;
1086 /* relocate a given section (CPU dependent) by applying the relocations
1087 in the associated relocation section */
1088 static void relocate_section(TCCState *s1, Section *s, Section *sr)
1090 ElfW_Rel *rel;
1091 ElfW(Sym) *sym;
1092 int type, sym_index;
1093 unsigned char *ptr;
1094 addr_t tgt, addr;
1095 int is_dwarf = s->sh_num >= s1->dwlo && s->sh_num < s1->dwhi;
1097 qrel = (ElfW_Rel *)sr->data;
1098 for_each_elem(sr, 0, rel, ElfW_Rel) {
1099 ptr = s->data + rel->r_offset;
1100 sym_index = ELFW(R_SYM)(rel->r_info);
1101 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1102 type = ELFW(R_TYPE)(rel->r_info);
1103 tgt = sym->st_value;
1104 #if SHT_RELX == SHT_RELA
1105 tgt += rel->r_addend;
1106 #endif
1107 if (is_dwarf && type == R_DATA_32DW
1108 && sym->st_shndx >= s1->dwlo && sym->st_shndx < s1->dwhi) {
1109 /* dwarf section relocation to each other */
1110 add32le(ptr, tgt - s1->sections[sym->st_shndx]->sh_addr);
1111 continue;
1113 addr = s->sh_addr + rel->r_offset;
1114 relocate(s1, rel, type, ptr, addr, tgt);
1116 #ifndef ELF_OBJ_ONLY
1117 /* if the relocation is allocated, we change its symbol table */
1118 if (sr->sh_flags & SHF_ALLOC) {
1119 sr->link = s1->dynsym;
1120 if (s1->output_type & TCC_OUTPUT_DYN) {
1121 size_t r = (uint8_t*)qrel - sr->data;
1122 if (sizeof ((Stab_Sym*)0)->n_value < PTR_SIZE
1123 && 0 == strcmp(s->name, ".stab"))
1124 r = 0; /* cannot apply 64bit relocation to 32bit value */
1125 sr->data_offset = sr->sh_size = r;
1126 #ifdef CONFIG_TCC_PIE
1127 if (r && 0 == (s->sh_flags & SHF_WRITE))
1128 tcc_warning("%d relocations to ro-section %s", (unsigned)(r / sizeof *qrel), s->name);
1129 #endif
1132 #endif
1135 /* relocate all sections */
1136 ST_FUNC void relocate_sections(TCCState *s1)
1138 int i;
1139 Section *s, *sr;
1141 for (i = 1; i < s1->nb_sections; ++i) {
1142 sr = s1->sections[i];
1143 if (sr->sh_type != SHT_RELX)
1144 continue;
1145 s = s1->sections[sr->sh_info];
1146 #ifndef TCC_TARGET_MACHO
1147 if (s != s1->got
1148 || s1->static_link
1149 || s1->output_type == TCC_OUTPUT_MEMORY)
1150 #endif
1152 relocate_section(s1, s, sr);
1154 #ifndef ELF_OBJ_ONLY
1155 if (sr->sh_flags & SHF_ALLOC) {
1156 ElfW_Rel *rel;
1157 /* relocate relocation table in 'sr' */
1158 for_each_elem(sr, 0, rel, ElfW_Rel)
1159 rel->r_offset += s->sh_addr;
1161 #endif
1165 #ifndef ELF_OBJ_ONLY
1166 /* count the number of dynamic relocations so that we can reserve
1167 their space */
1168 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
1170 int count = 0;
1171 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) || \
1172 defined(TCC_TARGET_ARM) || defined(TCC_TARGET_ARM64) || \
1173 defined(TCC_TARGET_RISCV64)
1174 ElfW_Rel *rel;
1175 for_each_elem(sr, 0, rel, ElfW_Rel) {
1176 int sym_index = ELFW(R_SYM)(rel->r_info);
1177 int type = ELFW(R_TYPE)(rel->r_info);
1178 switch(type) {
1179 #if defined(TCC_TARGET_I386)
1180 case R_386_32:
1181 if (!get_sym_attr(s1, sym_index, 0)->dyn_index
1182 && ((ElfW(Sym)*)symtab_section->data + sym_index)->st_shndx == SHN_UNDEF) {
1183 /* don't fixup unresolved (weak) symbols */
1184 rel->r_info = ELFW(R_INFO)(sym_index, R_386_RELATIVE);
1185 break;
1187 #elif defined(TCC_TARGET_X86_64)
1188 case R_X86_64_32:
1189 case R_X86_64_32S:
1190 case R_X86_64_64:
1191 #elif defined(TCC_TARGET_ARM)
1192 case R_ARM_ABS32:
1193 case R_ARM_TARGET1:
1194 #elif defined(TCC_TARGET_ARM64)
1195 case R_AARCH64_ABS32:
1196 case R_AARCH64_ABS64:
1197 #elif defined(TCC_TARGET_RISCV64)
1198 case R_RISCV_32:
1199 case R_RISCV_64:
1200 #endif
1201 count++;
1202 break;
1203 #if defined(TCC_TARGET_I386)
1204 case R_386_PC32:
1205 #elif defined(TCC_TARGET_X86_64)
1206 case R_X86_64_PC32:
1208 ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1209 /* Hidden defined symbols can and must be resolved locally.
1210 We're misusing a PLT32 reloc for this, as that's always
1211 resolved to its address even in shared libs. */
1212 if (sym->st_shndx != SHN_UNDEF &&
1213 ELFW(ST_VISIBILITY)(sym->st_other) == STV_HIDDEN) {
1214 rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PLT32);
1215 break;
1218 #elif defined(TCC_TARGET_ARM64)
1219 case R_AARCH64_PREL32:
1220 #endif
1221 if (s1->output_type != TCC_OUTPUT_DLL)
1222 break;
1223 if (get_sym_attr(s1, sym_index, 0)->dyn_index)
1224 count++;
1225 break;
1226 default:
1227 break;
1230 #endif
1231 return count;
1233 #endif
1235 #ifdef NEED_BUILD_GOT
1236 static int build_got(TCCState *s1)
1238 /* if no got, then create it */
1239 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
1240 s1->got->sh_entsize = 4;
1241 /* keep space for _DYNAMIC pointer and two dummy got entries */
1242 section_ptr_add(s1->got, 3 * PTR_SIZE);
1243 return set_elf_sym(symtab_section, 0, 0, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
1244 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
1247 /* Create a GOT and (for function call) a PLT entry corresponding to a symbol
1248 in s1->symtab. When creating the dynamic symbol table entry for the GOT
1249 relocation, use 'size' and 'info' for the corresponding symbol metadata.
1250 Returns the offset of the GOT or (if any) PLT entry. */
1251 static struct sym_attr * put_got_entry(TCCState *s1, int dyn_reloc_type,
1252 int sym_index)
1254 int need_plt_entry;
1255 const char *name;
1256 ElfW(Sym) *sym;
1257 struct sym_attr *attr;
1258 unsigned got_offset;
1259 char plt_name[200];
1260 int len;
1261 Section *s_rel;
1263 need_plt_entry = (dyn_reloc_type == R_JMP_SLOT);
1264 attr = get_sym_attr(s1, sym_index, 1);
1266 /* In case a function is both called and its address taken 2 GOT entries
1267 are created, one for taking the address (GOT) and the other for the PLT
1268 entry (PLTGOT). */
1269 if (need_plt_entry ? attr->plt_offset : attr->got_offset)
1270 return attr;
1272 s_rel = s1->got;
1273 if (need_plt_entry) {
1274 if (!s1->plt) {
1275 s1->plt = new_section(s1, ".plt", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
1276 s1->plt->sh_entsize = 4;
1278 s_rel = s1->plt;
1281 /* create the GOT entry */
1282 got_offset = s1->got->data_offset;
1283 section_ptr_add(s1->got, PTR_SIZE);
1285 /* Create the GOT relocation that will insert the address of the object or
1286 function of interest in the GOT entry. This is a static relocation for
1287 memory output (dlsym will give us the address of symbols) and dynamic
1288 relocation otherwise (executable and DLLs). The relocation should be
1289 done lazily for GOT entry with *_JUMP_SLOT relocation type (the one
1290 associated to a PLT entry) but is currently done at load time for an
1291 unknown reason. */
1293 sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1294 name = (char *) symtab_section->link->data + sym->st_name;
1295 //printf("sym %d %s\n", need_plt_entry, name);
1297 if (s1->dynsym) {
1298 if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) {
1299 /* Hack alarm. We don't want to emit dynamic symbols
1300 and symbol based relocs for STB_LOCAL symbols, but rather
1301 want to resolve them directly. At this point the symbol
1302 values aren't final yet, so we must defer this. We will later
1303 have to create a RELATIVE reloc anyway, so we misuse the
1304 relocation slot to smuggle the symbol reference until
1305 fill_local_got_entries. Not that the sym_index is
1306 relative to symtab_section, not s1->dynsym! Nevertheless
1307 we use s1->dyn_sym so that if this is the first call
1308 that got->reloc is correctly created. Also note that
1309 RELATIVE relocs are not normally created for the .got,
1310 so the types serves as a marker for later (and is retained
1311 also for the final output, which is okay because then the
1312 got is just normal data). */
1313 put_elf_reloc(s1->dynsym, s1->got, got_offset, R_RELATIVE,
1314 sym_index);
1315 } else {
1316 if (0 == attr->dyn_index)
1317 attr->dyn_index = set_elf_sym(s1->dynsym, sym->st_value,
1318 sym->st_size, sym->st_info, 0,
1319 sym->st_shndx, name);
1320 put_elf_reloc(s1->dynsym, s_rel, got_offset, dyn_reloc_type,
1321 attr->dyn_index);
1323 } else {
1324 put_elf_reloc(symtab_section, s1->got, got_offset, dyn_reloc_type,
1325 sym_index);
1328 if (need_plt_entry) {
1329 attr->plt_offset = create_plt_entry(s1, got_offset, attr);
1331 /* create a symbol 'sym@plt' for the PLT jump vector */
1332 len = strlen(name);
1333 if (len > sizeof plt_name - 5)
1334 len = sizeof plt_name - 5;
1335 memcpy(plt_name, name, len);
1336 strcpy(plt_name + len, "@plt");
1337 attr->plt_sym = put_elf_sym(s1->symtab, attr->plt_offset, 0,
1338 ELFW(ST_INFO)(STB_GLOBAL, STT_FUNC), 0, s1->plt->sh_num, plt_name);
1339 } else {
1340 attr->got_offset = got_offset;
1343 return attr;
1346 /* build GOT and PLT entries */
1347 /* Two passes because R_JMP_SLOT should become first. Some targets
1348 (arm, arm64) do not allow mixing R_JMP_SLOT and R_GLOB_DAT. */
1349 ST_FUNC void build_got_entries(TCCState *s1, int got_sym)
1351 Section *s;
1352 ElfW_Rel *rel;
1353 ElfW(Sym) *sym;
1354 int i, type, gotplt_entry, reloc_type, sym_index;
1355 struct sym_attr *attr;
1356 int pass = 0;
1357 redo:
1358 for(i = 1; i < s1->nb_sections; i++) {
1359 s = s1->sections[i];
1360 if (s->sh_type != SHT_RELX)
1361 continue;
1362 /* no need to handle got relocations */
1363 if (s->link != symtab_section)
1364 continue;
1365 for_each_elem(s, 0, rel, ElfW_Rel) {
1366 type = ELFW(R_TYPE)(rel->r_info);
1367 gotplt_entry = gotplt_entry_type(type);
1368 if (gotplt_entry == -1) {
1369 tcc_error_noabort ("Unknown relocation type for got: %d", type);
1370 continue;
1372 sym_index = ELFW(R_SYM)(rel->r_info);
1373 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1375 if (gotplt_entry == NO_GOTPLT_ENTRY) {
1376 continue;
1379 /* Automatically create PLT/GOT [entry] if it is an undefined
1380 reference (resolved at runtime), or the symbol is absolute,
1381 probably created by tcc_add_symbol, and thus on 64-bit
1382 targets might be too far from application code. */
1383 if (gotplt_entry == AUTO_GOTPLT_ENTRY) {
1384 if (sym->st_shndx == SHN_UNDEF) {
1385 ElfW(Sym) *esym;
1386 int dynindex;
1387 if (!PCRELATIVE_DLLPLT
1388 && (s1->output_type & TCC_OUTPUT_DYN))
1389 continue;
1390 /* Relocations for UNDEF symbols would normally need
1391 to be transferred into the executable or shared object.
1392 If that were done AUTO_GOTPLT_ENTRY wouldn't exist.
1393 But TCC doesn't do that (at least for exes), so we
1394 need to resolve all such relocs locally. And that
1395 means PLT slots for functions in DLLs and COPY relocs for
1396 data symbols. COPY relocs were generated in
1397 bind_exe_dynsyms (and the symbol adjusted to be defined),
1398 and for functions we were generated a dynamic symbol
1399 of function type. */
1400 if (s1->dynsym) {
1401 /* dynsym isn't set for -run :-/ */
1402 dynindex = get_sym_attr(s1, sym_index, 0)->dyn_index;
1403 esym = (ElfW(Sym) *)s1->dynsym->data + dynindex;
1404 if (dynindex
1405 && (ELFW(ST_TYPE)(esym->st_info) == STT_FUNC
1406 || (ELFW(ST_TYPE)(esym->st_info) == STT_NOTYPE
1407 && ELFW(ST_TYPE)(sym->st_info) == STT_FUNC)))
1408 goto jmp_slot;
1410 } else if (sym->st_shndx == SHN_ABS) {
1411 if (sym->st_value == 0) /* from tcc_add_btstub() */
1412 continue;
1413 #ifndef TCC_TARGET_ARM
1414 if (PTR_SIZE != 8)
1415 continue;
1416 #endif
1417 /* from tcc_add_symbol(): on 64 bit platforms these
1418 need to go through .got */
1419 } else
1420 continue;
1423 #ifdef TCC_TARGET_X86_64
1424 if ((type == R_X86_64_PLT32 || type == R_X86_64_PC32) &&
1425 sym->st_shndx != SHN_UNDEF &&
1426 (ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT ||
1427 ELFW(ST_BIND)(sym->st_info) == STB_LOCAL ||
1428 s1->output_type & TCC_OUTPUT_EXE)) {
1429 if (pass != 0)
1430 continue;
1431 rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32);
1432 continue;
1434 #endif
1435 reloc_type = code_reloc(type);
1436 if (reloc_type == -1) {
1437 tcc_error_noabort ("Unknown relocation type: %d", type);
1438 continue;
1441 if (reloc_type != 0) {
1442 jmp_slot:
1443 if (pass != 0)
1444 continue;
1445 reloc_type = R_JMP_SLOT;
1446 } else {
1447 if (pass != 1)
1448 continue;
1449 reloc_type = R_GLOB_DAT;
1452 if (!s1->got)
1453 got_sym = build_got(s1);
1455 if (gotplt_entry == BUILD_GOT_ONLY)
1456 continue;
1458 attr = put_got_entry(s1, reloc_type, sym_index);
1460 if (reloc_type == R_JMP_SLOT)
1461 rel->r_info = ELFW(R_INFO)(attr->plt_sym, type);
1464 if (++pass < 2)
1465 goto redo;
1466 /* .rel.plt refers to .got actually */
1467 if (s1->plt && s1->plt->reloc)
1468 s1->plt->reloc->sh_info = s1->got->sh_num;
1469 if (got_sym) /* set size */
1470 ((ElfW(Sym)*)symtab_section->data)[got_sym].st_size = s1->got->data_offset;
1472 #endif /* def NEED_BUILD_GOT */
1474 ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t offs)
1476 int shn = sec ? sec->sh_num : offs || !name ? SHN_ABS : SHN_UNDEF;
1477 if (sec && offs == -1)
1478 offs = sec->data_offset;
1479 return set_elf_sym(symtab_section, offs, 0,
1480 ELFW(ST_INFO)(name ? STB_GLOBAL : STB_LOCAL, STT_NOTYPE), 0, shn, name);
1483 static void add_init_array_defines(TCCState *s1, const char *section_name)
1485 Section *s;
1486 addr_t end_offset;
1487 char buf[1024];
1488 s = have_section(s1, section_name);
1489 if (!s || !(s->sh_flags & SHF_ALLOC)) {
1490 end_offset = 0;
1491 s = data_section;
1492 } else {
1493 end_offset = s->data_offset;
1495 snprintf(buf, sizeof(buf), "__%s_start", section_name + 1);
1496 set_global_sym(s1, buf, s, 0);
1497 snprintf(buf, sizeof(buf), "__%s_end", section_name + 1);
1498 set_global_sym(s1, buf, s, end_offset);
1501 ST_FUNC void add_array (TCCState *s1, const char *sec, int c)
1503 Section *s;
1504 s = find_section(s1, sec);
1505 s->sh_flags = shf_RELRO;
1506 s->sh_type = sec[1] == 'i' ? SHT_INIT_ARRAY : SHT_FINI_ARRAY;
1507 put_elf_reloc (s1->symtab, s, s->data_offset, R_DATA_PTR, c);
1508 section_ptr_add(s, PTR_SIZE);
1511 #ifdef CONFIG_TCC_BCHECK
1512 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1514 if (0 == s1->do_bounds_check)
1515 return;
1516 section_ptr_add(bounds_section, sizeof(addr_t));
1518 #endif
1520 /* set symbol to STB_LOCAL and resolve. The point is to not export it as
1521 a dynamic symbol to allow so's to have one each with a different value. */
1522 static void set_local_sym(TCCState *s1, const char *name, Section *s, int offset)
1524 int c = find_elf_sym(s1->symtab, name);
1525 if (c) {
1526 ElfW(Sym) *esym = (ElfW(Sym)*)s1->symtab->data + c;
1527 esym->st_info = ELFW(ST_INFO)(STB_LOCAL, STT_NOTYPE);
1528 esym->st_value = offset;
1529 esym->st_shndx = s->sh_num;
1533 /* avoid generating debug/test_coverage code for stub functions */
1534 static void tcc_compile_string_no_debug(TCCState *s, const char *str)
1536 int save_do_debug = s->do_debug;
1537 int save_test_coverage = s->test_coverage;
1539 s->do_debug = 0;
1540 s->test_coverage = 0;
1541 tcc_compile_string(s, str);
1542 s->do_debug = save_do_debug;
1543 s->test_coverage = save_test_coverage;
1546 #ifdef CONFIG_TCC_BACKTRACE
1547 static void put_ptr(TCCState *s1, Section *s, int offs)
1549 int c;
1550 c = set_global_sym(s1, NULL, s, offs);
1551 s = data_section;
1552 put_elf_reloc (s1->symtab, s, s->data_offset, R_DATA_PTR, c);
1553 section_ptr_add(s, PTR_SIZE);
1556 ST_FUNC void tcc_add_btstub(TCCState *s1)
1558 Section *s;
1559 int n, o, *p;
1560 CString cstr;
1561 const char *__rt_info = &"___rt_info"[!s1->leading_underscore];
1563 s = data_section;
1564 /* Align to PTR_SIZE */
1565 section_ptr_add(s, -s->data_offset & (PTR_SIZE - 1));
1566 o = s->data_offset;
1567 /* create a struct rt_context (see tccrun.c) */
1568 if (s1->dwarf) {
1569 put_ptr(s1, dwarf_line_section, 0);
1570 put_ptr(s1, dwarf_line_section, -1);
1571 if (s1->dwarf >= 5)
1572 put_ptr(s1, dwarf_line_str_section, 0);
1573 else
1574 put_ptr(s1, dwarf_str_section, 0);
1576 else
1578 put_ptr(s1, stab_section, 0);
1579 put_ptr(s1, stab_section, -1);
1580 put_ptr(s1, stab_section->link, 0);
1583 /* skip esym_start/esym_end/elf_str (not loaded) */
1584 section_ptr_add(s, 3 * PTR_SIZE);
1586 if (s1->output_type == TCC_OUTPUT_MEMORY && 0 == s1->dwarf) {
1587 put_ptr(s1, text_section, 0);
1588 } else {
1589 /* prog_base : local nameless symbol with offset 0 at SHN_ABS */
1590 put_ptr(s1, NULL, 0);
1591 #if defined TCC_TARGET_MACHO
1592 /* adjust for __PAGEZERO */
1593 if (s1->dwarf == 0 && s1->output_type == TCC_OUTPUT_EXE)
1594 write64le(data_section->data + data_section->data_offset - PTR_SIZE,
1595 (uint64_t)1 << 32);
1596 #endif
1598 n = 3 * PTR_SIZE;
1599 #ifdef CONFIG_TCC_BCHECK
1600 if (s1->do_bounds_check) {
1601 put_ptr(s1, bounds_section, 0);
1602 n -= PTR_SIZE;
1604 #endif
1605 section_ptr_add(s, n);
1606 p = section_ptr_add(s, 2 * sizeof (int));
1607 p[0] = s1->rt_num_callers;
1608 p[1] = s1->dwarf;
1609 // if (s->data_offset - o != 10*PTR_SIZE + 2*sizeof (int)) exit(99);
1611 if (s1->output_type == TCC_OUTPUT_MEMORY) {
1612 set_global_sym(s1, __rt_info, s, o);
1613 return;
1616 cstr_new(&cstr);
1617 cstr_printf(&cstr,
1618 "extern void __bt_init(),__bt_exit(),__bt_init_dll();"
1619 "static void *__rt_info[];"
1620 "__attribute__((constructor)) static void __bt_init_rt(){");
1621 #ifdef TCC_TARGET_PE
1622 if (s1->output_type == TCC_OUTPUT_DLL)
1623 #ifdef CONFIG_TCC_BCHECK
1624 cstr_printf(&cstr, "__bt_init_dll(%d);", s1->do_bounds_check);
1625 #else
1626 cstr_printf(&cstr, "__bt_init_dll(0);");
1627 #endif
1628 #endif
1629 cstr_printf(&cstr, "__bt_init(__rt_info,%d);}",
1630 s1->output_type != TCC_OUTPUT_DLL);
1631 /* In case dlcose is called by application */
1632 cstr_printf(&cstr,
1633 "__attribute__((destructor)) static void __bt_exit_rt(){"
1634 "__bt_exit(__rt_info);}");
1635 tcc_compile_string_no_debug(s1, cstr.data);
1636 cstr_free(&cstr);
1637 set_local_sym(s1, __rt_info, s, o);
1639 #endif /* def CONFIG_TCC_BACKTRACE */
1641 static void tcc_tcov_add_file(TCCState *s1, const char *filename)
1643 CString cstr;
1644 void *ptr;
1645 char wd[1024];
1647 if (tcov_section == NULL)
1648 return;
1649 section_ptr_add(tcov_section, 1);
1650 write32le (tcov_section->data, tcov_section->data_offset);
1652 cstr_new (&cstr);
1653 if (filename[0] == '/')
1654 cstr_printf (&cstr, "%s.tcov", filename);
1655 else {
1656 getcwd (wd, sizeof(wd));
1657 cstr_printf (&cstr, "%s/%s.tcov", wd, filename);
1659 ptr = section_ptr_add(tcov_section, cstr.size + 1);
1660 strcpy((char *)ptr, cstr.data);
1661 unlink((char *)ptr);
1662 #ifdef _WIN32
1663 normalize_slashes((char *)ptr);
1664 #endif
1665 cstr_free (&cstr);
1667 cstr_new(&cstr);
1668 cstr_printf(&cstr,
1669 "extern char *__tcov_data[];"
1670 "extern void __store_test_coverage ();"
1671 "__attribute__((destructor)) static void __tcov_exit() {"
1672 "__store_test_coverage(__tcov_data);"
1673 "}");
1674 tcc_compile_string_no_debug(s1, cstr.data);
1675 cstr_free(&cstr);
1676 set_local_sym(s1, &"___tcov_data"[!s1->leading_underscore], tcov_section, 0);
1679 #if !defined TCC_TARGET_PE && !defined TCC_TARGET_MACHO
1680 /* add libc crt1/crti objects */
1681 ST_FUNC void tccelf_add_crtbegin(TCCState *s1)
1683 #if TARGETOS_OpenBSD
1684 if (s1->output_type != TCC_OUTPUT_DLL)
1685 tcc_add_crt(s1, "crt0.o");
1686 if (s1->output_type == TCC_OUTPUT_DLL)
1687 tcc_add_crt(s1, "crtbeginS.o");
1688 else
1689 tcc_add_crt(s1, "crtbegin.o");
1690 #elif TARGETOS_FreeBSD || TARGETOS_NetBSD
1691 if (s1->output_type != TCC_OUTPUT_DLL)
1692 #if TARGETOS_FreeBSD
1693 tcc_add_crt(s1, "crt1.o");
1694 #else
1695 tcc_add_crt(s1, "crt0.o");
1696 #endif
1697 tcc_add_crt(s1, "crti.o");
1698 if (s1->static_link)
1699 tcc_add_crt(s1, "crtbeginT.o");
1700 else if (s1->output_type == TCC_OUTPUT_DLL)
1701 tcc_add_crt(s1, "crtbeginS.o");
1702 else
1703 tcc_add_crt(s1, "crtbegin.o");
1704 #elif TARGETOS_ANDROID
1705 if (s1->output_type == TCC_OUTPUT_DLL)
1706 tcc_add_crt(s1, "crtbegin_so.o");
1707 else
1708 tcc_add_crt(s1, "crtbegin_dynamic.o");
1709 #else
1710 if (s1->output_type != TCC_OUTPUT_DLL)
1711 tcc_add_crt(s1, "crt1.o");
1712 tcc_add_crt(s1, "crti.o");
1713 #endif
1716 ST_FUNC void tccelf_add_crtend(TCCState *s1)
1718 #if TARGETOS_OpenBSD
1719 if (s1->output_type == TCC_OUTPUT_DLL)
1720 tcc_add_crt(s1, "crtendS.o");
1721 else
1722 tcc_add_crt(s1, "crtend.o");
1723 #elif TARGETOS_FreeBSD || TARGETOS_NetBSD
1724 if (s1->output_type == TCC_OUTPUT_DLL)
1725 tcc_add_crt(s1, "crtendS.o");
1726 else
1727 tcc_add_crt(s1, "crtend.o");
1728 tcc_add_crt(s1, "crtn.o");
1729 #elif TARGETOS_ANDROID
1730 if (s1->output_type == TCC_OUTPUT_DLL)
1731 tcc_add_crt(s1, "crtend_so.o");
1732 else
1733 tcc_add_crt(s1, "crtend_android.o");
1734 #else
1735 tcc_add_crt(s1, "crtn.o");
1736 #endif
1738 #endif /* !defined TCC_TARGET_PE && !defined TCC_TARGET_MACHO */
1740 #ifndef TCC_TARGET_PE
1741 /* add tcc runtime libraries */
1742 ST_FUNC void tcc_add_runtime(TCCState *s1)
1744 s1->filetype = 0;
1746 #ifdef CONFIG_TCC_BCHECK
1747 tcc_add_bcheck(s1);
1748 #endif
1749 tcc_add_pragma_libs(s1);
1751 /* add libc */
1752 if (!s1->nostdlib) {
1753 int lpthread = s1->option_pthread;
1755 #ifdef CONFIG_TCC_BCHECK
1756 if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL) {
1757 tcc_add_support(s1, "bcheck.o");
1758 # if !(TARGETOS_OpenBSD || TARGETOS_NetBSD)
1759 tcc_add_library_err(s1, "dl");
1760 # endif
1761 lpthread = 1;
1763 #endif
1764 #ifdef CONFIG_TCC_BACKTRACE
1765 if (s1->do_backtrace) {
1766 if (s1->output_type & TCC_OUTPUT_EXE)
1767 tcc_add_support(s1, "bt-exe.o");
1768 if (s1->output_type != TCC_OUTPUT_DLL)
1769 tcc_add_support(s1, "bt-log.o");
1770 tcc_add_btstub(s1);
1771 lpthread = 1;
1773 #endif
1774 if (lpthread)
1775 tcc_add_library_err(s1, "pthread");
1776 tcc_add_library_err(s1, "c");
1777 #ifdef TCC_LIBGCC
1778 if (!s1->static_link) {
1779 if (TCC_LIBGCC[0] == '/')
1780 tcc_add_file(s1, TCC_LIBGCC);
1781 else
1782 tcc_add_dll(s1, TCC_LIBGCC, AFF_PRINT_ERROR);
1784 #endif
1785 #if defined TCC_TARGET_ARM && TARGETOS_FreeBSD
1786 tcc_add_library_err(s1, "gcc_s"); // unwind code
1787 #endif
1788 if (TCC_LIBTCC1[0])
1789 tcc_add_support(s1, TCC_LIBTCC1);
1790 #ifndef TCC_TARGET_MACHO
1791 if (s1->output_type != TCC_OUTPUT_MEMORY)
1792 tccelf_add_crtend(s1);
1793 #endif
1796 #endif /* ndef TCC_TARGET_PE */
1798 /* add various standard linker symbols (must be done after the
1799 sections are filled (for example after allocating common
1800 symbols)) */
1801 static void tcc_add_linker_symbols(TCCState *s1)
1803 char buf[1024];
1804 int i;
1805 Section *s;
1807 set_global_sym(s1, "_etext", text_section, -1);
1808 set_global_sym(s1, "_edata", data_section, -1);
1809 set_global_sym(s1, "_end", bss_section, -1);
1810 #if TARGETOS_OpenBSD
1811 set_global_sym(s1, "__executable_start", NULL, ELF_START_ADDR);
1812 #endif
1813 #ifdef TCC_TARGET_RISCV64
1814 /* XXX should be .sdata+0x800, not .data+0x800 */
1815 set_global_sym(s1, "__global_pointer$", data_section, 0x800);
1816 #endif
1817 /* horrible new standard ldscript defines */
1818 add_init_array_defines(s1, ".preinit_array");
1819 add_init_array_defines(s1, ".init_array");
1820 add_init_array_defines(s1, ".fini_array");
1821 /* add start and stop symbols for sections whose name can be
1822 expressed in C */
1823 for(i = 1; i < s1->nb_sections; i++) {
1824 s = s1->sections[i];
1825 if ((s->sh_flags & SHF_ALLOC)
1826 && (s->sh_type == SHT_PROGBITS
1827 || s->sh_type == SHT_STRTAB)) {
1828 const char *p;
1829 /* check if section name can be expressed in C */
1830 p = s->name;
1831 for(;;) {
1832 int c = *p;
1833 if (!c)
1834 break;
1835 if (!isid(c) && !isnum(c))
1836 goto next_sec;
1837 p++;
1839 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1840 set_global_sym(s1, buf, s, 0);
1841 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1842 set_global_sym(s1, buf, s, -1);
1844 next_sec: ;
1848 ST_FUNC void resolve_common_syms(TCCState *s1)
1850 ElfW(Sym) *sym;
1852 /* Allocate common symbols in BSS. */
1853 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
1854 if (sym->st_shndx == SHN_COMMON) {
1855 /* symbol alignment is in st_value for SHN_COMMONs */
1856 sym->st_value = section_add(bss_section, sym->st_size,
1857 sym->st_value);
1858 sym->st_shndx = bss_section->sh_num;
1862 /* Now assign linker provided symbols their value. */
1863 tcc_add_linker_symbols(s1);
1866 #ifndef ELF_OBJ_ONLY
1867 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1869 int sym_index = ELFW(R_SYM) (rel->r_info);
1870 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1871 struct sym_attr *attr = get_sym_attr(s1, sym_index, 0);
1872 unsigned offset = attr->got_offset;
1874 if (0 == offset)
1875 return;
1876 section_reserve(s1->got, offset + PTR_SIZE);
1877 #if PTR_SIZE == 8
1878 write64le(s1->got->data + offset, sym->st_value);
1879 #else
1880 write32le(s1->got->data + offset, sym->st_value);
1881 #endif
1884 /* Perform relocation to GOT or PLT entries */
1885 ST_FUNC void fill_got(TCCState *s1)
1887 Section *s;
1888 ElfW_Rel *rel;
1889 int i;
1891 for(i = 1; i < s1->nb_sections; i++) {
1892 s = s1->sections[i];
1893 if (s->sh_type != SHT_RELX)
1894 continue;
1895 /* no need to handle got relocations */
1896 if (s->link != symtab_section)
1897 continue;
1898 for_each_elem(s, 0, rel, ElfW_Rel) {
1899 switch (ELFW(R_TYPE) (rel->r_info)) {
1900 case R_X86_64_GOT32:
1901 case R_X86_64_GOTPCREL:
1902 case R_X86_64_GOTPCRELX:
1903 case R_X86_64_REX_GOTPCRELX:
1904 case R_X86_64_PLT32:
1905 fill_got_entry(s1, rel);
1906 break;
1912 /* See put_got_entry for a description. This is the second stage
1913 where GOT references to local defined symbols are rewritten. */
1914 static void fill_local_got_entries(TCCState *s1)
1916 ElfW_Rel *rel;
1917 if (!s1->got->reloc)
1918 return;
1919 for_each_elem(s1->got->reloc, 0, rel, ElfW_Rel) {
1920 if (ELFW(R_TYPE)(rel->r_info) == R_RELATIVE) {
1921 int sym_index = ELFW(R_SYM) (rel->r_info);
1922 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1923 struct sym_attr *attr = get_sym_attr(s1, sym_index, 0);
1924 unsigned offset = attr->got_offset;
1925 if (offset != rel->r_offset - s1->got->sh_addr)
1926 tcc_error_noabort("fill_local_got_entries: huh?");
1927 rel->r_info = ELFW(R_INFO)(0, R_RELATIVE);
1928 #if SHT_RELX == SHT_RELA
1929 rel->r_addend = sym->st_value;
1930 #else
1931 /* All our REL architectures also happen to be 32bit LE. */
1932 write32le(s1->got->data + offset, sym->st_value);
1933 #endif
1938 /* Bind symbols of executable: resolve undefined symbols from exported symbols
1939 in shared libraries */
1940 static void bind_exe_dynsyms(TCCState *s1, int is_PIE)
1942 const char *name;
1943 int sym_index, index;
1944 ElfW(Sym) *sym, *esym;
1945 int type;
1947 /* Resolve undefined symbols from dynamic symbols. When there is a match:
1948 - if STT_FUNC or STT_GNU_IFUNC symbol -> add it in PLT
1949 - if STT_OBJECT symbol -> add it in .bss section with suitable reloc */
1950 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
1951 if (sym->st_shndx == SHN_UNDEF) {
1952 name = (char *) symtab_section->link->data + sym->st_name;
1953 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1954 if (sym_index) {
1955 if (is_PIE)
1956 continue;
1957 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1958 type = ELFW(ST_TYPE)(esym->st_info);
1959 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1960 /* Indirect functions shall have STT_FUNC type in executable
1961 * dynsym section. Indeed, a dlsym call following a lazy
1962 * resolution would pick the symbol value from the
1963 * executable dynsym entry which would contain the address
1964 * of the function wanted by the caller of dlsym instead of
1965 * the address of the function that would return that
1966 * address */
1967 int dynindex
1968 = put_elf_sym(s1->dynsym, 0, esym->st_size,
1969 ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC), 0, 0,
1970 name);
1971 int index = sym - (ElfW(Sym) *) symtab_section->data;
1972 get_sym_attr(s1, index, 1)->dyn_index = dynindex;
1973 } else if (type == STT_OBJECT) {
1974 unsigned long offset;
1975 ElfW(Sym) *dynsym;
1976 offset = bss_section->data_offset;
1977 /* XXX: which alignment ? */
1978 offset = (offset + 16 - 1) & -16;
1979 set_elf_sym (s1->symtab, offset, esym->st_size,
1980 esym->st_info, 0, bss_section->sh_num, name);
1981 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1982 esym->st_info, 0, bss_section->sh_num,
1983 name);
1985 /* Ensure R_COPY works for weak symbol aliases */
1986 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1987 for_each_elem(s1->dynsymtab_section, 1, dynsym, ElfW(Sym)) {
1988 if ((dynsym->st_value == esym->st_value)
1989 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1990 char *dynname = (char *) s1->dynsymtab_section->link->data
1991 + dynsym->st_name;
1992 put_elf_sym(s1->dynsym, offset, dynsym->st_size,
1993 dynsym->st_info, 0,
1994 bss_section->sh_num, dynname);
1995 break;
2000 put_elf_reloc(s1->dynsym, bss_section,
2001 offset, R_COPY, index);
2002 offset += esym->st_size;
2003 bss_section->data_offset = offset;
2005 } else {
2006 /* STB_WEAK undefined symbols are accepted */
2007 /* XXX: _fp_hw seems to be part of the ABI, so we ignore it */
2008 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
2009 !strcmp(name, "_fp_hw")) {
2010 } else {
2011 tcc_error_noabort("undefined symbol '%s'", name);
2018 /* Bind symbols of libraries: export all non local symbols of executable that
2019 are referenced by shared libraries. The reason is that the dynamic loader
2020 search symbol first in executable and then in libraries. Therefore a
2021 reference to a symbol already defined by a library can still be resolved by
2022 a symbol in the executable. With -rdynamic, export all defined symbols */
2023 static void bind_libs_dynsyms(TCCState *s1)
2025 const char *name;
2026 int dynsym_index;
2027 ElfW(Sym) *sym, *esym;
2029 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
2030 name = (char *)symtab_section->link->data + sym->st_name;
2031 dynsym_index = find_elf_sym(s1->dynsymtab_section, name);
2032 if (sym->st_shndx != SHN_UNDEF) {
2033 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL
2034 && (dynsym_index || s1->rdynamic))
2035 set_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
2036 sym->st_info, 0, sym->st_shndx, name);
2037 } else if (dynsym_index) {
2038 esym = (ElfW(Sym) *)s1->dynsymtab_section->data + dynsym_index;
2039 if (esym->st_shndx == SHN_UNDEF) {
2040 /* weak symbols can stay undefined */
2041 if (ELFW(ST_BIND)(esym->st_info) != STB_WEAK)
2042 tcc_warning("undefined dynamic symbol '%s'", name);
2048 /* Export all non local symbols. This is used by shared libraries so that the
2049 non local symbols they define can resolve a reference in another shared
2050 library or in the executable. Correspondingly, it allows undefined local
2051 symbols to be resolved by other shared libraries or by the executable. */
2052 static void export_global_syms(TCCState *s1)
2054 int dynindex, index;
2055 const char *name;
2056 ElfW(Sym) *sym;
2057 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
2058 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2059 name = (char *) symtab_section->link->data + sym->st_name;
2060 dynindex = set_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
2061 sym->st_info, 0, sym->st_shndx, name);
2062 index = sym - (ElfW(Sym) *) symtab_section->data;
2063 get_sym_attr(s1, index, 1)->dyn_index = dynindex;
2068 /* decide if an unallocated section should be output. */
2069 static int set_sec_sizes(TCCState *s1)
2071 int i;
2072 Section *s;
2073 int textrel = 0;
2074 int file_type = s1->output_type;
2076 /* Allocate strings for section names */
2077 for(i = 1; i < s1->nb_sections; i++) {
2078 s = s1->sections[i];
2079 if (s->sh_type == SHT_RELX && !(s->sh_flags & SHF_ALLOC)) {
2080 /* when generating a DLL, we include relocations but
2081 we may patch them */
2082 if ((file_type & TCC_OUTPUT_DYN)
2083 && (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)) {
2084 int count = prepare_dynamic_rel(s1, s);
2085 if (count) {
2086 /* allocate the section */
2087 s->sh_flags |= SHF_ALLOC;
2088 s->sh_size = count * sizeof(ElfW_Rel);
2089 if (!(s1->sections[s->sh_info]->sh_flags & SHF_WRITE))
2090 textrel += count;
2093 } else if ((s->sh_flags & SHF_ALLOC)
2094 #ifdef TCC_TARGET_ARM
2095 || s->sh_type == SHT_ARM_ATTRIBUTES
2096 #endif
2097 || s1->do_debug) {
2098 s->sh_size = s->data_offset;
2101 #ifdef TCC_TARGET_ARM
2102 /* XXX: Suppress stack unwinding section. */
2103 if (s->sh_type == SHT_ARM_EXIDX) {
2104 s->sh_flags = 0;
2105 s->sh_size = 0;
2107 #endif
2110 return textrel;
2113 /* various data used under elf_output_file() */
2114 struct dyn_inf {
2115 Section *dynamic;
2116 Section *dynstr;
2117 struct {
2118 /* Info to be copied in dynamic section */
2119 unsigned long data_offset;
2120 addr_t rel_addr;
2121 addr_t rel_size;
2124 ElfW(Phdr) *phdr;
2125 int phnum;
2126 Section *interp;
2127 Section *note;
2128 Section *gnu_hash;
2130 /* read only segment mapping for GNU_RELRO */
2131 Section _roinf, *roinf;
2134 /* Decide the layout of sections loaded in memory. This must be done before
2135 program headers are filled since they contain info about the layout.
2136 We do the following ordering: interp, symbol tables, relocations, progbits,
2137 nobits */
2138 static int sort_sections(TCCState *s1, int *sec_order, Section *interp)
2140 Section *s;
2141 int i, j, k, f, f0, n;
2142 int nb_sections = s1->nb_sections;
2143 int *sec_cls = sec_order + nb_sections;
2145 for (i = 1; i < nb_sections; i++) {
2146 s = s1->sections[i];
2147 if (s->sh_flags & SHF_ALLOC) {
2148 j = 0x100;
2149 if (s->sh_flags & SHF_WRITE)
2150 j = 0x200;
2151 if (s->sh_flags & SHF_TLS)
2152 j += 0x200;
2153 } else if (s->sh_name) {
2154 j = 0x700;
2155 } else {
2156 j = 0x900; /* no sh_name: won't go to file */
2158 if (s->sh_type == SHT_SYMTAB || s->sh_type == SHT_DYNSYM) {
2159 k = 0x10;
2160 } else if (s->sh_type == SHT_STRTAB && strcmp(s->name, ".stabstr")) {
2161 k = 0x11;
2162 if (i == nb_sections - 1) /* ".shstrtab" assumed to remain last */
2163 k = 0xff;
2164 } else if (s->sh_type == SHT_HASH || s->sh_type == SHT_GNU_HASH) {
2165 k = 0x12;
2166 } else if (s->sh_type == SHT_RELX) {
2167 k = 0x20;
2168 if (s1->plt && s == s1->plt->reloc)
2169 k = 0x21;
2170 } else if (s->sh_type == SHT_PREINIT_ARRAY) {
2171 k = 0x41;
2172 } else if (s->sh_type == SHT_INIT_ARRAY) {
2173 k = 0x42;
2174 } else if (s->sh_type == SHT_FINI_ARRAY) {
2175 k = 0x43;
2176 #ifdef CONFIG_TCC_BCHECK
2177 } else if (s == bounds_section || s == lbounds_section) {
2178 k = 0x44;
2179 #endif
2180 } else if (s == rodata_section || 0 == strcmp(s->name, ".data.rel.ro")) {
2181 k = 0x45;
2182 } else if (s->sh_type == SHT_DYNAMIC) {
2183 k = 0x46;
2184 } else if (s == s1->got) {
2185 k = 0x47; /* .got as RELRO needs BIND_NOW in DT_FLAGS */
2186 } else {
2187 k = 0x50;
2188 if (s->sh_type == SHT_NOTE)
2189 k = 0x60;
2190 if (s->sh_flags & SHF_EXECINSTR)
2191 k = 0x70;
2192 if (s->sh_type == SHT_NOBITS)
2193 k = 0x80;
2194 if (s == interp)
2195 k = 0x00;
2197 k += j;
2199 for (n = i; n > 1 && k < (f = sec_cls[n - 1]); --n)
2200 sec_cls[n] = f, sec_order[n] = sec_order[n - 1];
2201 sec_cls[n] = k, sec_order[n] = i;
2203 sec_order[0] = 0;
2205 /* count PT_LOAD headers needed */
2206 n = f0 = 0;
2207 for (i = 1; i < nb_sections; i++) {
2208 s = s1->sections[sec_order[i]];
2209 k = sec_cls[i];
2210 f = 0;
2211 if (k < 0x700) {
2212 f = s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR|SHF_TLS);
2213 #if TARGETOS_NetBSD
2214 /* NetBSD only supports 2 PT_LOAD sections.
2215 See: https://blog.netbsd.org/tnf/entry/the_first_report_on_lld */
2216 if ((f & SHF_WRITE) == 0) f |= SHF_EXECINSTR;
2217 #else
2218 if ((k & 0xfff0) == 0x240) /* RELRO sections */
2219 f |= 1<<4;
2220 #endif
2221 if (f != f0) /* start new header when flags changed or relro */
2222 f0 = f, ++n, f |= 1<<8;
2224 sec_cls[i] = f;
2225 //printf("ph %d sec %02d : %3X %3X %8.2X %04X %s\n", !!f * n, i, f, k, s->sh_type, s->sh_size, s->name);
2227 return n;
2230 static ElfW(Phdr) *fill_phdr(ElfW(Phdr) *ph, int type, Section *s)
2232 if (s) {
2233 ph->p_offset = s->sh_offset;
2234 ph->p_vaddr = s->sh_addr;
2235 ph->p_filesz = s->sh_size;
2236 ph->p_align = s->sh_addralign;
2238 ph->p_type = type;
2239 ph->p_flags = PF_R;
2240 ph->p_paddr = ph->p_vaddr;
2241 ph->p_memsz = ph->p_filesz;
2242 return ph;
2245 /* Assign sections to segments and decide how are sections laid out when loaded
2246 in memory. This function also fills corresponding program headers. */
2247 static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
2249 Section *s;
2250 addr_t addr, tmp, align, s_align, base;
2251 ElfW(Phdr) *ph = NULL;
2252 int i, f, n, phnum, phfill;
2253 int file_offset;
2255 /* compute number of program headers */
2256 phnum = sort_sections(s1, sec_order, d->interp);
2257 phfill = 0; /* set to 1 to have dll's with a PT_PHDR */
2258 if (d->interp)
2259 phfill = 2;
2260 phnum += phfill;
2261 if (d->note)
2262 ++phnum;
2263 if (d->dynamic)
2264 ++phnum;
2265 if (d->roinf)
2266 ++phnum;
2267 d->phnum = phnum;
2268 d->phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
2270 file_offset = 0;
2271 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
2272 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2274 s_align = ELF_PAGE_SIZE;
2275 if (s1->section_align)
2276 s_align = s1->section_align;
2278 addr = ELF_START_ADDR;
2279 if (s1->output_type & TCC_OUTPUT_DYN)
2280 addr = 0;
2282 if (s1->has_text_addr) {
2283 addr = s1->text_addr;
2284 if (0) {
2285 int a_offset, p_offset;
2286 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
2287 ELF_PAGE_SIZE */
2288 a_offset = (int) (addr & (s_align - 1));
2289 p_offset = file_offset & (s_align - 1);
2290 if (a_offset < p_offset)
2291 a_offset += s_align;
2292 file_offset += (a_offset - p_offset);
2295 base = addr;
2296 /* compute address after headers */
2297 addr = addr + (file_offset & (s_align - 1));
2299 n = 0;
2300 for(i = 1; i < s1->nb_sections; i++) {
2301 s = s1->sections[sec_order[i]];
2302 f = sec_order[i + s1->nb_sections];
2303 align = s->sh_addralign - 1;
2305 if (f == 0) { /* no alloc */
2306 file_offset = (file_offset + align) & ~align;
2307 s->sh_offset = file_offset;
2308 if (s->sh_type != SHT_NOBITS)
2309 file_offset += s->sh_size;
2310 continue;
2313 if ((f & 1<<8) && n) {
2314 /* different rwx section flags */
2315 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2316 /* if in the middle of a page, w e duplicate the page in
2317 memory so that one copy is RX and the other is RW */
2318 if ((addr & (s_align - 1)) != 0)
2319 addr += s_align;
2320 } else {
2321 align = s_align - 1;
2325 tmp = addr;
2326 addr = (addr + align) & ~align;
2327 file_offset += (int)(addr - tmp);
2328 s->sh_offset = file_offset;
2329 s->sh_addr = addr;
2331 if (f & 1<<8) {
2332 /* set new program header */
2333 ph = &d->phdr[phfill + n];
2334 ph->p_type = PT_LOAD;
2335 ph->p_align = s_align;
2336 ph->p_flags = PF_R;
2337 if (f & SHF_WRITE)
2338 ph->p_flags |= PF_W;
2339 if (f & SHF_EXECINSTR)
2340 ph->p_flags |= PF_X;
2341 if (f & SHF_TLS) {
2342 ph->p_type = PT_TLS;
2343 ph->p_align = align + 1;
2346 ph->p_offset = file_offset;
2347 ph->p_vaddr = addr;
2348 if (n == 0) {
2349 /* Make the first PT_LOAD segment include the program
2350 headers itself (and the ELF header as well), it'll
2351 come out with same memory use but will make various
2352 tools like binutils strip work better. */
2353 ph->p_offset = 0;
2354 ph->p_vaddr = base;
2356 ph->p_paddr = ph->p_vaddr;
2357 ++n;
2360 if (f & 1<<4) {
2361 Section *roinf = &d->_roinf;
2362 if (roinf->sh_size == 0) {
2363 roinf->sh_offset = s->sh_offset;
2364 roinf->sh_addr = s->sh_addr;
2365 roinf->sh_addralign = 1;
2367 roinf->sh_size = (addr - roinf->sh_addr) + s->sh_size;
2370 addr += s->sh_size;
2371 if (s->sh_type != SHT_NOBITS)
2372 file_offset += s->sh_size;
2374 ph->p_filesz = file_offset - ph->p_offset;
2375 ph->p_memsz = addr - ph->p_vaddr;
2378 /* Fill other headers */
2379 if (d->note)
2380 fill_phdr(++ph, PT_NOTE, d->note);
2381 if (d->dynamic)
2382 fill_phdr(++ph, PT_DYNAMIC, d->dynamic)->p_flags |= PF_W;
2383 if (d->roinf)
2384 fill_phdr(++ph, PT_GNU_RELRO, d->roinf)->p_flags |= PF_W;
2385 if (d->interp)
2386 fill_phdr(&d->phdr[1], PT_INTERP, d->interp);
2387 if (phfill) {
2388 ph = &d->phdr[0];
2389 ph->p_offset = sizeof(ElfW(Ehdr));
2390 ph->p_vaddr = base + ph->p_offset;
2391 ph->p_filesz = phnum * sizeof(ElfW(Phdr));
2392 ph->p_align = 4;
2393 fill_phdr(ph, PT_PHDR, NULL);
2395 return file_offset;
2398 /* put dynamic tag */
2399 static void put_dt(Section *dynamic, int dt, addr_t val)
2401 ElfW(Dyn) *dyn;
2402 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
2403 dyn->d_tag = dt;
2404 dyn->d_un.d_val = val;
2407 /* Fill the dynamic section with tags describing the address and size of
2408 sections */
2409 static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
2411 Section *dynamic = dyninf->dynamic;
2412 Section *s;
2414 /* put dynamic section entries */
2415 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
2416 put_dt(dynamic, DT_GNU_HASH, dyninf->gnu_hash->sh_addr);
2417 put_dt(dynamic, DT_STRTAB, dyninf->dynstr->sh_addr);
2418 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2419 put_dt(dynamic, DT_STRSZ, dyninf->dynstr->data_offset);
2420 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2421 #if PTR_SIZE == 8
2422 put_dt(dynamic, DT_RELA, dyninf->rel_addr);
2423 put_dt(dynamic, DT_RELASZ, dyninf->rel_size);
2424 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2425 if (s1->plt && s1->plt->reloc) {
2426 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2427 put_dt(dynamic, DT_PLTRELSZ, s1->plt->reloc->data_offset);
2428 put_dt(dynamic, DT_JMPREL, s1->plt->reloc->sh_addr);
2429 put_dt(dynamic, DT_PLTREL, DT_RELA);
2431 put_dt(dynamic, DT_RELACOUNT, 0);
2432 #else
2433 put_dt(dynamic, DT_REL, dyninf->rel_addr);
2434 put_dt(dynamic, DT_RELSZ, dyninf->rel_size);
2435 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2436 if (s1->plt && s1->plt->reloc) {
2437 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2438 put_dt(dynamic, DT_PLTRELSZ, s1->plt->reloc->data_offset);
2439 put_dt(dynamic, DT_JMPREL, s1->plt->reloc->sh_addr);
2440 put_dt(dynamic, DT_PLTREL, DT_REL);
2442 put_dt(dynamic, DT_RELCOUNT, 0);
2443 #endif
2444 if (versym_section && verneed_section) {
2445 /* The dynamic linker can not handle VERSYM without VERNEED */
2446 put_dt(dynamic, DT_VERSYM, versym_section->sh_addr);
2447 put_dt(dynamic, DT_VERNEED, verneed_section->sh_addr);
2448 put_dt(dynamic, DT_VERNEEDNUM, dt_verneednum);
2450 s = have_section(s1, ".preinit_array");
2451 if (s && s->data_offset) {
2452 put_dt(dynamic, DT_PREINIT_ARRAY, s->sh_addr);
2453 put_dt(dynamic, DT_PREINIT_ARRAYSZ, s->data_offset);
2455 s = have_section(s1, ".init_array");
2456 if (s && s->data_offset) {
2457 put_dt(dynamic, DT_INIT_ARRAY, s->sh_addr);
2458 put_dt(dynamic, DT_INIT_ARRAYSZ, s->data_offset);
2460 s = have_section(s1, ".fini_array");
2461 if (s && s->data_offset) {
2462 put_dt(dynamic, DT_FINI_ARRAY, s->sh_addr);
2463 put_dt(dynamic, DT_FINI_ARRAYSZ, s->data_offset);
2465 s = have_section(s1, ".init");
2466 if (s && s->data_offset) {
2467 put_dt(dynamic, DT_INIT, s->sh_addr);
2469 s = have_section(s1, ".fini");
2470 if (s && s->data_offset) {
2471 put_dt(dynamic, DT_FINI, s->sh_addr);
2473 if (s1->do_debug)
2474 put_dt(dynamic, DT_DEBUG, 0);
2475 put_dt(dynamic, DT_NULL, 0);
2478 /* Remove gaps between RELX sections.
2479 These gaps are a result of final_sections_reloc. Here some relocs are removed.
2480 The gaps are then filled with 0 in tcc_output_elf. The 0 is intepreted as
2481 R_...NONE reloc. This does work on most targets but on OpenBSD/arm64 this
2482 is illegal. OpenBSD/arm64 does not support R_...NONE reloc. */
2483 static void update_reloc_sections(TCCState *s1, struct dyn_inf *dyninf)
2485 int i;
2486 unsigned long file_offset = 0;
2487 Section *s;
2488 Section *relocplt = s1->plt ? s1->plt->reloc : NULL;
2490 /* dynamic relocation table information, for .dynamic section */
2491 dyninf->rel_addr = dyninf->rel_size = 0;
2493 for(i = 1; i < s1->nb_sections; i++) {
2494 s = s1->sections[i];
2495 if (s->sh_type == SHT_RELX && s != relocplt) {
2496 if (dyninf->rel_size == 0) {
2497 dyninf->rel_addr = s->sh_addr;
2498 file_offset = s->sh_offset;
2500 else {
2501 s->sh_addr = dyninf->rel_addr + dyninf->rel_size;
2502 s->sh_offset = file_offset + dyninf->rel_size;
2504 dyninf->rel_size += s->sh_size;
2509 static int tidy_section_headers(TCCState *s1, int *sec_order);
2510 #endif /* ndef ELF_OBJ_ONLY */
2512 /* Create an ELF file on disk.
2513 This function handle ELF specific layout requirements */
2514 static int tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
2515 int file_offset, int *sec_order)
2517 int i, shnum, offset, size, file_type;
2518 Section *s;
2519 ElfW(Ehdr) ehdr;
2520 ElfW(Shdr) shdr, *sh;
2522 file_type = s1->output_type;
2523 shnum = s1->nb_sections;
2525 memset(&ehdr, 0, sizeof(ehdr));
2527 if (phnum > 0) {
2528 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2529 ehdr.e_phnum = phnum;
2530 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2531 #ifndef ELF_OBJ_ONLY
2532 shnum = tidy_section_headers(s1, sec_order);
2533 #endif
2536 /* align to 4 */
2537 file_offset = (file_offset + 3) & -4;
2539 /* fill header */
2540 ehdr.e_ident[0] = ELFMAG0;
2541 ehdr.e_ident[1] = ELFMAG1;
2542 ehdr.e_ident[2] = ELFMAG2;
2543 ehdr.e_ident[3] = ELFMAG3;
2544 ehdr.e_ident[4] = ELFCLASSW;
2545 ehdr.e_ident[5] = ELFDATA2LSB;
2546 ehdr.e_ident[6] = EV_CURRENT;
2548 #if TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel
2549 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2550 #elif defined TCC_TARGET_ARM && defined TCC_ARM_EABI
2551 ehdr.e_flags = EF_ARM_EABI_VER5;
2552 ehdr.e_flags |= s1->float_abi == ARM_HARD_FLOAT
2553 ? EF_ARM_VFP_FLOAT : EF_ARM_SOFT_FLOAT;
2554 #elif defined TCC_TARGET_ARM
2555 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2556 #elif defined TCC_TARGET_RISCV64
2557 /* XXX should be configurable */
2558 ehdr.e_flags = EF_RISCV_FLOAT_ABI_DOUBLE;
2559 #endif
2561 if (file_type == TCC_OUTPUT_OBJ) {
2562 ehdr.e_type = ET_REL;
2563 } else {
2564 if (file_type & TCC_OUTPUT_DYN)
2565 ehdr.e_type = ET_DYN;
2566 else
2567 ehdr.e_type = ET_EXEC;
2568 if (s1->elf_entryname)
2569 ehdr.e_entry = get_sym_addr(s1, s1->elf_entryname, 1, 0);
2570 else
2571 ehdr.e_entry = get_sym_addr(s1, "_start", !!(file_type & TCC_OUTPUT_EXE), 0);
2572 if (ehdr.e_entry == (addr_t)-1)
2573 ehdr.e_entry = text_section->sh_addr;
2574 if (s1->nb_errors)
2575 return -1;
2578 ehdr.e_machine = EM_TCC_TARGET;
2579 ehdr.e_version = EV_CURRENT;
2580 ehdr.e_shoff = file_offset;
2581 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2582 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2583 ehdr.e_shnum = shnum;
2584 ehdr.e_shstrndx = shnum - 1;
2586 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2587 if (phdr)
2588 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2589 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2591 sort_syms(s1, symtab_section);
2593 for(i = 1; i < shnum; i++) {
2594 s = s1->sections[sec_order ? sec_order[i] : i];
2595 if (s->sh_type != SHT_NOBITS) {
2596 while (offset < s->sh_offset) {
2597 fputc(0, f);
2598 offset++;
2600 size = s->sh_size;
2601 if (size)
2602 fwrite(s->data, 1, size, f);
2603 offset += size;
2607 /* output section headers */
2608 while (offset < ehdr.e_shoff) {
2609 fputc(0, f);
2610 offset++;
2613 for(i = 0; i < shnum; i++) {
2614 sh = &shdr;
2615 memset(sh, 0, sizeof(ElfW(Shdr)));
2616 s = s1->sections[i];
2617 if (s) {
2618 sh->sh_name = s->sh_name;
2619 sh->sh_type = s->sh_type;
2620 sh->sh_flags = s->sh_flags;
2621 sh->sh_entsize = s->sh_entsize;
2622 sh->sh_info = s->sh_info;
2623 if (s->link)
2624 sh->sh_link = s->link->sh_num;
2625 sh->sh_addralign = s->sh_addralign;
2626 sh->sh_addr = s->sh_addr;
2627 sh->sh_offset = s->sh_offset;
2628 sh->sh_size = s->sh_size;
2630 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2632 return 0;
2635 static int tcc_output_binary(TCCState *s1, FILE *f,
2636 const int *sec_order)
2638 Section *s;
2639 int i, offset, size;
2641 offset = 0;
2642 for(i=1;i<s1->nb_sections;i++) {
2643 s = s1->sections[sec_order[i]];
2644 if (s->sh_type != SHT_NOBITS &&
2645 (s->sh_flags & SHF_ALLOC)) {
2646 while (offset < s->sh_offset) {
2647 fputc(0, f);
2648 offset++;
2650 size = s->sh_size;
2651 fwrite(s->data, 1, size, f);
2652 offset += size;
2655 return 0;
2658 /* Write an elf, coff or "binary" file */
2659 static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum,
2660 ElfW(Phdr) *phdr, int file_offset, int *sec_order)
2662 int fd, mode, file_type, ret;
2663 FILE *f;
2665 file_type = s1->output_type;
2666 if (file_type == TCC_OUTPUT_OBJ)
2667 mode = 0666;
2668 else
2669 mode = 0777;
2670 unlink(filename);
2671 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2672 if (fd < 0 || (f = fdopen(fd, "wb")) == NULL)
2673 return tcc_error_noabort("could not write '%s: %s'", filename, strerror(errno));
2674 if (s1->verbose)
2675 printf("<- %s\n", filename);
2676 #ifdef TCC_TARGET_COFF
2677 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF)
2678 tcc_output_coff(s1, f);
2679 else
2680 #endif
2681 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
2682 ret = tcc_output_elf(s1, f, phnum, phdr, file_offset, sec_order);
2683 else
2684 ret = tcc_output_binary(s1, f, sec_order);
2685 fclose(f);
2687 return ret;
2690 #ifndef ELF_OBJ_ONLY
2691 /* Sort section headers by assigned sh_addr, remove sections
2692 that we aren't going to output. */
2693 static int tidy_section_headers(TCCState *s1, int *sec_order)
2695 int i, nnew, l, *backmap;
2696 Section **snew, *s;
2697 ElfW(Sym) *sym;
2699 snew = tcc_malloc(s1->nb_sections * sizeof(snew[0]));
2700 backmap = tcc_malloc(s1->nb_sections * sizeof(backmap[0]));
2701 for (i = 0, nnew = 0, l = s1->nb_sections; i < s1->nb_sections; i++) {
2702 s = s1->sections[sec_order[i]];
2703 if (!i || s->sh_name) {
2704 backmap[sec_order[i]] = nnew;
2705 snew[nnew] = s;
2706 ++nnew;
2707 } else {
2708 backmap[sec_order[i]] = 0;
2709 snew[--l] = s;
2712 for (i = 0; i < nnew; i++) {
2713 s = snew[i];
2714 if (s) {
2715 s->sh_num = i;
2716 if (s->sh_type == SHT_RELX)
2717 s->sh_info = backmap[s->sh_info];
2721 for_each_elem(symtab_section, 1, sym, ElfW(Sym))
2722 if (sym->st_shndx != SHN_UNDEF && sym->st_shndx < SHN_LORESERVE)
2723 sym->st_shndx = backmap[sym->st_shndx];
2724 if ( !s1->static_link ) {
2725 for_each_elem(s1->dynsym, 1, sym, ElfW(Sym))
2726 if (sym->st_shndx != SHN_UNDEF && sym->st_shndx < SHN_LORESERVE)
2727 sym->st_shndx = backmap[sym->st_shndx];
2729 for (i = 0; i < s1->nb_sections; i++)
2730 sec_order[i] = i;
2731 tcc_free(s1->sections);
2732 s1->sections = snew;
2733 tcc_free(backmap);
2734 return nnew;
2737 #ifdef TCC_TARGET_ARM
2738 static void create_arm_attribute_section(TCCState *s1)
2740 // Needed for DLL support.
2741 static const unsigned char arm_attr[] = {
2742 0x41, // 'A'
2743 0x2c, 0x00, 0x00, 0x00, // size 0x2c
2744 'a', 'e', 'a', 'b', 'i', 0x00, // "aeabi"
2745 0x01, 0x22, 0x00, 0x00, 0x00, // 'File Attributes', size 0x22
2746 0x05, 0x36, 0x00, // 'CPU_name', "6"
2747 0x06, 0x06, // 'CPU_arch', 'v6'
2748 0x08, 0x01, // 'ARM_ISA_use', 'Yes'
2749 0x09, 0x01, // 'THUMB_ISA_use', 'Thumb-1'
2750 0x0a, 0x02, // 'FP_arch', 'VFPv2'
2751 0x12, 0x04, // 'ABI_PCS_wchar_t', 4
2752 0x14, 0x01, // 'ABI_FP_denormal', 'Needed'
2753 0x15, 0x01, // 'ABI_FP_exceptions', 'Needed'
2754 0x17, 0x03, // 'ABI_FP_number_model', 'IEEE 754'
2755 0x18, 0x01, // 'ABI_align_needed', '8-byte'
2756 0x19, 0x01, // 'ABI_align_preserved', '8-byte, except leaf SP'
2757 0x1a, 0x02, // 'ABI_enum_size', 'int'
2758 0x1c, 0x01, // 'ABI_VFP_args', 'VFP registers'
2759 0x22, 0x01 // 'CPU_unaligned_access', 'v6'
2761 Section *attr = new_section(s1, ".ARM.attributes", SHT_ARM_ATTRIBUTES, 0);
2762 unsigned char *ptr = section_ptr_add(attr, sizeof(arm_attr));
2763 attr->sh_addralign = 1;
2764 memcpy(ptr, arm_attr, sizeof(arm_attr));
2765 if (s1->float_abi != ARM_HARD_FLOAT) {
2766 ptr[26] = 0x00; // 'FP_arch', 'No'
2767 ptr[41] = 0x1e; // 'ABI_optimization_goals'
2768 ptr[42] = 0x06; // 'Aggressive Debug'
2771 #endif
2773 #if TARGETOS_OpenBSD || TARGETOS_NetBSD
2774 static Section *create_bsd_note_section(TCCState *s1,
2775 const char *name,
2776 const char *value)
2778 Section *s = find_section (s1, name);
2780 if (s->data_offset == 0) {
2781 char *ptr = section_ptr_add(s, sizeof(ElfW(Nhdr)) + 8 + 4);
2782 ElfW(Nhdr) *note = (ElfW(Nhdr) *) ptr;
2784 s->sh_type = SHT_NOTE;
2785 note->n_namesz = 8;
2786 note->n_descsz = 4;
2787 note->n_type = ELF_NOTE_OS_GNU;
2788 strcpy (ptr + sizeof(ElfW(Nhdr)), value);
2790 return s;
2792 #endif
2794 static void alloc_sec_names(TCCState *s1, int is_obj);
2796 /* Output an elf, coff or binary file */
2797 /* XXX: suppress unneeded sections */
2798 static int elf_output_file(TCCState *s1, const char *filename)
2800 int i, ret, file_type, file_offset, *sec_order;
2801 struct dyn_inf dyninf = {0};
2802 Section *interp, *dynstr, *dynamic;
2803 int textrel, got_sym, dt_flags_1;
2805 file_type = s1->output_type;
2806 s1->nb_errors = 0;
2807 ret = -1;
2808 interp = dynstr = dynamic = NULL;
2809 sec_order = NULL;
2810 dyninf.roinf = &dyninf._roinf;
2812 #ifdef TCC_TARGET_ARM
2813 create_arm_attribute_section (s1);
2814 #endif
2816 #if TARGETOS_OpenBSD
2817 dyninf.note = create_bsd_note_section (s1, ".note.openbsd.ident", "OpenBSD");
2818 #endif
2820 #if TARGETOS_NetBSD
2821 dyninf.note = create_bsd_note_section (s1, ".note.netbsd.ident", "NetBSD");
2822 #endif
2824 #if TARGETOS_FreeBSD || TARGETOS_NetBSD
2825 dyninf.roinf = NULL;
2826 #endif
2827 /* if linking, also link in runtime libraries (libc, libgcc, etc.) */
2828 tcc_add_runtime(s1);
2829 resolve_common_syms(s1);
2831 if (!s1->static_link) {
2832 if (file_type & TCC_OUTPUT_EXE) {
2833 char *ptr;
2834 /* allow override the dynamic loader */
2835 const char *elfint = getenv("LD_SO");
2836 if (elfint == NULL)
2837 elfint = DEFAULT_ELFINTERP(s1);
2838 /* add interpreter section only if executable */
2839 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
2840 interp->sh_addralign = 1;
2841 ptr = section_ptr_add(interp, 1 + strlen(elfint));
2842 strcpy(ptr, elfint);
2843 dyninf.interp = interp;
2846 /* add dynamic symbol table */
2847 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
2848 ".dynstr",
2849 ".hash", SHF_ALLOC);
2850 /* Number of local symbols (readelf complains if not set) */
2851 s1->dynsym->sh_info = 1;
2852 dynstr = s1->dynsym->link;
2853 /* add dynamic section */
2854 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
2855 SHF_ALLOC | SHF_WRITE);
2856 dynamic->link = dynstr;
2857 dynamic->sh_entsize = sizeof(ElfW(Dyn));
2859 got_sym = build_got(s1);
2860 if (file_type & TCC_OUTPUT_EXE) {
2861 bind_exe_dynsyms(s1, file_type & TCC_OUTPUT_DYN);
2862 if (s1->nb_errors)
2863 goto the_end;
2865 build_got_entries(s1, got_sym);
2866 if (file_type & TCC_OUTPUT_EXE) {
2867 bind_libs_dynsyms(s1);
2868 } else {
2869 /* shared library case: simply export all global symbols */
2870 export_global_syms(s1);
2872 dyninf.gnu_hash = create_gnu_hash(s1);
2873 } else {
2874 build_got_entries(s1, 0);
2876 version_add (s1);
2878 textrel = set_sec_sizes(s1);
2879 alloc_sec_names(s1, 0);
2881 if (!s1->static_link) {
2882 /* add a list of needed dlls */
2883 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2884 DLLReference *dllref = s1->loaded_dlls[i];
2885 if (dllref->level == 0)
2886 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
2889 if (s1->rpath)
2890 put_dt(dynamic, s1->enable_new_dtags ? DT_RUNPATH : DT_RPATH,
2891 put_elf_str(dynstr, s1->rpath));
2893 dt_flags_1 = DF_1_NOW;
2894 if (file_type & TCC_OUTPUT_DYN) {
2895 if (s1->soname)
2896 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
2897 /* XXX: currently, since we do not handle PIC code, we
2898 must relocate the readonly segments */
2899 if (textrel)
2900 put_dt(dynamic, DT_TEXTREL, 0);
2901 if (file_type & TCC_OUTPUT_EXE)
2902 dt_flags_1 = DF_1_NOW | DF_1_PIE;
2904 put_dt(dynamic, DT_FLAGS, DF_BIND_NOW);
2905 put_dt(dynamic, DT_FLAGS_1, dt_flags_1);
2906 if (s1->symbolic)
2907 put_dt(dynamic, DT_SYMBOLIC, 0);
2909 dyninf.dynamic = dynamic;
2910 dyninf.dynstr = dynstr;
2911 /* remember offset and reserve space for 2nd call below */
2912 dyninf.data_offset = dynamic->data_offset;
2913 fill_dynamic(s1, &dyninf);
2914 dynamic->sh_size = dynamic->data_offset;
2915 dynstr->sh_size = dynstr->data_offset;
2918 /* this array is used to reorder sections in the output file */
2919 sec_order = tcc_malloc(sizeof(int) * 2 * s1->nb_sections);
2920 /* compute section to program header mapping */
2921 file_offset = layout_sections(s1, sec_order, &dyninf);
2923 if (dynamic) {
2924 /* put in GOT the dynamic section address and relocate PLT */
2925 write32le(s1->got->data, dynamic->sh_addr);
2926 if (file_type == TCC_OUTPUT_EXE
2927 || (RELOCATE_DLLPLT && (file_type & TCC_OUTPUT_DYN)))
2928 relocate_plt(s1);
2929 /* relocate symbols in .dynsym now that final addresses are known */
2930 relocate_syms(s1, s1->dynsym, 2);
2933 /* if building executable or DLL, then relocate each section
2934 except the GOT which is already relocated */
2935 relocate_syms(s1, s1->symtab, 0);
2936 if (s1->nb_errors != 0)
2937 goto the_end;
2938 relocate_sections(s1);
2939 if (dynamic) {
2940 update_reloc_sections (s1, &dyninf);
2941 dynamic->data_offset = dyninf.data_offset;
2942 fill_dynamic(s1, &dyninf);
2944 /* Perform relocation to GOT or PLT entries */
2945 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2946 fill_got(s1);
2947 else if (s1->got)
2948 fill_local_got_entries(s1);
2950 if (dyninf.gnu_hash)
2951 update_gnu_hash(s1, dyninf.gnu_hash);
2953 /* Create the ELF file with name 'filename' */
2954 ret = tcc_write_elf_file(s1, filename, dyninf.phnum, dyninf.phdr, file_offset, sec_order);
2955 the_end:
2956 tcc_free(sec_order);
2957 tcc_free(dyninf.phdr);
2958 return ret;
2960 #endif /* ndef ELF_OBJ_ONLY */
2962 /* Allocate strings for section names */
2963 static void alloc_sec_names(TCCState *s1, int is_obj)
2965 int i;
2966 Section *s, *strsec;
2968 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
2969 put_elf_str(strsec, "");
2970 for(i = 1; i < s1->nb_sections; i++) {
2971 s = s1->sections[i];
2972 if (is_obj)
2973 s->sh_size = s->data_offset;
2974 if (s == strsec || s->sh_size || (s->sh_flags & SHF_ALLOC))
2975 s->sh_name = put_elf_str(strsec, s->name);
2977 strsec->sh_size = strsec->data_offset;
2980 /* Output an elf .o file */
2981 static int elf_output_obj(TCCState *s1, const char *filename)
2983 Section *s;
2984 int i, ret, file_offset;
2985 s1->nb_errors = 0;
2986 /* Allocate strings for section names */
2987 alloc_sec_names(s1, 1);
2988 file_offset = sizeof (ElfW(Ehdr));
2989 for(i = 1; i < s1->nb_sections; i++) {
2990 s = s1->sections[i];
2991 file_offset = (file_offset + 15) & -16;
2992 s->sh_offset = file_offset;
2993 if (s->sh_type != SHT_NOBITS)
2994 file_offset += s->sh_size;
2996 /* Create the ELF file with name 'filename' */
2997 ret = tcc_write_elf_file(s1, filename, 0, NULL, file_offset, NULL);
2998 return ret;
3001 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
3003 if (s->test_coverage)
3004 tcc_tcov_add_file(s, filename);
3005 if (s->output_type == TCC_OUTPUT_OBJ)
3006 return elf_output_obj(s, filename);
3007 #ifdef TCC_TARGET_PE
3008 return pe_output_file(s, filename);
3009 #elif TCC_TARGET_MACHO
3010 return macho_output_file(s, filename);
3011 #else
3012 return elf_output_file(s, filename);
3013 #endif
3016 ST_FUNC ssize_t full_read(int fd, void *buf, size_t count) {
3017 char *cbuf = buf;
3018 size_t rnum = 0;
3019 while (1) {
3020 ssize_t num = read(fd, cbuf, count-rnum);
3021 if (num < 0) return num;
3022 if (num == 0) return rnum;
3023 rnum += num;
3024 cbuf += num;
3028 ST_FUNC void *load_data(int fd, unsigned long file_offset, unsigned long size)
3030 void *data;
3032 data = tcc_malloc(size);
3033 lseek(fd, file_offset, SEEK_SET);
3034 full_read(fd, data, size);
3035 return data;
3038 typedef struct SectionMergeInfo {
3039 Section *s; /* corresponding existing section */
3040 unsigned long offset; /* offset of the new section in the existing section */
3041 uint8_t new_section; /* true if section 's' was added */
3042 uint8_t link_once; /* true if link once section */
3043 } SectionMergeInfo;
3045 ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h)
3047 int size = full_read(fd, h, sizeof *h);
3048 if (size == sizeof *h && 0 == memcmp(h, ELFMAG, 4)) {
3049 if (h->e_type == ET_REL)
3050 return AFF_BINTYPE_REL;
3051 if (h->e_type == ET_DYN)
3052 return AFF_BINTYPE_DYN;
3053 } else if (size >= 8) {
3054 if (0 == memcmp(h, ARMAG, 8))
3055 return AFF_BINTYPE_AR;
3056 #ifdef TCC_TARGET_COFF
3057 if (((struct filehdr*)h)->f_magic == COFF_C67_MAGIC)
3058 return AFF_BINTYPE_C67;
3059 #endif
3061 return 0;
3064 /* load an object file and merge it with current files */
3065 /* XXX: handle correctly stab (debug) info */
3066 ST_FUNC int tcc_load_object_file(TCCState *s1,
3067 int fd, unsigned long file_offset)
3069 ElfW(Ehdr) ehdr;
3070 ElfW(Shdr) *shdr, *sh;
3071 unsigned long size, offset, offseti;
3072 int i, j, nb_syms, sym_index, ret, seencompressed;
3073 char *strsec, *strtab;
3074 int stab_index, stabstr_index;
3075 int *old_to_new_syms;
3076 char *sh_name, *name;
3077 SectionMergeInfo *sm_table, *sm;
3078 ElfW(Sym) *sym, *symtab;
3079 ElfW_Rel *rel;
3080 Section *s;
3082 lseek(fd, file_offset, SEEK_SET);
3083 if (tcc_object_type(fd, &ehdr) != AFF_BINTYPE_REL)
3084 goto invalid;
3085 /* test CPU specific stuff */
3086 if (ehdr.e_ident[5] != ELFDATA2LSB ||
3087 ehdr.e_machine != EM_TCC_TARGET) {
3088 invalid:
3089 return tcc_error_noabort("invalid object file");
3091 /* read sections */
3092 shdr = load_data(fd, file_offset + ehdr.e_shoff,
3093 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
3094 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
3096 /* load section names */
3097 sh = &shdr[ehdr.e_shstrndx];
3098 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
3100 /* load symtab and strtab */
3101 old_to_new_syms = NULL;
3102 symtab = NULL;
3103 strtab = NULL;
3104 nb_syms = 0;
3105 seencompressed = 0;
3106 stab_index = stabstr_index = 0;
3107 ret = -1;
3109 for(i = 1; i < ehdr.e_shnum; i++) {
3110 sh = &shdr[i];
3111 if (sh->sh_type == SHT_SYMTAB) {
3112 if (symtab) {
3113 tcc_error_noabort("object must contain only one symtab");
3114 goto the_end;
3116 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
3117 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
3118 sm_table[i].s = symtab_section;
3120 /* now load strtab */
3121 sh = &shdr[sh->sh_link];
3122 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
3124 if (sh->sh_flags & SHF_COMPRESSED)
3125 seencompressed = 1;
3128 /* now examine each section and try to merge its content with the
3129 ones in memory */
3130 for(i = 1; i < ehdr.e_shnum; i++) {
3131 /* no need to examine section name strtab */
3132 if (i == ehdr.e_shstrndx)
3133 continue;
3134 sh = &shdr[i];
3135 if (sh->sh_type == SHT_RELX)
3136 sh = &shdr[sh->sh_info];
3137 /* ignore sections types we do not handle (plus relocs to those) */
3138 if (sh->sh_type != SHT_PROGBITS &&
3139 #ifdef TCC_ARM_EABI
3140 sh->sh_type != SHT_ARM_EXIDX &&
3141 #endif
3142 #if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD
3143 sh->sh_type != SHT_X86_64_UNWIND &&
3144 #endif
3145 sh->sh_type != SHT_NOTE &&
3146 sh->sh_type != SHT_NOBITS &&
3147 sh->sh_type != SHT_PREINIT_ARRAY &&
3148 sh->sh_type != SHT_INIT_ARRAY &&
3149 sh->sh_type != SHT_FINI_ARRAY &&
3150 strcmp(strsec + sh->sh_name, ".stabstr")
3152 continue;
3153 if (seencompressed && 0 == strncmp(strsec + sh->sh_name, ".debug_", 7))
3154 continue;
3156 sh = &shdr[i];
3157 sh_name = strsec + sh->sh_name;
3158 if (sh->sh_addralign < 1)
3159 sh->sh_addralign = 1;
3160 /* find corresponding section, if any */
3161 for(j = 1; j < s1->nb_sections;j++) {
3162 s = s1->sections[j];
3163 if (!strcmp(s->name, sh_name)) {
3164 if (!strncmp(sh_name, ".gnu.linkonce",
3165 sizeof(".gnu.linkonce") - 1)) {
3166 /* if a 'linkonce' section is already present, we
3167 do not add it again. It is a little tricky as
3168 symbols can still be defined in
3169 it. */
3170 sm_table[i].link_once = 1;
3171 goto next;
3173 if (stab_section) {
3174 if (s == stab_section)
3175 stab_index = i;
3176 if (s == stab_section->link)
3177 stabstr_index = i;
3179 goto found;
3182 /* not found: create new section */
3183 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags & ~SHF_GROUP);
3184 /* take as much info as possible from the section. sh_link and
3185 sh_info will be updated later */
3186 s->sh_addralign = sh->sh_addralign;
3187 s->sh_entsize = sh->sh_entsize;
3188 sm_table[i].new_section = 1;
3189 found:
3190 if (sh->sh_type != s->sh_type
3191 #if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD
3192 && strcmp (s->name, ".eh_frame")
3193 #endif
3195 tcc_error_noabort("invalid section type");
3196 goto the_end;
3198 /* align start of section */
3199 s->data_offset += -s->data_offset & (sh->sh_addralign - 1);
3200 if (sh->sh_addralign > s->sh_addralign)
3201 s->sh_addralign = sh->sh_addralign;
3202 sm_table[i].offset = s->data_offset;
3203 sm_table[i].s = s;
3204 /* concatenate sections */
3205 size = sh->sh_size;
3206 if (sh->sh_type != SHT_NOBITS) {
3207 unsigned char *ptr;
3208 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
3209 ptr = section_ptr_add(s, size);
3210 full_read(fd, ptr, size);
3211 } else {
3212 s->data_offset += size;
3214 next: ;
3217 /* gr relocate stab strings */
3218 if (stab_index && stabstr_index) {
3219 Stab_Sym *a, *b;
3220 unsigned o;
3221 s = sm_table[stab_index].s;
3222 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
3223 b = (Stab_Sym *)(s->data + s->data_offset);
3224 o = sm_table[stabstr_index].offset;
3225 while (a < b) {
3226 if (a->n_strx)
3227 a->n_strx += o;
3228 a++;
3232 /* second short pass to update sh_link and sh_info fields of new
3233 sections */
3234 for(i = 1; i < ehdr.e_shnum; i++) {
3235 s = sm_table[i].s;
3236 if (!s || !sm_table[i].new_section)
3237 continue;
3238 sh = &shdr[i];
3239 if (sh->sh_link > 0)
3240 s->link = sm_table[sh->sh_link].s;
3241 if (sh->sh_type == SHT_RELX) {
3242 s->sh_info = sm_table[sh->sh_info].s->sh_num;
3243 /* update backward link */
3244 s1->sections[s->sh_info]->reloc = s;
3248 /* resolve symbols */
3249 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
3251 sym = symtab + 1;
3252 for(i = 1; i < nb_syms; i++, sym++) {
3253 if (sym->st_shndx != SHN_UNDEF &&
3254 sym->st_shndx < SHN_LORESERVE) {
3255 sm = &sm_table[sym->st_shndx];
3256 if (sm->link_once) {
3257 /* if a symbol is in a link once section, we use the
3258 already defined symbol. It is very important to get
3259 correct relocations */
3260 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
3261 name = strtab + sym->st_name;
3262 sym_index = find_elf_sym(symtab_section, name);
3263 if (sym_index)
3264 old_to_new_syms[i] = sym_index;
3266 continue;
3268 /* if no corresponding section added, no need to add symbol */
3269 if (!sm->s)
3270 continue;
3271 /* convert section number */
3272 sym->st_shndx = sm->s->sh_num;
3273 /* offset value */
3274 sym->st_value += sm->offset;
3276 /* add symbol */
3277 name = strtab + sym->st_name;
3278 sym_index = set_elf_sym(symtab_section, sym->st_value, sym->st_size,
3279 sym->st_info, sym->st_other,
3280 sym->st_shndx, name);
3281 old_to_new_syms[i] = sym_index;
3284 /* third pass to patch relocation entries */
3285 for(i = 1; i < ehdr.e_shnum; i++) {
3286 s = sm_table[i].s;
3287 if (!s)
3288 continue;
3289 sh = &shdr[i];
3290 offset = sm_table[i].offset;
3291 size = sh->sh_size;
3292 switch(s->sh_type) {
3293 case SHT_RELX:
3294 /* take relocation offset information */
3295 offseti = sm_table[sh->sh_info].offset;
3296 for (rel = (ElfW_Rel *) s->data + (offset / sizeof(*rel));
3297 rel < (ElfW_Rel *) s->data + ((offset + size) / sizeof(*rel));
3298 rel++) {
3299 int type;
3300 unsigned sym_index;
3301 /* convert symbol index */
3302 type = ELFW(R_TYPE)(rel->r_info);
3303 sym_index = ELFW(R_SYM)(rel->r_info);
3304 /* NOTE: only one symtab assumed */
3305 if (sym_index >= nb_syms)
3306 goto invalid_reloc;
3307 sym_index = old_to_new_syms[sym_index];
3308 /* ignore link_once in rel section. */
3309 if (!sym_index && !sm_table[sh->sh_info].link_once
3310 #ifdef TCC_TARGET_ARM
3311 && type != R_ARM_V4BX
3312 #elif defined TCC_TARGET_RISCV64
3313 && type != R_RISCV_ALIGN
3314 && type != R_RISCV_RELAX
3315 #endif
3317 invalid_reloc:
3318 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
3319 i, strsec + sh->sh_name, (int)rel->r_offset);
3320 goto the_end;
3322 rel->r_info = ELFW(R_INFO)(sym_index, type);
3323 /* offset the relocation offset */
3324 rel->r_offset += offseti;
3325 #ifdef TCC_TARGET_ARM
3326 /* Jumps and branches from a Thumb code to a PLT entry need
3327 special handling since PLT entries are ARM code.
3328 Unconditional bl instructions referencing PLT entries are
3329 handled by converting these instructions into blx
3330 instructions. Other case of instructions referencing a PLT
3331 entry require to add a Thumb stub before the PLT entry to
3332 switch to ARM mode. We set bit plt_thumb_stub of the
3333 attribute of a symbol to indicate such a case. */
3334 if (type == R_ARM_THM_JUMP24)
3335 get_sym_attr(s1, sym_index, 1)->plt_thumb_stub = 1;
3336 #endif
3338 break;
3339 default:
3340 break;
3344 ret = 0;
3345 the_end:
3346 tcc_free(symtab);
3347 tcc_free(strtab);
3348 tcc_free(old_to_new_syms);
3349 tcc_free(sm_table);
3350 tcc_free(strsec);
3351 tcc_free(shdr);
3352 return ret;
3355 typedef struct ArchiveHeader {
3356 char ar_name[16]; /* name of this member */
3357 char ar_date[12]; /* file mtime */
3358 char ar_uid[6]; /* owner uid; printed as decimal */
3359 char ar_gid[6]; /* owner gid; printed as decimal */
3360 char ar_mode[8]; /* file mode, printed as octal */
3361 char ar_size[10]; /* file size, printed as decimal */
3362 char ar_fmag[2]; /* should contain ARFMAG */
3363 } ArchiveHeader;
3365 #define ARFMAG "`\n"
3367 static unsigned long long get_be(const uint8_t *b, int n)
3369 unsigned long long ret = 0;
3370 while (n)
3371 ret = (ret << 8) | *b++, --n;
3372 return ret;
3375 static int read_ar_header(int fd, int offset, ArchiveHeader *hdr)
3377 char *p, *e;
3378 int len;
3379 lseek(fd, offset, SEEK_SET);
3380 len = full_read(fd, hdr, sizeof(ArchiveHeader));
3381 if (len != sizeof(ArchiveHeader))
3382 return len ? -1 : 0;
3383 p = hdr->ar_name;
3384 for (e = p + sizeof hdr->ar_name; e > p && e[-1] == ' ';)
3385 --e;
3386 *e = '\0';
3387 hdr->ar_size[sizeof hdr->ar_size-1] = 0;
3388 return len;
3391 /* load only the objects which resolve undefined symbols */
3392 static int tcc_load_alacarte(TCCState *s1, int fd, int size, int entrysize)
3394 int i, bound, nsyms, sym_index, len, ret = -1;
3395 unsigned long long off;
3396 uint8_t *data;
3397 const char *ar_names, *p;
3398 const uint8_t *ar_index;
3399 ElfW(Sym) *sym;
3400 ArchiveHeader hdr;
3402 data = tcc_malloc(size);
3403 if (full_read(fd, data, size) != size)
3404 goto the_end;
3405 nsyms = get_be(data, entrysize);
3406 ar_index = data + entrysize;
3407 ar_names = (char *) ar_index + nsyms * entrysize;
3409 do {
3410 bound = 0;
3411 for (p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
3412 Section *s = symtab_section;
3413 sym_index = find_elf_sym(s, p);
3414 if (!sym_index)
3415 continue;
3416 sym = &((ElfW(Sym) *)s->data)[sym_index];
3417 if(sym->st_shndx != SHN_UNDEF)
3418 continue;
3419 off = get_be(ar_index + i * entrysize, entrysize);
3420 len = read_ar_header(fd, off, &hdr);
3421 if (len <= 0 || memcmp(hdr.ar_fmag, ARFMAG, 2)) {
3422 tcc_error_noabort("invalid archive");
3423 goto the_end;
3425 off += len;
3426 if (s1->verbose == 2)
3427 printf(" -> %s\n", hdr.ar_name);
3428 if (tcc_load_object_file(s1, fd, off) < 0)
3429 goto the_end;
3430 ++bound;
3432 } while(bound);
3433 ret = 0;
3434 the_end:
3435 tcc_free(data);
3436 return ret;
3439 /* load a '.a' file */
3440 ST_FUNC int tcc_load_archive(TCCState *s1, int fd, int alacarte)
3442 ArchiveHeader hdr;
3443 /* char magic[8]; */
3444 int size, len;
3445 unsigned long file_offset;
3446 ElfW(Ehdr) ehdr;
3448 /* skip magic which was already checked */
3449 /* full_read(fd, magic, sizeof(magic)); */
3450 file_offset = sizeof ARMAG - 1;
3452 for(;;) {
3453 len = read_ar_header(fd, file_offset, &hdr);
3454 if (len == 0)
3455 return 0;
3456 if (len < 0)
3457 return tcc_error_noabort("invalid archive");
3458 file_offset += len;
3459 size = strtol(hdr.ar_size, NULL, 0);
3460 /* align to even */
3461 size = (size + 1) & ~1;
3462 if (alacarte) {
3463 /* coff symbol table : we handle it */
3464 if (!strcmp(hdr.ar_name, "/"))
3465 return tcc_load_alacarte(s1, fd, size, 4);
3466 if (!strcmp(hdr.ar_name, "/SYM64/"))
3467 return tcc_load_alacarte(s1, fd, size, 8);
3468 } else if (tcc_object_type(fd, &ehdr) == AFF_BINTYPE_REL) {
3469 if (s1->verbose == 2)
3470 printf(" -> %s\n", hdr.ar_name);
3471 if (tcc_load_object_file(s1, fd, file_offset) < 0)
3472 return -1;
3474 file_offset += size;
3478 #ifndef ELF_OBJ_ONLY
3479 /* Set LV[I] to the global index of sym-version (LIB,VERSION). Maybe resizes
3480 LV, maybe create a new entry for (LIB,VERSION). */
3481 static void set_ver_to_ver(TCCState *s1, int *n, int **lv, int i, char *lib, char *version)
3483 while (i >= *n) {
3484 *lv = tcc_realloc(*lv, (*n + 1) * sizeof(**lv));
3485 (*lv)[(*n)++] = -1;
3487 if ((*lv)[i] == -1) {
3488 int v, prev_same_lib = -1;
3489 for (v = 0; v < nb_sym_versions; v++) {
3490 if (strcmp(sym_versions[v].lib, lib))
3491 continue;
3492 prev_same_lib = v;
3493 if (!strcmp(sym_versions[v].version, version))
3494 break;
3496 if (v == nb_sym_versions) {
3497 sym_versions = tcc_realloc (sym_versions,
3498 (v + 1) * sizeof(*sym_versions));
3499 sym_versions[v].lib = tcc_strdup(lib);
3500 sym_versions[v].version = tcc_strdup(version);
3501 sym_versions[v].out_index = 0;
3502 sym_versions[v].prev_same_lib = prev_same_lib;
3503 nb_sym_versions++;
3505 (*lv)[i] = v;
3509 /* Associates symbol SYM_INDEX (in dynsymtab) with sym-version index
3510 VERNDX. */
3511 static void
3512 set_sym_version(TCCState *s1, int sym_index, int verndx)
3514 if (sym_index >= nb_sym_to_version) {
3515 int newelems = sym_index ? sym_index * 2 : 1;
3516 sym_to_version = tcc_realloc(sym_to_version,
3517 newelems * sizeof(*sym_to_version));
3518 memset(sym_to_version + nb_sym_to_version, -1,
3519 (newelems - nb_sym_to_version) * sizeof(*sym_to_version));
3520 nb_sym_to_version = newelems;
3522 if (sym_to_version[sym_index] < 0)
3523 sym_to_version[sym_index] = verndx;
3526 struct versym_info {
3527 int nb_versyms;
3528 ElfW(Verdef) *verdef;
3529 ElfW(Verneed) *verneed;
3530 ElfW(Half) *versym;
3531 int nb_local_ver, *local_ver;
3535 static void store_version(TCCState *s1, struct versym_info *v, char *dynstr)
3537 char *lib, *version;
3538 uint32_t next;
3539 int i;
3541 #define DEBUG_VERSION 0
3543 if (v->versym && v->verdef) {
3544 ElfW(Verdef) *vdef = v->verdef;
3545 lib = NULL;
3546 do {
3547 ElfW(Verdaux) *verdaux =
3548 (ElfW(Verdaux) *) (((char *) vdef) + vdef->vd_aux);
3550 #if DEBUG_VERSION
3551 printf ("verdef: version:%u flags:%u index:%u, hash:%u\n",
3552 vdef->vd_version, vdef->vd_flags, vdef->vd_ndx,
3553 vdef->vd_hash);
3554 #endif
3555 if (vdef->vd_cnt) {
3556 version = dynstr + verdaux->vda_name;
3558 if (lib == NULL)
3559 lib = version;
3560 else
3561 set_ver_to_ver(s1, &v->nb_local_ver, &v->local_ver, vdef->vd_ndx,
3562 lib, version);
3563 #if DEBUG_VERSION
3564 printf (" verdaux(%u): %s\n", vdef->vd_ndx, version);
3565 #endif
3567 next = vdef->vd_next;
3568 vdef = (ElfW(Verdef) *) (((char *) vdef) + next);
3569 } while (next);
3571 if (v->versym && v->verneed) {
3572 ElfW(Verneed) *vneed = v->verneed;
3573 do {
3574 ElfW(Vernaux) *vernaux =
3575 (ElfW(Vernaux) *) (((char *) vneed) + vneed->vn_aux);
3577 lib = dynstr + vneed->vn_file;
3578 #if DEBUG_VERSION
3579 printf ("verneed: %u %s\n", vneed->vn_version, lib);
3580 #endif
3581 for (i = 0; i < vneed->vn_cnt; i++) {
3582 if ((vernaux->vna_other & 0x8000) == 0) { /* hidden */
3583 version = dynstr + vernaux->vna_name;
3584 set_ver_to_ver(s1, &v->nb_local_ver, &v->local_ver, vernaux->vna_other,
3585 lib, version);
3586 #if DEBUG_VERSION
3587 printf (" vernaux(%u): %u %u %s\n",
3588 vernaux->vna_other, vernaux->vna_hash,
3589 vernaux->vna_flags, version);
3590 #endif
3592 vernaux = (ElfW(Vernaux) *) (((char *) vernaux) + vernaux->vna_next);
3594 next = vneed->vn_next;
3595 vneed = (ElfW(Verneed) *) (((char *) vneed) + next);
3596 } while (next);
3599 #if DEBUG_VERSION
3600 for (i = 0; i < v->nb_local_ver; i++) {
3601 if (v->local_ver[i] > 0) {
3602 printf ("%d: lib: %s, version %s\n",
3603 i, sym_versions[v->local_ver[i]].lib,
3604 sym_versions[v->local_ver[i]].version);
3607 #endif
3610 /* load a library / DLL
3611 'level = 0' means that the DLL is referenced by the user
3612 (so it should be added as DT_NEEDED in the generated ELF file) */
3613 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
3615 ElfW(Ehdr) ehdr;
3616 ElfW(Shdr) *shdr, *sh, *sh1;
3617 int i, nb_syms, nb_dts, sym_bind, ret = -1;
3618 ElfW(Sym) *sym, *dynsym;
3619 ElfW(Dyn) *dt, *dynamic;
3621 char *dynstr;
3622 int sym_index;
3623 const char *name, *soname;
3624 struct versym_info v;
3626 full_read(fd, &ehdr, sizeof(ehdr));
3628 /* test CPU specific stuff */
3629 if (ehdr.e_ident[5] != ELFDATA2LSB ||
3630 ehdr.e_machine != EM_TCC_TARGET) {
3631 return tcc_error_noabort("bad architecture");
3634 /* read sections */
3635 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
3637 /* load dynamic section and dynamic symbols */
3638 nb_syms = 0;
3639 nb_dts = 0;
3640 dynamic = NULL;
3641 dynsym = NULL; /* avoid warning */
3642 dynstr = NULL; /* avoid warning */
3643 memset(&v, 0, sizeof v);
3645 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
3646 switch(sh->sh_type) {
3647 case SHT_DYNAMIC:
3648 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
3649 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
3650 break;
3651 case SHT_DYNSYM:
3652 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
3653 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
3654 sh1 = &shdr[sh->sh_link];
3655 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
3656 break;
3657 case SHT_GNU_verdef:
3658 v.verdef = load_data(fd, sh->sh_offset, sh->sh_size);
3659 break;
3660 case SHT_GNU_verneed:
3661 v.verneed = load_data(fd, sh->sh_offset, sh->sh_size);
3662 break;
3663 case SHT_GNU_versym:
3664 v.nb_versyms = sh->sh_size / sizeof(ElfW(Half));
3665 v.versym = load_data(fd, sh->sh_offset, sh->sh_size);
3666 break;
3667 default:
3668 break;
3672 if (!dynamic)
3673 goto the_end;
3675 /* compute the real library name */
3676 soname = tcc_basename(filename);
3677 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++)
3678 if (dt->d_tag == DT_SONAME)
3679 soname = dynstr + dt->d_un.d_val;
3681 /* if the dll is already loaded, do not load it */
3682 if (tcc_add_dllref(s1, soname, level)->found)
3683 goto ret_success;
3685 if (v.nb_versyms != nb_syms)
3686 tcc_free (v.versym), v.versym = NULL;
3687 else
3688 store_version(s1, &v, dynstr);
3690 /* add dynamic symbols in dynsym_section */
3691 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
3692 sym_bind = ELFW(ST_BIND)(sym->st_info);
3693 if (sym_bind == STB_LOCAL)
3694 continue;
3695 name = dynstr + sym->st_name;
3696 sym_index = set_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
3697 sym->st_info, sym->st_other, sym->st_shndx, name);
3698 if (v.versym) {
3699 ElfW(Half) vsym = v.versym[i];
3700 if ((vsym & 0x8000) == 0 && vsym > 0 && vsym < v.nb_local_ver)
3701 set_sym_version(s1, sym_index, v.local_ver[vsym]);
3705 /* do not load all referenced libraries
3706 (recursive loading can break linking of libraries) */
3707 /* following DT_NEEDED is needed for the dynamic loader (libdl.so),
3708 but it is no longer needed, when linking a library or a program.
3709 When tcc output mode is OUTPUT_MEM,
3710 tcc calls dlopen, which handles DT_NEEDED for us */
3712 #if 0
3713 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++)
3714 if (dt->d_tag == DT_RPATH)
3715 tcc_add_library_path(s1, dynstr + dt->d_un.d_val);
3717 /* load all referenced DLLs */
3718 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
3719 switch(dt->d_tag) {
3720 case DT_NEEDED:
3721 name = dynstr + dt->d_un.d_val;
3722 if (tcc_add_dllref(s1, name, -1))
3723 continue;
3724 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
3725 ret = tcc_error_noabort("referenced dll '%s' not found", name);
3726 goto the_end;
3730 #endif
3732 ret_success:
3733 ret = 0;
3734 the_end:
3735 tcc_free(dynstr);
3736 tcc_free(dynsym);
3737 tcc_free(dynamic);
3738 tcc_free(shdr);
3739 tcc_free(v.local_ver);
3740 tcc_free(v.verdef);
3741 tcc_free(v.verneed);
3742 tcc_free(v.versym);
3743 return ret;
3746 #define LD_TOK_NAME 256
3747 #define LD_TOK_EOF (-1)
3749 static int ld_inp(TCCState *s1)
3751 char b;
3752 if (s1->cc != -1) {
3753 int c = s1->cc;
3754 s1->cc = -1;
3755 return c;
3757 if (1 == read(s1->fd, &b, 1))
3758 return b;
3759 return CH_EOF;
3762 /* return next ld script token */
3763 static int ld_next(TCCState *s1, char *name, int name_size)
3765 int c, d, ch;
3766 char *q;
3768 redo:
3769 ch = ld_inp(s1);
3770 switch(ch) {
3771 case ' ':
3772 case '\t':
3773 case '\f':
3774 case '\v':
3775 case '\r':
3776 case '\n':
3777 goto redo;
3778 case '/':
3779 ch = ld_inp(s1);
3780 if (ch == '*') { /* comment */
3781 for (d = 0;; d = ch) {
3782 ch = ld_inp(s1);
3783 if (ch == CH_EOF || (ch == '/' && d == '*'))
3784 break;
3786 goto redo;
3787 } else {
3788 q = name;
3789 *q++ = '/';
3790 goto parse_name;
3792 break;
3793 case '\\':
3794 /* case 'a' ... 'z': */
3795 case 'a':
3796 case 'b':
3797 case 'c':
3798 case 'd':
3799 case 'e':
3800 case 'f':
3801 case 'g':
3802 case 'h':
3803 case 'i':
3804 case 'j':
3805 case 'k':
3806 case 'l':
3807 case 'm':
3808 case 'n':
3809 case 'o':
3810 case 'p':
3811 case 'q':
3812 case 'r':
3813 case 's':
3814 case 't':
3815 case 'u':
3816 case 'v':
3817 case 'w':
3818 case 'x':
3819 case 'y':
3820 case 'z':
3821 /* case 'A' ... 'z': */
3822 case 'A':
3823 case 'B':
3824 case 'C':
3825 case 'D':
3826 case 'E':
3827 case 'F':
3828 case 'G':
3829 case 'H':
3830 case 'I':
3831 case 'J':
3832 case 'K':
3833 case 'L':
3834 case 'M':
3835 case 'N':
3836 case 'O':
3837 case 'P':
3838 case 'Q':
3839 case 'R':
3840 case 'S':
3841 case 'T':
3842 case 'U':
3843 case 'V':
3844 case 'W':
3845 case 'X':
3846 case 'Y':
3847 case 'Z':
3848 case '_':
3849 case '.':
3850 case '$':
3851 case '~':
3852 q = name;
3853 parse_name:
3854 for(;;) {
3855 if (!((ch >= 'a' && ch <= 'z') ||
3856 (ch >= 'A' && ch <= 'Z') ||
3857 (ch >= '0' && ch <= '9') ||
3858 strchr("/.-_+=$:\\,~", ch)))
3859 break;
3860 if ((q - name) < name_size - 1) {
3861 *q++ = ch;
3863 ch = ld_inp(s1);
3865 s1->cc = ch;
3866 *q = '\0';
3867 c = LD_TOK_NAME;
3868 break;
3869 case CH_EOF:
3870 c = LD_TOK_EOF;
3871 break;
3872 default:
3873 c = ch;
3874 break;
3876 return c;
3879 static int ld_add_file(TCCState *s1, const char filename[])
3881 if (filename[0] == '/') {
3882 if (CONFIG_SYSROOT[0] == '\0'
3883 && tcc_add_file_internal(s1, filename, AFF_TYPE_BIN) == 0)
3884 return 0;
3885 filename = tcc_basename(filename);
3887 return tcc_add_dll(s1, filename, AFF_PRINT_ERROR);
3890 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
3892 char filename[1024], libname[1024];
3893 int t, group, nblibs = 0, ret = 0;
3894 char **libs = NULL;
3896 group = !strcmp(cmd, "GROUP");
3897 if (!as_needed)
3898 s1->new_undef_sym = 0;
3899 t = ld_next(s1, filename, sizeof(filename));
3900 if (t != '(') {
3901 ret = tcc_error_noabort("( expected");
3902 goto lib_parse_error;
3904 t = ld_next(s1, filename, sizeof(filename));
3905 for(;;) {
3906 libname[0] = '\0';
3907 if (t == LD_TOK_EOF) {
3908 ret = tcc_error_noabort("unexpected end of file");
3909 goto lib_parse_error;
3910 } else if (t == ')') {
3911 break;
3912 } else if (t == '-') {
3913 t = ld_next(s1, filename, sizeof(filename));
3914 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
3915 ret = tcc_error_noabort("library name expected");
3916 goto lib_parse_error;
3918 pstrcpy(libname, sizeof libname, &filename[1]);
3919 if (s1->static_link) {
3920 snprintf(filename, sizeof filename, "lib%s.a", libname);
3921 } else {
3922 snprintf(filename, sizeof filename, "lib%s.so", libname);
3924 } else if (t != LD_TOK_NAME) {
3925 ret = tcc_error_noabort("filename expected");
3926 goto lib_parse_error;
3928 if (!strcmp(filename, "AS_NEEDED")) {
3929 ret = ld_add_file_list(s1, cmd, 1);
3930 if (ret)
3931 goto lib_parse_error;
3932 } else {
3933 /* TODO: Implement AS_NEEDED support. */
3934 /* DT_NEEDED is not used any more so ignore as_needed */
3935 if (1 || !as_needed) {
3936 ret = ld_add_file(s1, filename);
3937 if (ret)
3938 goto lib_parse_error;
3939 if (group) {
3940 /* Add the filename *and* the libname to avoid future conversions */
3941 dynarray_add(&libs, &nblibs, tcc_strdup(filename));
3942 if (libname[0] != '\0')
3943 dynarray_add(&libs, &nblibs, tcc_strdup(libname));
3947 t = ld_next(s1, filename, sizeof(filename));
3948 if (t == ',') {
3949 t = ld_next(s1, filename, sizeof(filename));
3952 if (group && !as_needed) {
3953 while (s1->new_undef_sym) {
3954 int i;
3955 s1->new_undef_sym = 0;
3956 for (i = 0; i < nblibs; i ++)
3957 ld_add_file(s1, libs[i]);
3960 lib_parse_error:
3961 dynarray_reset(&libs, &nblibs);
3962 return ret;
3965 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3966 files */
3967 ST_FUNC int tcc_load_ldscript(TCCState *s1, int fd)
3969 char cmd[64];
3970 char filename[1024];
3971 int t, ret;
3973 s1->fd = fd;
3974 s1->cc = -1;
3975 for(;;) {
3976 t = ld_next(s1, cmd, sizeof(cmd));
3977 if (t == LD_TOK_EOF)
3978 return 0;
3979 else if (t != LD_TOK_NAME)
3980 return -1;
3981 if (!strcmp(cmd, "INPUT") ||
3982 !strcmp(cmd, "GROUP")) {
3983 ret = ld_add_file_list(s1, cmd, 0);
3984 if (ret)
3985 return ret;
3986 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3987 !strcmp(cmd, "TARGET")) {
3988 /* ignore some commands */
3989 t = ld_next(s1, cmd, sizeof(cmd));
3990 if (t != '(')
3991 return tcc_error_noabort("( expected");
3992 for(;;) {
3993 t = ld_next(s1, filename, sizeof(filename));
3994 if (t == LD_TOK_EOF) {
3995 return tcc_error_noabort("unexpected end of file");
3996 } else if (t == ')') {
3997 break;
4000 } else {
4001 return -1;
4004 return 0;
4006 #endif /* !ELF_OBJ_ONLY */