Revert "Split elf_output_file in smaller functions"
[tinycc.git] / tccelf.c
blob6e89988e392a598cc1b23e5281f773afd385dd13
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 static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */
25 ST_FUNC int put_elf_str(Section *s, const char *sym)
27 int offset, len;
28 char *ptr;
30 len = strlen(sym) + 1;
31 offset = s->data_offset;
32 ptr = section_ptr_add(s, len);
33 memcpy(ptr, sym, len);
34 return offset;
37 /* elf symbol hashing function */
38 static unsigned long elf_hash(const unsigned char *name)
40 unsigned long h = 0, g;
42 while (*name) {
43 h = (h << 4) + *name++;
44 g = h & 0xf0000000;
45 if (g)
46 h ^= g >> 24;
47 h &= ~g;
49 return h;
52 /* rebuild hash table of section s */
53 /* NOTE: we do factorize the hash table code to go faster */
54 static void rebuild_hash(Section *s, unsigned int nb_buckets)
56 ElfW(Sym) *sym;
57 int *ptr, *hash, nb_syms, sym_index, h;
58 char *strtab;
60 strtab = s->link->data;
61 nb_syms = s->data_offset / sizeof(ElfW(Sym));
63 s->hash->data_offset = 0;
64 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
65 ptr[0] = nb_buckets;
66 ptr[1] = nb_syms;
67 ptr += 2;
68 hash = ptr;
69 memset(hash, 0, (nb_buckets + 1) * sizeof(int));
70 ptr += nb_buckets + 1;
72 sym = (ElfW(Sym) *)s->data + 1;
73 for(sym_index = 1; sym_index < nb_syms; sym_index++) {
74 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
75 h = elf_hash(strtab + sym->st_name) % nb_buckets;
76 *ptr = hash[h];
77 hash[h] = sym_index;
78 } else {
79 *ptr = 0;
81 ptr++;
82 sym++;
86 /* return the symbol number */
87 ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size,
88 int info, int other, int shndx, const char *name)
90 int name_offset, sym_index;
91 int nbuckets, h;
92 ElfW(Sym) *sym;
93 Section *hs;
95 sym = section_ptr_add(s, sizeof(ElfW(Sym)));
96 if (name)
97 name_offset = put_elf_str(s->link, name);
98 else
99 name_offset = 0;
100 /* XXX: endianness */
101 sym->st_name = name_offset;
102 sym->st_value = value;
103 sym->st_size = size;
104 sym->st_info = info;
105 sym->st_other = other;
106 sym->st_shndx = shndx;
107 sym_index = sym - (ElfW(Sym) *)s->data;
108 hs = s->hash;
109 if (hs) {
110 int *ptr, *base;
111 ptr = section_ptr_add(hs, sizeof(int));
112 base = (int *)hs->data;
113 /* only add global or weak symbols */
114 if (ELFW(ST_BIND)(info) != STB_LOCAL) {
115 /* add another hashing entry */
116 nbuckets = base[0];
117 h = elf_hash(name) % nbuckets;
118 *ptr = base[2 + h];
119 base[2 + h] = sym_index;
120 base[1]++;
121 /* we resize the hash table */
122 hs->nb_hashed_syms++;
123 if (hs->nb_hashed_syms > 2 * nbuckets) {
124 rebuild_hash(s, 2 * nbuckets);
126 } else {
127 *ptr = 0;
128 base[1]++;
131 return sym_index;
134 /* find global ELF symbol 'name' and return its index. Return 0 if not
135 found. */
136 ST_FUNC int find_elf_sym(Section *s, const char *name)
138 ElfW(Sym) *sym;
139 Section *hs;
140 int nbuckets, sym_index, h;
141 const char *name1;
143 hs = s->hash;
144 if (!hs)
145 return 0;
146 nbuckets = ((int *)hs->data)[0];
147 h = elf_hash(name) % nbuckets;
148 sym_index = ((int *)hs->data)[2 + h];
149 while (sym_index != 0) {
150 sym = &((ElfW(Sym) *)s->data)[sym_index];
151 name1 = s->link->data + sym->st_name;
152 if (!strcmp(name, name1))
153 return sym_index;
154 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
156 return 0;
159 /* return elf symbol value, signal error if 'err' is nonzero */
160 ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err)
162 int sym_index;
163 ElfW(Sym) *sym;
165 sym_index = find_elf_sym(s->symtab, name);
166 sym = &((ElfW(Sym) *)s->symtab->data)[sym_index];
167 if (!sym_index || sym->st_shndx == SHN_UNDEF) {
168 if (err)
169 tcc_error("%s not defined", name);
170 return 0;
172 return sym->st_value;
175 /* return elf symbol value */
176 LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
178 return (void*)(uintptr_t)get_elf_sym_addr(s, name, 0);
181 #if defined TCC_IS_NATIVE || defined TCC_TARGET_PE
182 /* return elf symbol value or error */
183 ST_FUNC void* tcc_get_symbol_err(TCCState *s, const char *name)
185 return (void*)(uintptr_t)get_elf_sym_addr(s, name, 1);
187 #endif
189 /* add an elf symbol : check if it is already defined and patch
190 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
191 ST_FUNC int add_elf_sym(Section *s, addr_t value, unsigned long size,
192 int info, int other, int sh_num, const char *name)
194 ElfW(Sym) *esym;
195 int sym_bind, sym_index, sym_type, esym_bind;
196 unsigned char sym_vis, esym_vis, new_vis;
198 sym_bind = ELFW(ST_BIND)(info);
199 sym_type = ELFW(ST_TYPE)(info);
200 sym_vis = ELFW(ST_VISIBILITY)(other);
202 if (sym_bind != STB_LOCAL) {
203 /* we search global or weak symbols */
204 sym_index = find_elf_sym(s, name);
205 if (!sym_index)
206 goto do_def;
207 esym = &((ElfW(Sym) *)s->data)[sym_index];
208 if (esym->st_shndx != SHN_UNDEF) {
209 esym_bind = ELFW(ST_BIND)(esym->st_info);
210 /* propagate the most constraining visibility */
211 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
212 esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
213 if (esym_vis == STV_DEFAULT) {
214 new_vis = sym_vis;
215 } else if (sym_vis == STV_DEFAULT) {
216 new_vis = esym_vis;
217 } else {
218 new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
220 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
221 | new_vis;
222 other = esym->st_other; /* in case we have to patch esym */
223 if (sh_num == SHN_UNDEF) {
224 /* ignore adding of undefined symbol if the
225 corresponding symbol is already defined */
226 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
227 /* global overrides weak, so patch */
228 goto do_patch;
229 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
230 /* weak is ignored if already global */
231 } else if (sym_bind == STB_WEAK && esym_bind == STB_WEAK) {
232 /* keep first-found weak definition, ignore subsequents */
233 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
234 /* ignore hidden symbols after */
235 } else if (esym->st_shndx == SHN_COMMON
236 && (sh_num < SHN_LORESERVE || sh_num == SHN_COMMON)) {
237 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
238 No idea if this is the correct solution ... */
239 goto do_patch;
240 } else if (s == tcc_state->dynsymtab_section) {
241 /* we accept that two DLL define the same symbol */
242 } else {
243 #if 0
244 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
245 sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
246 #endif
247 tcc_error_noabort("'%s' defined twice", name);
249 } else {
250 do_patch:
251 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
252 esym->st_shndx = sh_num;
253 new_undef_sym = 1;
254 esym->st_value = value;
255 esym->st_size = size;
256 esym->st_other = other;
258 } else {
259 do_def:
260 sym_index = put_elf_sym(s, value, size,
261 ELFW(ST_INFO)(sym_bind, sym_type), other,
262 sh_num, name);
264 return sym_index;
267 /* put relocation */
268 ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
269 int type, int symbol)
271 char buf[256];
272 Section *sr;
273 ElfW_Rel *rel;
275 sr = s->reloc;
276 if (!sr) {
277 /* if no relocation section, create it */
278 snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
279 /* if the symtab is allocated, then we consider the relocation
280 are also */
281 sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
282 sr->sh_entsize = sizeof(ElfW_Rel);
283 sr->link = symtab;
284 sr->sh_info = s->sh_num;
285 s->reloc = sr;
287 rel = section_ptr_add(sr, sizeof(ElfW_Rel));
288 rel->r_offset = offset;
289 rel->r_info = ELFW(R_INFO)(symbol, type);
290 #ifdef TCC_TARGET_X86_64
291 rel->r_addend = 0;
292 #endif
295 /* put stab debug information */
297 ST_FUNC void put_stabs(const char *str, int type, int other, int desc,
298 unsigned long value)
300 Stab_Sym *sym;
302 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
303 if (str) {
304 sym->n_strx = put_elf_str(stabstr_section, str);
305 } else {
306 sym->n_strx = 0;
308 sym->n_type = type;
309 sym->n_other = other;
310 sym->n_desc = desc;
311 sym->n_value = value;
314 ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc,
315 unsigned long value, Section *sec, int sym_index)
317 put_stabs(str, type, other, desc, value);
318 put_elf_reloc(symtab_section, stab_section,
319 stab_section->data_offset - sizeof(unsigned int),
320 R_DATA_32, sym_index);
323 ST_FUNC void put_stabn(int type, int other, int desc, int value)
325 put_stabs(NULL, type, other, desc, value);
328 ST_FUNC void put_stabd(int type, int other, int desc)
330 put_stabs(NULL, type, other, desc, 0);
333 /* Browse each elem of type <type> in section <sec> starting at elem <startoff>
334 using variable <elem> */
335 #define for_each_elem(sec, startoff, elem, type) \
336 for (elem = (type *) sec->data + startoff; \
337 elem < (type *) (sec->data + sec->data_offset); elem++)
339 /* In an ELF file symbol table, the local symbols must appear below
340 the global and weak ones. Since TCC cannot sort it while generating
341 the code, we must do it after. All the relocation tables are also
342 modified to take into account the symbol table sorting */
343 static void sort_syms(TCCState *s1, Section *s)
345 int *old_to_new_syms;
346 ElfW(Sym) *new_syms;
347 int nb_syms, i;
348 ElfW(Sym) *p, *q;
349 ElfW_Rel *rel;
350 Section *sr;
351 int type, sym_index;
353 nb_syms = s->data_offset / sizeof(ElfW(Sym));
354 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
355 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
357 /* first pass for local symbols */
358 p = (ElfW(Sym) *)s->data;
359 q = new_syms;
360 for(i = 0; i < nb_syms; i++) {
361 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
362 old_to_new_syms[i] = q - new_syms;
363 *q++ = *p;
365 p++;
367 /* save the number of local symbols in section header */
368 s->sh_info = q - new_syms;
370 /* then second pass for non local symbols */
371 p = (ElfW(Sym) *)s->data;
372 for(i = 0; i < nb_syms; i++) {
373 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
374 old_to_new_syms[i] = q - new_syms;
375 *q++ = *p;
377 p++;
380 /* we copy the new symbols to the old */
381 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
382 tcc_free(new_syms);
384 /* now we modify all the relocations */
385 for(i = 1; i < s1->nb_sections; i++) {
386 sr = s1->sections[i];
387 if (sr->sh_type == SHT_RELX && sr->link == s) {
388 for_each_elem(sr, 0, rel, ElfW_Rel) {
389 sym_index = ELFW(R_SYM)(rel->r_info);
390 type = ELFW(R_TYPE)(rel->r_info);
391 sym_index = old_to_new_syms[sym_index];
392 rel->r_info = ELFW(R_INFO)(sym_index, type);
397 tcc_free(old_to_new_syms);
400 /* relocate common symbols in the .bss section */
401 ST_FUNC void relocate_common_syms(void)
403 ElfW(Sym) *sym;
404 unsigned long offset, align;
406 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
407 if (sym->st_shndx == SHN_COMMON) {
408 /* align symbol */
409 align = sym->st_value;
410 offset = bss_section->data_offset;
411 offset = (offset + align - 1) & -align;
412 sym->st_value = offset;
413 sym->st_shndx = bss_section->sh_num;
414 offset += sym->st_size;
415 bss_section->data_offset = offset;
420 /* relocate symbol table, resolve undefined symbols if do_resolve is
421 true and output error if undefined symbol. */
422 ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
424 ElfW(Sym) *sym, *esym;
425 int sym_bind, sh_num, sym_index;
426 const char *name;
428 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
429 sh_num = sym->st_shndx;
430 if (sh_num == SHN_UNDEF) {
431 name = strtab_section->data + sym->st_name;
432 if (do_resolve) {
433 #if defined TCC_IS_NATIVE && !defined _WIN32
434 void *addr;
435 name = symtab_section->link->data + sym->st_name;
436 addr = resolve_sym(s1, name);
437 if (addr) {
438 sym->st_value = (addr_t)addr;
439 goto found;
441 #endif
442 } else if (s1->dynsym) {
443 /* if dynamic symbol exist, then use it */
444 sym_index = find_elf_sym(s1->dynsym, name);
445 if (sym_index) {
446 esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
447 sym->st_value = esym->st_value;
448 goto found;
451 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
452 it */
453 if (!strcmp(name, "_fp_hw"))
454 goto found;
455 /* only weak symbols are accepted to be undefined. Their
456 value is zero */
457 sym_bind = ELFW(ST_BIND)(sym->st_info);
458 if (sym_bind == STB_WEAK) {
459 sym->st_value = 0;
460 } else {
461 tcc_error_noabort("undefined symbol '%s'", name);
463 } else if (sh_num < SHN_LORESERVE) {
464 /* add section base */
465 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
467 found: ;
471 #ifdef TCC_HAS_RUNTIME_PLTGOT
472 #ifdef TCC_TARGET_X86_64
473 #define JMP_TABLE_ENTRY_SIZE 14
474 static addr_t add_jmp_table(TCCState *s1, addr_t val)
476 char *p = s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset;
477 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
478 /* jmp *0x0(%rip) */
479 p[0] = 0xff;
480 p[1] = 0x25;
481 *(int *)(p + 2) = 0;
482 *(addr_t *)(p + 6) = val;
483 return (addr_t)p;
486 static addr_t add_got_table(TCCState *s1, addr_t val)
488 addr_t *p = (addr_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
489 s1->runtime_plt_and_got_offset += sizeof(addr_t);
490 *p = val;
491 return (addr_t)p;
493 #elif defined TCC_TARGET_ARM
494 #define JMP_TABLE_ENTRY_SIZE 8
495 static addr_t add_jmp_table(TCCState *s1, int val)
497 uint32_t *p = (uint32_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
498 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
499 /* ldr pc, [pc, #-4] */
500 p[0] = 0xE51FF004;
501 p[1] = val;
502 return (addr_t)p;
504 #endif
505 #endif /* def TCC_HAS_RUNTIME_PLTGOT */
507 /* relocate a given section (CPU dependent) */
508 ST_FUNC void relocate_section(TCCState *s1, Section *s)
510 Section *sr;
511 ElfW_Rel *rel;
512 ElfW(Sym) *sym;
513 int type, sym_index;
514 unsigned char *ptr;
515 addr_t val, addr;
516 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
517 int esym_index;
518 #endif
520 sr = s->reloc;
521 for_each_elem(sr, 0, rel, ElfW_Rel) {
522 ptr = s->data + rel->r_offset;
524 sym_index = ELFW(R_SYM)(rel->r_info);
525 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
526 val = sym->st_value;
527 #ifdef TCC_TARGET_X86_64
528 val += rel->r_addend;
529 #endif
530 type = ELFW(R_TYPE)(rel->r_info);
531 addr = s->sh_addr + rel->r_offset;
533 /* CPU specific */
534 switch(type) {
535 #if defined(TCC_TARGET_I386)
536 case R_386_32:
537 if (s1->output_type == TCC_OUTPUT_DLL) {
538 esym_index = s1->symtab_to_dynsym[sym_index];
539 qrel->r_offset = rel->r_offset;
540 if (esym_index) {
541 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
542 qrel++;
543 break;
544 } else {
545 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
546 qrel++;
549 *(int *)ptr += val;
550 break;
551 case R_386_PC32:
552 if (s1->output_type == TCC_OUTPUT_DLL) {
553 /* DLL relocation */
554 esym_index = s1->symtab_to_dynsym[sym_index];
555 if (esym_index) {
556 qrel->r_offset = rel->r_offset;
557 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
558 qrel++;
559 break;
562 *(int *)ptr += val - addr;
563 break;
564 case R_386_PLT32:
565 *(int *)ptr += val - addr;
566 break;
567 case R_386_GLOB_DAT:
568 case R_386_JMP_SLOT:
569 *(int *)ptr = val;
570 break;
571 case R_386_GOTPC:
572 *(int *)ptr += s1->got->sh_addr - addr;
573 break;
574 case R_386_GOTOFF:
575 *(int *)ptr += val - s1->got->sh_addr;
576 break;
577 case R_386_GOT32:
578 /* we load the got offset */
579 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
580 break;
581 case R_386_16:
582 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
583 output_file:
584 tcc_error("can only produce 16-bit binary files");
586 *(short *)ptr += val;
587 break;
588 case R_386_PC16:
589 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
590 goto output_file;
591 *(short *)ptr += val - addr;
592 break;
593 #elif defined(TCC_TARGET_ARM)
594 case R_ARM_PC24:
595 case R_ARM_CALL:
596 case R_ARM_JUMP24:
597 case R_ARM_PLT32:
599 int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko;
600 x = (*(int *) ptr) & 0xffffff;
601 (*(int *)ptr) &= 0xff000000;
602 if (x & 0x800000)
603 x -= 0x1000000;
604 x <<= 2;
605 blx_avail = (TCC_ARM_VERSION >= 5);
606 is_thumb = val & 1;
607 is_bl = (*(unsigned *) ptr) >> 24 == 0xeb;
608 is_call = (type == R_ARM_CALL || (type == R_ARM_PC24 && is_bl));
609 x += val - addr;
610 h = x & 2;
611 th_ko = (x & 3) && (!blx_avail || !is_call);
612 #ifdef TCC_HAS_RUNTIME_PLTGOT
613 if (s1->output_type == TCC_OUTPUT_MEMORY) {
614 if (th_ko || x >= 0x2000000 || x < -0x2000000) {
615 x += add_jmp_table(s1, val) - val; /* add veneer */
616 th_ko = (x & 3) && (!blx_avail || !is_call);
617 is_thumb = 0; /* Veneer uses ARM instructions */
620 #endif
621 if (th_ko || x >= 0x2000000 || x < -0x2000000)
622 tcc_error("can't relocate value at %x",addr);
623 x >>= 2;
624 x &= 0xffffff;
625 /* Only reached if blx is avail and it is a call */
626 if (is_thumb) {
627 x |= h << 24;
628 (*(int *)ptr) = 0xfa << 24; /* bl -> blx */
630 (*(int *) ptr) |= x;
632 break;
633 /* Since these relocations only concern Thumb-2 and blx instruction was
634 introduced before Thumb-2, we can assume blx is available and not
635 guard its use */
636 case R_ARM_THM_PC22:
637 case R_ARM_THM_JUMP24:
639 int x, hi, lo, s, j1, j2, i1, i2, imm10, imm11;
640 int to_thumb, is_call, to_plt, blx_bit = 1 << 12;
641 Section *plt;
643 /* weak reference */
644 if (sym->st_shndx == SHN_UNDEF &&
645 ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
646 break;
648 /* Get initial offset */
649 hi = (*(uint16_t *)ptr);
650 lo = (*(uint16_t *)(ptr+2));
651 s = (hi >> 10) & 1;
652 j1 = (lo >> 13) & 1;
653 j2 = (lo >> 11) & 1;
654 i1 = (j1 ^ s) ^ 1;
655 i2 = (j2 ^ s) ^ 1;
656 imm10 = hi & 0x3ff;
657 imm11 = lo & 0x7ff;
658 x = (s << 24) | (i1 << 23) | (i2 << 22) |
659 (imm10 << 12) | (imm11 << 1);
660 if (x & 0x01000000)
661 x -= 0x02000000;
663 /* Relocation infos */
664 to_thumb = val & 1;
665 plt = s1->plt;
666 to_plt = (val >= plt->sh_addr) &&
667 (val < plt->sh_addr + plt->data_offset);
668 is_call = (type == R_ARM_THM_PC22);
670 /* Compute final offset */
671 if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */
672 x -= 4;
673 x += val - addr;
674 if (!to_thumb && is_call) {
675 blx_bit = 0; /* bl -> blx */
676 x = (x + 3) & -4; /* Compute offset from aligned PC */
679 /* Check that relocation is possible
680 * offset must not be out of range
681 * if target is to be entered in arm mode:
682 - bit 1 must not set
683 - instruction must be a call (bl) or a jump to PLT */
684 if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
685 if (to_thumb || (val & 2) || (!is_call && !to_plt))
686 tcc_error("can't relocate value at %x",addr);
688 /* Compute and store final offset */
689 s = (x >> 24) & 1;
690 i1 = (x >> 23) & 1;
691 i2 = (x >> 22) & 1;
692 j1 = s ^ (i1 ^ 1);
693 j2 = s ^ (i2 ^ 1);
694 imm10 = (x >> 12) & 0x3ff;
695 imm11 = (x >> 1) & 0x7ff;
696 (*(uint16_t *)ptr) = (uint16_t) ((hi & 0xf800) |
697 (s << 10) | imm10);
698 (*(uint16_t *)(ptr+2)) = (uint16_t) ((lo & 0xc000) |
699 (j1 << 13) | blx_bit | (j2 << 11) |
700 imm11);
702 break;
703 case R_ARM_MOVT_ABS:
704 case R_ARM_MOVW_ABS_NC:
706 int x, imm4, imm12;
707 if (type == R_ARM_MOVT_ABS)
708 val >>= 16;
709 imm12 = val & 0xfff;
710 imm4 = (val >> 12) & 0xf;
711 x = (imm4 << 16) | imm12;
712 if (type == R_ARM_THM_MOVT_ABS)
713 *(int *)ptr |= x;
714 else
715 *(int *)ptr += x;
717 break;
718 case R_ARM_THM_MOVT_ABS:
719 case R_ARM_THM_MOVW_ABS_NC:
721 int x, i, imm4, imm3, imm8;
722 if (type == R_ARM_THM_MOVT_ABS)
723 val >>= 16;
724 imm8 = val & 0xff;
725 imm3 = (val >> 8) & 0x7;
726 i = (val >> 11) & 1;
727 imm4 = (val >> 12) & 0xf;
728 x = (imm3 << 28) | (imm8 << 16) | (i << 10) | imm4;
729 if (type == R_ARM_THM_MOVT_ABS)
730 *(int *)ptr |= x;
731 else
732 *(int *)ptr += x;
734 break;
735 case R_ARM_PREL31:
737 int x;
738 x = (*(int *)ptr) & 0x7fffffff;
739 (*(int *)ptr) &= 0x80000000;
740 x = (x * 2) / 2;
741 x += val - addr;
742 if((x^(x>>1))&0x40000000)
743 tcc_error("can't relocate value at %x",addr);
744 (*(int *)ptr) |= x & 0x7fffffff;
746 case R_ARM_ABS32:
747 *(int *)ptr += val;
748 break;
749 case R_ARM_REL32:
750 *(int *)ptr += val - addr;
751 break;
752 case R_ARM_GOTPC:
753 *(int *)ptr += s1->got->sh_addr - addr;
754 break;
755 case R_ARM_GOTOFF:
756 *(int *)ptr += val - s1->got->sh_addr;
757 break;
758 case R_ARM_GOT32:
759 /* we load the got offset */
760 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
761 break;
762 case R_ARM_COPY:
763 break;
764 case R_ARM_V4BX:
765 /* trade Thumb support for ARMv4 support */
766 if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
767 *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
768 break;
769 default:
770 fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
771 type, (unsigned)addr, ptr, (unsigned)val);
772 break;
773 #elif defined(TCC_TARGET_C67)
774 case R_C60_32:
775 *(int *)ptr += val;
776 break;
777 case R_C60LO16:
779 uint32_t orig;
781 /* put the low 16 bits of the absolute address
782 add to what is already there */
784 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
785 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
787 /* patch both at once - assumes always in pairs Low - High */
789 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
790 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
792 break;
793 case R_C60HI16:
794 break;
795 default:
796 fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
797 type, (unsigned)addr, ptr, (unsigned)val);
798 break;
799 #elif defined(TCC_TARGET_X86_64)
800 case R_X86_64_64:
801 if (s1->output_type == TCC_OUTPUT_DLL) {
802 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
803 qrel->r_addend = *(long long *)ptr + val;
804 qrel++;
806 *(long long *)ptr += val;
807 break;
808 case R_X86_64_32:
809 case R_X86_64_32S:
810 if (s1->output_type == TCC_OUTPUT_DLL) {
811 /* XXX: this logic may depend on TCC's codegen
812 now TCC uses R_X86_64_32 even for a 64bit pointer */
813 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
814 qrel->r_addend = *(int *)ptr + val;
815 qrel++;
817 *(int *)ptr += val;
818 break;
820 case R_X86_64_PC32:
821 if (s1->output_type == TCC_OUTPUT_DLL) {
822 /* DLL relocation */
823 esym_index = s1->symtab_to_dynsym[sym_index];
824 if (esym_index) {
825 qrel->r_offset = rel->r_offset;
826 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
827 qrel->r_addend = *(int *)ptr;
828 qrel++;
829 break;
832 /* fall through */
833 case R_X86_64_PLT32: {
834 long long diff;
835 diff = (long long)val - addr;
836 if (diff <= -2147483647 || diff > 2147483647) {
837 #ifdef TCC_HAS_RUNTIME_PLTGOT
838 /* XXX: naive support for over 32bit jump */
839 if (s1->output_type == TCC_OUTPUT_MEMORY) {
840 val = (add_jmp_table(s1, val - rel->r_addend) +
841 rel->r_addend);
842 diff = val - addr;
844 #endif
845 if (diff <= -2147483647 || diff > 2147483647) {
846 tcc_error("internal error: relocation failed");
849 *(int *)ptr += diff;
851 break;
852 case R_X86_64_GLOB_DAT:
853 case R_X86_64_JUMP_SLOT:
854 /* They don't need addend */
855 *(int *)ptr = val - rel->r_addend;
856 break;
857 case R_X86_64_GOTPCREL:
858 #ifdef TCC_HAS_RUNTIME_PLTGOT
859 if (s1->output_type == TCC_OUTPUT_MEMORY) {
860 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
861 *(int *)ptr += val - addr;
862 break;
864 #endif
865 *(int *)ptr += (s1->got->sh_addr - addr +
866 s1->sym_attrs[sym_index].got_offset - 4);
867 break;
868 case R_X86_64_GOTTPOFF:
869 *(int *)ptr += val - s1->got->sh_addr;
870 break;
871 case R_X86_64_GOT32:
872 /* we load the got offset */
873 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
874 break;
875 #else
876 #error unsupported processor
877 #endif
880 /* if the relocation is allocated, we change its symbol table */
881 if (sr->sh_flags & SHF_ALLOC)
882 sr->link = s1->dynsym;
885 /* relocate relocation table in 'sr' */
886 static void relocate_rel(TCCState *s1, Section *sr)
888 Section *s;
889 ElfW_Rel *rel;
891 s = s1->sections[sr->sh_info];
892 for_each_elem(sr, 0, rel, ElfW_Rel)
893 rel->r_offset += s->sh_addr;
896 /* count the number of dynamic relocations so that we can reserve
897 their space */
898 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
900 ElfW_Rel *rel;
901 int sym_index, esym_index, type, count;
903 count = 0;
904 for_each_elem(sr, 0, rel, ElfW_Rel) {
905 sym_index = ELFW(R_SYM)(rel->r_info);
906 type = ELFW(R_TYPE)(rel->r_info);
907 switch(type) {
908 #if defined(TCC_TARGET_I386)
909 case R_386_32:
910 #elif defined(TCC_TARGET_X86_64)
911 case R_X86_64_32:
912 case R_X86_64_32S:
913 case R_X86_64_64:
914 #endif
915 count++;
916 break;
917 #if defined(TCC_TARGET_I386)
918 case R_386_PC32:
919 #elif defined(TCC_TARGET_X86_64)
920 case R_X86_64_PC32:
921 #endif
922 esym_index = s1->symtab_to_dynsym[sym_index];
923 if (esym_index)
924 count++;
925 break;
926 default:
927 break;
930 if (count) {
931 /* allocate the section */
932 sr->sh_flags |= SHF_ALLOC;
933 sr->sh_size = count * sizeof(ElfW_Rel);
935 return count;
938 static struct sym_attr *alloc_sym_attr(TCCState *s1, int index)
940 int n;
941 struct sym_attr *tab;
943 if (index >= s1->nb_sym_attrs) {
944 /* find immediately bigger power of 2 and reallocate array */
945 n = 1;
946 while (index >= n)
947 n *= 2;
948 tab = tcc_realloc(s1->sym_attrs, n * sizeof(*s1->sym_attrs));
949 s1->sym_attrs = tab;
950 memset(s1->sym_attrs + s1->nb_sym_attrs, 0,
951 (n - s1->nb_sym_attrs) * sizeof(*s1->sym_attrs));
952 s1->nb_sym_attrs = n;
954 return &s1->sym_attrs[index];
957 /* XXX: suppress that */
958 static void put32(unsigned char *p, uint32_t val)
960 p[0] = val;
961 p[1] = val >> 8;
962 p[2] = val >> 16;
963 p[3] = val >> 24;
966 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
967 defined(TCC_TARGET_X86_64)
968 static uint32_t get32(unsigned char *p)
970 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
972 #endif
974 static void build_got(TCCState *s1)
976 unsigned char *ptr;
978 /* if no got, then create it */
979 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
980 s1->got->sh_entsize = 4;
981 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
982 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
983 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
984 #if PTR_SIZE == 4
985 /* keep space for _DYNAMIC pointer, if present */
986 put32(ptr, 0);
987 /* two dummy got entries */
988 put32(ptr + 4, 0);
989 put32(ptr + 8, 0);
990 #else
991 /* keep space for _DYNAMIC pointer, if present */
992 put32(ptr, 0);
993 put32(ptr + 4, 0);
994 /* two dummy got entries */
995 put32(ptr + 8, 0);
996 put32(ptr + 12, 0);
997 put32(ptr + 16, 0);
998 put32(ptr + 20, 0);
999 #endif
1002 /* put a got entry corresponding to a symbol in symtab_section. 'size'
1003 and 'info' can be modifed if more precise info comes from the DLL */
1004 static void put_got_entry(TCCState *s1,
1005 int reloc_type, unsigned long size, int info,
1006 int sym_index)
1008 int index;
1009 const char *name;
1010 ElfW(Sym) *sym;
1011 unsigned long offset;
1012 int *ptr;
1014 if (!s1->got)
1015 build_got(s1);
1017 /* if a got entry already exists for that symbol, no need to add one */
1018 if (sym_index < s1->nb_sym_attrs &&
1019 s1->sym_attrs[sym_index].got_offset)
1020 return;
1022 alloc_sym_attr(s1, sym_index)->got_offset = s1->got->data_offset;
1024 if (s1->dynsym) {
1025 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1026 name = symtab_section->link->data + sym->st_name;
1027 offset = sym->st_value;
1028 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1029 if (reloc_type ==
1030 #ifdef TCC_TARGET_X86_64
1031 R_X86_64_JUMP_SLOT
1032 #else
1033 R_386_JMP_SLOT
1034 #endif
1036 Section *plt;
1037 uint8_t *p;
1038 int modrm;
1040 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1041 modrm = 0x25;
1042 #else
1043 /* if we build a DLL, we add a %ebx offset */
1044 if (s1->output_type == TCC_OUTPUT_DLL)
1045 modrm = 0xa3;
1046 else
1047 modrm = 0x25;
1048 #endif
1050 /* add a PLT entry */
1051 plt = s1->plt;
1052 if (plt->data_offset == 0) {
1053 /* first plt entry */
1054 p = section_ptr_add(plt, 16);
1055 p[0] = 0xff; /* pushl got + PTR_SIZE */
1056 p[1] = modrm + 0x10;
1057 put32(p + 2, PTR_SIZE);
1058 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1059 p[7] = modrm;
1060 put32(p + 8, PTR_SIZE * 2);
1063 p = section_ptr_add(plt, 16);
1064 p[0] = 0xff; /* jmp *(got + x) */
1065 p[1] = modrm;
1066 put32(p + 2, s1->got->data_offset);
1067 p[6] = 0x68; /* push $xxx */
1068 put32(p + 7, (plt->data_offset - 32) >> 1);
1069 p[11] = 0xe9; /* jmp plt_start */
1070 put32(p + 12, -(plt->data_offset));
1072 /* the symbol is modified so that it will be relocated to
1073 the PLT */
1074 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
1075 if (s1->output_type == TCC_OUTPUT_EXE)
1076 #endif
1077 offset = plt->data_offset - 16;
1079 #elif defined(TCC_TARGET_ARM)
1080 if (reloc_type == R_ARM_JUMP_SLOT) {
1081 Section *plt;
1082 uint8_t *p;
1084 /* if we build a DLL, we add a %ebx offset */
1085 if (s1->output_type == TCC_OUTPUT_DLL)
1086 tcc_error("DLLs unimplemented!");
1088 /* add a PLT entry */
1089 plt = s1->plt;
1090 if (plt->data_offset == 0) {
1091 /* first plt entry */
1092 p = section_ptr_add(plt, 16);
1093 put32(p, 0xe52de004); /* push {lr} */
1094 put32(p+4, 0xe59fe010); /* ldr lr, [pc, #16] */
1095 put32(p+8, 0xe08fe00e); /* add lr, pc, lr */
1096 put32(p+12, 0xe5bef008); /* ldr pc, [lr, #8]! */
1099 if (s1->sym_attrs[sym_index].plt_thumb_stub) {
1100 p = section_ptr_add(plt, 20);
1101 put32(p, 0x4778); /* bx pc */
1102 put32(p+2, 0x46c0); /* nop */
1103 p += 4;
1104 } else
1105 p = section_ptr_add(plt, 16);
1106 put32(p, 0xe59fc004); /* ldr ip, [pc, #4] ; GOT entry offset */
1107 put32(p+4, 0xe08fc00c); /* add ip, pc, ip ; addr of GOT entry */
1108 put32(p+8, 0xe59cf000); /* ldr pc, [ip] ; jump to GOT entry */
1109 put32(p+12, s1->got->data_offset); /* GOT entry off once patched */
1111 /* the symbol is modified so that it will be relocated to
1112 the PLT */
1113 if (s1->output_type == TCC_OUTPUT_EXE)
1114 offset = plt->data_offset - 16;
1116 #elif defined(TCC_TARGET_C67)
1117 tcc_error("C67 got not implemented");
1118 #else
1119 #error unsupported CPU
1120 #endif
1121 index = put_elf_sym(s1->dynsym, offset,
1122 size, info, 0, sym->st_shndx, name);
1123 /* put a got entry */
1124 put_elf_reloc(s1->dynsym, s1->got,
1125 s1->got->data_offset,
1126 reloc_type, index);
1128 ptr = section_ptr_add(s1->got, PTR_SIZE);
1129 *ptr = 0;
1132 /* build GOT and PLT entries */
1133 ST_FUNC void build_got_entries(TCCState *s1)
1135 Section *s;
1136 ElfW_Rel *rel;
1137 ElfW(Sym) *sym;
1138 int i, type, reloc_type, sym_index;
1140 for(i = 1; i < s1->nb_sections; i++) {
1141 s = s1->sections[i];
1142 if (s->sh_type != SHT_RELX)
1143 continue;
1144 /* no need to handle got relocations */
1145 if (s->link != symtab_section)
1146 continue;
1147 for_each_elem(s, 0, rel, ElfW_Rel) {
1148 type = ELFW(R_TYPE)(rel->r_info);
1149 switch(type) {
1150 #if defined(TCC_TARGET_I386)
1151 case R_386_GOT32:
1152 case R_386_GOTOFF:
1153 case R_386_GOTPC:
1154 case R_386_PLT32:
1155 if (!s1->got)
1156 build_got(s1);
1157 if (type == R_386_GOT32 || type == R_386_PLT32) {
1158 sym_index = ELFW(R_SYM)(rel->r_info);
1159 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1160 /* look at the symbol got offset. If none, then add one */
1161 if (type == R_386_GOT32)
1162 reloc_type = R_386_GLOB_DAT;
1163 else
1164 reloc_type = R_386_JMP_SLOT;
1165 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1166 sym_index);
1168 break;
1169 #elif defined(TCC_TARGET_ARM)
1170 case R_ARM_GOT32:
1171 case R_ARM_GOTOFF:
1172 case R_ARM_GOTPC:
1173 case R_ARM_PLT32:
1174 if (!s1->got)
1175 build_got(s1);
1176 if (type == R_ARM_GOT32 || type == R_ARM_PLT32) {
1177 sym_index = ELFW(R_SYM)(rel->r_info);
1178 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1179 /* look at the symbol got offset. If none, then add one */
1180 if (type == R_ARM_GOT32)
1181 reloc_type = R_ARM_GLOB_DAT;
1182 else
1183 reloc_type = R_ARM_JUMP_SLOT;
1184 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1185 sym_index);
1187 break;
1188 #elif defined(TCC_TARGET_C67)
1189 case R_C60_GOT32:
1190 case R_C60_GOTOFF:
1191 case R_C60_GOTPC:
1192 case R_C60_PLT32:
1193 if (!s1->got)
1194 build_got(s1);
1195 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1196 sym_index = ELFW(R_SYM)(rel->r_info);
1197 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1198 /* look at the symbol got offset. If none, then add one */
1199 if (type == R_C60_GOT32)
1200 reloc_type = R_C60_GLOB_DAT;
1201 else
1202 reloc_type = R_C60_JMP_SLOT;
1203 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1204 sym_index);
1206 break;
1207 #elif defined(TCC_TARGET_X86_64)
1208 case R_X86_64_GOT32:
1209 case R_X86_64_GOTTPOFF:
1210 case R_X86_64_GOTPCREL:
1211 case R_X86_64_PLT32:
1212 if (!s1->got)
1213 build_got(s1);
1214 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1215 type == R_X86_64_PLT32) {
1216 sym_index = ELFW(R_SYM)(rel->r_info);
1217 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1218 /* look at the symbol got offset. If none, then add one */
1219 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1220 reloc_type = R_X86_64_GLOB_DAT;
1221 else
1222 reloc_type = R_X86_64_JUMP_SLOT;
1223 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1224 sym_index);
1226 break;
1227 #else
1228 #error unsupported CPU
1229 #endif
1230 default:
1231 break;
1237 ST_FUNC Section *new_symtab(TCCState *s1,
1238 const char *symtab_name, int sh_type, int sh_flags,
1239 const char *strtab_name,
1240 const char *hash_name, int hash_sh_flags)
1242 Section *symtab, *strtab, *hash;
1243 int *ptr, nb_buckets;
1245 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1246 symtab->sh_entsize = sizeof(ElfW(Sym));
1247 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1248 put_elf_str(strtab, "");
1249 symtab->link = strtab;
1250 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1252 nb_buckets = 1;
1254 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1255 hash->sh_entsize = sizeof(int);
1256 symtab->hash = hash;
1257 hash->link = symtab;
1259 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1260 ptr[0] = nb_buckets;
1261 ptr[1] = 1;
1262 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1263 return symtab;
1266 /* put dynamic tag */
1267 static void put_dt(Section *dynamic, int dt, addr_t val)
1269 ElfW(Dyn) *dyn;
1270 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1271 dyn->d_tag = dt;
1272 dyn->d_un.d_val = val;
1275 static void add_init_array_defines(TCCState *s1, const char *section_name)
1277 Section *s;
1278 long end_offset;
1279 char sym_start[1024];
1280 char sym_end[1024];
1282 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1283 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1285 s = find_section(s1, section_name);
1286 if (!s) {
1287 end_offset = 0;
1288 s = data_section;
1289 } else {
1290 end_offset = s->data_offset;
1293 add_elf_sym(symtab_section,
1294 0, 0,
1295 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1296 s->sh_num, sym_start);
1297 add_elf_sym(symtab_section,
1298 end_offset, 0,
1299 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1300 s->sh_num, sym_end);
1303 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1305 #ifdef CONFIG_TCC_BCHECK
1306 unsigned long *ptr;
1307 Section *init_section;
1308 unsigned char *pinit;
1309 int sym_index;
1311 if (0 == s1->do_bounds_check)
1312 return;
1314 /* XXX: add an object file to do that */
1315 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1316 *ptr = 0;
1317 add_elf_sym(symtab_section, 0, 0,
1318 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1319 bounds_section->sh_num, "__bounds_start");
1320 #ifdef TCC_TARGET_I386
1321 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1322 /* add 'call __bound_init()' in .init section */
1323 init_section = find_section(s1, ".init");
1324 pinit = section_ptr_add(init_section, 5);
1325 pinit[0] = 0xe8;
1326 put32(pinit + 1, -4);
1327 sym_index = find_elf_sym(symtab_section, "__bound_init");
1328 put_elf_reloc(symtab_section, init_section,
1329 init_section->data_offset - 4, R_386_PC32, sym_index);
1331 #endif
1332 #endif
1335 static inline int tcc_add_support(TCCState *s1, const char *filename)
1337 char buf[1024];
1338 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, filename);
1339 return tcc_add_file(s1, buf);
1342 /* add tcc runtime libraries */
1343 ST_FUNC void tcc_add_runtime(TCCState *s1)
1345 tcc_add_bcheck(s1);
1347 /* add libc */
1348 if (!s1->nostdlib) {
1349 tcc_add_library(s1, "c");
1350 #ifdef CONFIG_USE_LIBGCC
1351 if (!s1->static_link)
1352 tcc_add_file(s1, TCC_LIBGCC);
1353 else
1354 tcc_add_support(s1, "libtcc1.a");
1355 #else
1356 tcc_add_support(s1, "libtcc1.a");
1357 #endif
1358 /* add crt end if not memory output */
1359 if (s1->output_type != TCC_OUTPUT_MEMORY)
1360 tcc_add_crt(s1, "crtn.o");
1364 /* add various standard linker symbols (must be done after the
1365 sections are filled (for example after allocating common
1366 symbols)) */
1367 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1369 char buf[1024];
1370 int i;
1371 Section *s;
1373 add_elf_sym(symtab_section,
1374 text_section->data_offset, 0,
1375 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1376 text_section->sh_num, "_etext");
1377 add_elf_sym(symtab_section,
1378 data_section->data_offset, 0,
1379 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1380 data_section->sh_num, "_edata");
1381 add_elf_sym(symtab_section,
1382 bss_section->data_offset, 0,
1383 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1384 bss_section->sh_num, "_end");
1385 /* horrible new standard ldscript defines */
1386 add_init_array_defines(s1, ".preinit_array");
1387 add_init_array_defines(s1, ".init_array");
1388 add_init_array_defines(s1, ".fini_array");
1390 /* add start and stop symbols for sections whose name can be
1391 expressed in C */
1392 for(i = 1; i < s1->nb_sections; i++) {
1393 s = s1->sections[i];
1394 if (s->sh_type == SHT_PROGBITS &&
1395 (s->sh_flags & SHF_ALLOC)) {
1396 const char *p;
1397 int ch;
1399 /* check if section name can be expressed in C */
1400 p = s->name;
1401 for(;;) {
1402 ch = *p;
1403 if (!ch)
1404 break;
1405 if (!isid(ch) && !isnum(ch))
1406 goto next_sec;
1407 p++;
1409 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1410 add_elf_sym(symtab_section,
1411 0, 0,
1412 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1413 s->sh_num, buf);
1414 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1415 add_elf_sym(symtab_section,
1416 s->data_offset, 0,
1417 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1418 s->sh_num, buf);
1420 next_sec: ;
1424 static void tcc_output_binary(TCCState *s1, FILE *f,
1425 const int *section_order)
1427 Section *s;
1428 int i, offset, size;
1430 offset = 0;
1431 for(i=1;i<s1->nb_sections;i++) {
1432 s = s1->sections[section_order[i]];
1433 if (s->sh_type != SHT_NOBITS &&
1434 (s->sh_flags & SHF_ALLOC)) {
1435 while (offset < s->sh_offset) {
1436 fputc(0, f);
1437 offset++;
1439 size = s->sh_size;
1440 fwrite(s->data, 1, size, f);
1441 offset += size;
1446 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1447 #define HAVE_PHDR 1
1448 #define EXTRA_RELITEMS 14
1450 /* move the relocation value from .dynsym to .got */
1451 void patch_dynsym_undef(TCCState *s1, Section *s)
1453 uint32_t *gotd = (void *)s1->got->data;
1454 ElfW(Sym) *sym;
1456 gotd += 3; /* dummy entries in .got */
1457 /* relocate symbols in .dynsym */
1458 for_each_elem(s, 1, sym, ElfW(Sym)) {
1459 if (sym->st_shndx == SHN_UNDEF) {
1460 *gotd++ = sym->st_value + 6; /* XXX 6 is magic ? */
1461 sym->st_value = 0;
1465 #else
1466 #define HAVE_PHDR 0
1467 #define EXTRA_RELITEMS 9
1469 /* zero plt offsets of weak symbols in .dynsym */
1470 void patch_dynsym_undef(TCCState *s1, Section *s)
1472 ElfW(Sym) *sym;
1474 for_each_elem(s, 1, sym, ElfW(Sym))
1475 if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
1476 sym->st_value = 0;
1478 #endif
1480 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1482 int sym_index = ELFW(R_SYM) (rel->r_info);
1483 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1484 unsigned long offset;
1486 if (sym_index >= s1->nb_sym_attrs)
1487 return;
1488 offset = s1->sym_attrs[sym_index].got_offset;
1489 section_reserve(s1->got, offset + PTR_SIZE);
1490 #ifdef TCC_TARGET_X86_64
1491 /* only works for x86-64 */
1492 put32(s1->got->data + offset + 4, sym->st_value >> 32);
1493 #endif
1494 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1497 ST_FUNC void fill_got(TCCState *s1)
1499 Section *s;
1500 ElfW_Rel *rel;
1501 int i;
1503 for(i = 1; i < s1->nb_sections; i++) {
1504 s = s1->sections[i];
1505 if (s->sh_type != SHT_RELX)
1506 continue;
1507 /* no need to handle got relocations */
1508 if (s->link != symtab_section)
1509 continue;
1510 for_each_elem(s, 0, rel, ElfW_Rel) {
1511 switch (ELFW(R_TYPE) (rel->r_info)) {
1512 case R_X86_64_GOT32:
1513 case R_X86_64_GOTPCREL:
1514 case R_X86_64_PLT32:
1515 fill_got_entry(s1, rel);
1516 break;
1523 /* output an ELF file */
1524 /* XXX: suppress unneeded sections */
1525 static int elf_output_file(TCCState *s1, const char *filename)
1527 ElfW(Ehdr) ehdr;
1528 FILE *f;
1529 int fd, mode, ret;
1530 int *section_order;
1531 int shnum, i, phnum, file_offset, offset, size, j, sh_order_index, k;
1532 long long tmp;
1533 addr_t addr;
1534 Section *strsec, *s;
1535 ElfW(Shdr) shdr, *sh;
1536 ElfW(Phdr) *phdr, *ph;
1537 Section *interp, *dynamic, *dynstr;
1538 unsigned long saved_dynamic_data_offset;
1539 ElfW(Sym) *sym;
1540 int type, file_type;
1541 addr_t rel_addr, rel_size;
1542 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1543 addr_t bss_addr, bss_size;
1544 #endif
1546 file_type = s1->output_type;
1547 s1->nb_errors = 0;
1549 if (file_type != TCC_OUTPUT_OBJ) {
1550 tcc_add_runtime(s1);
1553 phdr = NULL;
1554 section_order = NULL;
1555 interp = NULL;
1556 dynamic = NULL;
1557 dynstr = NULL; /* avoid warning */
1558 saved_dynamic_data_offset = 0; /* avoid warning */
1560 if (file_type != TCC_OUTPUT_OBJ) {
1561 relocate_common_syms();
1563 tcc_add_linker_symbols(s1);
1565 if (!s1->static_link) {
1566 const char *name;
1567 int sym_index, index;
1568 ElfW(Sym) *esym;
1570 if (file_type == TCC_OUTPUT_EXE) {
1571 char *ptr;
1572 /* allow override the dynamic loader */
1573 const char *elfint = getenv("LD_SO");
1574 if (elfint == NULL)
1575 elfint = DEFAULT_ELFINTERP(s1);
1576 /* add interpreter section only if executable */
1577 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1578 interp->sh_addralign = 1;
1579 ptr = section_ptr_add(interp, 1+strlen(elfint));
1580 strcpy(ptr, elfint);
1583 /* add dynamic symbol table */
1584 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1585 ".dynstr",
1586 ".hash", SHF_ALLOC);
1587 dynstr = s1->dynsym->link;
1589 /* add dynamic section */
1590 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1591 SHF_ALLOC | SHF_WRITE);
1592 dynamic->link = dynstr;
1593 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1595 /* add PLT */
1596 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1597 SHF_ALLOC | SHF_EXECINSTR);
1598 s1->plt->sh_entsize = 4;
1600 build_got(s1);
1602 /* scan for undefined symbols and see if they are in the
1603 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1604 is found, then we add it in the PLT. If a symbol
1605 STT_OBJECT is found, we add it in the .bss section with
1606 a suitable relocation */
1607 if (file_type == TCC_OUTPUT_EXE) {
1608 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
1609 if (sym->st_shndx == SHN_UNDEF) {
1610 name = symtab_section->link->data + sym->st_name;
1611 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1612 if (sym_index) {
1613 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1614 type = ELFW(ST_TYPE)(esym->st_info);
1615 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1616 /* Indirect functions shall have STT_FUNC type
1617 * in executable dynsym section. Indeed, a dlsym
1618 * call following a lazy resolution would pick
1619 * the symbol value from the executable dynsym
1620 * entry which would contain the address of the
1621 * function wanted by the caller of dlsym
1622 * instead of the address of the function that
1623 * would return that address */
1624 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1625 ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC),
1626 sym - (ElfW(Sym) *)symtab_section->data);
1627 } else if (type == STT_OBJECT) {
1628 unsigned long offset;
1629 ElfW(Sym) *dynsym;
1630 offset = bss_section->data_offset;
1631 /* XXX: which alignment ? */
1632 offset = (offset + 16 - 1) & -16;
1633 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1634 esym->st_info, 0,
1635 bss_section->sh_num, name);
1636 /* Ensure R_COPY works for weak symbol aliases */
1637 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1638 for_each_elem(s1->dynsymtab_section, 1, dynsym, ElfW(Sym)) {
1639 if ((dynsym->st_value == esym->st_value)
1640 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1641 char *dynname;
1642 dynname = s1->dynsymtab_section->link->data
1643 + dynsym->st_name;
1644 put_elf_sym(s1->dynsym, offset,
1645 dynsym->st_size,
1646 dynsym->st_info, 0,
1647 bss_section->sh_num,
1648 dynname);
1649 break;
1653 put_elf_reloc(s1->dynsym, bss_section,
1654 offset, R_COPY, index);
1655 offset += esym->st_size;
1656 bss_section->data_offset = offset;
1658 } else {
1659 /* STB_WEAK undefined symbols are accepted */
1660 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1661 it */
1662 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1663 !strcmp(name, "_fp_hw")) {
1664 } else {
1665 tcc_error_noabort("undefined symbol '%s'", name);
1668 } else if (s1->rdynamic &&
1669 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1670 /* if -rdynamic option, then export all non
1671 local symbols */
1672 name = symtab_section->link->data + sym->st_name;
1673 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1674 sym->st_info, 0,
1675 sym->st_shndx, name);
1679 if (s1->nb_errors)
1680 goto fail;
1682 /* now look at unresolved dynamic symbols and export
1683 corresponding symbol */
1684 for_each_elem(s1->dynsymtab_section, 1, esym, ElfW(Sym)) {
1685 if (esym->st_shndx == SHN_UNDEF) {
1686 name = s1->dynsymtab_section->link->data + esym->st_name;
1687 sym_index = find_elf_sym(symtab_section, name);
1688 if (sym_index) {
1689 /* XXX: avoid adding a symbol if already
1690 present because of -rdynamic ? */
1691 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1692 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1693 sym->st_info, 0,
1694 sym->st_shndx, name);
1695 } else {
1696 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1697 /* weak symbols can stay undefined */
1698 } else {
1699 tcc_warning("undefined dynamic symbol '%s'", name);
1704 } else {
1705 int nb_syms;
1706 /* shared library case : we simply export all the global symbols */
1707 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1708 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1709 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
1710 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1711 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1712 if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
1713 ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
1714 && sym->st_shndx == SHN_UNDEF) {
1715 int visibility = ELFW(ST_BIND)(sym->st_info);
1716 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1717 ELFW(ST_INFO)(visibility,STT_FUNC),
1718 sym - (ElfW(Sym) *)symtab_section->data);
1720 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1721 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1722 sym->st_info,
1723 sym - (ElfW(Sym) *)symtab_section->data);
1725 else
1726 #endif
1728 name = symtab_section->link->data + sym->st_name;
1729 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1730 sym->st_info, 0,
1731 sym->st_shndx, name);
1732 s1->symtab_to_dynsym[sym -
1733 (ElfW(Sym) *)symtab_section->data] =
1734 index;
1740 build_got_entries(s1);
1742 /* add a list of needed dlls */
1743 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1744 DLLReference *dllref = s1->loaded_dlls[i];
1745 if (dllref->level == 0)
1746 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1749 if (s1->rpath)
1750 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1752 /* XXX: currently, since we do not handle PIC code, we
1753 must relocate the readonly segments */
1754 if (file_type == TCC_OUTPUT_DLL) {
1755 if (s1->soname)
1756 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1757 put_dt(dynamic, DT_TEXTREL, 0);
1760 if (s1->symbolic)
1761 put_dt(dynamic, DT_SYMBOLIC, 0);
1763 /* add necessary space for other entries */
1764 saved_dynamic_data_offset = dynamic->data_offset;
1765 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1766 } else {
1767 /* still need to build got entries in case of static link */
1768 build_got_entries(s1);
1772 memset(&ehdr, 0, sizeof(ehdr));
1774 /* we add a section for symbols */
1775 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1776 put_elf_str(strsec, "");
1778 /* compute number of sections */
1779 shnum = s1->nb_sections;
1781 /* this array is used to reorder sections in the output file */
1782 section_order = tcc_malloc(sizeof(int) * shnum);
1783 section_order[0] = 0;
1784 sh_order_index = 1;
1786 /* compute number of program headers */
1787 switch(file_type) {
1788 default:
1789 case TCC_OUTPUT_OBJ:
1790 phnum = 0;
1791 break;
1792 case TCC_OUTPUT_EXE:
1793 if (!s1->static_link)
1794 phnum = 4 + HAVE_PHDR;
1795 else
1796 phnum = 2;
1797 break;
1798 case TCC_OUTPUT_DLL:
1799 phnum = 3;
1800 break;
1803 /* allocate strings for section names and decide if an unallocated
1804 section should be output */
1805 /* NOTE: the strsec section comes last, so its size is also
1806 correct ! */
1807 for(i = 1; i < s1->nb_sections; i++) {
1808 s = s1->sections[i];
1809 s->sh_name = put_elf_str(strsec, s->name);
1810 /* when generating a DLL, we include relocations but we may
1811 patch them */
1812 if (file_type == TCC_OUTPUT_DLL &&
1813 s->sh_type == SHT_RELX &&
1814 !(s->sh_flags & SHF_ALLOC)) {
1815 /* gr: avoid bogus relocs for empty (debug) sections */
1816 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1817 prepare_dynamic_rel(s1, s);
1818 else if (s1->do_debug)
1819 s->sh_size = s->data_offset;
1820 } else if (s1->do_debug ||
1821 file_type == TCC_OUTPUT_OBJ ||
1822 (s->sh_flags & SHF_ALLOC) ||
1823 i == (s1->nb_sections - 1)) {
1824 /* we output all sections if debug or object file */
1825 s->sh_size = s->data_offset;
1829 /* allocate program segment headers */
1830 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1832 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1833 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1834 } else {
1835 file_offset = 0;
1837 if (phnum > 0) {
1838 /* compute section to program header mapping */
1839 if (s1->has_text_addr) {
1840 int a_offset, p_offset;
1841 addr = s1->text_addr;
1842 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1843 ELF_PAGE_SIZE */
1844 a_offset = (int) (addr & (s1->section_align - 1));
1845 p_offset = file_offset & (s1->section_align - 1);
1846 if (a_offset < p_offset)
1847 a_offset += s1->section_align;
1848 file_offset += (a_offset - p_offset);
1849 } else {
1850 if (file_type == TCC_OUTPUT_DLL)
1851 addr = 0;
1852 else
1853 addr = ELF_START_ADDR;
1854 /* compute address after headers */
1855 addr += (file_offset & (s1->section_align - 1));
1858 /* dynamic relocation table information, for .dynamic section */
1859 rel_size = 0;
1860 rel_addr = 0;
1862 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1863 bss_addr = bss_size = 0;
1864 #endif
1865 /* leave one program header for the program interpreter */
1866 ph = &phdr[0];
1867 if (interp)
1868 ph += 1 + HAVE_PHDR;
1870 for(j = 0; j < 2; j++) {
1871 ph->p_type = PT_LOAD;
1872 if (j == 0)
1873 ph->p_flags = PF_R | PF_X;
1874 else
1875 ph->p_flags = PF_R | PF_W;
1876 ph->p_align = s1->section_align;
1878 /* we do the following ordering: interp, symbol tables,
1879 relocations, progbits, nobits */
1880 /* XXX: do faster and simpler sorting */
1881 for(k = 0; k < 5; k++) {
1882 for(i = 1; i < s1->nb_sections; i++) {
1883 s = s1->sections[i];
1884 /* compute if section should be included */
1885 if (j == 0) {
1886 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1887 SHF_ALLOC)
1888 continue;
1889 } else {
1890 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1891 (SHF_ALLOC | SHF_WRITE))
1892 continue;
1894 if (s == interp) {
1895 if (k != 0)
1896 continue;
1897 } else if (s->sh_type == SHT_DYNSYM ||
1898 s->sh_type == SHT_STRTAB ||
1899 s->sh_type == SHT_HASH) {
1900 if (k != 1)
1901 continue;
1902 } else if (s->sh_type == SHT_RELX) {
1903 if (k != 2)
1904 continue;
1905 } else if (s->sh_type == SHT_NOBITS) {
1906 if (k != 4)
1907 continue;
1908 } else {
1909 if (k != 3)
1910 continue;
1912 section_order[sh_order_index++] = i;
1914 /* section matches: we align it and add its size */
1915 tmp = addr;
1916 addr = (addr + s->sh_addralign - 1) &
1917 ~(s->sh_addralign - 1);
1918 file_offset += (int) ( addr - tmp );
1919 s->sh_offset = file_offset;
1920 s->sh_addr = addr;
1922 /* update program header infos */
1923 if (ph->p_offset == 0) {
1924 ph->p_offset = file_offset;
1925 ph->p_vaddr = addr;
1926 ph->p_paddr = ph->p_vaddr;
1928 /* update dynamic relocation infos */
1929 if (s->sh_type == SHT_RELX) {
1930 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1931 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) {
1932 rel_addr = addr;
1933 rel_size += s->sh_size; /* XXX only first rel. */
1935 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) {
1936 bss_addr = addr;
1937 bss_size = s->sh_size; /* XXX only first rel. */
1939 #else
1940 if (rel_size == 0)
1941 rel_addr = addr;
1942 rel_size += s->sh_size;
1943 #endif
1945 addr += s->sh_size;
1946 if (s->sh_type != SHT_NOBITS)
1947 file_offset += s->sh_size;
1950 ph->p_filesz = file_offset - ph->p_offset;
1951 ph->p_memsz = addr - ph->p_vaddr;
1952 ph++;
1953 if (j == 0) {
1954 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1955 /* if in the middle of a page, we duplicate the page in
1956 memory so that one copy is RX and the other is RW */
1957 if ((addr & (s1->section_align - 1)) != 0)
1958 addr += s1->section_align;
1959 } else {
1960 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1961 file_offset = (file_offset + s1->section_align - 1) &
1962 ~(s1->section_align - 1);
1967 /* if interpreter, then add corresponing program header */
1968 if (interp) {
1969 ph = &phdr[0];
1971 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1973 int len = phnum * sizeof(ElfW(Phdr));
1975 ph->p_type = PT_PHDR;
1976 ph->p_offset = sizeof(ElfW(Ehdr));
1977 ph->p_vaddr = interp->sh_addr - len;
1978 ph->p_paddr = ph->p_vaddr;
1979 ph->p_filesz = ph->p_memsz = len;
1980 ph->p_flags = PF_R | PF_X;
1981 ph->p_align = 4; /* interp->sh_addralign; */
1982 ph++;
1984 #endif
1986 ph->p_type = PT_INTERP;
1987 ph->p_offset = interp->sh_offset;
1988 ph->p_vaddr = interp->sh_addr;
1989 ph->p_paddr = ph->p_vaddr;
1990 ph->p_filesz = interp->sh_size;
1991 ph->p_memsz = interp->sh_size;
1992 ph->p_flags = PF_R;
1993 ph->p_align = interp->sh_addralign;
1996 /* if dynamic section, then add corresponing program header */
1997 if (dynamic) {
1998 ph = &phdr[phnum - 1];
2000 ph->p_type = PT_DYNAMIC;
2001 ph->p_offset = dynamic->sh_offset;
2002 ph->p_vaddr = dynamic->sh_addr;
2003 ph->p_paddr = ph->p_vaddr;
2004 ph->p_filesz = dynamic->sh_size;
2005 ph->p_memsz = dynamic->sh_size;
2006 ph->p_flags = PF_R | PF_W;
2007 ph->p_align = dynamic->sh_addralign;
2009 /* put GOT dynamic section address */
2010 put32(s1->got->data, dynamic->sh_addr);
2012 /* relocate the PLT */
2013 if (file_type == TCC_OUTPUT_EXE
2014 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2015 || file_type == TCC_OUTPUT_DLL
2016 #endif
2018 uint8_t *p, *p_end;
2020 p = s1->plt->data;
2021 p_end = p + s1->plt->data_offset;
2022 if (p < p_end) {
2023 #if defined(TCC_TARGET_I386)
2024 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2025 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
2026 p += 16;
2027 while (p < p_end) {
2028 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2029 p += 16;
2031 #elif defined(TCC_TARGET_X86_64)
2032 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
2033 put32(p + 2, get32(p + 2) + x);
2034 put32(p + 8, get32(p + 8) + x - 6);
2035 p += 16;
2036 while (p < p_end) {
2037 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
2038 p += 16;
2040 #elif defined(TCC_TARGET_ARM)
2041 int x;
2042 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
2043 p += 16;
2044 while (p < p_end) {
2045 if (get32(p) == 0x46c04778) /* PLT Thumb stub present */
2046 p += 4;
2047 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
2048 p += 16;
2050 #elif defined(TCC_TARGET_C67)
2051 /* XXX: TODO */
2052 #else
2053 #error unsupported CPU
2054 #endif
2058 /* relocate symbols in .dynsym */
2059 for_each_elem(s1->dynsym, 1, sym, ElfW(Sym)) {
2060 if (sym->st_shndx == SHN_UNDEF) {
2061 /* relocate to the PLT if the symbol corresponds
2062 to a PLT entry */
2063 if (sym->st_value)
2064 sym->st_value += s1->plt->sh_addr;
2065 } else if (sym->st_shndx < SHN_LORESERVE) {
2066 /* do symbol relocation */
2067 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
2071 /* put dynamic section entries */
2072 dynamic->data_offset = saved_dynamic_data_offset;
2073 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
2074 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
2075 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2076 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
2077 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2078 #ifdef TCC_TARGET_X86_64
2079 put_dt(dynamic, DT_RELA, rel_addr);
2080 put_dt(dynamic, DT_RELASZ, rel_size);
2081 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2082 #else
2083 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2084 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2085 put_dt(dynamic, DT_PLTRELSZ, rel_size);
2086 put_dt(dynamic, DT_JMPREL, rel_addr);
2087 put_dt(dynamic, DT_PLTREL, DT_REL);
2088 put_dt(dynamic, DT_REL, bss_addr);
2089 put_dt(dynamic, DT_RELSZ, bss_size);
2090 #else
2091 put_dt(dynamic, DT_REL, rel_addr);
2092 put_dt(dynamic, DT_RELSZ, rel_size);
2093 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2094 #endif
2095 #endif
2096 if (s1->do_debug)
2097 put_dt(dynamic, DT_DEBUG, 0);
2098 put_dt(dynamic, DT_NULL, 0);
2101 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2102 ehdr.e_phnum = phnum;
2103 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2106 /* all other sections come after */
2107 for(i = 1; i < s1->nb_sections; i++) {
2108 s = s1->sections[i];
2109 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2110 continue;
2111 section_order[sh_order_index++] = i;
2113 file_offset = (file_offset + s->sh_addralign - 1) &
2114 ~(s->sh_addralign - 1);
2115 s->sh_offset = file_offset;
2116 if (s->sh_type != SHT_NOBITS)
2117 file_offset += s->sh_size;
2120 /* if building executable or DLL, then relocate each section
2121 except the GOT which is already relocated */
2122 if (file_type != TCC_OUTPUT_OBJ) {
2123 relocate_syms(s1, 0);
2125 if (s1->nb_errors != 0) {
2126 fail:
2127 ret = -1;
2128 goto the_end;
2131 /* relocate sections */
2132 /* XXX: ignore sections with allocated relocations ? */
2133 for(i = 1; i < s1->nb_sections; i++) {
2134 s = s1->sections[i];
2135 if (s->reloc && s != s1->got)
2136 relocate_section(s1, s);
2139 /* relocate relocation entries if the relocation tables are
2140 allocated in the executable */
2141 for(i = 1; i < s1->nb_sections; i++) {
2142 s = s1->sections[i];
2143 if ((s->sh_flags & SHF_ALLOC) &&
2144 s->sh_type == SHT_RELX) {
2145 relocate_rel(s1, s);
2149 /* get entry point address */
2150 if (file_type == TCC_OUTPUT_EXE)
2151 ehdr.e_entry = get_elf_sym_addr(s1, "_start", 1);
2152 else
2153 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2155 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2156 fill_got(s1);
2158 /* write elf file */
2159 if (file_type == TCC_OUTPUT_OBJ)
2160 mode = 0666;
2161 else
2162 mode = 0777;
2163 unlink(filename);
2164 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2165 if (fd < 0) {
2166 tcc_error_noabort("could not write '%s'", filename);
2167 goto fail;
2169 f = fdopen(fd, "wb");
2170 if (s1->verbose)
2171 printf("<- %s\n", filename);
2173 #ifdef TCC_TARGET_COFF
2174 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2175 tcc_output_coff(s1, f);
2176 } else
2177 #endif
2178 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2179 sort_syms(s1, symtab_section);
2181 /* align to 4 */
2182 file_offset = (file_offset + 3) & -4;
2184 /* fill header */
2185 ehdr.e_ident[0] = ELFMAG0;
2186 ehdr.e_ident[1] = ELFMAG1;
2187 ehdr.e_ident[2] = ELFMAG2;
2188 ehdr.e_ident[3] = ELFMAG3;
2189 ehdr.e_ident[4] = ELFCLASSW;
2190 ehdr.e_ident[5] = ELFDATA2LSB;
2191 ehdr.e_ident[6] = EV_CURRENT;
2192 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2193 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2194 #endif
2195 #ifdef TCC_TARGET_ARM
2196 #ifdef TCC_ARM_EABI
2197 ehdr.e_ident[EI_OSABI] = 0;
2198 ehdr.e_flags = EF_ARM_EABI_VER4;
2199 if (file_type == TCC_OUTPUT_EXE || file_type == TCC_OUTPUT_DLL)
2200 ehdr.e_flags |= EF_ARM_HASENTRY;
2201 if (s1->float_abi == ARM_HARD_FLOAT)
2202 ehdr.e_flags |= EF_ARM_VFP_FLOAT;
2203 else
2204 ehdr.e_flags |= EF_ARM_SOFT_FLOAT;
2205 #else
2206 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2207 #endif
2208 #endif
2209 switch(file_type) {
2210 default:
2211 case TCC_OUTPUT_EXE:
2212 ehdr.e_type = ET_EXEC;
2213 break;
2214 case TCC_OUTPUT_DLL:
2215 ehdr.e_type = ET_DYN;
2216 break;
2217 case TCC_OUTPUT_OBJ:
2218 ehdr.e_type = ET_REL;
2219 break;
2221 ehdr.e_machine = EM_TCC_TARGET;
2222 ehdr.e_version = EV_CURRENT;
2223 ehdr.e_shoff = file_offset;
2224 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2225 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2226 ehdr.e_shnum = shnum;
2227 ehdr.e_shstrndx = shnum - 1;
2229 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2230 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2231 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2233 for(i=1;i<s1->nb_sections;i++) {
2234 s = s1->sections[section_order[i]];
2235 if (s->sh_type != SHT_NOBITS) {
2236 if (s->sh_type == SHT_DYNSYM)
2237 patch_dynsym_undef(s1, s);
2238 while (offset < s->sh_offset) {
2239 fputc(0, f);
2240 offset++;
2242 size = s->sh_size;
2243 fwrite(s->data, 1, size, f);
2244 offset += size;
2248 /* output section headers */
2249 while (offset < ehdr.e_shoff) {
2250 fputc(0, f);
2251 offset++;
2254 for(i=0;i<s1->nb_sections;i++) {
2255 sh = &shdr;
2256 memset(sh, 0, sizeof(ElfW(Shdr)));
2257 s = s1->sections[i];
2258 if (s) {
2259 sh->sh_name = s->sh_name;
2260 sh->sh_type = s->sh_type;
2261 sh->sh_flags = s->sh_flags;
2262 sh->sh_entsize = s->sh_entsize;
2263 sh->sh_info = s->sh_info;
2264 if (s->link)
2265 sh->sh_link = s->link->sh_num;
2266 sh->sh_addralign = s->sh_addralign;
2267 sh->sh_addr = s->sh_addr;
2268 sh->sh_offset = s->sh_offset;
2269 sh->sh_size = s->sh_size;
2271 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2273 } else {
2274 tcc_output_binary(s1, f, section_order);
2276 fclose(f);
2278 ret = 0;
2279 the_end:
2280 tcc_free(s1->symtab_to_dynsym);
2281 tcc_free(section_order);
2282 tcc_free(phdr);
2283 tcc_free(s1->sym_attrs);
2284 return ret;
2287 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2289 int ret;
2290 #ifdef TCC_TARGET_PE
2291 if (s->output_type != TCC_OUTPUT_OBJ) {
2292 ret = pe_output_file(s, filename);
2293 } else
2294 #endif
2296 ret = elf_output_file(s, filename);
2298 return ret;
2301 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2303 void *data;
2305 data = tcc_malloc(size);
2306 lseek(fd, file_offset, SEEK_SET);
2307 read(fd, data, size);
2308 return data;
2311 typedef struct SectionMergeInfo {
2312 Section *s; /* corresponding existing section */
2313 unsigned long offset; /* offset of the new section in the existing section */
2314 uint8_t new_section; /* true if section 's' was added */
2315 uint8_t link_once; /* true if link once section */
2316 } SectionMergeInfo;
2318 /* load an object file and merge it with current files */
2319 /* XXX: handle correctly stab (debug) info */
2320 ST_FUNC int tcc_load_object_file(TCCState *s1,
2321 int fd, unsigned long file_offset)
2323 ElfW(Ehdr) ehdr;
2324 ElfW(Shdr) *shdr, *sh;
2325 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2326 unsigned char *strsec, *strtab;
2327 int *old_to_new_syms;
2328 char *sh_name, *name;
2329 SectionMergeInfo *sm_table, *sm;
2330 ElfW(Sym) *sym, *symtab;
2331 ElfW_Rel *rel;
2332 Section *s;
2334 int stab_index;
2335 int stabstr_index;
2337 stab_index = stabstr_index = 0;
2339 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2340 goto fail1;
2341 if (ehdr.e_ident[0] != ELFMAG0 ||
2342 ehdr.e_ident[1] != ELFMAG1 ||
2343 ehdr.e_ident[2] != ELFMAG2 ||
2344 ehdr.e_ident[3] != ELFMAG3)
2345 goto fail1;
2346 /* test if object file */
2347 if (ehdr.e_type != ET_REL)
2348 goto fail1;
2349 /* test CPU specific stuff */
2350 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2351 ehdr.e_machine != EM_TCC_TARGET) {
2352 fail1:
2353 tcc_error_noabort("invalid object file");
2354 return -1;
2356 /* read sections */
2357 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2358 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2359 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2361 /* load section names */
2362 sh = &shdr[ehdr.e_shstrndx];
2363 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2365 /* load symtab and strtab */
2366 old_to_new_syms = NULL;
2367 symtab = NULL;
2368 strtab = NULL;
2369 nb_syms = 0;
2370 for(i = 1; i < ehdr.e_shnum; i++) {
2371 sh = &shdr[i];
2372 if (sh->sh_type == SHT_SYMTAB) {
2373 if (symtab) {
2374 tcc_error_noabort("object must contain only one symtab");
2375 fail:
2376 ret = -1;
2377 goto the_end;
2379 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2380 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2381 sm_table[i].s = symtab_section;
2383 /* now load strtab */
2384 sh = &shdr[sh->sh_link];
2385 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2389 /* now examine each section and try to merge its content with the
2390 ones in memory */
2391 for(i = 1; i < ehdr.e_shnum; i++) {
2392 /* no need to examine section name strtab */
2393 if (i == ehdr.e_shstrndx)
2394 continue;
2395 sh = &shdr[i];
2396 sh_name = strsec + sh->sh_name;
2397 /* ignore sections types we do not handle */
2398 if (sh->sh_type != SHT_PROGBITS &&
2399 sh->sh_type != SHT_RELX &&
2400 #ifdef TCC_ARM_EABI
2401 sh->sh_type != SHT_ARM_EXIDX &&
2402 #endif
2403 sh->sh_type != SHT_NOBITS &&
2404 sh->sh_type != SHT_PREINIT_ARRAY &&
2405 sh->sh_type != SHT_INIT_ARRAY &&
2406 sh->sh_type != SHT_FINI_ARRAY &&
2407 strcmp(sh_name, ".stabstr")
2409 continue;
2410 if (sh->sh_addralign < 1)
2411 sh->sh_addralign = 1;
2412 /* find corresponding section, if any */
2413 for(j = 1; j < s1->nb_sections;j++) {
2414 s = s1->sections[j];
2415 if (!strcmp(s->name, sh_name)) {
2416 if (!strncmp(sh_name, ".gnu.linkonce",
2417 sizeof(".gnu.linkonce") - 1)) {
2418 /* if a 'linkonce' section is already present, we
2419 do not add it again. It is a little tricky as
2420 symbols can still be defined in
2421 it. */
2422 sm_table[i].link_once = 1;
2423 goto next;
2424 } else {
2425 goto found;
2429 /* not found: create new section */
2430 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2431 /* take as much info as possible from the section. sh_link and
2432 sh_info will be updated later */
2433 s->sh_addralign = sh->sh_addralign;
2434 s->sh_entsize = sh->sh_entsize;
2435 sm_table[i].new_section = 1;
2436 found:
2437 if (sh->sh_type != s->sh_type) {
2438 tcc_error_noabort("invalid section type");
2439 goto fail;
2442 /* align start of section */
2443 offset = s->data_offset;
2445 if (0 == strcmp(sh_name, ".stab")) {
2446 stab_index = i;
2447 goto no_align;
2449 if (0 == strcmp(sh_name, ".stabstr")) {
2450 stabstr_index = i;
2451 goto no_align;
2454 size = sh->sh_addralign - 1;
2455 offset = (offset + size) & ~size;
2456 if (sh->sh_addralign > s->sh_addralign)
2457 s->sh_addralign = sh->sh_addralign;
2458 s->data_offset = offset;
2459 no_align:
2460 sm_table[i].offset = offset;
2461 sm_table[i].s = s;
2462 /* concatenate sections */
2463 size = sh->sh_size;
2464 if (sh->sh_type != SHT_NOBITS) {
2465 unsigned char *ptr;
2466 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2467 ptr = section_ptr_add(s, size);
2468 read(fd, ptr, size);
2469 } else {
2470 s->data_offset += size;
2472 next: ;
2475 /* gr relocate stab strings */
2476 if (stab_index && stabstr_index) {
2477 Stab_Sym *a, *b;
2478 unsigned o;
2479 s = sm_table[stab_index].s;
2480 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2481 b = (Stab_Sym *)(s->data + s->data_offset);
2482 o = sm_table[stabstr_index].offset;
2483 while (a < b)
2484 a->n_strx += o, a++;
2487 /* second short pass to update sh_link and sh_info fields of new
2488 sections */
2489 for(i = 1; i < ehdr.e_shnum; i++) {
2490 s = sm_table[i].s;
2491 if (!s || !sm_table[i].new_section)
2492 continue;
2493 sh = &shdr[i];
2494 if (sh->sh_link > 0)
2495 s->link = sm_table[sh->sh_link].s;
2496 if (sh->sh_type == SHT_RELX) {
2497 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2498 /* update backward link */
2499 s1->sections[s->sh_info]->reloc = s;
2502 sm = sm_table;
2504 /* resolve symbols */
2505 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2507 sym = symtab + 1;
2508 for(i = 1; i < nb_syms; i++, sym++) {
2509 if (sym->st_shndx != SHN_UNDEF &&
2510 sym->st_shndx < SHN_LORESERVE) {
2511 sm = &sm_table[sym->st_shndx];
2512 if (sm->link_once) {
2513 /* if a symbol is in a link once section, we use the
2514 already defined symbol. It is very important to get
2515 correct relocations */
2516 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2517 name = strtab + sym->st_name;
2518 sym_index = find_elf_sym(symtab_section, name);
2519 if (sym_index)
2520 old_to_new_syms[i] = sym_index;
2522 continue;
2524 /* if no corresponding section added, no need to add symbol */
2525 if (!sm->s)
2526 continue;
2527 /* convert section number */
2528 sym->st_shndx = sm->s->sh_num;
2529 /* offset value */
2530 sym->st_value += sm->offset;
2532 /* add symbol */
2533 name = strtab + sym->st_name;
2534 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2535 sym->st_info, sym->st_other,
2536 sym->st_shndx, name);
2537 old_to_new_syms[i] = sym_index;
2540 /* third pass to patch relocation entries */
2541 for(i = 1; i < ehdr.e_shnum; i++) {
2542 s = sm_table[i].s;
2543 if (!s)
2544 continue;
2545 sh = &shdr[i];
2546 offset = sm_table[i].offset;
2547 switch(s->sh_type) {
2548 case SHT_RELX:
2549 /* take relocation offset information */
2550 offseti = sm_table[sh->sh_info].offset;
2551 for_each_elem(s, (offset / sizeof(*rel)), rel, ElfW_Rel) {
2552 int type;
2553 unsigned sym_index;
2554 /* convert symbol index */
2555 type = ELFW(R_TYPE)(rel->r_info);
2556 sym_index = ELFW(R_SYM)(rel->r_info);
2557 /* NOTE: only one symtab assumed */
2558 if (sym_index >= nb_syms)
2559 goto invalid_reloc;
2560 sym_index = old_to_new_syms[sym_index];
2561 /* ignore link_once in rel section. */
2562 if (!sym_index && !sm->link_once
2563 #ifdef TCC_TARGET_ARM
2564 && type != R_ARM_V4BX
2565 #endif
2567 invalid_reloc:
2568 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2569 i, strsec + sh->sh_name, rel->r_offset);
2570 goto fail;
2572 rel->r_info = ELFW(R_INFO)(sym_index, type);
2573 /* offset the relocation offset */
2574 rel->r_offset += offseti;
2575 #ifdef TCC_TARGET_ARM
2576 /* Jumps and branches from a Thumb code to a PLT entry need
2577 special handling since PLT entries are ARM code.
2578 Unconditional bl instructions referencing PLT entries are
2579 handled by converting these instructions into blx
2580 instructions. Other case of instructions referencing a PLT
2581 entry require to add a Thumb stub before the PLT entry to
2582 switch to ARM mode. We set bit 0 of the got offset of a
2583 symbol to indicate such a case. */
2584 if (type == R_ARM_THM_JUMP24)
2585 alloc_sym_attr(s1, sym_index)->plt_thumb_stub = 1;
2586 #endif
2588 break;
2589 default:
2590 break;
2594 ret = 0;
2595 the_end:
2596 tcc_free(symtab);
2597 tcc_free(strtab);
2598 tcc_free(old_to_new_syms);
2599 tcc_free(sm_table);
2600 tcc_free(strsec);
2601 tcc_free(shdr);
2602 return ret;
2605 typedef struct ArchiveHeader {
2606 char ar_name[16]; /* name of this member */
2607 char ar_date[12]; /* file mtime */
2608 char ar_uid[6]; /* owner uid; printed as decimal */
2609 char ar_gid[6]; /* owner gid; printed as decimal */
2610 char ar_mode[8]; /* file mode, printed as octal */
2611 char ar_size[10]; /* file size, printed as decimal */
2612 char ar_fmag[2]; /* should contain ARFMAG */
2613 } ArchiveHeader;
2615 static int get_be32(const uint8_t *b)
2617 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2620 /* load only the objects which resolve undefined symbols */
2621 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2623 int i, bound, nsyms, sym_index, off, ret;
2624 uint8_t *data;
2625 const char *ar_names, *p;
2626 const uint8_t *ar_index;
2627 ElfW(Sym) *sym;
2629 data = tcc_malloc(size);
2630 if (read(fd, data, size) != size)
2631 goto fail;
2632 nsyms = get_be32(data);
2633 ar_index = data + 4;
2634 ar_names = ar_index + nsyms * 4;
2636 do {
2637 bound = 0;
2638 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2639 sym_index = find_elf_sym(symtab_section, p);
2640 if(sym_index) {
2641 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2642 if(sym->st_shndx == SHN_UNDEF) {
2643 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2644 ++bound;
2645 lseek(fd, off, SEEK_SET);
2646 if(tcc_load_object_file(s1, fd, off) < 0) {
2647 fail:
2648 ret = -1;
2649 goto the_end;
2654 } while(bound);
2655 ret = 0;
2656 the_end:
2657 tcc_free(data);
2658 return ret;
2661 /* load a '.a' file */
2662 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2664 ArchiveHeader hdr;
2665 char ar_size[11];
2666 char ar_name[17];
2667 char magic[8];
2668 int size, len, i;
2669 unsigned long file_offset;
2671 /* skip magic which was already checked */
2672 read(fd, magic, sizeof(magic));
2674 for(;;) {
2675 len = read(fd, &hdr, sizeof(hdr));
2676 if (len == 0)
2677 break;
2678 if (len != sizeof(hdr)) {
2679 tcc_error_noabort("invalid archive");
2680 return -1;
2682 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2683 ar_size[sizeof(hdr.ar_size)] = '\0';
2684 size = strtol(ar_size, NULL, 0);
2685 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2686 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2687 if (ar_name[i] != ' ')
2688 break;
2690 ar_name[i + 1] = '\0';
2691 file_offset = lseek(fd, 0, SEEK_CUR);
2692 /* align to even */
2693 size = (size + 1) & ~1;
2694 if (!strcmp(ar_name, "/")) {
2695 /* coff symbol table : we handle it */
2696 if(s1->alacarte_link)
2697 return tcc_load_alacarte(s1, fd, size);
2698 } else if (!strcmp(ar_name, "//") ||
2699 !strcmp(ar_name, "__.SYMDEF") ||
2700 !strcmp(ar_name, "__.SYMDEF/") ||
2701 !strcmp(ar_name, "ARFILENAMES/")) {
2702 /* skip symbol table or archive names */
2703 } else {
2704 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2705 return -1;
2707 lseek(fd, file_offset + size, SEEK_SET);
2709 return 0;
2712 #ifndef TCC_TARGET_PE
2713 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2714 is referenced by the user (so it should be added as DT_NEEDED in
2715 the generated ELF file) */
2716 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2718 ElfW(Ehdr) ehdr;
2719 ElfW(Shdr) *shdr, *sh, *sh1;
2720 int i, j, nb_syms, nb_dts, sym_bind, ret;
2721 ElfW(Sym) *sym, *dynsym;
2722 ElfW(Dyn) *dt, *dynamic;
2723 unsigned char *dynstr;
2724 const char *name, *soname;
2725 DLLReference *dllref;
2727 read(fd, &ehdr, sizeof(ehdr));
2729 /* test CPU specific stuff */
2730 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2731 ehdr.e_machine != EM_TCC_TARGET) {
2732 tcc_error_noabort("bad architecture");
2733 return -1;
2736 /* read sections */
2737 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2739 /* load dynamic section and dynamic symbols */
2740 nb_syms = 0;
2741 nb_dts = 0;
2742 dynamic = NULL;
2743 dynsym = NULL; /* avoid warning */
2744 dynstr = NULL; /* avoid warning */
2745 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2746 switch(sh->sh_type) {
2747 case SHT_DYNAMIC:
2748 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2749 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2750 break;
2751 case SHT_DYNSYM:
2752 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2753 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2754 sh1 = &shdr[sh->sh_link];
2755 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2756 break;
2757 default:
2758 break;
2762 /* compute the real library name */
2763 soname = tcc_basename(filename);
2765 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2766 if (dt->d_tag == DT_SONAME) {
2767 soname = dynstr + dt->d_un.d_val;
2771 /* if the dll is already loaded, do not load it */
2772 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2773 dllref = s1->loaded_dlls[i];
2774 if (!strcmp(soname, dllref->name)) {
2775 /* but update level if needed */
2776 if (level < dllref->level)
2777 dllref->level = level;
2778 ret = 0;
2779 goto the_end;
2783 /* add the dll and its level */
2784 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2785 dllref->level = level;
2786 strcpy(dllref->name, soname);
2787 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2789 /* add dynamic symbols in dynsym_section */
2790 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2791 sym_bind = ELFW(ST_BIND)(sym->st_info);
2792 if (sym_bind == STB_LOCAL)
2793 continue;
2794 name = dynstr + sym->st_name;
2795 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2796 sym->st_info, sym->st_other, sym->st_shndx, name);
2799 /* load all referenced DLLs */
2800 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2801 switch(dt->d_tag) {
2802 case DT_NEEDED:
2803 name = dynstr + dt->d_un.d_val;
2804 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2805 dllref = s1->loaded_dlls[j];
2806 if (!strcmp(name, dllref->name))
2807 goto already_loaded;
2809 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2810 tcc_error_noabort("referenced dll '%s' not found", name);
2811 ret = -1;
2812 goto the_end;
2814 already_loaded:
2815 break;
2818 ret = 0;
2819 the_end:
2820 tcc_free(dynstr);
2821 tcc_free(dynsym);
2822 tcc_free(dynamic);
2823 tcc_free(shdr);
2824 return ret;
2827 #define LD_TOK_NAME 256
2828 #define LD_TOK_EOF (-1)
2830 /* return next ld script token */
2831 static int ld_next(TCCState *s1, char *name, int name_size)
2833 int c;
2834 char *q;
2836 redo:
2837 switch(ch) {
2838 case ' ':
2839 case '\t':
2840 case '\f':
2841 case '\v':
2842 case '\r':
2843 case '\n':
2844 inp();
2845 goto redo;
2846 case '/':
2847 minp();
2848 if (ch == '*') {
2849 file->buf_ptr = parse_comment(file->buf_ptr);
2850 ch = file->buf_ptr[0];
2851 goto redo;
2852 } else {
2853 q = name;
2854 *q++ = '/';
2855 goto parse_name;
2857 break;
2858 /* case 'a' ... 'z': */
2859 case 'a':
2860 case 'b':
2861 case 'c':
2862 case 'd':
2863 case 'e':
2864 case 'f':
2865 case 'g':
2866 case 'h':
2867 case 'i':
2868 case 'j':
2869 case 'k':
2870 case 'l':
2871 case 'm':
2872 case 'n':
2873 case 'o':
2874 case 'p':
2875 case 'q':
2876 case 'r':
2877 case 's':
2878 case 't':
2879 case 'u':
2880 case 'v':
2881 case 'w':
2882 case 'x':
2883 case 'y':
2884 case 'z':
2885 /* case 'A' ... 'z': */
2886 case 'A':
2887 case 'B':
2888 case 'C':
2889 case 'D':
2890 case 'E':
2891 case 'F':
2892 case 'G':
2893 case 'H':
2894 case 'I':
2895 case 'J':
2896 case 'K':
2897 case 'L':
2898 case 'M':
2899 case 'N':
2900 case 'O':
2901 case 'P':
2902 case 'Q':
2903 case 'R':
2904 case 'S':
2905 case 'T':
2906 case 'U':
2907 case 'V':
2908 case 'W':
2909 case 'X':
2910 case 'Y':
2911 case 'Z':
2912 case '_':
2913 case '\\':
2914 case '.':
2915 case '$':
2916 case '~':
2917 q = name;
2918 parse_name:
2919 for(;;) {
2920 if (!((ch >= 'a' && ch <= 'z') ||
2921 (ch >= 'A' && ch <= 'Z') ||
2922 (ch >= '0' && ch <= '9') ||
2923 strchr("/.-_+=$:\\,~", ch)))
2924 break;
2925 if ((q - name) < name_size - 1) {
2926 *q++ = ch;
2928 minp();
2930 *q = '\0';
2931 c = LD_TOK_NAME;
2932 break;
2933 case CH_EOF:
2934 c = LD_TOK_EOF;
2935 break;
2936 default:
2937 c = ch;
2938 inp();
2939 break;
2941 return c;
2944 static int ld_add_file(TCCState *s1, const char filename[])
2946 int ret;
2948 ret = tcc_add_file_internal(s1, filename, 0);
2949 if (ret)
2950 ret = tcc_add_dll(s1, filename, 0);
2951 return ret;
2954 static inline int new_undef_syms(void)
2956 int ret = 0;
2957 ret = new_undef_sym;
2958 new_undef_sym = 0;
2959 return ret;
2962 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
2964 char filename[1024], libname[1024];
2965 int t, group, nblibs = 0, ret = 0;
2966 char **libs = NULL;
2968 group = !strcmp(cmd, "GROUP");
2969 if (!as_needed)
2970 new_undef_syms();
2971 t = ld_next(s1, filename, sizeof(filename));
2972 if (t != '(')
2973 expect("(");
2974 t = ld_next(s1, filename, sizeof(filename));
2975 for(;;) {
2976 libname[0] = '\0';
2977 if (t == LD_TOK_EOF) {
2978 tcc_error_noabort("unexpected end of file");
2979 ret = -1;
2980 goto lib_parse_error;
2981 } else if (t == ')') {
2982 break;
2983 } else if (t == '-') {
2984 t = ld_next(s1, filename, sizeof(filename));
2985 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
2986 tcc_error_noabort("library name expected");
2987 ret = -1;
2988 goto lib_parse_error;
2990 pstrcpy(libname, sizeof libname, &filename[1]);
2991 if (s1->static_link) {
2992 snprintf(filename, sizeof filename, "lib%s.a", libname);
2993 } else {
2994 snprintf(filename, sizeof filename, "lib%s.so", libname);
2996 } else if (t != LD_TOK_NAME) {
2997 tcc_error_noabort("filename expected");
2998 ret = -1;
2999 goto lib_parse_error;
3001 if (!strcmp(filename, "AS_NEEDED")) {
3002 ret = ld_add_file_list(s1, cmd, 1);
3003 if (ret)
3004 goto lib_parse_error;
3005 } else {
3006 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3007 if (!as_needed) {
3008 ret = ld_add_file(s1, filename);
3009 if (ret)
3010 goto lib_parse_error;
3011 if (group) {
3012 /* Add the filename *and* the libname to avoid future conversions */
3013 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
3014 if (libname[0] != '\0')
3015 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
3019 t = ld_next(s1, filename, sizeof(filename));
3020 if (t == ',') {
3021 t = ld_next(s1, filename, sizeof(filename));
3024 if (group && !as_needed) {
3025 while (new_undef_syms()) {
3026 int i;
3028 for (i = 0; i < nblibs; i ++)
3029 ld_add_file(s1, libs[i]);
3032 lib_parse_error:
3033 dynarray_reset(&libs, &nblibs);
3034 return ret;
3037 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3038 files */
3039 ST_FUNC int tcc_load_ldscript(TCCState *s1)
3041 char cmd[64];
3042 char filename[1024];
3043 int t, ret;
3045 ch = file->buf_ptr[0];
3046 ch = handle_eob();
3047 for(;;) {
3048 t = ld_next(s1, cmd, sizeof(cmd));
3049 if (t == LD_TOK_EOF)
3050 return 0;
3051 else if (t != LD_TOK_NAME)
3052 return -1;
3053 if (!strcmp(cmd, "INPUT") ||
3054 !strcmp(cmd, "GROUP")) {
3055 ret = ld_add_file_list(s1, cmd, 0);
3056 if (ret)
3057 return ret;
3058 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3059 !strcmp(cmd, "TARGET")) {
3060 /* ignore some commands */
3061 t = ld_next(s1, cmd, sizeof(cmd));
3062 if (t != '(')
3063 expect("(");
3064 for(;;) {
3065 t = ld_next(s1, filename, sizeof(filename));
3066 if (t == LD_TOK_EOF) {
3067 tcc_error_noabort("unexpected end of file");
3068 return -1;
3069 } else if (t == ')') {
3070 break;
3073 } else {
3074 return -1;
3077 return 0;
3079 #endif /* !TCC_TARGET_PE */