Only use blx if available
[tinycc.git] / tccelf.c
blobf46a74235d2cdaefbd5d5816cabcb3740529c15c
1 /*
2 * ELF file handling for TCC
3 *
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "tcc.h"
23 static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */
25 ST_FUNC int put_elf_str(Section *s, const char *sym)
27 int offset, len;
28 char *ptr;
30 len = strlen(sym) + 1;
31 offset = s->data_offset;
32 ptr = section_ptr_add(s, len);
33 memcpy(ptr, sym, len);
34 return offset;
37 /* elf symbol hashing function */
38 static unsigned long elf_hash(const unsigned char *name)
40 unsigned long h = 0, g;
42 while (*name) {
43 h = (h << 4) + *name++;
44 g = h & 0xf0000000;
45 if (g)
46 h ^= g >> 24;
47 h &= ~g;
49 return h;
52 /* rebuild hash table of section s */
53 /* NOTE: we do factorize the hash table code to go faster */
54 static void rebuild_hash(Section *s, unsigned int nb_buckets)
56 ElfW(Sym) *sym;
57 int *ptr, *hash, nb_syms, sym_index, h;
58 char *strtab;
60 strtab = s->link->data;
61 nb_syms = s->data_offset / sizeof(ElfW(Sym));
63 s->hash->data_offset = 0;
64 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
65 ptr[0] = nb_buckets;
66 ptr[1] = nb_syms;
67 ptr += 2;
68 hash = ptr;
69 memset(hash, 0, (nb_buckets + 1) * sizeof(int));
70 ptr += nb_buckets + 1;
72 sym = (ElfW(Sym) *)s->data + 1;
73 for(sym_index = 1; sym_index < nb_syms; sym_index++) {
74 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
75 h = elf_hash(strtab + sym->st_name) % nb_buckets;
76 *ptr = hash[h];
77 hash[h] = sym_index;
78 } else {
79 *ptr = 0;
81 ptr++;
82 sym++;
86 /* return the symbol number */
87 ST_FUNC int put_elf_sym(Section *s, uplong value, unsigned long size,
88 int info, int other, int shndx, const char *name)
90 int name_offset, sym_index;
91 int nbuckets, h;
92 ElfW(Sym) *sym;
93 Section *hs;
95 sym = section_ptr_add(s, sizeof(ElfW(Sym)));
96 if (name)
97 name_offset = put_elf_str(s->link, name);
98 else
99 name_offset = 0;
100 /* XXX: endianness */
101 sym->st_name = name_offset;
102 sym->st_value = value;
103 sym->st_size = size;
104 sym->st_info = info;
105 sym->st_other = other;
106 sym->st_shndx = shndx;
107 sym_index = sym - (ElfW(Sym) *)s->data;
108 hs = s->hash;
109 if (hs) {
110 int *ptr, *base;
111 ptr = section_ptr_add(hs, sizeof(int));
112 base = (int *)hs->data;
113 /* only add global or weak symbols */
114 if (ELFW(ST_BIND)(info) != STB_LOCAL) {
115 /* add another hashing entry */
116 nbuckets = base[0];
117 h = elf_hash(name) % nbuckets;
118 *ptr = base[2 + h];
119 base[2 + h] = sym_index;
120 base[1]++;
121 /* we resize the hash table */
122 hs->nb_hashed_syms++;
123 if (hs->nb_hashed_syms > 2 * nbuckets) {
124 rebuild_hash(s, 2 * nbuckets);
126 } else {
127 *ptr = 0;
128 base[1]++;
131 return sym_index;
134 /* find global ELF symbol 'name' and return its index. Return 0 if not
135 found. */
136 ST_FUNC int find_elf_sym(Section *s, const char *name)
138 ElfW(Sym) *sym;
139 Section *hs;
140 int nbuckets, sym_index, h;
141 const char *name1;
143 hs = s->hash;
144 if (!hs)
145 return 0;
146 nbuckets = ((int *)hs->data)[0];
147 h = elf_hash(name) % nbuckets;
148 sym_index = ((int *)hs->data)[2 + h];
149 while (sym_index != 0) {
150 sym = &((ElfW(Sym) *)s->data)[sym_index];
151 name1 = s->link->data + sym->st_name;
152 if (!strcmp(name, name1))
153 return sym_index;
154 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
156 return 0;
159 /* return elf symbol value, signal error if 'err' is nonzero */
160 static void *get_elf_sym_addr(TCCState *s, const char *name, int err)
162 int sym_index;
163 ElfW(Sym) *sym;
165 sym_index = find_elf_sym(s->symtab, name);
166 sym = &((ElfW(Sym) *)s->symtab->data)[sym_index];
167 if (!sym_index || sym->st_shndx == SHN_UNDEF) {
168 if (err)
169 tcc_error("%s not defined", name);
170 return NULL;
172 return (void*)(uplong)sym->st_value;
175 /* return elf symbol value */
176 LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
178 return get_elf_sym_addr(s, name, 0);
181 /* return elf symbol value or error */
182 ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name)
184 return get_elf_sym_addr(s, name, 1);
187 /* add an elf symbol : check if it is already defined and patch
188 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
189 ST_FUNC int add_elf_sym(Section *s, uplong value, unsigned long size,
190 int info, int other, int sh_num, const char *name)
192 ElfW(Sym) *esym;
193 int sym_bind, sym_index, sym_type, esym_bind;
194 unsigned char sym_vis, esym_vis, new_vis;
196 sym_bind = ELFW(ST_BIND)(info);
197 sym_type = ELFW(ST_TYPE)(info);
198 sym_vis = ELFW(ST_VISIBILITY)(other);
200 if (sym_bind != STB_LOCAL) {
201 /* we search global or weak symbols */
202 sym_index = find_elf_sym(s, name);
203 if (!sym_index)
204 goto do_def;
205 esym = &((ElfW(Sym) *)s->data)[sym_index];
206 if (esym->st_shndx != SHN_UNDEF) {
207 esym_bind = ELFW(ST_BIND)(esym->st_info);
208 /* propagate the most constraining visibility */
209 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
210 esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
211 if (esym_vis == STV_DEFAULT) {
212 new_vis = sym_vis;
213 } else if (sym_vis == STV_DEFAULT) {
214 new_vis = esym_vis;
215 } else {
216 new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
218 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
219 | new_vis;
220 other = esym->st_other; /* in case we have to patch esym */
221 if (sh_num == SHN_UNDEF) {
222 /* ignore adding of undefined symbol if the
223 corresponding symbol is already defined */
224 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
225 /* global overrides weak, so patch */
226 goto do_patch;
227 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
228 /* weak is ignored if already global */
229 } else if (sym_bind == STB_WEAK && esym_bind == STB_WEAK) {
230 /* keep first-found weak definition, ignore subsequents */
231 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
232 /* ignore hidden symbols after */
233 } else if (esym->st_shndx == SHN_COMMON
234 && (sh_num < SHN_LORESERVE || sh_num == SHN_COMMON)) {
235 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
236 No idea if this is the correct solution ... */
237 goto do_patch;
238 } else if (s == tcc_state->dynsymtab_section) {
239 /* we accept that two DLL define the same symbol */
240 } else {
241 #if 1
242 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
243 sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
244 #endif
245 tcc_error_noabort("'%s' defined twice", name);
247 } else {
248 do_patch:
249 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
250 esym->st_shndx = sh_num;
251 new_undef_sym = 1;
252 esym->st_value = value;
253 esym->st_size = size;
254 esym->st_other = other;
256 } else {
257 do_def:
258 sym_index = put_elf_sym(s, value, size,
259 ELFW(ST_INFO)(sym_bind, sym_type), other,
260 sh_num, name);
262 return sym_index;
265 /* put relocation */
266 ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
267 int type, int symbol)
269 char buf[256];
270 Section *sr;
271 ElfW_Rel *rel;
273 sr = s->reloc;
274 if (!sr) {
275 /* if no relocation section, create it */
276 snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
277 /* if the symtab is allocated, then we consider the relocation
278 are also */
279 sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
280 sr->sh_entsize = sizeof(ElfW_Rel);
281 sr->link = symtab;
282 sr->sh_info = s->sh_num;
283 s->reloc = sr;
285 rel = section_ptr_add(sr, sizeof(ElfW_Rel));
286 rel->r_offset = offset;
287 rel->r_info = ELFW(R_INFO)(symbol, type);
288 #ifdef TCC_TARGET_X86_64
289 rel->r_addend = 0;
290 #endif
293 /* put stab debug information */
295 ST_FUNC void put_stabs(const char *str, int type, int other, int desc,
296 unsigned long value)
298 Stab_Sym *sym;
300 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
301 if (str) {
302 sym->n_strx = put_elf_str(stabstr_section, str);
303 } else {
304 sym->n_strx = 0;
306 sym->n_type = type;
307 sym->n_other = other;
308 sym->n_desc = desc;
309 sym->n_value = value;
312 ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc,
313 unsigned long value, Section *sec, int sym_index)
315 put_stabs(str, type, other, desc, value);
316 put_elf_reloc(symtab_section, stab_section,
317 stab_section->data_offset - sizeof(unsigned int),
318 R_DATA_32, sym_index);
321 ST_FUNC void put_stabn(int type, int other, int desc, int value)
323 put_stabs(NULL, type, other, desc, value);
326 ST_FUNC void put_stabd(int type, int other, int desc)
328 put_stabs(NULL, type, other, desc, 0);
331 /* In an ELF file symbol table, the local symbols must appear below
332 the global and weak ones. Since TCC cannot sort it while generating
333 the code, we must do it after. All the relocation tables are also
334 modified to take into account the symbol table sorting */
335 static void sort_syms(TCCState *s1, Section *s)
337 int *old_to_new_syms;
338 ElfW(Sym) *new_syms;
339 int nb_syms, i;
340 ElfW(Sym) *p, *q;
341 ElfW_Rel *rel, *rel_end;
342 Section *sr;
343 int type, sym_index;
345 nb_syms = s->data_offset / sizeof(ElfW(Sym));
346 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
347 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
349 /* first pass for local symbols */
350 p = (ElfW(Sym) *)s->data;
351 q = new_syms;
352 for(i = 0; i < nb_syms; i++) {
353 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
354 old_to_new_syms[i] = q - new_syms;
355 *q++ = *p;
357 p++;
359 /* save the number of local symbols in section header */
360 s->sh_info = q - new_syms;
362 /* then second pass for non local symbols */
363 p = (ElfW(Sym) *)s->data;
364 for(i = 0; i < nb_syms; i++) {
365 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
366 old_to_new_syms[i] = q - new_syms;
367 *q++ = *p;
369 p++;
372 /* we copy the new symbols to the old */
373 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
374 tcc_free(new_syms);
376 /* now we modify all the relocations */
377 for(i = 1; i < s1->nb_sections; i++) {
378 sr = s1->sections[i];
379 if (sr->sh_type == SHT_RELX && sr->link == s) {
380 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
381 for(rel = (ElfW_Rel *)sr->data;
382 rel < rel_end;
383 rel++) {
384 sym_index = ELFW(R_SYM)(rel->r_info);
385 type = ELFW(R_TYPE)(rel->r_info);
386 sym_index = old_to_new_syms[sym_index];
387 rel->r_info = ELFW(R_INFO)(sym_index, type);
392 tcc_free(old_to_new_syms);
395 /* relocate common symbols in the .bss section */
396 ST_FUNC void relocate_common_syms(void)
398 ElfW(Sym) *sym, *sym_end;
399 unsigned long offset, align;
401 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
402 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
403 sym < sym_end;
404 sym++) {
405 if (sym->st_shndx == SHN_COMMON) {
406 /* align symbol */
407 align = sym->st_value;
408 offset = bss_section->data_offset;
409 offset = (offset + align - 1) & -align;
410 sym->st_value = offset;
411 sym->st_shndx = bss_section->sh_num;
412 offset += sym->st_size;
413 bss_section->data_offset = offset;
418 /* relocate symbol table, resolve undefined symbols if do_resolve is
419 true and output error if undefined symbol. */
420 ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
422 ElfW(Sym) *sym, *esym, *sym_end;
423 int sym_bind, sh_num, sym_index;
424 const char *name;
426 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
427 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
428 sym < sym_end;
429 sym++) {
430 sh_num = sym->st_shndx;
431 if (sh_num == SHN_UNDEF) {
432 name = strtab_section->data + sym->st_name;
433 if (do_resolve) {
434 #if !defined TCC_TARGET_PE || !defined _WIN32
435 void *addr;
436 name = symtab_section->link->data + sym->st_name;
437 addr = resolve_sym(s1, name);
438 if (addr) {
439 sym->st_value = (uplong)addr;
440 goto found;
442 #endif
443 } else if (s1->dynsym) {
444 /* if dynamic symbol exist, then use it */
445 sym_index = find_elf_sym(s1->dynsym, name);
446 if (sym_index) {
447 esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
448 sym->st_value = esym->st_value;
449 goto found;
452 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
453 it */
454 if (!strcmp(name, "_fp_hw"))
455 goto found;
456 /* only weak symbols are accepted to be undefined. Their
457 value is zero */
458 sym_bind = ELFW(ST_BIND)(sym->st_info);
459 if (sym_bind == STB_WEAK) {
460 sym->st_value = 0;
461 } else {
462 tcc_error_noabort("undefined symbol '%s'", name);
464 } else if (sh_num < SHN_LORESERVE) {
465 /* add section base */
466 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
468 found: ;
472 #ifndef TCC_TARGET_PE
473 #ifdef TCC_TARGET_X86_64
474 #define JMP_TABLE_ENTRY_SIZE 14
475 static uplong add_jmp_table(TCCState *s1, uplong val)
477 char *p = s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset;
478 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
479 /* jmp *0x0(%rip) */
480 p[0] = 0xff;
481 p[1] = 0x25;
482 *(int *)(p + 2) = 0;
483 *(uplong *)(p + 6) = val;
484 return (uplong)p;
487 static uplong add_got_table(TCCState *s1, uplong val)
489 uplong *p = (uplong *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
490 s1->runtime_plt_and_got_offset += sizeof(uplong);
491 *p = val;
492 return (uplong)p;
494 #elif defined TCC_TARGET_ARM
495 #define JMP_TABLE_ENTRY_SIZE 8
496 static uplong add_jmp_table(TCCState *s1, int val)
498 uint32_t *p = (uint32_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
499 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
500 /* ldr pc, [pc, #-4] */
501 p[0] = 0xE51FF004;
502 p[1] = val;
503 return (uplong)p;
505 #endif
506 #endif
508 /* relocate a given section (CPU dependent) */
509 ST_FUNC void relocate_section(TCCState *s1, Section *s)
511 Section *sr;
512 ElfW_Rel *rel, *rel_end, *qrel;
513 ElfW(Sym) *sym;
514 int type, sym_index;
515 unsigned char *ptr;
516 uplong val, addr;
517 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
518 int esym_index;
519 #endif
521 sr = s->reloc;
522 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
523 qrel = (ElfW_Rel *)sr->data;
524 for(rel = qrel;
525 rel < rel_end;
526 rel++) {
527 ptr = s->data + rel->r_offset;
529 sym_index = ELFW(R_SYM)(rel->r_info);
530 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
531 val = sym->st_value;
532 #ifdef TCC_TARGET_X86_64
533 val += rel->r_addend;
534 #endif
535 type = ELFW(R_TYPE)(rel->r_info);
536 addr = s->sh_addr + rel->r_offset;
538 /* CPU specific */
539 switch(type) {
540 #if defined(TCC_TARGET_I386)
541 case R_386_32:
542 if (s1->output_type == TCC_OUTPUT_DLL) {
543 esym_index = s1->symtab_to_dynsym[sym_index];
544 qrel->r_offset = rel->r_offset;
545 if (esym_index) {
546 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
547 qrel++;
548 break;
549 } else {
550 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
551 qrel++;
554 *(int *)ptr += val;
555 break;
556 case R_386_PC32:
557 if (s1->output_type == TCC_OUTPUT_DLL) {
558 /* DLL relocation */
559 esym_index = s1->symtab_to_dynsym[sym_index];
560 if (esym_index) {
561 qrel->r_offset = rel->r_offset;
562 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
563 qrel++;
564 break;
567 *(int *)ptr += val - addr;
568 break;
569 case R_386_PLT32:
570 *(int *)ptr += val - addr;
571 break;
572 case R_386_GLOB_DAT:
573 case R_386_JMP_SLOT:
574 *(int *)ptr = val;
575 break;
576 case R_386_GOTPC:
577 *(int *)ptr += s1->got->sh_addr - addr;
578 break;
579 case R_386_GOTOFF:
580 *(int *)ptr += val - s1->got->sh_addr;
581 break;
582 case R_386_GOT32:
583 /* we load the got offset */
584 *(int *)ptr += s1->got_offsets[sym_index];
585 break;
586 case R_386_16:
587 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
588 output_file:
589 tcc_error("can only produce 16-bit binary files");
591 *(short *)ptr += val;
592 break;
593 case R_386_PC16:
594 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
595 goto output_file;
596 *(short *)ptr += val - addr;
597 break;
598 #elif defined(TCC_TARGET_ARM)
599 case R_ARM_PC24:
600 case R_ARM_CALL:
601 case R_ARM_JUMP24:
602 case R_ARM_PLT32:
604 int x, is_thumb, is_call, h, blx_avail;
605 x = (*(int *)ptr)&0xffffff;
606 (*(int *)ptr) &= 0xff000000;
607 if (x & 0x800000)
608 x -= 0x1000000;
609 x <<= 2;
610 blx_avail = (TCC_ARM_VERSION >= 5);
611 is_thumb = val & 1;
612 is_call = (type == R_ARM_CALL);
613 x += val - addr;
614 h = x & 2;
615 #ifndef TCC_TARGET_PE
616 if ((x & 3) || x >= 0x4000000 || x < -0x4000000)
617 if (!(x & 3) || !blx_avail || !is_call)
618 if (s1->output_type == TCC_OUTPUT_MEMORY)
619 x += add_jmp_table(s1, val) - val; /* add veneer */
620 #endif
621 if ((x & 3) || x >= 0x4000000 || x < -0x4000000)
622 if (!(x & 3) || !blx_avail || !is_call)
623 tcc_error("can't relocate value at %x",addr);
624 x >>= 2;
625 x &= 0xffffff;
626 /* Only reached if blx is avail and it is a call */
627 if (is_thumb) {
628 x |= h << 24;
629 (*(int *)ptr) = 0xfa << 24; /* bl -> blx */
631 (*(int *)ptr) |= x;
633 break;
634 case R_ARM_MOVT_ABS:
635 case R_ARM_MOVW_ABS_NC:
637 int x, imm4, imm12;
638 if (type == R_ARM_MOVT_ABS)
639 val >>= 16;
640 imm12 = val & 0xfff;
641 imm4 = (val >> 12) & 0xf;
642 x = (imm4 << 16) | imm12;
643 if (type == R_ARM_THM_MOVT_ABS)
644 *(int *)ptr |= x;
645 else
646 *(int *)ptr += x;
648 break;
649 case R_ARM_THM_MOVT_ABS:
650 case R_ARM_THM_MOVW_ABS_NC:
652 int x, i, imm4, imm3, imm8;
653 if (type == R_ARM_THM_MOVT_ABS)
654 val >>= 16;
655 imm8 = val & 0xff;
656 imm3 = (val >> 8) & 0x7;
657 i = (val >> 11) & 1;
658 imm4 = (val >> 12) & 0xf;
659 x = (imm3 << 28) | (imm8 << 16) | (i << 10) | imm4;
660 if (type == R_ARM_THM_MOVT_ABS)
661 *(int *)ptr |= x;
662 else
663 *(int *)ptr += x;
665 break;
666 case R_ARM_PREL31:
668 int x;
669 x = (*(int *)ptr) & 0x7fffffff;
670 (*(int *)ptr) &= 0x80000000;
671 x = (x * 2) / 2;
672 x += val - addr;
673 if((x^(x>>1))&0x40000000)
674 tcc_error("can't relocate value at %x",addr);
675 (*(int *)ptr) |= x & 0x7fffffff;
677 case R_ARM_ABS32:
678 *(int *)ptr += val;
679 break;
680 case R_ARM_REL32:
681 *(int *)ptr += val - addr;
682 break;
683 case R_ARM_BASE_PREL:
684 *(int *)ptr += s1->got->sh_addr - addr;
685 break;
686 case R_ARM_GOTOFF32:
687 *(int *)ptr += val - s1->got->sh_addr;
688 break;
689 case R_ARM_GOT_BREL:
690 /* we load the got offset */
691 *(int *)ptr += s1->got_offsets[sym_index];
692 break;
693 case R_ARM_COPY:
694 break;
695 case R_ARM_V4BX:
696 /* trade Thumb support for ARMv4 support */
697 if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
698 *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
699 break;
700 default:
701 fprintf(stderr,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
702 type, (unsigned)addr, (unsigned)(uplong)ptr, (unsigned)val);
703 break;
704 #elif defined(TCC_TARGET_C67)
705 case R_C60_32:
706 *(int *)ptr += val;
707 break;
708 case R_C60LO16:
710 uint32_t orig;
712 /* put the low 16 bits of the absolute address */
713 // add to what is already there
715 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
716 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
718 //patch both at once - assumes always in pairs Low - High
720 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
721 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
723 break;
724 case R_C60HI16:
725 break;
726 default:
727 fprintf(stderr,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
728 type, (unsigned)addr, (unsigned)(uplong)ptr, (unsigned)val);
729 break;
730 #elif defined(TCC_TARGET_X86_64)
731 case R_X86_64_64:
732 if (s1->output_type == TCC_OUTPUT_DLL) {
733 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
734 qrel->r_addend = *(long long *)ptr + val;
735 qrel++;
737 *(long long *)ptr += val;
738 break;
739 case R_X86_64_32:
740 case R_X86_64_32S:
741 if (s1->output_type == TCC_OUTPUT_DLL) {
742 /* XXX: this logic may depend on TCC's codegen
743 now TCC uses R_X86_64_32 even for a 64bit pointer */
744 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
745 qrel->r_addend = *(int *)ptr + val;
746 qrel++;
748 *(int *)ptr += val;
749 break;
751 case R_X86_64_PC32:
752 if (s1->output_type == TCC_OUTPUT_DLL) {
753 /* DLL relocation */
754 esym_index = s1->symtab_to_dynsym[sym_index];
755 if (esym_index) {
756 qrel->r_offset = rel->r_offset;
757 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
758 qrel->r_addend = *(int *)ptr;
759 qrel++;
760 break;
763 /* fall through */
764 case R_X86_64_PLT32: {
765 long long diff;
766 diff = (long long)val - addr;
767 if (diff <= -2147483647 || diff > 2147483647) {
768 #ifndef TCC_TARGET_PE
769 /* XXX: naive support for over 32bit jump */
770 if (s1->output_type == TCC_OUTPUT_MEMORY) {
771 val = (add_jmp_table(s1, val - rel->r_addend) +
772 rel->r_addend);
773 diff = val - addr;
775 #endif
776 if (diff <= -2147483647 || diff > 2147483647) {
777 tcc_error("internal error: relocation failed");
780 *(int *)ptr += diff;
782 break;
783 case R_X86_64_GLOB_DAT:
784 case R_X86_64_JUMP_SLOT:
785 /* They don't need addend */
786 *(int *)ptr = val - rel->r_addend;
787 break;
788 case R_X86_64_GOTPCREL:
789 #ifndef TCC_TARGET_PE
790 if (s1->output_type == TCC_OUTPUT_MEMORY) {
791 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
792 *(int *)ptr += val - addr;
793 break;
795 #endif
796 *(int *)ptr += (s1->got->sh_addr - addr +
797 s1->got_offsets[sym_index] - 4);
798 break;
799 case R_X86_64_GOTTPOFF:
800 *(int *)ptr += val - s1->got->sh_addr;
801 break;
802 case R_X86_64_GOT32:
803 /* we load the got offset */
804 *(int *)ptr += s1->got_offsets[sym_index];
805 break;
806 #else
807 #error unsupported processor
808 #endif
811 /* if the relocation is allocated, we change its symbol table */
812 if (sr->sh_flags & SHF_ALLOC)
813 sr->link = s1->dynsym;
816 /* relocate relocation table in 'sr' */
817 static void relocate_rel(TCCState *s1, Section *sr)
819 Section *s;
820 ElfW_Rel *rel, *rel_end;
822 s = s1->sections[sr->sh_info];
823 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
824 for(rel = (ElfW_Rel *)sr->data;
825 rel < rel_end;
826 rel++) {
827 rel->r_offset += s->sh_addr;
831 /* count the number of dynamic relocations so that we can reserve
832 their space */
833 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
835 ElfW_Rel *rel, *rel_end;
836 int sym_index, esym_index, type, count;
838 count = 0;
839 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
840 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
841 sym_index = ELFW(R_SYM)(rel->r_info);
842 type = ELFW(R_TYPE)(rel->r_info);
843 switch(type) {
844 #if defined(TCC_TARGET_I386)
845 case R_386_32:
846 #elif defined(TCC_TARGET_X86_64)
847 case R_X86_64_32:
848 case R_X86_64_32S:
849 case R_X86_64_64:
850 #endif
851 count++;
852 break;
853 #if defined(TCC_TARGET_I386)
854 case R_386_PC32:
855 #elif defined(TCC_TARGET_X86_64)
856 case R_X86_64_PC32:
857 #endif
858 esym_index = s1->symtab_to_dynsym[sym_index];
859 if (esym_index)
860 count++;
861 break;
862 default:
863 break;
866 if (count) {
867 /* allocate the section */
868 sr->sh_flags |= SHF_ALLOC;
869 sr->sh_size = count * sizeof(ElfW_Rel);
871 return count;
874 static void put_got_offset(TCCState *s1, int index, unsigned long val)
876 int n;
877 unsigned long *tab;
879 if (index >= s1->nb_got_offsets) {
880 /* find immediately bigger power of 2 and reallocate array */
881 n = 1;
882 while (index >= n)
883 n *= 2;
884 tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
885 s1->got_offsets = tab;
886 memset(s1->got_offsets + s1->nb_got_offsets, 0,
887 (n - s1->nb_got_offsets) * sizeof(unsigned long));
888 s1->nb_got_offsets = n;
890 s1->got_offsets[index] = val;
893 /* XXX: suppress that */
894 static void put32(unsigned char *p, uint32_t val)
896 p[0] = val;
897 p[1] = val >> 8;
898 p[2] = val >> 16;
899 p[3] = val >> 24;
902 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
903 defined(TCC_TARGET_X86_64)
904 static uint32_t get32(unsigned char *p)
906 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
908 #endif
910 static void build_got(TCCState *s1)
912 unsigned char *ptr;
914 /* if no got, then create it */
915 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
916 s1->got->sh_entsize = 4;
917 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
918 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
919 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
920 #if PTR_SIZE == 4
921 /* keep space for _DYNAMIC pointer, if present */
922 put32(ptr, 0);
923 /* two dummy got entries */
924 put32(ptr + 4, 0);
925 put32(ptr + 8, 0);
926 #else
927 /* keep space for _DYNAMIC pointer, if present */
928 put32(ptr, 0);
929 put32(ptr + 4, 0);
930 /* two dummy got entries */
931 put32(ptr + 8, 0);
932 put32(ptr + 12, 0);
933 put32(ptr + 16, 0);
934 put32(ptr + 20, 0);
935 #endif
938 /* put a got entry corresponding to a symbol in symtab_section. 'size'
939 and 'info' can be modifed if more precise info comes from the DLL */
940 static void put_got_entry(TCCState *s1,
941 int reloc_type, unsigned long size, int info,
942 int sym_index)
944 int index;
945 const char *name;
946 ElfW(Sym) *sym;
947 unsigned long offset;
948 int *ptr;
950 if (!s1->got)
951 build_got(s1);
953 /* if a got entry already exists for that symbol, no need to add one */
954 if (sym_index < s1->nb_got_offsets &&
955 s1->got_offsets[sym_index] != 0)
956 return;
958 put_got_offset(s1, sym_index, s1->got->data_offset);
960 if (s1->dynsym) {
961 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
962 name = symtab_section->link->data + sym->st_name;
963 offset = sym->st_value;
964 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
965 if (reloc_type ==
966 #ifdef TCC_TARGET_X86_64
967 R_X86_64_JUMP_SLOT
968 #else
969 R_386_JMP_SLOT
970 #endif
972 Section *plt;
973 uint8_t *p;
974 int modrm;
976 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
977 modrm = 0x25;
978 #else
979 /* if we build a DLL, we add a %ebx offset */
980 if (s1->output_type == TCC_OUTPUT_DLL)
981 modrm = 0xa3;
982 else
983 modrm = 0x25;
984 #endif
986 /* add a PLT entry */
987 plt = s1->plt;
988 if (plt->data_offset == 0) {
989 /* first plt entry */
990 p = section_ptr_add(plt, 16);
991 p[0] = 0xff; /* pushl got + PTR_SIZE */
992 p[1] = modrm + 0x10;
993 put32(p + 2, PTR_SIZE);
994 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
995 p[7] = modrm;
996 put32(p + 8, PTR_SIZE * 2);
999 p = section_ptr_add(plt, 16);
1000 p[0] = 0xff; /* jmp *(got + x) */
1001 p[1] = modrm;
1002 put32(p + 2, s1->got->data_offset);
1003 p[6] = 0x68; /* push $xxx */
1004 put32(p + 7, (plt->data_offset - 32) >> 1);
1005 p[11] = 0xe9; /* jmp plt_start */
1006 put32(p + 12, -(plt->data_offset));
1008 /* the symbol is modified so that it will be relocated to
1009 the PLT */
1010 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
1011 if (s1->output_type == TCC_OUTPUT_EXE)
1012 #endif
1013 offset = plt->data_offset - 16;
1015 #elif defined(TCC_TARGET_ARM)
1016 if (reloc_type == R_ARM_JUMP_SLOT) {
1017 Section *plt;
1018 uint8_t *p;
1020 /* if we build a DLL, we add a %ebx offset */
1021 if (s1->output_type == TCC_OUTPUT_DLL)
1022 tcc_error("DLLs unimplemented!");
1024 /* add a PLT entry */
1025 plt = s1->plt;
1026 if (plt->data_offset == 0) {
1027 /* first plt entry */
1028 p = section_ptr_add(plt, 16);
1029 put32(p , 0xe52de004);
1030 put32(p + 4, 0xe59fe010);
1031 put32(p + 8, 0xe08fe00e);
1032 put32(p + 12, 0xe5bef008);
1035 p = section_ptr_add(plt, 16);
1036 put32(p , 0xe59fc004);
1037 put32(p+4, 0xe08fc00c);
1038 put32(p+8, 0xe59cf000);
1039 put32(p+12, s1->got->data_offset);
1041 /* the symbol is modified so that it will be relocated to
1042 the PLT */
1043 if (s1->output_type == TCC_OUTPUT_EXE)
1044 offset = plt->data_offset - 16;
1046 #elif defined(TCC_TARGET_C67)
1047 tcc_error("C67 got not implemented");
1048 #else
1049 #error unsupported CPU
1050 #endif
1051 index = put_elf_sym(s1->dynsym, offset,
1052 size, info, 0, sym->st_shndx, name);
1053 /* put a got entry */
1054 put_elf_reloc(s1->dynsym, s1->got,
1055 s1->got->data_offset,
1056 reloc_type, index);
1058 ptr = section_ptr_add(s1->got, PTR_SIZE);
1059 *ptr = 0;
1062 /* build GOT and PLT entries */
1063 ST_FUNC void build_got_entries(TCCState *s1)
1065 Section *s;
1066 ElfW_Rel *rel, *rel_end;
1067 ElfW(Sym) *sym;
1068 int i, type, reloc_type, sym_index;
1070 for(i = 1; i < s1->nb_sections; i++) {
1071 s = s1->sections[i];
1072 if (s->sh_type != SHT_RELX)
1073 continue;
1074 /* no need to handle got relocations */
1075 if (s->link != symtab_section)
1076 continue;
1077 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1078 for(rel = (ElfW_Rel *)s->data;
1079 rel < rel_end;
1080 rel++) {
1081 type = ELFW(R_TYPE)(rel->r_info);
1082 switch(type) {
1083 #if defined(TCC_TARGET_I386)
1084 case R_386_GOT32:
1085 case R_386_GOTOFF:
1086 case R_386_GOTPC:
1087 case R_386_PLT32:
1088 if (!s1->got)
1089 build_got(s1);
1090 if (type == R_386_GOT32 || type == R_386_PLT32) {
1091 sym_index = ELFW(R_SYM)(rel->r_info);
1092 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1093 /* look at the symbol got offset. If none, then add one */
1094 if (type == R_386_GOT32)
1095 reloc_type = R_386_GLOB_DAT;
1096 else
1097 reloc_type = R_386_JMP_SLOT;
1098 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1099 sym_index);
1101 break;
1102 #elif defined(TCC_TARGET_ARM)
1103 case R_ARM_GOT_BREL:
1104 case R_ARM_GOTOFF32:
1105 case R_ARM_BASE_PREL:
1106 case R_ARM_PLT32:
1107 if (!s1->got)
1108 build_got(s1);
1109 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1110 sym_index = ELFW(R_SYM)(rel->r_info);
1111 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1112 /* look at the symbol got offset. If none, then add one */
1113 if (type == R_ARM_GOT_BREL)
1114 reloc_type = R_ARM_GLOB_DAT;
1115 else
1116 reloc_type = R_ARM_JUMP_SLOT;
1117 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1118 sym_index);
1120 break;
1121 #elif defined(TCC_TARGET_C67)
1122 case R_C60_GOT32:
1123 case R_C60_GOTOFF:
1124 case R_C60_GOTPC:
1125 case R_C60_PLT32:
1126 if (!s1->got)
1127 build_got(s1);
1128 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1129 sym_index = ELFW(R_SYM)(rel->r_info);
1130 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1131 /* look at the symbol got offset. If none, then add one */
1132 if (type == R_C60_GOT32)
1133 reloc_type = R_C60_GLOB_DAT;
1134 else
1135 reloc_type = R_C60_JMP_SLOT;
1136 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1137 sym_index);
1139 break;
1140 #elif defined(TCC_TARGET_X86_64)
1141 case R_X86_64_GOT32:
1142 case R_X86_64_GOTTPOFF:
1143 case R_X86_64_GOTPCREL:
1144 case R_X86_64_PLT32:
1145 if (!s1->got)
1146 build_got(s1);
1147 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1148 type == R_X86_64_PLT32) {
1149 sym_index = ELFW(R_SYM)(rel->r_info);
1150 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1151 /* look at the symbol got offset. If none, then add one */
1152 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1153 reloc_type = R_X86_64_GLOB_DAT;
1154 else
1155 reloc_type = R_X86_64_JUMP_SLOT;
1156 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1157 sym_index);
1159 break;
1160 #else
1161 #error unsupported CPU
1162 #endif
1163 default:
1164 break;
1170 ST_FUNC Section *new_symtab(TCCState *s1,
1171 const char *symtab_name, int sh_type, int sh_flags,
1172 const char *strtab_name,
1173 const char *hash_name, int hash_sh_flags)
1175 Section *symtab, *strtab, *hash;
1176 int *ptr, nb_buckets;
1178 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1179 symtab->sh_entsize = sizeof(ElfW(Sym));
1180 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1181 put_elf_str(strtab, "");
1182 symtab->link = strtab;
1183 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1185 nb_buckets = 1;
1187 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1188 hash->sh_entsize = sizeof(int);
1189 symtab->hash = hash;
1190 hash->link = symtab;
1192 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1193 ptr[0] = nb_buckets;
1194 ptr[1] = 1;
1195 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1196 return symtab;
1199 /* put dynamic tag */
1200 static void put_dt(Section *dynamic, int dt, uplong val)
1202 ElfW(Dyn) *dyn;
1203 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1204 dyn->d_tag = dt;
1205 dyn->d_un.d_val = val;
1208 static void add_init_array_defines(TCCState *s1, const char *section_name)
1210 Section *s;
1211 long end_offset;
1212 char sym_start[1024];
1213 char sym_end[1024];
1215 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1216 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1218 s = find_section(s1, section_name);
1219 if (!s) {
1220 end_offset = 0;
1221 s = data_section;
1222 } else {
1223 end_offset = s->data_offset;
1226 add_elf_sym(symtab_section,
1227 0, 0,
1228 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1229 s->sh_num, sym_start);
1230 add_elf_sym(symtab_section,
1231 end_offset, 0,
1232 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1233 s->sh_num, sym_end);
1236 static int tcc_add_support(TCCState *s1, const char *filename)
1238 char buf[1024];
1239 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, filename);
1240 return tcc_add_file(s1, buf);
1243 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1245 #ifdef CONFIG_TCC_BCHECK
1246 unsigned long *ptr;
1247 Section *init_section;
1248 unsigned char *pinit;
1249 int sym_index;
1251 if (0 == s1->do_bounds_check)
1252 return;
1254 /* XXX: add an object file to do that */
1255 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1256 *ptr = 0;
1257 add_elf_sym(symtab_section, 0, 0,
1258 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1259 bounds_section->sh_num, "__bounds_start");
1260 /* add bound check code */
1261 #ifndef TCC_TARGET_PE
1262 tcc_add_support(s1, "bcheck.o");
1263 #endif
1264 #ifdef TCC_TARGET_I386
1265 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1266 /* add 'call __bound_init()' in .init section */
1267 init_section = find_section(s1, ".init");
1268 pinit = section_ptr_add(init_section, 5);
1269 pinit[0] = 0xe8;
1270 put32(pinit + 1, -4);
1271 sym_index = find_elf_sym(symtab_section, "__bound_init");
1272 put_elf_reloc(symtab_section, init_section,
1273 init_section->data_offset - 4, R_386_PC32, sym_index);
1275 #endif
1276 #endif
1279 /* add tcc runtime libraries */
1280 ST_FUNC void tcc_add_runtime(TCCState *s1)
1282 tcc_add_bcheck(s1);
1284 /* add libc */
1285 if (!s1->nostdlib) {
1286 tcc_add_library(s1, "c");
1287 #ifdef CONFIG_USE_LIBGCC
1288 tcc_add_file(s1, TCC_LIBGCC);
1289 #elif !defined WITHOUT_LIBTCC
1290 tcc_add_support(s1, "libtcc1.a");
1291 #endif
1292 /* add crt end if not memory output */
1293 if (s1->output_type != TCC_OUTPUT_MEMORY)
1294 tcc_add_crt(s1, "crtn.o");
1298 /* add various standard linker symbols (must be done after the
1299 sections are filled (for example after allocating common
1300 symbols)) */
1301 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1303 char buf[1024];
1304 int i;
1305 Section *s;
1307 add_elf_sym(symtab_section,
1308 text_section->data_offset, 0,
1309 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1310 text_section->sh_num, "_etext");
1311 add_elf_sym(symtab_section,
1312 data_section->data_offset, 0,
1313 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1314 data_section->sh_num, "_edata");
1315 add_elf_sym(symtab_section,
1316 bss_section->data_offset, 0,
1317 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1318 bss_section->sh_num, "_end");
1319 /* horrible new standard ldscript defines */
1320 add_init_array_defines(s1, ".preinit_array");
1321 add_init_array_defines(s1, ".init_array");
1322 add_init_array_defines(s1, ".fini_array");
1324 /* add start and stop symbols for sections whose name can be
1325 expressed in C */
1326 for(i = 1; i < s1->nb_sections; i++) {
1327 s = s1->sections[i];
1328 if (s->sh_type == SHT_PROGBITS &&
1329 (s->sh_flags & SHF_ALLOC)) {
1330 const char *p;
1331 int ch;
1333 /* check if section name can be expressed in C */
1334 p = s->name;
1335 for(;;) {
1336 ch = *p;
1337 if (!ch)
1338 break;
1339 if (!isid(ch) && !isnum(ch))
1340 goto next_sec;
1341 p++;
1343 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1344 add_elf_sym(symtab_section,
1345 0, 0,
1346 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1347 s->sh_num, buf);
1348 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1349 add_elf_sym(symtab_section,
1350 s->data_offset, 0,
1351 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1352 s->sh_num, buf);
1354 next_sec: ;
1358 static void tcc_output_binary(TCCState *s1, FILE *f,
1359 const int *section_order)
1361 Section *s;
1362 int i, offset, size;
1364 offset = 0;
1365 for(i=1;i<s1->nb_sections;i++) {
1366 s = s1->sections[section_order[i]];
1367 if (s->sh_type != SHT_NOBITS &&
1368 (s->sh_flags & SHF_ALLOC)) {
1369 while (offset < s->sh_offset) {
1370 fputc(0, f);
1371 offset++;
1373 size = s->sh_size;
1374 fwrite(s->data, 1, size, f);
1375 offset += size;
1380 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1381 #define HAVE_PHDR 1
1382 #define EXTRA_RELITEMS 14
1384 /* move the relocation value from .dynsym to .got */
1385 void patch_dynsym_undef(TCCState *s1, Section *s)
1387 uint32_t *gotd = (void *)s1->got->data;
1388 ElfW(Sym) *sym, *sym_end;
1390 gotd += 3; // dummy entries in .got
1391 /* relocate symbols in .dynsym */
1392 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1393 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1394 if (sym->st_shndx == SHN_UNDEF) {
1395 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1396 sym->st_value = 0;
1400 #else
1401 #define HAVE_PHDR 0
1402 #define EXTRA_RELITEMS 9
1404 /* zero plt offsets of weak symbols in .dynsym */
1405 void patch_dynsym_undef(TCCState *s1, Section *s)
1407 ElfW(Sym) *sym, *sym_end;
1409 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1410 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++)
1411 if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
1412 sym->st_value = 0;
1414 #endif
1416 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1418 int sym_index = ELFW(R_SYM) (rel->r_info);
1419 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1420 unsigned long offset;
1422 if (sym_index >= s1->nb_got_offsets)
1423 return;
1424 offset = s1->got_offsets[sym_index];
1425 section_reserve(s1->got, offset + PTR_SIZE);
1426 #ifdef TCC_TARGET_X86_64
1427 /* only works for x86-64 */
1428 put32(s1->got->data + offset + 4, sym->st_value >> 32);
1429 #endif
1430 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1433 ST_FUNC void fill_got(TCCState *s1)
1435 Section *s;
1436 ElfW_Rel *rel, *rel_end;
1437 int i;
1439 for(i = 1; i < s1->nb_sections; i++) {
1440 s = s1->sections[i];
1441 if (s->sh_type != SHT_RELX)
1442 continue;
1443 /* no need to handle got relocations */
1444 if (s->link != symtab_section)
1445 continue;
1446 rel_end = (ElfW_Rel *) (s->data + s->data_offset);
1447 for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
1448 switch (ELFW(R_TYPE) (rel->r_info)) {
1449 case R_X86_64_GOT32:
1450 case R_X86_64_GOTPCREL:
1451 case R_X86_64_PLT32:
1452 fill_got_entry(s1, rel);
1453 break;
1460 /* output an ELF file */
1461 /* XXX: suppress unneeded sections */
1462 static int elf_output_file(TCCState *s1, const char *filename)
1464 ElfW(Ehdr) ehdr;
1465 FILE *f;
1466 int fd, mode, ret;
1467 int *section_order;
1468 int shnum, i, phnum, file_offset, offset, size, j, sh_order_index, k;
1469 long long tmp;
1470 uplong addr;
1471 Section *strsec, *s;
1472 ElfW(Shdr) shdr, *sh;
1473 ElfW(Phdr) *phdr, *ph;
1474 Section *interp, *dynamic, *dynstr;
1475 unsigned long saved_dynamic_data_offset;
1476 ElfW(Sym) *sym;
1477 int type, file_type;
1478 uplong rel_addr, rel_size;
1479 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1480 uplong bss_addr, bss_size;
1481 #endif
1483 file_type = s1->output_type;
1484 s1->nb_errors = 0;
1486 if (file_type != TCC_OUTPUT_OBJ) {
1487 tcc_add_runtime(s1);
1490 phdr = NULL;
1491 section_order = NULL;
1492 interp = NULL;
1493 dynamic = NULL;
1494 dynstr = NULL; /* avoid warning */
1495 saved_dynamic_data_offset = 0; /* avoid warning */
1497 if (file_type != TCC_OUTPUT_OBJ) {
1498 relocate_common_syms();
1500 tcc_add_linker_symbols(s1);
1502 if (!s1->static_link) {
1503 const char *name;
1504 int sym_index, index;
1505 ElfW(Sym) *esym, *sym_end;
1507 if (file_type == TCC_OUTPUT_EXE) {
1508 char *ptr;
1509 /* allow override the dynamic loader */
1510 const char *elfint = getenv("LD_SO");
1511 if (elfint == NULL)
1512 elfint = CONFIG_TCC_ELFINTERP;
1513 /* add interpreter section only if executable */
1514 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1515 interp->sh_addralign = 1;
1516 ptr = section_ptr_add(interp, 1+strlen(elfint));
1517 strcpy(ptr, elfint);
1520 /* add dynamic symbol table */
1521 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1522 ".dynstr",
1523 ".hash", SHF_ALLOC);
1524 dynstr = s1->dynsym->link;
1526 /* add dynamic section */
1527 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1528 SHF_ALLOC | SHF_WRITE);
1529 dynamic->link = dynstr;
1530 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1532 /* add PLT */
1533 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1534 SHF_ALLOC | SHF_EXECINSTR);
1535 s1->plt->sh_entsize = 4;
1537 build_got(s1);
1539 /* scan for undefined symbols and see if they are in the
1540 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1541 is found, then we add it in the PLT. If a symbol
1542 STT_OBJECT is found, we add it in the .bss section with
1543 a suitable relocation */
1544 sym_end = (ElfW(Sym) *)(symtab_section->data +
1545 symtab_section->data_offset);
1546 if (file_type == TCC_OUTPUT_EXE) {
1547 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1548 sym < sym_end;
1549 sym++) {
1550 if (sym->st_shndx == SHN_UNDEF) {
1551 name = symtab_section->link->data + sym->st_name;
1552 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1553 if (sym_index) {
1554 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1555 type = ELFW(ST_TYPE)(esym->st_info);
1556 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1557 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1558 ELFW(ST_INFO)(STB_GLOBAL,type),
1559 sym - (ElfW(Sym) *)symtab_section->data);
1560 } else if (type == STT_OBJECT) {
1561 unsigned long offset;
1562 ElfW(Sym) *dynsym, *dynsym_end;
1563 offset = bss_section->data_offset;
1564 /* XXX: which alignment ? */
1565 offset = (offset + 16 - 1) & -16;
1566 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1567 esym->st_info, 0,
1568 bss_section->sh_num, name);
1569 // Ensure R_COPY works for weak symbol aliases
1570 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1571 dynsym_end = (ElfW(Sym) *)
1572 (s1->dynsymtab_section->data +
1573 s1->dynsymtab_section->data_offset);
1574 for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1575 dynsym < dynsym_end; dynsym++) {
1576 if ((dynsym->st_value == esym->st_value)
1577 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1578 char *dynname;
1579 dynname = s1->dynsymtab_section->link->data
1580 + dynsym->st_name;
1581 put_elf_sym(s1->dynsym, offset,
1582 dynsym->st_size,
1583 dynsym->st_info, 0,
1584 bss_section->sh_num,
1585 dynname);
1586 break;
1590 put_elf_reloc(s1->dynsym, bss_section,
1591 offset, R_COPY, index);
1592 offset += esym->st_size;
1593 bss_section->data_offset = offset;
1595 } else {
1596 /* STB_WEAK undefined symbols are accepted */
1597 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1598 it */
1599 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1600 !strcmp(name, "_fp_hw")) {
1601 } else {
1602 tcc_error_noabort("undefined symbol '%s'", name);
1605 } else if (s1->rdynamic &&
1606 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1607 /* if -rdynamic option, then export all non
1608 local symbols */
1609 name = symtab_section->link->data + sym->st_name;
1610 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1611 sym->st_info, 0,
1612 sym->st_shndx, name);
1616 if (s1->nb_errors)
1617 goto fail;
1619 /* now look at unresolved dynamic symbols and export
1620 corresponding symbol */
1621 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1622 s1->dynsymtab_section->data_offset);
1623 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1624 esym < sym_end;
1625 esym++) {
1626 if (esym->st_shndx == SHN_UNDEF) {
1627 name = s1->dynsymtab_section->link->data + esym->st_name;
1628 sym_index = find_elf_sym(symtab_section, name);
1629 if (sym_index) {
1630 /* XXX: avoid adding a symbol if already
1631 present because of -rdynamic ? */
1632 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1633 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1634 sym->st_info, 0,
1635 sym->st_shndx, name);
1636 } else {
1637 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1638 /* weak symbols can stay undefined */
1639 } else {
1640 tcc_warning("undefined dynamic symbol '%s'", name);
1645 } else {
1646 int nb_syms;
1647 /* shared library case : we simply export all the global symbols */
1648 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1649 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1650 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1651 sym < sym_end;
1652 sym++) {
1653 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1654 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1655 if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
1656 ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
1657 && sym->st_shndx == SHN_UNDEF) {
1658 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1659 sym->st_info,
1660 sym - (ElfW(Sym) *)symtab_section->data);
1662 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1663 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1664 sym->st_info,
1665 sym - (ElfW(Sym) *)symtab_section->data);
1667 else
1668 #endif
1670 name = symtab_section->link->data + sym->st_name;
1671 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1672 sym->st_info, 0,
1673 sym->st_shndx, name);
1674 s1->symtab_to_dynsym[sym -
1675 (ElfW(Sym) *)symtab_section->data] =
1676 index;
1682 build_got_entries(s1);
1684 /* add a list of needed dlls */
1685 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1686 DLLReference *dllref = s1->loaded_dlls[i];
1687 if (dllref->level == 0)
1688 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1691 if (s1->rpath)
1692 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1694 /* XXX: currently, since we do not handle PIC code, we
1695 must relocate the readonly segments */
1696 if (file_type == TCC_OUTPUT_DLL) {
1697 if (s1->soname)
1698 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1699 put_dt(dynamic, DT_TEXTREL, 0);
1702 if (s1->symbolic)
1703 put_dt(dynamic, DT_SYMBOLIC, 0);
1705 /* add necessary space for other entries */
1706 saved_dynamic_data_offset = dynamic->data_offset;
1707 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1708 } else {
1709 /* still need to build got entries in case of static link */
1710 build_got_entries(s1);
1714 memset(&ehdr, 0, sizeof(ehdr));
1716 /* we add a section for symbols */
1717 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1718 put_elf_str(strsec, "");
1720 /* compute number of sections */
1721 shnum = s1->nb_sections;
1723 /* this array is used to reorder sections in the output file */
1724 section_order = tcc_malloc(sizeof(int) * shnum);
1725 section_order[0] = 0;
1726 sh_order_index = 1;
1728 /* compute number of program headers */
1729 switch(file_type) {
1730 default:
1731 case TCC_OUTPUT_OBJ:
1732 phnum = 0;
1733 break;
1734 case TCC_OUTPUT_EXE:
1735 if (!s1->static_link)
1736 phnum = 4 + HAVE_PHDR;
1737 else
1738 phnum = 2;
1739 break;
1740 case TCC_OUTPUT_DLL:
1741 phnum = 3;
1742 break;
1745 /* allocate strings for section names and decide if an unallocated
1746 section should be output */
1747 /* NOTE: the strsec section comes last, so its size is also
1748 correct ! */
1749 for(i = 1; i < s1->nb_sections; i++) {
1750 s = s1->sections[i];
1751 s->sh_name = put_elf_str(strsec, s->name);
1752 #if 0 //gr
1753 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1754 s->sh_flags,
1755 s->sh_type,
1756 s->sh_info,
1757 s->name,
1758 s->reloc ? s->reloc->name : "n"
1760 #endif
1761 /* when generating a DLL, we include relocations but we may
1762 patch them */
1763 if (file_type == TCC_OUTPUT_DLL &&
1764 s->sh_type == SHT_RELX &&
1765 !(s->sh_flags & SHF_ALLOC)) {
1766 /* //gr: avoid bogus relocs for empty (debug) sections */
1767 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1768 prepare_dynamic_rel(s1, s);
1769 else if (s1->do_debug)
1770 s->sh_size = s->data_offset;
1771 } else if (s1->do_debug ||
1772 file_type == TCC_OUTPUT_OBJ ||
1773 (s->sh_flags & SHF_ALLOC) ||
1774 i == (s1->nb_sections - 1)) {
1775 /* we output all sections if debug or object file */
1776 s->sh_size = s->data_offset;
1780 /* allocate program segment headers */
1781 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1783 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1784 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1785 } else {
1786 file_offset = 0;
1788 if (phnum > 0) {
1789 /* compute section to program header mapping */
1790 if (s1->has_text_addr) {
1791 int a_offset, p_offset;
1792 addr = s1->text_addr;
1793 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1794 ELF_PAGE_SIZE */
1795 a_offset = (int) (addr & (s1->section_align - 1));
1796 p_offset = file_offset & (s1->section_align - 1);
1797 if (a_offset < p_offset)
1798 a_offset += s1->section_align;
1799 file_offset += (a_offset - p_offset);
1800 } else {
1801 if (file_type == TCC_OUTPUT_DLL)
1802 addr = 0;
1803 else
1804 addr = ELF_START_ADDR;
1805 /* compute address after headers */
1806 addr += (file_offset & (s1->section_align - 1));
1809 /* dynamic relocation table information, for .dynamic section */
1810 rel_size = 0;
1811 rel_addr = 0;
1813 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1814 bss_addr = bss_size = 0;
1815 #endif
1816 /* leave one program header for the program interpreter */
1817 ph = &phdr[0];
1818 if (interp)
1819 ph += 1 + HAVE_PHDR;
1821 for(j = 0; j < 2; j++) {
1822 ph->p_type = PT_LOAD;
1823 if (j == 0)
1824 ph->p_flags = PF_R | PF_X;
1825 else
1826 ph->p_flags = PF_R | PF_W;
1827 ph->p_align = s1->section_align;
1829 /* we do the following ordering: interp, symbol tables,
1830 relocations, progbits, nobits */
1831 /* XXX: do faster and simpler sorting */
1832 for(k = 0; k < 5; k++) {
1833 for(i = 1; i < s1->nb_sections; i++) {
1834 s = s1->sections[i];
1835 /* compute if section should be included */
1836 if (j == 0) {
1837 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1838 SHF_ALLOC)
1839 continue;
1840 } else {
1841 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1842 (SHF_ALLOC | SHF_WRITE))
1843 continue;
1845 if (s == interp) {
1846 if (k != 0)
1847 continue;
1848 } else if (s->sh_type == SHT_DYNSYM ||
1849 s->sh_type == SHT_STRTAB ||
1850 s->sh_type == SHT_HASH) {
1851 if (k != 1)
1852 continue;
1853 } else if (s->sh_type == SHT_RELX) {
1854 if (k != 2)
1855 continue;
1856 } else if (s->sh_type == SHT_NOBITS) {
1857 if (k != 4)
1858 continue;
1859 } else {
1860 if (k != 3)
1861 continue;
1863 section_order[sh_order_index++] = i;
1865 /* section matches: we align it and add its size */
1866 tmp = addr;
1867 addr = (addr + s->sh_addralign - 1) &
1868 ~(s->sh_addralign - 1);
1869 file_offset += (int) ( addr - tmp );
1870 s->sh_offset = file_offset;
1871 s->sh_addr = addr;
1873 /* update program header infos */
1874 if (ph->p_offset == 0) {
1875 ph->p_offset = file_offset;
1876 ph->p_vaddr = addr;
1877 ph->p_paddr = ph->p_vaddr;
1879 /* update dynamic relocation infos */
1880 if (s->sh_type == SHT_RELX) {
1881 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1882 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1883 rel_addr = addr;
1884 rel_size += s->sh_size; // XXX only first rel.
1886 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1887 bss_addr = addr;
1888 bss_size = s->sh_size; // XXX only first rel.
1890 #else
1891 if (rel_size == 0)
1892 rel_addr = addr;
1893 rel_size += s->sh_size;
1894 #endif
1896 addr += s->sh_size;
1897 if (s->sh_type != SHT_NOBITS)
1898 file_offset += s->sh_size;
1901 ph->p_filesz = file_offset - ph->p_offset;
1902 ph->p_memsz = addr - ph->p_vaddr;
1903 ph++;
1904 if (j == 0) {
1905 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1906 /* if in the middle of a page, we duplicate the page in
1907 memory so that one copy is RX and the other is RW */
1908 if ((addr & (s1->section_align - 1)) != 0)
1909 addr += s1->section_align;
1910 } else {
1911 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1912 file_offset = (file_offset + s1->section_align - 1) &
1913 ~(s1->section_align - 1);
1918 /* if interpreter, then add corresponing program header */
1919 if (interp) {
1920 ph = &phdr[0];
1922 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1924 int len = phnum * sizeof(ElfW(Phdr));
1926 ph->p_type = PT_PHDR;
1927 ph->p_offset = sizeof(ElfW(Ehdr));
1928 ph->p_vaddr = interp->sh_addr - len;
1929 ph->p_paddr = ph->p_vaddr;
1930 ph->p_filesz = ph->p_memsz = len;
1931 ph->p_flags = PF_R | PF_X;
1932 ph->p_align = 4; // interp->sh_addralign;
1933 ph++;
1935 #endif
1937 ph->p_type = PT_INTERP;
1938 ph->p_offset = interp->sh_offset;
1939 ph->p_vaddr = interp->sh_addr;
1940 ph->p_paddr = ph->p_vaddr;
1941 ph->p_filesz = interp->sh_size;
1942 ph->p_memsz = interp->sh_size;
1943 ph->p_flags = PF_R;
1944 ph->p_align = interp->sh_addralign;
1947 /* if dynamic section, then add corresponing program header */
1948 if (dynamic) {
1949 ElfW(Sym) *sym_end;
1951 ph = &phdr[phnum - 1];
1953 ph->p_type = PT_DYNAMIC;
1954 ph->p_offset = dynamic->sh_offset;
1955 ph->p_vaddr = dynamic->sh_addr;
1956 ph->p_paddr = ph->p_vaddr;
1957 ph->p_filesz = dynamic->sh_size;
1958 ph->p_memsz = dynamic->sh_size;
1959 ph->p_flags = PF_R | PF_W;
1960 ph->p_align = dynamic->sh_addralign;
1962 /* put GOT dynamic section address */
1963 put32(s1->got->data, dynamic->sh_addr);
1965 /* relocate the PLT */
1966 if (file_type == TCC_OUTPUT_EXE
1967 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1968 || file_type == TCC_OUTPUT_DLL
1969 #endif
1971 uint8_t *p, *p_end;
1973 p = s1->plt->data;
1974 p_end = p + s1->plt->data_offset;
1975 if (p < p_end) {
1976 #if defined(TCC_TARGET_I386)
1977 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1978 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1979 p += 16;
1980 while (p < p_end) {
1981 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1982 p += 16;
1984 #elif defined(TCC_TARGET_X86_64)
1985 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1986 put32(p + 2, get32(p + 2) + x);
1987 put32(p + 8, get32(p + 8) + x - 6);
1988 p += 16;
1989 while (p < p_end) {
1990 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1991 p += 16;
1993 #elif defined(TCC_TARGET_ARM)
1994 int x;
1995 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1996 p +=16;
1997 while (p < p_end) {
1998 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1999 p += 16;
2001 #elif defined(TCC_TARGET_C67)
2002 /* XXX: TODO */
2003 #else
2004 #error unsupported CPU
2005 #endif
2009 /* relocate symbols in .dynsym */
2010 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
2011 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
2012 sym < sym_end;
2013 sym++) {
2014 if (sym->st_shndx == SHN_UNDEF) {
2015 /* relocate to the PLT if the symbol corresponds
2016 to a PLT entry */
2017 if (sym->st_value)
2018 sym->st_value += s1->plt->sh_addr;
2019 } else if (sym->st_shndx < SHN_LORESERVE) {
2020 /* do symbol relocation */
2021 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
2025 /* put dynamic section entries */
2026 dynamic->data_offset = saved_dynamic_data_offset;
2027 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
2028 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
2029 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2030 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
2031 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2032 #ifdef TCC_TARGET_X86_64
2033 put_dt(dynamic, DT_RELA, rel_addr);
2034 put_dt(dynamic, DT_RELASZ, rel_size);
2035 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2036 #else
2037 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2038 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2039 put_dt(dynamic, DT_PLTRELSZ, rel_size);
2040 put_dt(dynamic, DT_JMPREL, rel_addr);
2041 put_dt(dynamic, DT_PLTREL, DT_REL);
2042 put_dt(dynamic, DT_REL, bss_addr);
2043 put_dt(dynamic, DT_RELSZ, bss_size);
2044 #else
2045 put_dt(dynamic, DT_REL, rel_addr);
2046 put_dt(dynamic, DT_RELSZ, rel_size);
2047 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2048 #endif
2049 #endif
2050 if (s1->do_debug)
2051 put_dt(dynamic, DT_DEBUG, 0);
2052 put_dt(dynamic, DT_NULL, 0);
2055 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2056 ehdr.e_phnum = phnum;
2057 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2060 /* all other sections come after */
2061 for(i = 1; i < s1->nb_sections; i++) {
2062 s = s1->sections[i];
2063 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2064 continue;
2065 section_order[sh_order_index++] = i;
2067 file_offset = (file_offset + s->sh_addralign - 1) &
2068 ~(s->sh_addralign - 1);
2069 s->sh_offset = file_offset;
2070 if (s->sh_type != SHT_NOBITS)
2071 file_offset += s->sh_size;
2074 /* if building executable or DLL, then relocate each section
2075 except the GOT which is already relocated */
2076 if (file_type != TCC_OUTPUT_OBJ) {
2077 relocate_syms(s1, 0);
2079 if (s1->nb_errors != 0) {
2080 fail:
2081 ret = -1;
2082 goto the_end;
2085 /* relocate sections */
2086 /* XXX: ignore sections with allocated relocations ? */
2087 for(i = 1; i < s1->nb_sections; i++) {
2088 s = s1->sections[i];
2089 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
2090 relocate_section(s1, s);
2093 /* relocate relocation entries if the relocation tables are
2094 allocated in the executable */
2095 for(i = 1; i < s1->nb_sections; i++) {
2096 s = s1->sections[i];
2097 if ((s->sh_flags & SHF_ALLOC) &&
2098 s->sh_type == SHT_RELX) {
2099 relocate_rel(s1, s);
2103 /* get entry point address */
2104 if (file_type == TCC_OUTPUT_EXE)
2105 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
2106 else
2107 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2109 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2110 fill_got(s1);
2112 /* write elf file */
2113 if (file_type == TCC_OUTPUT_OBJ)
2114 mode = 0666;
2115 else
2116 mode = 0777;
2117 unlink(filename);
2118 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2119 if (fd < 0) {
2120 tcc_error_noabort("could not write '%s'", filename);
2121 goto fail;
2123 f = fdopen(fd, "wb");
2124 if (s1->verbose)
2125 printf("<- %s\n", filename);
2127 #ifdef TCC_TARGET_COFF
2128 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2129 tcc_output_coff(s1, f);
2130 } else
2131 #endif
2132 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2133 sort_syms(s1, symtab_section);
2135 /* align to 4 */
2136 file_offset = (file_offset + 3) & -4;
2138 /* fill header */
2139 ehdr.e_ident[0] = ELFMAG0;
2140 ehdr.e_ident[1] = ELFMAG1;
2141 ehdr.e_ident[2] = ELFMAG2;
2142 ehdr.e_ident[3] = ELFMAG3;
2143 ehdr.e_ident[4] = ELFCLASSW;
2144 ehdr.e_ident[5] = ELFDATA2LSB;
2145 ehdr.e_ident[6] = EV_CURRENT;
2146 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2147 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2148 #endif
2149 #ifdef TCC_TARGET_ARM
2150 #ifdef TCC_ARM_EABI
2151 ehdr.e_ident[EI_OSABI] = 0;
2152 ehdr.e_flags = 4 << 24;
2153 #else
2154 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2155 #endif
2156 #endif
2157 switch(file_type) {
2158 default:
2159 case TCC_OUTPUT_EXE:
2160 ehdr.e_type = ET_EXEC;
2161 break;
2162 case TCC_OUTPUT_DLL:
2163 ehdr.e_type = ET_DYN;
2164 break;
2165 case TCC_OUTPUT_OBJ:
2166 ehdr.e_type = ET_REL;
2167 break;
2169 ehdr.e_machine = EM_TCC_TARGET;
2170 ehdr.e_version = EV_CURRENT;
2171 ehdr.e_shoff = file_offset;
2172 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2173 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2174 ehdr.e_shnum = shnum;
2175 ehdr.e_shstrndx = shnum - 1;
2177 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2178 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2179 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2181 for(i=1;i<s1->nb_sections;i++) {
2182 s = s1->sections[section_order[i]];
2183 if (s->sh_type != SHT_NOBITS) {
2184 if (s->sh_type == SHT_DYNSYM)
2185 patch_dynsym_undef(s1, s);
2186 while (offset < s->sh_offset) {
2187 fputc(0, f);
2188 offset++;
2190 size = s->sh_size;
2191 fwrite(s->data, 1, size, f);
2192 offset += size;
2196 /* output section headers */
2197 while (offset < ehdr.e_shoff) {
2198 fputc(0, f);
2199 offset++;
2202 for(i=0;i<s1->nb_sections;i++) {
2203 sh = &shdr;
2204 memset(sh, 0, sizeof(ElfW(Shdr)));
2205 s = s1->sections[i];
2206 if (s) {
2207 sh->sh_name = s->sh_name;
2208 sh->sh_type = s->sh_type;
2209 sh->sh_flags = s->sh_flags;
2210 sh->sh_entsize = s->sh_entsize;
2211 sh->sh_info = s->sh_info;
2212 if (s->link)
2213 sh->sh_link = s->link->sh_num;
2214 sh->sh_addralign = s->sh_addralign;
2215 sh->sh_addr = s->sh_addr;
2216 sh->sh_offset = s->sh_offset;
2217 sh->sh_size = s->sh_size;
2219 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2221 } else {
2222 tcc_output_binary(s1, f, section_order);
2224 fclose(f);
2226 ret = 0;
2227 the_end:
2228 tcc_free(s1->symtab_to_dynsym);
2229 tcc_free(section_order);
2230 tcc_free(phdr);
2231 tcc_free(s1->got_offsets);
2232 return ret;
2235 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2237 int ret;
2238 #ifdef TCC_TARGET_PE
2239 if (s->output_type != TCC_OUTPUT_OBJ) {
2240 ret = pe_output_file(s, filename);
2241 } else
2242 #endif
2244 ret = elf_output_file(s, filename);
2246 return ret;
2249 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2251 void *data;
2253 data = tcc_malloc(size);
2254 lseek(fd, file_offset, SEEK_SET);
2255 read(fd, data, size);
2256 return data;
2259 typedef struct SectionMergeInfo {
2260 Section *s; /* corresponding existing section */
2261 unsigned long offset; /* offset of the new section in the existing section */
2262 uint8_t new_section; /* true if section 's' was added */
2263 uint8_t link_once; /* true if link once section */
2264 } SectionMergeInfo;
2266 /* load an object file and merge it with current files */
2267 /* XXX: handle correctly stab (debug) info */
2268 ST_FUNC int tcc_load_object_file(TCCState *s1,
2269 int fd, unsigned long file_offset)
2271 ElfW(Ehdr) ehdr;
2272 ElfW(Shdr) *shdr, *sh;
2273 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2274 unsigned char *strsec, *strtab;
2275 int *old_to_new_syms;
2276 char *sh_name, *name;
2277 SectionMergeInfo *sm_table, *sm;
2278 ElfW(Sym) *sym, *symtab;
2279 ElfW_Rel *rel, *rel_end;
2280 Section *s;
2282 int stab_index;
2283 int stabstr_index;
2285 stab_index = stabstr_index = 0;
2287 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2288 goto fail1;
2289 if (ehdr.e_ident[0] != ELFMAG0 ||
2290 ehdr.e_ident[1] != ELFMAG1 ||
2291 ehdr.e_ident[2] != ELFMAG2 ||
2292 ehdr.e_ident[3] != ELFMAG3)
2293 goto fail1;
2294 /* test if object file */
2295 if (ehdr.e_type != ET_REL)
2296 goto fail1;
2297 /* test CPU specific stuff */
2298 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2299 ehdr.e_machine != EM_TCC_TARGET) {
2300 fail1:
2301 tcc_error_noabort("invalid object file");
2302 return -1;
2304 /* read sections */
2305 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2306 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2307 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2309 /* load section names */
2310 sh = &shdr[ehdr.e_shstrndx];
2311 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2313 /* load symtab and strtab */
2314 old_to_new_syms = NULL;
2315 symtab = NULL;
2316 strtab = NULL;
2317 nb_syms = 0;
2318 for(i = 1; i < ehdr.e_shnum; i++) {
2319 sh = &shdr[i];
2320 if (sh->sh_type == SHT_SYMTAB) {
2321 if (symtab) {
2322 tcc_error_noabort("object must contain only one symtab");
2323 fail:
2324 ret = -1;
2325 goto the_end;
2327 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2328 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2329 sm_table[i].s = symtab_section;
2331 /* now load strtab */
2332 sh = &shdr[sh->sh_link];
2333 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2337 /* now examine each section and try to merge its content with the
2338 ones in memory */
2339 for(i = 1; i < ehdr.e_shnum; i++) {
2340 /* no need to examine section name strtab */
2341 if (i == ehdr.e_shstrndx)
2342 continue;
2343 sh = &shdr[i];
2344 sh_name = strsec + sh->sh_name;
2345 /* ignore sections types we do not handle */
2346 if (sh->sh_type != SHT_PROGBITS &&
2347 sh->sh_type != SHT_RELX &&
2348 #ifdef TCC_ARM_EABI
2349 sh->sh_type != SHT_ARM_EXIDX &&
2350 #endif
2351 sh->sh_type != SHT_NOBITS &&
2352 sh->sh_type != SHT_PREINIT_ARRAY &&
2353 sh->sh_type != SHT_INIT_ARRAY &&
2354 sh->sh_type != SHT_FINI_ARRAY &&
2355 strcmp(sh_name, ".stabstr")
2357 continue;
2358 if (sh->sh_addralign < 1)
2359 sh->sh_addralign = 1;
2360 /* find corresponding section, if any */
2361 for(j = 1; j < s1->nb_sections;j++) {
2362 s = s1->sections[j];
2363 if (!strcmp(s->name, sh_name)) {
2364 if (!strncmp(sh_name, ".gnu.linkonce",
2365 sizeof(".gnu.linkonce") - 1)) {
2366 /* if a 'linkonce' section is already present, we
2367 do not add it again. It is a little tricky as
2368 symbols can still be defined in
2369 it. */
2370 sm_table[i].link_once = 1;
2371 goto next;
2372 } else {
2373 goto found;
2377 /* not found: create new section */
2378 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2379 /* take as much info as possible from the section. sh_link and
2380 sh_info will be updated later */
2381 s->sh_addralign = sh->sh_addralign;
2382 s->sh_entsize = sh->sh_entsize;
2383 sm_table[i].new_section = 1;
2384 found:
2385 if (sh->sh_type != s->sh_type) {
2386 tcc_error_noabort("invalid section type");
2387 goto fail;
2390 /* align start of section */
2391 offset = s->data_offset;
2393 if (0 == strcmp(sh_name, ".stab")) {
2394 stab_index = i;
2395 goto no_align;
2397 if (0 == strcmp(sh_name, ".stabstr")) {
2398 stabstr_index = i;
2399 goto no_align;
2402 size = sh->sh_addralign - 1;
2403 offset = (offset + size) & ~size;
2404 if (sh->sh_addralign > s->sh_addralign)
2405 s->sh_addralign = sh->sh_addralign;
2406 s->data_offset = offset;
2407 no_align:
2408 sm_table[i].offset = offset;
2409 sm_table[i].s = s;
2410 /* concatenate sections */
2411 size = sh->sh_size;
2412 if (sh->sh_type != SHT_NOBITS) {
2413 unsigned char *ptr;
2414 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2415 ptr = section_ptr_add(s, size);
2416 read(fd, ptr, size);
2417 } else {
2418 s->data_offset += size;
2420 next: ;
2423 /* //gr relocate stab strings */
2424 if (stab_index && stabstr_index) {
2425 Stab_Sym *a, *b;
2426 unsigned o;
2427 s = sm_table[stab_index].s;
2428 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2429 b = (Stab_Sym *)(s->data + s->data_offset);
2430 o = sm_table[stabstr_index].offset;
2431 while (a < b)
2432 a->n_strx += o, a++;
2435 /* second short pass to update sh_link and sh_info fields of new
2436 sections */
2437 for(i = 1; i < ehdr.e_shnum; i++) {
2438 s = sm_table[i].s;
2439 if (!s || !sm_table[i].new_section)
2440 continue;
2441 sh = &shdr[i];
2442 if (sh->sh_link > 0)
2443 s->link = sm_table[sh->sh_link].s;
2444 if (sh->sh_type == SHT_RELX) {
2445 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2446 /* update backward link */
2447 s1->sections[s->sh_info]->reloc = s;
2450 sm = sm_table;
2452 /* resolve symbols */
2453 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2455 sym = symtab + 1;
2456 for(i = 1; i < nb_syms; i++, sym++) {
2457 if (sym->st_shndx != SHN_UNDEF &&
2458 sym->st_shndx < SHN_LORESERVE) {
2459 sm = &sm_table[sym->st_shndx];
2460 if (sm->link_once) {
2461 /* if a symbol is in a link once section, we use the
2462 already defined symbol. It is very important to get
2463 correct relocations */
2464 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2465 name = strtab + sym->st_name;
2466 sym_index = find_elf_sym(symtab_section, name);
2467 if (sym_index)
2468 old_to_new_syms[i] = sym_index;
2470 continue;
2472 /* if no corresponding section added, no need to add symbol */
2473 if (!sm->s)
2474 continue;
2475 /* convert section number */
2476 sym->st_shndx = sm->s->sh_num;
2477 /* offset value */
2478 sym->st_value += sm->offset;
2480 /* add symbol */
2481 name = strtab + sym->st_name;
2482 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2483 sym->st_info, sym->st_other,
2484 sym->st_shndx, name);
2485 old_to_new_syms[i] = sym_index;
2488 /* third pass to patch relocation entries */
2489 for(i = 1; i < ehdr.e_shnum; i++) {
2490 s = sm_table[i].s;
2491 if (!s)
2492 continue;
2493 sh = &shdr[i];
2494 offset = sm_table[i].offset;
2495 switch(s->sh_type) {
2496 case SHT_RELX:
2497 /* take relocation offset information */
2498 offseti = sm_table[sh->sh_info].offset;
2499 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2500 for(rel = (ElfW_Rel *)(s->data + offset);
2501 rel < rel_end;
2502 rel++) {
2503 int type;
2504 unsigned sym_index;
2505 /* convert symbol index */
2506 type = ELFW(R_TYPE)(rel->r_info);
2507 sym_index = ELFW(R_SYM)(rel->r_info);
2508 /* NOTE: only one symtab assumed */
2509 if (sym_index >= nb_syms)
2510 goto invalid_reloc;
2511 sym_index = old_to_new_syms[sym_index];
2512 /* ignore link_once in rel section. */
2513 if (!sym_index && !sm->link_once
2514 #ifdef TCC_TARGET_ARM
2515 && type != R_ARM_V4BX
2516 #endif
2518 invalid_reloc:
2519 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2520 i, strsec + sh->sh_name, rel->r_offset);
2521 goto fail;
2523 rel->r_info = ELFW(R_INFO)(sym_index, type);
2524 /* offset the relocation offset */
2525 rel->r_offset += offseti;
2527 break;
2528 default:
2529 break;
2533 ret = 0;
2534 the_end:
2535 tcc_free(symtab);
2536 tcc_free(strtab);
2537 tcc_free(old_to_new_syms);
2538 tcc_free(sm_table);
2539 tcc_free(strsec);
2540 tcc_free(shdr);
2541 return ret;
2544 typedef struct ArchiveHeader {
2545 char ar_name[16]; /* name of this member */
2546 char ar_date[12]; /* file mtime */
2547 char ar_uid[6]; /* owner uid; printed as decimal */
2548 char ar_gid[6]; /* owner gid; printed as decimal */
2549 char ar_mode[8]; /* file mode, printed as octal */
2550 char ar_size[10]; /* file size, printed as decimal */
2551 char ar_fmag[2]; /* should contain ARFMAG */
2552 } ArchiveHeader;
2554 static int get_be32(const uint8_t *b)
2556 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2559 /* load only the objects which resolve undefined symbols */
2560 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2562 int i, bound, nsyms, sym_index, off, ret;
2563 uint8_t *data;
2564 const char *ar_names, *p;
2565 const uint8_t *ar_index;
2566 ElfW(Sym) *sym;
2568 data = tcc_malloc(size);
2569 if (read(fd, data, size) != size)
2570 goto fail;
2571 nsyms = get_be32(data);
2572 ar_index = data + 4;
2573 ar_names = ar_index + nsyms * 4;
2575 do {
2576 bound = 0;
2577 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2578 sym_index = find_elf_sym(symtab_section, p);
2579 if(sym_index) {
2580 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2581 if(sym->st_shndx == SHN_UNDEF) {
2582 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2583 #if 0
2584 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2585 #endif
2586 ++bound;
2587 lseek(fd, off, SEEK_SET);
2588 if(tcc_load_object_file(s1, fd, off) < 0) {
2589 fail:
2590 ret = -1;
2591 goto the_end;
2596 } while(bound);
2597 ret = 0;
2598 the_end:
2599 tcc_free(data);
2600 return ret;
2603 /* load a '.a' file */
2604 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2606 ArchiveHeader hdr;
2607 char ar_size[11];
2608 char ar_name[17];
2609 char magic[8];
2610 int size, len, i;
2611 unsigned long file_offset;
2613 /* skip magic which was already checked */
2614 read(fd, magic, sizeof(magic));
2616 for(;;) {
2617 len = read(fd, &hdr, sizeof(hdr));
2618 if (len == 0)
2619 break;
2620 if (len != sizeof(hdr)) {
2621 tcc_error_noabort("invalid archive");
2622 return -1;
2624 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2625 ar_size[sizeof(hdr.ar_size)] = '\0';
2626 size = strtol(ar_size, NULL, 0);
2627 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2628 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2629 if (ar_name[i] != ' ')
2630 break;
2632 ar_name[i + 1] = '\0';
2633 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2634 file_offset = lseek(fd, 0, SEEK_CUR);
2635 /* align to even */
2636 size = (size + 1) & ~1;
2637 if (!strcmp(ar_name, "/")) {
2638 /* coff symbol table : we handle it */
2639 if(s1->alacarte_link)
2640 return tcc_load_alacarte(s1, fd, size);
2641 } else if (!strcmp(ar_name, "//") ||
2642 !strcmp(ar_name, "__.SYMDEF") ||
2643 !strcmp(ar_name, "__.SYMDEF/") ||
2644 !strcmp(ar_name, "ARFILENAMES/")) {
2645 /* skip symbol table or archive names */
2646 } else {
2647 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2648 return -1;
2650 lseek(fd, file_offset + size, SEEK_SET);
2652 return 0;
2655 #ifndef TCC_TARGET_PE
2656 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2657 is referenced by the user (so it should be added as DT_NEEDED in
2658 the generated ELF file) */
2659 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2661 ElfW(Ehdr) ehdr;
2662 ElfW(Shdr) *shdr, *sh, *sh1;
2663 int i, j, nb_syms, nb_dts, sym_bind, ret;
2664 ElfW(Sym) *sym, *dynsym;
2665 ElfW(Dyn) *dt, *dynamic;
2666 unsigned char *dynstr;
2667 const char *name, *soname;
2668 DLLReference *dllref;
2670 read(fd, &ehdr, sizeof(ehdr));
2672 /* test CPU specific stuff */
2673 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2674 ehdr.e_machine != EM_TCC_TARGET) {
2675 tcc_error_noabort("bad architecture");
2676 return -1;
2679 /* read sections */
2680 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2682 /* load dynamic section and dynamic symbols */
2683 nb_syms = 0;
2684 nb_dts = 0;
2685 dynamic = NULL;
2686 dynsym = NULL; /* avoid warning */
2687 dynstr = NULL; /* avoid warning */
2688 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2689 switch(sh->sh_type) {
2690 case SHT_DYNAMIC:
2691 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2692 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2693 break;
2694 case SHT_DYNSYM:
2695 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2696 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2697 sh1 = &shdr[sh->sh_link];
2698 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2699 break;
2700 default:
2701 break;
2705 /* compute the real library name */
2706 soname = tcc_basename(filename);
2708 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2709 if (dt->d_tag == DT_SONAME) {
2710 soname = dynstr + dt->d_un.d_val;
2714 /* if the dll is already loaded, do not load it */
2715 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2716 dllref = s1->loaded_dlls[i];
2717 if (!strcmp(soname, dllref->name)) {
2718 /* but update level if needed */
2719 if (level < dllref->level)
2720 dllref->level = level;
2721 ret = 0;
2722 goto the_end;
2726 // printf("loading dll '%s'\n", soname);
2728 /* add the dll and its level */
2729 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2730 dllref->level = level;
2731 strcpy(dllref->name, soname);
2732 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2734 /* add dynamic symbols in dynsym_section */
2735 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2736 sym_bind = ELFW(ST_BIND)(sym->st_info);
2737 if (sym_bind == STB_LOCAL)
2738 continue;
2739 name = dynstr + sym->st_name;
2740 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2741 sym->st_info, sym->st_other, sym->st_shndx, name);
2744 /* load all referenced DLLs */
2745 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2746 switch(dt->d_tag) {
2747 case DT_NEEDED:
2748 name = dynstr + dt->d_un.d_val;
2749 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2750 dllref = s1->loaded_dlls[j];
2751 if (!strcmp(name, dllref->name))
2752 goto already_loaded;
2754 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2755 tcc_error_noabort("referenced dll '%s' not found", name);
2756 ret = -1;
2757 goto the_end;
2759 already_loaded:
2760 break;
2763 ret = 0;
2764 the_end:
2765 tcc_free(dynstr);
2766 tcc_free(dynsym);
2767 tcc_free(dynamic);
2768 tcc_free(shdr);
2769 return ret;
2772 #define LD_TOK_NAME 256
2773 #define LD_TOK_EOF (-1)
2775 /* return next ld script token */
2776 static int ld_next(TCCState *s1, char *name, int name_size)
2778 int c;
2779 char *q;
2781 redo:
2782 switch(ch) {
2783 case ' ':
2784 case '\t':
2785 case '\f':
2786 case '\v':
2787 case '\r':
2788 case '\n':
2789 inp();
2790 goto redo;
2791 case '/':
2792 minp();
2793 if (ch == '*') {
2794 file->buf_ptr = parse_comment(file->buf_ptr);
2795 ch = file->buf_ptr[0];
2796 goto redo;
2797 } else {
2798 q = name;
2799 *q++ = '/';
2800 goto parse_name;
2802 break;
2803 /* case 'a' ... 'z': */
2804 case 'a':
2805 case 'b':
2806 case 'c':
2807 case 'd':
2808 case 'e':
2809 case 'f':
2810 case 'g':
2811 case 'h':
2812 case 'i':
2813 case 'j':
2814 case 'k':
2815 case 'l':
2816 case 'm':
2817 case 'n':
2818 case 'o':
2819 case 'p':
2820 case 'q':
2821 case 'r':
2822 case 's':
2823 case 't':
2824 case 'u':
2825 case 'v':
2826 case 'w':
2827 case 'x':
2828 case 'y':
2829 case 'z':
2830 /* case 'A' ... 'z': */
2831 case 'A':
2832 case 'B':
2833 case 'C':
2834 case 'D':
2835 case 'E':
2836 case 'F':
2837 case 'G':
2838 case 'H':
2839 case 'I':
2840 case 'J':
2841 case 'K':
2842 case 'L':
2843 case 'M':
2844 case 'N':
2845 case 'O':
2846 case 'P':
2847 case 'Q':
2848 case 'R':
2849 case 'S':
2850 case 'T':
2851 case 'U':
2852 case 'V':
2853 case 'W':
2854 case 'X':
2855 case 'Y':
2856 case 'Z':
2857 case '_':
2858 case '\\':
2859 case '.':
2860 case '$':
2861 case '~':
2862 q = name;
2863 parse_name:
2864 for(;;) {
2865 if (!((ch >= 'a' && ch <= 'z') ||
2866 (ch >= 'A' && ch <= 'Z') ||
2867 (ch >= '0' && ch <= '9') ||
2868 strchr("/.-_+=$:\\,~", ch)))
2869 break;
2870 if ((q - name) < name_size - 1) {
2871 *q++ = ch;
2873 minp();
2875 *q = '\0';
2876 c = LD_TOK_NAME;
2877 break;
2878 case CH_EOF:
2879 c = LD_TOK_EOF;
2880 break;
2881 default:
2882 c = ch;
2883 inp();
2884 break;
2886 #if 0
2887 printf("tok=%c %d\n", c, c);
2888 if (c == LD_TOK_NAME)
2889 printf(" name=%s\n", name);
2890 #endif
2891 return c;
2895 * Extract the file name from the library name
2897 * /!\ No test on filename capacity, be careful
2899 static void libname_to_filename(TCCState *s1, const char libname[], char filename[])
2901 if (!s1->static_link) {
2902 sprintf(filename, "lib%s.so", libname);
2903 } else {
2904 sprintf(filename, "lib%s.a", libname);
2908 static int ld_add_file(TCCState *s1, const char filename[])
2910 int ret;
2912 ret = tcc_add_file_internal(s1, filename, 0);
2913 if (ret)
2914 ret = tcc_add_dll(s1, filename, 0);
2915 return ret;
2918 static inline int new_undef_syms(void)
2920 int ret = 0;
2921 ret = new_undef_sym;
2922 new_undef_sym = 0;
2923 return ret;
2926 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
2928 char filename[1024], libname[1024];
2929 int t, group, nblibs = 0, ret = 0;
2930 char **libs = NULL;
2932 group = !strcmp(cmd, "GROUP");
2933 if (!as_needed)
2934 new_undef_syms();
2935 t = ld_next(s1, filename, sizeof(filename));
2936 if (t != '(')
2937 expect("(");
2938 t = ld_next(s1, filename, sizeof(filename));
2939 for(;;) {
2940 libname[0] = '\0';
2941 if (t == LD_TOK_EOF) {
2942 tcc_error_noabort("unexpected end of file");
2943 ret = -1;
2944 goto lib_parse_error;
2945 } else if (t == ')') {
2946 break;
2947 } else if (t == '-') {
2948 t = ld_next(s1, filename, sizeof(filename));
2949 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
2950 tcc_error_noabort("library name expected");
2951 ret = -1;
2952 goto lib_parse_error;
2954 strcpy(libname, &filename[1]);
2955 libname_to_filename(s1, libname, filename);
2956 } else if (t != LD_TOK_NAME) {
2957 tcc_error_noabort("filename expected");
2958 ret = -1;
2959 goto lib_parse_error;
2961 if (!strcmp(filename, "AS_NEEDED")) {
2962 ret = ld_add_file_list(s1, cmd, 1);
2963 if (ret)
2964 goto lib_parse_error;
2965 } else {
2966 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2967 if (!as_needed) {
2968 ret = ld_add_file(s1, filename);
2969 if (ret)
2970 goto lib_parse_error;
2971 if (group) {
2972 /* Add the filename *and* the libname to avoid future conversions */
2973 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
2974 if (libname[0] != '\0')
2975 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
2979 t = ld_next(s1, filename, sizeof(filename));
2980 if (t == ',') {
2981 t = ld_next(s1, filename, sizeof(filename));
2984 if (group && !as_needed) {
2985 while (new_undef_syms()) {
2986 int i;
2988 for (i = 0; i < nblibs; i ++)
2989 ld_add_file(s1, libs[i]);
2992 lib_parse_error:
2993 dynarray_reset(&libs, &nblibs);
2994 return ret;
2997 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
2998 files */
2999 ST_FUNC int tcc_load_ldscript(TCCState *s1)
3001 char cmd[64];
3002 char filename[1024];
3003 int t, ret;
3005 ch = file->buf_ptr[0];
3006 ch = handle_eob();
3007 for(;;) {
3008 t = ld_next(s1, cmd, sizeof(cmd));
3009 if (t == LD_TOK_EOF)
3010 return 0;
3011 else if (t != LD_TOK_NAME)
3012 return -1;
3013 if (!strcmp(cmd, "INPUT") ||
3014 !strcmp(cmd, "GROUP")) {
3015 ret = ld_add_file_list(s1, cmd, 0);
3016 if (ret)
3017 return ret;
3018 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3019 !strcmp(cmd, "TARGET")) {
3020 /* ignore some commands */
3021 t = ld_next(s1, cmd, sizeof(cmd));
3022 if (t != '(')
3023 expect("(");
3024 for(;;) {
3025 t = ld_next(s1, filename, sizeof(filename));
3026 if (t == LD_TOK_EOF) {
3027 tcc_error_noabort("unexpected end of file");
3028 return -1;
3029 } else if (t == ')') {
3030 break;
3033 } else {
3034 return -1;
3037 return 0;
3039 #endif /* ndef TCC_TARGET_PE */