i386: We can change 'lea 0(%ebp),r' to 'mov %ebp,r'
[tinycc.git] / tccelf.c
blobc5690dd4130c70ab6c7862fcd7eb1003f7d69c6d
1 /*
2 * ELF file handling for TCC
3 *
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, uplong 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 static void *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 NULL;
172 return (void*)(uplong)sym->st_value;
175 /* return elf symbol value */
176 LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
178 return get_elf_sym_addr(s, name, 0);
181 /* return elf symbol value or error */
182 ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name)
184 return get_elf_sym_addr(s, name, 1);
187 /* add an elf symbol : check if it is already defined and patch
188 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
189 ST_FUNC int add_elf_sym(Section *s, uplong value, unsigned long size,
190 int info, int other, int sh_num, const char *name)
192 ElfW(Sym) *esym;
193 int sym_bind, sym_index, sym_type, esym_bind;
194 unsigned char sym_vis, esym_vis, new_vis;
196 sym_bind = ELFW(ST_BIND)(info);
197 sym_type = ELFW(ST_TYPE)(info);
198 sym_vis = ELFW(ST_VISIBILITY)(other);
200 if (sym_bind != STB_LOCAL) {
201 /* we search global or weak symbols */
202 sym_index = find_elf_sym(s, name);
203 if (!sym_index)
204 goto do_def;
205 esym = &((ElfW(Sym) *)s->data)[sym_index];
206 if (esym->st_shndx != SHN_UNDEF) {
207 esym_bind = ELFW(ST_BIND)(esym->st_info);
208 /* propagate the most constraining visibility */
209 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
210 esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
211 if (esym_vis == STV_DEFAULT) {
212 new_vis = sym_vis;
213 } else if (sym_vis == STV_DEFAULT) {
214 new_vis = esym_vis;
215 } else {
216 new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
218 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
219 | new_vis;
220 other = esym->st_other; /* in case we have to patch esym */
221 if (sh_num == SHN_UNDEF) {
222 /* ignore adding of undefined symbol if the
223 corresponding symbol is already defined */
224 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
225 /* global overrides weak, so patch */
226 goto do_patch;
227 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
228 /* weak is ignored if already global */
229 } else if (sym_bind == STB_WEAK && esym_bind == STB_WEAK) {
230 /* keep first-found weak definition, ignore subsequents */
231 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
232 /* ignore hidden symbols after */
233 } else if (esym->st_shndx == SHN_COMMON
234 && (sh_num < SHN_LORESERVE || sh_num == SHN_COMMON)) {
235 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
236 No idea if this is the correct solution ... */
237 goto do_patch;
238 } else if (s == tcc_state->dynsymtab_section) {
239 /* we accept that two DLL define the same symbol */
240 } else {
241 #if 1
242 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
243 sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
244 #endif
245 tcc_error_noabort("'%s' defined twice", name);
247 } else {
248 do_patch:
249 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
250 esym->st_shndx = sh_num;
251 new_undef_sym = 1;
252 esym->st_value = value;
253 esym->st_size = size;
254 esym->st_other = other;
256 } else {
257 do_def:
258 sym_index = put_elf_sym(s, value, size,
259 ELFW(ST_INFO)(sym_bind, sym_type), other,
260 sh_num, name);
262 return sym_index;
265 /* put relocation */
266 ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
267 int type, int symbol)
269 char buf[256];
270 Section *sr;
271 ElfW_Rel *rel;
273 sr = s->reloc;
274 if (!sr) {
275 /* if no relocation section, create it */
276 snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
277 /* if the symtab is allocated, then we consider the relocation
278 are also */
279 sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
280 sr->sh_entsize = sizeof(ElfW_Rel);
281 sr->link = symtab;
282 sr->sh_info = s->sh_num;
283 s->reloc = sr;
285 rel = section_ptr_add(sr, sizeof(ElfW_Rel));
286 rel->r_offset = offset;
287 rel->r_info = ELFW(R_INFO)(symbol, type);
288 #ifdef TCC_TARGET_X86_64
289 rel->r_addend = 0;
290 #endif
293 /* put stab debug information */
295 ST_FUNC void put_stabs(const char *str, int type, int other, int desc,
296 unsigned long value)
298 Stab_Sym *sym;
300 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
301 if (str) {
302 sym->n_strx = put_elf_str(stabstr_section, str);
303 } else {
304 sym->n_strx = 0;
306 sym->n_type = type;
307 sym->n_other = other;
308 sym->n_desc = desc;
309 sym->n_value = value;
312 ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc,
313 unsigned long value, Section *sec, int sym_index)
315 put_stabs(str, type, other, desc, value);
316 put_elf_reloc(symtab_section, stab_section,
317 stab_section->data_offset - sizeof(unsigned int),
318 R_DATA_32, sym_index);
321 ST_FUNC void put_stabn(int type, int other, int desc, int value)
323 put_stabs(NULL, type, other, desc, value);
326 ST_FUNC void put_stabd(int type, int other, int desc)
328 put_stabs(NULL, type, other, desc, 0);
331 /* In an ELF file symbol table, the local symbols must appear below
332 the global and weak ones. Since TCC cannot sort it while generating
333 the code, we must do it after. All the relocation tables are also
334 modified to take into account the symbol table sorting */
335 static void sort_syms(TCCState *s1, Section *s)
337 int *old_to_new_syms;
338 ElfW(Sym) *new_syms;
339 int nb_syms, i;
340 ElfW(Sym) *p, *q;
341 ElfW_Rel *rel, *rel_end;
342 Section *sr;
343 int type, sym_index;
345 nb_syms = s->data_offset / sizeof(ElfW(Sym));
346 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
347 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
349 /* first pass for local symbols */
350 p = (ElfW(Sym) *)s->data;
351 q = new_syms;
352 for(i = 0; i < nb_syms; i++) {
353 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
354 old_to_new_syms[i] = q - new_syms;
355 *q++ = *p;
357 p++;
359 /* save the number of local symbols in section header */
360 s->sh_info = q - new_syms;
362 /* then second pass for non local symbols */
363 p = (ElfW(Sym) *)s->data;
364 for(i = 0; i < nb_syms; i++) {
365 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
366 old_to_new_syms[i] = q - new_syms;
367 *q++ = *p;
369 p++;
372 /* we copy the new symbols to the old */
373 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
374 tcc_free(new_syms);
376 /* now we modify all the relocations */
377 for(i = 1; i < s1->nb_sections; i++) {
378 sr = s1->sections[i];
379 if (sr->sh_type == SHT_RELX && sr->link == s) {
380 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
381 for(rel = (ElfW_Rel *)sr->data;
382 rel < rel_end;
383 rel++) {
384 sym_index = ELFW(R_SYM)(rel->r_info);
385 type = ELFW(R_TYPE)(rel->r_info);
386 sym_index = old_to_new_syms[sym_index];
387 rel->r_info = ELFW(R_INFO)(sym_index, type);
392 tcc_free(old_to_new_syms);
395 /* relocate common symbols in the .bss section */
396 ST_FUNC void relocate_common_syms(void)
398 ElfW(Sym) *sym, *sym_end;
399 unsigned long offset, align;
401 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
402 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
403 sym < sym_end;
404 sym++) {
405 if (sym->st_shndx == SHN_COMMON) {
406 /* align symbol */
407 align = sym->st_value;
408 offset = bss_section->data_offset;
409 offset = (offset + align - 1) & -align;
410 sym->st_value = offset;
411 sym->st_shndx = bss_section->sh_num;
412 offset += sym->st_size;
413 bss_section->data_offset = offset;
418 /* relocate symbol table, resolve undefined symbols if do_resolve is
419 true and output error if undefined symbol. */
420 ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
422 ElfW(Sym) *sym, *esym, *sym_end;
423 int sym_bind, sh_num, sym_index;
424 const char *name;
426 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
427 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
428 sym < sym_end;
429 sym++) {
430 sh_num = sym->st_shndx;
431 if (sh_num == SHN_UNDEF) {
432 name = strtab_section->data + sym->st_name;
433 if (do_resolve) {
434 #if !defined TCC_TARGET_PE || !defined _WIN32
435 void *addr;
436 name = symtab_section->link->data + sym->st_name;
437 addr = resolve_sym(s1, name);
438 if (addr) {
439 sym->st_value = (uplong)addr;
440 goto found;
442 #endif
443 } else if (s1->dynsym) {
444 /* if dynamic symbol exist, then use it */
445 sym_index = find_elf_sym(s1->dynsym, name);
446 if (sym_index) {
447 esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
448 sym->st_value = esym->st_value;
449 goto found;
452 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
453 it */
454 if (!strcmp(name, "_fp_hw"))
455 goto found;
456 /* only weak symbols are accepted to be undefined. Their
457 value is zero */
458 sym_bind = ELFW(ST_BIND)(sym->st_info);
459 if (sym_bind == STB_WEAK) {
460 sym->st_value = 0;
461 } else {
462 tcc_error_noabort("undefined symbol '%s'", name);
464 } else if (sh_num < SHN_LORESERVE) {
465 /* add section base */
466 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
468 found: ;
472 #ifndef TCC_TARGET_PE
473 #ifdef TCC_TARGET_X86_64
474 #define JMP_TABLE_ENTRY_SIZE 14
475 static uplong add_jmp_table(TCCState *s1, uplong val)
477 char *p = s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset;
478 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
479 /* jmp *0x0(%rip) */
480 p[0] = 0xff;
481 p[1] = 0x25;
482 *(int *)(p + 2) = 0;
483 *(uplong *)(p + 6) = val;
484 return (uplong)p;
487 static uplong add_got_table(TCCState *s1, uplong val)
489 uplong *p = (uplong *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
490 s1->runtime_plt_and_got_offset += sizeof(uplong);
491 *p = val;
492 return (uplong)p;
494 #elif defined TCC_TARGET_ARM
495 #define JMP_TABLE_ENTRY_SIZE 8
496 static uplong add_jmp_table(TCCState *s1, int val)
498 uint32_t *p = (uint32_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
499 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
500 /* ldr pc, [pc, #-4] */
501 p[0] = 0xE51FF004;
502 p[1] = val;
503 return (uplong)p;
505 #endif
506 #endif
508 /* relocate a given section (CPU dependent) */
509 ST_FUNC void relocate_section(TCCState *s1, Section *s)
511 Section *sr;
512 ElfW_Rel *rel, *rel_end, *qrel;
513 ElfW(Sym) *sym;
514 int type, sym_index;
515 unsigned char *ptr;
516 uplong val, addr;
517 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
518 int esym_index;
519 #endif
521 sr = s->reloc;
522 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
523 qrel = (ElfW_Rel *)sr->data;
524 for(rel = qrel;
525 rel < rel_end;
526 rel++) {
527 ptr = s->data + rel->r_offset;
529 sym_index = ELFW(R_SYM)(rel->r_info);
530 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
531 val = sym->st_value;
532 #ifdef TCC_TARGET_X86_64
533 val += rel->r_addend;
534 #endif
535 type = ELFW(R_TYPE)(rel->r_info);
536 addr = s->sh_addr + rel->r_offset;
538 /* CPU specific */
539 switch(type) {
540 #if defined(TCC_TARGET_I386)
541 case R_386_32:
542 if (s1->output_type == TCC_OUTPUT_DLL) {
543 esym_index = s1->symtab_to_dynsym[sym_index];
544 qrel->r_offset = rel->r_offset;
545 if (esym_index) {
546 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
547 qrel++;
548 break;
549 } else {
550 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
551 qrel++;
554 *(int *)ptr += val;
555 break;
556 case R_386_PC32:
557 if (s1->output_type == TCC_OUTPUT_DLL) {
558 /* DLL relocation */
559 esym_index = s1->symtab_to_dynsym[sym_index];
560 if (esym_index) {
561 qrel->r_offset = rel->r_offset;
562 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
563 qrel++;
564 break;
567 *(int *)ptr += val - addr;
568 break;
569 case R_386_PLT32:
570 *(int *)ptr += val - addr;
571 break;
572 case R_386_GLOB_DAT:
573 case R_386_JMP_SLOT:
574 *(int *)ptr = val;
575 break;
576 case R_386_GOTPC:
577 *(int *)ptr += s1->got->sh_addr - addr;
578 break;
579 case R_386_GOTOFF:
580 *(int *)ptr += val - s1->got->sh_addr;
581 break;
582 case R_386_GOT32:
583 /* we load the got offset */
584 *(int *)ptr += s1->got_offsets[sym_index];
585 break;
586 case R_386_16:
587 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
588 output_file:
589 tcc_error("can only produce 16-bit binary files");
591 *(short *)ptr += val;
592 break;
593 case R_386_PC16:
594 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
595 goto output_file;
596 *(short *)ptr += val - addr;
597 break;
598 #elif defined(TCC_TARGET_ARM)
599 case R_ARM_PC24:
600 case R_ARM_CALL:
601 case R_ARM_JUMP24:
602 case R_ARM_PLT32:
604 int x, is_thumb, is_call, h, blx_avail;
605 x = (*(int *)ptr)&0xffffff;
606 (*(int *)ptr) &= 0xff000000;
607 if (x & 0x800000)
608 x -= 0x1000000;
609 x <<= 2;
610 blx_avail = (TCC_ARM_VERSION >= 5);
611 is_thumb = val & 1;
612 is_call = (type == R_ARM_CALL);
613 x += val - addr;
614 h = x & 2;
615 #ifndef TCC_TARGET_PE
616 if ((x & 3) || x >= 0x4000000 || x < -0x4000000)
617 if (!(x & 3) || !blx_avail || !is_call)
618 if (s1->output_type == TCC_OUTPUT_MEMORY) {
619 x += add_jmp_table(s1, val) - val; /* add veneer */
620 is_thumb = 0; /* Veneer uses ARM instructions */
622 #endif
623 if ((x & 3) || x >= 0x4000000 || x < -0x4000000)
624 if (!(x & 3) || !blx_avail || !is_call)
625 tcc_error("can't relocate value at %x",addr);
626 x >>= 2;
627 x &= 0xffffff;
628 /* Only reached if blx is avail and it is a call */
629 if (is_thumb) {
630 x |= h << 24;
631 (*(int *)ptr) = 0xfa << 24; /* bl -> blx */
633 (*(int *)ptr) |= x;
635 break;
636 /* Since these relocations only concern Thumb-2 and blx instruction was
637 introduced before Thumb-2, we can assume blx is available and not
638 guard its use */
639 case R_ARM_THM_CALL:
640 case R_ARM_THM_JUMP24:
642 int x, hi, lo, s, j1, j2, i1, i2, imm10, imm11;
643 int to_thumb, is_call, to_plt, blx_bit = 1 << 12;
644 Section *plt;
646 /* weak reference */
647 if (sym->st_shndx == SHN_UNDEF &&
648 ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
649 break;
651 /* Get initial offset */
652 hi = (*(uint16_t *)ptr);
653 lo = (*(uint16_t *)(ptr+2));
654 s = (hi >> 10) & 1;
655 j1 = (lo >> 13) & 1;
656 j2 = (lo >> 11) & 1;
657 i1 = (j1 ^ s) ^ 1;
658 i2 = (j2 ^ s) ^ 1;
659 imm10 = hi & 0x3ff;
660 imm11 = lo & 0x7ff;
661 x = (s << 24) | (i1 << 23) | (i2 << 22) |
662 (imm10 << 12) | (imm11 << 1);
663 if (x & 0x01000000)
664 x -= 0x02000000;
666 /* Relocation infos */
667 to_thumb = val & 1;
668 plt = s1->plt;
669 to_plt = (val >= plt->sh_addr) &&
670 (val < plt->sh_addr + plt->data_offset);
671 is_call = (type == R_ARM_THM_CALL);
673 /* Compute final offset */
674 if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */
675 x -= 4;
676 x += val - addr;
677 if (!to_thumb && is_call) {
678 blx_bit = 0; /* bl -> blx */
679 x = (x + 3) & -4; /* Compute offset from aligned PC */
682 /* Check that relocation is possible
683 * offset must not be out of range
684 * if target is to be entered in arm mode:
685 - bit 1 must not set
686 - instruction must be a call (bl) or a jump to PLT */
687 if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
688 if (to_thumb || (val & 2) || (!is_call && !to_plt))
689 tcc_error("can't relocate value at %x",addr);
691 /* Compute and store final offset */
692 s = (x >> 24) & 1;
693 i1 = (x >> 23) & 1;
694 i2 = (x >> 22) & 1;
695 j1 = s ^ (i1 ^ 1);
696 j2 = s ^ (i2 ^ 1);
697 imm10 = (x >> 12) & 0x3ff;
698 imm11 = (x >> 1) & 0x7ff;
699 (*(uint16_t *)ptr) = (uint16_t) ((hi & 0xf800) |
700 (s << 10) | imm10);
701 (*(uint16_t *)(ptr+2)) = (uint16_t) ((lo & 0xc000) |
702 (j1 << 13) | blx_bit | (j2 << 11) |
703 imm11);
705 break;
706 case R_ARM_MOVT_ABS:
707 case R_ARM_MOVW_ABS_NC:
709 int x, imm4, imm12;
710 if (type == R_ARM_MOVT_ABS)
711 val >>= 16;
712 imm12 = val & 0xfff;
713 imm4 = (val >> 12) & 0xf;
714 x = (imm4 << 16) | imm12;
715 if (type == R_ARM_THM_MOVT_ABS)
716 *(int *)ptr |= x;
717 else
718 *(int *)ptr += x;
720 break;
721 case R_ARM_THM_MOVT_ABS:
722 case R_ARM_THM_MOVW_ABS_NC:
724 int x, i, imm4, imm3, imm8;
725 if (type == R_ARM_THM_MOVT_ABS)
726 val >>= 16;
727 imm8 = val & 0xff;
728 imm3 = (val >> 8) & 0x7;
729 i = (val >> 11) & 1;
730 imm4 = (val >> 12) & 0xf;
731 x = (imm3 << 28) | (imm8 << 16) | (i << 10) | imm4;
732 if (type == R_ARM_THM_MOVT_ABS)
733 *(int *)ptr |= x;
734 else
735 *(int *)ptr += x;
737 break;
738 case R_ARM_PREL31:
740 int x;
741 x = (*(int *)ptr) & 0x7fffffff;
742 (*(int *)ptr) &= 0x80000000;
743 x = (x * 2) / 2;
744 x += val - addr;
745 if((x^(x>>1))&0x40000000)
746 tcc_error("can't relocate value at %x",addr);
747 (*(int *)ptr) |= x & 0x7fffffff;
749 case R_ARM_ABS32:
750 *(int *)ptr += val;
751 break;
752 case R_ARM_REL32:
753 *(int *)ptr += val - addr;
754 break;
755 case R_ARM_BASE_PREL:
756 *(int *)ptr += s1->got->sh_addr - addr;
757 break;
758 case R_ARM_GOTOFF32:
759 *(int *)ptr += val - s1->got->sh_addr;
760 break;
761 case R_ARM_GOT_BREL:
762 /* we load the got offset */
763 *(int *)ptr += s1->got_offsets[sym_index];
764 break;
765 case R_ARM_COPY:
766 break;
767 case R_ARM_V4BX:
768 /* trade Thumb support for ARMv4 support */
769 if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
770 *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
771 break;
772 default:
773 fprintf(stderr,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
774 type, (unsigned)addr, (unsigned)(uplong)ptr, (unsigned)val);
775 break;
776 #elif defined(TCC_TARGET_C67)
777 case R_C60_32:
778 *(int *)ptr += val;
779 break;
780 case R_C60LO16:
782 uint32_t orig;
784 /* put the low 16 bits of the absolute address */
785 // add to what is already there
787 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
788 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
790 //patch both at once - assumes always in pairs Low - High
792 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
793 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
795 break;
796 case R_C60HI16:
797 break;
798 default:
799 fprintf(stderr,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
800 type, (unsigned)addr, (unsigned)(uplong)ptr, (unsigned)val);
801 break;
802 #elif defined(TCC_TARGET_X86_64)
803 case R_X86_64_64:
804 if (s1->output_type == TCC_OUTPUT_DLL) {
805 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
806 qrel->r_addend = *(long long *)ptr + val;
807 qrel++;
809 *(long long *)ptr += val;
810 break;
811 case R_X86_64_32:
812 case R_X86_64_32S:
813 if (s1->output_type == TCC_OUTPUT_DLL) {
814 /* XXX: this logic may depend on TCC's codegen
815 now TCC uses R_X86_64_32 even for a 64bit pointer */
816 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
817 qrel->r_addend = *(int *)ptr + val;
818 qrel++;
820 *(int *)ptr += val;
821 break;
823 case R_X86_64_PC32:
824 if (s1->output_type == TCC_OUTPUT_DLL) {
825 /* DLL relocation */
826 esym_index = s1->symtab_to_dynsym[sym_index];
827 if (esym_index) {
828 qrel->r_offset = rel->r_offset;
829 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
830 qrel->r_addend = *(int *)ptr;
831 qrel++;
832 break;
835 /* fall through */
836 case R_X86_64_PLT32: {
837 long long diff;
838 diff = (long long)val - addr;
839 if (diff <= -2147483647 || diff > 2147483647) {
840 #ifndef TCC_TARGET_PE
841 /* XXX: naive support for over 32bit jump */
842 if (s1->output_type == TCC_OUTPUT_MEMORY) {
843 val = (add_jmp_table(s1, val - rel->r_addend) +
844 rel->r_addend);
845 diff = val - addr;
847 #endif
848 if (diff <= -2147483647 || diff > 2147483647) {
849 tcc_error("internal error: relocation failed");
852 *(int *)ptr += diff;
854 break;
855 case R_X86_64_GLOB_DAT:
856 case R_X86_64_JUMP_SLOT:
857 /* They don't need addend */
858 *(int *)ptr = val - rel->r_addend;
859 break;
860 case R_X86_64_GOTPCREL:
861 #ifndef TCC_TARGET_PE
862 if (s1->output_type == TCC_OUTPUT_MEMORY) {
863 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
864 *(int *)ptr += val - addr;
865 break;
867 #endif
868 *(int *)ptr += (s1->got->sh_addr - addr +
869 s1->got_offsets[sym_index] - 4);
870 break;
871 case R_X86_64_GOTTPOFF:
872 *(int *)ptr += val - s1->got->sh_addr;
873 break;
874 case R_X86_64_GOT32:
875 /* we load the got offset */
876 *(int *)ptr += s1->got_offsets[sym_index];
877 break;
878 #else
879 #error unsupported processor
880 #endif
883 /* if the relocation is allocated, we change its symbol table */
884 if (sr->sh_flags & SHF_ALLOC)
885 sr->link = s1->dynsym;
888 /* relocate relocation table in 'sr' */
889 static void relocate_rel(TCCState *s1, Section *sr)
891 Section *s;
892 ElfW_Rel *rel, *rel_end;
894 s = s1->sections[sr->sh_info];
895 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
896 for(rel = (ElfW_Rel *)sr->data;
897 rel < rel_end;
898 rel++) {
899 rel->r_offset += s->sh_addr;
903 /* count the number of dynamic relocations so that we can reserve
904 their space */
905 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
907 ElfW_Rel *rel, *rel_end;
908 int sym_index, esym_index, type, count;
910 count = 0;
911 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
912 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
913 sym_index = ELFW(R_SYM)(rel->r_info);
914 type = ELFW(R_TYPE)(rel->r_info);
915 switch(type) {
916 #if defined(TCC_TARGET_I386)
917 case R_386_32:
918 #elif defined(TCC_TARGET_X86_64)
919 case R_X86_64_32:
920 case R_X86_64_32S:
921 case R_X86_64_64:
922 #endif
923 count++;
924 break;
925 #if defined(TCC_TARGET_I386)
926 case R_386_PC32:
927 #elif defined(TCC_TARGET_X86_64)
928 case R_X86_64_PC32:
929 #endif
930 esym_index = s1->symtab_to_dynsym[sym_index];
931 if (esym_index)
932 count++;
933 break;
934 default:
935 break;
938 if (count) {
939 /* allocate the section */
940 sr->sh_flags |= SHF_ALLOC;
941 sr->sh_size = count * sizeof(ElfW_Rel);
943 return count;
946 static void put_got_offset(TCCState *s1, int index, unsigned long val)
948 int n;
949 unsigned long *tab;
951 if (index >= s1->nb_got_offsets) {
952 /* find immediately bigger power of 2 and reallocate array */
953 n = 1;
954 while (index >= n)
955 n *= 2;
956 tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
957 s1->got_offsets = tab;
958 memset(s1->got_offsets + s1->nb_got_offsets, 0,
959 (n - s1->nb_got_offsets) * sizeof(unsigned long));
960 s1->nb_got_offsets = n;
962 s1->got_offsets[index] = val;
965 /* XXX: suppress that */
966 static void put32(unsigned char *p, uint32_t val)
968 p[0] = val;
969 p[1] = val >> 8;
970 p[2] = val >> 16;
971 p[3] = val >> 24;
974 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
975 defined(TCC_TARGET_X86_64)
976 static uint32_t get32(unsigned char *p)
978 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
980 #endif
982 static void build_got(TCCState *s1)
984 unsigned char *ptr;
986 /* if no got, then create it */
987 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
988 s1->got->sh_entsize = 4;
989 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
990 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
991 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
992 #if PTR_SIZE == 4
993 /* keep space for _DYNAMIC pointer, if present */
994 put32(ptr, 0);
995 /* two dummy got entries */
996 put32(ptr + 4, 0);
997 put32(ptr + 8, 0);
998 #else
999 /* keep space for _DYNAMIC pointer, if present */
1000 put32(ptr, 0);
1001 put32(ptr + 4, 0);
1002 /* two dummy got entries */
1003 put32(ptr + 8, 0);
1004 put32(ptr + 12, 0);
1005 put32(ptr + 16, 0);
1006 put32(ptr + 20, 0);
1007 #endif
1010 /* put a got entry corresponding to a symbol in symtab_section. 'size'
1011 and 'info' can be modifed if more precise info comes from the DLL */
1012 static void put_got_entry(TCCState *s1,
1013 int reloc_type, unsigned long size, int info,
1014 int sym_index)
1016 int index;
1017 const char *name;
1018 ElfW(Sym) *sym;
1019 unsigned long offset;
1020 int *ptr;
1022 if (!s1->got)
1023 build_got(s1);
1025 /* if a got entry already exists for that symbol, no need to add one */
1026 if (sym_index < s1->nb_got_offsets &&
1027 s1->got_offsets[sym_index] != 0)
1028 return;
1030 put_got_offset(s1, sym_index, s1->got->data_offset);
1032 if (s1->dynsym) {
1033 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1034 name = symtab_section->link->data + sym->st_name;
1035 offset = sym->st_value;
1036 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1037 if (reloc_type ==
1038 #ifdef TCC_TARGET_X86_64
1039 R_X86_64_JUMP_SLOT
1040 #else
1041 R_386_JMP_SLOT
1042 #endif
1044 Section *plt;
1045 uint8_t *p;
1046 int modrm;
1048 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1049 modrm = 0x25;
1050 #else
1051 /* if we build a DLL, we add a %ebx offset */
1052 if (s1->output_type == TCC_OUTPUT_DLL)
1053 modrm = 0xa3;
1054 else
1055 modrm = 0x25;
1056 #endif
1058 /* add a PLT entry */
1059 plt = s1->plt;
1060 if (plt->data_offset == 0) {
1061 /* first plt entry */
1062 p = section_ptr_add(plt, 16);
1063 p[0] = 0xff; /* pushl got + PTR_SIZE */
1064 p[1] = modrm + 0x10;
1065 put32(p + 2, PTR_SIZE);
1066 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1067 p[7] = modrm;
1068 put32(p + 8, PTR_SIZE * 2);
1071 p = section_ptr_add(plt, 16);
1072 p[0] = 0xff; /* jmp *(got + x) */
1073 p[1] = modrm;
1074 put32(p + 2, s1->got->data_offset);
1075 p[6] = 0x68; /* push $xxx */
1076 put32(p + 7, (plt->data_offset - 32) >> 1);
1077 p[11] = 0xe9; /* jmp plt_start */
1078 put32(p + 12, -(plt->data_offset));
1080 /* the symbol is modified so that it will be relocated to
1081 the PLT */
1082 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
1083 if (s1->output_type == TCC_OUTPUT_EXE)
1084 #endif
1085 offset = plt->data_offset - 16;
1087 #elif defined(TCC_TARGET_ARM)
1088 if (reloc_type == R_ARM_JUMP_SLOT) {
1089 Section *plt;
1090 uint8_t *p;
1092 /* if we build a DLL, we add a %ebx offset */
1093 if (s1->output_type == TCC_OUTPUT_DLL)
1094 tcc_error("DLLs unimplemented!");
1096 /* add a PLT entry */
1097 plt = s1->plt;
1098 if (plt->data_offset == 0) {
1099 /* first plt entry */
1100 p = section_ptr_add(plt, 16);
1101 put32(p , 0xe52de004);
1102 put32(p + 4, 0xe59fe010);
1103 put32(p + 8, 0xe08fe00e);
1104 put32(p + 12, 0xe5bef008);
1107 p = section_ptr_add(plt, 20);
1108 put32(p , 0x4778); // bx pc
1109 put32(p+2, 0x46c0); // nop
1110 p += 4;
1111 put32(p , 0xe59fc004); // ldr ip, [pc, #4] // offset in GOT
1112 put32(p+4, 0xe08fc00c); // add ip, pc, ip // absolute address or offset
1113 put32(p+8, 0xe59cf000); // ldr pc, [ip] // load absolute address or load offset
1114 put32(p+12, s1->got->data_offset);
1116 /* the symbol is modified so that it will be relocated to
1117 the PLT */
1118 if (s1->output_type == TCC_OUTPUT_EXE)
1119 offset = plt->data_offset - 16;
1121 #elif defined(TCC_TARGET_C67)
1122 tcc_error("C67 got not implemented");
1123 #else
1124 #error unsupported CPU
1125 #endif
1126 index = put_elf_sym(s1->dynsym, offset,
1127 size, info, 0, sym->st_shndx, name);
1128 /* put a got entry */
1129 put_elf_reloc(s1->dynsym, s1->got,
1130 s1->got->data_offset,
1131 reloc_type, index);
1133 ptr = section_ptr_add(s1->got, PTR_SIZE);
1134 *ptr = 0;
1137 /* build GOT and PLT entries */
1138 ST_FUNC void build_got_entries(TCCState *s1)
1140 Section *s;
1141 ElfW_Rel *rel, *rel_end;
1142 ElfW(Sym) *sym;
1143 int i, type, reloc_type, sym_index;
1145 for(i = 1; i < s1->nb_sections; i++) {
1146 s = s1->sections[i];
1147 if (s->sh_type != SHT_RELX)
1148 continue;
1149 /* no need to handle got relocations */
1150 if (s->link != symtab_section)
1151 continue;
1152 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1153 for(rel = (ElfW_Rel *)s->data;
1154 rel < rel_end;
1155 rel++) {
1156 type = ELFW(R_TYPE)(rel->r_info);
1157 switch(type) {
1158 #if defined(TCC_TARGET_I386)
1159 case R_386_GOT32:
1160 case R_386_GOTOFF:
1161 case R_386_GOTPC:
1162 case R_386_PLT32:
1163 if (!s1->got)
1164 build_got(s1);
1165 if (type == R_386_GOT32 || type == R_386_PLT32) {
1166 sym_index = ELFW(R_SYM)(rel->r_info);
1167 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1168 /* look at the symbol got offset. If none, then add one */
1169 if (type == R_386_GOT32)
1170 reloc_type = R_386_GLOB_DAT;
1171 else
1172 reloc_type = R_386_JMP_SLOT;
1173 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1174 sym_index);
1176 break;
1177 #elif defined(TCC_TARGET_ARM)
1178 case R_ARM_GOT_BREL:
1179 case R_ARM_GOTOFF32:
1180 case R_ARM_BASE_PREL:
1181 case R_ARM_PLT32:
1182 if (!s1->got)
1183 build_got(s1);
1184 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1185 sym_index = ELFW(R_SYM)(rel->r_info);
1186 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1187 /* look at the symbol got offset. If none, then add one */
1188 if (type == R_ARM_GOT_BREL)
1189 reloc_type = R_ARM_GLOB_DAT;
1190 else
1191 reloc_type = R_ARM_JUMP_SLOT;
1192 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1193 sym_index);
1195 break;
1196 #elif defined(TCC_TARGET_C67)
1197 case R_C60_GOT32:
1198 case R_C60_GOTOFF:
1199 case R_C60_GOTPC:
1200 case R_C60_PLT32:
1201 if (!s1->got)
1202 build_got(s1);
1203 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1204 sym_index = ELFW(R_SYM)(rel->r_info);
1205 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1206 /* look at the symbol got offset. If none, then add one */
1207 if (type == R_C60_GOT32)
1208 reloc_type = R_C60_GLOB_DAT;
1209 else
1210 reloc_type = R_C60_JMP_SLOT;
1211 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1212 sym_index);
1214 break;
1215 #elif defined(TCC_TARGET_X86_64)
1216 case R_X86_64_GOT32:
1217 case R_X86_64_GOTTPOFF:
1218 case R_X86_64_GOTPCREL:
1219 case R_X86_64_PLT32:
1220 if (!s1->got)
1221 build_got(s1);
1222 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1223 type == R_X86_64_PLT32) {
1224 sym_index = ELFW(R_SYM)(rel->r_info);
1225 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1226 /* look at the symbol got offset. If none, then add one */
1227 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1228 reloc_type = R_X86_64_GLOB_DAT;
1229 else
1230 reloc_type = R_X86_64_JUMP_SLOT;
1231 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1232 sym_index);
1234 break;
1235 #else
1236 #error unsupported CPU
1237 #endif
1238 default:
1239 break;
1245 ST_FUNC Section *new_symtab(TCCState *s1,
1246 const char *symtab_name, int sh_type, int sh_flags,
1247 const char *strtab_name,
1248 const char *hash_name, int hash_sh_flags)
1250 Section *symtab, *strtab, *hash;
1251 int *ptr, nb_buckets;
1253 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1254 symtab->sh_entsize = sizeof(ElfW(Sym));
1255 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1256 put_elf_str(strtab, "");
1257 symtab->link = strtab;
1258 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1260 nb_buckets = 1;
1262 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1263 hash->sh_entsize = sizeof(int);
1264 symtab->hash = hash;
1265 hash->link = symtab;
1267 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1268 ptr[0] = nb_buckets;
1269 ptr[1] = 1;
1270 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1271 return symtab;
1274 /* put dynamic tag */
1275 static void put_dt(Section *dynamic, int dt, uplong val)
1277 ElfW(Dyn) *dyn;
1278 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1279 dyn->d_tag = dt;
1280 dyn->d_un.d_val = val;
1283 static void add_init_array_defines(TCCState *s1, const char *section_name)
1285 Section *s;
1286 long end_offset;
1287 char sym_start[1024];
1288 char sym_end[1024];
1290 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1291 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1293 s = find_section(s1, section_name);
1294 if (!s) {
1295 end_offset = 0;
1296 s = data_section;
1297 } else {
1298 end_offset = s->data_offset;
1301 add_elf_sym(symtab_section,
1302 0, 0,
1303 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1304 s->sh_num, sym_start);
1305 add_elf_sym(symtab_section,
1306 end_offset, 0,
1307 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1308 s->sh_num, sym_end);
1311 static int tcc_add_support(TCCState *s1, const char *filename)
1313 char buf[1024];
1314 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, filename);
1315 return tcc_add_file(s1, buf);
1318 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1320 #ifdef CONFIG_TCC_BCHECK
1321 unsigned long *ptr;
1322 Section *init_section;
1323 unsigned char *pinit;
1324 int sym_index;
1326 if (0 == s1->do_bounds_check)
1327 return;
1329 /* XXX: add an object file to do that */
1330 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1331 *ptr = 0;
1332 add_elf_sym(symtab_section, 0, 0,
1333 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1334 bounds_section->sh_num, "__bounds_start");
1335 /* add bound check code */
1336 #ifndef TCC_TARGET_PE
1337 tcc_add_support(s1, "bcheck.o");
1338 #endif
1339 #ifdef TCC_TARGET_I386
1340 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1341 /* add 'call __bound_init()' in .init section */
1342 init_section = find_section(s1, ".init");
1343 pinit = section_ptr_add(init_section, 5);
1344 pinit[0] = 0xe8;
1345 put32(pinit + 1, -4);
1346 sym_index = find_elf_sym(symtab_section, "__bound_init");
1347 put_elf_reloc(symtab_section, init_section,
1348 init_section->data_offset - 4, R_386_PC32, sym_index);
1350 #endif
1351 #endif
1354 /* add tcc runtime libraries */
1355 ST_FUNC void tcc_add_runtime(TCCState *s1)
1357 tcc_add_bcheck(s1);
1359 /* add libc */
1360 if (!s1->nostdlib) {
1361 tcc_add_library(s1, "c");
1362 #ifdef CONFIG_USE_LIBGCC
1363 tcc_add_file(s1, TCC_LIBGCC);
1364 #elif !defined WITHOUT_LIBTCC
1365 tcc_add_support(s1, "libtcc1.a");
1366 #endif
1367 /* add crt end if not memory output */
1368 if (s1->output_type != TCC_OUTPUT_MEMORY)
1369 tcc_add_crt(s1, "crtn.o");
1373 /* add various standard linker symbols (must be done after the
1374 sections are filled (for example after allocating common
1375 symbols)) */
1376 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1378 char buf[1024];
1379 int i;
1380 Section *s;
1382 add_elf_sym(symtab_section,
1383 text_section->data_offset, 0,
1384 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1385 text_section->sh_num, "_etext");
1386 add_elf_sym(symtab_section,
1387 data_section->data_offset, 0,
1388 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1389 data_section->sh_num, "_edata");
1390 add_elf_sym(symtab_section,
1391 bss_section->data_offset, 0,
1392 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1393 bss_section->sh_num, "_end");
1394 /* horrible new standard ldscript defines */
1395 add_init_array_defines(s1, ".preinit_array");
1396 add_init_array_defines(s1, ".init_array");
1397 add_init_array_defines(s1, ".fini_array");
1399 /* add start and stop symbols for sections whose name can be
1400 expressed in C */
1401 for(i = 1; i < s1->nb_sections; i++) {
1402 s = s1->sections[i];
1403 if (s->sh_type == SHT_PROGBITS &&
1404 (s->sh_flags & SHF_ALLOC)) {
1405 const char *p;
1406 int ch;
1408 /* check if section name can be expressed in C */
1409 p = s->name;
1410 for(;;) {
1411 ch = *p;
1412 if (!ch)
1413 break;
1414 if (!isid(ch) && !isnum(ch))
1415 goto next_sec;
1416 p++;
1418 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1419 add_elf_sym(symtab_section,
1420 0, 0,
1421 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1422 s->sh_num, buf);
1423 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1424 add_elf_sym(symtab_section,
1425 s->data_offset, 0,
1426 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1427 s->sh_num, buf);
1429 next_sec: ;
1433 static void tcc_output_binary(TCCState *s1, FILE *f,
1434 const int *section_order)
1436 Section *s;
1437 int i, offset, size;
1439 offset = 0;
1440 for(i=1;i<s1->nb_sections;i++) {
1441 s = s1->sections[section_order[i]];
1442 if (s->sh_type != SHT_NOBITS &&
1443 (s->sh_flags & SHF_ALLOC)) {
1444 while (offset < s->sh_offset) {
1445 fputc(0, f);
1446 offset++;
1448 size = s->sh_size;
1449 fwrite(s->data, 1, size, f);
1450 offset += size;
1455 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1456 #define HAVE_PHDR 1
1457 #define EXTRA_RELITEMS 14
1459 /* move the relocation value from .dynsym to .got */
1460 void patch_dynsym_undef(TCCState *s1, Section *s)
1462 uint32_t *gotd = (void *)s1->got->data;
1463 ElfW(Sym) *sym, *sym_end;
1465 gotd += 3; // dummy entries in .got
1466 /* relocate symbols in .dynsym */
1467 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1468 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1469 if (sym->st_shndx == SHN_UNDEF) {
1470 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1471 sym->st_value = 0;
1475 #else
1476 #define HAVE_PHDR 0
1477 #define EXTRA_RELITEMS 9
1479 /* zero plt offsets of weak symbols in .dynsym */
1480 void patch_dynsym_undef(TCCState *s1, Section *s)
1482 ElfW(Sym) *sym, *sym_end;
1484 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1485 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++)
1486 if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
1487 sym->st_value = 0;
1489 #endif
1491 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1493 int sym_index = ELFW(R_SYM) (rel->r_info);
1494 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1495 unsigned long offset;
1497 if (sym_index >= s1->nb_got_offsets)
1498 return;
1499 offset = s1->got_offsets[sym_index];
1500 section_reserve(s1->got, offset + PTR_SIZE);
1501 #ifdef TCC_TARGET_X86_64
1502 /* only works for x86-64 */
1503 put32(s1->got->data + offset + 4, sym->st_value >> 32);
1504 #endif
1505 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1508 ST_FUNC void fill_got(TCCState *s1)
1510 Section *s;
1511 ElfW_Rel *rel, *rel_end;
1512 int i;
1514 for(i = 1; i < s1->nb_sections; i++) {
1515 s = s1->sections[i];
1516 if (s->sh_type != SHT_RELX)
1517 continue;
1518 /* no need to handle got relocations */
1519 if (s->link != symtab_section)
1520 continue;
1521 rel_end = (ElfW_Rel *) (s->data + s->data_offset);
1522 for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
1523 switch (ELFW(R_TYPE) (rel->r_info)) {
1524 case R_X86_64_GOT32:
1525 case R_X86_64_GOTPCREL:
1526 case R_X86_64_PLT32:
1527 fill_got_entry(s1, rel);
1528 break;
1535 /* output an ELF file */
1536 /* XXX: suppress unneeded sections */
1537 static int elf_output_file(TCCState *s1, const char *filename)
1539 ElfW(Ehdr) ehdr;
1540 FILE *f;
1541 int fd, mode, ret;
1542 int *section_order;
1543 int shnum, i, phnum, file_offset, offset, size, j, sh_order_index, k;
1544 long long tmp;
1545 uplong addr;
1546 Section *strsec, *s;
1547 ElfW(Shdr) shdr, *sh;
1548 ElfW(Phdr) *phdr, *ph;
1549 Section *interp, *dynamic, *dynstr;
1550 unsigned long saved_dynamic_data_offset;
1551 ElfW(Sym) *sym;
1552 int type, file_type;
1553 uplong rel_addr, rel_size;
1554 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1555 uplong bss_addr, bss_size;
1556 #endif
1558 file_type = s1->output_type;
1559 s1->nb_errors = 0;
1561 if (file_type != TCC_OUTPUT_OBJ) {
1562 tcc_add_runtime(s1);
1565 phdr = NULL;
1566 section_order = NULL;
1567 interp = NULL;
1568 dynamic = NULL;
1569 dynstr = NULL; /* avoid warning */
1570 saved_dynamic_data_offset = 0; /* avoid warning */
1572 if (file_type != TCC_OUTPUT_OBJ) {
1573 relocate_common_syms();
1575 tcc_add_linker_symbols(s1);
1577 if (!s1->static_link) {
1578 const char *name;
1579 int sym_index, index;
1580 ElfW(Sym) *esym, *sym_end;
1582 if (file_type == TCC_OUTPUT_EXE) {
1583 char *ptr;
1584 /* allow override the dynamic loader */
1585 const char *elfint = getenv("LD_SO");
1586 if (elfint == NULL)
1587 elfint = CONFIG_TCC_ELFINTERP;
1588 /* add interpreter section only if executable */
1589 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1590 interp->sh_addralign = 1;
1591 ptr = section_ptr_add(interp, 1+strlen(elfint));
1592 strcpy(ptr, elfint);
1595 /* add dynamic symbol table */
1596 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1597 ".dynstr",
1598 ".hash", SHF_ALLOC);
1599 dynstr = s1->dynsym->link;
1601 /* add dynamic section */
1602 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1603 SHF_ALLOC | SHF_WRITE);
1604 dynamic->link = dynstr;
1605 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1607 /* add PLT */
1608 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1609 SHF_ALLOC | SHF_EXECINSTR);
1610 s1->plt->sh_entsize = 4;
1612 build_got(s1);
1614 /* scan for undefined symbols and see if they are in the
1615 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1616 is found, then we add it in the PLT. If a symbol
1617 STT_OBJECT is found, we add it in the .bss section with
1618 a suitable relocation */
1619 sym_end = (ElfW(Sym) *)(symtab_section->data +
1620 symtab_section->data_offset);
1621 if (file_type == TCC_OUTPUT_EXE) {
1622 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1623 sym < sym_end;
1624 sym++) {
1625 if (sym->st_shndx == SHN_UNDEF) {
1626 name = symtab_section->link->data + sym->st_name;
1627 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1628 if (sym_index) {
1629 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1630 type = ELFW(ST_TYPE)(esym->st_info);
1631 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1632 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1633 ELFW(ST_INFO)(STB_GLOBAL,type),
1634 sym - (ElfW(Sym) *)symtab_section->data);
1635 } else if (type == STT_OBJECT) {
1636 unsigned long offset;
1637 ElfW(Sym) *dynsym, *dynsym_end;
1638 offset = bss_section->data_offset;
1639 /* XXX: which alignment ? */
1640 offset = (offset + 16 - 1) & -16;
1641 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1642 esym->st_info, 0,
1643 bss_section->sh_num, name);
1644 // Ensure R_COPY works for weak symbol aliases
1645 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1646 dynsym_end = (ElfW(Sym) *)
1647 (s1->dynsymtab_section->data +
1648 s1->dynsymtab_section->data_offset);
1649 for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1650 dynsym < dynsym_end; dynsym++) {
1651 if ((dynsym->st_value == esym->st_value)
1652 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1653 char *dynname;
1654 dynname = s1->dynsymtab_section->link->data
1655 + dynsym->st_name;
1656 put_elf_sym(s1->dynsym, offset,
1657 dynsym->st_size,
1658 dynsym->st_info, 0,
1659 bss_section->sh_num,
1660 dynname);
1661 break;
1665 put_elf_reloc(s1->dynsym, bss_section,
1666 offset, R_COPY, index);
1667 offset += esym->st_size;
1668 bss_section->data_offset = offset;
1670 } else {
1671 /* STB_WEAK undefined symbols are accepted */
1672 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1673 it */
1674 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1675 !strcmp(name, "_fp_hw")) {
1676 } else {
1677 tcc_error_noabort("undefined symbol '%s'", name);
1680 } else if (s1->rdynamic &&
1681 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1682 /* if -rdynamic option, then export all non
1683 local symbols */
1684 name = symtab_section->link->data + sym->st_name;
1685 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1686 sym->st_info, 0,
1687 sym->st_shndx, name);
1691 if (s1->nb_errors)
1692 goto fail;
1694 /* now look at unresolved dynamic symbols and export
1695 corresponding symbol */
1696 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1697 s1->dynsymtab_section->data_offset);
1698 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1699 esym < sym_end;
1700 esym++) {
1701 if (esym->st_shndx == SHN_UNDEF) {
1702 name = s1->dynsymtab_section->link->data + esym->st_name;
1703 sym_index = find_elf_sym(symtab_section, name);
1704 if (sym_index) {
1705 /* XXX: avoid adding a symbol if already
1706 present because of -rdynamic ? */
1707 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1708 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1709 sym->st_info, 0,
1710 sym->st_shndx, name);
1711 } else {
1712 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1713 /* weak symbols can stay undefined */
1714 } else {
1715 tcc_warning("undefined dynamic symbol '%s'", name);
1720 } else {
1721 int nb_syms;
1722 /* shared library case : we simply export all the global symbols */
1723 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1724 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1725 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1726 sym < sym_end;
1727 sym++) {
1728 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1729 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1730 if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
1731 ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
1732 && sym->st_shndx == SHN_UNDEF) {
1733 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1734 sym->st_info,
1735 sym - (ElfW(Sym) *)symtab_section->data);
1737 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1738 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1739 sym->st_info,
1740 sym - (ElfW(Sym) *)symtab_section->data);
1742 else
1743 #endif
1745 name = symtab_section->link->data + sym->st_name;
1746 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1747 sym->st_info, 0,
1748 sym->st_shndx, name);
1749 s1->symtab_to_dynsym[sym -
1750 (ElfW(Sym) *)symtab_section->data] =
1751 index;
1757 build_got_entries(s1);
1759 /* add a list of needed dlls */
1760 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1761 DLLReference *dllref = s1->loaded_dlls[i];
1762 if (dllref->level == 0)
1763 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1766 if (s1->rpath)
1767 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1769 /* XXX: currently, since we do not handle PIC code, we
1770 must relocate the readonly segments */
1771 if (file_type == TCC_OUTPUT_DLL) {
1772 if (s1->soname)
1773 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1774 put_dt(dynamic, DT_TEXTREL, 0);
1777 if (s1->symbolic)
1778 put_dt(dynamic, DT_SYMBOLIC, 0);
1780 /* add necessary space for other entries */
1781 saved_dynamic_data_offset = dynamic->data_offset;
1782 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1783 } else {
1784 /* still need to build got entries in case of static link */
1785 build_got_entries(s1);
1789 memset(&ehdr, 0, sizeof(ehdr));
1791 /* we add a section for symbols */
1792 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1793 put_elf_str(strsec, "");
1795 /* compute number of sections */
1796 shnum = s1->nb_sections;
1798 /* this array is used to reorder sections in the output file */
1799 section_order = tcc_malloc(sizeof(int) * shnum);
1800 section_order[0] = 0;
1801 sh_order_index = 1;
1803 /* compute number of program headers */
1804 switch(file_type) {
1805 default:
1806 case TCC_OUTPUT_OBJ:
1807 phnum = 0;
1808 break;
1809 case TCC_OUTPUT_EXE:
1810 if (!s1->static_link)
1811 phnum = 4 + HAVE_PHDR;
1812 else
1813 phnum = 2;
1814 break;
1815 case TCC_OUTPUT_DLL:
1816 phnum = 3;
1817 break;
1820 /* allocate strings for section names and decide if an unallocated
1821 section should be output */
1822 /* NOTE: the strsec section comes last, so its size is also
1823 correct ! */
1824 for(i = 1; i < s1->nb_sections; i++) {
1825 s = s1->sections[i];
1826 s->sh_name = put_elf_str(strsec, s->name);
1827 #if 0 //gr
1828 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1829 s->sh_flags,
1830 s->sh_type,
1831 s->sh_info,
1832 s->name,
1833 s->reloc ? s->reloc->name : "n"
1835 #endif
1836 /* when generating a DLL, we include relocations but we may
1837 patch them */
1838 if (file_type == TCC_OUTPUT_DLL &&
1839 s->sh_type == SHT_RELX &&
1840 !(s->sh_flags & SHF_ALLOC)) {
1841 /* //gr: avoid bogus relocs for empty (debug) sections */
1842 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1843 prepare_dynamic_rel(s1, s);
1844 else if (s1->do_debug)
1845 s->sh_size = s->data_offset;
1846 } else if (s1->do_debug ||
1847 file_type == TCC_OUTPUT_OBJ ||
1848 (s->sh_flags & SHF_ALLOC) ||
1849 i == (s1->nb_sections - 1)) {
1850 /* we output all sections if debug or object file */
1851 s->sh_size = s->data_offset;
1855 /* allocate program segment headers */
1856 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1858 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1859 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1860 } else {
1861 file_offset = 0;
1863 if (phnum > 0) {
1864 /* compute section to program header mapping */
1865 if (s1->has_text_addr) {
1866 int a_offset, p_offset;
1867 addr = s1->text_addr;
1868 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1869 ELF_PAGE_SIZE */
1870 a_offset = (int) (addr & (s1->section_align - 1));
1871 p_offset = file_offset & (s1->section_align - 1);
1872 if (a_offset < p_offset)
1873 a_offset += s1->section_align;
1874 file_offset += (a_offset - p_offset);
1875 } else {
1876 if (file_type == TCC_OUTPUT_DLL)
1877 addr = 0;
1878 else
1879 addr = ELF_START_ADDR;
1880 /* compute address after headers */
1881 addr += (file_offset & (s1->section_align - 1));
1884 /* dynamic relocation table information, for .dynamic section */
1885 rel_size = 0;
1886 rel_addr = 0;
1888 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1889 bss_addr = bss_size = 0;
1890 #endif
1891 /* leave one program header for the program interpreter */
1892 ph = &phdr[0];
1893 if (interp)
1894 ph += 1 + HAVE_PHDR;
1896 for(j = 0; j < 2; j++) {
1897 ph->p_type = PT_LOAD;
1898 if (j == 0)
1899 ph->p_flags = PF_R | PF_X;
1900 else
1901 ph->p_flags = PF_R | PF_W;
1902 ph->p_align = s1->section_align;
1904 /* we do the following ordering: interp, symbol tables,
1905 relocations, progbits, nobits */
1906 /* XXX: do faster and simpler sorting */
1907 for(k = 0; k < 5; k++) {
1908 for(i = 1; i < s1->nb_sections; i++) {
1909 s = s1->sections[i];
1910 /* compute if section should be included */
1911 if (j == 0) {
1912 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1913 SHF_ALLOC)
1914 continue;
1915 } else {
1916 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1917 (SHF_ALLOC | SHF_WRITE))
1918 continue;
1920 if (s == interp) {
1921 if (k != 0)
1922 continue;
1923 } else if (s->sh_type == SHT_DYNSYM ||
1924 s->sh_type == SHT_STRTAB ||
1925 s->sh_type == SHT_HASH) {
1926 if (k != 1)
1927 continue;
1928 } else if (s->sh_type == SHT_RELX) {
1929 if (k != 2)
1930 continue;
1931 } else if (s->sh_type == SHT_NOBITS) {
1932 if (k != 4)
1933 continue;
1934 } else {
1935 if (k != 3)
1936 continue;
1938 section_order[sh_order_index++] = i;
1940 /* section matches: we align it and add its size */
1941 tmp = addr;
1942 addr = (addr + s->sh_addralign - 1) &
1943 ~(s->sh_addralign - 1);
1944 file_offset += (int) ( addr - tmp );
1945 s->sh_offset = file_offset;
1946 s->sh_addr = addr;
1948 /* update program header infos */
1949 if (ph->p_offset == 0) {
1950 ph->p_offset = file_offset;
1951 ph->p_vaddr = addr;
1952 ph->p_paddr = ph->p_vaddr;
1954 /* update dynamic relocation infos */
1955 if (s->sh_type == SHT_RELX) {
1956 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1957 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1958 rel_addr = addr;
1959 rel_size += s->sh_size; // XXX only first rel.
1961 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1962 bss_addr = addr;
1963 bss_size = s->sh_size; // XXX only first rel.
1965 #else
1966 if (rel_size == 0)
1967 rel_addr = addr;
1968 rel_size += s->sh_size;
1969 #endif
1971 addr += s->sh_size;
1972 if (s->sh_type != SHT_NOBITS)
1973 file_offset += s->sh_size;
1976 ph->p_filesz = file_offset - ph->p_offset;
1977 ph->p_memsz = addr - ph->p_vaddr;
1978 ph++;
1979 if (j == 0) {
1980 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1981 /* if in the middle of a page, we duplicate the page in
1982 memory so that one copy is RX and the other is RW */
1983 if ((addr & (s1->section_align - 1)) != 0)
1984 addr += s1->section_align;
1985 } else {
1986 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1987 file_offset = (file_offset + s1->section_align - 1) &
1988 ~(s1->section_align - 1);
1993 /* if interpreter, then add corresponing program header */
1994 if (interp) {
1995 ph = &phdr[0];
1997 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1999 int len = phnum * sizeof(ElfW(Phdr));
2001 ph->p_type = PT_PHDR;
2002 ph->p_offset = sizeof(ElfW(Ehdr));
2003 ph->p_vaddr = interp->sh_addr - len;
2004 ph->p_paddr = ph->p_vaddr;
2005 ph->p_filesz = ph->p_memsz = len;
2006 ph->p_flags = PF_R | PF_X;
2007 ph->p_align = 4; // interp->sh_addralign;
2008 ph++;
2010 #endif
2012 ph->p_type = PT_INTERP;
2013 ph->p_offset = interp->sh_offset;
2014 ph->p_vaddr = interp->sh_addr;
2015 ph->p_paddr = ph->p_vaddr;
2016 ph->p_filesz = interp->sh_size;
2017 ph->p_memsz = interp->sh_size;
2018 ph->p_flags = PF_R;
2019 ph->p_align = interp->sh_addralign;
2022 /* if dynamic section, then add corresponing program header */
2023 if (dynamic) {
2024 ElfW(Sym) *sym_end;
2026 ph = &phdr[phnum - 1];
2028 ph->p_type = PT_DYNAMIC;
2029 ph->p_offset = dynamic->sh_offset;
2030 ph->p_vaddr = dynamic->sh_addr;
2031 ph->p_paddr = ph->p_vaddr;
2032 ph->p_filesz = dynamic->sh_size;
2033 ph->p_memsz = dynamic->sh_size;
2034 ph->p_flags = PF_R | PF_W;
2035 ph->p_align = dynamic->sh_addralign;
2037 /* put GOT dynamic section address */
2038 put32(s1->got->data, dynamic->sh_addr);
2040 /* relocate the PLT */
2041 if (file_type == TCC_OUTPUT_EXE
2042 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2043 || file_type == TCC_OUTPUT_DLL
2044 #endif
2046 uint8_t *p, *p_end;
2048 p = s1->plt->data;
2049 p_end = p + s1->plt->data_offset;
2050 if (p < p_end) {
2051 #if defined(TCC_TARGET_I386)
2052 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2053 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
2054 p += 16;
2055 while (p < p_end) {
2056 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2057 p += 16;
2059 #elif defined(TCC_TARGET_X86_64)
2060 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
2061 put32(p + 2, get32(p + 2) + x);
2062 put32(p + 8, get32(p + 8) + x - 6);
2063 p += 16;
2064 while (p < p_end) {
2065 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
2066 p += 16;
2068 #elif defined(TCC_TARGET_ARM)
2069 int x;
2070 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
2071 p += 16;
2072 while (p < p_end) {
2073 p += 4;
2074 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
2075 p += 16;
2077 #elif defined(TCC_TARGET_C67)
2078 /* XXX: TODO */
2079 #else
2080 #error unsupported CPU
2081 #endif
2085 /* relocate symbols in .dynsym */
2086 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
2087 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
2088 sym < sym_end;
2089 sym++) {
2090 if (sym->st_shndx == SHN_UNDEF) {
2091 /* relocate to the PLT if the symbol corresponds
2092 to a PLT entry */
2093 if (sym->st_value)
2094 sym->st_value += s1->plt->sh_addr;
2095 } else if (sym->st_shndx < SHN_LORESERVE) {
2096 /* do symbol relocation */
2097 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
2101 /* put dynamic section entries */
2102 dynamic->data_offset = saved_dynamic_data_offset;
2103 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
2104 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
2105 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2106 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
2107 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2108 #ifdef TCC_TARGET_X86_64
2109 put_dt(dynamic, DT_RELA, rel_addr);
2110 put_dt(dynamic, DT_RELASZ, rel_size);
2111 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2112 #else
2113 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2114 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2115 put_dt(dynamic, DT_PLTRELSZ, rel_size);
2116 put_dt(dynamic, DT_JMPREL, rel_addr);
2117 put_dt(dynamic, DT_PLTREL, DT_REL);
2118 put_dt(dynamic, DT_REL, bss_addr);
2119 put_dt(dynamic, DT_RELSZ, bss_size);
2120 #else
2121 put_dt(dynamic, DT_REL, rel_addr);
2122 put_dt(dynamic, DT_RELSZ, rel_size);
2123 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2124 #endif
2125 #endif
2126 if (s1->do_debug)
2127 put_dt(dynamic, DT_DEBUG, 0);
2128 put_dt(dynamic, DT_NULL, 0);
2131 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2132 ehdr.e_phnum = phnum;
2133 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2136 /* all other sections come after */
2137 for(i = 1; i < s1->nb_sections; i++) {
2138 s = s1->sections[i];
2139 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2140 continue;
2141 section_order[sh_order_index++] = i;
2143 file_offset = (file_offset + s->sh_addralign - 1) &
2144 ~(s->sh_addralign - 1);
2145 s->sh_offset = file_offset;
2146 if (s->sh_type != SHT_NOBITS)
2147 file_offset += s->sh_size;
2150 /* if building executable or DLL, then relocate each section
2151 except the GOT which is already relocated */
2152 if (file_type != TCC_OUTPUT_OBJ) {
2153 relocate_syms(s1, 0);
2155 if (s1->nb_errors != 0) {
2156 fail:
2157 ret = -1;
2158 goto the_end;
2161 /* relocate sections */
2162 /* XXX: ignore sections with allocated relocations ? */
2163 for(i = 1; i < s1->nb_sections; i++) {
2164 s = s1->sections[i];
2165 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
2166 relocate_section(s1, s);
2169 /* relocate relocation entries if the relocation tables are
2170 allocated in the executable */
2171 for(i = 1; i < s1->nb_sections; i++) {
2172 s = s1->sections[i];
2173 if ((s->sh_flags & SHF_ALLOC) &&
2174 s->sh_type == SHT_RELX) {
2175 relocate_rel(s1, s);
2179 /* get entry point address */
2180 if (file_type == TCC_OUTPUT_EXE)
2181 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
2182 else
2183 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2185 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2186 fill_got(s1);
2188 /* write elf file */
2189 if (file_type == TCC_OUTPUT_OBJ)
2190 mode = 0666;
2191 else
2192 mode = 0777;
2193 unlink(filename);
2194 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2195 if (fd < 0) {
2196 tcc_error_noabort("could not write '%s'", filename);
2197 goto fail;
2199 f = fdopen(fd, "wb");
2200 if (s1->verbose)
2201 printf("<- %s\n", filename);
2203 #ifdef TCC_TARGET_COFF
2204 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2205 tcc_output_coff(s1, f);
2206 } else
2207 #endif
2208 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2209 sort_syms(s1, symtab_section);
2211 /* align to 4 */
2212 file_offset = (file_offset + 3) & -4;
2214 /* fill header */
2215 ehdr.e_ident[0] = ELFMAG0;
2216 ehdr.e_ident[1] = ELFMAG1;
2217 ehdr.e_ident[2] = ELFMAG2;
2218 ehdr.e_ident[3] = ELFMAG3;
2219 ehdr.e_ident[4] = ELFCLASSW;
2220 ehdr.e_ident[5] = ELFDATA2LSB;
2221 ehdr.e_ident[6] = EV_CURRENT;
2222 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2223 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2224 #endif
2225 #ifdef TCC_TARGET_ARM
2226 #ifdef TCC_ARM_EABI
2227 ehdr.e_ident[EI_OSABI] = 0;
2228 ehdr.e_flags = 4 << 24;
2229 #else
2230 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2231 #endif
2232 #endif
2233 switch(file_type) {
2234 default:
2235 case TCC_OUTPUT_EXE:
2236 ehdr.e_type = ET_EXEC;
2237 break;
2238 case TCC_OUTPUT_DLL:
2239 ehdr.e_type = ET_DYN;
2240 break;
2241 case TCC_OUTPUT_OBJ:
2242 ehdr.e_type = ET_REL;
2243 break;
2245 ehdr.e_machine = EM_TCC_TARGET;
2246 ehdr.e_version = EV_CURRENT;
2247 ehdr.e_shoff = file_offset;
2248 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2249 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2250 ehdr.e_shnum = shnum;
2251 ehdr.e_shstrndx = shnum - 1;
2253 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2254 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2255 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2257 for(i=1;i<s1->nb_sections;i++) {
2258 s = s1->sections[section_order[i]];
2259 if (s->sh_type != SHT_NOBITS) {
2260 if (s->sh_type == SHT_DYNSYM)
2261 patch_dynsym_undef(s1, s);
2262 while (offset < s->sh_offset) {
2263 fputc(0, f);
2264 offset++;
2266 size = s->sh_size;
2267 fwrite(s->data, 1, size, f);
2268 offset += size;
2272 /* output section headers */
2273 while (offset < ehdr.e_shoff) {
2274 fputc(0, f);
2275 offset++;
2278 for(i=0;i<s1->nb_sections;i++) {
2279 sh = &shdr;
2280 memset(sh, 0, sizeof(ElfW(Shdr)));
2281 s = s1->sections[i];
2282 if (s) {
2283 sh->sh_name = s->sh_name;
2284 sh->sh_type = s->sh_type;
2285 sh->sh_flags = s->sh_flags;
2286 sh->sh_entsize = s->sh_entsize;
2287 sh->sh_info = s->sh_info;
2288 if (s->link)
2289 sh->sh_link = s->link->sh_num;
2290 sh->sh_addralign = s->sh_addralign;
2291 sh->sh_addr = s->sh_addr;
2292 sh->sh_offset = s->sh_offset;
2293 sh->sh_size = s->sh_size;
2295 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2297 } else {
2298 tcc_output_binary(s1, f, section_order);
2300 fclose(f);
2302 ret = 0;
2303 the_end:
2304 tcc_free(s1->symtab_to_dynsym);
2305 tcc_free(section_order);
2306 tcc_free(phdr);
2307 tcc_free(s1->got_offsets);
2308 return ret;
2311 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2313 int ret;
2314 #ifdef TCC_TARGET_PE
2315 if (s->output_type != TCC_OUTPUT_OBJ) {
2316 ret = pe_output_file(s, filename);
2317 } else
2318 #endif
2320 ret = elf_output_file(s, filename);
2322 return ret;
2325 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2327 void *data;
2329 data = tcc_malloc(size);
2330 lseek(fd, file_offset, SEEK_SET);
2331 read(fd, data, size);
2332 return data;
2335 typedef struct SectionMergeInfo {
2336 Section *s; /* corresponding existing section */
2337 unsigned long offset; /* offset of the new section in the existing section */
2338 uint8_t new_section; /* true if section 's' was added */
2339 uint8_t link_once; /* true if link once section */
2340 } SectionMergeInfo;
2342 /* load an object file and merge it with current files */
2343 /* XXX: handle correctly stab (debug) info */
2344 ST_FUNC int tcc_load_object_file(TCCState *s1,
2345 int fd, unsigned long file_offset)
2347 ElfW(Ehdr) ehdr;
2348 ElfW(Shdr) *shdr, *sh;
2349 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2350 unsigned char *strsec, *strtab;
2351 int *old_to_new_syms;
2352 char *sh_name, *name;
2353 SectionMergeInfo *sm_table, *sm;
2354 ElfW(Sym) *sym, *symtab;
2355 ElfW_Rel *rel, *rel_end;
2356 Section *s;
2358 int stab_index;
2359 int stabstr_index;
2361 stab_index = stabstr_index = 0;
2363 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2364 goto fail1;
2365 if (ehdr.e_ident[0] != ELFMAG0 ||
2366 ehdr.e_ident[1] != ELFMAG1 ||
2367 ehdr.e_ident[2] != ELFMAG2 ||
2368 ehdr.e_ident[3] != ELFMAG3)
2369 goto fail1;
2370 /* test if object file */
2371 if (ehdr.e_type != ET_REL)
2372 goto fail1;
2373 /* test CPU specific stuff */
2374 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2375 ehdr.e_machine != EM_TCC_TARGET) {
2376 fail1:
2377 tcc_error_noabort("invalid object file");
2378 return -1;
2380 /* read sections */
2381 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2382 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2383 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2385 /* load section names */
2386 sh = &shdr[ehdr.e_shstrndx];
2387 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2389 /* load symtab and strtab */
2390 old_to_new_syms = NULL;
2391 symtab = NULL;
2392 strtab = NULL;
2393 nb_syms = 0;
2394 for(i = 1; i < ehdr.e_shnum; i++) {
2395 sh = &shdr[i];
2396 if (sh->sh_type == SHT_SYMTAB) {
2397 if (symtab) {
2398 tcc_error_noabort("object must contain only one symtab");
2399 fail:
2400 ret = -1;
2401 goto the_end;
2403 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2404 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2405 sm_table[i].s = symtab_section;
2407 /* now load strtab */
2408 sh = &shdr[sh->sh_link];
2409 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2413 /* now examine each section and try to merge its content with the
2414 ones in memory */
2415 for(i = 1; i < ehdr.e_shnum; i++) {
2416 /* no need to examine section name strtab */
2417 if (i == ehdr.e_shstrndx)
2418 continue;
2419 sh = &shdr[i];
2420 sh_name = strsec + sh->sh_name;
2421 /* ignore sections types we do not handle */
2422 if (sh->sh_type != SHT_PROGBITS &&
2423 sh->sh_type != SHT_RELX &&
2424 #ifdef TCC_ARM_EABI
2425 sh->sh_type != SHT_ARM_EXIDX &&
2426 #endif
2427 sh->sh_type != SHT_NOBITS &&
2428 sh->sh_type != SHT_PREINIT_ARRAY &&
2429 sh->sh_type != SHT_INIT_ARRAY &&
2430 sh->sh_type != SHT_FINI_ARRAY &&
2431 strcmp(sh_name, ".stabstr")
2433 continue;
2434 if (sh->sh_addralign < 1)
2435 sh->sh_addralign = 1;
2436 /* find corresponding section, if any */
2437 for(j = 1; j < s1->nb_sections;j++) {
2438 s = s1->sections[j];
2439 if (!strcmp(s->name, sh_name)) {
2440 if (!strncmp(sh_name, ".gnu.linkonce",
2441 sizeof(".gnu.linkonce") - 1)) {
2442 /* if a 'linkonce' section is already present, we
2443 do not add it again. It is a little tricky as
2444 symbols can still be defined in
2445 it. */
2446 sm_table[i].link_once = 1;
2447 goto next;
2448 } else {
2449 goto found;
2453 /* not found: create new section */
2454 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2455 /* take as much info as possible from the section. sh_link and
2456 sh_info will be updated later */
2457 s->sh_addralign = sh->sh_addralign;
2458 s->sh_entsize = sh->sh_entsize;
2459 sm_table[i].new_section = 1;
2460 found:
2461 if (sh->sh_type != s->sh_type) {
2462 tcc_error_noabort("invalid section type");
2463 goto fail;
2466 /* align start of section */
2467 offset = s->data_offset;
2469 if (0 == strcmp(sh_name, ".stab")) {
2470 stab_index = i;
2471 goto no_align;
2473 if (0 == strcmp(sh_name, ".stabstr")) {
2474 stabstr_index = i;
2475 goto no_align;
2478 size = sh->sh_addralign - 1;
2479 offset = (offset + size) & ~size;
2480 if (sh->sh_addralign > s->sh_addralign)
2481 s->sh_addralign = sh->sh_addralign;
2482 s->data_offset = offset;
2483 no_align:
2484 sm_table[i].offset = offset;
2485 sm_table[i].s = s;
2486 /* concatenate sections */
2487 size = sh->sh_size;
2488 if (sh->sh_type != SHT_NOBITS) {
2489 unsigned char *ptr;
2490 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2491 ptr = section_ptr_add(s, size);
2492 read(fd, ptr, size);
2493 } else {
2494 s->data_offset += size;
2496 next: ;
2499 /* //gr relocate stab strings */
2500 if (stab_index && stabstr_index) {
2501 Stab_Sym *a, *b;
2502 unsigned o;
2503 s = sm_table[stab_index].s;
2504 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2505 b = (Stab_Sym *)(s->data + s->data_offset);
2506 o = sm_table[stabstr_index].offset;
2507 while (a < b)
2508 a->n_strx += o, a++;
2511 /* second short pass to update sh_link and sh_info fields of new
2512 sections */
2513 for(i = 1; i < ehdr.e_shnum; i++) {
2514 s = sm_table[i].s;
2515 if (!s || !sm_table[i].new_section)
2516 continue;
2517 sh = &shdr[i];
2518 if (sh->sh_link > 0)
2519 s->link = sm_table[sh->sh_link].s;
2520 if (sh->sh_type == SHT_RELX) {
2521 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2522 /* update backward link */
2523 s1->sections[s->sh_info]->reloc = s;
2526 sm = sm_table;
2528 /* resolve symbols */
2529 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2531 sym = symtab + 1;
2532 for(i = 1; i < nb_syms; i++, sym++) {
2533 if (sym->st_shndx != SHN_UNDEF &&
2534 sym->st_shndx < SHN_LORESERVE) {
2535 sm = &sm_table[sym->st_shndx];
2536 if (sm->link_once) {
2537 /* if a symbol is in a link once section, we use the
2538 already defined symbol. It is very important to get
2539 correct relocations */
2540 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2541 name = strtab + sym->st_name;
2542 sym_index = find_elf_sym(symtab_section, name);
2543 if (sym_index)
2544 old_to_new_syms[i] = sym_index;
2546 continue;
2548 /* if no corresponding section added, no need to add symbol */
2549 if (!sm->s)
2550 continue;
2551 /* convert section number */
2552 sym->st_shndx = sm->s->sh_num;
2553 /* offset value */
2554 sym->st_value += sm->offset;
2556 /* add symbol */
2557 name = strtab + sym->st_name;
2558 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2559 sym->st_info, sym->st_other,
2560 sym->st_shndx, name);
2561 old_to_new_syms[i] = sym_index;
2564 /* third pass to patch relocation entries */
2565 for(i = 1; i < ehdr.e_shnum; i++) {
2566 s = sm_table[i].s;
2567 if (!s)
2568 continue;
2569 sh = &shdr[i];
2570 offset = sm_table[i].offset;
2571 switch(s->sh_type) {
2572 case SHT_RELX:
2573 /* take relocation offset information */
2574 offseti = sm_table[sh->sh_info].offset;
2575 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2576 for(rel = (ElfW_Rel *)(s->data + offset);
2577 rel < rel_end;
2578 rel++) {
2579 int type;
2580 unsigned sym_index;
2581 /* convert symbol index */
2582 type = ELFW(R_TYPE)(rel->r_info);
2583 sym_index = ELFW(R_SYM)(rel->r_info);
2584 /* NOTE: only one symtab assumed */
2585 if (sym_index >= nb_syms)
2586 goto invalid_reloc;
2587 sym_index = old_to_new_syms[sym_index];
2588 /* ignore link_once in rel section. */
2589 if (!sym_index && !sm->link_once
2590 #ifdef TCC_TARGET_ARM
2591 && type != R_ARM_V4BX
2592 #endif
2594 invalid_reloc:
2595 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2596 i, strsec + sh->sh_name, rel->r_offset);
2597 goto fail;
2599 rel->r_info = ELFW(R_INFO)(sym_index, type);
2600 /* offset the relocation offset */
2601 rel->r_offset += offseti;
2603 break;
2604 default:
2605 break;
2609 ret = 0;
2610 the_end:
2611 tcc_free(symtab);
2612 tcc_free(strtab);
2613 tcc_free(old_to_new_syms);
2614 tcc_free(sm_table);
2615 tcc_free(strsec);
2616 tcc_free(shdr);
2617 return ret;
2620 typedef struct ArchiveHeader {
2621 char ar_name[16]; /* name of this member */
2622 char ar_date[12]; /* file mtime */
2623 char ar_uid[6]; /* owner uid; printed as decimal */
2624 char ar_gid[6]; /* owner gid; printed as decimal */
2625 char ar_mode[8]; /* file mode, printed as octal */
2626 char ar_size[10]; /* file size, printed as decimal */
2627 char ar_fmag[2]; /* should contain ARFMAG */
2628 } ArchiveHeader;
2630 static int get_be32(const uint8_t *b)
2632 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2635 /* load only the objects which resolve undefined symbols */
2636 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2638 int i, bound, nsyms, sym_index, off, ret;
2639 uint8_t *data;
2640 const char *ar_names, *p;
2641 const uint8_t *ar_index;
2642 ElfW(Sym) *sym;
2644 data = tcc_malloc(size);
2645 if (read(fd, data, size) != size)
2646 goto fail;
2647 nsyms = get_be32(data);
2648 ar_index = data + 4;
2649 ar_names = ar_index + nsyms * 4;
2651 do {
2652 bound = 0;
2653 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2654 sym_index = find_elf_sym(symtab_section, p);
2655 if(sym_index) {
2656 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2657 if(sym->st_shndx == SHN_UNDEF) {
2658 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2659 #if 0
2660 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2661 #endif
2662 ++bound;
2663 lseek(fd, off, SEEK_SET);
2664 if(tcc_load_object_file(s1, fd, off) < 0) {
2665 fail:
2666 ret = -1;
2667 goto the_end;
2672 } while(bound);
2673 ret = 0;
2674 the_end:
2675 tcc_free(data);
2676 return ret;
2679 /* load a '.a' file */
2680 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2682 ArchiveHeader hdr;
2683 char ar_size[11];
2684 char ar_name[17];
2685 char magic[8];
2686 int size, len, i;
2687 unsigned long file_offset;
2689 /* skip magic which was already checked */
2690 read(fd, magic, sizeof(magic));
2692 for(;;) {
2693 len = read(fd, &hdr, sizeof(hdr));
2694 if (len == 0)
2695 break;
2696 if (len != sizeof(hdr)) {
2697 tcc_error_noabort("invalid archive");
2698 return -1;
2700 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2701 ar_size[sizeof(hdr.ar_size)] = '\0';
2702 size = strtol(ar_size, NULL, 0);
2703 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2704 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2705 if (ar_name[i] != ' ')
2706 break;
2708 ar_name[i + 1] = '\0';
2709 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2710 file_offset = lseek(fd, 0, SEEK_CUR);
2711 /* align to even */
2712 size = (size + 1) & ~1;
2713 if (!strcmp(ar_name, "/")) {
2714 /* coff symbol table : we handle it */
2715 if(s1->alacarte_link)
2716 return tcc_load_alacarte(s1, fd, size);
2717 } else if (!strcmp(ar_name, "//") ||
2718 !strcmp(ar_name, "__.SYMDEF") ||
2719 !strcmp(ar_name, "__.SYMDEF/") ||
2720 !strcmp(ar_name, "ARFILENAMES/")) {
2721 /* skip symbol table or archive names */
2722 } else {
2723 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2724 return -1;
2726 lseek(fd, file_offset + size, SEEK_SET);
2728 return 0;
2731 #ifndef TCC_TARGET_PE
2732 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2733 is referenced by the user (so it should be added as DT_NEEDED in
2734 the generated ELF file) */
2735 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2737 ElfW(Ehdr) ehdr;
2738 ElfW(Shdr) *shdr, *sh, *sh1;
2739 int i, j, nb_syms, nb_dts, sym_bind, ret;
2740 ElfW(Sym) *sym, *dynsym;
2741 ElfW(Dyn) *dt, *dynamic;
2742 unsigned char *dynstr;
2743 const char *name, *soname;
2744 DLLReference *dllref;
2746 read(fd, &ehdr, sizeof(ehdr));
2748 /* test CPU specific stuff */
2749 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2750 ehdr.e_machine != EM_TCC_TARGET) {
2751 tcc_error_noabort("bad architecture");
2752 return -1;
2755 /* read sections */
2756 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2758 /* load dynamic section and dynamic symbols */
2759 nb_syms = 0;
2760 nb_dts = 0;
2761 dynamic = NULL;
2762 dynsym = NULL; /* avoid warning */
2763 dynstr = NULL; /* avoid warning */
2764 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2765 switch(sh->sh_type) {
2766 case SHT_DYNAMIC:
2767 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2768 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2769 break;
2770 case SHT_DYNSYM:
2771 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2772 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2773 sh1 = &shdr[sh->sh_link];
2774 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2775 break;
2776 default:
2777 break;
2781 /* compute the real library name */
2782 soname = tcc_basename(filename);
2784 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2785 if (dt->d_tag == DT_SONAME) {
2786 soname = dynstr + dt->d_un.d_val;
2790 /* if the dll is already loaded, do not load it */
2791 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2792 dllref = s1->loaded_dlls[i];
2793 if (!strcmp(soname, dllref->name)) {
2794 /* but update level if needed */
2795 if (level < dllref->level)
2796 dllref->level = level;
2797 ret = 0;
2798 goto the_end;
2802 // printf("loading dll '%s'\n", soname);
2804 /* add the dll and its level */
2805 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2806 dllref->level = level;
2807 strcpy(dllref->name, soname);
2808 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2810 /* add dynamic symbols in dynsym_section */
2811 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2812 sym_bind = ELFW(ST_BIND)(sym->st_info);
2813 if (sym_bind == STB_LOCAL)
2814 continue;
2815 name = dynstr + sym->st_name;
2816 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2817 sym->st_info, sym->st_other, sym->st_shndx, name);
2820 /* load all referenced DLLs */
2821 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2822 switch(dt->d_tag) {
2823 case DT_NEEDED:
2824 name = dynstr + dt->d_un.d_val;
2825 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2826 dllref = s1->loaded_dlls[j];
2827 if (!strcmp(name, dllref->name))
2828 goto already_loaded;
2830 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2831 tcc_error_noabort("referenced dll '%s' not found", name);
2832 ret = -1;
2833 goto the_end;
2835 already_loaded:
2836 break;
2839 ret = 0;
2840 the_end:
2841 tcc_free(dynstr);
2842 tcc_free(dynsym);
2843 tcc_free(dynamic);
2844 tcc_free(shdr);
2845 return ret;
2848 #define LD_TOK_NAME 256
2849 #define LD_TOK_EOF (-1)
2851 /* return next ld script token */
2852 static int ld_next(TCCState *s1, char *name, int name_size)
2854 int c;
2855 char *q;
2857 redo:
2858 switch(ch) {
2859 case ' ':
2860 case '\t':
2861 case '\f':
2862 case '\v':
2863 case '\r':
2864 case '\n':
2865 inp();
2866 goto redo;
2867 case '/':
2868 minp();
2869 if (ch == '*') {
2870 file->buf_ptr = parse_comment(file->buf_ptr);
2871 ch = file->buf_ptr[0];
2872 goto redo;
2873 } else {
2874 q = name;
2875 *q++ = '/';
2876 goto parse_name;
2878 break;
2879 /* case 'a' ... 'z': */
2880 case 'a':
2881 case 'b':
2882 case 'c':
2883 case 'd':
2884 case 'e':
2885 case 'f':
2886 case 'g':
2887 case 'h':
2888 case 'i':
2889 case 'j':
2890 case 'k':
2891 case 'l':
2892 case 'm':
2893 case 'n':
2894 case 'o':
2895 case 'p':
2896 case 'q':
2897 case 'r':
2898 case 's':
2899 case 't':
2900 case 'u':
2901 case 'v':
2902 case 'w':
2903 case 'x':
2904 case 'y':
2905 case 'z':
2906 /* case 'A' ... 'z': */
2907 case 'A':
2908 case 'B':
2909 case 'C':
2910 case 'D':
2911 case 'E':
2912 case 'F':
2913 case 'G':
2914 case 'H':
2915 case 'I':
2916 case 'J':
2917 case 'K':
2918 case 'L':
2919 case 'M':
2920 case 'N':
2921 case 'O':
2922 case 'P':
2923 case 'Q':
2924 case 'R':
2925 case 'S':
2926 case 'T':
2927 case 'U':
2928 case 'V':
2929 case 'W':
2930 case 'X':
2931 case 'Y':
2932 case 'Z':
2933 case '_':
2934 case '\\':
2935 case '.':
2936 case '$':
2937 case '~':
2938 q = name;
2939 parse_name:
2940 for(;;) {
2941 if (!((ch >= 'a' && ch <= 'z') ||
2942 (ch >= 'A' && ch <= 'Z') ||
2943 (ch >= '0' && ch <= '9') ||
2944 strchr("/.-_+=$:\\,~", ch)))
2945 break;
2946 if ((q - name) < name_size - 1) {
2947 *q++ = ch;
2949 minp();
2951 *q = '\0';
2952 c = LD_TOK_NAME;
2953 break;
2954 case CH_EOF:
2955 c = LD_TOK_EOF;
2956 break;
2957 default:
2958 c = ch;
2959 inp();
2960 break;
2962 #if 0
2963 printf("tok=%c %d\n", c, c);
2964 if (c == LD_TOK_NAME)
2965 printf(" name=%s\n", name);
2966 #endif
2967 return c;
2971 * Extract the file name from the library name
2973 * /!\ No test on filename capacity, be careful
2975 static void libname_to_filename(TCCState *s1, const char libname[], char filename[])
2977 if (!s1->static_link) {
2978 sprintf(filename, "lib%s.so", libname);
2979 } else {
2980 sprintf(filename, "lib%s.a", libname);
2984 static int ld_add_file(TCCState *s1, const char filename[])
2986 int ret;
2988 ret = tcc_add_file_internal(s1, filename, 0);
2989 if (ret)
2990 ret = tcc_add_dll(s1, filename, 0);
2991 return ret;
2994 static inline int new_undef_syms(void)
2996 int ret = 0;
2997 ret = new_undef_sym;
2998 new_undef_sym = 0;
2999 return ret;
3002 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
3004 char filename[1024], libname[1024];
3005 int t, group, nblibs = 0, ret = 0;
3006 char **libs = NULL;
3008 group = !strcmp(cmd, "GROUP");
3009 if (!as_needed)
3010 new_undef_syms();
3011 t = ld_next(s1, filename, sizeof(filename));
3012 if (t != '(')
3013 expect("(");
3014 t = ld_next(s1, filename, sizeof(filename));
3015 for(;;) {
3016 libname[0] = '\0';
3017 if (t == LD_TOK_EOF) {
3018 tcc_error_noabort("unexpected end of file");
3019 ret = -1;
3020 goto lib_parse_error;
3021 } else if (t == ')') {
3022 break;
3023 } else if (t == '-') {
3024 t = ld_next(s1, filename, sizeof(filename));
3025 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
3026 tcc_error_noabort("library name expected");
3027 ret = -1;
3028 goto lib_parse_error;
3030 strcpy(libname, &filename[1]);
3031 libname_to_filename(s1, libname, filename);
3032 } else if (t != LD_TOK_NAME) {
3033 tcc_error_noabort("filename expected");
3034 ret = -1;
3035 goto lib_parse_error;
3037 if (!strcmp(filename, "AS_NEEDED")) {
3038 ret = ld_add_file_list(s1, cmd, 1);
3039 if (ret)
3040 goto lib_parse_error;
3041 } else {
3042 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3043 if (!as_needed) {
3044 ret = ld_add_file(s1, filename);
3045 if (ret)
3046 goto lib_parse_error;
3047 if (group) {
3048 /* Add the filename *and* the libname to avoid future conversions */
3049 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
3050 if (libname[0] != '\0')
3051 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
3055 t = ld_next(s1, filename, sizeof(filename));
3056 if (t == ',') {
3057 t = ld_next(s1, filename, sizeof(filename));
3060 if (group && !as_needed) {
3061 while (new_undef_syms()) {
3062 int i;
3064 for (i = 0; i < nblibs; i ++)
3065 ld_add_file(s1, libs[i]);
3068 lib_parse_error:
3069 dynarray_reset(&libs, &nblibs);
3070 return ret;
3073 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3074 files */
3075 ST_FUNC int tcc_load_ldscript(TCCState *s1)
3077 char cmd[64];
3078 char filename[1024];
3079 int t, ret;
3081 ch = file->buf_ptr[0];
3082 ch = handle_eob();
3083 for(;;) {
3084 t = ld_next(s1, cmd, sizeof(cmd));
3085 if (t == LD_TOK_EOF)
3086 return 0;
3087 else if (t != LD_TOK_NAME)
3088 return -1;
3089 if (!strcmp(cmd, "INPUT") ||
3090 !strcmp(cmd, "GROUP")) {
3091 ret = ld_add_file_list(s1, cmd, 0);
3092 if (ret)
3093 return ret;
3094 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3095 !strcmp(cmd, "TARGET")) {
3096 /* ignore some commands */
3097 t = ld_next(s1, cmd, sizeof(cmd));
3098 if (t != '(')
3099 expect("(");
3100 for(;;) {
3101 t = ld_next(s1, filename, sizeof(filename));
3102 if (t == LD_TOK_EOF) {
3103 tcc_error_noabort("unexpected end of file");
3104 return -1;
3105 } else if (t == ')') {
3106 break;
3109 } else {
3110 return -1;
3113 return 0;
3115 #endif /* ndef TCC_TARGET_PE */