Add support for R_ARM_THM_{JUMP24,CALL} relocs
[tinycc.git] / tccelf.c
blobe5bb1cb4a10b0b33a8ae2939ce197fcc7528d054
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 #endif
621 if ((x & 3) || x >= 0x4000000 || x < -0x4000000)
622 if (!(x & 3) || !blx_avail || !is_call)
623 tcc_error("can't relocate value at %x",addr);
624 x >>= 2;
625 x &= 0xffffff;
626 /* Only reached if blx is avail and it is a call */
627 if (is_thumb) {
628 x |= h << 24;
629 (*(int *)ptr) = 0xfa << 24; /* bl -> blx */
631 (*(int *)ptr) |= x;
633 break;
634 /* Since these relocations only concern Thumb-2 and blx instruction was
635 introduced before Thumb-2, we can assume blx is available and not
636 guard its use */
637 case R_ARM_THM_CALL:
638 case R_ARM_THM_JUMP24:
640 int x, hi, lo, s, j1, j2, i1, i2, imm10, imm11;
641 int to_thumb, is_call, blx_bit = 1 << 12;
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 is_call = (type == R_ARM_THM_CALL);
667 /* Compute final offset */
668 x += val - addr;
669 if (!to_thumb && is_call) {
670 blx_bit = 0; /* bl -> blx */
671 x = (x + 3) & -4; /* Compute offset from aligned PC */
674 /* Check that relocation is possible
675 * offset must not be out of range
676 * if target is to be entered in arm mode:
677 - bit 1 must not set
678 - instruction must be a call (bl) */
679 if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
680 if (to_thumb || (val & 2) || !is_call)
681 tcc_error("can't relocate value at %x",addr);
683 /* Compute and store final offset */
684 s = (x >> 24) & 1;
685 i1 = (x >> 23) & 1;
686 i2 = (x >> 22) & 1;
687 j1 = s ^ (i1 ^ 1);
688 j2 = s ^ (i2 ^ 1);
689 imm10 = (x >> 12) & 0x3ff;
690 imm11 = (x >> 1) & 0x7ff;
691 (*(uint16_t *)ptr) = (uint16_t) ((hi & 0xf800) |
692 (s << 10) | imm10);
693 (*(uint16_t *)(ptr+2)) = (uint16_t) ((lo & 0xc000) |
694 (j1 << 13) | blx_bit | (j2 << 11) |
695 imm11);
697 break;
698 case R_ARM_MOVT_ABS:
699 case R_ARM_MOVW_ABS_NC:
701 int x, imm4, imm12;
702 if (type == R_ARM_MOVT_ABS)
703 val >>= 16;
704 imm12 = val & 0xfff;
705 imm4 = (val >> 12) & 0xf;
706 x = (imm4 << 16) | imm12;
707 if (type == R_ARM_THM_MOVT_ABS)
708 *(int *)ptr |= x;
709 else
710 *(int *)ptr += x;
712 break;
713 case R_ARM_THM_MOVT_ABS:
714 case R_ARM_THM_MOVW_ABS_NC:
716 int x, i, imm4, imm3, imm8;
717 if (type == R_ARM_THM_MOVT_ABS)
718 val >>= 16;
719 imm8 = val & 0xff;
720 imm3 = (val >> 8) & 0x7;
721 i = (val >> 11) & 1;
722 imm4 = (val >> 12) & 0xf;
723 x = (imm3 << 28) | (imm8 << 16) | (i << 10) | imm4;
724 if (type == R_ARM_THM_MOVT_ABS)
725 *(int *)ptr |= x;
726 else
727 *(int *)ptr += x;
729 break;
730 case R_ARM_PREL31:
732 int x;
733 x = (*(int *)ptr) & 0x7fffffff;
734 (*(int *)ptr) &= 0x80000000;
735 x = (x * 2) / 2;
736 x += val - addr;
737 if((x^(x>>1))&0x40000000)
738 tcc_error("can't relocate value at %x",addr);
739 (*(int *)ptr) |= x & 0x7fffffff;
741 case R_ARM_ABS32:
742 *(int *)ptr += val;
743 break;
744 case R_ARM_REL32:
745 *(int *)ptr += val - addr;
746 break;
747 case R_ARM_BASE_PREL:
748 *(int *)ptr += s1->got->sh_addr - addr;
749 break;
750 case R_ARM_GOTOFF32:
751 *(int *)ptr += val - s1->got->sh_addr;
752 break;
753 case R_ARM_GOT_BREL:
754 /* we load the got offset */
755 *(int *)ptr += s1->got_offsets[sym_index];
756 break;
757 case R_ARM_COPY:
758 break;
759 case R_ARM_V4BX:
760 /* trade Thumb support for ARMv4 support */
761 if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
762 *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
763 break;
764 default:
765 fprintf(stderr,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
766 type, (unsigned)addr, (unsigned)(uplong)ptr, (unsigned)val);
767 break;
768 #elif defined(TCC_TARGET_C67)
769 case R_C60_32:
770 *(int *)ptr += val;
771 break;
772 case R_C60LO16:
774 uint32_t orig;
776 /* put the low 16 bits of the absolute address */
777 // add to what is already there
779 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
780 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
782 //patch both at once - assumes always in pairs Low - High
784 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
785 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
787 break;
788 case R_C60HI16:
789 break;
790 default:
791 fprintf(stderr,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
792 type, (unsigned)addr, (unsigned)(uplong)ptr, (unsigned)val);
793 break;
794 #elif defined(TCC_TARGET_X86_64)
795 case R_X86_64_64:
796 if (s1->output_type == TCC_OUTPUT_DLL) {
797 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
798 qrel->r_addend = *(long long *)ptr + val;
799 qrel++;
801 *(long long *)ptr += val;
802 break;
803 case R_X86_64_32:
804 case R_X86_64_32S:
805 if (s1->output_type == TCC_OUTPUT_DLL) {
806 /* XXX: this logic may depend on TCC's codegen
807 now TCC uses R_X86_64_32 even for a 64bit pointer */
808 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
809 qrel->r_addend = *(int *)ptr + val;
810 qrel++;
812 *(int *)ptr += val;
813 break;
815 case R_X86_64_PC32:
816 if (s1->output_type == TCC_OUTPUT_DLL) {
817 /* DLL relocation */
818 esym_index = s1->symtab_to_dynsym[sym_index];
819 if (esym_index) {
820 qrel->r_offset = rel->r_offset;
821 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
822 qrel->r_addend = *(int *)ptr;
823 qrel++;
824 break;
827 /* fall through */
828 case R_X86_64_PLT32: {
829 long long diff;
830 diff = (long long)val - addr;
831 if (diff <= -2147483647 || diff > 2147483647) {
832 #ifndef TCC_TARGET_PE
833 /* XXX: naive support for over 32bit jump */
834 if (s1->output_type == TCC_OUTPUT_MEMORY) {
835 val = (add_jmp_table(s1, val - rel->r_addend) +
836 rel->r_addend);
837 diff = val - addr;
839 #endif
840 if (diff <= -2147483647 || diff > 2147483647) {
841 tcc_error("internal error: relocation failed");
844 *(int *)ptr += diff;
846 break;
847 case R_X86_64_GLOB_DAT:
848 case R_X86_64_JUMP_SLOT:
849 /* They don't need addend */
850 *(int *)ptr = val - rel->r_addend;
851 break;
852 case R_X86_64_GOTPCREL:
853 #ifndef TCC_TARGET_PE
854 if (s1->output_type == TCC_OUTPUT_MEMORY) {
855 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
856 *(int *)ptr += val - addr;
857 break;
859 #endif
860 *(int *)ptr += (s1->got->sh_addr - addr +
861 s1->got_offsets[sym_index] - 4);
862 break;
863 case R_X86_64_GOTTPOFF:
864 *(int *)ptr += val - s1->got->sh_addr;
865 break;
866 case R_X86_64_GOT32:
867 /* we load the got offset */
868 *(int *)ptr += s1->got_offsets[sym_index];
869 break;
870 #else
871 #error unsupported processor
872 #endif
875 /* if the relocation is allocated, we change its symbol table */
876 if (sr->sh_flags & SHF_ALLOC)
877 sr->link = s1->dynsym;
880 /* relocate relocation table in 'sr' */
881 static void relocate_rel(TCCState *s1, Section *sr)
883 Section *s;
884 ElfW_Rel *rel, *rel_end;
886 s = s1->sections[sr->sh_info];
887 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
888 for(rel = (ElfW_Rel *)sr->data;
889 rel < rel_end;
890 rel++) {
891 rel->r_offset += s->sh_addr;
895 /* count the number of dynamic relocations so that we can reserve
896 their space */
897 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
899 ElfW_Rel *rel, *rel_end;
900 int sym_index, esym_index, type, count;
902 count = 0;
903 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
904 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; 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 void put_got_offset(TCCState *s1, int index, unsigned long val)
940 int n;
941 unsigned long *tab;
943 if (index >= s1->nb_got_offsets) {
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->got_offsets, n * sizeof(unsigned long));
949 s1->got_offsets = tab;
950 memset(s1->got_offsets + s1->nb_got_offsets, 0,
951 (n - s1->nb_got_offsets) * sizeof(unsigned long));
952 s1->nb_got_offsets = n;
954 s1->got_offsets[index] = val;
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_got_offsets &&
1019 s1->got_offsets[sym_index] != 0)
1020 return;
1022 put_got_offset(s1, sym_index, 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);
1094 put32(p + 4, 0xe59fe010);
1095 put32(p + 8, 0xe08fe00e);
1096 put32(p + 12, 0xe5bef008);
1099 p = section_ptr_add(plt, 16);
1100 put32(p , 0xe59fc004);
1101 put32(p+4, 0xe08fc00c);
1102 put32(p+8, 0xe59cf000);
1103 put32(p+12, s1->got->data_offset);
1105 /* the symbol is modified so that it will be relocated to
1106 the PLT */
1107 if (s1->output_type == TCC_OUTPUT_EXE)
1108 offset = plt->data_offset - 16;
1110 #elif defined(TCC_TARGET_C67)
1111 tcc_error("C67 got not implemented");
1112 #else
1113 #error unsupported CPU
1114 #endif
1115 index = put_elf_sym(s1->dynsym, offset,
1116 size, info, 0, sym->st_shndx, name);
1117 /* put a got entry */
1118 put_elf_reloc(s1->dynsym, s1->got,
1119 s1->got->data_offset,
1120 reloc_type, index);
1122 ptr = section_ptr_add(s1->got, PTR_SIZE);
1123 *ptr = 0;
1126 /* build GOT and PLT entries */
1127 ST_FUNC void build_got_entries(TCCState *s1)
1129 Section *s;
1130 ElfW_Rel *rel, *rel_end;
1131 ElfW(Sym) *sym;
1132 int i, type, reloc_type, sym_index;
1134 for(i = 1; i < s1->nb_sections; i++) {
1135 s = s1->sections[i];
1136 if (s->sh_type != SHT_RELX)
1137 continue;
1138 /* no need to handle got relocations */
1139 if (s->link != symtab_section)
1140 continue;
1141 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1142 for(rel = (ElfW_Rel *)s->data;
1143 rel < rel_end;
1144 rel++) {
1145 type = ELFW(R_TYPE)(rel->r_info);
1146 switch(type) {
1147 #if defined(TCC_TARGET_I386)
1148 case R_386_GOT32:
1149 case R_386_GOTOFF:
1150 case R_386_GOTPC:
1151 case R_386_PLT32:
1152 if (!s1->got)
1153 build_got(s1);
1154 if (type == R_386_GOT32 || type == R_386_PLT32) {
1155 sym_index = ELFW(R_SYM)(rel->r_info);
1156 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1157 /* look at the symbol got offset. If none, then add one */
1158 if (type == R_386_GOT32)
1159 reloc_type = R_386_GLOB_DAT;
1160 else
1161 reloc_type = R_386_JMP_SLOT;
1162 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1163 sym_index);
1165 break;
1166 #elif defined(TCC_TARGET_ARM)
1167 case R_ARM_GOT_BREL:
1168 case R_ARM_GOTOFF32:
1169 case R_ARM_BASE_PREL:
1170 case R_ARM_PLT32:
1171 if (!s1->got)
1172 build_got(s1);
1173 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1174 sym_index = ELFW(R_SYM)(rel->r_info);
1175 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1176 /* look at the symbol got offset. If none, then add one */
1177 if (type == R_ARM_GOT_BREL)
1178 reloc_type = R_ARM_GLOB_DAT;
1179 else
1180 reloc_type = R_ARM_JUMP_SLOT;
1181 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1182 sym_index);
1184 break;
1185 #elif defined(TCC_TARGET_C67)
1186 case R_C60_GOT32:
1187 case R_C60_GOTOFF:
1188 case R_C60_GOTPC:
1189 case R_C60_PLT32:
1190 if (!s1->got)
1191 build_got(s1);
1192 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1193 sym_index = ELFW(R_SYM)(rel->r_info);
1194 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1195 /* look at the symbol got offset. If none, then add one */
1196 if (type == R_C60_GOT32)
1197 reloc_type = R_C60_GLOB_DAT;
1198 else
1199 reloc_type = R_C60_JMP_SLOT;
1200 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1201 sym_index);
1203 break;
1204 #elif defined(TCC_TARGET_X86_64)
1205 case R_X86_64_GOT32:
1206 case R_X86_64_GOTTPOFF:
1207 case R_X86_64_GOTPCREL:
1208 case R_X86_64_PLT32:
1209 if (!s1->got)
1210 build_got(s1);
1211 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1212 type == R_X86_64_PLT32) {
1213 sym_index = ELFW(R_SYM)(rel->r_info);
1214 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1215 /* look at the symbol got offset. If none, then add one */
1216 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1217 reloc_type = R_X86_64_GLOB_DAT;
1218 else
1219 reloc_type = R_X86_64_JUMP_SLOT;
1220 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1221 sym_index);
1223 break;
1224 #else
1225 #error unsupported CPU
1226 #endif
1227 default:
1228 break;
1234 ST_FUNC Section *new_symtab(TCCState *s1,
1235 const char *symtab_name, int sh_type, int sh_flags,
1236 const char *strtab_name,
1237 const char *hash_name, int hash_sh_flags)
1239 Section *symtab, *strtab, *hash;
1240 int *ptr, nb_buckets;
1242 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1243 symtab->sh_entsize = sizeof(ElfW(Sym));
1244 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1245 put_elf_str(strtab, "");
1246 symtab->link = strtab;
1247 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1249 nb_buckets = 1;
1251 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1252 hash->sh_entsize = sizeof(int);
1253 symtab->hash = hash;
1254 hash->link = symtab;
1256 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1257 ptr[0] = nb_buckets;
1258 ptr[1] = 1;
1259 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1260 return symtab;
1263 /* put dynamic tag */
1264 static void put_dt(Section *dynamic, int dt, uplong val)
1266 ElfW(Dyn) *dyn;
1267 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1268 dyn->d_tag = dt;
1269 dyn->d_un.d_val = val;
1272 static void add_init_array_defines(TCCState *s1, const char *section_name)
1274 Section *s;
1275 long end_offset;
1276 char sym_start[1024];
1277 char sym_end[1024];
1279 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1280 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1282 s = find_section(s1, section_name);
1283 if (!s) {
1284 end_offset = 0;
1285 s = data_section;
1286 } else {
1287 end_offset = s->data_offset;
1290 add_elf_sym(symtab_section,
1291 0, 0,
1292 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1293 s->sh_num, sym_start);
1294 add_elf_sym(symtab_section,
1295 end_offset, 0,
1296 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1297 s->sh_num, sym_end);
1300 static int tcc_add_support(TCCState *s1, const char *filename)
1302 char buf[1024];
1303 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, filename);
1304 return tcc_add_file(s1, buf);
1307 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1309 #ifdef CONFIG_TCC_BCHECK
1310 unsigned long *ptr;
1311 Section *init_section;
1312 unsigned char *pinit;
1313 int sym_index;
1315 if (0 == s1->do_bounds_check)
1316 return;
1318 /* XXX: add an object file to do that */
1319 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1320 *ptr = 0;
1321 add_elf_sym(symtab_section, 0, 0,
1322 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1323 bounds_section->sh_num, "__bounds_start");
1324 /* add bound check code */
1325 #ifndef TCC_TARGET_PE
1326 tcc_add_support(s1, "bcheck.o");
1327 #endif
1328 #ifdef TCC_TARGET_I386
1329 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1330 /* add 'call __bound_init()' in .init section */
1331 init_section = find_section(s1, ".init");
1332 pinit = section_ptr_add(init_section, 5);
1333 pinit[0] = 0xe8;
1334 put32(pinit + 1, -4);
1335 sym_index = find_elf_sym(symtab_section, "__bound_init");
1336 put_elf_reloc(symtab_section, init_section,
1337 init_section->data_offset - 4, R_386_PC32, sym_index);
1339 #endif
1340 #endif
1343 /* add tcc runtime libraries */
1344 ST_FUNC void tcc_add_runtime(TCCState *s1)
1346 tcc_add_bcheck(s1);
1348 /* add libc */
1349 if (!s1->nostdlib) {
1350 tcc_add_library(s1, "c");
1351 #ifdef CONFIG_USE_LIBGCC
1352 tcc_add_file(s1, TCC_LIBGCC);
1353 #elif !defined WITHOUT_LIBTCC
1354 tcc_add_support(s1, "libtcc1.a");
1355 #endif
1356 /* add crt end if not memory output */
1357 if (s1->output_type != TCC_OUTPUT_MEMORY)
1358 tcc_add_crt(s1, "crtn.o");
1362 /* add various standard linker symbols (must be done after the
1363 sections are filled (for example after allocating common
1364 symbols)) */
1365 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1367 char buf[1024];
1368 int i;
1369 Section *s;
1371 add_elf_sym(symtab_section,
1372 text_section->data_offset, 0,
1373 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1374 text_section->sh_num, "_etext");
1375 add_elf_sym(symtab_section,
1376 data_section->data_offset, 0,
1377 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1378 data_section->sh_num, "_edata");
1379 add_elf_sym(symtab_section,
1380 bss_section->data_offset, 0,
1381 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1382 bss_section->sh_num, "_end");
1383 /* horrible new standard ldscript defines */
1384 add_init_array_defines(s1, ".preinit_array");
1385 add_init_array_defines(s1, ".init_array");
1386 add_init_array_defines(s1, ".fini_array");
1388 /* add start and stop symbols for sections whose name can be
1389 expressed in C */
1390 for(i = 1; i < s1->nb_sections; i++) {
1391 s = s1->sections[i];
1392 if (s->sh_type == SHT_PROGBITS &&
1393 (s->sh_flags & SHF_ALLOC)) {
1394 const char *p;
1395 int ch;
1397 /* check if section name can be expressed in C */
1398 p = s->name;
1399 for(;;) {
1400 ch = *p;
1401 if (!ch)
1402 break;
1403 if (!isid(ch) && !isnum(ch))
1404 goto next_sec;
1405 p++;
1407 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1408 add_elf_sym(symtab_section,
1409 0, 0,
1410 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1411 s->sh_num, buf);
1412 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1413 add_elf_sym(symtab_section,
1414 s->data_offset, 0,
1415 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1416 s->sh_num, buf);
1418 next_sec: ;
1422 static void tcc_output_binary(TCCState *s1, FILE *f,
1423 const int *section_order)
1425 Section *s;
1426 int i, offset, size;
1428 offset = 0;
1429 for(i=1;i<s1->nb_sections;i++) {
1430 s = s1->sections[section_order[i]];
1431 if (s->sh_type != SHT_NOBITS &&
1432 (s->sh_flags & SHF_ALLOC)) {
1433 while (offset < s->sh_offset) {
1434 fputc(0, f);
1435 offset++;
1437 size = s->sh_size;
1438 fwrite(s->data, 1, size, f);
1439 offset += size;
1444 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1445 #define HAVE_PHDR 1
1446 #define EXTRA_RELITEMS 14
1448 /* move the relocation value from .dynsym to .got */
1449 void patch_dynsym_undef(TCCState *s1, Section *s)
1451 uint32_t *gotd = (void *)s1->got->data;
1452 ElfW(Sym) *sym, *sym_end;
1454 gotd += 3; // dummy entries in .got
1455 /* relocate symbols in .dynsym */
1456 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1457 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1458 if (sym->st_shndx == SHN_UNDEF) {
1459 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1460 sym->st_value = 0;
1464 #else
1465 #define HAVE_PHDR 0
1466 #define EXTRA_RELITEMS 9
1468 /* zero plt offsets of weak symbols in .dynsym */
1469 void patch_dynsym_undef(TCCState *s1, Section *s)
1471 ElfW(Sym) *sym, *sym_end;
1473 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1474 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; 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_got_offsets)
1487 return;
1488 offset = s1->got_offsets[sym_index];
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, *rel_end;
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 rel_end = (ElfW_Rel *) (s->data + s->data_offset);
1511 for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
1512 switch (ELFW(R_TYPE) (rel->r_info)) {
1513 case R_X86_64_GOT32:
1514 case R_X86_64_GOTPCREL:
1515 case R_X86_64_PLT32:
1516 fill_got_entry(s1, rel);
1517 break;
1524 /* output an ELF file */
1525 /* XXX: suppress unneeded sections */
1526 static int elf_output_file(TCCState *s1, const char *filename)
1528 ElfW(Ehdr) ehdr;
1529 FILE *f;
1530 int fd, mode, ret;
1531 int *section_order;
1532 int shnum, i, phnum, file_offset, offset, size, j, sh_order_index, k;
1533 long long tmp;
1534 uplong addr;
1535 Section *strsec, *s;
1536 ElfW(Shdr) shdr, *sh;
1537 ElfW(Phdr) *phdr, *ph;
1538 Section *interp, *dynamic, *dynstr;
1539 unsigned long saved_dynamic_data_offset;
1540 ElfW(Sym) *sym;
1541 int type, file_type;
1542 uplong rel_addr, rel_size;
1543 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1544 uplong bss_addr, bss_size;
1545 #endif
1547 file_type = s1->output_type;
1548 s1->nb_errors = 0;
1550 if (file_type != TCC_OUTPUT_OBJ) {
1551 tcc_add_runtime(s1);
1554 phdr = NULL;
1555 section_order = NULL;
1556 interp = NULL;
1557 dynamic = NULL;
1558 dynstr = NULL; /* avoid warning */
1559 saved_dynamic_data_offset = 0; /* avoid warning */
1561 if (file_type != TCC_OUTPUT_OBJ) {
1562 relocate_common_syms();
1564 tcc_add_linker_symbols(s1);
1566 if (!s1->static_link) {
1567 const char *name;
1568 int sym_index, index;
1569 ElfW(Sym) *esym, *sym_end;
1571 if (file_type == TCC_OUTPUT_EXE) {
1572 char *ptr;
1573 /* allow override the dynamic loader */
1574 const char *elfint = getenv("LD_SO");
1575 if (elfint == NULL)
1576 elfint = CONFIG_TCC_ELFINTERP;
1577 /* add interpreter section only if executable */
1578 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1579 interp->sh_addralign = 1;
1580 ptr = section_ptr_add(interp, 1+strlen(elfint));
1581 strcpy(ptr, elfint);
1584 /* add dynamic symbol table */
1585 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1586 ".dynstr",
1587 ".hash", SHF_ALLOC);
1588 dynstr = s1->dynsym->link;
1590 /* add dynamic section */
1591 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1592 SHF_ALLOC | SHF_WRITE);
1593 dynamic->link = dynstr;
1594 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1596 /* add PLT */
1597 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1598 SHF_ALLOC | SHF_EXECINSTR);
1599 s1->plt->sh_entsize = 4;
1601 build_got(s1);
1603 /* scan for undefined symbols and see if they are in the
1604 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1605 is found, then we add it in the PLT. If a symbol
1606 STT_OBJECT is found, we add it in the .bss section with
1607 a suitable relocation */
1608 sym_end = (ElfW(Sym) *)(symtab_section->data +
1609 symtab_section->data_offset);
1610 if (file_type == TCC_OUTPUT_EXE) {
1611 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1612 sym < sym_end;
1613 sym++) {
1614 if (sym->st_shndx == SHN_UNDEF) {
1615 name = symtab_section->link->data + sym->st_name;
1616 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1617 if (sym_index) {
1618 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1619 type = ELFW(ST_TYPE)(esym->st_info);
1620 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1621 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1622 ELFW(ST_INFO)(STB_GLOBAL,type),
1623 sym - (ElfW(Sym) *)symtab_section->data);
1624 } else if (type == STT_OBJECT) {
1625 unsigned long offset;
1626 ElfW(Sym) *dynsym, *dynsym_end;
1627 offset = bss_section->data_offset;
1628 /* XXX: which alignment ? */
1629 offset = (offset + 16 - 1) & -16;
1630 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1631 esym->st_info, 0,
1632 bss_section->sh_num, name);
1633 // Ensure R_COPY works for weak symbol aliases
1634 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1635 dynsym_end = (ElfW(Sym) *)
1636 (s1->dynsymtab_section->data +
1637 s1->dynsymtab_section->data_offset);
1638 for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1639 dynsym < dynsym_end; dynsym++) {
1640 if ((dynsym->st_value == esym->st_value)
1641 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1642 char *dynname;
1643 dynname = s1->dynsymtab_section->link->data
1644 + dynsym->st_name;
1645 put_elf_sym(s1->dynsym, offset,
1646 dynsym->st_size,
1647 dynsym->st_info, 0,
1648 bss_section->sh_num,
1649 dynname);
1650 break;
1654 put_elf_reloc(s1->dynsym, bss_section,
1655 offset, R_COPY, index);
1656 offset += esym->st_size;
1657 bss_section->data_offset = offset;
1659 } else {
1660 /* STB_WEAK undefined symbols are accepted */
1661 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1662 it */
1663 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1664 !strcmp(name, "_fp_hw")) {
1665 } else {
1666 tcc_error_noabort("undefined symbol '%s'", name);
1669 } else if (s1->rdynamic &&
1670 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1671 /* if -rdynamic option, then export all non
1672 local symbols */
1673 name = symtab_section->link->data + sym->st_name;
1674 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1675 sym->st_info, 0,
1676 sym->st_shndx, name);
1680 if (s1->nb_errors)
1681 goto fail;
1683 /* now look at unresolved dynamic symbols and export
1684 corresponding symbol */
1685 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1686 s1->dynsymtab_section->data_offset);
1687 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1688 esym < sym_end;
1689 esym++) {
1690 if (esym->st_shndx == SHN_UNDEF) {
1691 name = s1->dynsymtab_section->link->data + esym->st_name;
1692 sym_index = find_elf_sym(symtab_section, name);
1693 if (sym_index) {
1694 /* XXX: avoid adding a symbol if already
1695 present because of -rdynamic ? */
1696 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1697 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1698 sym->st_info, 0,
1699 sym->st_shndx, name);
1700 } else {
1701 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1702 /* weak symbols can stay undefined */
1703 } else {
1704 tcc_warning("undefined dynamic symbol '%s'", name);
1709 } else {
1710 int nb_syms;
1711 /* shared library case : we simply export all the global symbols */
1712 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1713 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1714 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1715 sym < sym_end;
1716 sym++) {
1717 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1718 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1719 if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
1720 ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
1721 && sym->st_shndx == SHN_UNDEF) {
1722 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1723 sym->st_info,
1724 sym - (ElfW(Sym) *)symtab_section->data);
1726 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1727 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1728 sym->st_info,
1729 sym - (ElfW(Sym) *)symtab_section->data);
1731 else
1732 #endif
1734 name = symtab_section->link->data + sym->st_name;
1735 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1736 sym->st_info, 0,
1737 sym->st_shndx, name);
1738 s1->symtab_to_dynsym[sym -
1739 (ElfW(Sym) *)symtab_section->data] =
1740 index;
1746 build_got_entries(s1);
1748 /* add a list of needed dlls */
1749 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1750 DLLReference *dllref = s1->loaded_dlls[i];
1751 if (dllref->level == 0)
1752 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1755 if (s1->rpath)
1756 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1758 /* XXX: currently, since we do not handle PIC code, we
1759 must relocate the readonly segments */
1760 if (file_type == TCC_OUTPUT_DLL) {
1761 if (s1->soname)
1762 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1763 put_dt(dynamic, DT_TEXTREL, 0);
1766 if (s1->symbolic)
1767 put_dt(dynamic, DT_SYMBOLIC, 0);
1769 /* add necessary space for other entries */
1770 saved_dynamic_data_offset = dynamic->data_offset;
1771 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1772 } else {
1773 /* still need to build got entries in case of static link */
1774 build_got_entries(s1);
1778 memset(&ehdr, 0, sizeof(ehdr));
1780 /* we add a section for symbols */
1781 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1782 put_elf_str(strsec, "");
1784 /* compute number of sections */
1785 shnum = s1->nb_sections;
1787 /* this array is used to reorder sections in the output file */
1788 section_order = tcc_malloc(sizeof(int) * shnum);
1789 section_order[0] = 0;
1790 sh_order_index = 1;
1792 /* compute number of program headers */
1793 switch(file_type) {
1794 default:
1795 case TCC_OUTPUT_OBJ:
1796 phnum = 0;
1797 break;
1798 case TCC_OUTPUT_EXE:
1799 if (!s1->static_link)
1800 phnum = 4 + HAVE_PHDR;
1801 else
1802 phnum = 2;
1803 break;
1804 case TCC_OUTPUT_DLL:
1805 phnum = 3;
1806 break;
1809 /* allocate strings for section names and decide if an unallocated
1810 section should be output */
1811 /* NOTE: the strsec section comes last, so its size is also
1812 correct ! */
1813 for(i = 1; i < s1->nb_sections; i++) {
1814 s = s1->sections[i];
1815 s->sh_name = put_elf_str(strsec, s->name);
1816 #if 0 //gr
1817 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1818 s->sh_flags,
1819 s->sh_type,
1820 s->sh_info,
1821 s->name,
1822 s->reloc ? s->reloc->name : "n"
1824 #endif
1825 /* when generating a DLL, we include relocations but we may
1826 patch them */
1827 if (file_type == TCC_OUTPUT_DLL &&
1828 s->sh_type == SHT_RELX &&
1829 !(s->sh_flags & SHF_ALLOC)) {
1830 /* //gr: avoid bogus relocs for empty (debug) sections */
1831 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1832 prepare_dynamic_rel(s1, s);
1833 else if (s1->do_debug)
1834 s->sh_size = s->data_offset;
1835 } else if (s1->do_debug ||
1836 file_type == TCC_OUTPUT_OBJ ||
1837 (s->sh_flags & SHF_ALLOC) ||
1838 i == (s1->nb_sections - 1)) {
1839 /* we output all sections if debug or object file */
1840 s->sh_size = s->data_offset;
1844 /* allocate program segment headers */
1845 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1847 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1848 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1849 } else {
1850 file_offset = 0;
1852 if (phnum > 0) {
1853 /* compute section to program header mapping */
1854 if (s1->has_text_addr) {
1855 int a_offset, p_offset;
1856 addr = s1->text_addr;
1857 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1858 ELF_PAGE_SIZE */
1859 a_offset = (int) (addr & (s1->section_align - 1));
1860 p_offset = file_offset & (s1->section_align - 1);
1861 if (a_offset < p_offset)
1862 a_offset += s1->section_align;
1863 file_offset += (a_offset - p_offset);
1864 } else {
1865 if (file_type == TCC_OUTPUT_DLL)
1866 addr = 0;
1867 else
1868 addr = ELF_START_ADDR;
1869 /* compute address after headers */
1870 addr += (file_offset & (s1->section_align - 1));
1873 /* dynamic relocation table information, for .dynamic section */
1874 rel_size = 0;
1875 rel_addr = 0;
1877 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1878 bss_addr = bss_size = 0;
1879 #endif
1880 /* leave one program header for the program interpreter */
1881 ph = &phdr[0];
1882 if (interp)
1883 ph += 1 + HAVE_PHDR;
1885 for(j = 0; j < 2; j++) {
1886 ph->p_type = PT_LOAD;
1887 if (j == 0)
1888 ph->p_flags = PF_R | PF_X;
1889 else
1890 ph->p_flags = PF_R | PF_W;
1891 ph->p_align = s1->section_align;
1893 /* we do the following ordering: interp, symbol tables,
1894 relocations, progbits, nobits */
1895 /* XXX: do faster and simpler sorting */
1896 for(k = 0; k < 5; k++) {
1897 for(i = 1; i < s1->nb_sections; i++) {
1898 s = s1->sections[i];
1899 /* compute if section should be included */
1900 if (j == 0) {
1901 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1902 SHF_ALLOC)
1903 continue;
1904 } else {
1905 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1906 (SHF_ALLOC | SHF_WRITE))
1907 continue;
1909 if (s == interp) {
1910 if (k != 0)
1911 continue;
1912 } else if (s->sh_type == SHT_DYNSYM ||
1913 s->sh_type == SHT_STRTAB ||
1914 s->sh_type == SHT_HASH) {
1915 if (k != 1)
1916 continue;
1917 } else if (s->sh_type == SHT_RELX) {
1918 if (k != 2)
1919 continue;
1920 } else if (s->sh_type == SHT_NOBITS) {
1921 if (k != 4)
1922 continue;
1923 } else {
1924 if (k != 3)
1925 continue;
1927 section_order[sh_order_index++] = i;
1929 /* section matches: we align it and add its size */
1930 tmp = addr;
1931 addr = (addr + s->sh_addralign - 1) &
1932 ~(s->sh_addralign - 1);
1933 file_offset += (int) ( addr - tmp );
1934 s->sh_offset = file_offset;
1935 s->sh_addr = addr;
1937 /* update program header infos */
1938 if (ph->p_offset == 0) {
1939 ph->p_offset = file_offset;
1940 ph->p_vaddr = addr;
1941 ph->p_paddr = ph->p_vaddr;
1943 /* update dynamic relocation infos */
1944 if (s->sh_type == SHT_RELX) {
1945 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1946 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1947 rel_addr = addr;
1948 rel_size += s->sh_size; // XXX only first rel.
1950 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1951 bss_addr = addr;
1952 bss_size = s->sh_size; // XXX only first rel.
1954 #else
1955 if (rel_size == 0)
1956 rel_addr = addr;
1957 rel_size += s->sh_size;
1958 #endif
1960 addr += s->sh_size;
1961 if (s->sh_type != SHT_NOBITS)
1962 file_offset += s->sh_size;
1965 ph->p_filesz = file_offset - ph->p_offset;
1966 ph->p_memsz = addr - ph->p_vaddr;
1967 ph++;
1968 if (j == 0) {
1969 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1970 /* if in the middle of a page, we duplicate the page in
1971 memory so that one copy is RX and the other is RW */
1972 if ((addr & (s1->section_align - 1)) != 0)
1973 addr += s1->section_align;
1974 } else {
1975 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1976 file_offset = (file_offset + s1->section_align - 1) &
1977 ~(s1->section_align - 1);
1982 /* if interpreter, then add corresponing program header */
1983 if (interp) {
1984 ph = &phdr[0];
1986 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1988 int len = phnum * sizeof(ElfW(Phdr));
1990 ph->p_type = PT_PHDR;
1991 ph->p_offset = sizeof(ElfW(Ehdr));
1992 ph->p_vaddr = interp->sh_addr - len;
1993 ph->p_paddr = ph->p_vaddr;
1994 ph->p_filesz = ph->p_memsz = len;
1995 ph->p_flags = PF_R | PF_X;
1996 ph->p_align = 4; // interp->sh_addralign;
1997 ph++;
1999 #endif
2001 ph->p_type = PT_INTERP;
2002 ph->p_offset = interp->sh_offset;
2003 ph->p_vaddr = interp->sh_addr;
2004 ph->p_paddr = ph->p_vaddr;
2005 ph->p_filesz = interp->sh_size;
2006 ph->p_memsz = interp->sh_size;
2007 ph->p_flags = PF_R;
2008 ph->p_align = interp->sh_addralign;
2011 /* if dynamic section, then add corresponing program header */
2012 if (dynamic) {
2013 ElfW(Sym) *sym_end;
2015 ph = &phdr[phnum - 1];
2017 ph->p_type = PT_DYNAMIC;
2018 ph->p_offset = dynamic->sh_offset;
2019 ph->p_vaddr = dynamic->sh_addr;
2020 ph->p_paddr = ph->p_vaddr;
2021 ph->p_filesz = dynamic->sh_size;
2022 ph->p_memsz = dynamic->sh_size;
2023 ph->p_flags = PF_R | PF_W;
2024 ph->p_align = dynamic->sh_addralign;
2026 /* put GOT dynamic section address */
2027 put32(s1->got->data, dynamic->sh_addr);
2029 /* relocate the PLT */
2030 if (file_type == TCC_OUTPUT_EXE
2031 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2032 || file_type == TCC_OUTPUT_DLL
2033 #endif
2035 uint8_t *p, *p_end;
2037 p = s1->plt->data;
2038 p_end = p + s1->plt->data_offset;
2039 if (p < p_end) {
2040 #if defined(TCC_TARGET_I386)
2041 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2042 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
2043 p += 16;
2044 while (p < p_end) {
2045 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2046 p += 16;
2048 #elif defined(TCC_TARGET_X86_64)
2049 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
2050 put32(p + 2, get32(p + 2) + x);
2051 put32(p + 8, get32(p + 8) + x - 6);
2052 p += 16;
2053 while (p < p_end) {
2054 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
2055 p += 16;
2057 #elif defined(TCC_TARGET_ARM)
2058 int x;
2059 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
2060 p +=16;
2061 while (p < p_end) {
2062 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
2063 p += 16;
2065 #elif defined(TCC_TARGET_C67)
2066 /* XXX: TODO */
2067 #else
2068 #error unsupported CPU
2069 #endif
2073 /* relocate symbols in .dynsym */
2074 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
2075 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
2076 sym < sym_end;
2077 sym++) {
2078 if (sym->st_shndx == SHN_UNDEF) {
2079 /* relocate to the PLT if the symbol corresponds
2080 to a PLT entry */
2081 if (sym->st_value)
2082 sym->st_value += s1->plt->sh_addr;
2083 } else if (sym->st_shndx < SHN_LORESERVE) {
2084 /* do symbol relocation */
2085 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
2089 /* put dynamic section entries */
2090 dynamic->data_offset = saved_dynamic_data_offset;
2091 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
2092 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
2093 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2094 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
2095 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2096 #ifdef TCC_TARGET_X86_64
2097 put_dt(dynamic, DT_RELA, rel_addr);
2098 put_dt(dynamic, DT_RELASZ, rel_size);
2099 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2100 #else
2101 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2102 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2103 put_dt(dynamic, DT_PLTRELSZ, rel_size);
2104 put_dt(dynamic, DT_JMPREL, rel_addr);
2105 put_dt(dynamic, DT_PLTREL, DT_REL);
2106 put_dt(dynamic, DT_REL, bss_addr);
2107 put_dt(dynamic, DT_RELSZ, bss_size);
2108 #else
2109 put_dt(dynamic, DT_REL, rel_addr);
2110 put_dt(dynamic, DT_RELSZ, rel_size);
2111 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2112 #endif
2113 #endif
2114 if (s1->do_debug)
2115 put_dt(dynamic, DT_DEBUG, 0);
2116 put_dt(dynamic, DT_NULL, 0);
2119 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2120 ehdr.e_phnum = phnum;
2121 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2124 /* all other sections come after */
2125 for(i = 1; i < s1->nb_sections; i++) {
2126 s = s1->sections[i];
2127 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2128 continue;
2129 section_order[sh_order_index++] = i;
2131 file_offset = (file_offset + s->sh_addralign - 1) &
2132 ~(s->sh_addralign - 1);
2133 s->sh_offset = file_offset;
2134 if (s->sh_type != SHT_NOBITS)
2135 file_offset += s->sh_size;
2138 /* if building executable or DLL, then relocate each section
2139 except the GOT which is already relocated */
2140 if (file_type != TCC_OUTPUT_OBJ) {
2141 relocate_syms(s1, 0);
2143 if (s1->nb_errors != 0) {
2144 fail:
2145 ret = -1;
2146 goto the_end;
2149 /* relocate sections */
2150 /* XXX: ignore sections with allocated relocations ? */
2151 for(i = 1; i < s1->nb_sections; i++) {
2152 s = s1->sections[i];
2153 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
2154 relocate_section(s1, s);
2157 /* relocate relocation entries if the relocation tables are
2158 allocated in the executable */
2159 for(i = 1; i < s1->nb_sections; i++) {
2160 s = s1->sections[i];
2161 if ((s->sh_flags & SHF_ALLOC) &&
2162 s->sh_type == SHT_RELX) {
2163 relocate_rel(s1, s);
2167 /* get entry point address */
2168 if (file_type == TCC_OUTPUT_EXE)
2169 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
2170 else
2171 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2173 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2174 fill_got(s1);
2176 /* write elf file */
2177 if (file_type == TCC_OUTPUT_OBJ)
2178 mode = 0666;
2179 else
2180 mode = 0777;
2181 unlink(filename);
2182 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2183 if (fd < 0) {
2184 tcc_error_noabort("could not write '%s'", filename);
2185 goto fail;
2187 f = fdopen(fd, "wb");
2188 if (s1->verbose)
2189 printf("<- %s\n", filename);
2191 #ifdef TCC_TARGET_COFF
2192 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2193 tcc_output_coff(s1, f);
2194 } else
2195 #endif
2196 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2197 sort_syms(s1, symtab_section);
2199 /* align to 4 */
2200 file_offset = (file_offset + 3) & -4;
2202 /* fill header */
2203 ehdr.e_ident[0] = ELFMAG0;
2204 ehdr.e_ident[1] = ELFMAG1;
2205 ehdr.e_ident[2] = ELFMAG2;
2206 ehdr.e_ident[3] = ELFMAG3;
2207 ehdr.e_ident[4] = ELFCLASSW;
2208 ehdr.e_ident[5] = ELFDATA2LSB;
2209 ehdr.e_ident[6] = EV_CURRENT;
2210 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2211 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2212 #endif
2213 #ifdef TCC_TARGET_ARM
2214 #ifdef TCC_ARM_EABI
2215 ehdr.e_ident[EI_OSABI] = 0;
2216 ehdr.e_flags = 4 << 24;
2217 #else
2218 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2219 #endif
2220 #endif
2221 switch(file_type) {
2222 default:
2223 case TCC_OUTPUT_EXE:
2224 ehdr.e_type = ET_EXEC;
2225 break;
2226 case TCC_OUTPUT_DLL:
2227 ehdr.e_type = ET_DYN;
2228 break;
2229 case TCC_OUTPUT_OBJ:
2230 ehdr.e_type = ET_REL;
2231 break;
2233 ehdr.e_machine = EM_TCC_TARGET;
2234 ehdr.e_version = EV_CURRENT;
2235 ehdr.e_shoff = file_offset;
2236 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2237 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2238 ehdr.e_shnum = shnum;
2239 ehdr.e_shstrndx = shnum - 1;
2241 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2242 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2243 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2245 for(i=1;i<s1->nb_sections;i++) {
2246 s = s1->sections[section_order[i]];
2247 if (s->sh_type != SHT_NOBITS) {
2248 if (s->sh_type == SHT_DYNSYM)
2249 patch_dynsym_undef(s1, s);
2250 while (offset < s->sh_offset) {
2251 fputc(0, f);
2252 offset++;
2254 size = s->sh_size;
2255 fwrite(s->data, 1, size, f);
2256 offset += size;
2260 /* output section headers */
2261 while (offset < ehdr.e_shoff) {
2262 fputc(0, f);
2263 offset++;
2266 for(i=0;i<s1->nb_sections;i++) {
2267 sh = &shdr;
2268 memset(sh, 0, sizeof(ElfW(Shdr)));
2269 s = s1->sections[i];
2270 if (s) {
2271 sh->sh_name = s->sh_name;
2272 sh->sh_type = s->sh_type;
2273 sh->sh_flags = s->sh_flags;
2274 sh->sh_entsize = s->sh_entsize;
2275 sh->sh_info = s->sh_info;
2276 if (s->link)
2277 sh->sh_link = s->link->sh_num;
2278 sh->sh_addralign = s->sh_addralign;
2279 sh->sh_addr = s->sh_addr;
2280 sh->sh_offset = s->sh_offset;
2281 sh->sh_size = s->sh_size;
2283 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2285 } else {
2286 tcc_output_binary(s1, f, section_order);
2288 fclose(f);
2290 ret = 0;
2291 the_end:
2292 tcc_free(s1->symtab_to_dynsym);
2293 tcc_free(section_order);
2294 tcc_free(phdr);
2295 tcc_free(s1->got_offsets);
2296 return ret;
2299 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2301 int ret;
2302 #ifdef TCC_TARGET_PE
2303 if (s->output_type != TCC_OUTPUT_OBJ) {
2304 ret = pe_output_file(s, filename);
2305 } else
2306 #endif
2308 ret = elf_output_file(s, filename);
2310 return ret;
2313 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2315 void *data;
2317 data = tcc_malloc(size);
2318 lseek(fd, file_offset, SEEK_SET);
2319 read(fd, data, size);
2320 return data;
2323 typedef struct SectionMergeInfo {
2324 Section *s; /* corresponding existing section */
2325 unsigned long offset; /* offset of the new section in the existing section */
2326 uint8_t new_section; /* true if section 's' was added */
2327 uint8_t link_once; /* true if link once section */
2328 } SectionMergeInfo;
2330 /* load an object file and merge it with current files */
2331 /* XXX: handle correctly stab (debug) info */
2332 ST_FUNC int tcc_load_object_file(TCCState *s1,
2333 int fd, unsigned long file_offset)
2335 ElfW(Ehdr) ehdr;
2336 ElfW(Shdr) *shdr, *sh;
2337 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2338 unsigned char *strsec, *strtab;
2339 int *old_to_new_syms;
2340 char *sh_name, *name;
2341 SectionMergeInfo *sm_table, *sm;
2342 ElfW(Sym) *sym, *symtab;
2343 ElfW_Rel *rel, *rel_end;
2344 Section *s;
2346 int stab_index;
2347 int stabstr_index;
2349 stab_index = stabstr_index = 0;
2351 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2352 goto fail1;
2353 if (ehdr.e_ident[0] != ELFMAG0 ||
2354 ehdr.e_ident[1] != ELFMAG1 ||
2355 ehdr.e_ident[2] != ELFMAG2 ||
2356 ehdr.e_ident[3] != ELFMAG3)
2357 goto fail1;
2358 /* test if object file */
2359 if (ehdr.e_type != ET_REL)
2360 goto fail1;
2361 /* test CPU specific stuff */
2362 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2363 ehdr.e_machine != EM_TCC_TARGET) {
2364 fail1:
2365 tcc_error_noabort("invalid object file");
2366 return -1;
2368 /* read sections */
2369 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2370 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2371 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2373 /* load section names */
2374 sh = &shdr[ehdr.e_shstrndx];
2375 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2377 /* load symtab and strtab */
2378 old_to_new_syms = NULL;
2379 symtab = NULL;
2380 strtab = NULL;
2381 nb_syms = 0;
2382 for(i = 1; i < ehdr.e_shnum; i++) {
2383 sh = &shdr[i];
2384 if (sh->sh_type == SHT_SYMTAB) {
2385 if (symtab) {
2386 tcc_error_noabort("object must contain only one symtab");
2387 fail:
2388 ret = -1;
2389 goto the_end;
2391 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2392 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2393 sm_table[i].s = symtab_section;
2395 /* now load strtab */
2396 sh = &shdr[sh->sh_link];
2397 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2401 /* now examine each section and try to merge its content with the
2402 ones in memory */
2403 for(i = 1; i < ehdr.e_shnum; i++) {
2404 /* no need to examine section name strtab */
2405 if (i == ehdr.e_shstrndx)
2406 continue;
2407 sh = &shdr[i];
2408 sh_name = strsec + sh->sh_name;
2409 /* ignore sections types we do not handle */
2410 if (sh->sh_type != SHT_PROGBITS &&
2411 sh->sh_type != SHT_RELX &&
2412 #ifdef TCC_ARM_EABI
2413 sh->sh_type != SHT_ARM_EXIDX &&
2414 #endif
2415 sh->sh_type != SHT_NOBITS &&
2416 sh->sh_type != SHT_PREINIT_ARRAY &&
2417 sh->sh_type != SHT_INIT_ARRAY &&
2418 sh->sh_type != SHT_FINI_ARRAY &&
2419 strcmp(sh_name, ".stabstr")
2421 continue;
2422 if (sh->sh_addralign < 1)
2423 sh->sh_addralign = 1;
2424 /* find corresponding section, if any */
2425 for(j = 1; j < s1->nb_sections;j++) {
2426 s = s1->sections[j];
2427 if (!strcmp(s->name, sh_name)) {
2428 if (!strncmp(sh_name, ".gnu.linkonce",
2429 sizeof(".gnu.linkonce") - 1)) {
2430 /* if a 'linkonce' section is already present, we
2431 do not add it again. It is a little tricky as
2432 symbols can still be defined in
2433 it. */
2434 sm_table[i].link_once = 1;
2435 goto next;
2436 } else {
2437 goto found;
2441 /* not found: create new section */
2442 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2443 /* take as much info as possible from the section. sh_link and
2444 sh_info will be updated later */
2445 s->sh_addralign = sh->sh_addralign;
2446 s->sh_entsize = sh->sh_entsize;
2447 sm_table[i].new_section = 1;
2448 found:
2449 if (sh->sh_type != s->sh_type) {
2450 tcc_error_noabort("invalid section type");
2451 goto fail;
2454 /* align start of section */
2455 offset = s->data_offset;
2457 if (0 == strcmp(sh_name, ".stab")) {
2458 stab_index = i;
2459 goto no_align;
2461 if (0 == strcmp(sh_name, ".stabstr")) {
2462 stabstr_index = i;
2463 goto no_align;
2466 size = sh->sh_addralign - 1;
2467 offset = (offset + size) & ~size;
2468 if (sh->sh_addralign > s->sh_addralign)
2469 s->sh_addralign = sh->sh_addralign;
2470 s->data_offset = offset;
2471 no_align:
2472 sm_table[i].offset = offset;
2473 sm_table[i].s = s;
2474 /* concatenate sections */
2475 size = sh->sh_size;
2476 if (sh->sh_type != SHT_NOBITS) {
2477 unsigned char *ptr;
2478 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2479 ptr = section_ptr_add(s, size);
2480 read(fd, ptr, size);
2481 } else {
2482 s->data_offset += size;
2484 next: ;
2487 /* //gr relocate stab strings */
2488 if (stab_index && stabstr_index) {
2489 Stab_Sym *a, *b;
2490 unsigned o;
2491 s = sm_table[stab_index].s;
2492 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2493 b = (Stab_Sym *)(s->data + s->data_offset);
2494 o = sm_table[stabstr_index].offset;
2495 while (a < b)
2496 a->n_strx += o, a++;
2499 /* second short pass to update sh_link and sh_info fields of new
2500 sections */
2501 for(i = 1; i < ehdr.e_shnum; i++) {
2502 s = sm_table[i].s;
2503 if (!s || !sm_table[i].new_section)
2504 continue;
2505 sh = &shdr[i];
2506 if (sh->sh_link > 0)
2507 s->link = sm_table[sh->sh_link].s;
2508 if (sh->sh_type == SHT_RELX) {
2509 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2510 /* update backward link */
2511 s1->sections[s->sh_info]->reloc = s;
2514 sm = sm_table;
2516 /* resolve symbols */
2517 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2519 sym = symtab + 1;
2520 for(i = 1; i < nb_syms; i++, sym++) {
2521 if (sym->st_shndx != SHN_UNDEF &&
2522 sym->st_shndx < SHN_LORESERVE) {
2523 sm = &sm_table[sym->st_shndx];
2524 if (sm->link_once) {
2525 /* if a symbol is in a link once section, we use the
2526 already defined symbol. It is very important to get
2527 correct relocations */
2528 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2529 name = strtab + sym->st_name;
2530 sym_index = find_elf_sym(symtab_section, name);
2531 if (sym_index)
2532 old_to_new_syms[i] = sym_index;
2534 continue;
2536 /* if no corresponding section added, no need to add symbol */
2537 if (!sm->s)
2538 continue;
2539 /* convert section number */
2540 sym->st_shndx = sm->s->sh_num;
2541 /* offset value */
2542 sym->st_value += sm->offset;
2544 /* add symbol */
2545 name = strtab + sym->st_name;
2546 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2547 sym->st_info, sym->st_other,
2548 sym->st_shndx, name);
2549 old_to_new_syms[i] = sym_index;
2552 /* third pass to patch relocation entries */
2553 for(i = 1; i < ehdr.e_shnum; i++) {
2554 s = sm_table[i].s;
2555 if (!s)
2556 continue;
2557 sh = &shdr[i];
2558 offset = sm_table[i].offset;
2559 switch(s->sh_type) {
2560 case SHT_RELX:
2561 /* take relocation offset information */
2562 offseti = sm_table[sh->sh_info].offset;
2563 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2564 for(rel = (ElfW_Rel *)(s->data + offset);
2565 rel < rel_end;
2566 rel++) {
2567 int type;
2568 unsigned sym_index;
2569 /* convert symbol index */
2570 type = ELFW(R_TYPE)(rel->r_info);
2571 sym_index = ELFW(R_SYM)(rel->r_info);
2572 /* NOTE: only one symtab assumed */
2573 if (sym_index >= nb_syms)
2574 goto invalid_reloc;
2575 sym_index = old_to_new_syms[sym_index];
2576 /* ignore link_once in rel section. */
2577 if (!sym_index && !sm->link_once
2578 #ifdef TCC_TARGET_ARM
2579 && type != R_ARM_V4BX
2580 #endif
2582 invalid_reloc:
2583 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2584 i, strsec + sh->sh_name, rel->r_offset);
2585 goto fail;
2587 rel->r_info = ELFW(R_INFO)(sym_index, type);
2588 /* offset the relocation offset */
2589 rel->r_offset += offseti;
2591 break;
2592 default:
2593 break;
2597 ret = 0;
2598 the_end:
2599 tcc_free(symtab);
2600 tcc_free(strtab);
2601 tcc_free(old_to_new_syms);
2602 tcc_free(sm_table);
2603 tcc_free(strsec);
2604 tcc_free(shdr);
2605 return ret;
2608 typedef struct ArchiveHeader {
2609 char ar_name[16]; /* name of this member */
2610 char ar_date[12]; /* file mtime */
2611 char ar_uid[6]; /* owner uid; printed as decimal */
2612 char ar_gid[6]; /* owner gid; printed as decimal */
2613 char ar_mode[8]; /* file mode, printed as octal */
2614 char ar_size[10]; /* file size, printed as decimal */
2615 char ar_fmag[2]; /* should contain ARFMAG */
2616 } ArchiveHeader;
2618 static int get_be32(const uint8_t *b)
2620 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2623 /* load only the objects which resolve undefined symbols */
2624 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2626 int i, bound, nsyms, sym_index, off, ret;
2627 uint8_t *data;
2628 const char *ar_names, *p;
2629 const uint8_t *ar_index;
2630 ElfW(Sym) *sym;
2632 data = tcc_malloc(size);
2633 if (read(fd, data, size) != size)
2634 goto fail;
2635 nsyms = get_be32(data);
2636 ar_index = data + 4;
2637 ar_names = ar_index + nsyms * 4;
2639 do {
2640 bound = 0;
2641 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2642 sym_index = find_elf_sym(symtab_section, p);
2643 if(sym_index) {
2644 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2645 if(sym->st_shndx == SHN_UNDEF) {
2646 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2647 #if 0
2648 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2649 #endif
2650 ++bound;
2651 lseek(fd, off, SEEK_SET);
2652 if(tcc_load_object_file(s1, fd, off) < 0) {
2653 fail:
2654 ret = -1;
2655 goto the_end;
2660 } while(bound);
2661 ret = 0;
2662 the_end:
2663 tcc_free(data);
2664 return ret;
2667 /* load a '.a' file */
2668 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2670 ArchiveHeader hdr;
2671 char ar_size[11];
2672 char ar_name[17];
2673 char magic[8];
2674 int size, len, i;
2675 unsigned long file_offset;
2677 /* skip magic which was already checked */
2678 read(fd, magic, sizeof(magic));
2680 for(;;) {
2681 len = read(fd, &hdr, sizeof(hdr));
2682 if (len == 0)
2683 break;
2684 if (len != sizeof(hdr)) {
2685 tcc_error_noabort("invalid archive");
2686 return -1;
2688 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2689 ar_size[sizeof(hdr.ar_size)] = '\0';
2690 size = strtol(ar_size, NULL, 0);
2691 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2692 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2693 if (ar_name[i] != ' ')
2694 break;
2696 ar_name[i + 1] = '\0';
2697 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2698 file_offset = lseek(fd, 0, SEEK_CUR);
2699 /* align to even */
2700 size = (size + 1) & ~1;
2701 if (!strcmp(ar_name, "/")) {
2702 /* coff symbol table : we handle it */
2703 if(s1->alacarte_link)
2704 return tcc_load_alacarte(s1, fd, size);
2705 } else if (!strcmp(ar_name, "//") ||
2706 !strcmp(ar_name, "__.SYMDEF") ||
2707 !strcmp(ar_name, "__.SYMDEF/") ||
2708 !strcmp(ar_name, "ARFILENAMES/")) {
2709 /* skip symbol table or archive names */
2710 } else {
2711 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2712 return -1;
2714 lseek(fd, file_offset + size, SEEK_SET);
2716 return 0;
2719 #ifndef TCC_TARGET_PE
2720 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2721 is referenced by the user (so it should be added as DT_NEEDED in
2722 the generated ELF file) */
2723 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2725 ElfW(Ehdr) ehdr;
2726 ElfW(Shdr) *shdr, *sh, *sh1;
2727 int i, j, nb_syms, nb_dts, sym_bind, ret;
2728 ElfW(Sym) *sym, *dynsym;
2729 ElfW(Dyn) *dt, *dynamic;
2730 unsigned char *dynstr;
2731 const char *name, *soname;
2732 DLLReference *dllref;
2734 read(fd, &ehdr, sizeof(ehdr));
2736 /* test CPU specific stuff */
2737 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2738 ehdr.e_machine != EM_TCC_TARGET) {
2739 tcc_error_noabort("bad architecture");
2740 return -1;
2743 /* read sections */
2744 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2746 /* load dynamic section and dynamic symbols */
2747 nb_syms = 0;
2748 nb_dts = 0;
2749 dynamic = NULL;
2750 dynsym = NULL; /* avoid warning */
2751 dynstr = NULL; /* avoid warning */
2752 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2753 switch(sh->sh_type) {
2754 case SHT_DYNAMIC:
2755 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2756 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2757 break;
2758 case SHT_DYNSYM:
2759 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2760 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2761 sh1 = &shdr[sh->sh_link];
2762 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2763 break;
2764 default:
2765 break;
2769 /* compute the real library name */
2770 soname = tcc_basename(filename);
2772 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2773 if (dt->d_tag == DT_SONAME) {
2774 soname = dynstr + dt->d_un.d_val;
2778 /* if the dll is already loaded, do not load it */
2779 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2780 dllref = s1->loaded_dlls[i];
2781 if (!strcmp(soname, dllref->name)) {
2782 /* but update level if needed */
2783 if (level < dllref->level)
2784 dllref->level = level;
2785 ret = 0;
2786 goto the_end;
2790 // printf("loading dll '%s'\n", soname);
2792 /* add the dll and its level */
2793 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2794 dllref->level = level;
2795 strcpy(dllref->name, soname);
2796 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2798 /* add dynamic symbols in dynsym_section */
2799 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2800 sym_bind = ELFW(ST_BIND)(sym->st_info);
2801 if (sym_bind == STB_LOCAL)
2802 continue;
2803 name = dynstr + sym->st_name;
2804 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2805 sym->st_info, sym->st_other, sym->st_shndx, name);
2808 /* load all referenced DLLs */
2809 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2810 switch(dt->d_tag) {
2811 case DT_NEEDED:
2812 name = dynstr + dt->d_un.d_val;
2813 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2814 dllref = s1->loaded_dlls[j];
2815 if (!strcmp(name, dllref->name))
2816 goto already_loaded;
2818 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2819 tcc_error_noabort("referenced dll '%s' not found", name);
2820 ret = -1;
2821 goto the_end;
2823 already_loaded:
2824 break;
2827 ret = 0;
2828 the_end:
2829 tcc_free(dynstr);
2830 tcc_free(dynsym);
2831 tcc_free(dynamic);
2832 tcc_free(shdr);
2833 return ret;
2836 #define LD_TOK_NAME 256
2837 #define LD_TOK_EOF (-1)
2839 /* return next ld script token */
2840 static int ld_next(TCCState *s1, char *name, int name_size)
2842 int c;
2843 char *q;
2845 redo:
2846 switch(ch) {
2847 case ' ':
2848 case '\t':
2849 case '\f':
2850 case '\v':
2851 case '\r':
2852 case '\n':
2853 inp();
2854 goto redo;
2855 case '/':
2856 minp();
2857 if (ch == '*') {
2858 file->buf_ptr = parse_comment(file->buf_ptr);
2859 ch = file->buf_ptr[0];
2860 goto redo;
2861 } else {
2862 q = name;
2863 *q++ = '/';
2864 goto parse_name;
2866 break;
2867 /* case 'a' ... 'z': */
2868 case 'a':
2869 case 'b':
2870 case 'c':
2871 case 'd':
2872 case 'e':
2873 case 'f':
2874 case 'g':
2875 case 'h':
2876 case 'i':
2877 case 'j':
2878 case 'k':
2879 case 'l':
2880 case 'm':
2881 case 'n':
2882 case 'o':
2883 case 'p':
2884 case 'q':
2885 case 'r':
2886 case 's':
2887 case 't':
2888 case 'u':
2889 case 'v':
2890 case 'w':
2891 case 'x':
2892 case 'y':
2893 case 'z':
2894 /* case 'A' ... 'z': */
2895 case 'A':
2896 case 'B':
2897 case 'C':
2898 case 'D':
2899 case 'E':
2900 case 'F':
2901 case 'G':
2902 case 'H':
2903 case 'I':
2904 case 'J':
2905 case 'K':
2906 case 'L':
2907 case 'M':
2908 case 'N':
2909 case 'O':
2910 case 'P':
2911 case 'Q':
2912 case 'R':
2913 case 'S':
2914 case 'T':
2915 case 'U':
2916 case 'V':
2917 case 'W':
2918 case 'X':
2919 case 'Y':
2920 case 'Z':
2921 case '_':
2922 case '\\':
2923 case '.':
2924 case '$':
2925 case '~':
2926 q = name;
2927 parse_name:
2928 for(;;) {
2929 if (!((ch >= 'a' && ch <= 'z') ||
2930 (ch >= 'A' && ch <= 'Z') ||
2931 (ch >= '0' && ch <= '9') ||
2932 strchr("/.-_+=$:\\,~", ch)))
2933 break;
2934 if ((q - name) < name_size - 1) {
2935 *q++ = ch;
2937 minp();
2939 *q = '\0';
2940 c = LD_TOK_NAME;
2941 break;
2942 case CH_EOF:
2943 c = LD_TOK_EOF;
2944 break;
2945 default:
2946 c = ch;
2947 inp();
2948 break;
2950 #if 0
2951 printf("tok=%c %d\n", c, c);
2952 if (c == LD_TOK_NAME)
2953 printf(" name=%s\n", name);
2954 #endif
2955 return c;
2959 * Extract the file name from the library name
2961 * /!\ No test on filename capacity, be careful
2963 static void libname_to_filename(TCCState *s1, const char libname[], char filename[])
2965 if (!s1->static_link) {
2966 sprintf(filename, "lib%s.so", libname);
2967 } else {
2968 sprintf(filename, "lib%s.a", libname);
2972 static int ld_add_file(TCCState *s1, const char filename[])
2974 int ret;
2976 ret = tcc_add_file_internal(s1, filename, 0);
2977 if (ret)
2978 ret = tcc_add_dll(s1, filename, 0);
2979 return ret;
2982 static inline int new_undef_syms(void)
2984 int ret = 0;
2985 ret = new_undef_sym;
2986 new_undef_sym = 0;
2987 return ret;
2990 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
2992 char filename[1024], libname[1024];
2993 int t, group, nblibs = 0, ret = 0;
2994 char **libs = NULL;
2996 group = !strcmp(cmd, "GROUP");
2997 if (!as_needed)
2998 new_undef_syms();
2999 t = ld_next(s1, filename, sizeof(filename));
3000 if (t != '(')
3001 expect("(");
3002 t = ld_next(s1, filename, sizeof(filename));
3003 for(;;) {
3004 libname[0] = '\0';
3005 if (t == LD_TOK_EOF) {
3006 tcc_error_noabort("unexpected end of file");
3007 ret = -1;
3008 goto lib_parse_error;
3009 } else if (t == ')') {
3010 break;
3011 } else if (t == '-') {
3012 t = ld_next(s1, filename, sizeof(filename));
3013 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
3014 tcc_error_noabort("library name expected");
3015 ret = -1;
3016 goto lib_parse_error;
3018 strcpy(libname, &filename[1]);
3019 libname_to_filename(s1, libname, filename);
3020 } else if (t != LD_TOK_NAME) {
3021 tcc_error_noabort("filename expected");
3022 ret = -1;
3023 goto lib_parse_error;
3025 if (!strcmp(filename, "AS_NEEDED")) {
3026 ret = ld_add_file_list(s1, cmd, 1);
3027 if (ret)
3028 goto lib_parse_error;
3029 } else {
3030 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3031 if (!as_needed) {
3032 ret = ld_add_file(s1, filename);
3033 if (ret)
3034 goto lib_parse_error;
3035 if (group) {
3036 /* Add the filename *and* the libname to avoid future conversions */
3037 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
3038 if (libname[0] != '\0')
3039 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
3043 t = ld_next(s1, filename, sizeof(filename));
3044 if (t == ',') {
3045 t = ld_next(s1, filename, sizeof(filename));
3048 if (group && !as_needed) {
3049 while (new_undef_syms()) {
3050 int i;
3052 for (i = 0; i < nblibs; i ++)
3053 ld_add_file(s1, libs[i]);
3056 lib_parse_error:
3057 dynarray_reset(&libs, &nblibs);
3058 return ret;
3061 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3062 files */
3063 ST_FUNC int tcc_load_ldscript(TCCState *s1)
3065 char cmd[64];
3066 char filename[1024];
3067 int t, ret;
3069 ch = file->buf_ptr[0];
3070 ch = handle_eob();
3071 for(;;) {
3072 t = ld_next(s1, cmd, sizeof(cmd));
3073 if (t == LD_TOK_EOF)
3074 return 0;
3075 else if (t != LD_TOK_NAME)
3076 return -1;
3077 if (!strcmp(cmd, "INPUT") ||
3078 !strcmp(cmd, "GROUP")) {
3079 ret = ld_add_file_list(s1, cmd, 0);
3080 if (ret)
3081 return ret;
3082 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3083 !strcmp(cmd, "TARGET")) {
3084 /* ignore some commands */
3085 t = ld_next(s1, cmd, sizeof(cmd));
3086 if (t != '(')
3087 expect("(");
3088 for(;;) {
3089 t = ld_next(s1, filename, sizeof(filename));
3090 if (t == LD_TOK_EOF) {
3091 tcc_error_noabort("unexpected end of file");
3092 return -1;
3093 } else if (t == ')') {
3094 break;
3097 } else {
3098 return -1;
3101 return 0;
3103 #endif /* ndef TCC_TARGET_PE */