Fix R_ARM_CALL when target fonction is Thumb
[tinycc.git] / tccelf.c
blob794376323707e64011de6f0bee847befc8275860
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;
605 x = (*(int *)ptr)&0xffffff;
606 (*(int *)ptr) &= 0xff000000;
607 if (x & 0x800000)
608 x -= 0x1000000;
609 x <<= 2;
610 is_thumb = val & 1;
611 is_call = (type == R_ARM_CALL);
612 x += (val & -2) - addr;
613 h = x & 2;
614 #ifndef TCC_TARGET_PE
615 if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
616 if (s1->output_type == TCC_OUTPUT_MEMORY)
617 x += add_jmp_table(s1, val) - val; /* add veneer */
618 #endif
619 if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
620 if (!(h && is_call && is_thumb))
621 tcc_error("can't relocate value at %x",addr);
622 x >>= 2;
623 x &= 0xffffff;
624 if (is_call && is_thumb) {
625 x |= h << 24;
626 (*(int *)ptr) = 0xfa << 24; /* bl -> blx */
628 (*(int *)ptr) |= x;
630 break;
631 case R_ARM_MOVT_ABS:
632 case R_ARM_MOVW_ABS_NC:
634 int x, imm4, imm12;
635 if (type == R_ARM_MOVT_ABS)
636 val >>= 16;
637 imm12 = val & 0xfff;
638 imm4 = (val >> 12) & 0xf;
639 x = (imm4 << 16) | imm12;
640 if (type == R_ARM_THM_MOVT_ABS)
641 *(int *)ptr |= x;
642 else
643 *(int *)ptr += x;
645 break;
646 case R_ARM_THM_MOVT_ABS:
647 case R_ARM_THM_MOVW_ABS_NC:
649 int x, i, imm4, imm3, imm8;
650 if (type == R_ARM_THM_MOVT_ABS)
651 val >>= 16;
652 imm8 = val & 0xff;
653 imm3 = (val >> 8) & 0x7;
654 i = (val >> 11) & 1;
655 imm4 = (val >> 12) & 0xf;
656 x = (imm3 << 28) | (imm8 << 16) | (i << 10) | imm4;
657 if (type == R_ARM_THM_MOVT_ABS)
658 *(int *)ptr |= x;
659 else
660 *(int *)ptr += x;
662 break;
663 case R_ARM_PREL31:
665 int x;
666 x = (*(int *)ptr) & 0x7fffffff;
667 (*(int *)ptr) &= 0x80000000;
668 x = (x * 2) / 2;
669 x += val - addr;
670 if((x^(x>>1))&0x40000000)
671 tcc_error("can't relocate value at %x",addr);
672 (*(int *)ptr) |= x & 0x7fffffff;
674 case R_ARM_ABS32:
675 *(int *)ptr += val;
676 break;
677 case R_ARM_REL32:
678 *(int *)ptr += val - addr;
679 break;
680 case R_ARM_BASE_PREL:
681 *(int *)ptr += s1->got->sh_addr - addr;
682 break;
683 case R_ARM_GOTOFF32:
684 *(int *)ptr += val - s1->got->sh_addr;
685 break;
686 case R_ARM_GOT_BREL:
687 /* we load the got offset */
688 *(int *)ptr += s1->got_offsets[sym_index];
689 break;
690 case R_ARM_COPY:
691 break;
692 case R_ARM_V4BX:
693 /* trade Thumb support for ARMv4 support */
694 if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
695 *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
696 break;
697 default:
698 fprintf(stderr,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
699 type, (unsigned)addr, (unsigned)(uplong)ptr, (unsigned)val);
700 break;
701 #elif defined(TCC_TARGET_C67)
702 case R_C60_32:
703 *(int *)ptr += val;
704 break;
705 case R_C60LO16:
707 uint32_t orig;
709 /* put the low 16 bits of the absolute address */
710 // add to what is already there
712 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
713 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
715 //patch both at once - assumes always in pairs Low - High
717 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
718 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
720 break;
721 case R_C60HI16:
722 break;
723 default:
724 fprintf(stderr,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
725 type, (unsigned)addr, (unsigned)(uplong)ptr, (unsigned)val);
726 break;
727 #elif defined(TCC_TARGET_X86_64)
728 case R_X86_64_64:
729 if (s1->output_type == TCC_OUTPUT_DLL) {
730 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
731 qrel->r_addend = *(long long *)ptr + val;
732 qrel++;
734 *(long long *)ptr += val;
735 break;
736 case R_X86_64_32:
737 case R_X86_64_32S:
738 if (s1->output_type == TCC_OUTPUT_DLL) {
739 /* XXX: this logic may depend on TCC's codegen
740 now TCC uses R_X86_64_32 even for a 64bit pointer */
741 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
742 qrel->r_addend = *(int *)ptr + val;
743 qrel++;
745 *(int *)ptr += val;
746 break;
748 case R_X86_64_PC32:
749 if (s1->output_type == TCC_OUTPUT_DLL) {
750 /* DLL relocation */
751 esym_index = s1->symtab_to_dynsym[sym_index];
752 if (esym_index) {
753 qrel->r_offset = rel->r_offset;
754 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
755 qrel->r_addend = *(int *)ptr;
756 qrel++;
757 break;
760 /* fall through */
761 case R_X86_64_PLT32: {
762 long long diff;
763 diff = (long long)val - addr;
764 if (diff <= -2147483647 || diff > 2147483647) {
765 #ifndef TCC_TARGET_PE
766 /* XXX: naive support for over 32bit jump */
767 if (s1->output_type == TCC_OUTPUT_MEMORY) {
768 val = (add_jmp_table(s1, val - rel->r_addend) +
769 rel->r_addend);
770 diff = val - addr;
772 #endif
773 if (diff <= -2147483647 || diff > 2147483647) {
774 tcc_error("internal error: relocation failed");
777 *(int *)ptr += diff;
779 break;
780 case R_X86_64_GLOB_DAT:
781 case R_X86_64_JUMP_SLOT:
782 /* They don't need addend */
783 *(int *)ptr = val - rel->r_addend;
784 break;
785 case R_X86_64_GOTPCREL:
786 #ifndef TCC_TARGET_PE
787 if (s1->output_type == TCC_OUTPUT_MEMORY) {
788 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
789 *(int *)ptr += val - addr;
790 break;
792 #endif
793 *(int *)ptr += (s1->got->sh_addr - addr +
794 s1->got_offsets[sym_index] - 4);
795 break;
796 case R_X86_64_GOTTPOFF:
797 *(int *)ptr += val - s1->got->sh_addr;
798 break;
799 case R_X86_64_GOT32:
800 /* we load the got offset */
801 *(int *)ptr += s1->got_offsets[sym_index];
802 break;
803 #else
804 #error unsupported processor
805 #endif
808 /* if the relocation is allocated, we change its symbol table */
809 if (sr->sh_flags & SHF_ALLOC)
810 sr->link = s1->dynsym;
813 /* relocate relocation table in 'sr' */
814 static void relocate_rel(TCCState *s1, Section *sr)
816 Section *s;
817 ElfW_Rel *rel, *rel_end;
819 s = s1->sections[sr->sh_info];
820 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
821 for(rel = (ElfW_Rel *)sr->data;
822 rel < rel_end;
823 rel++) {
824 rel->r_offset += s->sh_addr;
828 /* count the number of dynamic relocations so that we can reserve
829 their space */
830 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
832 ElfW_Rel *rel, *rel_end;
833 int sym_index, esym_index, type, count;
835 count = 0;
836 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
837 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
838 sym_index = ELFW(R_SYM)(rel->r_info);
839 type = ELFW(R_TYPE)(rel->r_info);
840 switch(type) {
841 #if defined(TCC_TARGET_I386)
842 case R_386_32:
843 #elif defined(TCC_TARGET_X86_64)
844 case R_X86_64_32:
845 case R_X86_64_32S:
846 case R_X86_64_64:
847 #endif
848 count++;
849 break;
850 #if defined(TCC_TARGET_I386)
851 case R_386_PC32:
852 #elif defined(TCC_TARGET_X86_64)
853 case R_X86_64_PC32:
854 #endif
855 esym_index = s1->symtab_to_dynsym[sym_index];
856 if (esym_index)
857 count++;
858 break;
859 default:
860 break;
863 if (count) {
864 /* allocate the section */
865 sr->sh_flags |= SHF_ALLOC;
866 sr->sh_size = count * sizeof(ElfW_Rel);
868 return count;
871 static void put_got_offset(TCCState *s1, int index, unsigned long val)
873 int n;
874 unsigned long *tab;
876 if (index >= s1->nb_got_offsets) {
877 /* find immediately bigger power of 2 and reallocate array */
878 n = 1;
879 while (index >= n)
880 n *= 2;
881 tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
882 s1->got_offsets = tab;
883 memset(s1->got_offsets + s1->nb_got_offsets, 0,
884 (n - s1->nb_got_offsets) * sizeof(unsigned long));
885 s1->nb_got_offsets = n;
887 s1->got_offsets[index] = val;
890 /* XXX: suppress that */
891 static void put32(unsigned char *p, uint32_t val)
893 p[0] = val;
894 p[1] = val >> 8;
895 p[2] = val >> 16;
896 p[3] = val >> 24;
899 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
900 defined(TCC_TARGET_X86_64)
901 static uint32_t get32(unsigned char *p)
903 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
905 #endif
907 static void build_got(TCCState *s1)
909 unsigned char *ptr;
911 /* if no got, then create it */
912 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
913 s1->got->sh_entsize = 4;
914 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
915 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
916 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
917 #if PTR_SIZE == 4
918 /* keep space for _DYNAMIC pointer, if present */
919 put32(ptr, 0);
920 /* two dummy got entries */
921 put32(ptr + 4, 0);
922 put32(ptr + 8, 0);
923 #else
924 /* keep space for _DYNAMIC pointer, if present */
925 put32(ptr, 0);
926 put32(ptr + 4, 0);
927 /* two dummy got entries */
928 put32(ptr + 8, 0);
929 put32(ptr + 12, 0);
930 put32(ptr + 16, 0);
931 put32(ptr + 20, 0);
932 #endif
935 /* put a got entry corresponding to a symbol in symtab_section. 'size'
936 and 'info' can be modifed if more precise info comes from the DLL */
937 static void put_got_entry(TCCState *s1,
938 int reloc_type, unsigned long size, int info,
939 int sym_index)
941 int index;
942 const char *name;
943 ElfW(Sym) *sym;
944 unsigned long offset;
945 int *ptr;
947 if (!s1->got)
948 build_got(s1);
950 /* if a got entry already exists for that symbol, no need to add one */
951 if (sym_index < s1->nb_got_offsets &&
952 s1->got_offsets[sym_index] != 0)
953 return;
955 put_got_offset(s1, sym_index, s1->got->data_offset);
957 if (s1->dynsym) {
958 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
959 name = symtab_section->link->data + sym->st_name;
960 offset = sym->st_value;
961 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
962 if (reloc_type ==
963 #ifdef TCC_TARGET_X86_64
964 R_X86_64_JUMP_SLOT
965 #else
966 R_386_JMP_SLOT
967 #endif
969 Section *plt;
970 uint8_t *p;
971 int modrm;
973 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
974 modrm = 0x25;
975 #else
976 /* if we build a DLL, we add a %ebx offset */
977 if (s1->output_type == TCC_OUTPUT_DLL)
978 modrm = 0xa3;
979 else
980 modrm = 0x25;
981 #endif
983 /* add a PLT entry */
984 plt = s1->plt;
985 if (plt->data_offset == 0) {
986 /* first plt entry */
987 p = section_ptr_add(plt, 16);
988 p[0] = 0xff; /* pushl got + PTR_SIZE */
989 p[1] = modrm + 0x10;
990 put32(p + 2, PTR_SIZE);
991 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
992 p[7] = modrm;
993 put32(p + 8, PTR_SIZE * 2);
996 p = section_ptr_add(plt, 16);
997 p[0] = 0xff; /* jmp *(got + x) */
998 p[1] = modrm;
999 put32(p + 2, s1->got->data_offset);
1000 p[6] = 0x68; /* push $xxx */
1001 put32(p + 7, (plt->data_offset - 32) >> 1);
1002 p[11] = 0xe9; /* jmp plt_start */
1003 put32(p + 12, -(plt->data_offset));
1005 /* the symbol is modified so that it will be relocated to
1006 the PLT */
1007 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
1008 if (s1->output_type == TCC_OUTPUT_EXE)
1009 #endif
1010 offset = plt->data_offset - 16;
1012 #elif defined(TCC_TARGET_ARM)
1013 if (reloc_type == R_ARM_JUMP_SLOT) {
1014 Section *plt;
1015 uint8_t *p;
1017 /* if we build a DLL, we add a %ebx offset */
1018 if (s1->output_type == TCC_OUTPUT_DLL)
1019 tcc_error("DLLs unimplemented!");
1021 /* add a PLT entry */
1022 plt = s1->plt;
1023 if (plt->data_offset == 0) {
1024 /* first plt entry */
1025 p = section_ptr_add(plt, 16);
1026 put32(p , 0xe52de004);
1027 put32(p + 4, 0xe59fe010);
1028 put32(p + 8, 0xe08fe00e);
1029 put32(p + 12, 0xe5bef008);
1032 p = section_ptr_add(plt, 16);
1033 put32(p , 0xe59fc004);
1034 put32(p+4, 0xe08fc00c);
1035 put32(p+8, 0xe59cf000);
1036 put32(p+12, s1->got->data_offset);
1038 /* the symbol is modified so that it will be relocated to
1039 the PLT */
1040 if (s1->output_type == TCC_OUTPUT_EXE)
1041 offset = plt->data_offset - 16;
1043 #elif defined(TCC_TARGET_C67)
1044 tcc_error("C67 got not implemented");
1045 #else
1046 #error unsupported CPU
1047 #endif
1048 index = put_elf_sym(s1->dynsym, offset,
1049 size, info, 0, sym->st_shndx, name);
1050 /* put a got entry */
1051 put_elf_reloc(s1->dynsym, s1->got,
1052 s1->got->data_offset,
1053 reloc_type, index);
1055 ptr = section_ptr_add(s1->got, PTR_SIZE);
1056 *ptr = 0;
1059 /* build GOT and PLT entries */
1060 ST_FUNC void build_got_entries(TCCState *s1)
1062 Section *s;
1063 ElfW_Rel *rel, *rel_end;
1064 ElfW(Sym) *sym;
1065 int i, type, reloc_type, sym_index;
1067 for(i = 1; i < s1->nb_sections; i++) {
1068 s = s1->sections[i];
1069 if (s->sh_type != SHT_RELX)
1070 continue;
1071 /* no need to handle got relocations */
1072 if (s->link != symtab_section)
1073 continue;
1074 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1075 for(rel = (ElfW_Rel *)s->data;
1076 rel < rel_end;
1077 rel++) {
1078 type = ELFW(R_TYPE)(rel->r_info);
1079 switch(type) {
1080 #if defined(TCC_TARGET_I386)
1081 case R_386_GOT32:
1082 case R_386_GOTOFF:
1083 case R_386_GOTPC:
1084 case R_386_PLT32:
1085 if (!s1->got)
1086 build_got(s1);
1087 if (type == R_386_GOT32 || type == R_386_PLT32) {
1088 sym_index = ELFW(R_SYM)(rel->r_info);
1089 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1090 /* look at the symbol got offset. If none, then add one */
1091 if (type == R_386_GOT32)
1092 reloc_type = R_386_GLOB_DAT;
1093 else
1094 reloc_type = R_386_JMP_SLOT;
1095 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1096 sym_index);
1098 break;
1099 #elif defined(TCC_TARGET_ARM)
1100 case R_ARM_GOT_BREL:
1101 case R_ARM_GOTOFF32:
1102 case R_ARM_BASE_PREL:
1103 case R_ARM_PLT32:
1104 if (!s1->got)
1105 build_got(s1);
1106 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1107 sym_index = ELFW(R_SYM)(rel->r_info);
1108 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1109 /* look at the symbol got offset. If none, then add one */
1110 if (type == R_ARM_GOT_BREL)
1111 reloc_type = R_ARM_GLOB_DAT;
1112 else
1113 reloc_type = R_ARM_JUMP_SLOT;
1114 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1115 sym_index);
1117 break;
1118 #elif defined(TCC_TARGET_C67)
1119 case R_C60_GOT32:
1120 case R_C60_GOTOFF:
1121 case R_C60_GOTPC:
1122 case R_C60_PLT32:
1123 if (!s1->got)
1124 build_got(s1);
1125 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1126 sym_index = ELFW(R_SYM)(rel->r_info);
1127 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1128 /* look at the symbol got offset. If none, then add one */
1129 if (type == R_C60_GOT32)
1130 reloc_type = R_C60_GLOB_DAT;
1131 else
1132 reloc_type = R_C60_JMP_SLOT;
1133 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1134 sym_index);
1136 break;
1137 #elif defined(TCC_TARGET_X86_64)
1138 case R_X86_64_GOT32:
1139 case R_X86_64_GOTTPOFF:
1140 case R_X86_64_GOTPCREL:
1141 case R_X86_64_PLT32:
1142 if (!s1->got)
1143 build_got(s1);
1144 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1145 type == R_X86_64_PLT32) {
1146 sym_index = ELFW(R_SYM)(rel->r_info);
1147 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1148 /* look at the symbol got offset. If none, then add one */
1149 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1150 reloc_type = R_X86_64_GLOB_DAT;
1151 else
1152 reloc_type = R_X86_64_JUMP_SLOT;
1153 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1154 sym_index);
1156 break;
1157 #else
1158 #error unsupported CPU
1159 #endif
1160 default:
1161 break;
1167 ST_FUNC Section *new_symtab(TCCState *s1,
1168 const char *symtab_name, int sh_type, int sh_flags,
1169 const char *strtab_name,
1170 const char *hash_name, int hash_sh_flags)
1172 Section *symtab, *strtab, *hash;
1173 int *ptr, nb_buckets;
1175 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1176 symtab->sh_entsize = sizeof(ElfW(Sym));
1177 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1178 put_elf_str(strtab, "");
1179 symtab->link = strtab;
1180 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1182 nb_buckets = 1;
1184 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1185 hash->sh_entsize = sizeof(int);
1186 symtab->hash = hash;
1187 hash->link = symtab;
1189 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1190 ptr[0] = nb_buckets;
1191 ptr[1] = 1;
1192 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1193 return symtab;
1196 /* put dynamic tag */
1197 static void put_dt(Section *dynamic, int dt, uplong val)
1199 ElfW(Dyn) *dyn;
1200 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1201 dyn->d_tag = dt;
1202 dyn->d_un.d_val = val;
1205 static void add_init_array_defines(TCCState *s1, const char *section_name)
1207 Section *s;
1208 long end_offset;
1209 char sym_start[1024];
1210 char sym_end[1024];
1212 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1213 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1215 s = find_section(s1, section_name);
1216 if (!s) {
1217 end_offset = 0;
1218 s = data_section;
1219 } else {
1220 end_offset = s->data_offset;
1223 add_elf_sym(symtab_section,
1224 0, 0,
1225 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1226 s->sh_num, sym_start);
1227 add_elf_sym(symtab_section,
1228 end_offset, 0,
1229 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1230 s->sh_num, sym_end);
1233 static int tcc_add_support(TCCState *s1, const char *filename)
1235 char buf[1024];
1236 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, filename);
1237 return tcc_add_file(s1, buf);
1240 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1242 #ifdef CONFIG_TCC_BCHECK
1243 unsigned long *ptr;
1244 Section *init_section;
1245 unsigned char *pinit;
1246 int sym_index;
1248 if (0 == s1->do_bounds_check)
1249 return;
1251 /* XXX: add an object file to do that */
1252 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1253 *ptr = 0;
1254 add_elf_sym(symtab_section, 0, 0,
1255 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1256 bounds_section->sh_num, "__bounds_start");
1257 /* add bound check code */
1258 #ifndef TCC_TARGET_PE
1259 tcc_add_support(s1, "bcheck.o");
1260 #endif
1261 #ifdef TCC_TARGET_I386
1262 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1263 /* add 'call __bound_init()' in .init section */
1264 init_section = find_section(s1, ".init");
1265 pinit = section_ptr_add(init_section, 5);
1266 pinit[0] = 0xe8;
1267 put32(pinit + 1, -4);
1268 sym_index = find_elf_sym(symtab_section, "__bound_init");
1269 put_elf_reloc(symtab_section, init_section,
1270 init_section->data_offset - 4, R_386_PC32, sym_index);
1272 #endif
1273 #endif
1276 /* add tcc runtime libraries */
1277 ST_FUNC void tcc_add_runtime(TCCState *s1)
1279 tcc_add_bcheck(s1);
1281 /* add libc */
1282 if (!s1->nostdlib) {
1283 tcc_add_library(s1, "c");
1284 #ifdef CONFIG_USE_LIBGCC
1285 tcc_add_file(s1, TCC_LIBGCC);
1286 #elif !defined WITHOUT_LIBTCC
1287 tcc_add_support(s1, "libtcc1.a");
1288 #endif
1289 /* add crt end if not memory output */
1290 if (s1->output_type != TCC_OUTPUT_MEMORY)
1291 tcc_add_crt(s1, "crtn.o");
1295 /* add various standard linker symbols (must be done after the
1296 sections are filled (for example after allocating common
1297 symbols)) */
1298 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1300 char buf[1024];
1301 int i;
1302 Section *s;
1304 add_elf_sym(symtab_section,
1305 text_section->data_offset, 0,
1306 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1307 text_section->sh_num, "_etext");
1308 add_elf_sym(symtab_section,
1309 data_section->data_offset, 0,
1310 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1311 data_section->sh_num, "_edata");
1312 add_elf_sym(symtab_section,
1313 bss_section->data_offset, 0,
1314 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1315 bss_section->sh_num, "_end");
1316 /* horrible new standard ldscript defines */
1317 add_init_array_defines(s1, ".preinit_array");
1318 add_init_array_defines(s1, ".init_array");
1319 add_init_array_defines(s1, ".fini_array");
1321 /* add start and stop symbols for sections whose name can be
1322 expressed in C */
1323 for(i = 1; i < s1->nb_sections; i++) {
1324 s = s1->sections[i];
1325 if (s->sh_type == SHT_PROGBITS &&
1326 (s->sh_flags & SHF_ALLOC)) {
1327 const char *p;
1328 int ch;
1330 /* check if section name can be expressed in C */
1331 p = s->name;
1332 for(;;) {
1333 ch = *p;
1334 if (!ch)
1335 break;
1336 if (!isid(ch) && !isnum(ch))
1337 goto next_sec;
1338 p++;
1340 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1341 add_elf_sym(symtab_section,
1342 0, 0,
1343 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1344 s->sh_num, buf);
1345 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1346 add_elf_sym(symtab_section,
1347 s->data_offset, 0,
1348 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1349 s->sh_num, buf);
1351 next_sec: ;
1355 static void tcc_output_binary(TCCState *s1, FILE *f,
1356 const int *section_order)
1358 Section *s;
1359 int i, offset, size;
1361 offset = 0;
1362 for(i=1;i<s1->nb_sections;i++) {
1363 s = s1->sections[section_order[i]];
1364 if (s->sh_type != SHT_NOBITS &&
1365 (s->sh_flags & SHF_ALLOC)) {
1366 while (offset < s->sh_offset) {
1367 fputc(0, f);
1368 offset++;
1370 size = s->sh_size;
1371 fwrite(s->data, 1, size, f);
1372 offset += size;
1377 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1378 #define HAVE_PHDR 1
1379 #define EXTRA_RELITEMS 14
1381 /* move the relocation value from .dynsym to .got */
1382 void patch_dynsym_undef(TCCState *s1, Section *s)
1384 uint32_t *gotd = (void *)s1->got->data;
1385 ElfW(Sym) *sym, *sym_end;
1387 gotd += 3; // dummy entries in .got
1388 /* relocate symbols in .dynsym */
1389 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1390 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1391 if (sym->st_shndx == SHN_UNDEF) {
1392 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1393 sym->st_value = 0;
1397 #else
1398 #define HAVE_PHDR 0
1399 #define EXTRA_RELITEMS 9
1401 /* zero plt offsets of weak symbols in .dynsym */
1402 void patch_dynsym_undef(TCCState *s1, Section *s)
1404 ElfW(Sym) *sym, *sym_end;
1406 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1407 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++)
1408 if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
1409 sym->st_value = 0;
1411 #endif
1413 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1415 int sym_index = ELFW(R_SYM) (rel->r_info);
1416 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1417 unsigned long offset;
1419 if (sym_index >= s1->nb_got_offsets)
1420 return;
1421 offset = s1->got_offsets[sym_index];
1422 section_reserve(s1->got, offset + PTR_SIZE);
1423 #ifdef TCC_TARGET_X86_64
1424 /* only works for x86-64 */
1425 put32(s1->got->data + offset + 4, sym->st_value >> 32);
1426 #endif
1427 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1430 ST_FUNC void fill_got(TCCState *s1)
1432 Section *s;
1433 ElfW_Rel *rel, *rel_end;
1434 int i;
1436 for(i = 1; i < s1->nb_sections; i++) {
1437 s = s1->sections[i];
1438 if (s->sh_type != SHT_RELX)
1439 continue;
1440 /* no need to handle got relocations */
1441 if (s->link != symtab_section)
1442 continue;
1443 rel_end = (ElfW_Rel *) (s->data + s->data_offset);
1444 for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
1445 switch (ELFW(R_TYPE) (rel->r_info)) {
1446 case R_X86_64_GOT32:
1447 case R_X86_64_GOTPCREL:
1448 case R_X86_64_PLT32:
1449 fill_got_entry(s1, rel);
1450 break;
1457 /* output an ELF file */
1458 /* XXX: suppress unneeded sections */
1459 static int elf_output_file(TCCState *s1, const char *filename)
1461 ElfW(Ehdr) ehdr;
1462 FILE *f;
1463 int fd, mode, ret;
1464 int *section_order;
1465 int shnum, i, phnum, file_offset, offset, size, j, sh_order_index, k;
1466 long long tmp;
1467 uplong addr;
1468 Section *strsec, *s;
1469 ElfW(Shdr) shdr, *sh;
1470 ElfW(Phdr) *phdr, *ph;
1471 Section *interp, *dynamic, *dynstr;
1472 unsigned long saved_dynamic_data_offset;
1473 ElfW(Sym) *sym;
1474 int type, file_type;
1475 uplong rel_addr, rel_size;
1476 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1477 uplong bss_addr, bss_size;
1478 #endif
1480 file_type = s1->output_type;
1481 s1->nb_errors = 0;
1483 if (file_type != TCC_OUTPUT_OBJ) {
1484 tcc_add_runtime(s1);
1487 phdr = NULL;
1488 section_order = NULL;
1489 interp = NULL;
1490 dynamic = NULL;
1491 dynstr = NULL; /* avoid warning */
1492 saved_dynamic_data_offset = 0; /* avoid warning */
1494 if (file_type != TCC_OUTPUT_OBJ) {
1495 relocate_common_syms();
1497 tcc_add_linker_symbols(s1);
1499 if (!s1->static_link) {
1500 const char *name;
1501 int sym_index, index;
1502 ElfW(Sym) *esym, *sym_end;
1504 if (file_type == TCC_OUTPUT_EXE) {
1505 char *ptr;
1506 /* allow override the dynamic loader */
1507 const char *elfint = getenv("LD_SO");
1508 if (elfint == NULL)
1509 elfint = CONFIG_TCC_ELFINTERP;
1510 /* add interpreter section only if executable */
1511 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1512 interp->sh_addralign = 1;
1513 ptr = section_ptr_add(interp, 1+strlen(elfint));
1514 strcpy(ptr, elfint);
1517 /* add dynamic symbol table */
1518 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1519 ".dynstr",
1520 ".hash", SHF_ALLOC);
1521 dynstr = s1->dynsym->link;
1523 /* add dynamic section */
1524 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1525 SHF_ALLOC | SHF_WRITE);
1526 dynamic->link = dynstr;
1527 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1529 /* add PLT */
1530 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1531 SHF_ALLOC | SHF_EXECINSTR);
1532 s1->plt->sh_entsize = 4;
1534 build_got(s1);
1536 /* scan for undefined symbols and see if they are in the
1537 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1538 is found, then we add it in the PLT. If a symbol
1539 STT_OBJECT is found, we add it in the .bss section with
1540 a suitable relocation */
1541 sym_end = (ElfW(Sym) *)(symtab_section->data +
1542 symtab_section->data_offset);
1543 if (file_type == TCC_OUTPUT_EXE) {
1544 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1545 sym < sym_end;
1546 sym++) {
1547 if (sym->st_shndx == SHN_UNDEF) {
1548 name = symtab_section->link->data + sym->st_name;
1549 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1550 if (sym_index) {
1551 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1552 type = ELFW(ST_TYPE)(esym->st_info);
1553 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1554 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1555 ELFW(ST_INFO)(STB_GLOBAL,type),
1556 sym - (ElfW(Sym) *)symtab_section->data);
1557 } else if (type == STT_OBJECT) {
1558 unsigned long offset;
1559 ElfW(Sym) *dynsym, *dynsym_end;
1560 offset = bss_section->data_offset;
1561 /* XXX: which alignment ? */
1562 offset = (offset + 16 - 1) & -16;
1563 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1564 esym->st_info, 0,
1565 bss_section->sh_num, name);
1566 // Ensure R_COPY works for weak symbol aliases
1567 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1568 dynsym_end = (ElfW(Sym) *)
1569 (s1->dynsymtab_section->data +
1570 s1->dynsymtab_section->data_offset);
1571 for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1572 dynsym < dynsym_end; dynsym++) {
1573 if ((dynsym->st_value == esym->st_value)
1574 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1575 char *dynname;
1576 dynname = s1->dynsymtab_section->link->data
1577 + dynsym->st_name;
1578 put_elf_sym(s1->dynsym, offset,
1579 dynsym->st_size,
1580 dynsym->st_info, 0,
1581 bss_section->sh_num,
1582 dynname);
1583 break;
1587 put_elf_reloc(s1->dynsym, bss_section,
1588 offset, R_COPY, index);
1589 offset += esym->st_size;
1590 bss_section->data_offset = offset;
1592 } else {
1593 /* STB_WEAK undefined symbols are accepted */
1594 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1595 it */
1596 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1597 !strcmp(name, "_fp_hw")) {
1598 } else {
1599 tcc_error_noabort("undefined symbol '%s'", name);
1602 } else if (s1->rdynamic &&
1603 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1604 /* if -rdynamic option, then export all non
1605 local symbols */
1606 name = symtab_section->link->data + sym->st_name;
1607 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1608 sym->st_info, 0,
1609 sym->st_shndx, name);
1613 if (s1->nb_errors)
1614 goto fail;
1616 /* now look at unresolved dynamic symbols and export
1617 corresponding symbol */
1618 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1619 s1->dynsymtab_section->data_offset);
1620 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1621 esym < sym_end;
1622 esym++) {
1623 if (esym->st_shndx == SHN_UNDEF) {
1624 name = s1->dynsymtab_section->link->data + esym->st_name;
1625 sym_index = find_elf_sym(symtab_section, name);
1626 if (sym_index) {
1627 /* XXX: avoid adding a symbol if already
1628 present because of -rdynamic ? */
1629 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1630 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1631 sym->st_info, 0,
1632 sym->st_shndx, name);
1633 } else {
1634 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1635 /* weak symbols can stay undefined */
1636 } else {
1637 tcc_warning("undefined dynamic symbol '%s'", name);
1642 } else {
1643 int nb_syms;
1644 /* shared library case : we simply export all the global symbols */
1645 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1646 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1647 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1648 sym < sym_end;
1649 sym++) {
1650 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1651 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1652 if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
1653 ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
1654 && sym->st_shndx == SHN_UNDEF) {
1655 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1656 sym->st_info,
1657 sym - (ElfW(Sym) *)symtab_section->data);
1659 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1660 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1661 sym->st_info,
1662 sym - (ElfW(Sym) *)symtab_section->data);
1664 else
1665 #endif
1667 name = symtab_section->link->data + sym->st_name;
1668 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1669 sym->st_info, 0,
1670 sym->st_shndx, name);
1671 s1->symtab_to_dynsym[sym -
1672 (ElfW(Sym) *)symtab_section->data] =
1673 index;
1679 build_got_entries(s1);
1681 /* add a list of needed dlls */
1682 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1683 DLLReference *dllref = s1->loaded_dlls[i];
1684 if (dllref->level == 0)
1685 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1688 if (s1->rpath)
1689 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1691 /* XXX: currently, since we do not handle PIC code, we
1692 must relocate the readonly segments */
1693 if (file_type == TCC_OUTPUT_DLL) {
1694 if (s1->soname)
1695 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1696 put_dt(dynamic, DT_TEXTREL, 0);
1699 if (s1->symbolic)
1700 put_dt(dynamic, DT_SYMBOLIC, 0);
1702 /* add necessary space for other entries */
1703 saved_dynamic_data_offset = dynamic->data_offset;
1704 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1705 } else {
1706 /* still need to build got entries in case of static link */
1707 build_got_entries(s1);
1711 memset(&ehdr, 0, sizeof(ehdr));
1713 /* we add a section for symbols */
1714 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1715 put_elf_str(strsec, "");
1717 /* compute number of sections */
1718 shnum = s1->nb_sections;
1720 /* this array is used to reorder sections in the output file */
1721 section_order = tcc_malloc(sizeof(int) * shnum);
1722 section_order[0] = 0;
1723 sh_order_index = 1;
1725 /* compute number of program headers */
1726 switch(file_type) {
1727 default:
1728 case TCC_OUTPUT_OBJ:
1729 phnum = 0;
1730 break;
1731 case TCC_OUTPUT_EXE:
1732 if (!s1->static_link)
1733 phnum = 4 + HAVE_PHDR;
1734 else
1735 phnum = 2;
1736 break;
1737 case TCC_OUTPUT_DLL:
1738 phnum = 3;
1739 break;
1742 /* allocate strings for section names and decide if an unallocated
1743 section should be output */
1744 /* NOTE: the strsec section comes last, so its size is also
1745 correct ! */
1746 for(i = 1; i < s1->nb_sections; i++) {
1747 s = s1->sections[i];
1748 s->sh_name = put_elf_str(strsec, s->name);
1749 #if 0 //gr
1750 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1751 s->sh_flags,
1752 s->sh_type,
1753 s->sh_info,
1754 s->name,
1755 s->reloc ? s->reloc->name : "n"
1757 #endif
1758 /* when generating a DLL, we include relocations but we may
1759 patch them */
1760 if (file_type == TCC_OUTPUT_DLL &&
1761 s->sh_type == SHT_RELX &&
1762 !(s->sh_flags & SHF_ALLOC)) {
1763 /* //gr: avoid bogus relocs for empty (debug) sections */
1764 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1765 prepare_dynamic_rel(s1, s);
1766 else if (s1->do_debug)
1767 s->sh_size = s->data_offset;
1768 } else if (s1->do_debug ||
1769 file_type == TCC_OUTPUT_OBJ ||
1770 (s->sh_flags & SHF_ALLOC) ||
1771 i == (s1->nb_sections - 1)) {
1772 /* we output all sections if debug or object file */
1773 s->sh_size = s->data_offset;
1777 /* allocate program segment headers */
1778 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1780 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1781 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1782 } else {
1783 file_offset = 0;
1785 if (phnum > 0) {
1786 /* compute section to program header mapping */
1787 if (s1->has_text_addr) {
1788 int a_offset, p_offset;
1789 addr = s1->text_addr;
1790 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1791 ELF_PAGE_SIZE */
1792 a_offset = (int) (addr & (s1->section_align - 1));
1793 p_offset = file_offset & (s1->section_align - 1);
1794 if (a_offset < p_offset)
1795 a_offset += s1->section_align;
1796 file_offset += (a_offset - p_offset);
1797 } else {
1798 if (file_type == TCC_OUTPUT_DLL)
1799 addr = 0;
1800 else
1801 addr = ELF_START_ADDR;
1802 /* compute address after headers */
1803 addr += (file_offset & (s1->section_align - 1));
1806 /* dynamic relocation table information, for .dynamic section */
1807 rel_size = 0;
1808 rel_addr = 0;
1810 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1811 bss_addr = bss_size = 0;
1812 #endif
1813 /* leave one program header for the program interpreter */
1814 ph = &phdr[0];
1815 if (interp)
1816 ph += 1 + HAVE_PHDR;
1818 for(j = 0; j < 2; j++) {
1819 ph->p_type = PT_LOAD;
1820 if (j == 0)
1821 ph->p_flags = PF_R | PF_X;
1822 else
1823 ph->p_flags = PF_R | PF_W;
1824 ph->p_align = s1->section_align;
1826 /* we do the following ordering: interp, symbol tables,
1827 relocations, progbits, nobits */
1828 /* XXX: do faster and simpler sorting */
1829 for(k = 0; k < 5; k++) {
1830 for(i = 1; i < s1->nb_sections; i++) {
1831 s = s1->sections[i];
1832 /* compute if section should be included */
1833 if (j == 0) {
1834 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1835 SHF_ALLOC)
1836 continue;
1837 } else {
1838 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1839 (SHF_ALLOC | SHF_WRITE))
1840 continue;
1842 if (s == interp) {
1843 if (k != 0)
1844 continue;
1845 } else if (s->sh_type == SHT_DYNSYM ||
1846 s->sh_type == SHT_STRTAB ||
1847 s->sh_type == SHT_HASH) {
1848 if (k != 1)
1849 continue;
1850 } else if (s->sh_type == SHT_RELX) {
1851 if (k != 2)
1852 continue;
1853 } else if (s->sh_type == SHT_NOBITS) {
1854 if (k != 4)
1855 continue;
1856 } else {
1857 if (k != 3)
1858 continue;
1860 section_order[sh_order_index++] = i;
1862 /* section matches: we align it and add its size */
1863 tmp = addr;
1864 addr = (addr + s->sh_addralign - 1) &
1865 ~(s->sh_addralign - 1);
1866 file_offset += (int) ( addr - tmp );
1867 s->sh_offset = file_offset;
1868 s->sh_addr = addr;
1870 /* update program header infos */
1871 if (ph->p_offset == 0) {
1872 ph->p_offset = file_offset;
1873 ph->p_vaddr = addr;
1874 ph->p_paddr = ph->p_vaddr;
1876 /* update dynamic relocation infos */
1877 if (s->sh_type == SHT_RELX) {
1878 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1879 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1880 rel_addr = addr;
1881 rel_size += s->sh_size; // XXX only first rel.
1883 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1884 bss_addr = addr;
1885 bss_size = s->sh_size; // XXX only first rel.
1887 #else
1888 if (rel_size == 0)
1889 rel_addr = addr;
1890 rel_size += s->sh_size;
1891 #endif
1893 addr += s->sh_size;
1894 if (s->sh_type != SHT_NOBITS)
1895 file_offset += s->sh_size;
1898 ph->p_filesz = file_offset - ph->p_offset;
1899 ph->p_memsz = addr - ph->p_vaddr;
1900 ph++;
1901 if (j == 0) {
1902 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1903 /* if in the middle of a page, we duplicate the page in
1904 memory so that one copy is RX and the other is RW */
1905 if ((addr & (s1->section_align - 1)) != 0)
1906 addr += s1->section_align;
1907 } else {
1908 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1909 file_offset = (file_offset + s1->section_align - 1) &
1910 ~(s1->section_align - 1);
1915 /* if interpreter, then add corresponing program header */
1916 if (interp) {
1917 ph = &phdr[0];
1919 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1921 int len = phnum * sizeof(ElfW(Phdr));
1923 ph->p_type = PT_PHDR;
1924 ph->p_offset = sizeof(ElfW(Ehdr));
1925 ph->p_vaddr = interp->sh_addr - len;
1926 ph->p_paddr = ph->p_vaddr;
1927 ph->p_filesz = ph->p_memsz = len;
1928 ph->p_flags = PF_R | PF_X;
1929 ph->p_align = 4; // interp->sh_addralign;
1930 ph++;
1932 #endif
1934 ph->p_type = PT_INTERP;
1935 ph->p_offset = interp->sh_offset;
1936 ph->p_vaddr = interp->sh_addr;
1937 ph->p_paddr = ph->p_vaddr;
1938 ph->p_filesz = interp->sh_size;
1939 ph->p_memsz = interp->sh_size;
1940 ph->p_flags = PF_R;
1941 ph->p_align = interp->sh_addralign;
1944 /* if dynamic section, then add corresponing program header */
1945 if (dynamic) {
1946 ElfW(Sym) *sym_end;
1948 ph = &phdr[phnum - 1];
1950 ph->p_type = PT_DYNAMIC;
1951 ph->p_offset = dynamic->sh_offset;
1952 ph->p_vaddr = dynamic->sh_addr;
1953 ph->p_paddr = ph->p_vaddr;
1954 ph->p_filesz = dynamic->sh_size;
1955 ph->p_memsz = dynamic->sh_size;
1956 ph->p_flags = PF_R | PF_W;
1957 ph->p_align = dynamic->sh_addralign;
1959 /* put GOT dynamic section address */
1960 put32(s1->got->data, dynamic->sh_addr);
1962 /* relocate the PLT */
1963 if (file_type == TCC_OUTPUT_EXE
1964 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1965 || file_type == TCC_OUTPUT_DLL
1966 #endif
1968 uint8_t *p, *p_end;
1970 p = s1->plt->data;
1971 p_end = p + s1->plt->data_offset;
1972 if (p < p_end) {
1973 #if defined(TCC_TARGET_I386)
1974 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1975 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1976 p += 16;
1977 while (p < p_end) {
1978 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1979 p += 16;
1981 #elif defined(TCC_TARGET_X86_64)
1982 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1983 put32(p + 2, get32(p + 2) + x);
1984 put32(p + 8, get32(p + 8) + x - 6);
1985 p += 16;
1986 while (p < p_end) {
1987 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1988 p += 16;
1990 #elif defined(TCC_TARGET_ARM)
1991 int x;
1992 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1993 p +=16;
1994 while (p < p_end) {
1995 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1996 p += 16;
1998 #elif defined(TCC_TARGET_C67)
1999 /* XXX: TODO */
2000 #else
2001 #error unsupported CPU
2002 #endif
2006 /* relocate symbols in .dynsym */
2007 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
2008 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
2009 sym < sym_end;
2010 sym++) {
2011 if (sym->st_shndx == SHN_UNDEF) {
2012 /* relocate to the PLT if the symbol corresponds
2013 to a PLT entry */
2014 if (sym->st_value)
2015 sym->st_value += s1->plt->sh_addr;
2016 } else if (sym->st_shndx < SHN_LORESERVE) {
2017 /* do symbol relocation */
2018 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
2022 /* put dynamic section entries */
2023 dynamic->data_offset = saved_dynamic_data_offset;
2024 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
2025 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
2026 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2027 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
2028 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2029 #ifdef TCC_TARGET_X86_64
2030 put_dt(dynamic, DT_RELA, rel_addr);
2031 put_dt(dynamic, DT_RELASZ, rel_size);
2032 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2033 #else
2034 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2035 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2036 put_dt(dynamic, DT_PLTRELSZ, rel_size);
2037 put_dt(dynamic, DT_JMPREL, rel_addr);
2038 put_dt(dynamic, DT_PLTREL, DT_REL);
2039 put_dt(dynamic, DT_REL, bss_addr);
2040 put_dt(dynamic, DT_RELSZ, bss_size);
2041 #else
2042 put_dt(dynamic, DT_REL, rel_addr);
2043 put_dt(dynamic, DT_RELSZ, rel_size);
2044 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2045 #endif
2046 #endif
2047 if (s1->do_debug)
2048 put_dt(dynamic, DT_DEBUG, 0);
2049 put_dt(dynamic, DT_NULL, 0);
2052 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2053 ehdr.e_phnum = phnum;
2054 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2057 /* all other sections come after */
2058 for(i = 1; i < s1->nb_sections; i++) {
2059 s = s1->sections[i];
2060 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2061 continue;
2062 section_order[sh_order_index++] = i;
2064 file_offset = (file_offset + s->sh_addralign - 1) &
2065 ~(s->sh_addralign - 1);
2066 s->sh_offset = file_offset;
2067 if (s->sh_type != SHT_NOBITS)
2068 file_offset += s->sh_size;
2071 /* if building executable or DLL, then relocate each section
2072 except the GOT which is already relocated */
2073 if (file_type != TCC_OUTPUT_OBJ) {
2074 relocate_syms(s1, 0);
2076 if (s1->nb_errors != 0) {
2077 fail:
2078 ret = -1;
2079 goto the_end;
2082 /* relocate sections */
2083 /* XXX: ignore sections with allocated relocations ? */
2084 for(i = 1; i < s1->nb_sections; i++) {
2085 s = s1->sections[i];
2086 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
2087 relocate_section(s1, s);
2090 /* relocate relocation entries if the relocation tables are
2091 allocated in the executable */
2092 for(i = 1; i < s1->nb_sections; i++) {
2093 s = s1->sections[i];
2094 if ((s->sh_flags & SHF_ALLOC) &&
2095 s->sh_type == SHT_RELX) {
2096 relocate_rel(s1, s);
2100 /* get entry point address */
2101 if (file_type == TCC_OUTPUT_EXE)
2102 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
2103 else
2104 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2106 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2107 fill_got(s1);
2109 /* write elf file */
2110 if (file_type == TCC_OUTPUT_OBJ)
2111 mode = 0666;
2112 else
2113 mode = 0777;
2114 unlink(filename);
2115 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2116 if (fd < 0) {
2117 tcc_error_noabort("could not write '%s'", filename);
2118 goto fail;
2120 f = fdopen(fd, "wb");
2121 if (s1->verbose)
2122 printf("<- %s\n", filename);
2124 #ifdef TCC_TARGET_COFF
2125 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2126 tcc_output_coff(s1, f);
2127 } else
2128 #endif
2129 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2130 sort_syms(s1, symtab_section);
2132 /* align to 4 */
2133 file_offset = (file_offset + 3) & -4;
2135 /* fill header */
2136 ehdr.e_ident[0] = ELFMAG0;
2137 ehdr.e_ident[1] = ELFMAG1;
2138 ehdr.e_ident[2] = ELFMAG2;
2139 ehdr.e_ident[3] = ELFMAG3;
2140 ehdr.e_ident[4] = ELFCLASSW;
2141 ehdr.e_ident[5] = ELFDATA2LSB;
2142 ehdr.e_ident[6] = EV_CURRENT;
2143 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2144 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2145 #endif
2146 #ifdef TCC_TARGET_ARM
2147 #ifdef TCC_ARM_EABI
2148 ehdr.e_ident[EI_OSABI] = 0;
2149 ehdr.e_flags = 4 << 24;
2150 #else
2151 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2152 #endif
2153 #endif
2154 switch(file_type) {
2155 default:
2156 case TCC_OUTPUT_EXE:
2157 ehdr.e_type = ET_EXEC;
2158 break;
2159 case TCC_OUTPUT_DLL:
2160 ehdr.e_type = ET_DYN;
2161 break;
2162 case TCC_OUTPUT_OBJ:
2163 ehdr.e_type = ET_REL;
2164 break;
2166 ehdr.e_machine = EM_TCC_TARGET;
2167 ehdr.e_version = EV_CURRENT;
2168 ehdr.e_shoff = file_offset;
2169 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2170 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2171 ehdr.e_shnum = shnum;
2172 ehdr.e_shstrndx = shnum - 1;
2174 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2175 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2176 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2178 for(i=1;i<s1->nb_sections;i++) {
2179 s = s1->sections[section_order[i]];
2180 if (s->sh_type != SHT_NOBITS) {
2181 if (s->sh_type == SHT_DYNSYM)
2182 patch_dynsym_undef(s1, s);
2183 while (offset < s->sh_offset) {
2184 fputc(0, f);
2185 offset++;
2187 size = s->sh_size;
2188 fwrite(s->data, 1, size, f);
2189 offset += size;
2193 /* output section headers */
2194 while (offset < ehdr.e_shoff) {
2195 fputc(0, f);
2196 offset++;
2199 for(i=0;i<s1->nb_sections;i++) {
2200 sh = &shdr;
2201 memset(sh, 0, sizeof(ElfW(Shdr)));
2202 s = s1->sections[i];
2203 if (s) {
2204 sh->sh_name = s->sh_name;
2205 sh->sh_type = s->sh_type;
2206 sh->sh_flags = s->sh_flags;
2207 sh->sh_entsize = s->sh_entsize;
2208 sh->sh_info = s->sh_info;
2209 if (s->link)
2210 sh->sh_link = s->link->sh_num;
2211 sh->sh_addralign = s->sh_addralign;
2212 sh->sh_addr = s->sh_addr;
2213 sh->sh_offset = s->sh_offset;
2214 sh->sh_size = s->sh_size;
2216 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2218 } else {
2219 tcc_output_binary(s1, f, section_order);
2221 fclose(f);
2223 ret = 0;
2224 the_end:
2225 tcc_free(s1->symtab_to_dynsym);
2226 tcc_free(section_order);
2227 tcc_free(phdr);
2228 tcc_free(s1->got_offsets);
2229 return ret;
2232 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2234 int ret;
2235 #ifdef TCC_TARGET_PE
2236 if (s->output_type != TCC_OUTPUT_OBJ) {
2237 ret = pe_output_file(s, filename);
2238 } else
2239 #endif
2241 ret = elf_output_file(s, filename);
2243 return ret;
2246 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2248 void *data;
2250 data = tcc_malloc(size);
2251 lseek(fd, file_offset, SEEK_SET);
2252 read(fd, data, size);
2253 return data;
2256 typedef struct SectionMergeInfo {
2257 Section *s; /* corresponding existing section */
2258 unsigned long offset; /* offset of the new section in the existing section */
2259 uint8_t new_section; /* true if section 's' was added */
2260 uint8_t link_once; /* true if link once section */
2261 } SectionMergeInfo;
2263 /* load an object file and merge it with current files */
2264 /* XXX: handle correctly stab (debug) info */
2265 ST_FUNC int tcc_load_object_file(TCCState *s1,
2266 int fd, unsigned long file_offset)
2268 ElfW(Ehdr) ehdr;
2269 ElfW(Shdr) *shdr, *sh;
2270 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2271 unsigned char *strsec, *strtab;
2272 int *old_to_new_syms;
2273 char *sh_name, *name;
2274 SectionMergeInfo *sm_table, *sm;
2275 ElfW(Sym) *sym, *symtab;
2276 ElfW_Rel *rel, *rel_end;
2277 Section *s;
2279 int stab_index;
2280 int stabstr_index;
2282 stab_index = stabstr_index = 0;
2284 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2285 goto fail1;
2286 if (ehdr.e_ident[0] != ELFMAG0 ||
2287 ehdr.e_ident[1] != ELFMAG1 ||
2288 ehdr.e_ident[2] != ELFMAG2 ||
2289 ehdr.e_ident[3] != ELFMAG3)
2290 goto fail1;
2291 /* test if object file */
2292 if (ehdr.e_type != ET_REL)
2293 goto fail1;
2294 /* test CPU specific stuff */
2295 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2296 ehdr.e_machine != EM_TCC_TARGET) {
2297 fail1:
2298 tcc_error_noabort("invalid object file");
2299 return -1;
2301 /* read sections */
2302 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2303 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2304 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2306 /* load section names */
2307 sh = &shdr[ehdr.e_shstrndx];
2308 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2310 /* load symtab and strtab */
2311 old_to_new_syms = NULL;
2312 symtab = NULL;
2313 strtab = NULL;
2314 nb_syms = 0;
2315 for(i = 1; i < ehdr.e_shnum; i++) {
2316 sh = &shdr[i];
2317 if (sh->sh_type == SHT_SYMTAB) {
2318 if (symtab) {
2319 tcc_error_noabort("object must contain only one symtab");
2320 fail:
2321 ret = -1;
2322 goto the_end;
2324 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2325 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2326 sm_table[i].s = symtab_section;
2328 /* now load strtab */
2329 sh = &shdr[sh->sh_link];
2330 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2334 /* now examine each section and try to merge its content with the
2335 ones in memory */
2336 for(i = 1; i < ehdr.e_shnum; i++) {
2337 /* no need to examine section name strtab */
2338 if (i == ehdr.e_shstrndx)
2339 continue;
2340 sh = &shdr[i];
2341 sh_name = strsec + sh->sh_name;
2342 /* ignore sections types we do not handle */
2343 if (sh->sh_type != SHT_PROGBITS &&
2344 sh->sh_type != SHT_RELX &&
2345 #ifdef TCC_ARM_EABI
2346 sh->sh_type != SHT_ARM_EXIDX &&
2347 #endif
2348 sh->sh_type != SHT_NOBITS &&
2349 sh->sh_type != SHT_PREINIT_ARRAY &&
2350 sh->sh_type != SHT_INIT_ARRAY &&
2351 sh->sh_type != SHT_FINI_ARRAY &&
2352 strcmp(sh_name, ".stabstr")
2354 continue;
2355 if (sh->sh_addralign < 1)
2356 sh->sh_addralign = 1;
2357 /* find corresponding section, if any */
2358 for(j = 1; j < s1->nb_sections;j++) {
2359 s = s1->sections[j];
2360 if (!strcmp(s->name, sh_name)) {
2361 if (!strncmp(sh_name, ".gnu.linkonce",
2362 sizeof(".gnu.linkonce") - 1)) {
2363 /* if a 'linkonce' section is already present, we
2364 do not add it again. It is a little tricky as
2365 symbols can still be defined in
2366 it. */
2367 sm_table[i].link_once = 1;
2368 goto next;
2369 } else {
2370 goto found;
2374 /* not found: create new section */
2375 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2376 /* take as much info as possible from the section. sh_link and
2377 sh_info will be updated later */
2378 s->sh_addralign = sh->sh_addralign;
2379 s->sh_entsize = sh->sh_entsize;
2380 sm_table[i].new_section = 1;
2381 found:
2382 if (sh->sh_type != s->sh_type) {
2383 tcc_error_noabort("invalid section type");
2384 goto fail;
2387 /* align start of section */
2388 offset = s->data_offset;
2390 if (0 == strcmp(sh_name, ".stab")) {
2391 stab_index = i;
2392 goto no_align;
2394 if (0 == strcmp(sh_name, ".stabstr")) {
2395 stabstr_index = i;
2396 goto no_align;
2399 size = sh->sh_addralign - 1;
2400 offset = (offset + size) & ~size;
2401 if (sh->sh_addralign > s->sh_addralign)
2402 s->sh_addralign = sh->sh_addralign;
2403 s->data_offset = offset;
2404 no_align:
2405 sm_table[i].offset = offset;
2406 sm_table[i].s = s;
2407 /* concatenate sections */
2408 size = sh->sh_size;
2409 if (sh->sh_type != SHT_NOBITS) {
2410 unsigned char *ptr;
2411 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2412 ptr = section_ptr_add(s, size);
2413 read(fd, ptr, size);
2414 } else {
2415 s->data_offset += size;
2417 next: ;
2420 /* //gr relocate stab strings */
2421 if (stab_index && stabstr_index) {
2422 Stab_Sym *a, *b;
2423 unsigned o;
2424 s = sm_table[stab_index].s;
2425 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2426 b = (Stab_Sym *)(s->data + s->data_offset);
2427 o = sm_table[stabstr_index].offset;
2428 while (a < b)
2429 a->n_strx += o, a++;
2432 /* second short pass to update sh_link and sh_info fields of new
2433 sections */
2434 for(i = 1; i < ehdr.e_shnum; i++) {
2435 s = sm_table[i].s;
2436 if (!s || !sm_table[i].new_section)
2437 continue;
2438 sh = &shdr[i];
2439 if (sh->sh_link > 0)
2440 s->link = sm_table[sh->sh_link].s;
2441 if (sh->sh_type == SHT_RELX) {
2442 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2443 /* update backward link */
2444 s1->sections[s->sh_info]->reloc = s;
2447 sm = sm_table;
2449 /* resolve symbols */
2450 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2452 sym = symtab + 1;
2453 for(i = 1; i < nb_syms; i++, sym++) {
2454 if (sym->st_shndx != SHN_UNDEF &&
2455 sym->st_shndx < SHN_LORESERVE) {
2456 sm = &sm_table[sym->st_shndx];
2457 if (sm->link_once) {
2458 /* if a symbol is in a link once section, we use the
2459 already defined symbol. It is very important to get
2460 correct relocations */
2461 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2462 name = strtab + sym->st_name;
2463 sym_index = find_elf_sym(symtab_section, name);
2464 if (sym_index)
2465 old_to_new_syms[i] = sym_index;
2467 continue;
2469 /* if no corresponding section added, no need to add symbol */
2470 if (!sm->s)
2471 continue;
2472 /* convert section number */
2473 sym->st_shndx = sm->s->sh_num;
2474 /* offset value */
2475 sym->st_value += sm->offset;
2477 /* add symbol */
2478 name = strtab + sym->st_name;
2479 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2480 sym->st_info, sym->st_other,
2481 sym->st_shndx, name);
2482 old_to_new_syms[i] = sym_index;
2485 /* third pass to patch relocation entries */
2486 for(i = 1; i < ehdr.e_shnum; i++) {
2487 s = sm_table[i].s;
2488 if (!s)
2489 continue;
2490 sh = &shdr[i];
2491 offset = sm_table[i].offset;
2492 switch(s->sh_type) {
2493 case SHT_RELX:
2494 /* take relocation offset information */
2495 offseti = sm_table[sh->sh_info].offset;
2496 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2497 for(rel = (ElfW_Rel *)(s->data + offset);
2498 rel < rel_end;
2499 rel++) {
2500 int type;
2501 unsigned sym_index;
2502 /* convert symbol index */
2503 type = ELFW(R_TYPE)(rel->r_info);
2504 sym_index = ELFW(R_SYM)(rel->r_info);
2505 /* NOTE: only one symtab assumed */
2506 if (sym_index >= nb_syms)
2507 goto invalid_reloc;
2508 sym_index = old_to_new_syms[sym_index];
2509 /* ignore link_once in rel section. */
2510 if (!sym_index && !sm->link_once
2511 #ifdef TCC_TARGET_ARM
2512 && type != R_ARM_V4BX
2513 #endif
2515 invalid_reloc:
2516 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2517 i, strsec + sh->sh_name, rel->r_offset);
2518 goto fail;
2520 rel->r_info = ELFW(R_INFO)(sym_index, type);
2521 /* offset the relocation offset */
2522 rel->r_offset += offseti;
2524 break;
2525 default:
2526 break;
2530 ret = 0;
2531 the_end:
2532 tcc_free(symtab);
2533 tcc_free(strtab);
2534 tcc_free(old_to_new_syms);
2535 tcc_free(sm_table);
2536 tcc_free(strsec);
2537 tcc_free(shdr);
2538 return ret;
2541 typedef struct ArchiveHeader {
2542 char ar_name[16]; /* name of this member */
2543 char ar_date[12]; /* file mtime */
2544 char ar_uid[6]; /* owner uid; printed as decimal */
2545 char ar_gid[6]; /* owner gid; printed as decimal */
2546 char ar_mode[8]; /* file mode, printed as octal */
2547 char ar_size[10]; /* file size, printed as decimal */
2548 char ar_fmag[2]; /* should contain ARFMAG */
2549 } ArchiveHeader;
2551 static int get_be32(const uint8_t *b)
2553 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2556 /* load only the objects which resolve undefined symbols */
2557 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2559 int i, bound, nsyms, sym_index, off, ret;
2560 uint8_t *data;
2561 const char *ar_names, *p;
2562 const uint8_t *ar_index;
2563 ElfW(Sym) *sym;
2565 data = tcc_malloc(size);
2566 if (read(fd, data, size) != size)
2567 goto fail;
2568 nsyms = get_be32(data);
2569 ar_index = data + 4;
2570 ar_names = ar_index + nsyms * 4;
2572 do {
2573 bound = 0;
2574 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2575 sym_index = find_elf_sym(symtab_section, p);
2576 if(sym_index) {
2577 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2578 if(sym->st_shndx == SHN_UNDEF) {
2579 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2580 #if 0
2581 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2582 #endif
2583 ++bound;
2584 lseek(fd, off, SEEK_SET);
2585 if(tcc_load_object_file(s1, fd, off) < 0) {
2586 fail:
2587 ret = -1;
2588 goto the_end;
2593 } while(bound);
2594 ret = 0;
2595 the_end:
2596 tcc_free(data);
2597 return ret;
2600 /* load a '.a' file */
2601 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2603 ArchiveHeader hdr;
2604 char ar_size[11];
2605 char ar_name[17];
2606 char magic[8];
2607 int size, len, i;
2608 unsigned long file_offset;
2610 /* skip magic which was already checked */
2611 read(fd, magic, sizeof(magic));
2613 for(;;) {
2614 len = read(fd, &hdr, sizeof(hdr));
2615 if (len == 0)
2616 break;
2617 if (len != sizeof(hdr)) {
2618 tcc_error_noabort("invalid archive");
2619 return -1;
2621 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2622 ar_size[sizeof(hdr.ar_size)] = '\0';
2623 size = strtol(ar_size, NULL, 0);
2624 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2625 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2626 if (ar_name[i] != ' ')
2627 break;
2629 ar_name[i + 1] = '\0';
2630 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2631 file_offset = lseek(fd, 0, SEEK_CUR);
2632 /* align to even */
2633 size = (size + 1) & ~1;
2634 if (!strcmp(ar_name, "/")) {
2635 /* coff symbol table : we handle it */
2636 if(s1->alacarte_link)
2637 return tcc_load_alacarte(s1, fd, size);
2638 } else if (!strcmp(ar_name, "//") ||
2639 !strcmp(ar_name, "__.SYMDEF") ||
2640 !strcmp(ar_name, "__.SYMDEF/") ||
2641 !strcmp(ar_name, "ARFILENAMES/")) {
2642 /* skip symbol table or archive names */
2643 } else {
2644 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2645 return -1;
2647 lseek(fd, file_offset + size, SEEK_SET);
2649 return 0;
2652 #ifndef TCC_TARGET_PE
2653 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2654 is referenced by the user (so it should be added as DT_NEEDED in
2655 the generated ELF file) */
2656 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2658 ElfW(Ehdr) ehdr;
2659 ElfW(Shdr) *shdr, *sh, *sh1;
2660 int i, j, nb_syms, nb_dts, sym_bind, ret;
2661 ElfW(Sym) *sym, *dynsym;
2662 ElfW(Dyn) *dt, *dynamic;
2663 unsigned char *dynstr;
2664 const char *name, *soname;
2665 DLLReference *dllref;
2667 read(fd, &ehdr, sizeof(ehdr));
2669 /* test CPU specific stuff */
2670 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2671 ehdr.e_machine != EM_TCC_TARGET) {
2672 tcc_error_noabort("bad architecture");
2673 return -1;
2676 /* read sections */
2677 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2679 /* load dynamic section and dynamic symbols */
2680 nb_syms = 0;
2681 nb_dts = 0;
2682 dynamic = NULL;
2683 dynsym = NULL; /* avoid warning */
2684 dynstr = NULL; /* avoid warning */
2685 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2686 switch(sh->sh_type) {
2687 case SHT_DYNAMIC:
2688 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2689 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2690 break;
2691 case SHT_DYNSYM:
2692 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2693 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2694 sh1 = &shdr[sh->sh_link];
2695 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2696 break;
2697 default:
2698 break;
2702 /* compute the real library name */
2703 soname = tcc_basename(filename);
2705 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2706 if (dt->d_tag == DT_SONAME) {
2707 soname = dynstr + dt->d_un.d_val;
2711 /* if the dll is already loaded, do not load it */
2712 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2713 dllref = s1->loaded_dlls[i];
2714 if (!strcmp(soname, dllref->name)) {
2715 /* but update level if needed */
2716 if (level < dllref->level)
2717 dllref->level = level;
2718 ret = 0;
2719 goto the_end;
2723 // printf("loading dll '%s'\n", soname);
2725 /* add the dll and its level */
2726 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2727 dllref->level = level;
2728 strcpy(dllref->name, soname);
2729 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2731 /* add dynamic symbols in dynsym_section */
2732 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2733 sym_bind = ELFW(ST_BIND)(sym->st_info);
2734 if (sym_bind == STB_LOCAL)
2735 continue;
2736 name = dynstr + sym->st_name;
2737 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2738 sym->st_info, sym->st_other, sym->st_shndx, name);
2741 /* load all referenced DLLs */
2742 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2743 switch(dt->d_tag) {
2744 case DT_NEEDED:
2745 name = dynstr + dt->d_un.d_val;
2746 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2747 dllref = s1->loaded_dlls[j];
2748 if (!strcmp(name, dllref->name))
2749 goto already_loaded;
2751 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2752 tcc_error_noabort("referenced dll '%s' not found", name);
2753 ret = -1;
2754 goto the_end;
2756 already_loaded:
2757 break;
2760 ret = 0;
2761 the_end:
2762 tcc_free(dynstr);
2763 tcc_free(dynsym);
2764 tcc_free(dynamic);
2765 tcc_free(shdr);
2766 return ret;
2769 #define LD_TOK_NAME 256
2770 #define LD_TOK_EOF (-1)
2772 /* return next ld script token */
2773 static int ld_next(TCCState *s1, char *name, int name_size)
2775 int c;
2776 char *q;
2778 redo:
2779 switch(ch) {
2780 case ' ':
2781 case '\t':
2782 case '\f':
2783 case '\v':
2784 case '\r':
2785 case '\n':
2786 inp();
2787 goto redo;
2788 case '/':
2789 minp();
2790 if (ch == '*') {
2791 file->buf_ptr = parse_comment(file->buf_ptr);
2792 ch = file->buf_ptr[0];
2793 goto redo;
2794 } else {
2795 q = name;
2796 *q++ = '/';
2797 goto parse_name;
2799 break;
2800 /* case 'a' ... 'z': */
2801 case 'a':
2802 case 'b':
2803 case 'c':
2804 case 'd':
2805 case 'e':
2806 case 'f':
2807 case 'g':
2808 case 'h':
2809 case 'i':
2810 case 'j':
2811 case 'k':
2812 case 'l':
2813 case 'm':
2814 case 'n':
2815 case 'o':
2816 case 'p':
2817 case 'q':
2818 case 'r':
2819 case 's':
2820 case 't':
2821 case 'u':
2822 case 'v':
2823 case 'w':
2824 case 'x':
2825 case 'y':
2826 case 'z':
2827 /* case 'A' ... 'z': */
2828 case 'A':
2829 case 'B':
2830 case 'C':
2831 case 'D':
2832 case 'E':
2833 case 'F':
2834 case 'G':
2835 case 'H':
2836 case 'I':
2837 case 'J':
2838 case 'K':
2839 case 'L':
2840 case 'M':
2841 case 'N':
2842 case 'O':
2843 case 'P':
2844 case 'Q':
2845 case 'R':
2846 case 'S':
2847 case 'T':
2848 case 'U':
2849 case 'V':
2850 case 'W':
2851 case 'X':
2852 case 'Y':
2853 case 'Z':
2854 case '_':
2855 case '\\':
2856 case '.':
2857 case '$':
2858 case '~':
2859 q = name;
2860 parse_name:
2861 for(;;) {
2862 if (!((ch >= 'a' && ch <= 'z') ||
2863 (ch >= 'A' && ch <= 'Z') ||
2864 (ch >= '0' && ch <= '9') ||
2865 strchr("/.-_+=$:\\,~", ch)))
2866 break;
2867 if ((q - name) < name_size - 1) {
2868 *q++ = ch;
2870 minp();
2872 *q = '\0';
2873 c = LD_TOK_NAME;
2874 break;
2875 case CH_EOF:
2876 c = LD_TOK_EOF;
2877 break;
2878 default:
2879 c = ch;
2880 inp();
2881 break;
2883 #if 0
2884 printf("tok=%c %d\n", c, c);
2885 if (c == LD_TOK_NAME)
2886 printf(" name=%s\n", name);
2887 #endif
2888 return c;
2892 * Extract the file name from the library name
2894 * /!\ No test on filename capacity, be careful
2896 static void libname_to_filename(TCCState *s1, const char libname[], char filename[])
2898 if (!s1->static_link) {
2899 sprintf(filename, "lib%s.so", libname);
2900 } else {
2901 sprintf(filename, "lib%s.a", libname);
2905 static int ld_add_file(TCCState *s1, const char filename[])
2907 int ret;
2909 ret = tcc_add_file_internal(s1, filename, 0);
2910 if (ret)
2911 ret = tcc_add_dll(s1, filename, 0);
2912 return ret;
2915 static inline int new_undef_syms(void)
2917 int ret = 0;
2918 ret = new_undef_sym;
2919 new_undef_sym = 0;
2920 return ret;
2923 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
2925 char filename[1024], libname[1024];
2926 int t, group, nblibs = 0, ret = 0;
2927 char **libs = NULL;
2929 group = !strcmp(cmd, "GROUP");
2930 if (!as_needed)
2931 new_undef_syms();
2932 t = ld_next(s1, filename, sizeof(filename));
2933 if (t != '(')
2934 expect("(");
2935 t = ld_next(s1, filename, sizeof(filename));
2936 for(;;) {
2937 libname[0] = '\0';
2938 if (t == LD_TOK_EOF) {
2939 tcc_error_noabort("unexpected end of file");
2940 ret = -1;
2941 goto lib_parse_error;
2942 } else if (t == ')') {
2943 break;
2944 } else if (t == '-') {
2945 t = ld_next(s1, filename, sizeof(filename));
2946 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
2947 tcc_error_noabort("library name expected");
2948 ret = -1;
2949 goto lib_parse_error;
2951 strcpy(libname, &filename[1]);
2952 libname_to_filename(s1, libname, filename);
2953 } else if (t != LD_TOK_NAME) {
2954 tcc_error_noabort("filename expected");
2955 ret = -1;
2956 goto lib_parse_error;
2958 if (!strcmp(filename, "AS_NEEDED")) {
2959 ret = ld_add_file_list(s1, cmd, 1);
2960 if (ret)
2961 goto lib_parse_error;
2962 } else {
2963 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2964 if (!as_needed) {
2965 ret = ld_add_file(s1, filename);
2966 if (ret)
2967 goto lib_parse_error;
2968 if (group) {
2969 /* Add the filename *and* the libname to avoid future conversions */
2970 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
2971 if (libname[0] != '\0')
2972 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
2976 t = ld_next(s1, filename, sizeof(filename));
2977 if (t == ',') {
2978 t = ld_next(s1, filename, sizeof(filename));
2981 if (group && !as_needed) {
2982 while (new_undef_syms()) {
2983 int i;
2985 for (i = 0; i < nblibs; i ++)
2986 ld_add_file(s1, libs[i]);
2989 lib_parse_error:
2990 dynarray_reset(&libs, &nblibs);
2991 return ret;
2994 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
2995 files */
2996 ST_FUNC int tcc_load_ldscript(TCCState *s1)
2998 char cmd[64];
2999 char filename[1024];
3000 int t, ret;
3002 ch = file->buf_ptr[0];
3003 ch = handle_eob();
3004 for(;;) {
3005 t = ld_next(s1, cmd, sizeof(cmd));
3006 if (t == LD_TOK_EOF)
3007 return 0;
3008 else if (t != LD_TOK_NAME)
3009 return -1;
3010 if (!strcmp(cmd, "INPUT") ||
3011 !strcmp(cmd, "GROUP")) {
3012 ret = ld_add_file_list(s1, cmd, 0);
3013 if (ret)
3014 return ret;
3015 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3016 !strcmp(cmd, "TARGET")) {
3017 /* ignore some commands */
3018 t = ld_next(s1, cmd, sizeof(cmd));
3019 if (t != '(')
3020 expect("(");
3021 for(;;) {
3022 t = ld_next(s1, filename, sizeof(filename));
3023 if (t == LD_TOK_EOF) {
3024 tcc_error_noabort("unexpected end of file");
3025 return -1;
3026 } else if (t == ')') {
3027 break;
3030 } else {
3031 return -1;
3034 return 0;
3036 #endif /* ndef TCC_TARGET_PE */