Add support for thread-local storage variables
[tinycc.git] / tccelf.c
blob4602ce8c601a548d0ff48ee81dba700786ed6cbd
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 #ifdef TCC_IS_NATIVE
182 /* return elf symbol value or error */
183 ST_FUNC void* tcc_get_symbol_err(TCCState *s, const char *name)
185 return (void*)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;
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_call = (type == R_ARM_CALL);
615 x += val - addr;
616 h = x & 2;
617 #ifdef TCC_HAS_RUNTIME_PLTGOT
618 if (s1->output_type == TCC_OUTPUT_MEMORY) {
619 if ((x & 3) || x >= 0x2000000 || x < -0x2000000)
620 if (!(x & 3) || !blx_avail || !is_call) {
621 x += add_jmp_table(s1, val) - val; /* add veneer */
622 is_thumb = 0; /* Veneer uses ARM instructions */
625 #endif
626 if ((x & 3) || x >= 0x2000000 || x < -0x2000000)
627 if (!(x & 3) || !blx_avail || !is_call)
628 tcc_error("can't relocate value at %x",addr);
629 x >>= 2;
630 x &= 0xffffff;
631 /* Only reached if blx is avail and it is a call */
632 if (is_thumb) {
633 x |= h << 24;
634 (*(int *)ptr) = 0xfa << 24; /* bl -> blx */
636 (*(int *)ptr) |= x;
638 break;
639 /* Since these relocations only concern Thumb-2 and blx instruction was
640 introduced before Thumb-2, we can assume blx is available and not
641 guard its use */
642 case R_ARM_THM_CALL:
643 case R_ARM_THM_JUMP24:
645 int x, hi, lo, s, j1, j2, i1, i2, imm10, imm11;
646 int to_thumb, is_call, to_plt, blx_bit = 1 << 12;
647 Section *plt;
649 /* weak reference */
650 if (sym->st_shndx == SHN_UNDEF &&
651 ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
652 break;
654 /* Get initial offset */
655 hi = (*(uint16_t *)ptr);
656 lo = (*(uint16_t *)(ptr+2));
657 s = (hi >> 10) & 1;
658 j1 = (lo >> 13) & 1;
659 j2 = (lo >> 11) & 1;
660 i1 = (j1 ^ s) ^ 1;
661 i2 = (j2 ^ s) ^ 1;
662 imm10 = hi & 0x3ff;
663 imm11 = lo & 0x7ff;
664 x = (s << 24) | (i1 << 23) | (i2 << 22) |
665 (imm10 << 12) | (imm11 << 1);
666 if (x & 0x01000000)
667 x -= 0x02000000;
669 /* Relocation infos */
670 to_thumb = val & 1;
671 plt = s1->plt;
672 to_plt = (val >= plt->sh_addr) &&
673 (val < plt->sh_addr + plt->data_offset);
674 is_call = (type == R_ARM_THM_CALL);
676 /* Compute final offset */
677 if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */
678 x -= 4;
679 x += val - addr;
680 if (!to_thumb && is_call) {
681 blx_bit = 0; /* bl -> blx */
682 x = (x + 3) & -4; /* Compute offset from aligned PC */
685 /* Check that relocation is possible
686 * offset must not be out of range
687 * if target is to be entered in arm mode:
688 - bit 1 must not set
689 - instruction must be a call (bl) or a jump to PLT */
690 if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
691 if (to_thumb || (val & 2) || (!is_call && !to_plt))
692 tcc_error("can't relocate value at %x",addr);
694 /* Compute and store final offset */
695 s = (x >> 24) & 1;
696 i1 = (x >> 23) & 1;
697 i2 = (x >> 22) & 1;
698 j1 = s ^ (i1 ^ 1);
699 j2 = s ^ (i2 ^ 1);
700 imm10 = (x >> 12) & 0x3ff;
701 imm11 = (x >> 1) & 0x7ff;
702 (*(uint16_t *)ptr) = (uint16_t) ((hi & 0xf800) |
703 (s << 10) | imm10);
704 (*(uint16_t *)(ptr+2)) = (uint16_t) ((lo & 0xc000) |
705 (j1 << 13) | blx_bit | (j2 << 11) |
706 imm11);
708 break;
709 case R_ARM_MOVT_ABS:
710 case R_ARM_MOVW_ABS_NC:
712 int x, imm4, imm12;
713 if (type == R_ARM_MOVT_ABS)
714 val >>= 16;
715 imm12 = val & 0xfff;
716 imm4 = (val >> 12) & 0xf;
717 x = (imm4 << 16) | imm12;
718 if (type == R_ARM_THM_MOVT_ABS)
719 *(int *)ptr |= x;
720 else
721 *(int *)ptr += x;
723 break;
724 case R_ARM_THM_MOVT_ABS:
725 case R_ARM_THM_MOVW_ABS_NC:
727 int x, i, imm4, imm3, imm8;
728 if (type == R_ARM_THM_MOVT_ABS)
729 val >>= 16;
730 imm8 = val & 0xff;
731 imm3 = (val >> 8) & 0x7;
732 i = (val >> 11) & 1;
733 imm4 = (val >> 12) & 0xf;
734 x = (imm3 << 28) | (imm8 << 16) | (i << 10) | imm4;
735 if (type == R_ARM_THM_MOVT_ABS)
736 *(int *)ptr |= x;
737 else
738 *(int *)ptr += x;
740 break;
741 case R_ARM_PREL31:
743 int x;
744 x = (*(int *)ptr) & 0x7fffffff;
745 (*(int *)ptr) &= 0x80000000;
746 x = (x * 2) / 2;
747 x += val - addr;
748 if((x^(x>>1))&0x40000000)
749 tcc_error("can't relocate value at %x",addr);
750 (*(int *)ptr) |= x & 0x7fffffff;
752 case R_ARM_ABS32:
753 *(int *)ptr += val;
754 break;
755 case R_ARM_REL32:
756 *(int *)ptr += val - addr;
757 break;
758 case R_ARM_BASE_PREL:
759 *(int *)ptr += s1->got->sh_addr - addr;
760 break;
761 case R_ARM_GOTOFF32:
762 *(int *)ptr += val - s1->got->sh_addr;
763 break;
764 case R_ARM_GOT_BREL:
765 /* we load the got offset */
766 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
767 break;
768 case R_ARM_COPY:
769 break;
770 case R_ARM_V4BX:
771 /* trade Thumb support for ARMv4 support */
772 if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
773 *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
774 break;
775 default:
776 fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
777 type, (unsigned)addr, ptr, (unsigned)val);
778 break;
779 #elif defined(TCC_TARGET_C67)
780 case R_C60_32:
781 *(int *)ptr += val;
782 break;
783 case R_C60LO16:
785 uint32_t orig;
787 /* put the low 16 bits of the absolute address */
788 // add to what is already there
790 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
791 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
793 //patch both at once - assumes always in pairs Low - High
795 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
796 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
798 break;
799 case R_C60HI16:
800 break;
801 default:
802 fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
803 type, (unsigned)addr, ptr, (unsigned)val);
804 break;
805 #elif defined(TCC_TARGET_X86_64)
806 case R_X86_64_64:
807 if (s1->output_type == TCC_OUTPUT_DLL) {
808 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
809 qrel->r_addend = *(long long *)ptr + val;
810 qrel++;
812 *(long long *)ptr += val;
813 break;
814 case R_X86_64_32:
815 case R_X86_64_32S:
816 if (s1->output_type == TCC_OUTPUT_DLL) {
817 /* XXX: this logic may depend on TCC's codegen
818 now TCC uses R_X86_64_32 even for a 64bit pointer */
819 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
820 qrel->r_addend = *(int *)ptr + val;
821 qrel++;
823 *(int *)ptr += val;
824 break;
826 case R_X86_64_PC32:
827 if (s1->output_type == TCC_OUTPUT_DLL) {
828 /* DLL relocation */
829 esym_index = s1->symtab_to_dynsym[sym_index];
830 if (esym_index) {
831 qrel->r_offset = rel->r_offset;
832 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
833 qrel->r_addend = *(int *)ptr;
834 qrel++;
835 break;
838 /* fall through */
839 case R_X86_64_PLT32: {
840 long long diff;
841 diff = (long long)val - addr;
842 if (diff <= -2147483647 || diff > 2147483647) {
843 #ifdef TCC_HAS_RUNTIME_PLTGOT
844 /* XXX: naive support for over 32bit jump */
845 if (s1->output_type == TCC_OUTPUT_MEMORY) {
846 val = (add_jmp_table(s1, val - rel->r_addend) +
847 rel->r_addend);
848 diff = val - addr;
850 #endif
851 if (diff <= -2147483647 || diff > 2147483647) {
852 tcc_error("internal error: relocation failed");
855 *(int *)ptr += diff;
857 break;
858 case R_X86_64_GLOB_DAT:
859 case R_X86_64_JUMP_SLOT:
860 /* They don't need addend */
861 *(int *)ptr = val - rel->r_addend;
862 break;
863 case R_X86_64_GOTPCREL:
864 #ifdef TCC_HAS_RUNTIME_PLTGOT
865 if (s1->output_type == TCC_OUTPUT_MEMORY) {
866 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
867 *(int *)ptr += val - addr;
868 break;
870 #endif
871 *(int *)ptr += (s1->got->sh_addr - addr +
872 s1->sym_attrs[sym_index].got_offset - 4);
873 break;
874 case R_X86_64_GOTTPOFF:
875 *(int *)ptr += val - s1->got->sh_addr;
876 break;
877 case R_X86_64_GOT32:
878 /* we load the got offset */
879 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
880 break;
881 #else
882 #error unsupported processor
883 #endif
886 /* if the relocation is allocated, we change its symbol table */
887 if (sr->sh_flags & SHF_ALLOC)
888 sr->link = s1->dynsym;
891 /* relocate relocation table in 'sr' */
892 static void relocate_rel(TCCState *s1, Section *sr)
894 Section *s;
895 ElfW_Rel *rel, *rel_end;
897 s = s1->sections[sr->sh_info];
898 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
899 for(rel = (ElfW_Rel *)sr->data;
900 rel < rel_end;
901 rel++) {
902 rel->r_offset += s->sh_addr;
906 /* count the number of dynamic relocations so that we can reserve
907 their space */
908 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
910 ElfW_Rel *rel, *rel_end;
911 int sym_index, esym_index, type, count;
913 count = 0;
914 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
915 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
916 sym_index = ELFW(R_SYM)(rel->r_info);
917 type = ELFW(R_TYPE)(rel->r_info);
918 switch(type) {
919 #if defined(TCC_TARGET_I386)
920 case R_386_32:
921 #elif defined(TCC_TARGET_X86_64)
922 case R_X86_64_32:
923 case R_X86_64_32S:
924 case R_X86_64_64:
925 #endif
926 count++;
927 break;
928 #if defined(TCC_TARGET_I386)
929 case R_386_PC32:
930 #elif defined(TCC_TARGET_X86_64)
931 case R_X86_64_PC32:
932 #endif
933 esym_index = s1->symtab_to_dynsym[sym_index];
934 if (esym_index)
935 count++;
936 break;
937 default:
938 break;
941 if (count) {
942 /* allocate the section */
943 sr->sh_flags |= SHF_ALLOC;
944 sr->sh_size = count * sizeof(ElfW_Rel);
946 return count;
949 static struct sym_attr *alloc_sym_attr(TCCState *s1, int index)
951 int n;
952 struct sym_attr *tab;
954 if (index >= s1->nb_sym_attrs) {
955 /* find immediately bigger power of 2 and reallocate array */
956 n = 1;
957 while (index >= n)
958 n *= 2;
959 tab = tcc_realloc(s1->sym_attrs, n * sizeof(*s1->sym_attrs));
960 s1->sym_attrs = tab;
961 memset(s1->sym_attrs + s1->nb_sym_attrs, 0,
962 (n - s1->nb_sym_attrs) * sizeof(*s1->sym_attrs));
963 s1->nb_sym_attrs = n;
965 return &s1->sym_attrs[index];
968 /* XXX: suppress that */
969 static void put32(unsigned char *p, uint32_t val)
971 p[0] = val;
972 p[1] = val >> 8;
973 p[2] = val >> 16;
974 p[3] = val >> 24;
977 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
978 defined(TCC_TARGET_X86_64)
979 static uint32_t get32(unsigned char *p)
981 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
983 #endif
985 static void build_got(TCCState *s1)
987 unsigned char *ptr;
989 /* if no got, then create it */
990 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
991 s1->got->sh_entsize = 4;
992 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
993 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
994 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
995 #if PTR_SIZE == 4
996 /* keep space for _DYNAMIC pointer, if present */
997 put32(ptr, 0);
998 /* two dummy got entries */
999 put32(ptr + 4, 0);
1000 put32(ptr + 8, 0);
1001 #else
1002 /* keep space for _DYNAMIC pointer, if present */
1003 put32(ptr, 0);
1004 put32(ptr + 4, 0);
1005 /* two dummy got entries */
1006 put32(ptr + 8, 0);
1007 put32(ptr + 12, 0);
1008 put32(ptr + 16, 0);
1009 put32(ptr + 20, 0);
1010 #endif
1013 /* put a got entry corresponding to a symbol in symtab_section. 'size'
1014 and 'info' can be modifed if more precise info comes from the DLL */
1015 static void put_got_entry(TCCState *s1,
1016 int reloc_type, unsigned long size, int info,
1017 int sym_index)
1019 int index;
1020 const char *name;
1021 ElfW(Sym) *sym;
1022 unsigned long offset;
1023 int *ptr;
1025 if (!s1->got)
1026 build_got(s1);
1028 /* if a got entry already exists for that symbol, no need to add one */
1029 if (sym_index < s1->nb_sym_attrs &&
1030 s1->sym_attrs[sym_index].got_offset)
1031 return;
1033 alloc_sym_attr(s1, sym_index)->got_offset = s1->got->data_offset;
1035 if (s1->dynsym) {
1036 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1037 name = symtab_section->link->data + sym->st_name;
1038 offset = sym->st_value;
1039 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1040 if (reloc_type ==
1041 #ifdef TCC_TARGET_X86_64
1042 R_X86_64_JUMP_SLOT
1043 #else
1044 R_386_JMP_SLOT
1045 #endif
1047 Section *plt;
1048 uint8_t *p;
1049 int modrm;
1051 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1052 modrm = 0x25;
1053 #else
1054 /* if we build a DLL, we add a %ebx offset */
1055 if (s1->output_type == TCC_OUTPUT_DLL)
1056 modrm = 0xa3;
1057 else
1058 modrm = 0x25;
1059 #endif
1061 /* add a PLT entry */
1062 plt = s1->plt;
1063 if (plt->data_offset == 0) {
1064 /* first plt entry */
1065 p = section_ptr_add(plt, 16);
1066 p[0] = 0xff; /* pushl got + PTR_SIZE */
1067 p[1] = modrm + 0x10;
1068 put32(p + 2, PTR_SIZE);
1069 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1070 p[7] = modrm;
1071 put32(p + 8, PTR_SIZE * 2);
1074 p = section_ptr_add(plt, 16);
1075 p[0] = 0xff; /* jmp *(got + x) */
1076 p[1] = modrm;
1077 put32(p + 2, s1->got->data_offset);
1078 p[6] = 0x68; /* push $xxx */
1079 put32(p + 7, (plt->data_offset - 32) >> 1);
1080 p[11] = 0xe9; /* jmp plt_start */
1081 put32(p + 12, -(plt->data_offset));
1083 /* the symbol is modified so that it will be relocated to
1084 the PLT */
1085 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
1086 if (s1->output_type == TCC_OUTPUT_EXE)
1087 #endif
1088 offset = plt->data_offset - 16;
1090 #elif defined(TCC_TARGET_ARM)
1091 if (reloc_type == R_ARM_JUMP_SLOT) {
1092 Section *plt;
1093 uint8_t *p;
1095 /* if we build a DLL, we add a %ebx offset */
1096 if (s1->output_type == TCC_OUTPUT_DLL)
1097 tcc_error("DLLs unimplemented!");
1099 /* add a PLT entry */
1100 plt = s1->plt;
1101 if (plt->data_offset == 0) {
1102 /* first plt entry */
1103 p = section_ptr_add(plt, 16);
1104 put32(p , 0xe52de004);
1105 put32(p + 4, 0xe59fe010);
1106 put32(p + 8, 0xe08fe00e);
1107 put32(p + 12, 0xe5bef008);
1110 if (s1->sym_attrs[sym_index].plt_thumb_stub) {
1111 p = section_ptr_add(plt, 20);
1112 put32(p , 0x4778); // bx pc
1113 put32(p+2, 0x46c0); // nop
1114 p += 4;
1115 } else
1116 p = section_ptr_add(plt, 16);
1117 put32(p , 0xe59fc004); // ldr ip, [pc, #4] // offset in GOT
1118 put32(p+4, 0xe08fc00c); // add ip, pc, ip // absolute address or offset
1119 put32(p+8, 0xe59cf000); // ldr pc, [ip] // load absolute address or load offset
1120 put32(p+12, s1->got->data_offset);
1122 /* the symbol is modified so that it will be relocated to
1123 the PLT */
1124 if (s1->output_type == TCC_OUTPUT_EXE)
1125 offset = plt->data_offset - 16;
1127 #elif defined(TCC_TARGET_C67)
1128 tcc_error("C67 got not implemented");
1129 #else
1130 #error unsupported CPU
1131 #endif
1132 index = put_elf_sym(s1->dynsym, offset,
1133 size, info, 0, sym->st_shndx, name);
1134 /* put a got entry */
1135 put_elf_reloc(s1->dynsym, s1->got,
1136 s1->got->data_offset,
1137 reloc_type, index);
1139 ptr = section_ptr_add(s1->got, PTR_SIZE);
1140 *ptr = 0;
1143 /* build GOT and PLT entries */
1144 ST_FUNC void build_got_entries(TCCState *s1)
1146 Section *s;
1147 ElfW_Rel *rel, *rel_end;
1148 ElfW(Sym) *sym;
1149 int i, type, reloc_type, sym_index;
1151 for(i = 1; i < s1->nb_sections; i++) {
1152 s = s1->sections[i];
1153 if (s->sh_type != SHT_RELX)
1154 continue;
1155 /* no need to handle got relocations */
1156 if (s->link != symtab_section)
1157 continue;
1158 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1159 for(rel = (ElfW_Rel *)s->data;
1160 rel < rel_end;
1161 rel++) {
1162 type = ELFW(R_TYPE)(rel->r_info);
1163 switch(type) {
1164 #if defined(TCC_TARGET_I386)
1165 case R_386_GOT32:
1166 case R_386_GOTOFF:
1167 case R_386_GOTPC:
1168 case R_386_PLT32:
1169 if (!s1->got)
1170 build_got(s1);
1171 if (type == R_386_GOT32 || type == R_386_PLT32) {
1172 sym_index = ELFW(R_SYM)(rel->r_info);
1173 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1174 /* look at the symbol got offset. If none, then add one */
1175 if (type == R_386_GOT32)
1176 reloc_type = R_386_GLOB_DAT;
1177 else
1178 reloc_type = R_386_JMP_SLOT;
1179 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1180 sym_index);
1182 break;
1183 #elif defined(TCC_TARGET_ARM)
1184 case R_ARM_GOT_BREL:
1185 case R_ARM_GOTOFF32:
1186 case R_ARM_BASE_PREL:
1187 case R_ARM_PLT32:
1188 if (!s1->got)
1189 build_got(s1);
1190 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1191 sym_index = ELFW(R_SYM)(rel->r_info);
1192 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1193 /* look at the symbol got offset. If none, then add one */
1194 if (type == R_ARM_GOT_BREL)
1195 reloc_type = R_ARM_GLOB_DAT;
1196 else
1197 reloc_type = R_ARM_JUMP_SLOT;
1198 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1199 sym_index);
1201 break;
1202 #elif defined(TCC_TARGET_C67)
1203 case R_C60_GOT32:
1204 case R_C60_GOTOFF:
1205 case R_C60_GOTPC:
1206 case R_C60_PLT32:
1207 if (!s1->got)
1208 build_got(s1);
1209 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1210 sym_index = ELFW(R_SYM)(rel->r_info);
1211 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1212 /* look at the symbol got offset. If none, then add one */
1213 if (type == R_C60_GOT32)
1214 reloc_type = R_C60_GLOB_DAT;
1215 else
1216 reloc_type = R_C60_JMP_SLOT;
1217 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1218 sym_index);
1220 break;
1221 #elif defined(TCC_TARGET_X86_64)
1222 case R_X86_64_GOT32:
1223 case R_X86_64_GOTTPOFF:
1224 case R_X86_64_GOTPCREL:
1225 case R_X86_64_PLT32:
1226 if (!s1->got)
1227 build_got(s1);
1228 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1229 type == R_X86_64_PLT32) {
1230 sym_index = ELFW(R_SYM)(rel->r_info);
1231 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1232 /* look at the symbol got offset. If none, then add one */
1233 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1234 reloc_type = R_X86_64_GLOB_DAT;
1235 else
1236 reloc_type = R_X86_64_JUMP_SLOT;
1237 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1238 sym_index);
1240 break;
1241 #else
1242 #error unsupported CPU
1243 #endif
1244 default:
1245 break;
1251 ST_FUNC Section *new_symtab(TCCState *s1,
1252 const char *symtab_name, int sh_type, int sh_flags,
1253 const char *strtab_name,
1254 const char *hash_name, int hash_sh_flags)
1256 Section *symtab, *strtab, *hash;
1257 int *ptr, nb_buckets;
1259 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1260 symtab->sh_entsize = sizeof(ElfW(Sym));
1261 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1262 put_elf_str(strtab, "");
1263 symtab->link = strtab;
1264 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1266 nb_buckets = 1;
1268 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1269 hash->sh_entsize = sizeof(int);
1270 symtab->hash = hash;
1271 hash->link = symtab;
1273 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1274 ptr[0] = nb_buckets;
1275 ptr[1] = 1;
1276 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1277 return symtab;
1280 /* put dynamic tag */
1281 static void put_dt(Section *dynamic, int dt, addr_t val)
1283 ElfW(Dyn) *dyn;
1284 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1285 dyn->d_tag = dt;
1286 dyn->d_un.d_val = val;
1289 static void add_init_array_defines(TCCState *s1, const char *section_name)
1291 Section *s;
1292 long end_offset;
1293 char sym_start[1024];
1294 char sym_end[1024];
1296 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1297 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1299 s = find_section(s1, section_name);
1300 if (!s) {
1301 end_offset = 0;
1302 s = data_section;
1303 } else {
1304 end_offset = s->data_offset;
1307 add_elf_sym(symtab_section,
1308 0, 0,
1309 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1310 s->sh_num, sym_start);
1311 add_elf_sym(symtab_section,
1312 end_offset, 0,
1313 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1314 s->sh_num, sym_end);
1317 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1319 #ifdef CONFIG_TCC_BCHECK
1320 unsigned long *ptr;
1321 Section *init_section;
1322 unsigned char *pinit;
1323 int sym_index;
1325 if (0 == s1->do_bounds_check)
1326 return;
1328 /* XXX: add an object file to do that */
1329 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1330 *ptr = 0;
1331 add_elf_sym(symtab_section, 0, 0,
1332 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1333 bounds_section->sh_num, "__bounds_start");
1334 #ifdef TCC_TARGET_I386
1335 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1336 /* add 'call __bound_init()' in .init section */
1337 init_section = find_section(s1, ".init");
1338 pinit = section_ptr_add(init_section, 5);
1339 pinit[0] = 0xe8;
1340 put32(pinit + 1, -4);
1341 sym_index = find_elf_sym(symtab_section, "__bound_init");
1342 put_elf_reloc(symtab_section, init_section,
1343 init_section->data_offset - 4, R_386_PC32, sym_index);
1345 #endif
1346 #endif
1349 static inline int tcc_add_support(TCCState *s1, const char *filename)
1351 char buf[1024];
1352 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, filename);
1353 return tcc_add_file(s1, buf);
1356 /* add tcc runtime libraries */
1357 ST_FUNC void tcc_add_runtime(TCCState *s1)
1359 tcc_add_bcheck(s1);
1361 /* add libc */
1362 if (!s1->nostdlib) {
1363 tcc_add_library(s1, "c");
1364 #ifdef CONFIG_USE_LIBGCC
1365 tcc_add_file(s1, TCC_LIBGCC);
1366 #elif !defined WITHOUT_LIBTCC
1367 tcc_add_support(s1, "libtcc1.a");
1368 #endif
1369 /* add crt end if not memory output */
1370 if (s1->output_type != TCC_OUTPUT_MEMORY)
1371 tcc_add_crt(s1, "crtn.o");
1375 /* add various standard linker symbols (must be done after the
1376 sections are filled (for example after allocating common
1377 symbols)) */
1378 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1380 char buf[1024];
1381 int i;
1382 Section *s;
1384 add_elf_sym(symtab_section,
1385 text_section->data_offset, 0,
1386 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1387 text_section->sh_num, "_etext");
1388 add_elf_sym(symtab_section,
1389 data_section->data_offset, 0,
1390 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1391 data_section->sh_num, "_edata");
1392 add_elf_sym(symtab_section,
1393 bss_section->data_offset, 0,
1394 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1395 bss_section->sh_num, "_end");
1396 /* horrible new standard ldscript defines */
1397 add_init_array_defines(s1, ".preinit_array");
1398 add_init_array_defines(s1, ".init_array");
1399 add_init_array_defines(s1, ".fini_array");
1401 /* add start and stop symbols for sections whose name can be
1402 expressed in C */
1403 for(i = 1; i < s1->nb_sections; i++) {
1404 s = s1->sections[i];
1405 if (s->sh_type == SHT_PROGBITS &&
1406 (s->sh_flags & SHF_ALLOC)) {
1407 const char *p;
1408 int ch;
1410 /* check if section name can be expressed in C */
1411 p = s->name;
1412 for(;;) {
1413 ch = *p;
1414 if (!ch)
1415 break;
1416 if (!isid(ch) && !isnum(ch))
1417 goto next_sec;
1418 p++;
1420 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1421 add_elf_sym(symtab_section,
1422 0, 0,
1423 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1424 s->sh_num, buf);
1425 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1426 add_elf_sym(symtab_section,
1427 s->data_offset, 0,
1428 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1429 s->sh_num, buf);
1431 next_sec: ;
1435 static void tcc_output_binary(TCCState *s1, FILE *f,
1436 const int *section_order)
1438 Section *s;
1439 int i, offset, size;
1441 offset = 0;
1442 for(i=1;i<s1->nb_sections;i++) {
1443 s = s1->sections[section_order[i]];
1444 if (s->sh_type != SHT_NOBITS &&
1445 (s->sh_flags & SHF_ALLOC)) {
1446 while (offset < s->sh_offset) {
1447 fputc(0, f);
1448 offset++;
1450 size = s->sh_size;
1451 fwrite(s->data, 1, size, f);
1452 offset += size;
1457 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1458 #define HAVE_PHDR 1
1459 #define EXTRA_RELITEMS 14
1461 /* move the relocation value from .dynsym to .got */
1462 void patch_dynsym_undef(TCCState *s1, Section *s)
1464 uint32_t *gotd = (void *)s1->got->data;
1465 ElfW(Sym) *sym, *sym_end;
1467 gotd += 3; // dummy entries in .got
1468 /* relocate symbols in .dynsym */
1469 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1470 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1471 if (sym->st_shndx == SHN_UNDEF) {
1472 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1473 sym->st_value = 0;
1477 #else
1478 #define HAVE_PHDR 0
1479 #define EXTRA_RELITEMS 9
1481 /* zero plt offsets of weak symbols in .dynsym */
1482 void patch_dynsym_undef(TCCState *s1, Section *s)
1484 ElfW(Sym) *sym, *sym_end;
1486 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1487 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++)
1488 if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
1489 sym->st_value = 0;
1491 #endif
1493 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1495 int sym_index = ELFW(R_SYM) (rel->r_info);
1496 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1497 unsigned long offset;
1499 if (sym_index >= s1->nb_sym_attrs)
1500 return;
1501 offset = s1->sym_attrs[sym_index].got_offset;
1502 section_reserve(s1->got, offset + PTR_SIZE);
1503 #ifdef TCC_TARGET_X86_64
1504 /* only works for x86-64 */
1505 put32(s1->got->data + offset + 4, sym->st_value >> 32);
1506 #endif
1507 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1510 ST_FUNC void fill_got(TCCState *s1)
1512 Section *s;
1513 ElfW_Rel *rel, *rel_end;
1514 int i;
1516 for(i = 1; i < s1->nb_sections; i++) {
1517 s = s1->sections[i];
1518 if (s->sh_type != SHT_RELX)
1519 continue;
1520 /* no need to handle got relocations */
1521 if (s->link != symtab_section)
1522 continue;
1523 rel_end = (ElfW_Rel *) (s->data + s->data_offset);
1524 for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
1525 switch (ELFW(R_TYPE) (rel->r_info)) {
1526 case R_X86_64_GOT32:
1527 case R_X86_64_GOTPCREL:
1528 case R_X86_64_PLT32:
1529 fill_got_entry(s1, rel);
1530 break;
1537 /* output an ELF file */
1538 /* XXX: suppress unneeded sections */
1539 static int elf_output_file(TCCState *s1, const char *filename)
1541 ElfW(Ehdr) ehdr;
1542 FILE *f;
1543 int fd, mode, ret;
1544 int *section_order;
1545 int shnum, i, phnum, file_offset, offset, size, j, sh_order_index, k;
1546 int have_tls_section = 0;
1547 long long tmp;
1548 addr_t addr;
1549 Section *strsec, *s;
1550 ElfW(Shdr) shdr, *sh;
1551 ElfW(Phdr) *phdr, *ph;
1552 Section *interp, *dynamic, *dynstr;
1553 unsigned long saved_dynamic_data_offset;
1554 ElfW(Sym) *sym;
1555 int type, file_type;
1556 addr_t rel_addr, rel_size;
1557 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1558 addr_t bss_addr, bss_size;
1559 #endif
1561 file_type = s1->output_type;
1562 s1->nb_errors = 0;
1564 if (file_type != TCC_OUTPUT_OBJ) {
1565 tcc_add_runtime(s1);
1568 phdr = NULL;
1569 section_order = NULL;
1570 interp = NULL;
1571 dynamic = NULL;
1572 dynstr = NULL; /* avoid warning */
1573 saved_dynamic_data_offset = 0; /* avoid warning */
1575 if (file_type != TCC_OUTPUT_OBJ) {
1576 relocate_common_syms();
1578 tcc_add_linker_symbols(s1);
1580 if (!s1->static_link) {
1581 const char *name;
1582 int sym_index, index;
1583 ElfW(Sym) *esym, *sym_end;
1585 if (file_type == TCC_OUTPUT_EXE) {
1586 char *ptr;
1587 /* allow override the dynamic loader */
1588 const char *elfint = getenv("LD_SO");
1589 if (elfint == NULL)
1590 elfint = CONFIG_TCC_ELFINTERP;
1591 /* add interpreter section only if executable */
1592 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1593 interp->sh_addralign = 1;
1594 ptr = section_ptr_add(interp, 1+strlen(elfint));
1595 strcpy(ptr, elfint);
1598 /* add dynamic symbol table */
1599 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1600 ".dynstr",
1601 ".hash", SHF_ALLOC);
1602 dynstr = s1->dynsym->link;
1604 /* add dynamic section */
1605 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1606 SHF_ALLOC | SHF_WRITE);
1607 dynamic->link = dynstr;
1608 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1610 /* add PLT */
1611 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1612 SHF_ALLOC | SHF_EXECINSTR);
1613 s1->plt->sh_entsize = 4;
1615 build_got(s1);
1617 /* scan for undefined symbols and see if they are in the
1618 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1619 is found, then we add it in the PLT. If a symbol
1620 STT_OBJECT is found, we add it in the .bss section with
1621 a suitable relocation */
1622 sym_end = (ElfW(Sym) *)(symtab_section->data +
1623 symtab_section->data_offset);
1624 if (file_type == TCC_OUTPUT_EXE) {
1625 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1626 sym < sym_end;
1627 sym++) {
1628 if (sym->st_shndx == SHN_UNDEF) {
1629 name = symtab_section->link->data + sym->st_name;
1630 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1631 if (sym_index) {
1632 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1633 type = ELFW(ST_TYPE)(esym->st_info);
1634 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1635 /* Indirect functions shall have STT_FUNC type
1636 * in executable dynsym section. Indeed, a dlsym
1637 * call following a lazy resolution would pick
1638 * the symbol value from the executable dynsym
1639 * entry which would contain the address of the
1640 * function wanted by the caller of dlsym
1641 * instead of the address of the function that
1642 * would return that address */
1643 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1644 ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC),
1645 sym - (ElfW(Sym) *)symtab_section->data);
1646 } else if (type == STT_OBJECT) {
1647 unsigned long offset;
1648 ElfW(Sym) *dynsym, *dynsym_end;
1649 offset = bss_section->data_offset;
1650 /* XXX: which alignment ? */
1651 offset = (offset + 16 - 1) & -16;
1652 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1653 esym->st_info, 0,
1654 bss_section->sh_num, name);
1655 // Ensure R_COPY works for weak symbol aliases
1656 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1657 dynsym_end = (ElfW(Sym) *)
1658 (s1->dynsymtab_section->data +
1659 s1->dynsymtab_section->data_offset);
1660 for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1661 dynsym < dynsym_end; dynsym++) {
1662 if ((dynsym->st_value == esym->st_value)
1663 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1664 char *dynname;
1665 dynname = s1->dynsymtab_section->link->data
1666 + dynsym->st_name;
1667 put_elf_sym(s1->dynsym, offset,
1668 dynsym->st_size,
1669 dynsym->st_info, 0,
1670 bss_section->sh_num,
1671 dynname);
1672 break;
1676 put_elf_reloc(s1->dynsym, bss_section,
1677 offset, R_COPY, index);
1678 offset += esym->st_size;
1679 bss_section->data_offset = offset;
1681 } else {
1682 /* STB_WEAK undefined symbols are accepted */
1683 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1684 it */
1685 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1686 !strcmp(name, "_fp_hw")) {
1687 } else {
1688 tcc_error_noabort("undefined symbol '%s'", name);
1691 } else if (s1->rdynamic &&
1692 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1693 /* if -rdynamic option, then export all non
1694 local symbols */
1695 name = symtab_section->link->data + sym->st_name;
1696 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1697 sym->st_info, 0,
1698 sym->st_shndx, name);
1702 if (s1->nb_errors)
1703 goto fail;
1705 /* now look at unresolved dynamic symbols and export
1706 corresponding symbol */
1707 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1708 s1->dynsymtab_section->data_offset);
1709 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1710 esym < sym_end;
1711 esym++) {
1712 if (esym->st_shndx == SHN_UNDEF) {
1713 name = s1->dynsymtab_section->link->data + esym->st_name;
1714 sym_index = find_elf_sym(symtab_section, name);
1715 if (sym_index) {
1716 /* XXX: avoid adding a symbol if already
1717 present because of -rdynamic ? */
1718 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1719 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1720 sym->st_info, 0,
1721 sym->st_shndx, name);
1722 } else {
1723 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1724 /* weak symbols can stay undefined */
1725 } else {
1726 tcc_warning("undefined dynamic symbol '%s'", name);
1731 } else {
1732 int nb_syms;
1733 /* shared library case : we simply export all the global symbols */
1734 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1735 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1736 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1737 sym < sym_end;
1738 sym++) {
1739 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1740 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1741 if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
1742 ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
1743 && sym->st_shndx == SHN_UNDEF) {
1744 int visibility = ELFW(ST_BIND)(sym->st_info);
1745 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1746 ELFW(ST_INFO)(visibility,STT_FUNC),
1747 sym - (ElfW(Sym) *)symtab_section->data);
1749 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1750 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1751 sym->st_info,
1752 sym - (ElfW(Sym) *)symtab_section->data);
1754 else
1755 #endif
1757 name = symtab_section->link->data + sym->st_name;
1758 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1759 sym->st_info, 0,
1760 sym->st_shndx, name);
1761 s1->symtab_to_dynsym[sym -
1762 (ElfW(Sym) *)symtab_section->data] =
1763 index;
1769 build_got_entries(s1);
1771 /* add a list of needed dlls */
1772 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1773 DLLReference *dllref = s1->loaded_dlls[i];
1774 if (dllref->level == 0)
1775 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1778 if (s1->rpath)
1779 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1781 /* XXX: currently, since we do not handle PIC code, we
1782 must relocate the readonly segments */
1783 if (file_type == TCC_OUTPUT_DLL) {
1784 if (s1->soname)
1785 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1786 put_dt(dynamic, DT_TEXTREL, 0);
1789 if (s1->symbolic)
1790 put_dt(dynamic, DT_SYMBOLIC, 0);
1792 /* add necessary space for other entries */
1793 saved_dynamic_data_offset = dynamic->data_offset;
1794 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1795 } else {
1796 /* still need to build got entries in case of static link */
1797 build_got_entries(s1);
1801 memset(&ehdr, 0, sizeof(ehdr));
1803 /* we add a section for symbols */
1804 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1805 put_elf_str(strsec, "");
1807 /* compute number of sections */
1808 shnum = s1->nb_sections;
1810 /* this array is used to reorder sections in the output file */
1811 section_order = tcc_malloc(sizeof(int) * shnum);
1812 section_order[0] = 0;
1813 sh_order_index = 1;
1815 /* compute number of program headers */
1816 switch(file_type) {
1817 default:
1818 case TCC_OUTPUT_OBJ:
1819 phnum = 0;
1820 break;
1821 case TCC_OUTPUT_EXE:
1822 if (!s1->static_link)
1823 phnum = 4 + HAVE_PHDR;
1824 else
1825 phnum = 2;
1826 break;
1827 case TCC_OUTPUT_DLL:
1828 phnum = 3;
1829 break;
1832 /* allocate strings for section names and decide if an unallocated
1833 section should be output */
1834 /* NOTE: the strsec section comes last, so its size is also
1835 correct ! */
1836 for(i = 1; i < s1->nb_sections; i++) {
1837 s = s1->sections[i];
1838 s->sh_name = put_elf_str(strsec, s->name);
1839 #if 0 /* gr */
1840 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1841 s->sh_flags,
1842 s->sh_type,
1843 s->sh_info,
1844 s->name,
1845 s->reloc ? s->reloc->name : "n"
1847 #endif
1848 /* when generating a DLL, we include relocations but we may
1849 patch them */
1850 if (file_type == TCC_OUTPUT_DLL &&
1851 s->sh_type == SHT_RELX &&
1852 !(s->sh_flags & SHF_ALLOC)) {
1853 /* //gr: avoid bogus relocs for empty (debug) sections */
1854 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1855 prepare_dynamic_rel(s1, s);
1856 else if (s1->do_debug)
1857 s->sh_size = s->data_offset;
1858 } else if (s1->do_debug ||
1859 file_type == TCC_OUTPUT_OBJ ||
1860 (s->sh_flags & SHF_ALLOC) ||
1861 i == (s1->nb_sections - 1)) {
1862 /* we output all sections if debug or object file */
1863 s->sh_size = s->data_offset;
1865 /* if tls section we'll need to add one segment */
1866 if (s->sh_flags & SHF_TLS) {
1867 have_tls_section = 1;
1868 phnum++;
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 + have_tls_section; j++) {
1914 if (j != 2)
1915 ph->p_type = PT_LOAD;
1916 else
1917 ph->p_type = PT_TLS;
1918 ph->p_flags = PF_R;
1919 if (j == 0)
1920 ph->p_flags |= PF_X;
1921 else if (j == 1)
1922 ph->p_flags |= PF_W;
1923 ph->p_align = s1->section_align;
1925 /* we do the following ordering: interp, symbol tables,
1926 relocations, progbits, nobits */
1927 /* XXX: do faster and simpler sorting */
1928 for(k = 0; k < 5; k++) {
1929 for(i = 1; i < s1->nb_sections; i++) {
1930 s = s1->sections[i];
1931 /* compute if section should be included */
1932 if (j == 0) {
1933 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_TLS)) !=
1934 SHF_ALLOC)
1935 continue;
1936 } else if (j == 1) {
1937 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_TLS)) !=
1938 (SHF_ALLOC | SHF_WRITE))
1939 continue;
1940 } else {
1941 if ((s->sh_flags & SHF_TLS) != SHF_TLS)
1942 continue;
1944 if (s == interp) {
1945 if (k != 0)
1946 continue;
1947 } else if (s->sh_type == SHT_DYNSYM ||
1948 s->sh_type == SHT_STRTAB ||
1949 s->sh_type == SHT_HASH) {
1950 if (k != 1)
1951 continue;
1952 } else if (s->sh_type == SHT_RELX) {
1953 if (k != 2)
1954 continue;
1955 } else if (s->sh_type == SHT_NOBITS) {
1956 if (k != 4)
1957 continue;
1958 } else {
1959 if (k != 3)
1960 continue;
1962 section_order[sh_order_index++] = i;
1964 /* section matches: we align it and add its size */
1965 tmp = addr;
1966 addr = (addr + s->sh_addralign - 1) &
1967 ~(s->sh_addralign - 1);
1968 file_offset += (int) ( addr - tmp );
1969 s->sh_offset = file_offset;
1970 s->sh_addr = addr;
1972 /* update program header infos */
1973 if (ph->p_offset == 0) {
1974 ph->p_offset = file_offset;
1975 ph->p_vaddr = addr;
1976 ph->p_paddr = ph->p_vaddr;
1978 /* update dynamic relocation infos */
1979 if (s->sh_type == SHT_RELX) {
1980 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1981 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1982 rel_addr = addr;
1983 rel_size += s->sh_size; // XXX only first rel.
1985 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1986 bss_addr = addr;
1987 bss_size = s->sh_size; // XXX only first rel.
1989 #else
1990 if (rel_size == 0)
1991 rel_addr = addr;
1992 rel_size += s->sh_size;
1993 #endif
1995 addr += s->sh_size;
1996 if (s->sh_type != SHT_NOBITS)
1997 file_offset += s->sh_size;
2000 ph->p_filesz = file_offset - ph->p_offset;
2001 ph->p_memsz = addr - ph->p_vaddr;
2002 ph++;
2003 if (j == 0) {
2004 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2005 /* if in the middle of a page, we duplicate the page in
2006 memory so that one copy is RX and the other is RW */
2007 if ((addr & (s1->section_align - 1)) != 0)
2008 addr += s1->section_align;
2009 } else {
2010 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
2011 file_offset = (file_offset + s1->section_align - 1) &
2012 ~(s1->section_align - 1);
2017 /* if interpreter, then add corresponing program header */
2018 if (interp) {
2019 ph = &phdr[0];
2021 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2023 int len = phnum * sizeof(ElfW(Phdr));
2025 ph->p_type = PT_PHDR;
2026 ph->p_offset = sizeof(ElfW(Ehdr));
2027 ph->p_vaddr = interp->sh_addr - len;
2028 ph->p_paddr = ph->p_vaddr;
2029 ph->p_filesz = ph->p_memsz = len;
2030 ph->p_flags = PF_R | PF_X;
2031 ph->p_align = 4; // interp->sh_addralign;
2032 ph++;
2034 #endif
2036 ph->p_type = PT_INTERP;
2037 ph->p_offset = interp->sh_offset;
2038 ph->p_vaddr = interp->sh_addr;
2039 ph->p_paddr = ph->p_vaddr;
2040 ph->p_filesz = interp->sh_size;
2041 ph->p_memsz = interp->sh_size;
2042 ph->p_flags = PF_R;
2043 ph->p_align = interp->sh_addralign;
2046 /* if dynamic section, then add corresponing program header */
2047 if (dynamic) {
2048 ElfW(Sym) *sym_end;
2050 ph = &phdr[phnum - 1];
2052 ph->p_type = PT_DYNAMIC;
2053 ph->p_offset = dynamic->sh_offset;
2054 ph->p_vaddr = dynamic->sh_addr;
2055 ph->p_paddr = ph->p_vaddr;
2056 ph->p_filesz = dynamic->sh_size;
2057 ph->p_memsz = dynamic->sh_size;
2058 ph->p_flags = PF_R | PF_W;
2059 ph->p_align = dynamic->sh_addralign;
2061 /* put GOT dynamic section address */
2062 put32(s1->got->data, dynamic->sh_addr);
2064 /* relocate the PLT */
2065 if (file_type == TCC_OUTPUT_EXE
2066 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2067 || file_type == TCC_OUTPUT_DLL
2068 #endif
2070 uint8_t *p, *p_end;
2072 p = s1->plt->data;
2073 p_end = p + s1->plt->data_offset;
2074 if (p < p_end) {
2075 #if defined(TCC_TARGET_I386)
2076 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2077 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
2078 p += 16;
2079 while (p < p_end) {
2080 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2081 p += 16;
2083 #elif defined(TCC_TARGET_X86_64)
2084 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
2085 put32(p + 2, get32(p + 2) + x);
2086 put32(p + 8, get32(p + 8) + x - 6);
2087 p += 16;
2088 while (p < p_end) {
2089 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
2090 p += 16;
2092 #elif defined(TCC_TARGET_ARM)
2093 int x;
2094 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
2095 p += 16;
2096 while (p < p_end) {
2097 if (get32(p) == 0x46c04778) /* PLT Thumb stub present */
2098 p += 4;
2099 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
2100 p += 16;
2102 #elif defined(TCC_TARGET_C67)
2103 /* XXX: TODO */
2104 #else
2105 #error unsupported CPU
2106 #endif
2110 /* relocate symbols in .dynsym */
2111 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
2112 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
2113 sym < sym_end;
2114 sym++) {
2115 if (sym->st_shndx == SHN_UNDEF) {
2116 /* relocate to the PLT if the symbol corresponds
2117 to a PLT entry */
2118 if (sym->st_value)
2119 sym->st_value += s1->plt->sh_addr;
2120 } else if (sym->st_shndx < SHN_LORESERVE) {
2121 /* do symbol relocation */
2122 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
2126 /* put dynamic section entries */
2127 dynamic->data_offset = saved_dynamic_data_offset;
2128 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
2129 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
2130 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2131 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
2132 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2133 #ifdef TCC_TARGET_X86_64
2134 put_dt(dynamic, DT_RELA, rel_addr);
2135 put_dt(dynamic, DT_RELASZ, rel_size);
2136 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2137 #else
2138 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2139 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2140 put_dt(dynamic, DT_PLTRELSZ, rel_size);
2141 put_dt(dynamic, DT_JMPREL, rel_addr);
2142 put_dt(dynamic, DT_PLTREL, DT_REL);
2143 put_dt(dynamic, DT_REL, bss_addr);
2144 put_dt(dynamic, DT_RELSZ, bss_size);
2145 #else
2146 put_dt(dynamic, DT_REL, rel_addr);
2147 put_dt(dynamic, DT_RELSZ, rel_size);
2148 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2149 #endif
2150 #endif
2151 if (s1->do_debug)
2152 put_dt(dynamic, DT_DEBUG, 0);
2153 put_dt(dynamic, DT_NULL, 0);
2156 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2157 ehdr.e_phnum = phnum;
2158 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2161 /* all other sections come after */
2162 for(i = 1; i < s1->nb_sections; i++) {
2163 s = s1->sections[i];
2164 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2165 continue;
2166 section_order[sh_order_index++] = i;
2168 file_offset = (file_offset + s->sh_addralign - 1) &
2169 ~(s->sh_addralign - 1);
2170 s->sh_offset = file_offset;
2171 if (s->sh_type != SHT_NOBITS)
2172 file_offset += s->sh_size;
2175 /* if building executable or DLL, then relocate each section
2176 except the GOT which is already relocated */
2177 if (file_type != TCC_OUTPUT_OBJ) {
2178 relocate_syms(s1, 0);
2180 if (s1->nb_errors != 0) {
2181 fail:
2182 ret = -1;
2183 goto the_end;
2186 /* relocate sections */
2187 /* XXX: ignore sections with allocated relocations ? */
2188 for(i = 1; i < s1->nb_sections; i++) {
2189 s = s1->sections[i];
2190 if (s->reloc && s != s1->got)
2191 relocate_section(s1, s);
2194 /* relocate relocation entries if the relocation tables are
2195 allocated in the executable */
2196 for(i = 1; i < s1->nb_sections; i++) {
2197 s = s1->sections[i];
2198 if ((s->sh_flags & SHF_ALLOC) &&
2199 s->sh_type == SHT_RELX) {
2200 relocate_rel(s1, s);
2204 /* get entry point address */
2205 if (file_type == TCC_OUTPUT_EXE)
2206 ehdr.e_entry = get_elf_sym_addr(s1, "_start", 1);
2207 else
2208 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2210 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2211 fill_got(s1);
2213 /* write elf file */
2214 if (file_type == TCC_OUTPUT_OBJ)
2215 mode = 0666;
2216 else
2217 mode = 0777;
2218 unlink(filename);
2219 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2220 if (fd < 0) {
2221 tcc_error_noabort("could not write '%s'", filename);
2222 goto fail;
2224 f = fdopen(fd, "wb");
2225 if (s1->verbose)
2226 printf("<- %s\n", filename);
2228 #ifdef TCC_TARGET_COFF
2229 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2230 tcc_output_coff(s1, f);
2231 } else
2232 #endif
2233 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2234 sort_syms(s1, symtab_section);
2236 /* align to 4 */
2237 file_offset = (file_offset + 3) & -4;
2239 /* fill header */
2240 ehdr.e_ident[0] = ELFMAG0;
2241 ehdr.e_ident[1] = ELFMAG1;
2242 ehdr.e_ident[2] = ELFMAG2;
2243 ehdr.e_ident[3] = ELFMAG3;
2244 ehdr.e_ident[4] = ELFCLASSW;
2245 ehdr.e_ident[5] = ELFDATA2LSB;
2246 ehdr.e_ident[6] = EV_CURRENT;
2247 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2248 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2249 #endif
2250 #ifdef TCC_TARGET_ARM
2251 #ifdef TCC_ARM_EABI
2252 ehdr.e_ident[EI_OSABI] = 0;
2253 ehdr.e_flags = 4 << 24;
2254 #else
2255 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2256 #endif
2257 #endif
2258 switch(file_type) {
2259 default:
2260 case TCC_OUTPUT_EXE:
2261 ehdr.e_type = ET_EXEC;
2262 break;
2263 case TCC_OUTPUT_DLL:
2264 ehdr.e_type = ET_DYN;
2265 break;
2266 case TCC_OUTPUT_OBJ:
2267 ehdr.e_type = ET_REL;
2268 break;
2270 ehdr.e_machine = EM_TCC_TARGET;
2271 ehdr.e_version = EV_CURRENT;
2272 ehdr.e_shoff = file_offset;
2273 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2274 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2275 ehdr.e_shnum = shnum;
2276 ehdr.e_shstrndx = shnum - 1;
2278 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2279 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2280 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2282 for(i=1;i<s1->nb_sections;i++) {
2283 s = s1->sections[section_order[i]];
2284 if (s->sh_type != SHT_NOBITS) {
2285 if (s->sh_type == SHT_DYNSYM)
2286 patch_dynsym_undef(s1, s);
2287 while (offset < s->sh_offset) {
2288 fputc(0, f);
2289 offset++;
2291 size = s->sh_size;
2292 fwrite(s->data, 1, size, f);
2293 offset += size;
2297 /* output section headers */
2298 while (offset < ehdr.e_shoff) {
2299 fputc(0, f);
2300 offset++;
2303 for(i=0;i<s1->nb_sections;i++) {
2304 sh = &shdr;
2305 memset(sh, 0, sizeof(ElfW(Shdr)));
2306 s = s1->sections[i];
2307 if (s) {
2308 sh->sh_name = s->sh_name;
2309 sh->sh_type = s->sh_type;
2310 sh->sh_flags = s->sh_flags;
2311 sh->sh_entsize = s->sh_entsize;
2312 sh->sh_info = s->sh_info;
2313 if (s->link)
2314 sh->sh_link = s->link->sh_num;
2315 sh->sh_addralign = s->sh_addralign;
2316 sh->sh_addr = s->sh_addr;
2317 sh->sh_offset = s->sh_offset;
2318 sh->sh_size = s->sh_size;
2320 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2322 } else {
2323 tcc_output_binary(s1, f, section_order);
2325 fclose(f);
2327 ret = 0;
2328 the_end:
2329 tcc_free(s1->symtab_to_dynsym);
2330 tcc_free(section_order);
2331 tcc_free(phdr);
2332 tcc_free(s1->sym_attrs);
2333 return ret;
2336 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2338 int ret;
2339 #ifdef TCC_TARGET_PE
2340 if (s->output_type != TCC_OUTPUT_OBJ) {
2341 ret = pe_output_file(s, filename);
2342 } else
2343 #endif
2345 ret = elf_output_file(s, filename);
2347 return ret;
2350 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2352 void *data;
2354 data = tcc_malloc(size);
2355 lseek(fd, file_offset, SEEK_SET);
2356 read(fd, data, size);
2357 return data;
2360 typedef struct SectionMergeInfo {
2361 Section *s; /* corresponding existing section */
2362 unsigned long offset; /* offset of the new section in the existing section */
2363 uint8_t new_section; /* true if section 's' was added */
2364 uint8_t link_once; /* true if link once section */
2365 } SectionMergeInfo;
2367 /* load an object file and merge it with current files */
2368 /* XXX: handle correctly stab (debug) info */
2369 ST_FUNC int tcc_load_object_file(TCCState *s1,
2370 int fd, unsigned long file_offset)
2372 ElfW(Ehdr) ehdr;
2373 ElfW(Shdr) *shdr, *sh;
2374 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2375 unsigned char *strsec, *strtab;
2376 int *old_to_new_syms;
2377 char *sh_name, *name;
2378 SectionMergeInfo *sm_table, *sm;
2379 ElfW(Sym) *sym, *symtab;
2380 ElfW_Rel *rel, *rel_end;
2381 Section *s;
2383 int stab_index;
2384 int stabstr_index;
2386 stab_index = stabstr_index = 0;
2388 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2389 goto fail1;
2390 if (ehdr.e_ident[0] != ELFMAG0 ||
2391 ehdr.e_ident[1] != ELFMAG1 ||
2392 ehdr.e_ident[2] != ELFMAG2 ||
2393 ehdr.e_ident[3] != ELFMAG3)
2394 goto fail1;
2395 /* test if object file */
2396 if (ehdr.e_type != ET_REL)
2397 goto fail1;
2398 /* test CPU specific stuff */
2399 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2400 ehdr.e_machine != EM_TCC_TARGET) {
2401 fail1:
2402 tcc_error_noabort("invalid object file");
2403 return -1;
2405 /* read sections */
2406 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2407 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2408 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2410 /* load section names */
2411 sh = &shdr[ehdr.e_shstrndx];
2412 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2414 /* load symtab and strtab */
2415 old_to_new_syms = NULL;
2416 symtab = NULL;
2417 strtab = NULL;
2418 nb_syms = 0;
2419 for(i = 1; i < ehdr.e_shnum; i++) {
2420 sh = &shdr[i];
2421 if (sh->sh_type == SHT_SYMTAB) {
2422 if (symtab) {
2423 tcc_error_noabort("object must contain only one symtab");
2424 fail:
2425 ret = -1;
2426 goto the_end;
2428 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2429 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2430 sm_table[i].s = symtab_section;
2432 /* now load strtab */
2433 sh = &shdr[sh->sh_link];
2434 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2438 /* now examine each section and try to merge its content with the
2439 ones in memory */
2440 for(i = 1; i < ehdr.e_shnum; i++) {
2441 /* no need to examine section name strtab */
2442 if (i == ehdr.e_shstrndx)
2443 continue;
2444 sh = &shdr[i];
2445 sh_name = strsec + sh->sh_name;
2446 /* ignore sections types we do not handle */
2447 if (sh->sh_type != SHT_PROGBITS &&
2448 sh->sh_type != SHT_RELX &&
2449 #ifdef TCC_ARM_EABI
2450 sh->sh_type != SHT_ARM_EXIDX &&
2451 #endif
2452 sh->sh_type != SHT_NOBITS &&
2453 sh->sh_type != SHT_PREINIT_ARRAY &&
2454 sh->sh_type != SHT_INIT_ARRAY &&
2455 sh->sh_type != SHT_FINI_ARRAY &&
2456 strcmp(sh_name, ".stabstr")
2458 continue;
2459 if (sh->sh_addralign < 1)
2460 sh->sh_addralign = 1;
2461 /* find corresponding section, if any */
2462 for(j = 1; j < s1->nb_sections;j++) {
2463 s = s1->sections[j];
2464 if (!strcmp(s->name, sh_name)) {
2465 if (!strncmp(sh_name, ".gnu.linkonce",
2466 sizeof(".gnu.linkonce") - 1)) {
2467 /* if a 'linkonce' section is already present, we
2468 do not add it again. It is a little tricky as
2469 symbols can still be defined in
2470 it. */
2471 sm_table[i].link_once = 1;
2472 goto next;
2473 } else {
2474 goto found;
2478 /* not found: create new section */
2479 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2480 /* take as much info as possible from the section. sh_link and
2481 sh_info will be updated later */
2482 s->sh_addralign = sh->sh_addralign;
2483 s->sh_entsize = sh->sh_entsize;
2484 sm_table[i].new_section = 1;
2485 found:
2486 if (sh->sh_type != s->sh_type) {
2487 tcc_error_noabort("invalid section type");
2488 goto fail;
2491 /* align start of section */
2492 offset = s->data_offset;
2494 if (0 == strcmp(sh_name, ".stab")) {
2495 stab_index = i;
2496 goto no_align;
2498 if (0 == strcmp(sh_name, ".stabstr")) {
2499 stabstr_index = i;
2500 goto no_align;
2503 size = sh->sh_addralign - 1;
2504 offset = (offset + size) & ~size;
2505 if (sh->sh_addralign > s->sh_addralign)
2506 s->sh_addralign = sh->sh_addralign;
2507 s->data_offset = offset;
2508 no_align:
2509 sm_table[i].offset = offset;
2510 sm_table[i].s = s;
2511 /* concatenate sections */
2512 size = sh->sh_size;
2513 if (sh->sh_type != SHT_NOBITS) {
2514 unsigned char *ptr;
2515 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2516 ptr = section_ptr_add(s, size);
2517 read(fd, ptr, size);
2518 } else {
2519 s->data_offset += size;
2521 next: ;
2524 /* //gr relocate stab strings */
2525 if (stab_index && stabstr_index) {
2526 Stab_Sym *a, *b;
2527 unsigned o;
2528 s = sm_table[stab_index].s;
2529 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2530 b = (Stab_Sym *)(s->data + s->data_offset);
2531 o = sm_table[stabstr_index].offset;
2532 while (a < b)
2533 a->n_strx += o, a++;
2536 /* second short pass to update sh_link and sh_info fields of new
2537 sections */
2538 for(i = 1; i < ehdr.e_shnum; i++) {
2539 s = sm_table[i].s;
2540 if (!s || !sm_table[i].new_section)
2541 continue;
2542 sh = &shdr[i];
2543 if (sh->sh_link > 0)
2544 s->link = sm_table[sh->sh_link].s;
2545 if (sh->sh_type == SHT_RELX) {
2546 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2547 /* update backward link */
2548 s1->sections[s->sh_info]->reloc = s;
2551 sm = sm_table;
2553 /* resolve symbols */
2554 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2556 sym = symtab + 1;
2557 for(i = 1; i < nb_syms; i++, sym++) {
2558 if (sym->st_shndx != SHN_UNDEF &&
2559 sym->st_shndx < SHN_LORESERVE) {
2560 sm = &sm_table[sym->st_shndx];
2561 if (sm->link_once) {
2562 /* if a symbol is in a link once section, we use the
2563 already defined symbol. It is very important to get
2564 correct relocations */
2565 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2566 name = strtab + sym->st_name;
2567 sym_index = find_elf_sym(symtab_section, name);
2568 if (sym_index)
2569 old_to_new_syms[i] = sym_index;
2571 continue;
2573 /* if no corresponding section added, no need to add symbol */
2574 if (!sm->s)
2575 continue;
2576 /* convert section number */
2577 sym->st_shndx = sm->s->sh_num;
2578 /* offset value */
2579 sym->st_value += sm->offset;
2581 /* add symbol */
2582 name = strtab + sym->st_name;
2583 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2584 sym->st_info, sym->st_other,
2585 sym->st_shndx, name);
2586 old_to_new_syms[i] = sym_index;
2589 /* third pass to patch relocation entries */
2590 for(i = 1; i < ehdr.e_shnum; i++) {
2591 s = sm_table[i].s;
2592 if (!s)
2593 continue;
2594 sh = &shdr[i];
2595 offset = sm_table[i].offset;
2596 switch(s->sh_type) {
2597 case SHT_RELX:
2598 /* take relocation offset information */
2599 offseti = sm_table[sh->sh_info].offset;
2600 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2601 for(rel = (ElfW_Rel *)(s->data + offset);
2602 rel < rel_end;
2603 rel++) {
2604 int type;
2605 unsigned sym_index;
2606 /* convert symbol index */
2607 type = ELFW(R_TYPE)(rel->r_info);
2608 sym_index = ELFW(R_SYM)(rel->r_info);
2609 /* NOTE: only one symtab assumed */
2610 if (sym_index >= nb_syms)
2611 goto invalid_reloc;
2612 sym_index = old_to_new_syms[sym_index];
2613 /* ignore link_once in rel section. */
2614 if (!sym_index && !sm->link_once
2615 #ifdef TCC_TARGET_ARM
2616 && type != R_ARM_V4BX
2617 #endif
2619 invalid_reloc:
2620 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2621 i, strsec + sh->sh_name, rel->r_offset);
2622 goto fail;
2624 rel->r_info = ELFW(R_INFO)(sym_index, type);
2625 /* offset the relocation offset */
2626 rel->r_offset += offseti;
2627 #ifdef TCC_TARGET_ARM
2628 /* Jumps and branches from a Thumb code to a PLT entry need
2629 special handling since PLT entries are ARM code.
2630 Unconditional bl instructions referencing PLT entries are
2631 handled by converting these instructions into blx
2632 instructions. Other case of instructions referencing a PLT
2633 entry require to add a Thumb stub before the PLT entry to
2634 switch to ARM mode. We set bit 0 of the got offset of a
2635 symbol to indicate such a case. */
2636 if (type == R_ARM_THM_JUMP24)
2637 alloc_sym_attr(s1, sym_index)->plt_thumb_stub = 1;
2638 #endif
2640 break;
2641 default:
2642 break;
2646 ret = 0;
2647 the_end:
2648 tcc_free(symtab);
2649 tcc_free(strtab);
2650 tcc_free(old_to_new_syms);
2651 tcc_free(sm_table);
2652 tcc_free(strsec);
2653 tcc_free(shdr);
2654 return ret;
2657 typedef struct ArchiveHeader {
2658 char ar_name[16]; /* name of this member */
2659 char ar_date[12]; /* file mtime */
2660 char ar_uid[6]; /* owner uid; printed as decimal */
2661 char ar_gid[6]; /* owner gid; printed as decimal */
2662 char ar_mode[8]; /* file mode, printed as octal */
2663 char ar_size[10]; /* file size, printed as decimal */
2664 char ar_fmag[2]; /* should contain ARFMAG */
2665 } ArchiveHeader;
2667 static int get_be32(const uint8_t *b)
2669 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2672 /* load only the objects which resolve undefined symbols */
2673 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2675 int i, bound, nsyms, sym_index, off, ret;
2676 uint8_t *data;
2677 const char *ar_names, *p;
2678 const uint8_t *ar_index;
2679 ElfW(Sym) *sym;
2681 data = tcc_malloc(size);
2682 if (read(fd, data, size) != size)
2683 goto fail;
2684 nsyms = get_be32(data);
2685 ar_index = data + 4;
2686 ar_names = ar_index + nsyms * 4;
2688 do {
2689 bound = 0;
2690 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2691 sym_index = find_elf_sym(symtab_section, p);
2692 if(sym_index) {
2693 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2694 if(sym->st_shndx == SHN_UNDEF) {
2695 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2696 #if 0
2697 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2698 #endif
2699 ++bound;
2700 lseek(fd, off, SEEK_SET);
2701 if(tcc_load_object_file(s1, fd, off) < 0) {
2702 fail:
2703 ret = -1;
2704 goto the_end;
2709 } while(bound);
2710 ret = 0;
2711 the_end:
2712 tcc_free(data);
2713 return ret;
2716 /* load a '.a' file */
2717 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2719 ArchiveHeader hdr;
2720 char ar_size[11];
2721 char ar_name[17];
2722 char magic[8];
2723 int size, len, i;
2724 unsigned long file_offset;
2726 /* skip magic which was already checked */
2727 read(fd, magic, sizeof(magic));
2729 for(;;) {
2730 len = read(fd, &hdr, sizeof(hdr));
2731 if (len == 0)
2732 break;
2733 if (len != sizeof(hdr)) {
2734 tcc_error_noabort("invalid archive");
2735 return -1;
2737 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2738 ar_size[sizeof(hdr.ar_size)] = '\0';
2739 size = strtol(ar_size, NULL, 0);
2740 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2741 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2742 if (ar_name[i] != ' ')
2743 break;
2745 ar_name[i + 1] = '\0';
2746 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2747 file_offset = lseek(fd, 0, SEEK_CUR);
2748 /* align to even */
2749 size = (size + 1) & ~1;
2750 if (!strcmp(ar_name, "/")) {
2751 /* coff symbol table : we handle it */
2752 if(s1->alacarte_link)
2753 return tcc_load_alacarte(s1, fd, size);
2754 } else if (!strcmp(ar_name, "//") ||
2755 !strcmp(ar_name, "__.SYMDEF") ||
2756 !strcmp(ar_name, "__.SYMDEF/") ||
2757 !strcmp(ar_name, "ARFILENAMES/")) {
2758 /* skip symbol table or archive names */
2759 } else {
2760 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2761 return -1;
2763 lseek(fd, file_offset + size, SEEK_SET);
2765 return 0;
2768 #ifndef TCC_TARGET_PE
2769 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2770 is referenced by the user (so it should be added as DT_NEEDED in
2771 the generated ELF file) */
2772 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2774 ElfW(Ehdr) ehdr;
2775 ElfW(Shdr) *shdr, *sh, *sh1;
2776 int i, j, nb_syms, nb_dts, sym_bind, ret;
2777 ElfW(Sym) *sym, *dynsym;
2778 ElfW(Dyn) *dt, *dynamic;
2779 unsigned char *dynstr;
2780 const char *name, *soname;
2781 DLLReference *dllref;
2783 read(fd, &ehdr, sizeof(ehdr));
2785 /* test CPU specific stuff */
2786 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2787 ehdr.e_machine != EM_TCC_TARGET) {
2788 tcc_error_noabort("bad architecture");
2789 return -1;
2792 /* read sections */
2793 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2795 /* load dynamic section and dynamic symbols */
2796 nb_syms = 0;
2797 nb_dts = 0;
2798 dynamic = NULL;
2799 dynsym = NULL; /* avoid warning */
2800 dynstr = NULL; /* avoid warning */
2801 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2802 switch(sh->sh_type) {
2803 case SHT_DYNAMIC:
2804 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2805 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2806 break;
2807 case SHT_DYNSYM:
2808 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2809 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2810 sh1 = &shdr[sh->sh_link];
2811 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2812 break;
2813 default:
2814 break;
2818 /* compute the real library name */
2819 soname = tcc_basename(filename);
2821 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2822 if (dt->d_tag == DT_SONAME) {
2823 soname = dynstr + dt->d_un.d_val;
2827 /* if the dll is already loaded, do not load it */
2828 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2829 dllref = s1->loaded_dlls[i];
2830 if (!strcmp(soname, dllref->name)) {
2831 /* but update level if needed */
2832 if (level < dllref->level)
2833 dllref->level = level;
2834 ret = 0;
2835 goto the_end;
2839 // printf("loading dll '%s'\n", soname);
2841 /* add the dll and its level */
2842 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2843 dllref->level = level;
2844 strcpy(dllref->name, soname);
2845 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2847 /* add dynamic symbols in dynsym_section */
2848 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2849 sym_bind = ELFW(ST_BIND)(sym->st_info);
2850 if (sym_bind == STB_LOCAL)
2851 continue;
2852 name = dynstr + sym->st_name;
2853 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2854 sym->st_info, sym->st_other, sym->st_shndx, name);
2857 /* load all referenced DLLs */
2858 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2859 switch(dt->d_tag) {
2860 case DT_NEEDED:
2861 name = dynstr + dt->d_un.d_val;
2862 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2863 dllref = s1->loaded_dlls[j];
2864 if (!strcmp(name, dllref->name))
2865 goto already_loaded;
2867 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2868 tcc_error_noabort("referenced dll '%s' not found", name);
2869 ret = -1;
2870 goto the_end;
2872 already_loaded:
2873 break;
2876 ret = 0;
2877 the_end:
2878 tcc_free(dynstr);
2879 tcc_free(dynsym);
2880 tcc_free(dynamic);
2881 tcc_free(shdr);
2882 return ret;
2885 #define LD_TOK_NAME 256
2886 #define LD_TOK_EOF (-1)
2888 /* return next ld script token */
2889 static int ld_next(TCCState *s1, char *name, int name_size)
2891 int c;
2892 char *q;
2894 redo:
2895 switch(ch) {
2896 case ' ':
2897 case '\t':
2898 case '\f':
2899 case '\v':
2900 case '\r':
2901 case '\n':
2902 inp();
2903 goto redo;
2904 case '/':
2905 minp();
2906 if (ch == '*') {
2907 file->buf_ptr = parse_comment(file->buf_ptr);
2908 ch = file->buf_ptr[0];
2909 goto redo;
2910 } else {
2911 q = name;
2912 *q++ = '/';
2913 goto parse_name;
2915 break;
2916 /* case 'a' ... 'z': */
2917 case 'a':
2918 case 'b':
2919 case 'c':
2920 case 'd':
2921 case 'e':
2922 case 'f':
2923 case 'g':
2924 case 'h':
2925 case 'i':
2926 case 'j':
2927 case 'k':
2928 case 'l':
2929 case 'm':
2930 case 'n':
2931 case 'o':
2932 case 'p':
2933 case 'q':
2934 case 'r':
2935 case 's':
2936 case 't':
2937 case 'u':
2938 case 'v':
2939 case 'w':
2940 case 'x':
2941 case 'y':
2942 case 'z':
2943 /* case 'A' ... 'z': */
2944 case 'A':
2945 case 'B':
2946 case 'C':
2947 case 'D':
2948 case 'E':
2949 case 'F':
2950 case 'G':
2951 case 'H':
2952 case 'I':
2953 case 'J':
2954 case 'K':
2955 case 'L':
2956 case 'M':
2957 case 'N':
2958 case 'O':
2959 case 'P':
2960 case 'Q':
2961 case 'R':
2962 case 'S':
2963 case 'T':
2964 case 'U':
2965 case 'V':
2966 case 'W':
2967 case 'X':
2968 case 'Y':
2969 case 'Z':
2970 case '_':
2971 case '\\':
2972 case '.':
2973 case '$':
2974 case '~':
2975 q = name;
2976 parse_name:
2977 for(;;) {
2978 if (!((ch >= 'a' && ch <= 'z') ||
2979 (ch >= 'A' && ch <= 'Z') ||
2980 (ch >= '0' && ch <= '9') ||
2981 strchr("/.-_+=$:\\,~", ch)))
2982 break;
2983 if ((q - name) < name_size - 1) {
2984 *q++ = ch;
2986 minp();
2988 *q = '\0';
2989 c = LD_TOK_NAME;
2990 break;
2991 case CH_EOF:
2992 c = LD_TOK_EOF;
2993 break;
2994 default:
2995 c = ch;
2996 inp();
2997 break;
2999 #if 0
3000 printf("tok=%c %d\n", c, c);
3001 if (c == LD_TOK_NAME)
3002 printf(" name=%s\n", name);
3003 #endif
3004 return c;
3007 static int ld_add_file(TCCState *s1, const char filename[])
3009 int ret;
3011 ret = tcc_add_file_internal(s1, filename, 0);
3012 if (ret)
3013 ret = tcc_add_dll(s1, filename, 0);
3014 return ret;
3017 static inline int new_undef_syms(void)
3019 int ret = 0;
3020 ret = new_undef_sym;
3021 new_undef_sym = 0;
3022 return ret;
3025 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
3027 char filename[1024], libname[1024];
3028 int t, group, nblibs = 0, ret = 0;
3029 char **libs = NULL;
3031 group = !strcmp(cmd, "GROUP");
3032 if (!as_needed)
3033 new_undef_syms();
3034 t = ld_next(s1, filename, sizeof(filename));
3035 if (t != '(')
3036 expect("(");
3037 t = ld_next(s1, filename, sizeof(filename));
3038 for(;;) {
3039 libname[0] = '\0';
3040 if (t == LD_TOK_EOF) {
3041 tcc_error_noabort("unexpected end of file");
3042 ret = -1;
3043 goto lib_parse_error;
3044 } else if (t == ')') {
3045 break;
3046 } else if (t == '-') {
3047 t = ld_next(s1, filename, sizeof(filename));
3048 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
3049 tcc_error_noabort("library name expected");
3050 ret = -1;
3051 goto lib_parse_error;
3053 pstrcpy(libname, sizeof libname, &filename[1]);
3054 if (s1->static_link) {
3055 snprintf(filename, sizeof filename, "lib%s.a", libname);
3056 } else {
3057 snprintf(filename, sizeof filename, "lib%s.so", libname);
3059 } else if (t != LD_TOK_NAME) {
3060 tcc_error_noabort("filename expected");
3061 ret = -1;
3062 goto lib_parse_error;
3064 if (!strcmp(filename, "AS_NEEDED")) {
3065 ret = ld_add_file_list(s1, cmd, 1);
3066 if (ret)
3067 goto lib_parse_error;
3068 } else {
3069 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3070 if (!as_needed) {
3071 ret = ld_add_file(s1, filename);
3072 if (ret)
3073 goto lib_parse_error;
3074 if (group) {
3075 /* Add the filename *and* the libname to avoid future conversions */
3076 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
3077 if (libname[0] != '\0')
3078 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
3082 t = ld_next(s1, filename, sizeof(filename));
3083 if (t == ',') {
3084 t = ld_next(s1, filename, sizeof(filename));
3087 if (group && !as_needed) {
3088 while (new_undef_syms()) {
3089 int i;
3091 for (i = 0; i < nblibs; i ++)
3092 ld_add_file(s1, libs[i]);
3095 lib_parse_error:
3096 dynarray_reset(&libs, &nblibs);
3097 return ret;
3100 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3101 files */
3102 ST_FUNC int tcc_load_ldscript(TCCState *s1)
3104 char cmd[64];
3105 char filename[1024];
3106 int t, ret;
3108 ch = file->buf_ptr[0];
3109 ch = handle_eob();
3110 for(;;) {
3111 t = ld_next(s1, cmd, sizeof(cmd));
3112 if (t == LD_TOK_EOF)
3113 return 0;
3114 else if (t != LD_TOK_NAME)
3115 return -1;
3116 if (!strcmp(cmd, "INPUT") ||
3117 !strcmp(cmd, "GROUP")) {
3118 ret = ld_add_file_list(s1, cmd, 0);
3119 if (ret)
3120 return ret;
3121 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3122 !strcmp(cmd, "TARGET")) {
3123 /* ignore some commands */
3124 t = ld_next(s1, cmd, sizeof(cmd));
3125 if (t != '(')
3126 expect("(");
3127 for(;;) {
3128 t = ld_next(s1, filename, sizeof(filename));
3129 if (t == LD_TOK_EOF) {
3130 tcc_error_noabort("unexpected end of file");
3131 return -1;
3132 } else if (t == ')') {
3133 break;
3136 } else {
3137 return -1;
3140 return 0;
3142 #endif /* ndef TCC_TARGET_PE */