Improve ELF on ARM
[tinycc.git] / tccelf.c
blob92ea449b84ca0b823f3c2032cfea63a7b3fd06d9
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, addr_t value, unsigned long size,
88 int info, int other, int shndx, const char *name)
90 int name_offset, sym_index;
91 int nbuckets, h;
92 ElfW(Sym) *sym;
93 Section *hs;
95 sym = section_ptr_add(s, sizeof(ElfW(Sym)));
96 if (name)
97 name_offset = put_elf_str(s->link, name);
98 else
99 name_offset = 0;
100 /* XXX: endianness */
101 sym->st_name = name_offset;
102 sym->st_value = value;
103 sym->st_size = size;
104 sym->st_info = info;
105 sym->st_other = other;
106 sym->st_shndx = shndx;
107 sym_index = sym - (ElfW(Sym) *)s->data;
108 hs = s->hash;
109 if (hs) {
110 int *ptr, *base;
111 ptr = section_ptr_add(hs, sizeof(int));
112 base = (int *)hs->data;
113 /* only add global or weak symbols */
114 if (ELFW(ST_BIND)(info) != STB_LOCAL) {
115 /* add another hashing entry */
116 nbuckets = base[0];
117 h = elf_hash(name) % nbuckets;
118 *ptr = base[2 + h];
119 base[2 + h] = sym_index;
120 base[1]++;
121 /* we resize the hash table */
122 hs->nb_hashed_syms++;
123 if (hs->nb_hashed_syms > 2 * nbuckets) {
124 rebuild_hash(s, 2 * nbuckets);
126 } else {
127 *ptr = 0;
128 base[1]++;
131 return sym_index;
134 /* find global ELF symbol 'name' and return its index. Return 0 if not
135 found. */
136 ST_FUNC int find_elf_sym(Section *s, const char *name)
138 ElfW(Sym) *sym;
139 Section *hs;
140 int nbuckets, sym_index, h;
141 const char *name1;
143 hs = s->hash;
144 if (!hs)
145 return 0;
146 nbuckets = ((int *)hs->data)[0];
147 h = elf_hash(name) % nbuckets;
148 sym_index = ((int *)hs->data)[2 + h];
149 while (sym_index != 0) {
150 sym = &((ElfW(Sym) *)s->data)[sym_index];
151 name1 = s->link->data + sym->st_name;
152 if (!strcmp(name, name1))
153 return sym_index;
154 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
156 return 0;
159 /* return elf symbol value, signal error if 'err' is nonzero */
160 ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err)
162 int sym_index;
163 ElfW(Sym) *sym;
165 sym_index = find_elf_sym(s->symtab, name);
166 sym = &((ElfW(Sym) *)s->symtab->data)[sym_index];
167 if (!sym_index || sym->st_shndx == SHN_UNDEF) {
168 if (err)
169 tcc_error("%s not defined", name);
170 return 0;
172 return sym->st_value;
175 /* return elf symbol value */
176 LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
178 return (void*)(uintptr_t)get_elf_sym_addr(s, name, 0);
181 #if defined TCC_IS_NATIVE || defined TCC_TARGET_PE
182 /* return elf symbol value or error */
183 ST_FUNC void* tcc_get_symbol_err(TCCState *s, const char *name)
185 return (void*)(uintptr_t)get_elf_sym_addr(s, name, 1);
187 #endif
189 /* add an elf symbol : check if it is already defined and patch
190 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
191 ST_FUNC int add_elf_sym(Section *s, addr_t value, unsigned long size,
192 int info, int other, int sh_num, const char *name)
194 ElfW(Sym) *esym;
195 int sym_bind, sym_index, sym_type, esym_bind;
196 unsigned char sym_vis, esym_vis, new_vis;
198 sym_bind = ELFW(ST_BIND)(info);
199 sym_type = ELFW(ST_TYPE)(info);
200 sym_vis = ELFW(ST_VISIBILITY)(other);
202 if (sym_bind != STB_LOCAL) {
203 /* we search global or weak symbols */
204 sym_index = find_elf_sym(s, name);
205 if (!sym_index)
206 goto do_def;
207 esym = &((ElfW(Sym) *)s->data)[sym_index];
208 if (esym->st_shndx != SHN_UNDEF) {
209 esym_bind = ELFW(ST_BIND)(esym->st_info);
210 /* propagate the most constraining visibility */
211 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
212 esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
213 if (esym_vis == STV_DEFAULT) {
214 new_vis = sym_vis;
215 } else if (sym_vis == STV_DEFAULT) {
216 new_vis = esym_vis;
217 } else {
218 new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
220 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
221 | new_vis;
222 other = esym->st_other; /* in case we have to patch esym */
223 if (sh_num == SHN_UNDEF) {
224 /* ignore adding of undefined symbol if the
225 corresponding symbol is already defined */
226 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
227 /* global overrides weak, so patch */
228 goto do_patch;
229 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
230 /* weak is ignored if already global */
231 } else if (sym_bind == STB_WEAK && esym_bind == STB_WEAK) {
232 /* keep first-found weak definition, ignore subsequents */
233 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
234 /* ignore hidden symbols after */
235 } else if (esym->st_shndx == SHN_COMMON
236 && (sh_num < SHN_LORESERVE || sh_num == SHN_COMMON)) {
237 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
238 No idea if this is the correct solution ... */
239 goto do_patch;
240 } else if (s == tcc_state->dynsymtab_section) {
241 /* we accept that two DLL define the same symbol */
242 } else {
243 #if 0
244 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
245 sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
246 #endif
247 tcc_error_noabort("'%s' defined twice", name);
249 } else {
250 do_patch:
251 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
252 esym->st_shndx = sh_num;
253 new_undef_sym = 1;
254 esym->st_value = value;
255 esym->st_size = size;
256 esym->st_other = other;
258 } else {
259 do_def:
260 sym_index = put_elf_sym(s, value, size,
261 ELFW(ST_INFO)(sym_bind, sym_type), other,
262 sh_num, name);
264 return sym_index;
267 /* put relocation */
268 ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
269 int type, int symbol)
271 char buf[256];
272 Section *sr;
273 ElfW_Rel *rel;
275 sr = s->reloc;
276 if (!sr) {
277 /* if no relocation section, create it */
278 snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
279 /* if the symtab is allocated, then we consider the relocation
280 are also */
281 sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
282 sr->sh_entsize = sizeof(ElfW_Rel);
283 sr->link = symtab;
284 sr->sh_info = s->sh_num;
285 s->reloc = sr;
287 rel = section_ptr_add(sr, sizeof(ElfW_Rel));
288 rel->r_offset = offset;
289 rel->r_info = ELFW(R_INFO)(symbol, type);
290 #ifdef TCC_TARGET_X86_64
291 rel->r_addend = 0;
292 #endif
295 /* put stab debug information */
297 ST_FUNC void put_stabs(const char *str, int type, int other, int desc,
298 unsigned long value)
300 Stab_Sym *sym;
302 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
303 if (str) {
304 sym->n_strx = put_elf_str(stabstr_section, str);
305 } else {
306 sym->n_strx = 0;
308 sym->n_type = type;
309 sym->n_other = other;
310 sym->n_desc = desc;
311 sym->n_value = value;
314 ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc,
315 unsigned long value, Section *sec, int sym_index)
317 put_stabs(str, type, other, desc, value);
318 put_elf_reloc(symtab_section, stab_section,
319 stab_section->data_offset - sizeof(unsigned int),
320 R_DATA_32, sym_index);
323 ST_FUNC void put_stabn(int type, int other, int desc, int value)
325 put_stabs(NULL, type, other, desc, value);
328 ST_FUNC void put_stabd(int type, int other, int desc)
330 put_stabs(NULL, type, other, desc, 0);
333 /* In an ELF file symbol table, the local symbols must appear below
334 the global and weak ones. Since TCC cannot sort it while generating
335 the code, we must do it after. All the relocation tables are also
336 modified to take into account the symbol table sorting */
337 static void sort_syms(TCCState *s1, Section *s)
339 int *old_to_new_syms;
340 ElfW(Sym) *new_syms;
341 int nb_syms, i;
342 ElfW(Sym) *p, *q;
343 ElfW_Rel *rel, *rel_end;
344 Section *sr;
345 int type, sym_index;
347 nb_syms = s->data_offset / sizeof(ElfW(Sym));
348 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
349 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
351 /* first pass for local symbols */
352 p = (ElfW(Sym) *)s->data;
353 q = new_syms;
354 for(i = 0; i < nb_syms; i++) {
355 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
356 old_to_new_syms[i] = q - new_syms;
357 *q++ = *p;
359 p++;
361 /* save the number of local symbols in section header */
362 s->sh_info = q - new_syms;
364 /* then second pass for non local symbols */
365 p = (ElfW(Sym) *)s->data;
366 for(i = 0; i < nb_syms; i++) {
367 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
368 old_to_new_syms[i] = q - new_syms;
369 *q++ = *p;
371 p++;
374 /* we copy the new symbols to the old */
375 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
376 tcc_free(new_syms);
378 /* now we modify all the relocations */
379 for(i = 1; i < s1->nb_sections; i++) {
380 sr = s1->sections[i];
381 if (sr->sh_type == SHT_RELX && sr->link == s) {
382 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
383 for(rel = (ElfW_Rel *)sr->data;
384 rel < rel_end;
385 rel++) {
386 sym_index = ELFW(R_SYM)(rel->r_info);
387 type = ELFW(R_TYPE)(rel->r_info);
388 sym_index = old_to_new_syms[sym_index];
389 rel->r_info = ELFW(R_INFO)(sym_index, type);
394 tcc_free(old_to_new_syms);
397 /* relocate common symbols in the .bss section */
398 ST_FUNC void relocate_common_syms(void)
400 ElfW(Sym) *sym, *sym_end;
401 unsigned long offset, align;
403 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
404 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
405 sym < sym_end;
406 sym++) {
407 if (sym->st_shndx == SHN_COMMON) {
408 /* align symbol */
409 align = sym->st_value;
410 offset = bss_section->data_offset;
411 offset = (offset + align - 1) & -align;
412 sym->st_value = offset;
413 sym->st_shndx = bss_section->sh_num;
414 offset += sym->st_size;
415 bss_section->data_offset = offset;
420 /* relocate symbol table, resolve undefined symbols if do_resolve is
421 true and output error if undefined symbol. */
422 ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
424 ElfW(Sym) *sym, *esym, *sym_end;
425 int sym_bind, sh_num, sym_index;
426 const char *name;
428 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
429 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
430 sym < sym_end;
431 sym++) {
432 sh_num = sym->st_shndx;
433 if (sh_num == SHN_UNDEF) {
434 name = strtab_section->data + sym->st_name;
435 if (do_resolve) {
436 #if defined TCC_IS_NATIVE && !defined _WIN32
437 void *addr;
438 name = symtab_section->link->data + sym->st_name;
439 addr = resolve_sym(s1, name);
440 if (addr) {
441 sym->st_value = (addr_t)addr;
442 goto found;
444 #endif
445 } else if (s1->dynsym) {
446 /* if dynamic symbol exist, then use it */
447 sym_index = find_elf_sym(s1->dynsym, name);
448 if (sym_index) {
449 esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
450 sym->st_value = esym->st_value;
451 goto found;
454 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
455 it */
456 if (!strcmp(name, "_fp_hw"))
457 goto found;
458 /* only weak symbols are accepted to be undefined. Their
459 value is zero */
460 sym_bind = ELFW(ST_BIND)(sym->st_info);
461 if (sym_bind == STB_WEAK) {
462 sym->st_value = 0;
463 } else {
464 tcc_error_noabort("undefined symbol '%s'", name);
466 } else if (sh_num < SHN_LORESERVE) {
467 /* add section base */
468 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
470 found: ;
474 #ifdef TCC_HAS_RUNTIME_PLTGOT
475 #ifdef TCC_TARGET_X86_64
476 #define JMP_TABLE_ENTRY_SIZE 14
477 static addr_t add_jmp_table(TCCState *s1, addr_t val)
479 char *p = s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset;
480 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
481 /* jmp *0x0(%rip) */
482 p[0] = 0xff;
483 p[1] = 0x25;
484 *(int *)(p + 2) = 0;
485 *(addr_t *)(p + 6) = val;
486 return (addr_t)p;
489 static addr_t add_got_table(TCCState *s1, addr_t val)
491 addr_t *p = (addr_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
492 s1->runtime_plt_and_got_offset += sizeof(addr_t);
493 *p = val;
494 return (addr_t)p;
496 #elif defined TCC_TARGET_ARM
497 #define JMP_TABLE_ENTRY_SIZE 8
498 static addr_t add_jmp_table(TCCState *s1, int val)
500 uint32_t *p = (uint32_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
501 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
502 /* ldr pc, [pc, #-4] */
503 p[0] = 0xE51FF004;
504 p[1] = val;
505 return (addr_t)p;
507 #endif
508 #endif /* def TCC_HAS_RUNTIME_PLTGOT */
510 /* relocate a given section (CPU dependent) */
511 ST_FUNC void relocate_section(TCCState *s1, Section *s)
513 Section *sr;
514 ElfW_Rel *rel, *rel_end, *qrel;
515 ElfW(Sym) *sym;
516 int type, sym_index;
517 unsigned char *ptr;
518 addr_t val, addr;
519 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
520 int esym_index;
521 #endif
523 sr = s->reloc;
524 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
525 qrel = (ElfW_Rel *)sr->data;
526 for(rel = qrel;
527 rel < rel_end;
528 rel++) {
529 ptr = s->data + rel->r_offset;
531 sym_index = ELFW(R_SYM)(rel->r_info);
532 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
533 val = sym->st_value;
534 #ifdef TCC_TARGET_X86_64
535 val += rel->r_addend;
536 #endif
537 type = ELFW(R_TYPE)(rel->r_info);
538 addr = s->sh_addr + rel->r_offset;
540 /* CPU specific */
541 switch(type) {
542 #if defined(TCC_TARGET_I386)
543 case R_386_32:
544 if (s1->output_type == TCC_OUTPUT_DLL) {
545 esym_index = s1->symtab_to_dynsym[sym_index];
546 qrel->r_offset = rel->r_offset;
547 if (esym_index) {
548 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
549 qrel++;
550 break;
551 } else {
552 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
553 qrel++;
556 *(int *)ptr += val;
557 break;
558 case R_386_PC32:
559 if (s1->output_type == TCC_OUTPUT_DLL) {
560 /* DLL relocation */
561 esym_index = s1->symtab_to_dynsym[sym_index];
562 if (esym_index) {
563 qrel->r_offset = rel->r_offset;
564 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
565 qrel++;
566 break;
569 *(int *)ptr += val - addr;
570 break;
571 case R_386_PLT32:
572 *(int *)ptr += val - addr;
573 break;
574 case R_386_GLOB_DAT:
575 case R_386_JMP_SLOT:
576 *(int *)ptr = val;
577 break;
578 case R_386_GOTPC:
579 *(int *)ptr += s1->got->sh_addr - addr;
580 break;
581 case R_386_GOTOFF:
582 *(int *)ptr += val - s1->got->sh_addr;
583 break;
584 case R_386_GOT32:
585 /* we load the got offset */
586 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
587 break;
588 case R_386_16:
589 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
590 output_file:
591 tcc_error("can only produce 16-bit binary files");
593 *(short *)ptr += val;
594 break;
595 case R_386_PC16:
596 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
597 goto output_file;
598 *(short *)ptr += val - addr;
599 break;
600 #elif defined(TCC_TARGET_ARM)
601 case R_ARM_PC24:
602 case R_ARM_CALL:
603 case R_ARM_JUMP24:
604 case R_ARM_PLT32:
606 int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko;
607 x = (*(int *) ptr) & 0xffffff;
608 (*(int *)ptr) &= 0xff000000;
609 if (x & 0x800000)
610 x -= 0x1000000;
611 x <<= 2;
612 blx_avail = (TCC_ARM_VERSION >= 5);
613 is_thumb = val & 1;
614 is_bl = (*(unsigned *) ptr) >> 24 == 0xeb;
615 is_call = (type == R_ARM_CALL || (type == R_ARM_PC24 && is_bl));
616 x += val - addr;
617 h = x & 2;
618 th_ko = (x & 3) && (!blx_avail || !is_call);
619 #ifdef TCC_HAS_RUNTIME_PLTGOT
620 if (s1->output_type == TCC_OUTPUT_MEMORY) {
621 if (th_ko || x >= 0x2000000 || x < -0x2000000) {
622 x += add_jmp_table(s1, val) - val; /* add veneer */
623 th_ko = (x & 3) && (!blx_avail || !is_call);
624 is_thumb = 0; /* Veneer uses ARM instructions */
627 #endif
628 if (th_ko || x >= 0x2000000 || x < -0x2000000)
629 tcc_error("can't relocate value at %x",addr);
630 x >>= 2;
631 x &= 0xffffff;
632 /* Only reached if blx is avail and it is a call */
633 if (is_thumb) {
634 x |= h << 24;
635 (*(int *)ptr) = 0xfa << 24; /* bl -> blx */
637 (*(int *) ptr) |= x;
639 break;
640 /* Since these relocations only concern Thumb-2 and blx instruction was
641 introduced before Thumb-2, we can assume blx is available and not
642 guard its use */
643 case R_ARM_THM_PC22:
644 case R_ARM_THM_JUMP24:
646 int x, hi, lo, s, j1, j2, i1, i2, imm10, imm11;
647 int to_thumb, is_call, to_plt, blx_bit = 1 << 12;
648 Section *plt;
650 /* weak reference */
651 if (sym->st_shndx == SHN_UNDEF &&
652 ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
653 break;
655 /* Get initial offset */
656 hi = (*(uint16_t *)ptr);
657 lo = (*(uint16_t *)(ptr+2));
658 s = (hi >> 10) & 1;
659 j1 = (lo >> 13) & 1;
660 j2 = (lo >> 11) & 1;
661 i1 = (j1 ^ s) ^ 1;
662 i2 = (j2 ^ s) ^ 1;
663 imm10 = hi & 0x3ff;
664 imm11 = lo & 0x7ff;
665 x = (s << 24) | (i1 << 23) | (i2 << 22) |
666 (imm10 << 12) | (imm11 << 1);
667 if (x & 0x01000000)
668 x -= 0x02000000;
670 /* Relocation infos */
671 to_thumb = val & 1;
672 plt = s1->plt;
673 to_plt = (val >= plt->sh_addr) &&
674 (val < plt->sh_addr + plt->data_offset);
675 is_call = (type == R_ARM_THM_PC22);
677 /* Compute final offset */
678 if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */
679 x -= 4;
680 x += val - addr;
681 if (!to_thumb && is_call) {
682 blx_bit = 0; /* bl -> blx */
683 x = (x + 3) & -4; /* Compute offset from aligned PC */
686 /* Check that relocation is possible
687 * offset must not be out of range
688 * if target is to be entered in arm mode:
689 - bit 1 must not set
690 - instruction must be a call (bl) or a jump to PLT */
691 if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
692 if (to_thumb || (val & 2) || (!is_call && !to_plt))
693 tcc_error("can't relocate value at %x",addr);
695 /* Compute and store final offset */
696 s = (x >> 24) & 1;
697 i1 = (x >> 23) & 1;
698 i2 = (x >> 22) & 1;
699 j1 = s ^ (i1 ^ 1);
700 j2 = s ^ (i2 ^ 1);
701 imm10 = (x >> 12) & 0x3ff;
702 imm11 = (x >> 1) & 0x7ff;
703 (*(uint16_t *)ptr) = (uint16_t) ((hi & 0xf800) |
704 (s << 10) | imm10);
705 (*(uint16_t *)(ptr+2)) = (uint16_t) ((lo & 0xc000) |
706 (j1 << 13) | blx_bit | (j2 << 11) |
707 imm11);
709 break;
710 case R_ARM_MOVT_ABS:
711 case R_ARM_MOVW_ABS_NC:
713 int x, imm4, imm12;
714 if (type == R_ARM_MOVT_ABS)
715 val >>= 16;
716 imm12 = val & 0xfff;
717 imm4 = (val >> 12) & 0xf;
718 x = (imm4 << 16) | imm12;
719 if (type == R_ARM_THM_MOVT_ABS)
720 *(int *)ptr |= x;
721 else
722 *(int *)ptr += x;
724 break;
725 case R_ARM_THM_MOVT_ABS:
726 case R_ARM_THM_MOVW_ABS_NC:
728 int x, i, imm4, imm3, imm8;
729 if (type == R_ARM_THM_MOVT_ABS)
730 val >>= 16;
731 imm8 = val & 0xff;
732 imm3 = (val >> 8) & 0x7;
733 i = (val >> 11) & 1;
734 imm4 = (val >> 12) & 0xf;
735 x = (imm3 << 28) | (imm8 << 16) | (i << 10) | imm4;
736 if (type == R_ARM_THM_MOVT_ABS)
737 *(int *)ptr |= x;
738 else
739 *(int *)ptr += x;
741 break;
742 case R_ARM_PREL31:
744 int x;
745 x = (*(int *)ptr) & 0x7fffffff;
746 (*(int *)ptr) &= 0x80000000;
747 x = (x * 2) / 2;
748 x += val - addr;
749 if((x^(x>>1))&0x40000000)
750 tcc_error("can't relocate value at %x",addr);
751 (*(int *)ptr) |= x & 0x7fffffff;
753 case R_ARM_ABS32:
754 *(int *)ptr += val;
755 break;
756 case R_ARM_REL32:
757 *(int *)ptr += val - addr;
758 break;
759 case R_ARM_GOTPC:
760 *(int *)ptr += s1->got->sh_addr - addr;
761 break;
762 case R_ARM_GOTOFF:
763 *(int *)ptr += val - s1->got->sh_addr;
764 break;
765 case R_ARM_GOT32:
766 /* we load the got offset */
767 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
768 break;
769 case R_ARM_COPY:
770 break;
771 case R_ARM_V4BX:
772 /* trade Thumb support for ARMv4 support */
773 if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
774 *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
775 break;
776 default:
777 fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
778 type, (unsigned)addr, ptr, (unsigned)val);
779 break;
780 #elif defined(TCC_TARGET_C67)
781 case R_C60_32:
782 *(int *)ptr += val;
783 break;
784 case R_C60LO16:
786 uint32_t orig;
788 /* put the low 16 bits of the absolute address */
789 // add to what is already there
791 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
792 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
794 //patch both at once - assumes always in pairs Low - High
796 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
797 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
799 break;
800 case R_C60HI16:
801 break;
802 default:
803 fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
804 type, (unsigned)addr, ptr, (unsigned)val);
805 break;
806 #elif defined(TCC_TARGET_X86_64)
807 case R_X86_64_64:
808 if (s1->output_type == TCC_OUTPUT_DLL) {
809 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
810 qrel->r_addend = *(long long *)ptr + val;
811 qrel++;
813 *(long long *)ptr += val;
814 break;
815 case R_X86_64_32:
816 case R_X86_64_32S:
817 if (s1->output_type == TCC_OUTPUT_DLL) {
818 /* XXX: this logic may depend on TCC's codegen
819 now TCC uses R_X86_64_32 even for a 64bit pointer */
820 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
821 qrel->r_addend = *(int *)ptr + val;
822 qrel++;
824 *(int *)ptr += val;
825 break;
827 case R_X86_64_PC32:
828 if (s1->output_type == TCC_OUTPUT_DLL) {
829 /* DLL relocation */
830 esym_index = s1->symtab_to_dynsym[sym_index];
831 if (esym_index) {
832 qrel->r_offset = rel->r_offset;
833 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
834 qrel->r_addend = *(int *)ptr;
835 qrel++;
836 break;
839 /* fall through */
840 case R_X86_64_PLT32: {
841 long long diff;
842 diff = (long long)val - addr;
843 if (diff <= -2147483647 || diff > 2147483647) {
844 #ifdef TCC_HAS_RUNTIME_PLTGOT
845 /* XXX: naive support for over 32bit jump */
846 if (s1->output_type == TCC_OUTPUT_MEMORY) {
847 val = (add_jmp_table(s1, val - rel->r_addend) +
848 rel->r_addend);
849 diff = val - addr;
851 #endif
852 if (diff <= -2147483647 || diff > 2147483647) {
853 tcc_error("internal error: relocation failed");
856 *(int *)ptr += diff;
858 break;
859 case R_X86_64_GLOB_DAT:
860 case R_X86_64_JUMP_SLOT:
861 /* They don't need addend */
862 *(int *)ptr = val - rel->r_addend;
863 break;
864 case R_X86_64_GOTPCREL:
865 #ifdef TCC_HAS_RUNTIME_PLTGOT
866 if (s1->output_type == TCC_OUTPUT_MEMORY) {
867 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
868 *(int *)ptr += val - addr;
869 break;
871 #endif
872 *(int *)ptr += (s1->got->sh_addr - addr +
873 s1->sym_attrs[sym_index].got_offset - 4);
874 break;
875 case R_X86_64_GOTTPOFF:
876 *(int *)ptr += val - s1->got->sh_addr;
877 break;
878 case R_X86_64_GOT32:
879 /* we load the got offset */
880 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
881 break;
882 #else
883 #error unsupported processor
884 #endif
887 /* if the relocation is allocated, we change its symbol table */
888 if (sr->sh_flags & SHF_ALLOC)
889 sr->link = s1->dynsym;
892 /* relocate relocation table in 'sr' */
893 static void relocate_rel(TCCState *s1, Section *sr)
895 Section *s;
896 ElfW_Rel *rel, *rel_end;
898 s = s1->sections[sr->sh_info];
899 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
900 for(rel = (ElfW_Rel *)sr->data;
901 rel < rel_end;
902 rel++) {
903 rel->r_offset += s->sh_addr;
907 /* count the number of dynamic relocations so that we can reserve
908 their space */
909 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
911 ElfW_Rel *rel, *rel_end;
912 int sym_index, esym_index, type, count;
914 count = 0;
915 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
916 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
917 sym_index = ELFW(R_SYM)(rel->r_info);
918 type = ELFW(R_TYPE)(rel->r_info);
919 switch(type) {
920 #if defined(TCC_TARGET_I386)
921 case R_386_32:
922 #elif defined(TCC_TARGET_X86_64)
923 case R_X86_64_32:
924 case R_X86_64_32S:
925 case R_X86_64_64:
926 #endif
927 count++;
928 break;
929 #if defined(TCC_TARGET_I386)
930 case R_386_PC32:
931 #elif defined(TCC_TARGET_X86_64)
932 case R_X86_64_PC32:
933 #endif
934 esym_index = s1->symtab_to_dynsym[sym_index];
935 if (esym_index)
936 count++;
937 break;
938 default:
939 break;
942 if (count) {
943 /* allocate the section */
944 sr->sh_flags |= SHF_ALLOC;
945 sr->sh_size = count * sizeof(ElfW_Rel);
947 return count;
950 static struct sym_attr *alloc_sym_attr(TCCState *s1, int index)
952 int n;
953 struct sym_attr *tab;
955 if (index >= s1->nb_sym_attrs) {
956 /* find immediately bigger power of 2 and reallocate array */
957 n = 1;
958 while (index >= n)
959 n *= 2;
960 tab = tcc_realloc(s1->sym_attrs, n * sizeof(*s1->sym_attrs));
961 s1->sym_attrs = tab;
962 memset(s1->sym_attrs + s1->nb_sym_attrs, 0,
963 (n - s1->nb_sym_attrs) * sizeof(*s1->sym_attrs));
964 s1->nb_sym_attrs = n;
966 return &s1->sym_attrs[index];
969 /* XXX: suppress that */
970 static void put32(unsigned char *p, uint32_t val)
972 p[0] = val;
973 p[1] = val >> 8;
974 p[2] = val >> 16;
975 p[3] = val >> 24;
978 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
979 defined(TCC_TARGET_X86_64)
980 static uint32_t get32(unsigned char *p)
982 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
984 #endif
986 static void build_got(TCCState *s1)
988 unsigned char *ptr;
990 /* if no got, then create it */
991 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
992 s1->got->sh_entsize = 4;
993 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
994 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
995 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
996 #if PTR_SIZE == 4
997 /* keep space for _DYNAMIC pointer, if present */
998 put32(ptr, 0);
999 /* two dummy got entries */
1000 put32(ptr + 4, 0);
1001 put32(ptr + 8, 0);
1002 #else
1003 /* keep space for _DYNAMIC pointer, if present */
1004 put32(ptr, 0);
1005 put32(ptr + 4, 0);
1006 /* two dummy got entries */
1007 put32(ptr + 8, 0);
1008 put32(ptr + 12, 0);
1009 put32(ptr + 16, 0);
1010 put32(ptr + 20, 0);
1011 #endif
1014 /* put a got entry corresponding to a symbol in symtab_section. 'size'
1015 and 'info' can be modifed if more precise info comes from the DLL */
1016 static void put_got_entry(TCCState *s1,
1017 int reloc_type, unsigned long size, int info,
1018 int sym_index)
1020 int index;
1021 const char *name;
1022 ElfW(Sym) *sym;
1023 unsigned long offset;
1024 int *ptr;
1026 if (!s1->got)
1027 build_got(s1);
1029 /* if a got entry already exists for that symbol, no need to add one */
1030 if (sym_index < s1->nb_sym_attrs &&
1031 s1->sym_attrs[sym_index].got_offset)
1032 return;
1034 alloc_sym_attr(s1, sym_index)->got_offset = s1->got->data_offset;
1036 if (s1->dynsym) {
1037 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1038 name = symtab_section->link->data + sym->st_name;
1039 offset = sym->st_value;
1040 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1041 if (reloc_type ==
1042 #ifdef TCC_TARGET_X86_64
1043 R_X86_64_JUMP_SLOT
1044 #else
1045 R_386_JMP_SLOT
1046 #endif
1048 Section *plt;
1049 uint8_t *p;
1050 int modrm;
1052 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1053 modrm = 0x25;
1054 #else
1055 /* if we build a DLL, we add a %ebx offset */
1056 if (s1->output_type == TCC_OUTPUT_DLL)
1057 modrm = 0xa3;
1058 else
1059 modrm = 0x25;
1060 #endif
1062 /* add a PLT entry */
1063 plt = s1->plt;
1064 if (plt->data_offset == 0) {
1065 /* first plt entry */
1066 p = section_ptr_add(plt, 16);
1067 p[0] = 0xff; /* pushl got + PTR_SIZE */
1068 p[1] = modrm + 0x10;
1069 put32(p + 2, PTR_SIZE);
1070 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1071 p[7] = modrm;
1072 put32(p + 8, PTR_SIZE * 2);
1075 p = section_ptr_add(plt, 16);
1076 p[0] = 0xff; /* jmp *(got + x) */
1077 p[1] = modrm;
1078 put32(p + 2, s1->got->data_offset);
1079 p[6] = 0x68; /* push $xxx */
1080 put32(p + 7, (plt->data_offset - 32) >> 1);
1081 p[11] = 0xe9; /* jmp plt_start */
1082 put32(p + 12, -(plt->data_offset));
1084 /* the symbol is modified so that it will be relocated to
1085 the PLT */
1086 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
1087 if (s1->output_type == TCC_OUTPUT_EXE)
1088 #endif
1089 offset = plt->data_offset - 16;
1091 #elif defined(TCC_TARGET_ARM)
1092 if (reloc_type == R_ARM_JUMP_SLOT) {
1093 Section *plt;
1094 uint8_t *p;
1096 /* if we build a DLL, we add a %ebx offset */
1097 if (s1->output_type == TCC_OUTPUT_DLL)
1098 tcc_error("DLLs unimplemented!");
1100 /* add a PLT entry */
1101 plt = s1->plt;
1102 if (plt->data_offset == 0) {
1103 /* first plt entry */
1104 p = section_ptr_add(plt, 16);
1105 put32(p , 0xe52de004);
1106 put32(p + 4, 0xe59fe010);
1107 put32(p + 8, 0xe08fe00e);
1108 put32(p + 12, 0xe5bef008);
1111 if (s1->sym_attrs[sym_index].plt_thumb_stub) {
1112 p = section_ptr_add(plt, 20);
1113 put32(p , 0x4778); // bx pc
1114 put32(p+2, 0x46c0); // nop
1115 p += 4;
1116 } else
1117 p = section_ptr_add(plt, 16);
1118 put32(p , 0xe59fc004); // ldr ip, [pc, #4] // offset in GOT
1119 put32(p+4, 0xe08fc00c); // add ip, pc, ip // absolute address or offset
1120 put32(p+8, 0xe59cf000); // ldr pc, [ip] // load absolute address or load offset
1121 put32(p+12, s1->got->data_offset);
1123 /* the symbol is modified so that it will be relocated to
1124 the PLT */
1125 if (s1->output_type == TCC_OUTPUT_EXE)
1126 offset = plt->data_offset - 16;
1128 #elif defined(TCC_TARGET_C67)
1129 tcc_error("C67 got not implemented");
1130 #else
1131 #error unsupported CPU
1132 #endif
1133 index = put_elf_sym(s1->dynsym, offset,
1134 size, info, 0, sym->st_shndx, name);
1135 /* put a got entry */
1136 put_elf_reloc(s1->dynsym, s1->got,
1137 s1->got->data_offset,
1138 reloc_type, index);
1140 ptr = section_ptr_add(s1->got, PTR_SIZE);
1141 *ptr = 0;
1144 /* build GOT and PLT entries */
1145 ST_FUNC void build_got_entries(TCCState *s1)
1147 Section *s;
1148 ElfW_Rel *rel, *rel_end;
1149 ElfW(Sym) *sym;
1150 int i, type, reloc_type, sym_index;
1152 for(i = 1; i < s1->nb_sections; i++) {
1153 s = s1->sections[i];
1154 if (s->sh_type != SHT_RELX)
1155 continue;
1156 /* no need to handle got relocations */
1157 if (s->link != symtab_section)
1158 continue;
1159 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1160 for(rel = (ElfW_Rel *)s->data;
1161 rel < rel_end;
1162 rel++) {
1163 type = ELFW(R_TYPE)(rel->r_info);
1164 switch(type) {
1165 #if defined(TCC_TARGET_I386)
1166 case R_386_GOT32:
1167 case R_386_GOTOFF:
1168 case R_386_GOTPC:
1169 case R_386_PLT32:
1170 if (!s1->got)
1171 build_got(s1);
1172 if (type == R_386_GOT32 || type == R_386_PLT32) {
1173 sym_index = ELFW(R_SYM)(rel->r_info);
1174 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1175 /* look at the symbol got offset. If none, then add one */
1176 if (type == R_386_GOT32)
1177 reloc_type = R_386_GLOB_DAT;
1178 else
1179 reloc_type = R_386_JMP_SLOT;
1180 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1181 sym_index);
1183 break;
1184 #elif defined(TCC_TARGET_ARM)
1185 case R_ARM_GOT32:
1186 case R_ARM_GOTOFF:
1187 case R_ARM_GOTPC:
1188 case R_ARM_PLT32:
1189 if (!s1->got)
1190 build_got(s1);
1191 if (type == R_ARM_GOT32 || type == R_ARM_PLT32) {
1192 sym_index = ELFW(R_SYM)(rel->r_info);
1193 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1194 /* look at the symbol got offset. If none, then add one */
1195 if (type == R_ARM_GOT32)
1196 reloc_type = R_ARM_GLOB_DAT;
1197 else
1198 reloc_type = R_ARM_JUMP_SLOT;
1199 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1200 sym_index);
1202 break;
1203 #elif defined(TCC_TARGET_C67)
1204 case R_C60_GOT32:
1205 case R_C60_GOTOFF:
1206 case R_C60_GOTPC:
1207 case R_C60_PLT32:
1208 if (!s1->got)
1209 build_got(s1);
1210 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1211 sym_index = ELFW(R_SYM)(rel->r_info);
1212 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1213 /* look at the symbol got offset. If none, then add one */
1214 if (type == R_C60_GOT32)
1215 reloc_type = R_C60_GLOB_DAT;
1216 else
1217 reloc_type = R_C60_JMP_SLOT;
1218 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1219 sym_index);
1221 break;
1222 #elif defined(TCC_TARGET_X86_64)
1223 case R_X86_64_GOT32:
1224 case R_X86_64_GOTTPOFF:
1225 case R_X86_64_GOTPCREL:
1226 case R_X86_64_PLT32:
1227 if (!s1->got)
1228 build_got(s1);
1229 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1230 type == R_X86_64_PLT32) {
1231 sym_index = ELFW(R_SYM)(rel->r_info);
1232 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1233 /* look at the symbol got offset. If none, then add one */
1234 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1235 reloc_type = R_X86_64_GLOB_DAT;
1236 else
1237 reloc_type = R_X86_64_JUMP_SLOT;
1238 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1239 sym_index);
1241 break;
1242 #else
1243 #error unsupported CPU
1244 #endif
1245 default:
1246 break;
1252 ST_FUNC Section *new_symtab(TCCState *s1,
1253 const char *symtab_name, int sh_type, int sh_flags,
1254 const char *strtab_name,
1255 const char *hash_name, int hash_sh_flags)
1257 Section *symtab, *strtab, *hash;
1258 int *ptr, nb_buckets;
1260 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1261 symtab->sh_entsize = sizeof(ElfW(Sym));
1262 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1263 put_elf_str(strtab, "");
1264 symtab->link = strtab;
1265 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1267 nb_buckets = 1;
1269 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1270 hash->sh_entsize = sizeof(int);
1271 symtab->hash = hash;
1272 hash->link = symtab;
1274 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1275 ptr[0] = nb_buckets;
1276 ptr[1] = 1;
1277 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1278 return symtab;
1281 /* put dynamic tag */
1282 static void put_dt(Section *dynamic, int dt, addr_t val)
1284 ElfW(Dyn) *dyn;
1285 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1286 dyn->d_tag = dt;
1287 dyn->d_un.d_val = val;
1290 static void add_init_array_defines(TCCState *s1, const char *section_name)
1292 Section *s;
1293 long end_offset;
1294 char sym_start[1024];
1295 char sym_end[1024];
1297 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1298 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1300 s = find_section(s1, section_name);
1301 if (!s) {
1302 end_offset = 0;
1303 s = data_section;
1304 } else {
1305 end_offset = s->data_offset;
1308 add_elf_sym(symtab_section,
1309 0, 0,
1310 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1311 s->sh_num, sym_start);
1312 add_elf_sym(symtab_section,
1313 end_offset, 0,
1314 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1315 s->sh_num, sym_end);
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 #ifdef TCC_TARGET_I386
1336 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1337 /* add 'call __bound_init()' in .init section */
1338 init_section = find_section(s1, ".init");
1339 pinit = section_ptr_add(init_section, 5);
1340 pinit[0] = 0xe8;
1341 put32(pinit + 1, -4);
1342 sym_index = find_elf_sym(symtab_section, "__bound_init");
1343 put_elf_reloc(symtab_section, init_section,
1344 init_section->data_offset - 4, R_386_PC32, sym_index);
1346 #endif
1347 #endif
1350 static inline int tcc_add_support(TCCState *s1, const char *filename)
1352 char buf[1024];
1353 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, filename);
1354 return tcc_add_file(s1, buf);
1357 /* add tcc runtime libraries */
1358 ST_FUNC void tcc_add_runtime(TCCState *s1)
1360 tcc_add_bcheck(s1);
1362 /* add libc */
1363 if (!s1->nostdlib) {
1364 tcc_add_library(s1, "c");
1365 #ifdef CONFIG_USE_LIBGCC
1366 if (!s1->static_link)
1367 tcc_add_file(s1, TCC_LIBGCC);
1368 #if !defined WITHOUT_LIBTCC
1369 else
1370 tcc_add_support(s1, "libtcc1.a");
1371 #endif
1372 #elif !defined WITHOUT_LIBTCC
1373 tcc_add_support(s1, "libtcc1.a");
1374 #endif
1375 /* add crt end if not memory output */
1376 if (s1->output_type != TCC_OUTPUT_MEMORY)
1377 tcc_add_crt(s1, "crtn.o");
1381 /* add various standard linker symbols (must be done after the
1382 sections are filled (for example after allocating common
1383 symbols)) */
1384 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1386 char buf[1024];
1387 int i;
1388 Section *s;
1390 add_elf_sym(symtab_section,
1391 text_section->data_offset, 0,
1392 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1393 text_section->sh_num, "_etext");
1394 add_elf_sym(symtab_section,
1395 data_section->data_offset, 0,
1396 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1397 data_section->sh_num, "_edata");
1398 add_elf_sym(symtab_section,
1399 bss_section->data_offset, 0,
1400 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1401 bss_section->sh_num, "_end");
1402 /* horrible new standard ldscript defines */
1403 add_init_array_defines(s1, ".preinit_array");
1404 add_init_array_defines(s1, ".init_array");
1405 add_init_array_defines(s1, ".fini_array");
1407 /* add start and stop symbols for sections whose name can be
1408 expressed in C */
1409 for(i = 1; i < s1->nb_sections; i++) {
1410 s = s1->sections[i];
1411 if (s->sh_type == SHT_PROGBITS &&
1412 (s->sh_flags & SHF_ALLOC)) {
1413 const char *p;
1414 int ch;
1416 /* check if section name can be expressed in C */
1417 p = s->name;
1418 for(;;) {
1419 ch = *p;
1420 if (!ch)
1421 break;
1422 if (!isid(ch) && !isnum(ch))
1423 goto next_sec;
1424 p++;
1426 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1427 add_elf_sym(symtab_section,
1428 0, 0,
1429 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1430 s->sh_num, buf);
1431 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1432 add_elf_sym(symtab_section,
1433 s->data_offset, 0,
1434 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1435 s->sh_num, buf);
1437 next_sec: ;
1441 static void tcc_output_binary(TCCState *s1, FILE *f,
1442 const int *section_order)
1444 Section *s;
1445 int i, offset, size;
1447 offset = 0;
1448 for(i=1;i<s1->nb_sections;i++) {
1449 s = s1->sections[section_order[i]];
1450 if (s->sh_type != SHT_NOBITS &&
1451 (s->sh_flags & SHF_ALLOC)) {
1452 while (offset < s->sh_offset) {
1453 fputc(0, f);
1454 offset++;
1456 size = s->sh_size;
1457 fwrite(s->data, 1, size, f);
1458 offset += size;
1463 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1464 #define HAVE_PHDR 1
1465 #define EXTRA_RELITEMS 14
1467 /* move the relocation value from .dynsym to .got */
1468 void patch_dynsym_undef(TCCState *s1, Section *s)
1470 uint32_t *gotd = (void *)s1->got->data;
1471 ElfW(Sym) *sym, *sym_end;
1473 gotd += 3; // dummy entries in .got
1474 /* relocate symbols in .dynsym */
1475 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1476 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1477 if (sym->st_shndx == SHN_UNDEF) {
1478 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1479 sym->st_value = 0;
1483 #else
1484 #define HAVE_PHDR 0
1485 #define EXTRA_RELITEMS 9
1487 /* zero plt offsets of weak symbols in .dynsym */
1488 void patch_dynsym_undef(TCCState *s1, Section *s)
1490 ElfW(Sym) *sym, *sym_end;
1492 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1493 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++)
1494 if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
1495 sym->st_value = 0;
1497 #endif
1499 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1501 int sym_index = ELFW(R_SYM) (rel->r_info);
1502 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1503 unsigned long offset;
1505 if (sym_index >= s1->nb_sym_attrs)
1506 return;
1507 offset = s1->sym_attrs[sym_index].got_offset;
1508 section_reserve(s1->got, offset + PTR_SIZE);
1509 #ifdef TCC_TARGET_X86_64
1510 /* only works for x86-64 */
1511 put32(s1->got->data + offset + 4, sym->st_value >> 32);
1512 #endif
1513 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1516 ST_FUNC void fill_got(TCCState *s1)
1518 Section *s;
1519 ElfW_Rel *rel, *rel_end;
1520 int i;
1522 for(i = 1; i < s1->nb_sections; i++) {
1523 s = s1->sections[i];
1524 if (s->sh_type != SHT_RELX)
1525 continue;
1526 /* no need to handle got relocations */
1527 if (s->link != symtab_section)
1528 continue;
1529 rel_end = (ElfW_Rel *) (s->data + s->data_offset);
1530 for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
1531 switch (ELFW(R_TYPE) (rel->r_info)) {
1532 case R_X86_64_GOT32:
1533 case R_X86_64_GOTPCREL:
1534 case R_X86_64_PLT32:
1535 fill_got_entry(s1, rel);
1536 break;
1543 /* output an ELF file */
1544 /* XXX: suppress unneeded sections */
1545 static int elf_output_file(TCCState *s1, const char *filename)
1547 ElfW(Ehdr) ehdr;
1548 FILE *f;
1549 int fd, mode, ret;
1550 int *section_order;
1551 int shnum, i, phnum, file_offset, offset, size, j, sh_order_index, k;
1552 long long tmp;
1553 addr_t addr;
1554 Section *strsec, *s;
1555 ElfW(Shdr) shdr, *sh;
1556 ElfW(Phdr) *phdr, *ph;
1557 Section *interp, *dynamic, *dynstr;
1558 unsigned long saved_dynamic_data_offset;
1559 ElfW(Sym) *sym;
1560 int type, file_type;
1561 addr_t rel_addr, rel_size;
1562 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1563 addr_t bss_addr, bss_size;
1564 #endif
1566 file_type = s1->output_type;
1567 s1->nb_errors = 0;
1569 if (file_type != TCC_OUTPUT_OBJ) {
1570 tcc_add_runtime(s1);
1573 phdr = NULL;
1574 section_order = NULL;
1575 interp = NULL;
1576 dynamic = NULL;
1577 dynstr = NULL; /* avoid warning */
1578 saved_dynamic_data_offset = 0; /* avoid warning */
1580 if (file_type != TCC_OUTPUT_OBJ) {
1581 relocate_common_syms();
1583 tcc_add_linker_symbols(s1);
1585 if (!s1->static_link) {
1586 const char *name;
1587 int sym_index, index;
1588 ElfW(Sym) *esym, *sym_end;
1590 if (file_type == TCC_OUTPUT_EXE) {
1591 char *ptr;
1592 /* allow override the dynamic loader */
1593 const char *elfint = getenv("LD_SO");
1594 if (elfint == NULL)
1595 elfint = DEFAULT_ELFINTERP(s1);
1596 /* add interpreter section only if executable */
1597 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1598 interp->sh_addralign = 1;
1599 ptr = section_ptr_add(interp, 1+strlen(elfint));
1600 strcpy(ptr, elfint);
1603 /* add dynamic symbol table */
1604 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1605 ".dynstr",
1606 ".hash", SHF_ALLOC);
1607 dynstr = s1->dynsym->link;
1609 /* add dynamic section */
1610 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1611 SHF_ALLOC | SHF_WRITE);
1612 dynamic->link = dynstr;
1613 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1615 /* add PLT */
1616 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1617 SHF_ALLOC | SHF_EXECINSTR);
1618 s1->plt->sh_entsize = 4;
1620 build_got(s1);
1622 /* scan for undefined symbols and see if they are in the
1623 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1624 is found, then we add it in the PLT. If a symbol
1625 STT_OBJECT is found, we add it in the .bss section with
1626 a suitable relocation */
1627 sym_end = (ElfW(Sym) *)(symtab_section->data +
1628 symtab_section->data_offset);
1629 if (file_type == TCC_OUTPUT_EXE) {
1630 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1631 sym < sym_end;
1632 sym++) {
1633 if (sym->st_shndx == SHN_UNDEF) {
1634 name = symtab_section->link->data + sym->st_name;
1635 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1636 if (sym_index) {
1637 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1638 type = ELFW(ST_TYPE)(esym->st_info);
1639 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1640 /* Indirect functions shall have STT_FUNC type
1641 * in executable dynsym section. Indeed, a dlsym
1642 * call following a lazy resolution would pick
1643 * the symbol value from the executable dynsym
1644 * entry which would contain the address of the
1645 * function wanted by the caller of dlsym
1646 * instead of the address of the function that
1647 * would return that address */
1648 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1649 ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC),
1650 sym - (ElfW(Sym) *)symtab_section->data);
1651 } else if (type == STT_OBJECT) {
1652 unsigned long offset;
1653 ElfW(Sym) *dynsym, *dynsym_end;
1654 offset = bss_section->data_offset;
1655 /* XXX: which alignment ? */
1656 offset = (offset + 16 - 1) & -16;
1657 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1658 esym->st_info, 0,
1659 bss_section->sh_num, name);
1660 // Ensure R_COPY works for weak symbol aliases
1661 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1662 dynsym_end = (ElfW(Sym) *)
1663 (s1->dynsymtab_section->data +
1664 s1->dynsymtab_section->data_offset);
1665 for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1666 dynsym < dynsym_end; dynsym++) {
1667 if ((dynsym->st_value == esym->st_value)
1668 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1669 char *dynname;
1670 dynname = s1->dynsymtab_section->link->data
1671 + dynsym->st_name;
1672 put_elf_sym(s1->dynsym, offset,
1673 dynsym->st_size,
1674 dynsym->st_info, 0,
1675 bss_section->sh_num,
1676 dynname);
1677 break;
1681 put_elf_reloc(s1->dynsym, bss_section,
1682 offset, R_COPY, index);
1683 offset += esym->st_size;
1684 bss_section->data_offset = offset;
1686 } else {
1687 /* STB_WEAK undefined symbols are accepted */
1688 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1689 it */
1690 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1691 !strcmp(name, "_fp_hw")) {
1692 } else {
1693 tcc_error_noabort("undefined symbol '%s'", name);
1696 } else if (s1->rdynamic &&
1697 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1698 /* if -rdynamic option, then export all non
1699 local symbols */
1700 name = symtab_section->link->data + sym->st_name;
1701 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1702 sym->st_info, 0,
1703 sym->st_shndx, name);
1707 if (s1->nb_errors)
1708 goto fail;
1710 /* now look at unresolved dynamic symbols and export
1711 corresponding symbol */
1712 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1713 s1->dynsymtab_section->data_offset);
1714 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1715 esym < sym_end;
1716 esym++) {
1717 if (esym->st_shndx == SHN_UNDEF) {
1718 name = s1->dynsymtab_section->link->data + esym->st_name;
1719 sym_index = find_elf_sym(symtab_section, name);
1720 if (sym_index) {
1721 /* XXX: avoid adding a symbol if already
1722 present because of -rdynamic ? */
1723 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1724 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1725 sym->st_info, 0,
1726 sym->st_shndx, name);
1727 } else {
1728 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1729 /* weak symbols can stay undefined */
1730 } else {
1731 tcc_warning("undefined dynamic symbol '%s'", name);
1736 } else {
1737 int nb_syms;
1738 /* shared library case : we simply export all the global symbols */
1739 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1740 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1741 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1742 sym < sym_end;
1743 sym++) {
1744 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1745 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1746 if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
1747 ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
1748 && sym->st_shndx == SHN_UNDEF) {
1749 int visibility = ELFW(ST_BIND)(sym->st_info);
1750 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1751 ELFW(ST_INFO)(visibility,STT_FUNC),
1752 sym - (ElfW(Sym) *)symtab_section->data);
1754 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1755 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1756 sym->st_info,
1757 sym - (ElfW(Sym) *)symtab_section->data);
1759 else
1760 #endif
1762 name = symtab_section->link->data + sym->st_name;
1763 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1764 sym->st_info, 0,
1765 sym->st_shndx, name);
1766 s1->symtab_to_dynsym[sym -
1767 (ElfW(Sym) *)symtab_section->data] =
1768 index;
1774 build_got_entries(s1);
1776 /* add a list of needed dlls */
1777 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1778 DLLReference *dllref = s1->loaded_dlls[i];
1779 if (dllref->level == 0)
1780 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1783 if (s1->rpath)
1784 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1786 /* XXX: currently, since we do not handle PIC code, we
1787 must relocate the readonly segments */
1788 if (file_type == TCC_OUTPUT_DLL) {
1789 if (s1->soname)
1790 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1791 put_dt(dynamic, DT_TEXTREL, 0);
1794 if (s1->symbolic)
1795 put_dt(dynamic, DT_SYMBOLIC, 0);
1797 /* add necessary space for other entries */
1798 saved_dynamic_data_offset = dynamic->data_offset;
1799 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1800 } else {
1801 /* still need to build got entries in case of static link */
1802 build_got_entries(s1);
1806 memset(&ehdr, 0, sizeof(ehdr));
1808 /* we add a section for symbols */
1809 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1810 put_elf_str(strsec, "");
1812 /* compute number of sections */
1813 shnum = s1->nb_sections;
1815 /* this array is used to reorder sections in the output file */
1816 section_order = tcc_malloc(sizeof(int) * shnum);
1817 section_order[0] = 0;
1818 sh_order_index = 1;
1820 /* compute number of program headers */
1821 switch(file_type) {
1822 default:
1823 case TCC_OUTPUT_OBJ:
1824 phnum = 0;
1825 break;
1826 case TCC_OUTPUT_EXE:
1827 if (!s1->static_link)
1828 phnum = 4 + HAVE_PHDR;
1829 else
1830 phnum = 2;
1831 break;
1832 case TCC_OUTPUT_DLL:
1833 phnum = 3;
1834 break;
1837 /* allocate strings for section names and decide if an unallocated
1838 section should be output */
1839 /* NOTE: the strsec section comes last, so its size is also
1840 correct ! */
1841 for(i = 1; i < s1->nb_sections; i++) {
1842 s = s1->sections[i];
1843 s->sh_name = put_elf_str(strsec, s->name);
1844 #if 0 /* gr */
1845 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1846 s->sh_flags,
1847 s->sh_type,
1848 s->sh_info,
1849 s->name,
1850 s->reloc ? s->reloc->name : "n"
1852 #endif
1853 /* when generating a DLL, we include relocations but we may
1854 patch them */
1855 if (file_type == TCC_OUTPUT_DLL &&
1856 s->sh_type == SHT_RELX &&
1857 !(s->sh_flags & SHF_ALLOC)) {
1858 /* //gr: avoid bogus relocs for empty (debug) sections */
1859 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1860 prepare_dynamic_rel(s1, s);
1861 else if (s1->do_debug)
1862 s->sh_size = s->data_offset;
1863 } else if (s1->do_debug ||
1864 file_type == TCC_OUTPUT_OBJ ||
1865 (s->sh_flags & SHF_ALLOC) ||
1866 i == (s1->nb_sections - 1)) {
1867 /* we output all sections if debug or object file */
1868 s->sh_size = s->data_offset;
1872 /* allocate program segment headers */
1873 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1875 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1876 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1877 } else {
1878 file_offset = 0;
1880 if (phnum > 0) {
1881 /* compute section to program header mapping */
1882 if (s1->has_text_addr) {
1883 int a_offset, p_offset;
1884 addr = s1->text_addr;
1885 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1886 ELF_PAGE_SIZE */
1887 a_offset = (int) (addr & (s1->section_align - 1));
1888 p_offset = file_offset & (s1->section_align - 1);
1889 if (a_offset < p_offset)
1890 a_offset += s1->section_align;
1891 file_offset += (a_offset - p_offset);
1892 } else {
1893 if (file_type == TCC_OUTPUT_DLL)
1894 addr = 0;
1895 else
1896 addr = ELF_START_ADDR;
1897 /* compute address after headers */
1898 addr += (file_offset & (s1->section_align - 1));
1901 /* dynamic relocation table information, for .dynamic section */
1902 rel_size = 0;
1903 rel_addr = 0;
1905 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1906 bss_addr = bss_size = 0;
1907 #endif
1908 /* leave one program header for the program interpreter */
1909 ph = &phdr[0];
1910 if (interp)
1911 ph += 1 + HAVE_PHDR;
1913 for(j = 0; j < 2; j++) {
1914 ph->p_type = PT_LOAD;
1915 if (j == 0)
1916 ph->p_flags = PF_R | PF_X;
1917 else
1918 ph->p_flags = PF_R | PF_W;
1919 ph->p_align = s1->section_align;
1921 /* we do the following ordering: interp, symbol tables,
1922 relocations, progbits, nobits */
1923 /* XXX: do faster and simpler sorting */
1924 for(k = 0; k < 5; k++) {
1925 for(i = 1; i < s1->nb_sections; i++) {
1926 s = s1->sections[i];
1927 /* compute if section should be included */
1928 if (j == 0) {
1929 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1930 SHF_ALLOC)
1931 continue;
1932 } else {
1933 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1934 (SHF_ALLOC | SHF_WRITE))
1935 continue;
1937 if (s == interp) {
1938 if (k != 0)
1939 continue;
1940 } else if (s->sh_type == SHT_DYNSYM ||
1941 s->sh_type == SHT_STRTAB ||
1942 s->sh_type == SHT_HASH) {
1943 if (k != 1)
1944 continue;
1945 } else if (s->sh_type == SHT_RELX) {
1946 if (k != 2)
1947 continue;
1948 } else if (s->sh_type == SHT_NOBITS) {
1949 if (k != 4)
1950 continue;
1951 } else {
1952 if (k != 3)
1953 continue;
1955 section_order[sh_order_index++] = i;
1957 /* section matches: we align it and add its size */
1958 tmp = addr;
1959 addr = (addr + s->sh_addralign - 1) &
1960 ~(s->sh_addralign - 1);
1961 file_offset += (int) ( addr - tmp );
1962 s->sh_offset = file_offset;
1963 s->sh_addr = addr;
1965 /* update program header infos */
1966 if (ph->p_offset == 0) {
1967 ph->p_offset = file_offset;
1968 ph->p_vaddr = addr;
1969 ph->p_paddr = ph->p_vaddr;
1971 /* update dynamic relocation infos */
1972 if (s->sh_type == SHT_RELX) {
1973 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1974 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1975 rel_addr = addr;
1976 rel_size += s->sh_size; // XXX only first rel.
1978 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1979 bss_addr = addr;
1980 bss_size = s->sh_size; // XXX only first rel.
1982 #else
1983 if (rel_size == 0)
1984 rel_addr = addr;
1985 rel_size += s->sh_size;
1986 #endif
1988 addr += s->sh_size;
1989 if (s->sh_type != SHT_NOBITS)
1990 file_offset += s->sh_size;
1993 ph->p_filesz = file_offset - ph->p_offset;
1994 ph->p_memsz = addr - ph->p_vaddr;
1995 ph++;
1996 if (j == 0) {
1997 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1998 /* if in the middle of a page, we duplicate the page in
1999 memory so that one copy is RX and the other is RW */
2000 if ((addr & (s1->section_align - 1)) != 0)
2001 addr += s1->section_align;
2002 } else {
2003 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
2004 file_offset = (file_offset + s1->section_align - 1) &
2005 ~(s1->section_align - 1);
2010 /* if interpreter, then add corresponing program header */
2011 if (interp) {
2012 ph = &phdr[0];
2014 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2016 int len = phnum * sizeof(ElfW(Phdr));
2018 ph->p_type = PT_PHDR;
2019 ph->p_offset = sizeof(ElfW(Ehdr));
2020 ph->p_vaddr = interp->sh_addr - len;
2021 ph->p_paddr = ph->p_vaddr;
2022 ph->p_filesz = ph->p_memsz = len;
2023 ph->p_flags = PF_R | PF_X;
2024 ph->p_align = 4; // interp->sh_addralign;
2025 ph++;
2027 #endif
2029 ph->p_type = PT_INTERP;
2030 ph->p_offset = interp->sh_offset;
2031 ph->p_vaddr = interp->sh_addr;
2032 ph->p_paddr = ph->p_vaddr;
2033 ph->p_filesz = interp->sh_size;
2034 ph->p_memsz = interp->sh_size;
2035 ph->p_flags = PF_R;
2036 ph->p_align = interp->sh_addralign;
2039 /* if dynamic section, then add corresponing program header */
2040 if (dynamic) {
2041 ElfW(Sym) *sym_end;
2043 ph = &phdr[phnum - 1];
2045 ph->p_type = PT_DYNAMIC;
2046 ph->p_offset = dynamic->sh_offset;
2047 ph->p_vaddr = dynamic->sh_addr;
2048 ph->p_paddr = ph->p_vaddr;
2049 ph->p_filesz = dynamic->sh_size;
2050 ph->p_memsz = dynamic->sh_size;
2051 ph->p_flags = PF_R | PF_W;
2052 ph->p_align = dynamic->sh_addralign;
2054 /* put GOT dynamic section address */
2055 put32(s1->got->data, dynamic->sh_addr);
2057 /* relocate the PLT */
2058 if (file_type == TCC_OUTPUT_EXE
2059 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2060 || file_type == TCC_OUTPUT_DLL
2061 #endif
2063 uint8_t *p, *p_end;
2065 p = s1->plt->data;
2066 p_end = p + s1->plt->data_offset;
2067 if (p < p_end) {
2068 #if defined(TCC_TARGET_I386)
2069 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2070 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
2071 p += 16;
2072 while (p < p_end) {
2073 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2074 p += 16;
2076 #elif defined(TCC_TARGET_X86_64)
2077 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
2078 put32(p + 2, get32(p + 2) + x);
2079 put32(p + 8, get32(p + 8) + x - 6);
2080 p += 16;
2081 while (p < p_end) {
2082 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
2083 p += 16;
2085 #elif defined(TCC_TARGET_ARM)
2086 int x;
2087 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
2088 p += 16;
2089 while (p < p_end) {
2090 if (get32(p) == 0x46c04778) /* PLT Thumb stub present */
2091 p += 4;
2092 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
2093 p += 16;
2095 #elif defined(TCC_TARGET_C67)
2096 /* XXX: TODO */
2097 #else
2098 #error unsupported CPU
2099 #endif
2103 /* relocate symbols in .dynsym */
2104 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
2105 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
2106 sym < sym_end;
2107 sym++) {
2108 if (sym->st_shndx == SHN_UNDEF) {
2109 /* relocate to the PLT if the symbol corresponds
2110 to a PLT entry */
2111 if (sym->st_value)
2112 sym->st_value += s1->plt->sh_addr;
2113 } else if (sym->st_shndx < SHN_LORESERVE) {
2114 /* do symbol relocation */
2115 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
2119 /* put dynamic section entries */
2120 dynamic->data_offset = saved_dynamic_data_offset;
2121 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
2122 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
2123 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2124 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
2125 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2126 #ifdef TCC_TARGET_X86_64
2127 put_dt(dynamic, DT_RELA, rel_addr);
2128 put_dt(dynamic, DT_RELASZ, rel_size);
2129 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2130 #else
2131 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2132 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2133 put_dt(dynamic, DT_PLTRELSZ, rel_size);
2134 put_dt(dynamic, DT_JMPREL, rel_addr);
2135 put_dt(dynamic, DT_PLTREL, DT_REL);
2136 put_dt(dynamic, DT_REL, bss_addr);
2137 put_dt(dynamic, DT_RELSZ, bss_size);
2138 #else
2139 put_dt(dynamic, DT_REL, rel_addr);
2140 put_dt(dynamic, DT_RELSZ, rel_size);
2141 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2142 #endif
2143 #endif
2144 if (s1->do_debug)
2145 put_dt(dynamic, DT_DEBUG, 0);
2146 put_dt(dynamic, DT_NULL, 0);
2149 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2150 ehdr.e_phnum = phnum;
2151 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2154 /* all other sections come after */
2155 for(i = 1; i < s1->nb_sections; i++) {
2156 s = s1->sections[i];
2157 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2158 continue;
2159 section_order[sh_order_index++] = i;
2161 file_offset = (file_offset + s->sh_addralign - 1) &
2162 ~(s->sh_addralign - 1);
2163 s->sh_offset = file_offset;
2164 if (s->sh_type != SHT_NOBITS)
2165 file_offset += s->sh_size;
2168 /* if building executable or DLL, then relocate each section
2169 except the GOT which is already relocated */
2170 if (file_type != TCC_OUTPUT_OBJ) {
2171 relocate_syms(s1, 0);
2173 if (s1->nb_errors != 0) {
2174 fail:
2175 ret = -1;
2176 goto the_end;
2179 /* relocate sections */
2180 /* XXX: ignore sections with allocated relocations ? */
2181 for(i = 1; i < s1->nb_sections; i++) {
2182 s = s1->sections[i];
2183 if (s->reloc && s != s1->got)
2184 relocate_section(s1, s);
2187 /* relocate relocation entries if the relocation tables are
2188 allocated in the executable */
2189 for(i = 1; i < s1->nb_sections; i++) {
2190 s = s1->sections[i];
2191 if ((s->sh_flags & SHF_ALLOC) &&
2192 s->sh_type == SHT_RELX) {
2193 relocate_rel(s1, s);
2197 /* get entry point address */
2198 if (file_type == TCC_OUTPUT_EXE)
2199 ehdr.e_entry = get_elf_sym_addr(s1, "_start", 1);
2200 else
2201 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2203 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2204 fill_got(s1);
2206 /* write elf file */
2207 if (file_type == TCC_OUTPUT_OBJ)
2208 mode = 0666;
2209 else
2210 mode = 0777;
2211 unlink(filename);
2212 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2213 if (fd < 0) {
2214 tcc_error_noabort("could not write '%s'", filename);
2215 goto fail;
2217 f = fdopen(fd, "wb");
2218 if (s1->verbose)
2219 printf("<- %s\n", filename);
2221 #ifdef TCC_TARGET_COFF
2222 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2223 tcc_output_coff(s1, f);
2224 } else
2225 #endif
2226 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2227 sort_syms(s1, symtab_section);
2229 /* align to 4 */
2230 file_offset = (file_offset + 3) & -4;
2232 /* fill header */
2233 ehdr.e_ident[0] = ELFMAG0;
2234 ehdr.e_ident[1] = ELFMAG1;
2235 ehdr.e_ident[2] = ELFMAG2;
2236 ehdr.e_ident[3] = ELFMAG3;
2237 ehdr.e_ident[4] = ELFCLASSW;
2238 ehdr.e_ident[5] = ELFDATA2LSB;
2239 ehdr.e_ident[6] = EV_CURRENT;
2240 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2241 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2242 #endif
2243 #ifdef TCC_TARGET_ARM
2244 #ifdef TCC_ARM_EABI
2245 ehdr.e_ident[EI_OSABI] = 0;
2246 ehdr.e_flags = EF_ARM_EABI_VER4;
2247 if (file_type == TCC_OUTPUT_EXE)
2248 ehdr.e_flags |= EF_ARM_HASENTRY;
2249 if (s1->float_abi == ARM_HARD_FLOAT)
2250 ehdr.e_flags |= EF_ARM_VFP_FLOAT;
2251 else
2252 ehdr.e_flags |= EF_ARM_SOFT_FLOAT;
2253 #else
2254 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2255 #endif
2256 #endif
2257 switch(file_type) {
2258 default:
2259 case TCC_OUTPUT_EXE:
2260 ehdr.e_type = ET_EXEC;
2261 break;
2262 case TCC_OUTPUT_DLL:
2263 ehdr.e_type = ET_DYN;
2264 break;
2265 case TCC_OUTPUT_OBJ:
2266 ehdr.e_type = ET_REL;
2267 break;
2269 ehdr.e_machine = EM_TCC_TARGET;
2270 ehdr.e_version = EV_CURRENT;
2271 ehdr.e_shoff = file_offset;
2272 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2273 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2274 ehdr.e_shnum = shnum;
2275 ehdr.e_shstrndx = shnum - 1;
2277 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2278 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2279 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2281 for(i=1;i<s1->nb_sections;i++) {
2282 s = s1->sections[section_order[i]];
2283 if (s->sh_type != SHT_NOBITS) {
2284 if (s->sh_type == SHT_DYNSYM)
2285 patch_dynsym_undef(s1, s);
2286 while (offset < s->sh_offset) {
2287 fputc(0, f);
2288 offset++;
2290 size = s->sh_size;
2291 fwrite(s->data, 1, size, f);
2292 offset += size;
2296 /* output section headers */
2297 while (offset < ehdr.e_shoff) {
2298 fputc(0, f);
2299 offset++;
2302 for(i=0;i<s1->nb_sections;i++) {
2303 sh = &shdr;
2304 memset(sh, 0, sizeof(ElfW(Shdr)));
2305 s = s1->sections[i];
2306 if (s) {
2307 sh->sh_name = s->sh_name;
2308 sh->sh_type = s->sh_type;
2309 sh->sh_flags = s->sh_flags;
2310 sh->sh_entsize = s->sh_entsize;
2311 sh->sh_info = s->sh_info;
2312 if (s->link)
2313 sh->sh_link = s->link->sh_num;
2314 sh->sh_addralign = s->sh_addralign;
2315 sh->sh_addr = s->sh_addr;
2316 sh->sh_offset = s->sh_offset;
2317 sh->sh_size = s->sh_size;
2319 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2321 } else {
2322 tcc_output_binary(s1, f, section_order);
2324 fclose(f);
2326 ret = 0;
2327 the_end:
2328 tcc_free(s1->symtab_to_dynsym);
2329 tcc_free(section_order);
2330 tcc_free(phdr);
2331 tcc_free(s1->sym_attrs);
2332 return ret;
2335 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2337 int ret;
2338 #ifdef TCC_TARGET_PE
2339 if (s->output_type != TCC_OUTPUT_OBJ) {
2340 ret = pe_output_file(s, filename);
2341 } else
2342 #endif
2344 ret = elf_output_file(s, filename);
2346 return ret;
2349 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2351 void *data;
2353 data = tcc_malloc(size);
2354 lseek(fd, file_offset, SEEK_SET);
2355 read(fd, data, size);
2356 return data;
2359 typedef struct SectionMergeInfo {
2360 Section *s; /* corresponding existing section */
2361 unsigned long offset; /* offset of the new section in the existing section */
2362 uint8_t new_section; /* true if section 's' was added */
2363 uint8_t link_once; /* true if link once section */
2364 } SectionMergeInfo;
2366 /* load an object file and merge it with current files */
2367 /* XXX: handle correctly stab (debug) info */
2368 ST_FUNC int tcc_load_object_file(TCCState *s1,
2369 int fd, unsigned long file_offset)
2371 ElfW(Ehdr) ehdr;
2372 ElfW(Shdr) *shdr, *sh;
2373 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2374 unsigned char *strsec, *strtab;
2375 int *old_to_new_syms;
2376 char *sh_name, *name;
2377 SectionMergeInfo *sm_table, *sm;
2378 ElfW(Sym) *sym, *symtab;
2379 ElfW_Rel *rel, *rel_end;
2380 Section *s;
2382 int stab_index;
2383 int stabstr_index;
2385 stab_index = stabstr_index = 0;
2387 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2388 goto fail1;
2389 if (ehdr.e_ident[0] != ELFMAG0 ||
2390 ehdr.e_ident[1] != ELFMAG1 ||
2391 ehdr.e_ident[2] != ELFMAG2 ||
2392 ehdr.e_ident[3] != ELFMAG3)
2393 goto fail1;
2394 /* test if object file */
2395 if (ehdr.e_type != ET_REL)
2396 goto fail1;
2397 /* test CPU specific stuff */
2398 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2399 ehdr.e_machine != EM_TCC_TARGET) {
2400 fail1:
2401 tcc_error_noabort("invalid object file");
2402 return -1;
2404 /* read sections */
2405 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2406 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2407 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2409 /* load section names */
2410 sh = &shdr[ehdr.e_shstrndx];
2411 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2413 /* load symtab and strtab */
2414 old_to_new_syms = NULL;
2415 symtab = NULL;
2416 strtab = NULL;
2417 nb_syms = 0;
2418 for(i = 1; i < ehdr.e_shnum; i++) {
2419 sh = &shdr[i];
2420 if (sh->sh_type == SHT_SYMTAB) {
2421 if (symtab) {
2422 tcc_error_noabort("object must contain only one symtab");
2423 fail:
2424 ret = -1;
2425 goto the_end;
2427 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2428 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2429 sm_table[i].s = symtab_section;
2431 /* now load strtab */
2432 sh = &shdr[sh->sh_link];
2433 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2437 /* now examine each section and try to merge its content with the
2438 ones in memory */
2439 for(i = 1; i < ehdr.e_shnum; i++) {
2440 /* no need to examine section name strtab */
2441 if (i == ehdr.e_shstrndx)
2442 continue;
2443 sh = &shdr[i];
2444 sh_name = strsec + sh->sh_name;
2445 /* ignore sections types we do not handle */
2446 if (sh->sh_type != SHT_PROGBITS &&
2447 sh->sh_type != SHT_RELX &&
2448 #ifdef TCC_ARM_EABI
2449 sh->sh_type != SHT_ARM_EXIDX &&
2450 #endif
2451 sh->sh_type != SHT_NOBITS &&
2452 sh->sh_type != SHT_PREINIT_ARRAY &&
2453 sh->sh_type != SHT_INIT_ARRAY &&
2454 sh->sh_type != SHT_FINI_ARRAY &&
2455 strcmp(sh_name, ".stabstr")
2457 continue;
2458 if (sh->sh_addralign < 1)
2459 sh->sh_addralign = 1;
2460 /* find corresponding section, if any */
2461 for(j = 1; j < s1->nb_sections;j++) {
2462 s = s1->sections[j];
2463 if (!strcmp(s->name, sh_name)) {
2464 if (!strncmp(sh_name, ".gnu.linkonce",
2465 sizeof(".gnu.linkonce") - 1)) {
2466 /* if a 'linkonce' section is already present, we
2467 do not add it again. It is a little tricky as
2468 symbols can still be defined in
2469 it. */
2470 sm_table[i].link_once = 1;
2471 goto next;
2472 } else {
2473 goto found;
2477 /* not found: create new section */
2478 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2479 /* take as much info as possible from the section. sh_link and
2480 sh_info will be updated later */
2481 s->sh_addralign = sh->sh_addralign;
2482 s->sh_entsize = sh->sh_entsize;
2483 sm_table[i].new_section = 1;
2484 found:
2485 if (sh->sh_type != s->sh_type) {
2486 tcc_error_noabort("invalid section type");
2487 goto fail;
2490 /* align start of section */
2491 offset = s->data_offset;
2493 if (0 == strcmp(sh_name, ".stab")) {
2494 stab_index = i;
2495 goto no_align;
2497 if (0 == strcmp(sh_name, ".stabstr")) {
2498 stabstr_index = i;
2499 goto no_align;
2502 size = sh->sh_addralign - 1;
2503 offset = (offset + size) & ~size;
2504 if (sh->sh_addralign > s->sh_addralign)
2505 s->sh_addralign = sh->sh_addralign;
2506 s->data_offset = offset;
2507 no_align:
2508 sm_table[i].offset = offset;
2509 sm_table[i].s = s;
2510 /* concatenate sections */
2511 size = sh->sh_size;
2512 if (sh->sh_type != SHT_NOBITS) {
2513 unsigned char *ptr;
2514 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2515 ptr = section_ptr_add(s, size);
2516 read(fd, ptr, size);
2517 } else {
2518 s->data_offset += size;
2520 next: ;
2523 /* //gr relocate stab strings */
2524 if (stab_index && stabstr_index) {
2525 Stab_Sym *a, *b;
2526 unsigned o;
2527 s = sm_table[stab_index].s;
2528 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2529 b = (Stab_Sym *)(s->data + s->data_offset);
2530 o = sm_table[stabstr_index].offset;
2531 while (a < b)
2532 a->n_strx += o, a++;
2535 /* second short pass to update sh_link and sh_info fields of new
2536 sections */
2537 for(i = 1; i < ehdr.e_shnum; i++) {
2538 s = sm_table[i].s;
2539 if (!s || !sm_table[i].new_section)
2540 continue;
2541 sh = &shdr[i];
2542 if (sh->sh_link > 0)
2543 s->link = sm_table[sh->sh_link].s;
2544 if (sh->sh_type == SHT_RELX) {
2545 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2546 /* update backward link */
2547 s1->sections[s->sh_info]->reloc = s;
2550 sm = sm_table;
2552 /* resolve symbols */
2553 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2555 sym = symtab + 1;
2556 for(i = 1; i < nb_syms; i++, sym++) {
2557 if (sym->st_shndx != SHN_UNDEF &&
2558 sym->st_shndx < SHN_LORESERVE) {
2559 sm = &sm_table[sym->st_shndx];
2560 if (sm->link_once) {
2561 /* if a symbol is in a link once section, we use the
2562 already defined symbol. It is very important to get
2563 correct relocations */
2564 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2565 name = strtab + sym->st_name;
2566 sym_index = find_elf_sym(symtab_section, name);
2567 if (sym_index)
2568 old_to_new_syms[i] = sym_index;
2570 continue;
2572 /* if no corresponding section added, no need to add symbol */
2573 if (!sm->s)
2574 continue;
2575 /* convert section number */
2576 sym->st_shndx = sm->s->sh_num;
2577 /* offset value */
2578 sym->st_value += sm->offset;
2580 /* add symbol */
2581 name = strtab + sym->st_name;
2582 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2583 sym->st_info, sym->st_other,
2584 sym->st_shndx, name);
2585 old_to_new_syms[i] = sym_index;
2588 /* third pass to patch relocation entries */
2589 for(i = 1; i < ehdr.e_shnum; i++) {
2590 s = sm_table[i].s;
2591 if (!s)
2592 continue;
2593 sh = &shdr[i];
2594 offset = sm_table[i].offset;
2595 switch(s->sh_type) {
2596 case SHT_RELX:
2597 /* take relocation offset information */
2598 offseti = sm_table[sh->sh_info].offset;
2599 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2600 for(rel = (ElfW_Rel *)(s->data + offset);
2601 rel < rel_end;
2602 rel++) {
2603 int type;
2604 unsigned sym_index;
2605 /* convert symbol index */
2606 type = ELFW(R_TYPE)(rel->r_info);
2607 sym_index = ELFW(R_SYM)(rel->r_info);
2608 /* NOTE: only one symtab assumed */
2609 if (sym_index >= nb_syms)
2610 goto invalid_reloc;
2611 sym_index = old_to_new_syms[sym_index];
2612 /* ignore link_once in rel section. */
2613 if (!sym_index && !sm->link_once
2614 #ifdef TCC_TARGET_ARM
2615 && type != R_ARM_V4BX
2616 #endif
2618 invalid_reloc:
2619 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2620 i, strsec + sh->sh_name, rel->r_offset);
2621 goto fail;
2623 rel->r_info = ELFW(R_INFO)(sym_index, type);
2624 /* offset the relocation offset */
2625 rel->r_offset += offseti;
2626 #ifdef TCC_TARGET_ARM
2627 /* Jumps and branches from a Thumb code to a PLT entry need
2628 special handling since PLT entries are ARM code.
2629 Unconditional bl instructions referencing PLT entries are
2630 handled by converting these instructions into blx
2631 instructions. Other case of instructions referencing a PLT
2632 entry require to add a Thumb stub before the PLT entry to
2633 switch to ARM mode. We set bit 0 of the got offset of a
2634 symbol to indicate such a case. */
2635 if (type == R_ARM_THM_JUMP24)
2636 alloc_sym_attr(s1, sym_index)->plt_thumb_stub = 1;
2637 #endif
2639 break;
2640 default:
2641 break;
2645 ret = 0;
2646 the_end:
2647 tcc_free(symtab);
2648 tcc_free(strtab);
2649 tcc_free(old_to_new_syms);
2650 tcc_free(sm_table);
2651 tcc_free(strsec);
2652 tcc_free(shdr);
2653 return ret;
2656 typedef struct ArchiveHeader {
2657 char ar_name[16]; /* name of this member */
2658 char ar_date[12]; /* file mtime */
2659 char ar_uid[6]; /* owner uid; printed as decimal */
2660 char ar_gid[6]; /* owner gid; printed as decimal */
2661 char ar_mode[8]; /* file mode, printed as octal */
2662 char ar_size[10]; /* file size, printed as decimal */
2663 char ar_fmag[2]; /* should contain ARFMAG */
2664 } ArchiveHeader;
2666 static int get_be32(const uint8_t *b)
2668 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2671 /* load only the objects which resolve undefined symbols */
2672 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2674 int i, bound, nsyms, sym_index, off, ret;
2675 uint8_t *data;
2676 const char *ar_names, *p;
2677 const uint8_t *ar_index;
2678 ElfW(Sym) *sym;
2680 data = tcc_malloc(size);
2681 if (read(fd, data, size) != size)
2682 goto fail;
2683 nsyms = get_be32(data);
2684 ar_index = data + 4;
2685 ar_names = ar_index + nsyms * 4;
2687 do {
2688 bound = 0;
2689 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2690 sym_index = find_elf_sym(symtab_section, p);
2691 if(sym_index) {
2692 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2693 if(sym->st_shndx == SHN_UNDEF) {
2694 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2695 #if 0
2696 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2697 #endif
2698 ++bound;
2699 lseek(fd, off, SEEK_SET);
2700 if(tcc_load_object_file(s1, fd, off) < 0) {
2701 fail:
2702 ret = -1;
2703 goto the_end;
2708 } while(bound);
2709 ret = 0;
2710 the_end:
2711 tcc_free(data);
2712 return ret;
2715 /* load a '.a' file */
2716 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2718 ArchiveHeader hdr;
2719 char ar_size[11];
2720 char ar_name[17];
2721 char magic[8];
2722 int size, len, i;
2723 unsigned long file_offset;
2725 /* skip magic which was already checked */
2726 read(fd, magic, sizeof(magic));
2728 for(;;) {
2729 len = read(fd, &hdr, sizeof(hdr));
2730 if (len == 0)
2731 break;
2732 if (len != sizeof(hdr)) {
2733 tcc_error_noabort("invalid archive");
2734 return -1;
2736 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2737 ar_size[sizeof(hdr.ar_size)] = '\0';
2738 size = strtol(ar_size, NULL, 0);
2739 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2740 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2741 if (ar_name[i] != ' ')
2742 break;
2744 ar_name[i + 1] = '\0';
2745 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2746 file_offset = lseek(fd, 0, SEEK_CUR);
2747 /* align to even */
2748 size = (size + 1) & ~1;
2749 if (!strcmp(ar_name, "/")) {
2750 /* coff symbol table : we handle it */
2751 if(s1->alacarte_link)
2752 return tcc_load_alacarte(s1, fd, size);
2753 } else if (!strcmp(ar_name, "//") ||
2754 !strcmp(ar_name, "__.SYMDEF") ||
2755 !strcmp(ar_name, "__.SYMDEF/") ||
2756 !strcmp(ar_name, "ARFILENAMES/")) {
2757 /* skip symbol table or archive names */
2758 } else {
2759 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2760 return -1;
2762 lseek(fd, file_offset + size, SEEK_SET);
2764 return 0;
2767 #ifndef TCC_TARGET_PE
2768 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2769 is referenced by the user (so it should be added as DT_NEEDED in
2770 the generated ELF file) */
2771 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2773 ElfW(Ehdr) ehdr;
2774 ElfW(Shdr) *shdr, *sh, *sh1;
2775 int i, j, nb_syms, nb_dts, sym_bind, ret;
2776 ElfW(Sym) *sym, *dynsym;
2777 ElfW(Dyn) *dt, *dynamic;
2778 unsigned char *dynstr;
2779 const char *name, *soname;
2780 DLLReference *dllref;
2782 read(fd, &ehdr, sizeof(ehdr));
2784 /* test CPU specific stuff */
2785 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2786 ehdr.e_machine != EM_TCC_TARGET) {
2787 tcc_error_noabort("bad architecture");
2788 return -1;
2791 /* read sections */
2792 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2794 /* load dynamic section and dynamic symbols */
2795 nb_syms = 0;
2796 nb_dts = 0;
2797 dynamic = NULL;
2798 dynsym = NULL; /* avoid warning */
2799 dynstr = NULL; /* avoid warning */
2800 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2801 switch(sh->sh_type) {
2802 case SHT_DYNAMIC:
2803 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2804 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2805 break;
2806 case SHT_DYNSYM:
2807 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2808 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2809 sh1 = &shdr[sh->sh_link];
2810 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2811 break;
2812 default:
2813 break;
2817 /* compute the real library name */
2818 soname = tcc_basename(filename);
2820 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2821 if (dt->d_tag == DT_SONAME) {
2822 soname = dynstr + dt->d_un.d_val;
2826 /* if the dll is already loaded, do not load it */
2827 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2828 dllref = s1->loaded_dlls[i];
2829 if (!strcmp(soname, dllref->name)) {
2830 /* but update level if needed */
2831 if (level < dllref->level)
2832 dllref->level = level;
2833 ret = 0;
2834 goto the_end;
2838 // printf("loading dll '%s'\n", soname);
2840 /* add the dll and its level */
2841 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2842 dllref->level = level;
2843 strcpy(dllref->name, soname);
2844 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2846 /* add dynamic symbols in dynsym_section */
2847 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2848 sym_bind = ELFW(ST_BIND)(sym->st_info);
2849 if (sym_bind == STB_LOCAL)
2850 continue;
2851 name = dynstr + sym->st_name;
2852 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2853 sym->st_info, sym->st_other, sym->st_shndx, name);
2856 /* load all referenced DLLs */
2857 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2858 switch(dt->d_tag) {
2859 case DT_NEEDED:
2860 name = dynstr + dt->d_un.d_val;
2861 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2862 dllref = s1->loaded_dlls[j];
2863 if (!strcmp(name, dllref->name))
2864 goto already_loaded;
2866 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2867 tcc_error_noabort("referenced dll '%s' not found", name);
2868 ret = -1;
2869 goto the_end;
2871 already_loaded:
2872 break;
2875 ret = 0;
2876 the_end:
2877 tcc_free(dynstr);
2878 tcc_free(dynsym);
2879 tcc_free(dynamic);
2880 tcc_free(shdr);
2881 return ret;
2884 #define LD_TOK_NAME 256
2885 #define LD_TOK_EOF (-1)
2887 /* return next ld script token */
2888 static int ld_next(TCCState *s1, char *name, int name_size)
2890 int c;
2891 char *q;
2893 redo:
2894 switch(ch) {
2895 case ' ':
2896 case '\t':
2897 case '\f':
2898 case '\v':
2899 case '\r':
2900 case '\n':
2901 inp();
2902 goto redo;
2903 case '/':
2904 minp();
2905 if (ch == '*') {
2906 file->buf_ptr = parse_comment(file->buf_ptr);
2907 ch = file->buf_ptr[0];
2908 goto redo;
2909 } else {
2910 q = name;
2911 *q++ = '/';
2912 goto parse_name;
2914 break;
2915 /* case 'a' ... 'z': */
2916 case 'a':
2917 case 'b':
2918 case 'c':
2919 case 'd':
2920 case 'e':
2921 case 'f':
2922 case 'g':
2923 case 'h':
2924 case 'i':
2925 case 'j':
2926 case 'k':
2927 case 'l':
2928 case 'm':
2929 case 'n':
2930 case 'o':
2931 case 'p':
2932 case 'q':
2933 case 'r':
2934 case 's':
2935 case 't':
2936 case 'u':
2937 case 'v':
2938 case 'w':
2939 case 'x':
2940 case 'y':
2941 case 'z':
2942 /* case 'A' ... 'z': */
2943 case 'A':
2944 case 'B':
2945 case 'C':
2946 case 'D':
2947 case 'E':
2948 case 'F':
2949 case 'G':
2950 case 'H':
2951 case 'I':
2952 case 'J':
2953 case 'K':
2954 case 'L':
2955 case 'M':
2956 case 'N':
2957 case 'O':
2958 case 'P':
2959 case 'Q':
2960 case 'R':
2961 case 'S':
2962 case 'T':
2963 case 'U':
2964 case 'V':
2965 case 'W':
2966 case 'X':
2967 case 'Y':
2968 case 'Z':
2969 case '_':
2970 case '\\':
2971 case '.':
2972 case '$':
2973 case '~':
2974 q = name;
2975 parse_name:
2976 for(;;) {
2977 if (!((ch >= 'a' && ch <= 'z') ||
2978 (ch >= 'A' && ch <= 'Z') ||
2979 (ch >= '0' && ch <= '9') ||
2980 strchr("/.-_+=$:\\,~", ch)))
2981 break;
2982 if ((q - name) < name_size - 1) {
2983 *q++ = ch;
2985 minp();
2987 *q = '\0';
2988 c = LD_TOK_NAME;
2989 break;
2990 case CH_EOF:
2991 c = LD_TOK_EOF;
2992 break;
2993 default:
2994 c = ch;
2995 inp();
2996 break;
2998 #if 0
2999 printf("tok=%c %d\n", c, c);
3000 if (c == LD_TOK_NAME)
3001 printf(" name=%s\n", name);
3002 #endif
3003 return c;
3006 static int ld_add_file(TCCState *s1, const char filename[])
3008 int ret;
3010 ret = tcc_add_file_internal(s1, filename, 0);
3011 if (ret)
3012 ret = tcc_add_dll(s1, filename, 0);
3013 return ret;
3016 static inline int new_undef_syms(void)
3018 int ret = 0;
3019 ret = new_undef_sym;
3020 new_undef_sym = 0;
3021 return ret;
3024 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
3026 char filename[1024], libname[1024];
3027 int t, group, nblibs = 0, ret = 0;
3028 char **libs = NULL;
3030 group = !strcmp(cmd, "GROUP");
3031 if (!as_needed)
3032 new_undef_syms();
3033 t = ld_next(s1, filename, sizeof(filename));
3034 if (t != '(')
3035 expect("(");
3036 t = ld_next(s1, filename, sizeof(filename));
3037 for(;;) {
3038 libname[0] = '\0';
3039 if (t == LD_TOK_EOF) {
3040 tcc_error_noabort("unexpected end of file");
3041 ret = -1;
3042 goto lib_parse_error;
3043 } else if (t == ')') {
3044 break;
3045 } else if (t == '-') {
3046 t = ld_next(s1, filename, sizeof(filename));
3047 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
3048 tcc_error_noabort("library name expected");
3049 ret = -1;
3050 goto lib_parse_error;
3052 pstrcpy(libname, sizeof libname, &filename[1]);
3053 if (s1->static_link) {
3054 snprintf(filename, sizeof filename, "lib%s.a", libname);
3055 } else {
3056 snprintf(filename, sizeof filename, "lib%s.so", libname);
3058 } else if (t != LD_TOK_NAME) {
3059 tcc_error_noabort("filename expected");
3060 ret = -1;
3061 goto lib_parse_error;
3063 if (!strcmp(filename, "AS_NEEDED")) {
3064 ret = ld_add_file_list(s1, cmd, 1);
3065 if (ret)
3066 goto lib_parse_error;
3067 } else {
3068 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3069 if (!as_needed) {
3070 ret = ld_add_file(s1, filename);
3071 if (ret)
3072 goto lib_parse_error;
3073 if (group) {
3074 /* Add the filename *and* the libname to avoid future conversions */
3075 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
3076 if (libname[0] != '\0')
3077 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
3081 t = ld_next(s1, filename, sizeof(filename));
3082 if (t == ',') {
3083 t = ld_next(s1, filename, sizeof(filename));
3086 if (group && !as_needed) {
3087 while (new_undef_syms()) {
3088 int i;
3090 for (i = 0; i < nblibs; i ++)
3091 ld_add_file(s1, libs[i]);
3094 lib_parse_error:
3095 dynarray_reset(&libs, &nblibs);
3096 return ret;
3099 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3100 files */
3101 ST_FUNC int tcc_load_ldscript(TCCState *s1)
3103 char cmd[64];
3104 char filename[1024];
3105 int t, ret;
3107 ch = file->buf_ptr[0];
3108 ch = handle_eob();
3109 for(;;) {
3110 t = ld_next(s1, cmd, sizeof(cmd));
3111 if (t == LD_TOK_EOF)
3112 return 0;
3113 else if (t != LD_TOK_NAME)
3114 return -1;
3115 if (!strcmp(cmd, "INPUT") ||
3116 !strcmp(cmd, "GROUP")) {
3117 ret = ld_add_file_list(s1, cmd, 0);
3118 if (ret)
3119 return ret;
3120 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3121 !strcmp(cmd, "TARGET")) {
3122 /* ignore some commands */
3123 t = ld_next(s1, cmd, sizeof(cmd));
3124 if (t != '(')
3125 expect("(");
3126 for(;;) {
3127 t = ld_next(s1, filename, sizeof(filename));
3128 if (t == LD_TOK_EOF) {
3129 tcc_error_noabort("unexpected end of file");
3130 return -1;
3131 } else if (t == ')') {
3132 break;
3135 } else {
3136 return -1;
3139 return 0;
3141 #endif /* ndef TCC_TARGET_PE */