Always link libtcc1.a in (useful for va_* on x86)
[tinycc.git] / tccelf.c
blob5072acab4f10d4046240400c1db7d132e7b11954
1 /*
2 * ELF file handling for TCC
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "tcc.h"
23 /* XXX: avoid static variable */
24 static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */
26 ST_FUNC int put_elf_str(Section *s, const char *sym)
28 int offset, len;
29 char *ptr;
31 len = strlen(sym) + 1;
32 offset = s->data_offset;
33 ptr = section_ptr_add(s, len);
34 memcpy(ptr, sym, len);
35 return offset;
38 /* elf symbol hashing function */
39 static unsigned long elf_hash(const unsigned char *name)
41 unsigned long h = 0, g;
43 while (*name) {
44 h = (h << 4) + *name++;
45 g = h & 0xf0000000;
46 if (g)
47 h ^= g >> 24;
48 h &= ~g;
50 return h;
53 /* rebuild hash table of section s */
54 /* NOTE: we do factorize the hash table code to go faster */
55 static void rebuild_hash(Section *s, unsigned int nb_buckets)
57 ElfW(Sym) *sym;
58 int *ptr, *hash, nb_syms, sym_index, h;
59 unsigned char *strtab;
61 strtab = s->link->data;
62 nb_syms = s->data_offset / sizeof(ElfW(Sym));
64 s->hash->data_offset = 0;
65 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
66 ptr[0] = nb_buckets;
67 ptr[1] = nb_syms;
68 ptr += 2;
69 hash = ptr;
70 memset(hash, 0, (nb_buckets + 1) * sizeof(int));
71 ptr += nb_buckets + 1;
73 sym = (ElfW(Sym) *)s->data + 1;
74 for(sym_index = 1; sym_index < nb_syms; sym_index++) {
75 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
76 h = elf_hash(strtab + sym->st_name) % nb_buckets;
77 *ptr = hash[h];
78 hash[h] = sym_index;
79 } else {
80 *ptr = 0;
82 ptr++;
83 sym++;
87 /* return the symbol number */
88 ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size,
89 int info, int other, int shndx, const char *name)
91 int name_offset, sym_index;
92 int nbuckets, h;
93 ElfW(Sym) *sym;
94 Section *hs;
96 sym = section_ptr_add(s, sizeof(ElfW(Sym)));
97 if (name)
98 name_offset = put_elf_str(s->link, name);
99 else
100 name_offset = 0;
101 /* XXX: endianness */
102 sym->st_name = name_offset;
103 sym->st_value = value;
104 sym->st_size = size;
105 sym->st_info = info;
106 sym->st_other = other;
107 sym->st_shndx = shndx;
108 sym_index = sym - (ElfW(Sym) *)s->data;
109 hs = s->hash;
110 if (hs) {
111 int *ptr, *base;
112 ptr = section_ptr_add(hs, sizeof(int));
113 base = (int *)hs->data;
114 /* only add global or weak symbols */
115 if (ELFW(ST_BIND)(info) != STB_LOCAL) {
116 /* add another hashing entry */
117 nbuckets = base[0];
118 h = elf_hash((unsigned char *) name) % nbuckets;
119 *ptr = base[2 + h];
120 base[2 + h] = sym_index;
121 base[1]++;
122 /* we resize the hash table */
123 hs->nb_hashed_syms++;
124 if (hs->nb_hashed_syms > 2 * nbuckets) {
125 rebuild_hash(s, 2 * nbuckets);
127 } else {
128 *ptr = 0;
129 base[1]++;
132 return sym_index;
135 /* find global ELF symbol 'name' and return its index. Return 0 if not
136 found. */
137 ST_FUNC int find_elf_sym(Section *s, const char *name)
139 ElfW(Sym) *sym;
140 Section *hs;
141 int nbuckets, sym_index, h;
142 const char *name1;
144 hs = s->hash;
145 if (!hs)
146 return 0;
147 nbuckets = ((int *)hs->data)[0];
148 h = elf_hash((unsigned char *) name) % nbuckets;
149 sym_index = ((int *)hs->data)[2 + h];
150 while (sym_index != 0) {
151 sym = &((ElfW(Sym) *)s->data)[sym_index];
152 name1 = (char *) s->link->data + sym->st_name;
153 if (!strcmp(name, name1))
154 return sym_index;
155 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
157 return 0;
160 /* return elf symbol value, signal error if 'err' is nonzero */
161 ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err)
163 int sym_index;
164 ElfW(Sym) *sym;
166 sym_index = find_elf_sym(s->symtab, name);
167 sym = &((ElfW(Sym) *)s->symtab->data)[sym_index];
168 if (!sym_index || sym->st_shndx == SHN_UNDEF) {
169 if (err)
170 tcc_error("%s not defined", name);
171 return 0;
173 return sym->st_value;
176 /* return elf symbol value */
177 LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
179 return (void*)(uintptr_t)get_elf_sym_addr(s, name, 0);
182 #if defined TCC_IS_NATIVE || defined TCC_TARGET_PE
183 /* return elf symbol value or error */
184 ST_FUNC void* tcc_get_symbol_err(TCCState *s, const char *name)
186 return (void*)(uintptr_t)get_elf_sym_addr(s, name, 1);
188 #endif
190 /* add an elf symbol : check if it is already defined and patch
191 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
192 ST_FUNC int add_elf_sym(Section *s, addr_t value, unsigned long size,
193 int info, int other, int sh_num, const char *name)
195 ElfW(Sym) *esym;
196 int sym_bind, sym_index, sym_type, esym_bind;
197 unsigned char sym_vis, esym_vis, new_vis;
199 sym_bind = ELFW(ST_BIND)(info);
200 sym_type = ELFW(ST_TYPE)(info);
201 sym_vis = ELFW(ST_VISIBILITY)(other);
203 if (sym_bind != STB_LOCAL) {
204 /* we search global or weak symbols */
205 sym_index = find_elf_sym(s, name);
206 if (!sym_index)
207 goto do_def;
208 esym = &((ElfW(Sym) *)s->data)[sym_index];
209 if (esym->st_shndx != SHN_UNDEF) {
210 esym_bind = ELFW(ST_BIND)(esym->st_info);
211 /* propagate the most constraining visibility */
212 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
213 esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
214 if (esym_vis == STV_DEFAULT) {
215 new_vis = sym_vis;
216 } else if (sym_vis == STV_DEFAULT) {
217 new_vis = esym_vis;
218 } else {
219 new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
221 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
222 | new_vis;
223 other = esym->st_other; /* in case we have to patch esym */
224 if (sh_num == SHN_UNDEF) {
225 /* ignore adding of undefined symbol if the
226 corresponding symbol is already defined */
227 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
228 /* global overrides weak, so patch */
229 goto do_patch;
230 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
231 /* weak is ignored if already global */
232 } else if (sym_bind == STB_WEAK && esym_bind == STB_WEAK) {
233 /* keep first-found weak definition, ignore subsequents */
234 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
235 /* ignore hidden symbols after */
236 } else if (esym->st_shndx == SHN_COMMON
237 && (sh_num < SHN_LORESERVE || sh_num == SHN_COMMON)) {
238 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
239 No idea if this is the correct solution ... */
240 goto do_patch;
241 } else if (s == tcc_state->dynsymtab_section) {
242 /* we accept that two DLL define the same symbol */
243 } else {
244 #if 0
245 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
246 sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
247 #endif
248 tcc_error_noabort("'%s' defined twice", name);
250 } else {
251 do_patch:
252 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
253 esym->st_shndx = sh_num;
254 new_undef_sym = 1;
255 esym->st_value = value;
256 esym->st_size = size;
257 esym->st_other = other;
259 } else {
260 do_def:
261 sym_index = put_elf_sym(s, value, size,
262 ELFW(ST_INFO)(sym_bind, sym_type), other,
263 sh_num, name);
265 return sym_index;
268 /* put relocation */
269 ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
270 int type, int symbol)
272 char buf[256];
273 Section *sr;
274 ElfW_Rel *rel;
276 sr = s->reloc;
277 if (!sr) {
278 /* if no relocation section, create it */
279 snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
280 /* if the symtab is allocated, then we consider the relocation
281 are also */
282 sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
283 sr->sh_entsize = sizeof(ElfW_Rel);
284 sr->link = symtab;
285 sr->sh_info = s->sh_num;
286 s->reloc = sr;
288 rel = section_ptr_add(sr, sizeof(ElfW_Rel));
289 rel->r_offset = offset;
290 rel->r_info = ELFW(R_INFO)(symbol, type);
291 #ifdef TCC_TARGET_X86_64
292 rel->r_addend = 0;
293 #endif
296 /* put stab debug information */
298 ST_FUNC void put_stabs(const char *str, int type, int other, int desc,
299 unsigned long value)
301 Stab_Sym *sym;
303 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
304 if (str) {
305 sym->n_strx = put_elf_str(stabstr_section, str);
306 } else {
307 sym->n_strx = 0;
309 sym->n_type = type;
310 sym->n_other = other;
311 sym->n_desc = desc;
312 sym->n_value = value;
315 ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc,
316 unsigned long value, Section *sec, int sym_index)
318 put_stabs(str, type, other, desc, value);
319 put_elf_reloc(symtab_section, stab_section,
320 stab_section->data_offset - sizeof(unsigned int),
321 R_DATA_32, sym_index);
324 ST_FUNC void put_stabn(int type, int other, int desc, int value)
326 put_stabs(NULL, type, other, desc, value);
329 ST_FUNC void put_stabd(int type, int other, int desc)
331 put_stabs(NULL, type, other, desc, 0);
334 /* Browse each elem of type <type> in section <sec> starting at elem <startoff>
335 using variable <elem> */
336 #define for_each_elem(sec, startoff, elem, type) \
337 for (elem = (type *) sec->data + startoff; \
338 elem < (type *) (sec->data + sec->data_offset); elem++)
340 /* In an ELF file symbol table, the local symbols must appear below
341 the global and weak ones. Since TCC cannot sort it while generating
342 the code, we must do it after. All the relocation tables are also
343 modified to take into account the symbol table sorting */
344 static void sort_syms(TCCState *s1, Section *s)
346 int *old_to_new_syms;
347 ElfW(Sym) *new_syms;
348 int nb_syms, i;
349 ElfW(Sym) *p, *q;
350 ElfW_Rel *rel;
351 Section *sr;
352 int type, sym_index;
354 nb_syms = s->data_offset / sizeof(ElfW(Sym));
355 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
356 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
358 /* first pass for local symbols */
359 p = (ElfW(Sym) *)s->data;
360 q = new_syms;
361 for(i = 0; i < nb_syms; i++) {
362 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
363 old_to_new_syms[i] = q - new_syms;
364 *q++ = *p;
366 p++;
368 /* save the number of local symbols in section header */
369 s->sh_info = q - new_syms;
371 /* then second pass for non local symbols */
372 p = (ElfW(Sym) *)s->data;
373 for(i = 0; i < nb_syms; i++) {
374 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
375 old_to_new_syms[i] = q - new_syms;
376 *q++ = *p;
378 p++;
381 /* we copy the new symbols to the old */
382 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
383 tcc_free(new_syms);
385 /* now we modify all the relocations */
386 for(i = 1; i < s1->nb_sections; i++) {
387 sr = s1->sections[i];
388 if (sr->sh_type == SHT_RELX && sr->link == s) {
389 for_each_elem(sr, 0, rel, ElfW_Rel) {
390 sym_index = ELFW(R_SYM)(rel->r_info);
391 type = ELFW(R_TYPE)(rel->r_info);
392 sym_index = old_to_new_syms[sym_index];
393 rel->r_info = ELFW(R_INFO)(sym_index, type);
398 tcc_free(old_to_new_syms);
401 /* relocate common symbols in the .bss section */
402 ST_FUNC void relocate_common_syms(void)
404 ElfW(Sym) *sym;
405 unsigned long offset, align;
407 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
408 if (sym->st_shndx == SHN_COMMON) {
409 /* align symbol */
410 align = sym->st_value;
411 offset = bss_section->data_offset;
412 offset = (offset + align - 1) & -align;
413 sym->st_value = offset;
414 sym->st_shndx = bss_section->sh_num;
415 offset += sym->st_size;
416 bss_section->data_offset = offset;
421 /* relocate symbol table, resolve undefined symbols if do_resolve is
422 true and output error if undefined symbol. */
423 ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
425 ElfW(Sym) *sym, *esym;
426 int sym_bind, sh_num, sym_index;
427 const char *name;
429 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
430 sh_num = sym->st_shndx;
431 if (sh_num == SHN_UNDEF) {
432 name = (char *) strtab_section->data + sym->st_name;
433 /* Use ld.so to resolve symbol for us (for tcc -run) */
434 if (do_resolve) {
435 #if defined TCC_IS_NATIVE && !defined _WIN32
436 void *addr;
437 name = (char *) symtab_section->link->data + sym->st_name;
438 addr = resolve_sym(s1, name);
439 if (addr) {
440 sym->st_value = (addr_t)addr;
441 goto found;
443 #endif
444 } else if (s1->dynsym) {
445 /* if dynamic symbol exist, then use it */
446 sym_index = find_elf_sym(s1->dynsym, name);
447 if (sym_index) {
448 esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
449 sym->st_value = esym->st_value;
450 goto found;
453 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
454 it */
455 if (!strcmp(name, "_fp_hw"))
456 goto found;
457 /* only weak symbols are accepted to be undefined. Their
458 value is zero */
459 sym_bind = ELFW(ST_BIND)(sym->st_info);
460 if (sym_bind == STB_WEAK) {
461 sym->st_value = 0;
462 } else {
463 tcc_error_noabort("undefined symbol '%s'", name);
465 } else if (sh_num < SHN_LORESERVE) {
466 /* add section base */
467 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
469 found: ;
473 #ifdef TCC_HAS_RUNTIME_PLTGOT
474 #ifdef TCC_TARGET_X86_64
475 #define JMP_TABLE_ENTRY_SIZE 14
476 static addr_t add_jmp_table(TCCState *s1, addr_t val)
478 char *p = s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset;
479 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
480 /* jmp *0x0(%rip) */
481 p[0] = 0xff;
482 p[1] = 0x25;
483 *(int *)(p + 2) = 0;
484 *(addr_t *)(p + 6) = val;
485 return (addr_t)p;
488 static addr_t add_got_table(TCCState *s1, addr_t val)
490 addr_t *p = (addr_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
491 s1->runtime_plt_and_got_offset += sizeof(addr_t);
492 *p = val;
493 return (addr_t)p;
495 #elif defined TCC_TARGET_ARM
496 #define JMP_TABLE_ENTRY_SIZE 8
497 static addr_t add_jmp_table(TCCState *s1, int val)
499 uint32_t *p = (uint32_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
500 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
501 /* ldr pc, [pc, #-4] */
502 p[0] = 0xE51FF004;
503 p[1] = val;
504 return (addr_t)p;
506 #endif
507 #endif /* def TCC_HAS_RUNTIME_PLTGOT */
509 /* relocate a given section (CPU dependent) by applying the relocations
510 in the associated relocation section */
511 ST_FUNC void relocate_section(TCCState *s1, Section *s)
513 Section *sr = s->reloc;
514 ElfW_Rel *rel;
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 ElfW_Rel *qrel = (ElfW_Rel *) sr->data; /* ptr to next reloc entry reused */
521 int esym_index;
522 #endif
524 for_each_elem(sr, 0, rel, ElfW_Rel) {
525 ptr = s->data + rel->r_offset;
527 sym_index = ELFW(R_SYM)(rel->r_info);
528 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
529 val = sym->st_value;
530 #ifdef TCC_TARGET_X86_64
531 val += rel->r_addend;
532 #endif
533 type = ELFW(R_TYPE)(rel->r_info);
534 addr = s->sh_addr + rel->r_offset;
536 /* CPU specific */
537 switch(type) {
538 #if defined(TCC_TARGET_I386)
539 case R_386_32:
540 if (s1->output_type == TCC_OUTPUT_DLL) {
541 esym_index = s1->symtab_to_dynsym[sym_index];
542 qrel->r_offset = rel->r_offset;
543 if (esym_index) {
544 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
545 qrel++;
546 break;
547 } else {
548 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
549 qrel++;
552 *(int *)ptr += val;
553 break;
554 case R_386_PC32:
555 if (s1->output_type == TCC_OUTPUT_DLL) {
556 /* DLL relocation */
557 esym_index = s1->symtab_to_dynsym[sym_index];
558 if (esym_index) {
559 qrel->r_offset = rel->r_offset;
560 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
561 qrel++;
562 break;
565 *(int *)ptr += val - addr;
566 break;
567 case R_386_PLT32:
568 *(int *)ptr += val - addr;
569 break;
570 case R_386_GLOB_DAT:
571 case R_386_JMP_SLOT:
572 *(int *)ptr = val;
573 break;
574 case R_386_GOTPC:
575 *(int *)ptr += s1->got->sh_addr - addr;
576 break;
577 case R_386_GOTOFF:
578 *(int *)ptr += val - s1->got->sh_addr;
579 break;
580 case R_386_GOT32:
581 /* we load the got offset */
582 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
583 break;
584 case R_386_16:
585 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
586 output_file:
587 tcc_error("can only produce 16-bit binary files");
589 *(short *)ptr += val;
590 break;
591 case R_386_PC16:
592 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
593 goto output_file;
594 *(short *)ptr += val - addr;
595 break;
596 #elif defined(TCC_TARGET_ARM)
597 case R_ARM_PC24:
598 case R_ARM_CALL:
599 case R_ARM_JUMP24:
600 case R_ARM_PLT32:
602 int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko;
603 x = (*(int *) ptr) & 0xffffff;
604 (*(int *)ptr) &= 0xff000000;
605 if (x & 0x800000)
606 x -= 0x1000000;
607 x <<= 2;
608 blx_avail = (TCC_ARM_VERSION >= 5);
609 is_thumb = val & 1;
610 is_bl = (*(unsigned *) ptr) >> 24 == 0xeb;
611 is_call = (type == R_ARM_CALL || (type == R_ARM_PC24 && is_bl));
612 x += val - addr;
613 h = x & 2;
614 th_ko = (x & 3) && (!blx_avail || !is_call);
615 #ifdef TCC_HAS_RUNTIME_PLTGOT
616 if (s1->output_type == TCC_OUTPUT_MEMORY) {
617 if (th_ko || x >= 0x2000000 || x < -0x2000000) {
618 x += add_jmp_table(s1, val) - val; /* add veneer */
619 th_ko = (x & 3) && (!blx_avail || !is_call);
620 is_thumb = 0; /* Veneer uses ARM instructions */
623 #endif
624 if (th_ko || x >= 0x2000000 || x < -0x2000000)
625 tcc_error("can't relocate value at %x",addr);
626 x >>= 2;
627 x &= 0xffffff;
628 /* Only reached if blx is avail and it is a call */
629 if (is_thumb) {
630 x |= h << 24;
631 (*(int *)ptr) = 0xfa << 24; /* bl -> blx */
633 (*(int *) ptr) |= x;
635 break;
636 /* Since these relocations only concern Thumb-2 and blx instruction was
637 introduced before Thumb-2, we can assume blx is available and not
638 guard its use */
639 case R_ARM_THM_PC22:
640 case R_ARM_THM_JUMP24:
642 int x, hi, lo, s, j1, j2, i1, i2, imm10, imm11;
643 int to_thumb, is_call, to_plt, blx_bit = 1 << 12;
644 Section *plt;
646 /* weak reference */
647 if (sym->st_shndx == SHN_UNDEF &&
648 ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
649 break;
651 /* Get initial offset */
652 hi = (*(uint16_t *)ptr);
653 lo = (*(uint16_t *)(ptr+2));
654 s = (hi >> 10) & 1;
655 j1 = (lo >> 13) & 1;
656 j2 = (lo >> 11) & 1;
657 i1 = (j1 ^ s) ^ 1;
658 i2 = (j2 ^ s) ^ 1;
659 imm10 = hi & 0x3ff;
660 imm11 = lo & 0x7ff;
661 x = (s << 24) | (i1 << 23) | (i2 << 22) |
662 (imm10 << 12) | (imm11 << 1);
663 if (x & 0x01000000)
664 x -= 0x02000000;
666 /* Relocation infos */
667 to_thumb = val & 1;
668 plt = s1->plt;
669 to_plt = (val >= plt->sh_addr) &&
670 (val < plt->sh_addr + plt->data_offset);
671 is_call = (type == R_ARM_THM_PC22);
673 /* Compute final offset */
674 if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */
675 x -= 4;
676 x += val - addr;
677 if (!to_thumb && is_call) {
678 blx_bit = 0; /* bl -> blx */
679 x = (x + 3) & -4; /* Compute offset from aligned PC */
682 /* Check that relocation is possible
683 * offset must not be out of range
684 * if target is to be entered in arm mode:
685 - bit 1 must not set
686 - instruction must be a call (bl) or a jump to PLT */
687 if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
688 if (to_thumb || (val & 2) || (!is_call && !to_plt))
689 tcc_error("can't relocate value at %x",addr);
691 /* Compute and store final offset */
692 s = (x >> 24) & 1;
693 i1 = (x >> 23) & 1;
694 i2 = (x >> 22) & 1;
695 j1 = s ^ (i1 ^ 1);
696 j2 = s ^ (i2 ^ 1);
697 imm10 = (x >> 12) & 0x3ff;
698 imm11 = (x >> 1) & 0x7ff;
699 (*(uint16_t *)ptr) = (uint16_t) ((hi & 0xf800) |
700 (s << 10) | imm10);
701 (*(uint16_t *)(ptr+2)) = (uint16_t) ((lo & 0xc000) |
702 (j1 << 13) | blx_bit | (j2 << 11) |
703 imm11);
705 break;
706 case R_ARM_MOVT_ABS:
707 case R_ARM_MOVW_ABS_NC:
709 int x, imm4, imm12;
710 if (type == R_ARM_MOVT_ABS)
711 val >>= 16;
712 imm12 = val & 0xfff;
713 imm4 = (val >> 12) & 0xf;
714 x = (imm4 << 16) | imm12;
715 if (type == R_ARM_THM_MOVT_ABS)
716 *(int *)ptr |= x;
717 else
718 *(int *)ptr += x;
720 break;
721 case R_ARM_THM_MOVT_ABS:
722 case R_ARM_THM_MOVW_ABS_NC:
724 int x, i, imm4, imm3, imm8;
725 if (type == R_ARM_THM_MOVT_ABS)
726 val >>= 16;
727 imm8 = val & 0xff;
728 imm3 = (val >> 8) & 0x7;
729 i = (val >> 11) & 1;
730 imm4 = (val >> 12) & 0xf;
731 x = (imm3 << 28) | (imm8 << 16) | (i << 10) | imm4;
732 if (type == R_ARM_THM_MOVT_ABS)
733 *(int *)ptr |= x;
734 else
735 *(int *)ptr += x;
737 break;
738 case R_ARM_PREL31:
740 int x;
741 x = (*(int *)ptr) & 0x7fffffff;
742 (*(int *)ptr) &= 0x80000000;
743 x = (x * 2) / 2;
744 x += val - addr;
745 if((x^(x>>1))&0x40000000)
746 tcc_error("can't relocate value at %x",addr);
747 (*(int *)ptr) |= x & 0x7fffffff;
749 case R_ARM_ABS32:
750 *(int *)ptr += val;
751 break;
752 case R_ARM_REL32:
753 *(int *)ptr += val - addr;
754 break;
755 case R_ARM_GOTPC:
756 *(int *)ptr += s1->got->sh_addr - addr;
757 break;
758 case R_ARM_GOTOFF:
759 *(int *)ptr += val - s1->got->sh_addr;
760 break;
761 case R_ARM_GOT32:
762 /* we load the got offset */
763 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
764 break;
765 case R_ARM_COPY:
766 break;
767 case R_ARM_V4BX:
768 /* trade Thumb support for ARMv4 support */
769 if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
770 *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
771 break;
772 default:
773 fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
774 type, (unsigned)addr, ptr, (unsigned)val);
775 break;
776 #elif defined(TCC_TARGET_C67)
777 case R_C60_32:
778 *(int *)ptr += val;
779 break;
780 case R_C60LO16:
782 uint32_t orig;
784 /* put the low 16 bits of the absolute address
785 add to what is already there */
787 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
788 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
790 /* patch both at once - assumes always in pairs Low - High */
792 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
793 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
795 break;
796 case R_C60HI16:
797 break;
798 default:
799 fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
800 type, (unsigned)addr, ptr, (unsigned)val);
801 break;
802 #elif defined(TCC_TARGET_X86_64)
803 case R_X86_64_64:
804 if (s1->output_type == TCC_OUTPUT_DLL) {
805 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
806 qrel->r_addend = *(long long *)ptr + val;
807 qrel++;
809 *(long long *)ptr += val;
810 break;
811 case R_X86_64_32:
812 case R_X86_64_32S:
813 if (s1->output_type == TCC_OUTPUT_DLL) {
814 /* XXX: this logic may depend on TCC's codegen
815 now TCC uses R_X86_64_32 even for a 64bit pointer */
816 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
817 qrel->r_addend = *(int *)ptr + val;
818 qrel++;
820 *(int *)ptr += val;
821 break;
823 case R_X86_64_PC32:
824 if (s1->output_type == TCC_OUTPUT_DLL) {
825 /* DLL relocation */
826 esym_index = s1->symtab_to_dynsym[sym_index];
827 if (esym_index) {
828 qrel->r_offset = rel->r_offset;
829 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
830 qrel->r_addend = *(int *)ptr;
831 qrel++;
832 break;
835 /* fall through */
836 case R_X86_64_PLT32: {
837 long long diff;
838 diff = (long long)val - addr;
839 if (diff <= -2147483647 || diff > 2147483647) {
840 #ifdef TCC_HAS_RUNTIME_PLTGOT
841 /* XXX: naive support for over 32bit jump */
842 if (s1->output_type == TCC_OUTPUT_MEMORY) {
843 val = (add_jmp_table(s1, val - rel->r_addend) +
844 rel->r_addend);
845 diff = val - addr;
847 #endif
848 if (diff <= -2147483647 || diff > 2147483647) {
849 tcc_error("internal error: relocation failed");
852 *(int *)ptr += diff;
854 break;
855 case R_X86_64_GLOB_DAT:
856 case R_X86_64_JUMP_SLOT:
857 /* They don't need addend */
858 *(int *)ptr = val - rel->r_addend;
859 break;
860 case R_X86_64_GOTPCREL:
861 #ifdef TCC_HAS_RUNTIME_PLTGOT
862 if (s1->output_type == TCC_OUTPUT_MEMORY) {
863 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
864 *(int *)ptr += val - addr;
865 break;
867 #endif
868 *(int *)ptr += (s1->got->sh_addr - addr +
869 s1->sym_attrs[sym_index].got_offset - 4);
870 break;
871 case R_X86_64_GOTTPOFF:
872 *(int *)ptr += val - s1->got->sh_addr;
873 break;
874 case R_X86_64_GOT32:
875 /* we load the got offset */
876 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
877 break;
878 #else
879 #error unsupported processor
880 #endif
883 /* if the relocation is allocated, we change its symbol table */
884 if (sr->sh_flags & SHF_ALLOC)
885 sr->link = s1->dynsym;
888 /* relocate relocation table in 'sr' */
889 static void relocate_rel(TCCState *s1, Section *sr)
891 Section *s;
892 ElfW_Rel *rel;
894 s = s1->sections[sr->sh_info];
895 for_each_elem(sr, 0, rel, ElfW_Rel)
896 rel->r_offset += s->sh_addr;
899 /* count the number of dynamic relocations so that we can reserve
900 their space */
901 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
903 ElfW_Rel *rel;
904 int sym_index, esym_index, type, count;
906 count = 0;
907 for_each_elem(sr, 0, rel, ElfW_Rel) {
908 sym_index = ELFW(R_SYM)(rel->r_info);
909 type = ELFW(R_TYPE)(rel->r_info);
910 switch(type) {
911 #if defined(TCC_TARGET_I386)
912 case R_386_32:
913 #elif defined(TCC_TARGET_X86_64)
914 case R_X86_64_32:
915 case R_X86_64_32S:
916 case R_X86_64_64:
917 #endif
918 count++;
919 break;
920 #if defined(TCC_TARGET_I386)
921 case R_386_PC32:
922 #elif defined(TCC_TARGET_X86_64)
923 case R_X86_64_PC32:
924 #endif
925 esym_index = s1->symtab_to_dynsym[sym_index];
926 if (esym_index)
927 count++;
928 break;
929 default:
930 break;
933 if (count) {
934 /* allocate the section */
935 sr->sh_flags |= SHF_ALLOC;
936 sr->sh_size = count * sizeof(ElfW_Rel);
938 return count;
941 static struct sym_attr *alloc_sym_attr(TCCState *s1, int index)
943 int n;
944 struct sym_attr *tab;
946 if (index >= s1->nb_sym_attrs) {
947 /* find immediately bigger power of 2 and reallocate array */
948 n = 1;
949 while (index >= n)
950 n *= 2;
951 tab = tcc_realloc(s1->sym_attrs, n * sizeof(*s1->sym_attrs));
952 s1->sym_attrs = tab;
953 memset(s1->sym_attrs + s1->nb_sym_attrs, 0,
954 (n - s1->nb_sym_attrs) * sizeof(*s1->sym_attrs));
955 s1->nb_sym_attrs = n;
957 return &s1->sym_attrs[index];
960 /* XXX: suppress that */
961 static void put32(unsigned char *p, uint32_t val)
963 p[0] = val;
964 p[1] = val >> 8;
965 p[2] = val >> 16;
966 p[3] = val >> 24;
969 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
970 defined(TCC_TARGET_X86_64)
971 static uint32_t get32(unsigned char *p)
973 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
975 #endif
977 static void build_got(TCCState *s1)
979 unsigned char *ptr;
981 /* if no got, then create it */
982 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
983 s1->got->sh_entsize = 4;
984 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
985 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
986 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
987 #if PTR_SIZE == 4
988 /* keep space for _DYNAMIC pointer, if present */
989 put32(ptr, 0);
990 /* two dummy got entries */
991 put32(ptr + 4, 0);
992 put32(ptr + 8, 0);
993 #else
994 /* keep space for _DYNAMIC pointer, if present */
995 put32(ptr, 0);
996 put32(ptr + 4, 0);
997 /* two dummy got entries */
998 put32(ptr + 8, 0);
999 put32(ptr + 12, 0);
1000 put32(ptr + 16, 0);
1001 put32(ptr + 20, 0);
1002 #endif
1005 /* put a got entry corresponding to a symbol in symtab_section. 'size'
1006 and 'info' can be modifed if more precise info comes from the DLL */
1007 static void put_got_entry(TCCState *s1,
1008 int reloc_type, unsigned long size, int info,
1009 int sym_index)
1011 int index;
1012 const char *name;
1013 ElfW(Sym) *sym;
1014 unsigned long offset;
1015 int *ptr;
1017 if (!s1->got)
1018 build_got(s1);
1020 /* if a got entry already exists for that symbol, no need to add one */
1021 if (sym_index < s1->nb_sym_attrs &&
1022 s1->sym_attrs[sym_index].got_offset)
1023 return;
1025 alloc_sym_attr(s1, sym_index)->got_offset = s1->got->data_offset;
1027 if (s1->dynsym) {
1028 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1029 name = (char *) symtab_section->link->data + sym->st_name;
1030 offset = sym->st_value;
1031 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1032 if (reloc_type ==
1033 #ifdef TCC_TARGET_X86_64
1034 R_X86_64_JUMP_SLOT
1035 #else
1036 R_386_JMP_SLOT
1037 #endif
1039 Section *plt;
1040 uint8_t *p;
1041 int modrm;
1043 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1044 modrm = 0x25;
1045 #else
1046 /* if we build a DLL, we add a %ebx offset */
1047 if (s1->output_type == TCC_OUTPUT_DLL)
1048 modrm = 0xa3;
1049 else
1050 modrm = 0x25;
1051 #endif
1053 /* add a PLT entry */
1054 plt = s1->plt;
1055 if (plt->data_offset == 0) {
1056 /* first plt entry */
1057 p = section_ptr_add(plt, 16);
1058 p[0] = 0xff; /* pushl got + PTR_SIZE */
1059 p[1] = modrm + 0x10;
1060 put32(p + 2, PTR_SIZE);
1061 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1062 p[7] = modrm;
1063 put32(p + 8, PTR_SIZE * 2);
1066 p = section_ptr_add(plt, 16);
1067 p[0] = 0xff; /* jmp *(got + x) */
1068 p[1] = modrm;
1069 put32(p + 2, s1->got->data_offset);
1070 p[6] = 0x68; /* push $xxx */
1071 put32(p + 7, (plt->data_offset - 32) >> 1);
1072 p[11] = 0xe9; /* jmp plt_start */
1073 put32(p + 12, -(plt->data_offset));
1075 /* the symbol is modified so that it will be relocated to
1076 the PLT */
1077 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
1078 if (s1->output_type == TCC_OUTPUT_EXE)
1079 #endif
1080 offset = plt->data_offset - 16;
1082 #elif defined(TCC_TARGET_ARM)
1083 if (reloc_type == R_ARM_JUMP_SLOT) {
1084 Section *plt;
1085 uint8_t *p;
1087 /* if we build a DLL, we add a %ebx offset */
1088 if (s1->output_type == TCC_OUTPUT_DLL)
1089 tcc_error("DLLs unimplemented!");
1091 /* add a PLT entry */
1092 plt = s1->plt;
1093 if (plt->data_offset == 0) {
1094 /* first plt entry */
1095 p = section_ptr_add(plt, 16);
1096 put32(p, 0xe52de004); /* push {lr} */
1097 put32(p+4, 0xe59fe010); /* ldr lr, [pc, #16] */
1098 put32(p+8, 0xe08fe00e); /* add lr, pc, lr */
1099 put32(p+12, 0xe5bef008); /* ldr pc, [lr, #8]! */
1102 if (s1->sym_attrs[sym_index].plt_thumb_stub) {
1103 p = section_ptr_add(plt, 20);
1104 put32(p, 0x4778); /* bx pc */
1105 put32(p+2, 0x46c0); /* nop */
1106 p += 4;
1107 } else
1108 p = section_ptr_add(plt, 16);
1109 put32(p, 0xe59fc004); /* ldr ip, [pc, #4] ; GOT entry offset */
1110 put32(p+4, 0xe08fc00c); /* add ip, pc, ip ; addr of GOT entry */
1111 put32(p+8, 0xe59cf000); /* ldr pc, [ip] ; jump to GOT entry */
1112 put32(p+12, s1->got->data_offset); /* GOT entry off once patched */
1114 /* the symbol is modified so that it will be relocated to
1115 the PLT */
1116 if (s1->output_type == TCC_OUTPUT_EXE)
1117 offset = plt->data_offset - 16;
1119 #elif defined(TCC_TARGET_C67)
1120 tcc_error("C67 got not implemented");
1121 #else
1122 #error unsupported CPU
1123 #endif
1124 index = put_elf_sym(s1->dynsym, offset,
1125 size, info, 0, sym->st_shndx, name);
1126 /* put a got entry */
1127 put_elf_reloc(s1->dynsym, s1->got,
1128 s1->got->data_offset,
1129 reloc_type, index);
1131 ptr = section_ptr_add(s1->got, PTR_SIZE);
1132 *ptr = 0;
1135 /* build GOT and PLT entries */
1136 ST_FUNC void build_got_entries(TCCState *s1)
1138 Section *s;
1139 ElfW_Rel *rel;
1140 ElfW(Sym) *sym;
1141 int i, type, reloc_type, sym_index;
1143 for(i = 1; i < s1->nb_sections; i++) {
1144 s = s1->sections[i];
1145 if (s->sh_type != SHT_RELX)
1146 continue;
1147 /* no need to handle got relocations */
1148 if (s->link != symtab_section)
1149 continue;
1150 for_each_elem(s, 0, rel, ElfW_Rel) {
1151 type = ELFW(R_TYPE)(rel->r_info);
1152 switch(type) {
1153 #if defined(TCC_TARGET_I386)
1154 case R_386_GOT32:
1155 case R_386_GOTOFF:
1156 case R_386_GOTPC:
1157 case R_386_PLT32:
1158 if (!s1->got)
1159 build_got(s1);
1160 if (type == R_386_GOT32 || type == R_386_PLT32) {
1161 sym_index = ELFW(R_SYM)(rel->r_info);
1162 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1163 /* look at the symbol got offset. If none, then add one */
1164 if (type == R_386_GOT32)
1165 reloc_type = R_386_GLOB_DAT;
1166 else
1167 reloc_type = R_386_JMP_SLOT;
1168 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1169 sym_index);
1171 break;
1172 #elif defined(TCC_TARGET_ARM)
1173 case R_ARM_GOT32:
1174 case R_ARM_GOTOFF:
1175 case R_ARM_GOTPC:
1176 case R_ARM_PLT32:
1177 if (!s1->got)
1178 build_got(s1);
1179 if (type == R_ARM_GOT32 || type == R_ARM_PLT32) {
1180 sym_index = ELFW(R_SYM)(rel->r_info);
1181 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1182 /* look at the symbol got offset. If none, then add one */
1183 if (type == R_ARM_GOT32)
1184 reloc_type = R_ARM_GLOB_DAT;
1185 else
1186 reloc_type = R_ARM_JUMP_SLOT;
1187 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1188 sym_index);
1190 break;
1191 case R_ARM_THM_JUMP24:
1192 sym_index = ELFW(R_SYM)(rel->r_info);
1193 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1194 /* We are relocating a jump from thumb code to arm code */
1195 if (sym->st_shndx != SHN_UNDEF && !(sym->st_value & 1)) {
1196 int index;
1197 uint8_t *p;
1198 char *name, buf[1024];
1199 Section *text_section;
1201 name = (char *) symtab_section->link->data + sym->st_name;
1202 text_section = s1->sections[sym->st_shndx];
1203 /* Modify reloc to target a thumb stub to switch to ARM */
1204 snprintf(buf, sizeof(buf), "%s_from_thumb", name);
1205 index = put_elf_sym(symtab_section,
1206 text_section->data_offset + 1,
1207 sym->st_size, sym->st_info, 0,
1208 sym->st_shndx, buf);
1209 rel->r_info = ELFW(R_INFO)(index, type);
1210 /* Create a thumb stub fonction to switch to ARM mode */
1211 put_elf_reloc(symtab_section, text_section,
1212 text_section->data_offset + 4, R_ARM_JUMP24,
1213 sym_index);
1214 p = section_ptr_add(text_section, 8);
1215 put32(p, 0x4778); /* bx pc */
1216 put32(p+2, 0x46c0); /* nop */
1217 put32(p+4, 0xeafffffe); /* b $sym */
1219 #elif defined(TCC_TARGET_C67)
1220 case R_C60_GOT32:
1221 case R_C60_GOTOFF:
1222 case R_C60_GOTPC:
1223 case R_C60_PLT32:
1224 if (!s1->got)
1225 build_got(s1);
1226 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1227 sym_index = ELFW(R_SYM)(rel->r_info);
1228 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1229 /* look at the symbol got offset. If none, then add one */
1230 if (type == R_C60_GOT32)
1231 reloc_type = R_C60_GLOB_DAT;
1232 else
1233 reloc_type = R_C60_JMP_SLOT;
1234 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1235 sym_index);
1237 break;
1238 #elif defined(TCC_TARGET_X86_64)
1239 case R_X86_64_GOT32:
1240 case R_X86_64_GOTTPOFF:
1241 case R_X86_64_GOTPCREL:
1242 case R_X86_64_PLT32:
1243 if (!s1->got)
1244 build_got(s1);
1245 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1246 type == R_X86_64_PLT32) {
1247 sym_index = ELFW(R_SYM)(rel->r_info);
1248 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1249 /* look at the symbol got offset. If none, then add one */
1250 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1251 reloc_type = R_X86_64_GLOB_DAT;
1252 else
1253 reloc_type = R_X86_64_JUMP_SLOT;
1254 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1255 sym_index);
1257 break;
1258 #else
1259 #error unsupported CPU
1260 #endif
1261 default:
1262 break;
1268 ST_FUNC Section *new_symtab(TCCState *s1,
1269 const char *symtab_name, int sh_type, int sh_flags,
1270 const char *strtab_name,
1271 const char *hash_name, int hash_sh_flags)
1273 Section *symtab, *strtab, *hash;
1274 int *ptr, nb_buckets;
1276 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1277 symtab->sh_entsize = sizeof(ElfW(Sym));
1278 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1279 put_elf_str(strtab, "");
1280 symtab->link = strtab;
1281 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1283 nb_buckets = 1;
1285 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1286 hash->sh_entsize = sizeof(int);
1287 symtab->hash = hash;
1288 hash->link = symtab;
1290 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1291 ptr[0] = nb_buckets;
1292 ptr[1] = 1;
1293 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1294 return symtab;
1297 /* put dynamic tag */
1298 static void put_dt(Section *dynamic, int dt, addr_t val)
1300 ElfW(Dyn) *dyn;
1301 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1302 dyn->d_tag = dt;
1303 dyn->d_un.d_val = val;
1306 static void add_init_array_defines(TCCState *s1, const char *section_name)
1308 Section *s;
1309 long end_offset;
1310 char sym_start[1024];
1311 char sym_end[1024];
1313 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1314 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1316 s = find_section(s1, section_name);
1317 if (!s) {
1318 end_offset = 0;
1319 s = data_section;
1320 } else {
1321 end_offset = s->data_offset;
1324 add_elf_sym(symtab_section,
1325 0, 0,
1326 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1327 s->sh_num, sym_start);
1328 add_elf_sym(symtab_section,
1329 end_offset, 0,
1330 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1331 s->sh_num, sym_end);
1334 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1336 #ifdef CONFIG_TCC_BCHECK
1337 unsigned long *ptr;
1338 Section *init_section;
1339 unsigned char *pinit;
1340 int sym_index;
1342 if (0 == s1->do_bounds_check)
1343 return;
1345 /* XXX: add an object file to do that */
1346 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1347 *ptr = 0;
1348 add_elf_sym(symtab_section, 0, 0,
1349 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1350 bounds_section->sh_num, "__bounds_start");
1351 #ifdef TCC_TARGET_I386
1352 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1353 /* add 'call __bound_init()' in .init section */
1354 init_section = find_section(s1, ".init");
1355 pinit = section_ptr_add(init_section, 5);
1356 pinit[0] = 0xe8;
1357 put32(pinit + 1, -4);
1358 sym_index = find_elf_sym(symtab_section, "__bound_init");
1359 put_elf_reloc(symtab_section, init_section,
1360 init_section->data_offset - 4, R_386_PC32, sym_index);
1362 #endif
1363 #endif
1366 static inline int tcc_add_support(TCCState *s1, const char *filename)
1368 char buf[1024];
1369 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, filename);
1370 return tcc_add_file(s1, buf);
1373 /* add tcc runtime libraries */
1374 ST_FUNC void tcc_add_runtime(TCCState *s1)
1376 /* add libc */
1377 if (!s1->nostdlib) {
1378 tcc_add_library(s1, "c");
1379 #ifdef CONFIG_USE_LIBGCC
1380 if (!s1->static_link) {
1381 tcc_add_file(s1, TCC_LIBGCC);
1382 tcc_add_support(s1, "libtcc1.a");
1383 } else
1384 tcc_add_support(s1, "libtcc1.a");
1385 #else
1386 tcc_add_support(s1, "libtcc1.a");
1387 #endif
1390 /* tcc_add_bcheck tries to relocate a call to __bound_init in _init so
1391 libtcc1.a must be loaded before for __bound_init to be defined and
1392 crtn.o must be loaded after to not finalize _init too early. */
1393 tcc_add_bcheck(s1);
1395 if (!s1->nostdlib) {
1396 /* add crt end if not memory output */
1397 if (s1->output_type != TCC_OUTPUT_MEMORY)
1398 tcc_add_crt(s1, "crtn.o");
1402 /* add various standard linker symbols (must be done after the
1403 sections are filled (for example after allocating common
1404 symbols)) */
1405 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1407 char buf[1024];
1408 int i;
1409 Section *s;
1411 add_elf_sym(symtab_section,
1412 text_section->data_offset, 0,
1413 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1414 text_section->sh_num, "_etext");
1415 add_elf_sym(symtab_section,
1416 data_section->data_offset, 0,
1417 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1418 data_section->sh_num, "_edata");
1419 add_elf_sym(symtab_section,
1420 bss_section->data_offset, 0,
1421 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1422 bss_section->sh_num, "_end");
1423 /* horrible new standard ldscript defines */
1424 add_init_array_defines(s1, ".preinit_array");
1425 add_init_array_defines(s1, ".init_array");
1426 add_init_array_defines(s1, ".fini_array");
1428 /* add start and stop symbols for sections whose name can be
1429 expressed in C */
1430 for(i = 1; i < s1->nb_sections; i++) {
1431 s = s1->sections[i];
1432 if (s->sh_type == SHT_PROGBITS &&
1433 (s->sh_flags & SHF_ALLOC)) {
1434 const char *p;
1435 int ch;
1437 /* check if section name can be expressed in C */
1438 p = s->name;
1439 for(;;) {
1440 ch = *p;
1441 if (!ch)
1442 break;
1443 if (!isid(ch) && !isnum(ch))
1444 goto next_sec;
1445 p++;
1447 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1448 add_elf_sym(symtab_section,
1449 0, 0,
1450 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1451 s->sh_num, buf);
1452 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1453 add_elf_sym(symtab_section,
1454 s->data_offset, 0,
1455 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1456 s->sh_num, buf);
1458 next_sec: ;
1462 static void tcc_output_binary(TCCState *s1, FILE *f,
1463 const int *sec_order)
1465 Section *s;
1466 int i, offset, size;
1468 offset = 0;
1469 for(i=1;i<s1->nb_sections;i++) {
1470 s = s1->sections[sec_order[i]];
1471 if (s->sh_type != SHT_NOBITS &&
1472 (s->sh_flags & SHF_ALLOC)) {
1473 while (offset < s->sh_offset) {
1474 fputc(0, f);
1475 offset++;
1477 size = s->sh_size;
1478 fwrite(s->data, 1, size, f);
1479 offset += size;
1484 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1485 #define HAVE_PHDR 1
1486 #define EXTRA_RELITEMS 14
1488 /* move the relocation value from .dynsym to .got */
1489 void patch_dynsym_undef(TCCState *s1, Section *s)
1491 uint32_t *gotd = (void *)s1->got->data;
1492 ElfW(Sym) *sym;
1494 gotd += 3; /* dummy entries in .got */
1495 /* relocate symbols in .dynsym */
1496 for_each_elem(s, 1, sym, ElfW(Sym)) {
1497 if (sym->st_shndx == SHN_UNDEF) {
1498 *gotd++ = sym->st_value + 6; /* XXX 6 is magic ? */
1499 sym->st_value = 0;
1503 #else
1504 #define HAVE_PHDR 0
1505 #define EXTRA_RELITEMS 9
1507 /* zero plt offsets of weak symbols in .dynsym */
1508 void patch_dynsym_undef(TCCState *s1, Section *s)
1510 ElfW(Sym) *sym;
1512 for_each_elem(s, 1, sym, ElfW(Sym))
1513 if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
1514 sym->st_value = 0;
1516 #endif
1518 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1520 int sym_index = ELFW(R_SYM) (rel->r_info);
1521 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1522 unsigned long offset;
1524 if (sym_index >= s1->nb_sym_attrs)
1525 return;
1526 offset = s1->sym_attrs[sym_index].got_offset;
1527 section_reserve(s1->got, offset + PTR_SIZE);
1528 #ifdef TCC_TARGET_X86_64
1529 /* only works for x86-64 */
1530 put32(s1->got->data + offset + 4, sym->st_value >> 32);
1531 #endif
1532 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1535 /* Perform relocation to GOT or PLT entries */
1536 ST_FUNC void fill_got(TCCState *s1)
1538 Section *s;
1539 ElfW_Rel *rel;
1540 int i;
1542 for(i = 1; i < s1->nb_sections; i++) {
1543 s = s1->sections[i];
1544 if (s->sh_type != SHT_RELX)
1545 continue;
1546 /* no need to handle got relocations */
1547 if (s->link != symtab_section)
1548 continue;
1549 for_each_elem(s, 0, rel, ElfW_Rel) {
1550 switch (ELFW(R_TYPE) (rel->r_info)) {
1551 case R_X86_64_GOT32:
1552 case R_X86_64_GOTPCREL:
1553 case R_X86_64_PLT32:
1554 fill_got_entry(s1, rel);
1555 break;
1561 /* Bind symbols of executable: resolve undefined symbols from exported symbols
1562 in shared libraries and export non local defined symbols to shared libraries
1563 if -rdynamic switch was given on command line */
1564 static void bind_exe_dynsyms(TCCState *s1)
1566 const char *name;
1567 int sym_index, index;
1568 ElfW(Sym) *sym, *esym;
1569 int type;
1571 /* Resolve undefined symbols from dynamic symbols. When there is a match:
1572 - if STT_FUNC or STT_GNU_IFUNC symbol -> add it in PLT
1573 - if STT_OBJECT symbol -> add it in .bss section with suitable reloc */
1574 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
1575 if (sym->st_shndx == SHN_UNDEF) {
1576 name = (char *) symtab_section->link->data + sym->st_name;
1577 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1578 if (sym_index) {
1579 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1580 type = ELFW(ST_TYPE)(esym->st_info);
1581 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1582 /* Indirect functions shall have STT_FUNC type in executable
1583 * dynsym section. Indeed, a dlsym call following a lazy
1584 * resolution would pick the symbol value from the
1585 * executable dynsym entry which would contain the address
1586 * of the function wanted by the caller of dlsym instead of
1587 * the address of the function that would return that
1588 * address */
1589 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1590 ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC),
1591 sym - (ElfW(Sym) *)symtab_section->data);
1592 } else if (type == STT_OBJECT) {
1593 unsigned long offset;
1594 ElfW(Sym) *dynsym;
1595 offset = bss_section->data_offset;
1596 /* XXX: which alignment ? */
1597 offset = (offset + 16 - 1) & -16;
1598 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1599 esym->st_info, 0, bss_section->sh_num,
1600 name);
1601 /* Ensure R_COPY works for weak symbol aliases */
1602 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1603 for_each_elem(s1->dynsymtab_section, 1, dynsym, ElfW(Sym)) {
1604 if ((dynsym->st_value == esym->st_value)
1605 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1606 char *dynname = (char *) s1->dynsymtab_section->link->data
1607 + dynsym->st_name;
1608 put_elf_sym(s1->dynsym, offset, dynsym->st_size,
1609 dynsym->st_info, 0,
1610 bss_section->sh_num, dynname);
1611 break;
1615 put_elf_reloc(s1->dynsym, bss_section,
1616 offset, R_COPY, index);
1617 offset += esym->st_size;
1618 bss_section->data_offset = offset;
1620 } else {
1621 /* STB_WEAK undefined symbols are accepted */
1622 /* XXX: _fp_hw seems to be part of the ABI, so we ignore it */
1623 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1624 !strcmp(name, "_fp_hw")) {
1625 } else {
1626 tcc_error_noabort("undefined symbol '%s'", name);
1629 } else if (s1->rdynamic && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1630 /* if -rdynamic option, then export all non local symbols */
1631 name = (char *) symtab_section->link->data + sym->st_name;
1632 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, sym->st_info,
1633 0, sym->st_shndx, name);
1638 /* Bind symbols of libraries: export non local symbols of executable that
1639 resolve undefined symbols of shared libraries */
1640 static void bind_libs_dynsyms(TCCState *s1)
1642 const char *name;
1643 int sym_index;
1644 ElfW(Sym) *sym, *esym;
1646 /* now look at unresolved dynamic symbols and export
1647 corresponding symbol */
1648 for_each_elem(s1->dynsymtab_section, 1, esym, ElfW(Sym)) {
1649 if (esym->st_shndx == SHN_UNDEF) {
1650 name = (char *) s1->dynsymtab_section->link->data + esym->st_name;
1651 sym_index = find_elf_sym(symtab_section, name);
1652 if (sym_index) {
1653 /* XXX: avoid adding a symbol if already present because of
1654 -rdynamic ? */
1655 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1656 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1657 sym->st_info, 0, sym->st_shndx, name);
1658 } else {
1659 /* weak symbols can stay undefined */
1660 if (ELFW(ST_BIND)(esym->st_info) != STB_WEAK)
1661 tcc_warning("undefined dynamic symbol '%s'", name);
1667 /* Export all non local symbols (for shared libraries) */
1668 static void export_global_syms(TCCState *s1)
1670 int nb_syms, dynindex, index;
1671 const char *name;
1672 ElfW(Sym) *sym;
1674 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1675 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1676 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
1677 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1678 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1679 int type = ELFW(ST_TYPE)(sym->st_info);
1680 if ((type == STT_FUNC || type == STT_GNU_IFUNC)
1681 && sym->st_shndx == SHN_UNDEF) {
1682 int visibility = ELFW(ST_BIND)(sym->st_info);
1683 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1684 ELFW(ST_INFO)(visibility, STT_FUNC),
1685 sym - (ElfW(Sym) *) symtab_section->data);
1686 } else if (type == STT_OBJECT) {
1687 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size, sym->st_info,
1688 sym - (ElfW(Sym) *) symtab_section->data);
1689 } else
1690 #endif
1692 name = (char *) symtab_section->link->data + sym->st_name;
1693 dynindex = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1694 sym->st_info, 0, sym->st_shndx, name);
1695 index = sym - (ElfW(Sym) *) symtab_section->data;
1696 s1->symtab_to_dynsym[index] = dynindex;
1702 /* relocate the PLT: compute addresses and offsets in the PLT now that final
1703 address for PLT and GOT are known (see fill_program_header) */
1704 static void relocate_plt(TCCState *s1)
1706 uint8_t *p, *p_end;
1708 p = s1->plt->data;
1709 p_end = p + s1->plt->data_offset;
1710 if (p < p_end) {
1711 #if defined(TCC_TARGET_I386)
1712 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1713 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1714 p += 16;
1715 while (p < p_end) {
1716 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1717 p += 16;
1719 #elif defined(TCC_TARGET_X86_64)
1720 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1721 put32(p + 2, get32(p + 2) + x);
1722 put32(p + 8, get32(p + 8) + x - 6);
1723 p += 16;
1724 while (p < p_end) {
1725 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1726 p += 16;
1728 #elif defined(TCC_TARGET_ARM)
1729 int x;
1730 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1731 p += 16;
1732 while (p < p_end) {
1733 if (get32(p) == 0x46c04778) /* PLT Thumb stub present */
1734 p += 4;
1735 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1736 p += 16;
1738 #elif defined(TCC_TARGET_C67)
1739 /* XXX: TODO */
1740 #else
1741 #error unsupported CPU
1742 #endif
1746 /* Allocate strings for section names and decide if an unallocated section
1747 should be output.
1749 NOTE: the strsec section comes last, so its size is also correct ! */
1750 static void alloc_sec_names(TCCState *s1, int file_type, Section *strsec)
1752 int i;
1753 Section *s;
1755 /* Allocate strings for section names */
1756 for(i = 1; i < s1->nb_sections; i++) {
1757 s = s1->sections[i];
1758 s->sh_name = put_elf_str(strsec, s->name);
1759 /* when generating a DLL, we include relocations but we may
1760 patch them */
1761 if (file_type == TCC_OUTPUT_DLL &&
1762 s->sh_type == SHT_RELX &&
1763 !(s->sh_flags & SHF_ALLOC)) {
1764 /* gr: avoid bogus relocs for empty (debug) sections */
1765 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1766 prepare_dynamic_rel(s1, s);
1767 else if (s1->do_debug)
1768 s->sh_size = s->data_offset;
1769 } else if (s1->do_debug ||
1770 file_type == TCC_OUTPUT_OBJ ||
1771 (s->sh_flags & SHF_ALLOC) ||
1772 i == (s1->nb_sections - 1)) {
1773 /* we output all sections if debug or object file */
1774 s->sh_size = s->data_offset;
1779 /* Info to be copied in dynamic section */
1780 struct dyn_inf {
1781 Section *dynamic;
1782 Section *dynstr;
1783 unsigned long dyn_rel_off;
1784 addr_t rel_addr;
1785 addr_t rel_size;
1786 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1787 addr_t bss_addr;
1788 addr_t bss_size;
1789 #endif
1792 /* Assign sections to segments and decide how are sections laid out when loaded
1793 in memory. This function also fills corresponding program headers. */
1794 static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
1795 Section *interp, struct dyn_inf *dyninf,
1796 int *sec_order)
1798 int i, j, k, file_type, sh_order_index, file_offset;
1799 long long tmp;
1800 addr_t addr;
1801 ElfW(Phdr) *ph;
1802 Section *s;
1804 file_type = s1->output_type;
1805 sh_order_index = 1;
1806 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
1807 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1808 else
1809 file_offset = 0;
1811 if (phnum > 0) {
1812 if (s1->has_text_addr) {
1813 int a_offset, p_offset;
1814 addr = s1->text_addr;
1815 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1816 ELF_PAGE_SIZE */
1817 a_offset = (int) (addr & (s1->section_align - 1));
1818 p_offset = file_offset & (s1->section_align - 1);
1819 if (a_offset < p_offset)
1820 a_offset += s1->section_align;
1821 file_offset += (a_offset - p_offset);
1822 } else {
1823 if (file_type == TCC_OUTPUT_DLL)
1824 addr = 0;
1825 else
1826 addr = ELF_START_ADDR;
1827 /* compute address after headers */
1828 addr += (file_offset & (s1->section_align - 1));
1831 ph = &phdr[0];
1832 /* Leave one program headers for the program interpreter and one for
1833 the program header table itself if needed. These are done later as
1834 they require section layout to be done first. */
1835 if (interp)
1836 ph += 1 + HAVE_PHDR;
1838 /* dynamic relocation table information, for .dynamic section */
1839 dyninf->rel_addr = dyninf->rel_size = 0;
1840 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1841 dyninf->bss_addr = dyninf->bss_size = 0;
1842 #endif
1844 for(j = 0; j < 2; j++) {
1845 ph->p_type = PT_LOAD;
1846 if (j == 0)
1847 ph->p_flags = PF_R | PF_X;
1848 else
1849 ph->p_flags = PF_R | PF_W;
1850 ph->p_align = s1->section_align;
1852 /* Decide the layout of sections loaded in memory. This must
1853 be done before program headers are filled since they contain
1854 info about the layout. We do the following ordering: interp,
1855 symbol tables, relocations, progbits, nobits */
1856 /* XXX: do faster and simpler sorting */
1857 for(k = 0; k < 5; k++) {
1858 for(i = 1; i < s1->nb_sections; i++) {
1859 s = s1->sections[i];
1860 /* compute if section should be included */
1861 if (j == 0) {
1862 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1863 SHF_ALLOC)
1864 continue;
1865 } else {
1866 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1867 (SHF_ALLOC | SHF_WRITE))
1868 continue;
1870 if (s == interp) {
1871 if (k != 0)
1872 continue;
1873 } else if (s->sh_type == SHT_DYNSYM ||
1874 s->sh_type == SHT_STRTAB ||
1875 s->sh_type == SHT_HASH) {
1876 if (k != 1)
1877 continue;
1878 } else if (s->sh_type == SHT_RELX) {
1879 if (k != 2)
1880 continue;
1881 } else if (s->sh_type == SHT_NOBITS) {
1882 if (k != 4)
1883 continue;
1884 } else {
1885 if (k != 3)
1886 continue;
1888 sec_order[sh_order_index++] = i;
1890 /* section matches: we align it and add its size */
1891 tmp = addr;
1892 addr = (addr + s->sh_addralign - 1) &
1893 ~(s->sh_addralign - 1);
1894 file_offset += (int) ( addr - tmp );
1895 s->sh_offset = file_offset;
1896 s->sh_addr = addr;
1898 /* update program header infos */
1899 if (ph->p_offset == 0) {
1900 ph->p_offset = file_offset;
1901 ph->p_vaddr = addr;
1902 ph->p_paddr = ph->p_vaddr;
1904 /* update dynamic relocation infos */
1905 if (s->sh_type == SHT_RELX) {
1906 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1907 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) {
1908 dyninf->rel_addr = addr;
1909 dyninf->rel_size += s->sh_size; /* XXX only first rel. */
1911 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) {
1912 dyninf->bss_addr = addr;
1913 dyninf->bss_size = s->sh_size; /* XXX only first rel. */
1915 #else
1916 if (dyninf->rel_size == 0)
1917 dyninf->rel_addr = addr;
1918 dyninf->rel_size += s->sh_size;
1919 #endif
1921 addr += s->sh_size;
1922 if (s->sh_type != SHT_NOBITS)
1923 file_offset += s->sh_size;
1926 ph->p_filesz = file_offset - ph->p_offset;
1927 ph->p_memsz = addr - ph->p_vaddr;
1928 ph++;
1929 if (j == 0) {
1930 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1931 /* if in the middle of a page, we duplicate the page in
1932 memory so that one copy is RX and the other is RW */
1933 if ((addr & (s1->section_align - 1)) != 0)
1934 addr += s1->section_align;
1935 } else {
1936 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1937 file_offset = (file_offset + s1->section_align - 1) &
1938 ~(s1->section_align - 1);
1944 /* all other sections come after */
1945 for(i = 1; i < s1->nb_sections; i++) {
1946 s = s1->sections[i];
1947 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
1948 continue;
1949 sec_order[sh_order_index++] = i;
1951 file_offset = (file_offset + s->sh_addralign - 1) &
1952 ~(s->sh_addralign - 1);
1953 s->sh_offset = file_offset;
1954 if (s->sh_type != SHT_NOBITS)
1955 file_offset += s->sh_size;
1958 return file_offset;
1961 static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp,
1962 Section *dynamic)
1964 ElfW(Phdr) *ph;
1966 /* if interpreter, then add corresponding program header */
1967 if (interp) {
1968 ph = &phdr[0];
1970 if (HAVE_PHDR)
1972 int len = phnum * sizeof(ElfW(Phdr));
1974 ph->p_type = PT_PHDR;
1975 ph->p_offset = sizeof(ElfW(Ehdr));
1976 ph->p_vaddr = interp->sh_addr - len;
1977 ph->p_paddr = ph->p_vaddr;
1978 ph->p_filesz = ph->p_memsz = len;
1979 ph->p_flags = PF_R | PF_X;
1980 ph->p_align = 4; /* interp->sh_addralign; */
1981 ph++;
1984 ph->p_type = PT_INTERP;
1985 ph->p_offset = interp->sh_offset;
1986 ph->p_vaddr = interp->sh_addr;
1987 ph->p_paddr = ph->p_vaddr;
1988 ph->p_filesz = interp->sh_size;
1989 ph->p_memsz = interp->sh_size;
1990 ph->p_flags = PF_R;
1991 ph->p_align = interp->sh_addralign;
1994 /* if dynamic section, then add corresponding program header */
1995 if (dynamic) {
1996 ph = &phdr[phnum - 1];
1998 ph->p_type = PT_DYNAMIC;
1999 ph->p_offset = dynamic->sh_offset;
2000 ph->p_vaddr = dynamic->sh_addr;
2001 ph->p_paddr = ph->p_vaddr;
2002 ph->p_filesz = dynamic->sh_size;
2003 ph->p_memsz = dynamic->sh_size;
2004 ph->p_flags = PF_R | PF_W;
2005 ph->p_align = dynamic->sh_addralign;
2009 /* Fill the dynamic section with tags describing the address and size of
2010 sections */
2011 static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
2013 Section *dynamic;
2015 dynamic = dyninf->dynamic;
2017 /* put dynamic section entries */
2018 dynamic->data_offset = dyninf->dyn_rel_off;
2019 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
2020 put_dt(dynamic, DT_STRTAB, dyninf->dynstr->sh_addr);
2021 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2022 put_dt(dynamic, DT_STRSZ, dyninf->dynstr->data_offset);
2023 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2024 #ifdef TCC_TARGET_X86_64
2025 put_dt(dynamic, DT_RELA, dyninf->rel_addr);
2026 put_dt(dynamic, DT_RELASZ, dyninf->rel_size);
2027 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2028 #else
2029 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2030 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2031 put_dt(dynamic, DT_PLTRELSZ, dyninf->rel_size);
2032 put_dt(dynamic, DT_JMPREL, dyninf->rel_addr);
2033 put_dt(dynamic, DT_PLTREL, DT_REL);
2034 put_dt(dynamic, DT_REL, dyninf->bss_addr);
2035 put_dt(dynamic, DT_RELSZ, dyninf->bss_size);
2036 #else
2037 put_dt(dynamic, DT_REL, dyninf->rel_addr);
2038 put_dt(dynamic, DT_RELSZ, dyninf->rel_size);
2039 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2040 #endif
2041 #endif
2042 if (s1->do_debug)
2043 put_dt(dynamic, DT_DEBUG, 0);
2044 put_dt(dynamic, DT_NULL, 0);
2047 /* Relocate remaining sections and symbols (that is those not related to
2048 dynamic linking) */
2049 static int final_sections_reloc(TCCState *s1)
2051 int i;
2052 Section *s;
2054 relocate_syms(s1, 0);
2056 if (s1->nb_errors != 0)
2057 return -1;
2059 /* relocate sections */
2060 /* XXX: ignore sections with allocated relocations ? */
2061 for(i = 1; i < s1->nb_sections; i++) {
2062 s = s1->sections[i];
2063 if (s->reloc && s != s1->got)
2064 relocate_section(s1, s);
2067 /* relocate relocation entries if the relocation tables are
2068 allocated in the executable */
2069 for(i = 1; i < s1->nb_sections; i++) {
2070 s = s1->sections[i];
2071 if ((s->sh_flags & SHF_ALLOC) &&
2072 s->sh_type == SHT_RELX) {
2073 relocate_rel(s1, s);
2076 return 0;
2079 /* Create an ELF file on disk.
2080 This function handle ELF specific layout requirements */
2081 static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
2082 int file_offset, int *sec_order)
2084 int i, shnum, offset, size, file_type;
2085 Section *s;
2086 ElfW(Ehdr) ehdr;
2087 ElfW(Shdr) shdr, *sh;
2089 file_type = s1->output_type;
2090 shnum = s1->nb_sections;
2092 memset(&ehdr, 0, sizeof(ehdr));
2094 if (phnum > 0) {
2095 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2096 ehdr.e_phnum = phnum;
2097 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2100 /* align to 4 */
2101 file_offset = (file_offset + 3) & -4;
2103 /* fill header */
2104 ehdr.e_ident[0] = ELFMAG0;
2105 ehdr.e_ident[1] = ELFMAG1;
2106 ehdr.e_ident[2] = ELFMAG2;
2107 ehdr.e_ident[3] = ELFMAG3;
2108 ehdr.e_ident[4] = ELFCLASSW;
2109 ehdr.e_ident[5] = ELFDATA2LSB;
2110 ehdr.e_ident[6] = EV_CURRENT;
2111 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2112 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2113 #endif
2114 #ifdef TCC_TARGET_ARM
2115 #ifdef TCC_ARM_EABI
2116 ehdr.e_ident[EI_OSABI] = 0;
2117 ehdr.e_flags = EF_ARM_EABI_VER4;
2118 if (file_type == TCC_OUTPUT_EXE || file_type == TCC_OUTPUT_DLL)
2119 ehdr.e_flags |= EF_ARM_HASENTRY;
2120 if (s1->float_abi == ARM_HARD_FLOAT)
2121 ehdr.e_flags |= EF_ARM_VFP_FLOAT;
2122 else
2123 ehdr.e_flags |= EF_ARM_SOFT_FLOAT;
2124 #else
2125 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2126 #endif
2127 #endif
2128 switch(file_type) {
2129 default:
2130 case TCC_OUTPUT_EXE:
2131 ehdr.e_type = ET_EXEC;
2132 ehdr.e_entry = get_elf_sym_addr(s1, "_start", 1);
2133 break;
2134 case TCC_OUTPUT_DLL:
2135 ehdr.e_type = ET_DYN;
2136 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2137 break;
2138 case TCC_OUTPUT_OBJ:
2139 ehdr.e_type = ET_REL;
2140 break;
2142 ehdr.e_machine = EM_TCC_TARGET;
2143 ehdr.e_version = EV_CURRENT;
2144 ehdr.e_shoff = file_offset;
2145 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2146 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2147 ehdr.e_shnum = shnum;
2148 ehdr.e_shstrndx = shnum - 1;
2150 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2151 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2152 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2154 sort_syms(s1, symtab_section);
2155 for(i = 1; i < s1->nb_sections; i++) {
2156 s = s1->sections[sec_order[i]];
2157 if (s->sh_type != SHT_NOBITS) {
2158 if (s->sh_type == SHT_DYNSYM)
2159 patch_dynsym_undef(s1, s);
2160 while (offset < s->sh_offset) {
2161 fputc(0, f);
2162 offset++;
2164 size = s->sh_size;
2165 fwrite(s->data, 1, size, f);
2166 offset += size;
2170 /* output section headers */
2171 while (offset < ehdr.e_shoff) {
2172 fputc(0, f);
2173 offset++;
2176 for(i = 0; i < s1->nb_sections; i++) {
2177 sh = &shdr;
2178 memset(sh, 0, sizeof(ElfW(Shdr)));
2179 s = s1->sections[i];
2180 if (s) {
2181 sh->sh_name = s->sh_name;
2182 sh->sh_type = s->sh_type;
2183 sh->sh_flags = s->sh_flags;
2184 sh->sh_entsize = s->sh_entsize;
2185 sh->sh_info = s->sh_info;
2186 if (s->link)
2187 sh->sh_link = s->link->sh_num;
2188 sh->sh_addralign = s->sh_addralign;
2189 sh->sh_addr = s->sh_addr;
2190 sh->sh_offset = s->sh_offset;
2191 sh->sh_size = s->sh_size;
2193 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2197 /* Write an elf, coff or "binary" file */
2198 static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum,
2199 ElfW(Phdr) *phdr, int file_offset, int *sec_order)
2201 int fd, mode, file_type;
2202 FILE *f;
2204 file_type = s1->output_type;
2205 if (file_type == TCC_OUTPUT_OBJ)
2206 mode = 0666;
2207 else
2208 mode = 0777;
2209 unlink(filename);
2210 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2211 if (fd < 0) {
2212 tcc_error_noabort("could not write '%s'", filename);
2213 return -1;
2215 f = fdopen(fd, "wb");
2216 if (s1->verbose)
2217 printf("<- %s\n", filename);
2219 #ifdef TCC_TARGET_COFF
2220 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF)
2221 tcc_output_coff(s1, f);
2222 else
2223 #endif
2224 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
2225 tcc_output_elf(s1, f, phnum, phdr, file_offset, sec_order);
2226 else
2227 tcc_output_binary(s1, f, sec_order);
2228 fclose(f);
2230 return 0;
2233 /* Output an elf, coff or binary file */
2234 /* XXX: suppress unneeded sections */
2235 static int elf_output_file(TCCState *s1, const char *filename)
2237 int i, ret, phnum, shnum, file_type, file_offset, *sec_order;
2238 struct dyn_inf dyninf;
2239 ElfW(Phdr) *phdr;
2240 ElfW(Sym) *sym;
2241 Section *strsec, *interp, *dynamic, *dynstr;
2243 file_type = s1->output_type;
2244 s1->nb_errors = 0;
2246 /* if linking, also link in runtime libraries (libc, libgcc, etc.) */
2247 if (file_type != TCC_OUTPUT_OBJ) {
2248 tcc_add_runtime(s1);
2251 phdr = NULL;
2252 sec_order = NULL;
2253 interp = dynamic = dynstr = NULL; /* avoid warning */
2254 dyninf.dyn_rel_off = 0; /* avoid warning */
2256 if (file_type != TCC_OUTPUT_OBJ) {
2257 relocate_common_syms();
2259 tcc_add_linker_symbols(s1);
2261 if (!s1->static_link) {
2262 if (file_type == TCC_OUTPUT_EXE) {
2263 char *ptr;
2264 /* allow override the dynamic loader */
2265 const char *elfint = getenv("LD_SO");
2266 if (elfint == NULL)
2267 elfint = DEFAULT_ELFINTERP(s1);
2268 /* add interpreter section only if executable */
2269 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
2270 interp->sh_addralign = 1;
2271 ptr = section_ptr_add(interp, 1 + strlen(elfint));
2272 strcpy(ptr, elfint);
2275 /* add dynamic symbol table */
2276 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
2277 ".dynstr",
2278 ".hash", SHF_ALLOC);
2279 dynstr = s1->dynsym->link;
2281 /* add dynamic section */
2282 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
2283 SHF_ALLOC | SHF_WRITE);
2284 dynamic->link = dynstr;
2285 dynamic->sh_entsize = sizeof(ElfW(Dyn));
2287 /* add PLT */
2288 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
2289 SHF_ALLOC | SHF_EXECINSTR);
2290 s1->plt->sh_entsize = 4;
2292 build_got(s1);
2294 if (file_type == TCC_OUTPUT_EXE) {
2295 bind_exe_dynsyms(s1);
2297 if (s1->nb_errors) {
2298 ret = -1;
2299 goto the_end;
2302 bind_libs_dynsyms(s1);
2303 } else /* shared library case: simply export all global symbols */
2304 export_global_syms(s1);
2306 build_got_entries(s1);
2308 /* add a list of needed dlls */
2309 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2310 DLLReference *dllref = s1->loaded_dlls[i];
2311 if (dllref->level == 0)
2312 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
2315 if (s1->rpath)
2316 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
2318 /* XXX: currently, since we do not handle PIC code, we
2319 must relocate the readonly segments */
2320 if (file_type == TCC_OUTPUT_DLL) {
2321 if (s1->soname)
2322 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
2323 put_dt(dynamic, DT_TEXTREL, 0);
2326 if (s1->symbolic)
2327 put_dt(dynamic, DT_SYMBOLIC, 0);
2329 /* add necessary space for other entries */
2330 dyninf.dyn_rel_off = dynamic->data_offset;
2331 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
2332 } else {
2333 /* still need to build got entries in case of static link */
2334 build_got_entries(s1);
2338 /* we add a section for symbols */
2339 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
2340 put_elf_str(strsec, "");
2342 /* compute number of sections */
2343 shnum = s1->nb_sections;
2345 /* this array is used to reorder sections in the output file */
2346 sec_order = tcc_malloc(sizeof(int) * shnum);
2347 sec_order[0] = 0;
2349 /* compute number of program headers */
2350 switch(file_type) {
2351 default:
2352 case TCC_OUTPUT_OBJ:
2353 phnum = 0;
2354 break;
2355 case TCC_OUTPUT_EXE:
2356 if (!s1->static_link)
2357 phnum = 4 + HAVE_PHDR;
2358 else
2359 phnum = 2;
2360 break;
2361 case TCC_OUTPUT_DLL:
2362 phnum = 3;
2363 break;
2366 /* Allocate strings for section names */
2367 alloc_sec_names(s1, file_type, strsec);
2369 /* allocate program segment headers */
2370 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
2372 /* compute section to program header mapping */
2373 file_offset = layout_sections(s1, phdr, phnum, interp, &dyninf, sec_order);
2375 /* Fill remaining program header and finalize relocation related to dynamic
2376 linking. */
2377 if (phnum > 0) {
2378 fill_unloadable_phdr(phdr, phnum, interp, dynamic);
2379 if (dynamic) {
2380 dyninf.dynamic = dynamic;
2381 dyninf.dynstr = dynstr;
2383 fill_dynamic(s1, &dyninf);
2385 /* put in GOT the dynamic section address and relocate PLT */
2386 put32(s1->got->data, dynamic->sh_addr);
2387 if (file_type == TCC_OUTPUT_EXE
2388 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2389 || file_type == TCC_OUTPUT_DLL
2390 #endif
2392 relocate_plt(s1);
2394 /* relocate symbols in .dynsym now that final addresses are known */
2395 for_each_elem(s1->dynsym, 1, sym, ElfW(Sym)) {
2396 /* relocate to PLT if symbol corresponds to a PLT entry */
2397 if (sym->st_shndx == SHN_UNDEF) {
2398 if (sym->st_value)
2399 sym->st_value += s1->plt->sh_addr;
2400 } else if (sym->st_shndx < SHN_LORESERVE) {
2401 /* do symbol relocation */
2402 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
2408 /* if building executable or DLL, then relocate each section
2409 except the GOT which is already relocated */
2410 if (file_type != TCC_OUTPUT_OBJ) {
2411 ret = final_sections_reloc(s1);
2412 if (ret)
2413 goto the_end;
2416 /* Perform relocation to GOT or PLT entries */
2417 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2418 fill_got(s1);
2420 /* Create the ELF file with name 'filename' */
2421 ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order);
2422 the_end:
2423 tcc_free(s1->symtab_to_dynsym);
2424 tcc_free(sec_order);
2425 tcc_free(phdr);
2426 tcc_free(s1->sym_attrs);
2427 return ret;
2430 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2432 int ret;
2433 #ifdef TCC_TARGET_PE
2434 if (s->output_type != TCC_OUTPUT_OBJ) {
2435 ret = pe_output_file(s, filename);
2436 } else
2437 #endif
2438 ret = elf_output_file(s, filename);
2439 return ret;
2442 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2444 void *data;
2446 data = tcc_malloc(size);
2447 lseek(fd, file_offset, SEEK_SET);
2448 read(fd, data, size);
2449 return data;
2452 typedef struct SectionMergeInfo {
2453 Section *s; /* corresponding existing section */
2454 unsigned long offset; /* offset of the new section in the existing section */
2455 uint8_t new_section; /* true if section 's' was added */
2456 uint8_t link_once; /* true if link once section */
2457 } SectionMergeInfo;
2459 /* load an object file and merge it with current files */
2460 /* XXX: handle correctly stab (debug) info */
2461 ST_FUNC int tcc_load_object_file(TCCState *s1,
2462 int fd, unsigned long file_offset)
2464 ElfW(Ehdr) ehdr;
2465 ElfW(Shdr) *shdr, *sh;
2466 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2467 unsigned char *strsec, *strtab;
2468 int *old_to_new_syms;
2469 char *sh_name, *name;
2470 SectionMergeInfo *sm_table, *sm;
2471 ElfW(Sym) *sym, *symtab;
2472 ElfW_Rel *rel;
2473 Section *s;
2475 int stab_index;
2476 int stabstr_index;
2478 stab_index = stabstr_index = 0;
2480 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2481 goto fail1;
2482 if (ehdr.e_ident[0] != ELFMAG0 ||
2483 ehdr.e_ident[1] != ELFMAG1 ||
2484 ehdr.e_ident[2] != ELFMAG2 ||
2485 ehdr.e_ident[3] != ELFMAG3)
2486 goto fail1;
2487 /* test if object file */
2488 if (ehdr.e_type != ET_REL)
2489 goto fail1;
2490 /* test CPU specific stuff */
2491 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2492 ehdr.e_machine != EM_TCC_TARGET) {
2493 fail1:
2494 tcc_error_noabort("invalid object file");
2495 return -1;
2497 /* read sections */
2498 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2499 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2500 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2502 /* load section names */
2503 sh = &shdr[ehdr.e_shstrndx];
2504 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2506 /* load symtab and strtab */
2507 old_to_new_syms = NULL;
2508 symtab = NULL;
2509 strtab = NULL;
2510 nb_syms = 0;
2511 for(i = 1; i < ehdr.e_shnum; i++) {
2512 sh = &shdr[i];
2513 if (sh->sh_type == SHT_SYMTAB) {
2514 if (symtab) {
2515 tcc_error_noabort("object must contain only one symtab");
2516 fail:
2517 ret = -1;
2518 goto the_end;
2520 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2521 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2522 sm_table[i].s = symtab_section;
2524 /* now load strtab */
2525 sh = &shdr[sh->sh_link];
2526 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2530 /* now examine each section and try to merge its content with the
2531 ones in memory */
2532 for(i = 1; i < ehdr.e_shnum; i++) {
2533 /* no need to examine section name strtab */
2534 if (i == ehdr.e_shstrndx)
2535 continue;
2536 sh = &shdr[i];
2537 sh_name = (char *) strsec + sh->sh_name;
2538 /* ignore sections types we do not handle */
2539 if (sh->sh_type != SHT_PROGBITS &&
2540 sh->sh_type != SHT_RELX &&
2541 #ifdef TCC_ARM_EABI
2542 sh->sh_type != SHT_ARM_EXIDX &&
2543 #endif
2544 sh->sh_type != SHT_NOBITS &&
2545 sh->sh_type != SHT_PREINIT_ARRAY &&
2546 sh->sh_type != SHT_INIT_ARRAY &&
2547 sh->sh_type != SHT_FINI_ARRAY &&
2548 strcmp(sh_name, ".stabstr")
2550 continue;
2551 if (sh->sh_addralign < 1)
2552 sh->sh_addralign = 1;
2553 /* find corresponding section, if any */
2554 for(j = 1; j < s1->nb_sections;j++) {
2555 s = s1->sections[j];
2556 if (!strcmp(s->name, sh_name)) {
2557 if (!strncmp(sh_name, ".gnu.linkonce",
2558 sizeof(".gnu.linkonce") - 1)) {
2559 /* if a 'linkonce' section is already present, we
2560 do not add it again. It is a little tricky as
2561 symbols can still be defined in
2562 it. */
2563 sm_table[i].link_once = 1;
2564 goto next;
2565 } else {
2566 goto found;
2570 /* not found: create new section */
2571 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2572 /* take as much info as possible from the section. sh_link and
2573 sh_info will be updated later */
2574 s->sh_addralign = sh->sh_addralign;
2575 s->sh_entsize = sh->sh_entsize;
2576 sm_table[i].new_section = 1;
2577 found:
2578 if (sh->sh_type != s->sh_type) {
2579 tcc_error_noabort("invalid section type");
2580 goto fail;
2583 /* align start of section */
2584 offset = s->data_offset;
2586 if (0 == strcmp(sh_name, ".stab")) {
2587 stab_index = i;
2588 goto no_align;
2590 if (0 == strcmp(sh_name, ".stabstr")) {
2591 stabstr_index = i;
2592 goto no_align;
2595 size = sh->sh_addralign - 1;
2596 offset = (offset + size) & ~size;
2597 if (sh->sh_addralign > s->sh_addralign)
2598 s->sh_addralign = sh->sh_addralign;
2599 s->data_offset = offset;
2600 no_align:
2601 sm_table[i].offset = offset;
2602 sm_table[i].s = s;
2603 /* concatenate sections */
2604 size = sh->sh_size;
2605 if (sh->sh_type != SHT_NOBITS) {
2606 unsigned char *ptr;
2607 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2608 ptr = section_ptr_add(s, size);
2609 read(fd, ptr, size);
2610 } else {
2611 s->data_offset += size;
2613 next: ;
2616 /* gr relocate stab strings */
2617 if (stab_index && stabstr_index) {
2618 Stab_Sym *a, *b;
2619 unsigned o;
2620 s = sm_table[stab_index].s;
2621 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2622 b = (Stab_Sym *)(s->data + s->data_offset);
2623 o = sm_table[stabstr_index].offset;
2624 while (a < b)
2625 a->n_strx += o, a++;
2628 /* second short pass to update sh_link and sh_info fields of new
2629 sections */
2630 for(i = 1; i < ehdr.e_shnum; i++) {
2631 s = sm_table[i].s;
2632 if (!s || !sm_table[i].new_section)
2633 continue;
2634 sh = &shdr[i];
2635 if (sh->sh_link > 0)
2636 s->link = sm_table[sh->sh_link].s;
2637 if (sh->sh_type == SHT_RELX) {
2638 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2639 /* update backward link */
2640 s1->sections[s->sh_info]->reloc = s;
2643 sm = sm_table;
2645 /* resolve symbols */
2646 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2648 sym = symtab + 1;
2649 for(i = 1; i < nb_syms; i++, sym++) {
2650 if (sym->st_shndx != SHN_UNDEF &&
2651 sym->st_shndx < SHN_LORESERVE) {
2652 sm = &sm_table[sym->st_shndx];
2653 if (sm->link_once) {
2654 /* if a symbol is in a link once section, we use the
2655 already defined symbol. It is very important to get
2656 correct relocations */
2657 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2658 name = (char *) strtab + sym->st_name;
2659 sym_index = find_elf_sym(symtab_section, name);
2660 if (sym_index)
2661 old_to_new_syms[i] = sym_index;
2663 continue;
2665 /* if no corresponding section added, no need to add symbol */
2666 if (!sm->s)
2667 continue;
2668 /* convert section number */
2669 sym->st_shndx = sm->s->sh_num;
2670 /* offset value */
2671 sym->st_value += sm->offset;
2673 /* add symbol */
2674 name = (char *) strtab + sym->st_name;
2675 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2676 sym->st_info, sym->st_other,
2677 sym->st_shndx, name);
2678 old_to_new_syms[i] = sym_index;
2681 /* third pass to patch relocation entries */
2682 for(i = 1; i < ehdr.e_shnum; i++) {
2683 s = sm_table[i].s;
2684 if (!s)
2685 continue;
2686 sh = &shdr[i];
2687 offset = sm_table[i].offset;
2688 switch(s->sh_type) {
2689 case SHT_RELX:
2690 /* take relocation offset information */
2691 offseti = sm_table[sh->sh_info].offset;
2692 for_each_elem(s, (offset / sizeof(*rel)), rel, ElfW_Rel) {
2693 int type;
2694 unsigned sym_index;
2695 /* convert symbol index */
2696 type = ELFW(R_TYPE)(rel->r_info);
2697 sym_index = ELFW(R_SYM)(rel->r_info);
2698 /* NOTE: only one symtab assumed */
2699 if (sym_index >= nb_syms)
2700 goto invalid_reloc;
2701 sym_index = old_to_new_syms[sym_index];
2702 /* ignore link_once in rel section. */
2703 if (!sym_index && !sm->link_once
2704 #ifdef TCC_TARGET_ARM
2705 && type != R_ARM_V4BX
2706 #endif
2708 invalid_reloc:
2709 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2710 i, strsec + sh->sh_name, rel->r_offset);
2711 goto fail;
2713 rel->r_info = ELFW(R_INFO)(sym_index, type);
2714 /* offset the relocation offset */
2715 rel->r_offset += offseti;
2716 #ifdef TCC_TARGET_ARM
2717 /* Jumps and branches from a Thumb code to a PLT entry need
2718 special handling since PLT entries are ARM code.
2719 Unconditional bl instructions referencing PLT entries are
2720 handled by converting these instructions into blx
2721 instructions. Other case of instructions referencing a PLT
2722 entry require to add a Thumb stub before the PLT entry to
2723 switch to ARM mode. We set bit plt_thumb_stub of the
2724 attribute of a symbol to indicate such a case. */
2725 if (type == R_ARM_THM_JUMP24)
2726 alloc_sym_attr(s1, sym_index)->plt_thumb_stub = 1;
2727 #endif
2729 break;
2730 default:
2731 break;
2735 ret = 0;
2736 the_end:
2737 tcc_free(symtab);
2738 tcc_free(strtab);
2739 tcc_free(old_to_new_syms);
2740 tcc_free(sm_table);
2741 tcc_free(strsec);
2742 tcc_free(shdr);
2743 return ret;
2746 typedef struct ArchiveHeader {
2747 char ar_name[16]; /* name of this member */
2748 char ar_date[12]; /* file mtime */
2749 char ar_uid[6]; /* owner uid; printed as decimal */
2750 char ar_gid[6]; /* owner gid; printed as decimal */
2751 char ar_mode[8]; /* file mode, printed as octal */
2752 char ar_size[10]; /* file size, printed as decimal */
2753 char ar_fmag[2]; /* should contain ARFMAG */
2754 } ArchiveHeader;
2756 static int get_be32(const uint8_t *b)
2758 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2761 /* load only the objects which resolve undefined symbols */
2762 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2764 int i, bound, nsyms, sym_index, off, ret;
2765 uint8_t *data;
2766 const char *ar_names, *p;
2767 const uint8_t *ar_index;
2768 ElfW(Sym) *sym;
2770 data = tcc_malloc(size);
2771 if (read(fd, data, size) != size)
2772 goto fail;
2773 nsyms = get_be32(data);
2774 ar_index = data + 4;
2775 ar_names = (char *) ar_index + nsyms * 4;
2777 do {
2778 bound = 0;
2779 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2780 sym_index = find_elf_sym(symtab_section, p);
2781 if(sym_index) {
2782 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2783 if(sym->st_shndx == SHN_UNDEF) {
2784 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2785 ++bound;
2786 lseek(fd, off, SEEK_SET);
2787 if(tcc_load_object_file(s1, fd, off) < 0) {
2788 fail:
2789 ret = -1;
2790 goto the_end;
2795 } while(bound);
2796 ret = 0;
2797 the_end:
2798 tcc_free(data);
2799 return ret;
2802 /* load a '.a' file */
2803 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2805 ArchiveHeader hdr;
2806 char ar_size[11];
2807 char ar_name[17];
2808 char magic[8];
2809 int size, len, i;
2810 unsigned long file_offset;
2812 /* skip magic which was already checked */
2813 read(fd, magic, sizeof(magic));
2815 for(;;) {
2816 len = read(fd, &hdr, sizeof(hdr));
2817 if (len == 0)
2818 break;
2819 if (len != sizeof(hdr)) {
2820 tcc_error_noabort("invalid archive");
2821 return -1;
2823 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2824 ar_size[sizeof(hdr.ar_size)] = '\0';
2825 size = strtol(ar_size, NULL, 0);
2826 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2827 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2828 if (ar_name[i] != ' ')
2829 break;
2831 ar_name[i + 1] = '\0';
2832 file_offset = lseek(fd, 0, SEEK_CUR);
2833 /* align to even */
2834 size = (size + 1) & ~1;
2835 if (!strcmp(ar_name, "/")) {
2836 /* coff symbol table : we handle it */
2837 if(s1->alacarte_link)
2838 return tcc_load_alacarte(s1, fd, size);
2839 } else if (!strcmp(ar_name, "//") ||
2840 !strcmp(ar_name, "__.SYMDEF") ||
2841 !strcmp(ar_name, "__.SYMDEF/") ||
2842 !strcmp(ar_name, "ARFILENAMES/")) {
2843 /* skip symbol table or archive names */
2844 } else {
2845 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2846 return -1;
2848 lseek(fd, file_offset + size, SEEK_SET);
2850 return 0;
2853 #ifndef TCC_TARGET_PE
2854 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2855 is referenced by the user (so it should be added as DT_NEEDED in
2856 the generated ELF file) */
2857 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2859 ElfW(Ehdr) ehdr;
2860 ElfW(Shdr) *shdr, *sh, *sh1;
2861 int i, j, nb_syms, nb_dts, sym_bind, ret;
2862 ElfW(Sym) *sym, *dynsym;
2863 ElfW(Dyn) *dt, *dynamic;
2864 unsigned char *dynstr;
2865 const char *name, *soname;
2866 DLLReference *dllref;
2868 read(fd, &ehdr, sizeof(ehdr));
2870 /* test CPU specific stuff */
2871 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2872 ehdr.e_machine != EM_TCC_TARGET) {
2873 tcc_error_noabort("bad architecture");
2874 return -1;
2877 /* read sections */
2878 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2880 /* load dynamic section and dynamic symbols */
2881 nb_syms = 0;
2882 nb_dts = 0;
2883 dynamic = NULL;
2884 dynsym = NULL; /* avoid warning */
2885 dynstr = NULL; /* avoid warning */
2886 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2887 switch(sh->sh_type) {
2888 case SHT_DYNAMIC:
2889 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2890 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2891 break;
2892 case SHT_DYNSYM:
2893 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2894 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2895 sh1 = &shdr[sh->sh_link];
2896 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2897 break;
2898 default:
2899 break;
2903 /* compute the real library name */
2904 soname = tcc_basename(filename);
2906 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2907 if (dt->d_tag == DT_SONAME) {
2908 soname = (char *) dynstr + dt->d_un.d_val;
2912 /* if the dll is already loaded, do not load it */
2913 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2914 dllref = s1->loaded_dlls[i];
2915 if (!strcmp(soname, dllref->name)) {
2916 /* but update level if needed */
2917 if (level < dllref->level)
2918 dllref->level = level;
2919 ret = 0;
2920 goto the_end;
2924 /* add the dll and its level */
2925 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2926 dllref->level = level;
2927 strcpy(dllref->name, soname);
2928 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2930 /* add dynamic symbols in dynsym_section */
2931 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2932 sym_bind = ELFW(ST_BIND)(sym->st_info);
2933 if (sym_bind == STB_LOCAL)
2934 continue;
2935 name = (char *) dynstr + sym->st_name;
2936 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2937 sym->st_info, sym->st_other, sym->st_shndx, name);
2940 /* load all referenced DLLs */
2941 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2942 switch(dt->d_tag) {
2943 case DT_NEEDED:
2944 name = (char *) dynstr + dt->d_un.d_val;
2945 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2946 dllref = s1->loaded_dlls[j];
2947 if (!strcmp(name, dllref->name))
2948 goto already_loaded;
2950 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2951 tcc_error_noabort("referenced dll '%s' not found", name);
2952 ret = -1;
2953 goto the_end;
2955 already_loaded:
2956 break;
2959 ret = 0;
2960 the_end:
2961 tcc_free(dynstr);
2962 tcc_free(dynsym);
2963 tcc_free(dynamic);
2964 tcc_free(shdr);
2965 return ret;
2968 #define LD_TOK_NAME 256
2969 #define LD_TOK_EOF (-1)
2971 /* return next ld script token */
2972 static int ld_next(TCCState *s1, char *name, int name_size)
2974 int c;
2975 char *q;
2977 redo:
2978 switch(ch) {
2979 case ' ':
2980 case '\t':
2981 case '\f':
2982 case '\v':
2983 case '\r':
2984 case '\n':
2985 inp();
2986 goto redo;
2987 case '/':
2988 minp();
2989 if (ch == '*') {
2990 file->buf_ptr = parse_comment(file->buf_ptr);
2991 ch = file->buf_ptr[0];
2992 goto redo;
2993 } else {
2994 q = name;
2995 *q++ = '/';
2996 goto parse_name;
2998 break;
2999 /* case 'a' ... 'z': */
3000 case 'a':
3001 case 'b':
3002 case 'c':
3003 case 'd':
3004 case 'e':
3005 case 'f':
3006 case 'g':
3007 case 'h':
3008 case 'i':
3009 case 'j':
3010 case 'k':
3011 case 'l':
3012 case 'm':
3013 case 'n':
3014 case 'o':
3015 case 'p':
3016 case 'q':
3017 case 'r':
3018 case 's':
3019 case 't':
3020 case 'u':
3021 case 'v':
3022 case 'w':
3023 case 'x':
3024 case 'y':
3025 case 'z':
3026 /* case 'A' ... 'z': */
3027 case 'A':
3028 case 'B':
3029 case 'C':
3030 case 'D':
3031 case 'E':
3032 case 'F':
3033 case 'G':
3034 case 'H':
3035 case 'I':
3036 case 'J':
3037 case 'K':
3038 case 'L':
3039 case 'M':
3040 case 'N':
3041 case 'O':
3042 case 'P':
3043 case 'Q':
3044 case 'R':
3045 case 'S':
3046 case 'T':
3047 case 'U':
3048 case 'V':
3049 case 'W':
3050 case 'X':
3051 case 'Y':
3052 case 'Z':
3053 case '_':
3054 case '\\':
3055 case '.':
3056 case '$':
3057 case '~':
3058 q = name;
3059 parse_name:
3060 for(;;) {
3061 if (!((ch >= 'a' && ch <= 'z') ||
3062 (ch >= 'A' && ch <= 'Z') ||
3063 (ch >= '0' && ch <= '9') ||
3064 strchr("/.-_+=$:\\,~", ch)))
3065 break;
3066 if ((q - name) < name_size - 1) {
3067 *q++ = ch;
3069 minp();
3071 *q = '\0';
3072 c = LD_TOK_NAME;
3073 break;
3074 case CH_EOF:
3075 c = LD_TOK_EOF;
3076 break;
3077 default:
3078 c = ch;
3079 inp();
3080 break;
3082 return c;
3085 static int ld_add_file(TCCState *s1, const char filename[])
3087 int ret;
3089 ret = tcc_add_file_internal(s1, filename, 0);
3090 if (ret)
3091 ret = tcc_add_dll(s1, filename, 0);
3092 return ret;
3095 static inline int new_undef_syms(void)
3097 int ret = 0;
3098 ret = new_undef_sym;
3099 new_undef_sym = 0;
3100 return ret;
3103 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
3105 char filename[1024], libname[1024];
3106 int t, group, nblibs = 0, ret = 0;
3107 char **libs = NULL;
3109 group = !strcmp(cmd, "GROUP");
3110 if (!as_needed)
3111 new_undef_syms();
3112 t = ld_next(s1, filename, sizeof(filename));
3113 if (t != '(')
3114 expect("(");
3115 t = ld_next(s1, filename, sizeof(filename));
3116 for(;;) {
3117 libname[0] = '\0';
3118 if (t == LD_TOK_EOF) {
3119 tcc_error_noabort("unexpected end of file");
3120 ret = -1;
3121 goto lib_parse_error;
3122 } else if (t == ')') {
3123 break;
3124 } else if (t == '-') {
3125 t = ld_next(s1, filename, sizeof(filename));
3126 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
3127 tcc_error_noabort("library name expected");
3128 ret = -1;
3129 goto lib_parse_error;
3131 pstrcpy(libname, sizeof libname, &filename[1]);
3132 if (s1->static_link) {
3133 snprintf(filename, sizeof filename, "lib%s.a", libname);
3134 } else {
3135 snprintf(filename, sizeof filename, "lib%s.so", libname);
3137 } else if (t != LD_TOK_NAME) {
3138 tcc_error_noabort("filename expected");
3139 ret = -1;
3140 goto lib_parse_error;
3142 if (!strcmp(filename, "AS_NEEDED")) {
3143 ret = ld_add_file_list(s1, cmd, 1);
3144 if (ret)
3145 goto lib_parse_error;
3146 } else {
3147 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3148 if (!as_needed) {
3149 ret = ld_add_file(s1, filename);
3150 if (ret)
3151 goto lib_parse_error;
3152 if (group) {
3153 /* Add the filename *and* the libname to avoid future conversions */
3154 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
3155 if (libname[0] != '\0')
3156 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
3160 t = ld_next(s1, filename, sizeof(filename));
3161 if (t == ',') {
3162 t = ld_next(s1, filename, sizeof(filename));
3165 if (group && !as_needed) {
3166 while (new_undef_syms()) {
3167 int i;
3169 for (i = 0; i < nblibs; i ++)
3170 ld_add_file(s1, libs[i]);
3173 lib_parse_error:
3174 dynarray_reset(&libs, &nblibs);
3175 return ret;
3178 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3179 files */
3180 ST_FUNC int tcc_load_ldscript(TCCState *s1)
3182 char cmd[64];
3183 char filename[1024];
3184 int t, ret;
3186 ch = file->buf_ptr[0];
3187 ch = handle_eob();
3188 for(;;) {
3189 t = ld_next(s1, cmd, sizeof(cmd));
3190 if (t == LD_TOK_EOF)
3191 return 0;
3192 else if (t != LD_TOK_NAME)
3193 return -1;
3194 if (!strcmp(cmd, "INPUT") ||
3195 !strcmp(cmd, "GROUP")) {
3196 ret = ld_add_file_list(s1, cmd, 0);
3197 if (ret)
3198 return ret;
3199 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3200 !strcmp(cmd, "TARGET")) {
3201 /* ignore some commands */
3202 t = ld_next(s1, cmd, sizeof(cmd));
3203 if (t != '(')
3204 expect("(");
3205 for(;;) {
3206 t = ld_next(s1, filename, sizeof(filename));
3207 if (t == LD_TOK_EOF) {
3208 tcc_error_noabort("unexpected end of file");
3209 return -1;
3210 } else if (t == ')') {
3211 break;
3214 } else {
3215 return -1;
3218 return 0;
3220 #endif /* !TCC_TARGET_PE */