ARM: use uint32_t for opcodes
[tinycc.git] / tccelf.c
blob4ea8dc84f8f77ccb95622b2748db188f629cb48a
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 #ifdef TCC_TARGET_X86_64
24 #define ElfW_Rel ElfW(Rela)
25 #define SHT_RELX SHT_RELA
26 #define REL_SECTION_FMT ".rela%s"
27 /* x86-64 requires PLT for DLLs */
28 #define TCC_OUTPUT_DLL_WITH_PLT
29 #else
30 #define ElfW_Rel ElfW(Rel)
31 #define SHT_RELX SHT_REL
32 #define REL_SECTION_FMT ".rel%s"
33 #endif
35 static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */
37 /* XXX: DLL with PLT would only work with x86-64 for now */
38 //#define TCC_OUTPUT_DLL_WITH_PLT
40 ST_FUNC int put_elf_str(Section *s, const char *sym)
42 int offset, len;
43 char *ptr;
45 len = strlen(sym) + 1;
46 offset = s->data_offset;
47 ptr = section_ptr_add(s, len);
48 memcpy(ptr, sym, len);
49 return offset;
52 /* elf symbol hashing function */
53 static unsigned long elf_hash(const unsigned char *name)
55 unsigned long h = 0, g;
57 while (*name) {
58 h = (h << 4) + *name++;
59 g = h & 0xf0000000;
60 if (g)
61 h ^= g >> 24;
62 h &= ~g;
64 return h;
67 /* rebuild hash table of section s */
68 /* NOTE: we do factorize the hash table code to go faster */
69 static void rebuild_hash(Section *s, unsigned int nb_buckets)
71 ElfW(Sym) *sym;
72 int *ptr, *hash, nb_syms, sym_index, h;
73 char *strtab;
75 strtab = s->link->data;
76 nb_syms = s->data_offset / sizeof(ElfW(Sym));
78 s->hash->data_offset = 0;
79 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
80 ptr[0] = nb_buckets;
81 ptr[1] = nb_syms;
82 ptr += 2;
83 hash = ptr;
84 memset(hash, 0, (nb_buckets + 1) * sizeof(int));
85 ptr += nb_buckets + 1;
87 sym = (ElfW(Sym) *)s->data + 1;
88 for(sym_index = 1; sym_index < nb_syms; sym_index++) {
89 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
90 h = elf_hash(strtab + sym->st_name) % nb_buckets;
91 *ptr = hash[h];
92 hash[h] = sym_index;
93 } else {
94 *ptr = 0;
96 ptr++;
97 sym++;
101 /* return the symbol number */
102 ST_FUNC int put_elf_sym(Section *s, uplong value, unsigned long size,
103 int info, int other, int shndx, const char *name)
105 int name_offset, sym_index;
106 int nbuckets, h;
107 ElfW(Sym) *sym;
108 Section *hs;
110 sym = section_ptr_add(s, sizeof(ElfW(Sym)));
111 if (name)
112 name_offset = put_elf_str(s->link, name);
113 else
114 name_offset = 0;
115 /* XXX: endianness */
116 sym->st_name = name_offset;
117 sym->st_value = value;
118 sym->st_size = size;
119 sym->st_info = info;
120 sym->st_other = other;
121 sym->st_shndx = shndx;
122 sym_index = sym - (ElfW(Sym) *)s->data;
123 hs = s->hash;
124 if (hs) {
125 int *ptr, *base;
126 ptr = section_ptr_add(hs, sizeof(int));
127 base = (int *)hs->data;
128 /* only add global or weak symbols */
129 if (ELFW(ST_BIND)(info) != STB_LOCAL) {
130 /* add another hashing entry */
131 nbuckets = base[0];
132 h = elf_hash(name) % nbuckets;
133 *ptr = base[2 + h];
134 base[2 + h] = sym_index;
135 base[1]++;
136 /* we resize the hash table */
137 hs->nb_hashed_syms++;
138 if (hs->nb_hashed_syms > 2 * nbuckets) {
139 rebuild_hash(s, 2 * nbuckets);
141 } else {
142 *ptr = 0;
143 base[1]++;
146 return sym_index;
149 /* find global ELF symbol 'name' and return its index. Return 0 if not
150 found. */
151 ST_FUNC int find_elf_sym(Section *s, const char *name)
153 ElfW(Sym) *sym;
154 Section *hs;
155 int nbuckets, sym_index, h;
156 const char *name1;
158 hs = s->hash;
159 if (!hs)
160 return 0;
161 nbuckets = ((int *)hs->data)[0];
162 h = elf_hash(name) % nbuckets;
163 sym_index = ((int *)hs->data)[2 + h];
164 while (sym_index != 0) {
165 sym = &((ElfW(Sym) *)s->data)[sym_index];
166 name1 = s->link->data + sym->st_name;
167 if (!strcmp(name, name1))
168 return sym_index;
169 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
171 return 0;
174 /* return elf symbol value, signal error if 'err' is nonzero */
175 static void *get_elf_sym_addr(TCCState *s, const char *name, int err)
177 int sym_index;
178 ElfW(Sym) *sym;
180 sym_index = find_elf_sym(symtab_section, name);
181 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
182 if (!sym_index || sym->st_shndx == SHN_UNDEF) {
183 if (err)
184 error("%s not defined", name);
185 return NULL;
187 return (void*)(uplong)sym->st_value;
190 /* return elf symbol value */
191 LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
193 return get_elf_sym_addr(s, name, 0);
196 /* return elf symbol value or error */
197 ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name)
199 return get_elf_sym_addr(s, name, 1);
202 /* add an elf symbol : check if it is already defined and patch
203 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
204 ST_FUNC int add_elf_sym(Section *s, uplong value, unsigned long size,
205 int info, int other, int sh_num, const char *name)
207 ElfW(Sym) *esym;
208 int sym_bind, sym_index, sym_type, esym_bind;
209 unsigned char sym_vis, esym_vis, new_vis;
211 sym_bind = ELFW(ST_BIND)(info);
212 sym_type = ELFW(ST_TYPE)(info);
213 sym_vis = ELFW(ST_VISIBILITY)(other);
215 if (sym_bind != STB_LOCAL) {
216 /* we search global or weak symbols */
217 sym_index = find_elf_sym(s, name);
218 if (!sym_index)
219 goto do_def;
220 esym = &((ElfW(Sym) *)s->data)[sym_index];
221 if (esym->st_shndx != SHN_UNDEF) {
222 esym_bind = ELFW(ST_BIND)(esym->st_info);
223 /* propagate the most constraining visibility */
224 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
225 esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
226 if (esym_vis == STV_DEFAULT) {
227 new_vis = sym_vis;
228 } else if (sym_vis == STV_DEFAULT) {
229 new_vis = esym_vis;
230 } else {
231 new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
233 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
234 | new_vis;
235 other = esym->st_other; /* in case we have to patch esym */
236 if (sh_num == SHN_UNDEF) {
237 /* ignore adding of undefined symbol if the
238 corresponding symbol is already defined */
239 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
240 /* global overrides weak, so patch */
241 goto do_patch;
242 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
243 /* weak is ignored if already global */
244 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
245 /* ignore hidden symbols after */
246 } else if (esym->st_shndx == SHN_COMMON
247 && (sh_num < SHN_LORESERVE || sh_num == SHN_COMMON)) {
248 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
249 No idea if this is the correct solution ... */
250 goto do_patch;
251 } else if (s == tcc_state->dynsymtab_section) {
252 /* we accept that two DLL define the same symbol */
253 } else {
254 #if 1
255 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
256 sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
257 #endif
258 error_noabort("'%s' defined twice", name);
260 } else {
261 do_patch:
262 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
263 esym->st_shndx = sh_num;
264 new_undef_sym = 1;
265 esym->st_value = value;
266 esym->st_size = size;
267 esym->st_other = other;
269 } else {
270 do_def:
271 sym_index = put_elf_sym(s, value, size,
272 ELFW(ST_INFO)(sym_bind, sym_type), other,
273 sh_num, name);
275 return sym_index;
278 /* put relocation */
279 ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
280 int type, int symbol)
282 char buf[256];
283 Section *sr;
284 ElfW_Rel *rel;
286 sr = s->reloc;
287 if (!sr) {
288 /* if no relocation section, create it */
289 snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
290 /* if the symtab is allocated, then we consider the relocation
291 are also */
292 sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
293 sr->sh_entsize = sizeof(ElfW_Rel);
294 sr->link = symtab;
295 sr->sh_info = s->sh_num;
296 s->reloc = sr;
298 rel = section_ptr_add(sr, sizeof(ElfW_Rel));
299 rel->r_offset = offset;
300 rel->r_info = ELFW(R_INFO)(symbol, type);
301 #ifdef TCC_TARGET_X86_64
302 rel->r_addend = 0;
303 #endif
306 /* put stab debug information */
308 ST_FUNC void put_stabs(const char *str, int type, int other, int desc,
309 unsigned long value)
311 Stab_Sym *sym;
313 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
314 if (str) {
315 sym->n_strx = put_elf_str(stabstr_section, str);
316 } else {
317 sym->n_strx = 0;
319 sym->n_type = type;
320 sym->n_other = other;
321 sym->n_desc = desc;
322 sym->n_value = value;
325 ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc,
326 unsigned long value, Section *sec, int sym_index)
328 put_stabs(str, type, other, desc, value);
329 put_elf_reloc(symtab_section, stab_section,
330 stab_section->data_offset - sizeof(unsigned int),
331 R_DATA_32, sym_index);
334 ST_FUNC void put_stabn(int type, int other, int desc, int value)
336 put_stabs(NULL, type, other, desc, value);
339 ST_FUNC void put_stabd(int type, int other, int desc)
341 put_stabs(NULL, type, other, desc, 0);
344 /* In an ELF file symbol table, the local symbols must appear below
345 the global and weak ones. Since TCC cannot sort it while generating
346 the code, we must do it after. All the relocation tables are also
347 modified to take into account the symbol table sorting */
348 static void sort_syms(TCCState *s1, Section *s)
350 int *old_to_new_syms;
351 ElfW(Sym) *new_syms;
352 int nb_syms, i;
353 ElfW(Sym) *p, *q;
354 ElfW_Rel *rel, *rel_end;
355 Section *sr;
356 int type, sym_index;
358 nb_syms = s->data_offset / sizeof(ElfW(Sym));
359 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
360 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
362 /* first pass for local symbols */
363 p = (ElfW(Sym) *)s->data;
364 q = new_syms;
365 for(i = 0; i < nb_syms; i++) {
366 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
367 old_to_new_syms[i] = q - new_syms;
368 *q++ = *p;
370 p++;
372 /* save the number of local symbols in section header */
373 s->sh_info = q - new_syms;
375 /* then second pass for non local symbols */
376 p = (ElfW(Sym) *)s->data;
377 for(i = 0; i < nb_syms; i++) {
378 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
379 old_to_new_syms[i] = q - new_syms;
380 *q++ = *p;
382 p++;
385 /* we copy the new symbols to the old */
386 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
387 tcc_free(new_syms);
389 /* now we modify all the relocations */
390 for(i = 1; i < s1->nb_sections; i++) {
391 sr = s1->sections[i];
392 if (sr->sh_type == SHT_RELX && sr->link == s) {
393 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
394 for(rel = (ElfW_Rel *)sr->data;
395 rel < rel_end;
396 rel++) {
397 sym_index = ELFW(R_SYM)(rel->r_info);
398 type = ELFW(R_TYPE)(rel->r_info);
399 sym_index = old_to_new_syms[sym_index];
400 rel->r_info = ELFW(R_INFO)(sym_index, type);
405 tcc_free(old_to_new_syms);
408 /* relocate common symbols in the .bss section */
409 ST_FUNC void relocate_common_syms(void)
411 ElfW(Sym) *sym, *sym_end;
412 unsigned long offset, align;
414 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
415 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
416 sym < sym_end;
417 sym++) {
418 if (sym->st_shndx == SHN_COMMON) {
419 /* align symbol */
420 align = sym->st_value;
421 offset = bss_section->data_offset;
422 offset = (offset + align - 1) & -align;
423 sym->st_value = offset;
424 sym->st_shndx = bss_section->sh_num;
425 offset += sym->st_size;
426 bss_section->data_offset = offset;
431 /* relocate symbol table, resolve undefined symbols if do_resolve is
432 true and output error if undefined symbol. */
433 ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
435 ElfW(Sym) *sym, *esym, *sym_end;
436 int sym_bind, sh_num, sym_index;
437 const char *name;
439 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
440 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
441 sym < sym_end;
442 sym++) {
443 sh_num = sym->st_shndx;
444 if (sh_num == SHN_UNDEF) {
445 name = strtab_section->data + sym->st_name;
446 if (do_resolve) {
447 #if !defined TCC_TARGET_PE || !defined _WIN32
448 void *addr;
449 name = symtab_section->link->data + sym->st_name;
450 addr = resolve_sym(s1, name);
451 if (addr) {
452 sym->st_value = (uplong)addr;
453 goto found;
455 #endif
456 } else if (s1->dynsym) {
457 /* if dynamic symbol exist, then use it */
458 sym_index = find_elf_sym(s1->dynsym, name);
459 if (sym_index) {
460 esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
461 sym->st_value = esym->st_value;
462 goto found;
465 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
466 it */
467 if (!strcmp(name, "_fp_hw"))
468 goto found;
469 /* only weak symbols are accepted to be undefined. Their
470 value is zero */
471 sym_bind = ELFW(ST_BIND)(sym->st_info);
472 if (sym_bind == STB_WEAK) {
473 sym->st_value = 0;
474 } else {
475 error_noabort("undefined symbol '%s'", name);
477 } else if (sh_num < SHN_LORESERVE) {
478 /* add section base */
479 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
481 found: ;
485 #ifndef TCC_TARGET_PE
486 #ifdef TCC_TARGET_X86_64
487 #define JMP_TABLE_ENTRY_SIZE 14
488 static uplong add_jmp_table(TCCState *s1, uplong val)
490 char *p = s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset;
491 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
492 /* jmp *0x0(%rip) */
493 p[0] = 0xff;
494 p[1] = 0x25;
495 *(int *)(p + 2) = 0;
496 *(uplong *)(p + 6) = val;
497 return (uplong)p;
500 static uplong add_got_table(TCCState *s1, uplong val)
502 uplong *p = (uplong *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
503 s1->runtime_plt_and_got_offset += sizeof(uplong);
504 *p = val;
505 return (uplong)p;
507 #endif
508 #endif
510 /* relocate a given section (CPU dependent) */
511 ST_FUNC void relocate_section(TCCState *s1, Section *s)
513 Section *sr;
514 ElfW_Rel *rel, *rel_end, *qrel;
515 ElfW(Sym) *sym;
516 int type, sym_index;
517 unsigned char *ptr;
518 uplong val, addr;
519 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
520 int esym_index;
521 #endif
523 sr = s->reloc;
524 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
525 qrel = (ElfW_Rel *)sr->data;
526 for(rel = qrel;
527 rel < rel_end;
528 rel++) {
529 ptr = s->data + rel->r_offset;
531 sym_index = ELFW(R_SYM)(rel->r_info);
532 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
533 val = sym->st_value;
534 #ifdef TCC_TARGET_X86_64
535 /* XXX: not tested */
536 val += rel->r_addend;
537 #endif
538 type = ELFW(R_TYPE)(rel->r_info);
539 addr = s->sh_addr + rel->r_offset;
541 /* CPU specific */
542 switch(type) {
543 #if defined(TCC_TARGET_I386)
544 case R_386_32:
545 if (s1->output_type == TCC_OUTPUT_DLL) {
546 esym_index = s1->symtab_to_dynsym[sym_index];
547 qrel->r_offset = rel->r_offset;
548 if (esym_index) {
549 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
550 qrel++;
551 break;
552 } else {
553 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
554 qrel++;
557 *(int *)ptr += val;
558 break;
559 case R_386_PC32:
560 if (s1->output_type == TCC_OUTPUT_DLL) {
561 /* DLL relocation */
562 esym_index = s1->symtab_to_dynsym[sym_index];
563 if (esym_index) {
564 qrel->r_offset = rel->r_offset;
565 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
566 qrel++;
567 break;
570 *(int *)ptr += val - addr;
571 break;
572 case R_386_PLT32:
573 *(int *)ptr += val - addr;
574 break;
575 case R_386_GLOB_DAT:
576 case R_386_JMP_SLOT:
577 *(int *)ptr = val;
578 break;
579 case R_386_GOTPC:
580 *(int *)ptr += s1->got->sh_addr - addr;
581 break;
582 case R_386_GOTOFF:
583 *(int *)ptr += val - s1->got->sh_addr;
584 break;
585 case R_386_GOT32:
586 /* we load the got offset */
587 *(int *)ptr += s1->got_offsets[sym_index];
588 break;
589 case R_386_16:
590 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
591 output_file:
592 error("can only produce 16-bit binary files");
594 *(short *)ptr += val;
595 break;
596 case R_386_PC16:
597 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
598 goto output_file;
599 *(short *)ptr += val - addr;
600 break;
601 #elif defined(TCC_TARGET_ARM)
602 case R_ARM_PC24:
603 case R_ARM_CALL:
604 case R_ARM_JUMP24:
605 case R_ARM_PLT32:
607 int x;
608 x = (*(int *)ptr)&0xffffff;
609 (*(int *)ptr) &= 0xff000000;
610 if (x & 0x800000)
611 x -= 0x1000000;
612 x *= 4;
613 x += val - addr;
614 if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
615 error("can't relocate value at %x",addr);
616 x >>= 2;
617 x &= 0xffffff;
618 (*(int *)ptr) |= x;
620 break;
621 case R_ARM_PREL31:
623 int x;
624 x = (*(int *)ptr) & 0x7fffffff;
625 (*(int *)ptr) &= 0x80000000;
626 x = (x * 2) / 2;
627 x += val - addr;
628 if((x^(x>>1))&0x40000000)
629 error("can't relocate value at %x",addr);
630 (*(int *)ptr) |= x & 0x7fffffff;
632 case R_ARM_ABS32:
633 *(int *)ptr += val;
634 break;
635 case R_ARM_BASE_PREL:
636 *(int *)ptr += s1->got->sh_addr - addr;
637 break;
638 case R_ARM_GOTOFF32:
639 *(int *)ptr += val - s1->got->sh_addr;
640 break;
641 case R_ARM_GOT_BREL:
642 /* we load the got offset */
643 *(int *)ptr += s1->got_offsets[sym_index];
644 break;
645 case R_ARM_COPY:
646 break;
647 default:
648 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
649 type,addr,(unsigned int)(long)ptr,val);
650 break;
651 #elif defined(TCC_TARGET_C67)
652 case R_C60_32:
653 *(int *)ptr += val;
654 break;
655 case R_C60LO16:
657 uint32_t orig;
659 /* put the low 16 bits of the absolute address */
660 // add to what is already there
662 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
663 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
665 //patch both at once - assumes always in pairs Low - High
667 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
668 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
670 break;
671 case R_C60HI16:
672 break;
673 default:
674 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
675 type,addr,(unsigned int)(long)ptr, val);
676 break;
677 #elif defined(TCC_TARGET_X86_64)
678 case R_X86_64_64:
679 if (s1->output_type == TCC_OUTPUT_DLL) {
680 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
681 qrel->r_addend = *(long long *)ptr + val;
682 qrel++;
684 *(long long *)ptr += val;
685 break;
686 case R_X86_64_32:
687 case R_X86_64_32S:
688 if (s1->output_type == TCC_OUTPUT_DLL) {
689 /* XXX: this logic may depend on TCC's codegen
690 now TCC uses R_X86_64_32 even for a 64bit pointer */
691 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
692 qrel->r_addend = *(int *)ptr + val;
693 qrel++;
695 *(int *)ptr += val;
696 break;
697 case R_X86_64_PC32: {
698 long long diff;
699 if (s1->output_type == TCC_OUTPUT_DLL) {
700 /* DLL relocation */
701 esym_index = s1->symtab_to_dynsym[sym_index];
702 if (esym_index) {
703 qrel->r_offset = rel->r_offset;
704 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
705 qrel->r_addend = *(int *)ptr;
706 qrel++;
707 break;
710 diff = (long long)val - addr;
711 if (diff <= -2147483647 || diff > 2147483647) {
712 #ifndef TCC_TARGET_PE
713 /* XXX: naive support for over 32bit jump */
714 if (s1->output_type == TCC_OUTPUT_MEMORY) {
715 val = add_jmp_table(s1, val);
716 diff = val - addr;
718 #endif
719 if (diff <= -2147483647 || diff > 2147483647) {
720 error("internal error: relocation failed");
723 *(int *)ptr += diff;
725 break;
726 case R_X86_64_PLT32:
727 *(int *)ptr += val - addr;
728 break;
729 case R_X86_64_GLOB_DAT:
730 case R_X86_64_JUMP_SLOT:
731 *(int *)ptr = val;
732 break;
733 case R_X86_64_GOTPCREL:
734 #ifndef TCC_TARGET_PE
735 if (s1->output_type == TCC_OUTPUT_MEMORY) {
736 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
737 *(int *)ptr += val - addr;
738 break;
740 #endif
741 *(int *)ptr += (s1->got->sh_addr - addr +
742 s1->got_offsets[sym_index] - 4);
743 break;
744 case R_X86_64_GOTTPOFF:
745 *(int *)ptr += val - s1->got->sh_addr;
746 break;
747 case R_X86_64_GOT32:
748 /* we load the got offset */
749 *(int *)ptr += s1->got_offsets[sym_index];
750 break;
751 #else
752 #error unsupported processor
753 #endif
756 /* if the relocation is allocated, we change its symbol table */
757 if (sr->sh_flags & SHF_ALLOC)
758 sr->link = s1->dynsym;
761 /* relocate relocation table in 'sr' */
762 static void relocate_rel(TCCState *s1, Section *sr)
764 Section *s;
765 ElfW_Rel *rel, *rel_end;
767 s = s1->sections[sr->sh_info];
768 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
769 for(rel = (ElfW_Rel *)sr->data;
770 rel < rel_end;
771 rel++) {
772 rel->r_offset += s->sh_addr;
776 /* count the number of dynamic relocations so that we can reserve
777 their space */
778 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
780 ElfW_Rel *rel, *rel_end;
781 int sym_index, esym_index, type, count;
783 count = 0;
784 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
785 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
786 sym_index = ELFW(R_SYM)(rel->r_info);
787 type = ELFW(R_TYPE)(rel->r_info);
788 switch(type) {
789 #if defined(TCC_TARGET_I386)
790 case R_386_32:
791 #elif defined(TCC_TARGET_X86_64)
792 case R_X86_64_32:
793 case R_X86_64_32S:
794 case R_X86_64_64:
795 #endif
796 count++;
797 break;
798 #if defined(TCC_TARGET_I386)
799 case R_386_PC32:
800 #elif defined(TCC_TARGET_X86_64)
801 case R_X86_64_PC32:
802 #endif
803 esym_index = s1->symtab_to_dynsym[sym_index];
804 if (esym_index)
805 count++;
806 break;
807 default:
808 break;
811 if (count) {
812 /* allocate the section */
813 sr->sh_flags |= SHF_ALLOC;
814 sr->sh_size = count * sizeof(ElfW_Rel);
816 return count;
819 static void put_got_offset(TCCState *s1, int index, unsigned long val)
821 int n;
822 unsigned long *tab;
824 if (index >= s1->nb_got_offsets) {
825 /* find immediately bigger power of 2 and reallocate array */
826 n = 1;
827 while (index >= n)
828 n *= 2;
829 tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
830 if (!tab)
831 error("memory full");
832 s1->got_offsets = tab;
833 memset(s1->got_offsets + s1->nb_got_offsets, 0,
834 (n - s1->nb_got_offsets) * sizeof(unsigned long));
835 s1->nb_got_offsets = n;
837 s1->got_offsets[index] = val;
840 /* XXX: suppress that */
841 static void put32(unsigned char *p, uint32_t val)
843 p[0] = val;
844 p[1] = val >> 8;
845 p[2] = val >> 16;
846 p[3] = val >> 24;
849 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
850 defined(TCC_TARGET_X86_64)
851 static uint32_t get32(unsigned char *p)
853 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
855 #endif
857 static void build_got(TCCState *s1)
859 unsigned char *ptr;
861 /* if no got, then create it */
862 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
863 s1->got->sh_entsize = 4;
864 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
865 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
866 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
867 #if PTR_SIZE == 4
868 /* keep space for _DYNAMIC pointer, if present */
869 put32(ptr, 0);
870 /* two dummy got entries */
871 put32(ptr + 4, 0);
872 put32(ptr + 8, 0);
873 #else
874 /* keep space for _DYNAMIC pointer, if present */
875 put32(ptr, 0);
876 put32(ptr + 4, 0);
877 /* two dummy got entries */
878 put32(ptr + 8, 0);
879 put32(ptr + 12, 0);
880 put32(ptr + 16, 0);
881 put32(ptr + 20, 0);
882 #endif
885 /* put a got entry corresponding to a symbol in symtab_section. 'size'
886 and 'info' can be modifed if more precise info comes from the DLL */
887 static void put_got_entry(TCCState *s1,
888 int reloc_type, unsigned long size, int info,
889 int sym_index)
891 int index;
892 const char *name;
893 ElfW(Sym) *sym;
894 unsigned long offset;
895 int *ptr;
897 if (!s1->got)
898 build_got(s1);
900 /* if a got entry already exists for that symbol, no need to add one */
901 if (sym_index < s1->nb_got_offsets &&
902 s1->got_offsets[sym_index] != 0)
903 return;
905 put_got_offset(s1, sym_index, s1->got->data_offset);
907 if (s1->dynsym) {
908 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
909 name = symtab_section->link->data + sym->st_name;
910 offset = sym->st_value;
911 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
912 if (reloc_type ==
913 #ifdef TCC_TARGET_X86_64
914 R_X86_64_JUMP_SLOT
915 #else
916 R_386_JMP_SLOT
917 #endif
919 Section *plt;
920 uint8_t *p;
921 int modrm;
923 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
924 modrm = 0x25;
925 #else
926 /* if we build a DLL, we add a %ebx offset */
927 if (s1->output_type == TCC_OUTPUT_DLL)
928 modrm = 0xa3;
929 else
930 modrm = 0x25;
931 #endif
933 /* add a PLT entry */
934 plt = s1->plt;
935 if (plt->data_offset == 0) {
936 /* first plt entry */
937 p = section_ptr_add(plt, 16);
938 p[0] = 0xff; /* pushl got + PTR_SIZE */
939 p[1] = modrm + 0x10;
940 put32(p + 2, PTR_SIZE);
941 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
942 p[7] = modrm;
943 put32(p + 8, PTR_SIZE * 2);
946 p = section_ptr_add(plt, 16);
947 p[0] = 0xff; /* jmp *(got + x) */
948 p[1] = modrm;
949 put32(p + 2, s1->got->data_offset);
950 p[6] = 0x68; /* push $xxx */
951 put32(p + 7, (plt->data_offset - 32) >> 1);
952 p[11] = 0xe9; /* jmp plt_start */
953 put32(p + 12, -(plt->data_offset));
955 /* the symbol is modified so that it will be relocated to
956 the PLT */
957 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
958 if (s1->output_type == TCC_OUTPUT_EXE)
959 #endif
960 offset = plt->data_offset - 16;
962 #elif defined(TCC_TARGET_ARM)
963 if (reloc_type == R_ARM_JUMP_SLOT) {
964 Section *plt;
965 uint8_t *p;
967 /* if we build a DLL, we add a %ebx offset */
968 if (s1->output_type == TCC_OUTPUT_DLL)
969 error("DLLs unimplemented!");
971 /* add a PLT entry */
972 plt = s1->plt;
973 if (plt->data_offset == 0) {
974 /* first plt entry */
975 p = section_ptr_add(plt, 16);
976 put32(p , 0xe52de004);
977 put32(p + 4, 0xe59fe010);
978 put32(p + 8, 0xe08fe00e);
979 put32(p + 12, 0xe5bef008);
982 p = section_ptr_add(plt, 16);
983 put32(p , 0xe59fc004);
984 put32(p+4, 0xe08fc00c);
985 put32(p+8, 0xe59cf000);
986 put32(p+12, s1->got->data_offset);
988 /* the symbol is modified so that it will be relocated to
989 the PLT */
990 if (s1->output_type == TCC_OUTPUT_EXE)
991 offset = plt->data_offset - 16;
993 #elif defined(TCC_TARGET_C67)
994 error("C67 got not implemented");
995 #else
996 #error unsupported CPU
997 #endif
998 index = put_elf_sym(s1->dynsym, offset,
999 size, info, 0, sym->st_shndx, name);
1000 /* put a got entry */
1001 put_elf_reloc(s1->dynsym, s1->got,
1002 s1->got->data_offset,
1003 reloc_type, index);
1005 ptr = section_ptr_add(s1->got, PTR_SIZE);
1006 *ptr = 0;
1009 /* build GOT and PLT entries */
1010 ST_FUNC void build_got_entries(TCCState *s1)
1012 Section *s, *symtab;
1013 ElfW_Rel *rel, *rel_end;
1014 ElfW(Sym) *sym;
1015 int i, type, reloc_type, sym_index;
1017 for(i = 1; i < s1->nb_sections; i++) {
1018 s = s1->sections[i];
1019 if (s->sh_type != SHT_RELX)
1020 continue;
1021 /* no need to handle got relocations */
1022 if (s->link != symtab_section)
1023 continue;
1024 symtab = s->link;
1025 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1026 for(rel = (ElfW_Rel *)s->data;
1027 rel < rel_end;
1028 rel++) {
1029 type = ELFW(R_TYPE)(rel->r_info);
1030 switch(type) {
1031 #if defined(TCC_TARGET_I386)
1032 case R_386_GOT32:
1033 case R_386_GOTOFF:
1034 case R_386_GOTPC:
1035 case R_386_PLT32:
1036 if (!s1->got)
1037 build_got(s1);
1038 if (type == R_386_GOT32 || type == R_386_PLT32) {
1039 sym_index = ELFW(R_SYM)(rel->r_info);
1040 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1041 /* look at the symbol got offset. If none, then add one */
1042 if (type == R_386_GOT32)
1043 reloc_type = R_386_GLOB_DAT;
1044 else
1045 reloc_type = R_386_JMP_SLOT;
1046 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1047 sym_index);
1049 break;
1050 #elif defined(TCC_TARGET_ARM)
1051 case R_ARM_GOT_BREL:
1052 case R_ARM_GOTOFF32:
1053 case R_ARM_BASE_PREL:
1054 case R_ARM_PLT32:
1055 if (!s1->got)
1056 build_got(s1);
1057 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1058 sym_index = ELFW(R_SYM)(rel->r_info);
1059 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1060 /* look at the symbol got offset. If none, then add one */
1061 if (type == R_ARM_GOT_BREL)
1062 reloc_type = R_ARM_GLOB_DAT;
1063 else
1064 reloc_type = R_ARM_JUMP_SLOT;
1065 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1066 sym_index);
1068 break;
1069 #elif defined(TCC_TARGET_C67)
1070 case R_C60_GOT32:
1071 case R_C60_GOTOFF:
1072 case R_C60_GOTPC:
1073 case R_C60_PLT32:
1074 if (!s1->got)
1075 build_got(s1);
1076 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1077 sym_index = ELFW(R_SYM)(rel->r_info);
1078 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1079 /* look at the symbol got offset. If none, then add one */
1080 if (type == R_C60_GOT32)
1081 reloc_type = R_C60_GLOB_DAT;
1082 else
1083 reloc_type = R_C60_JMP_SLOT;
1084 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1085 sym_index);
1087 break;
1088 #elif defined(TCC_TARGET_X86_64)
1089 case R_X86_64_GOT32:
1090 case R_X86_64_GOTTPOFF:
1091 case R_X86_64_GOTPCREL:
1092 case R_X86_64_PLT32:
1093 if (!s1->got)
1094 build_got(s1);
1095 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1096 type == R_X86_64_PLT32) {
1097 sym_index = ELFW(R_SYM)(rel->r_info);
1098 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1099 /* look at the symbol got offset. If none, then add one */
1100 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1101 reloc_type = R_X86_64_GLOB_DAT;
1102 else
1103 reloc_type = R_X86_64_JUMP_SLOT;
1104 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1105 sym_index);
1107 break;
1108 #else
1109 #error unsupported CPU
1110 #endif
1111 default:
1112 break;
1118 ST_FUNC Section *new_symtab(TCCState *s1,
1119 const char *symtab_name, int sh_type, int sh_flags,
1120 const char *strtab_name,
1121 const char *hash_name, int hash_sh_flags)
1123 Section *symtab, *strtab, *hash;
1124 int *ptr, nb_buckets;
1126 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1127 symtab->sh_entsize = sizeof(ElfW(Sym));
1128 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1129 put_elf_str(strtab, "");
1130 symtab->link = strtab;
1131 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1133 nb_buckets = 1;
1135 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1136 hash->sh_entsize = sizeof(int);
1137 symtab->hash = hash;
1138 hash->link = symtab;
1140 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1141 ptr[0] = nb_buckets;
1142 ptr[1] = 1;
1143 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1144 return symtab;
1147 /* put dynamic tag */
1148 static void put_dt(Section *dynamic, int dt, unsigned long val)
1150 ElfW(Dyn) *dyn;
1151 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1152 dyn->d_tag = dt;
1153 dyn->d_un.d_val = val;
1156 static void add_init_array_defines(TCCState *s1, const char *section_name)
1158 Section *s;
1159 long end_offset;
1160 char sym_start[1024];
1161 char sym_end[1024];
1163 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1164 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1166 s = find_section(s1, section_name);
1167 if (!s) {
1168 end_offset = 0;
1169 s = data_section;
1170 } else {
1171 end_offset = s->data_offset;
1174 add_elf_sym(symtab_section,
1175 0, 0,
1176 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1177 s->sh_num, sym_start);
1178 add_elf_sym(symtab_section,
1179 end_offset, 0,
1180 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1181 s->sh_num, sym_end);
1184 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1186 #ifdef CONFIG_TCC_BCHECK
1187 unsigned long *ptr;
1188 Section *init_section;
1189 unsigned char *pinit;
1190 int sym_index;
1192 if (0 == s1->do_bounds_check)
1193 return;
1195 /* XXX: add an object file to do that */
1196 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1197 *ptr = 0;
1198 add_elf_sym(symtab_section, 0, 0,
1199 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1200 bounds_section->sh_num, "__bounds_start");
1201 /* add bound check code */
1202 #ifndef TCC_TARGET_PE
1204 char buf[1024];
1205 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "bcheck.o");
1206 tcc_add_file(s1, buf);
1208 #endif
1209 #ifdef TCC_TARGET_I386
1210 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1211 /* add 'call __bound_init()' in .init section */
1212 init_section = find_section(s1, ".init");
1213 pinit = section_ptr_add(init_section, 5);
1214 pinit[0] = 0xe8;
1215 put32(pinit + 1, -4);
1216 sym_index = find_elf_sym(symtab_section, "__bound_init");
1217 put_elf_reloc(symtab_section, init_section,
1218 init_section->data_offset - 4, R_386_PC32, sym_index);
1220 #endif
1221 #endif
1224 /* add tcc runtime libraries */
1225 ST_FUNC void tcc_add_runtime(TCCState *s1)
1227 tcc_add_bcheck(s1);
1229 /* add libc */
1230 if (!s1->nostdlib) {
1231 #ifdef CONFIG_USE_LIBGCC
1232 tcc_add_library(s1, "c");
1233 tcc_add_file(s1, CONFIG_SYSROOT "/lib/libgcc_s.so.1");
1234 #else
1235 tcc_add_library(s1, "c");
1236 #ifndef WITHOUT_LIBTCC
1238 char buf[1024];
1239 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "libtcc1.a");
1240 tcc_add_file(s1, buf);
1242 #endif
1243 #endif
1245 /* add crt end if not memory output */
1246 if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) {
1247 tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
1251 /* add various standard linker symbols (must be done after the
1252 sections are filled (for example after allocating common
1253 symbols)) */
1254 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1256 char buf[1024];
1257 int i;
1258 Section *s;
1260 add_elf_sym(symtab_section,
1261 text_section->data_offset, 0,
1262 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1263 text_section->sh_num, "_etext");
1264 add_elf_sym(symtab_section,
1265 data_section->data_offset, 0,
1266 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1267 data_section->sh_num, "_edata");
1268 add_elf_sym(symtab_section,
1269 bss_section->data_offset, 0,
1270 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1271 bss_section->sh_num, "_end");
1272 /* horrible new standard ldscript defines */
1273 add_init_array_defines(s1, ".preinit_array");
1274 add_init_array_defines(s1, ".init_array");
1275 add_init_array_defines(s1, ".fini_array");
1277 /* add start and stop symbols for sections whose name can be
1278 expressed in C */
1279 for(i = 1; i < s1->nb_sections; i++) {
1280 s = s1->sections[i];
1281 if (s->sh_type == SHT_PROGBITS &&
1282 (s->sh_flags & SHF_ALLOC)) {
1283 const char *p;
1284 int ch;
1286 /* check if section name can be expressed in C */
1287 p = s->name;
1288 for(;;) {
1289 ch = *p;
1290 if (!ch)
1291 break;
1292 if (!isid(ch) && !isnum(ch))
1293 goto next_sec;
1294 p++;
1296 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1297 add_elf_sym(symtab_section,
1298 0, 0,
1299 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1300 s->sh_num, buf);
1301 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1302 add_elf_sym(symtab_section,
1303 s->data_offset, 0,
1304 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1305 s->sh_num, buf);
1307 next_sec: ;
1311 /* name of ELF interpreter */
1312 #if defined __FreeBSD__
1313 static const char elf_interp[] = "/libexec/ld-elf.so.1";
1314 #elif defined TCC_ARM_EABI
1315 static const char elf_interp[] = "/lib/ld-linux.so.3";
1316 #elif defined(TCC_TARGET_X86_64)
1317 # if defined(TCC_TARGET_X86_64_CENTOS)
1318 static const char elf_interp[] = "/lib64/ld-linux-x86-64.so.2";
1319 # else
1320 static const char elf_interp[] = "/lib/ld-linux-x86-64.so.2";
1321 # endif /* TCC_TARGET_X86_64_CENTOS */
1322 #elif defined(TCC_UCLIBC)
1323 static const char elf_interp[] = "/lib/ld-uClibc.so.0";
1324 #else
1325 static const char elf_interp[] = "/lib/ld-linux.so.2";
1326 #endif
1328 static void tcc_output_binary(TCCState *s1, FILE *f,
1329 const int *section_order)
1331 Section *s;
1332 int i, offset, size;
1334 offset = 0;
1335 for(i=1;i<s1->nb_sections;i++) {
1336 s = s1->sections[section_order[i]];
1337 if (s->sh_type != SHT_NOBITS &&
1338 (s->sh_flags & SHF_ALLOC)) {
1339 while (offset < s->sh_offset) {
1340 fputc(0, f);
1341 offset++;
1343 size = s->sh_size;
1344 fwrite(s->data, 1, size, f);
1345 offset += size;
1350 #if defined(__FreeBSD__)
1351 #define HAVE_PHDR 1
1352 #define EXTRA_RELITEMS 14
1354 /* move the relocation value from .dynsym to .got */
1355 void patch_dynsym_undef(TCCState *s1, Section *s)
1357 uint32_t *gotd = (void *)s1->got->data;
1358 ElfW(Sym) *sym, *sym_end;
1360 gotd += 3; // dummy entries in .got
1361 /* relocate symbols in .dynsym */
1362 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1363 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1364 if (sym->st_shndx == SHN_UNDEF) {
1365 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1366 sym->st_value = 0;
1370 #else
1371 #define HAVE_PHDR 0
1372 #define EXTRA_RELITEMS 9
1373 #endif
1375 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1377 int sym_index = ELFW(R_SYM) (rel->r_info);
1378 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1379 unsigned long offset;
1381 if (sym_index >= s1->nb_got_offsets)
1382 return;
1383 offset = s1->got_offsets[sym_index];
1384 section_reserve(s1->got, offset + PTR_SIZE);
1385 #ifdef TCC_TARGET_X86_64
1386 /* only works for x86-64 */
1387 put32(s1->got->data + offset, sym->st_value >> 32);
1388 #endif
1389 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1392 ST_FUNC void fill_got(TCCState *s1)
1394 Section *s;
1395 ElfW_Rel *rel, *rel_end;
1396 int i;
1398 for(i = 1; i < s1->nb_sections; i++) {
1399 s = s1->sections[i];
1400 if (s->sh_type != SHT_RELX)
1401 continue;
1402 /* no need to handle got relocations */
1403 if (s->link != symtab_section)
1404 continue;
1405 rel_end = (ElfW_Rel *) (s->data + s->data_offset);
1406 for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
1407 switch (ELFW(R_TYPE) (rel->r_info)) {
1408 case R_X86_64_GOT32:
1409 case R_X86_64_GOTPCREL:
1410 case R_X86_64_PLT32:
1411 fill_got_entry(s1, rel);
1412 break;
1419 /* output an ELF file */
1420 /* XXX: suppress unneeded sections */
1421 static int elf_output_file(TCCState *s1, const char *filename)
1423 ElfW(Ehdr) ehdr;
1424 FILE *f;
1425 int fd, mode, ret;
1426 int *section_order;
1427 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
1428 unsigned long addr;
1429 Section *strsec, *s;
1430 ElfW(Shdr) shdr, *sh;
1431 ElfW(Phdr) *phdr, *ph;
1432 Section *interp, *dynamic, *dynstr;
1433 unsigned long saved_dynamic_data_offset;
1434 ElfW(Sym) *sym;
1435 int type, file_type;
1436 unsigned long rel_addr, rel_size;
1437 unsigned long bss_addr, bss_size;
1439 file_type = s1->output_type;
1440 s1->nb_errors = 0;
1442 if (file_type != TCC_OUTPUT_OBJ) {
1443 tcc_add_runtime(s1);
1446 phdr = NULL;
1447 section_order = NULL;
1448 interp = NULL;
1449 dynamic = NULL;
1450 dynstr = NULL; /* avoid warning */
1451 saved_dynamic_data_offset = 0; /* avoid warning */
1453 if (file_type != TCC_OUTPUT_OBJ) {
1454 relocate_common_syms();
1456 tcc_add_linker_symbols(s1);
1458 if (!s1->static_link) {
1459 const char *name;
1460 int sym_index, index;
1461 ElfW(Sym) *esym, *sym_end;
1463 if (file_type == TCC_OUTPUT_EXE) {
1464 char *ptr;
1465 /* allow override the dynamic loader */
1466 const char *elfint = getenv("LD_SO");
1467 if (elfint == NULL)
1468 elfint = elf_interp;
1469 /* add interpreter section only if executable */
1470 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1471 interp->sh_addralign = 1;
1472 ptr = section_ptr_add(interp, 1+strlen(elfint));
1473 strcpy(ptr, elfint);
1476 /* add dynamic symbol table */
1477 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1478 ".dynstr",
1479 ".hash", SHF_ALLOC);
1480 dynstr = s1->dynsym->link;
1482 /* add dynamic section */
1483 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1484 SHF_ALLOC | SHF_WRITE);
1485 dynamic->link = dynstr;
1486 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1488 /* add PLT */
1489 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1490 SHF_ALLOC | SHF_EXECINSTR);
1491 s1->plt->sh_entsize = 4;
1493 build_got(s1);
1495 /* scan for undefined symbols and see if they are in the
1496 dynamic symbols. If a symbol STT_FUNC is found, then we
1497 add it in the PLT. If a symbol STT_OBJECT is found, we
1498 add it in the .bss section with a suitable relocation */
1499 sym_end = (ElfW(Sym) *)(symtab_section->data +
1500 symtab_section->data_offset);
1501 if (file_type == TCC_OUTPUT_EXE) {
1502 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1503 sym < sym_end;
1504 sym++) {
1505 if (sym->st_shndx == SHN_UNDEF) {
1506 name = symtab_section->link->data + sym->st_name;
1507 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1508 if (sym_index) {
1509 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1510 type = ELFW(ST_TYPE)(esym->st_info);
1511 if (type == STT_FUNC) {
1512 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1513 esym->st_info,
1514 sym - (ElfW(Sym) *)symtab_section->data);
1515 } else if (type == STT_OBJECT) {
1516 unsigned long offset;
1517 ElfW(Sym) *dynsym, *dynsym_end;
1518 offset = bss_section->data_offset;
1519 /* XXX: which alignment ? */
1520 offset = (offset + 16 - 1) & -16;
1521 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1522 esym->st_info, 0,
1523 bss_section->sh_num, name);
1524 /* Ensure symbol aliases (that is, symbols with
1525 the same st_value) resolve to the same
1526 address in program .bss or .data section. */
1527 dynsym_end = (ElfW(Sym) *)
1528 (s1->dynsymtab_section->data +
1529 s1->dynsymtab_section->data_offset);
1530 for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1531 dynsym < dynsym_end; dynsym++) {
1532 if (dynsym->st_value == esym->st_value) {
1533 char *dynname;
1534 dynname = s1->dynsymtab_section->link->data
1535 + dynsym->st_name;
1536 put_elf_sym(s1->dynsym, offset,
1537 dynsym->st_size,
1538 dynsym->st_info, 0,
1539 bss_section->sh_num,
1540 dynname);
1543 put_elf_reloc(s1->dynsym, bss_section,
1544 offset, R_COPY, index);
1545 offset += esym->st_size;
1546 bss_section->data_offset = offset;
1548 } else {
1549 /* STB_WEAK undefined symbols are accepted */
1550 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1551 it */
1552 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1553 !strcmp(name, "_fp_hw")) {
1554 } else {
1555 error_noabort("undefined symbol '%s'", name);
1558 } else if (s1->rdynamic &&
1559 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1560 /* if -rdynamic option, then export all non
1561 local symbols */
1562 name = symtab_section->link->data + sym->st_name;
1563 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1564 sym->st_info, 0,
1565 sym->st_shndx, name);
1569 if (s1->nb_errors)
1570 goto fail;
1572 /* now look at unresolved dynamic symbols and export
1573 corresponding symbol */
1574 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1575 s1->dynsymtab_section->data_offset);
1576 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1577 esym < sym_end;
1578 esym++) {
1579 if (esym->st_shndx == SHN_UNDEF) {
1580 name = s1->dynsymtab_section->link->data + esym->st_name;
1581 sym_index = find_elf_sym(symtab_section, name);
1582 if (sym_index) {
1583 /* XXX: avoid adding a symbol if already
1584 present because of -rdynamic ? */
1585 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1586 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1587 sym->st_info, 0,
1588 sym->st_shndx, name);
1589 } else {
1590 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1591 /* weak symbols can stay undefined */
1592 } else {
1593 warning("undefined dynamic symbol '%s'", name);
1598 } else {
1599 int nb_syms;
1600 /* shared library case : we simply export all the global symbols */
1601 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1602 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1603 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1604 sym < sym_end;
1605 sym++) {
1606 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1607 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1608 if (ELFW(ST_TYPE)(sym->st_info) == STT_FUNC &&
1609 sym->st_shndx == SHN_UNDEF) {
1610 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1611 sym->st_info,
1612 sym - (ElfW(Sym) *)symtab_section->data);
1614 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1615 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1616 sym->st_info,
1617 sym - (ElfW(Sym) *)symtab_section->data);
1619 else
1620 #endif
1622 name = symtab_section->link->data + sym->st_name;
1623 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1624 sym->st_info, 0,
1625 sym->st_shndx, name);
1626 s1->symtab_to_dynsym[sym -
1627 (ElfW(Sym) *)symtab_section->data] =
1628 index;
1634 build_got_entries(s1);
1636 /* add a list of needed dlls */
1637 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1638 DLLReference *dllref = s1->loaded_dlls[i];
1639 if (dllref->level == 0)
1640 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1643 if (s1->rpath)
1644 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1646 /* XXX: currently, since we do not handle PIC code, we
1647 must relocate the readonly segments */
1648 if (file_type == TCC_OUTPUT_DLL) {
1649 if (s1->soname)
1650 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1651 put_dt(dynamic, DT_TEXTREL, 0);
1654 if (s1->symbolic)
1655 put_dt(dynamic, DT_SYMBOLIC, 0);
1657 /* add necessary space for other entries */
1658 saved_dynamic_data_offset = dynamic->data_offset;
1659 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1660 } else {
1661 /* still need to build got entries in case of static link */
1662 build_got_entries(s1);
1666 memset(&ehdr, 0, sizeof(ehdr));
1668 /* we add a section for symbols */
1669 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1670 put_elf_str(strsec, "");
1672 /* compute number of sections */
1673 shnum = s1->nb_sections;
1675 /* this array is used to reorder sections in the output file */
1676 section_order = tcc_malloc(sizeof(int) * shnum);
1677 section_order[0] = 0;
1678 sh_order_index = 1;
1680 /* compute number of program headers */
1681 switch(file_type) {
1682 default:
1683 case TCC_OUTPUT_OBJ:
1684 phnum = 0;
1685 break;
1686 case TCC_OUTPUT_EXE:
1687 if (!s1->static_link)
1688 phnum = 4 + HAVE_PHDR;
1689 else
1690 phnum = 2;
1691 break;
1692 case TCC_OUTPUT_DLL:
1693 phnum = 3;
1694 break;
1697 /* allocate strings for section names and decide if an unallocated
1698 section should be output */
1699 /* NOTE: the strsec section comes last, so its size is also
1700 correct ! */
1701 for(i = 1; i < s1->nb_sections; i++) {
1702 s = s1->sections[i];
1703 s->sh_name = put_elf_str(strsec, s->name);
1704 #if 0 //gr
1705 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1706 s->sh_flags,
1707 s->sh_type,
1708 s->sh_info,
1709 s->name,
1710 s->reloc ? s->reloc->name : "n"
1712 #endif
1713 /* when generating a DLL, we include relocations but we may
1714 patch them */
1715 if (file_type == TCC_OUTPUT_DLL &&
1716 s->sh_type == SHT_RELX &&
1717 !(s->sh_flags & SHF_ALLOC)) {
1718 /* //gr: avoid bogus relocs for empty (debug) sections */
1719 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1720 prepare_dynamic_rel(s1, s);
1721 else if (s1->do_debug)
1722 s->sh_size = s->data_offset;
1723 } else if (s1->do_debug ||
1724 file_type == TCC_OUTPUT_OBJ ||
1725 (s->sh_flags & SHF_ALLOC) ||
1726 i == (s1->nb_sections - 1)) {
1727 /* we output all sections if debug or object file */
1728 s->sh_size = s->data_offset;
1732 /* allocate program segment headers */
1733 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1735 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1736 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1737 } else {
1738 file_offset = 0;
1740 if (phnum > 0) {
1741 /* compute section to program header mapping */
1742 if (s1->has_text_addr) {
1743 int a_offset, p_offset;
1744 addr = s1->text_addr;
1745 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1746 ELF_PAGE_SIZE */
1747 a_offset = addr & (s1->section_align - 1);
1748 p_offset = file_offset & (s1->section_align - 1);
1749 if (a_offset < p_offset)
1750 a_offset += s1->section_align;
1751 file_offset += (a_offset - p_offset);
1752 } else {
1753 if (file_type == TCC_OUTPUT_DLL)
1754 addr = 0;
1755 else
1756 addr = ELF_START_ADDR;
1757 /* compute address after headers */
1758 addr += (file_offset & (s1->section_align - 1));
1761 /* dynamic relocation table information, for .dynamic section */
1762 rel_size = 0;
1763 rel_addr = 0;
1765 bss_addr = bss_size = 0;
1766 /* leave one program header for the program interpreter */
1767 ph = &phdr[0];
1768 if (interp)
1769 ph += 1 + HAVE_PHDR;
1771 for(j = 0; j < 2; j++) {
1772 ph->p_type = PT_LOAD;
1773 if (j == 0)
1774 ph->p_flags = PF_R | PF_X;
1775 else
1776 ph->p_flags = PF_R | PF_W;
1777 ph->p_align = s1->section_align;
1779 /* we do the following ordering: interp, symbol tables,
1780 relocations, progbits, nobits */
1781 /* XXX: do faster and simpler sorting */
1782 for(k = 0; k < 5; k++) {
1783 for(i = 1; i < s1->nb_sections; i++) {
1784 s = s1->sections[i];
1785 /* compute if section should be included */
1786 if (j == 0) {
1787 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1788 SHF_ALLOC)
1789 continue;
1790 } else {
1791 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1792 (SHF_ALLOC | SHF_WRITE))
1793 continue;
1795 if (s == interp) {
1796 if (k != 0)
1797 continue;
1798 } else if (s->sh_type == SHT_DYNSYM ||
1799 s->sh_type == SHT_STRTAB ||
1800 s->sh_type == SHT_HASH) {
1801 if (k != 1)
1802 continue;
1803 } else if (s->sh_type == SHT_RELX) {
1804 if (k != 2)
1805 continue;
1806 } else if (s->sh_type == SHT_NOBITS) {
1807 if (k != 4)
1808 continue;
1809 } else {
1810 if (k != 3)
1811 continue;
1813 section_order[sh_order_index++] = i;
1815 /* section matches: we align it and add its size */
1816 tmp = addr;
1817 addr = (addr + s->sh_addralign - 1) &
1818 ~(s->sh_addralign - 1);
1819 file_offset += addr - tmp;
1820 s->sh_offset = file_offset;
1821 s->sh_addr = addr;
1823 /* update program header infos */
1824 if (ph->p_offset == 0) {
1825 ph->p_offset = file_offset;
1826 ph->p_vaddr = addr;
1827 ph->p_paddr = ph->p_vaddr;
1829 /* update dynamic relocation infos */
1830 if (s->sh_type == SHT_RELX) {
1831 #if defined(__FreeBSD__)
1832 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1833 rel_addr = addr;
1834 rel_size += s->sh_size; // XXX only first rel.
1836 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1837 bss_addr = addr;
1838 bss_size = s->sh_size; // XXX only first rel.
1840 #else
1841 if (rel_size == 0)
1842 rel_addr = addr;
1843 rel_size += s->sh_size;
1844 #endif
1846 addr += s->sh_size;
1847 if (s->sh_type != SHT_NOBITS)
1848 file_offset += s->sh_size;
1851 ph->p_filesz = file_offset - ph->p_offset;
1852 ph->p_memsz = addr - ph->p_vaddr;
1853 ph++;
1854 if (j == 0) {
1855 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1856 /* if in the middle of a page, we duplicate the page in
1857 memory so that one copy is RX and the other is RW */
1858 if ((addr & (s1->section_align - 1)) != 0)
1859 addr += s1->section_align;
1860 } else {
1861 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1862 file_offset = (file_offset + s1->section_align - 1) &
1863 ~(s1->section_align - 1);
1868 /* if interpreter, then add corresponing program header */
1869 if (interp) {
1870 ph = &phdr[0];
1872 #if defined(__FreeBSD__)
1874 int len = phnum * sizeof(ElfW(Phdr));
1876 ph->p_type = PT_PHDR;
1877 ph->p_offset = sizeof(ElfW(Ehdr));
1878 ph->p_vaddr = interp->sh_addr - len;
1879 ph->p_paddr = ph->p_vaddr;
1880 ph->p_filesz = ph->p_memsz = len;
1881 ph->p_flags = PF_R | PF_X;
1882 ph->p_align = 4; // interp->sh_addralign;
1883 ph++;
1885 #endif
1887 ph->p_type = PT_INTERP;
1888 ph->p_offset = interp->sh_offset;
1889 ph->p_vaddr = interp->sh_addr;
1890 ph->p_paddr = ph->p_vaddr;
1891 ph->p_filesz = interp->sh_size;
1892 ph->p_memsz = interp->sh_size;
1893 ph->p_flags = PF_R;
1894 ph->p_align = interp->sh_addralign;
1897 /* if dynamic section, then add corresponing program header */
1898 if (dynamic) {
1899 ElfW(Sym) *sym_end;
1901 ph = &phdr[phnum - 1];
1903 ph->p_type = PT_DYNAMIC;
1904 ph->p_offset = dynamic->sh_offset;
1905 ph->p_vaddr = dynamic->sh_addr;
1906 ph->p_paddr = ph->p_vaddr;
1907 ph->p_filesz = dynamic->sh_size;
1908 ph->p_memsz = dynamic->sh_size;
1909 ph->p_flags = PF_R | PF_W;
1910 ph->p_align = dynamic->sh_addralign;
1912 /* put GOT dynamic section address */
1913 put32(s1->got->data, dynamic->sh_addr);
1915 /* relocate the PLT */
1916 if (file_type == TCC_OUTPUT_EXE
1917 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1918 || file_type == TCC_OUTPUT_DLL
1919 #endif
1921 uint8_t *p, *p_end;
1923 p = s1->plt->data;
1924 p_end = p + s1->plt->data_offset;
1925 if (p < p_end) {
1926 #if defined(TCC_TARGET_I386)
1927 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1928 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1929 p += 16;
1930 while (p < p_end) {
1931 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1932 p += 16;
1934 #elif defined(TCC_TARGET_X86_64)
1935 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1936 put32(p + 2, get32(p + 2) + x);
1937 put32(p + 8, get32(p + 8) + x - 6);
1938 p += 16;
1939 while (p < p_end) {
1940 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1941 p += 16;
1943 #elif defined(TCC_TARGET_ARM)
1944 int x;
1945 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1946 p +=16;
1947 while (p < p_end) {
1948 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1949 p += 16;
1951 #elif defined(TCC_TARGET_C67)
1952 /* XXX: TODO */
1953 #else
1954 #error unsupported CPU
1955 #endif
1959 /* relocate symbols in .dynsym */
1960 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
1961 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
1962 sym < sym_end;
1963 sym++) {
1964 if (sym->st_shndx == SHN_UNDEF) {
1965 /* relocate to the PLT if the symbol corresponds
1966 to a PLT entry */
1967 if (sym->st_value)
1968 sym->st_value += s1->plt->sh_addr;
1969 } else if (sym->st_shndx < SHN_LORESERVE) {
1970 /* do symbol relocation */
1971 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
1975 /* put dynamic section entries */
1976 dynamic->data_offset = saved_dynamic_data_offset;
1977 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
1978 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
1979 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
1980 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
1981 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
1982 #ifdef TCC_TARGET_X86_64
1983 put_dt(dynamic, DT_RELA, rel_addr);
1984 put_dt(dynamic, DT_RELASZ, rel_size);
1985 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
1986 #else
1987 #if defined(__FreeBSD__)
1988 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
1989 put_dt(dynamic, DT_PLTRELSZ, rel_size);
1990 put_dt(dynamic, DT_JMPREL, rel_addr);
1991 put_dt(dynamic, DT_PLTREL, DT_REL);
1992 put_dt(dynamic, DT_REL, bss_addr);
1993 put_dt(dynamic, DT_RELSZ, bss_size);
1994 #else
1995 put_dt(dynamic, DT_REL, rel_addr);
1996 put_dt(dynamic, DT_RELSZ, rel_size);
1997 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
1998 #endif
1999 #endif
2000 if (s1->do_debug)
2001 put_dt(dynamic, DT_DEBUG, 0);
2002 put_dt(dynamic, DT_NULL, 0);
2005 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2006 ehdr.e_phnum = phnum;
2007 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2010 /* all other sections come after */
2011 for(i = 1; i < s1->nb_sections; i++) {
2012 s = s1->sections[i];
2013 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2014 continue;
2015 section_order[sh_order_index++] = i;
2017 file_offset = (file_offset + s->sh_addralign - 1) &
2018 ~(s->sh_addralign - 1);
2019 s->sh_offset = file_offset;
2020 if (s->sh_type != SHT_NOBITS)
2021 file_offset += s->sh_size;
2024 /* if building executable or DLL, then relocate each section
2025 except the GOT which is already relocated */
2026 if (file_type != TCC_OUTPUT_OBJ) {
2027 relocate_syms(s1, 0);
2029 if (s1->nb_errors != 0) {
2030 fail:
2031 ret = -1;
2032 goto the_end;
2035 /* relocate sections */
2036 /* XXX: ignore sections with allocated relocations ? */
2037 for(i = 1; i < s1->nb_sections; i++) {
2038 s = s1->sections[i];
2039 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
2040 relocate_section(s1, s);
2043 /* relocate relocation entries if the relocation tables are
2044 allocated in the executable */
2045 for(i = 1; i < s1->nb_sections; i++) {
2046 s = s1->sections[i];
2047 if ((s->sh_flags & SHF_ALLOC) &&
2048 s->sh_type == SHT_RELX) {
2049 relocate_rel(s1, s);
2053 /* get entry point address */
2054 if (file_type == TCC_OUTPUT_EXE)
2055 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
2056 else
2057 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2059 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2060 fill_got(s1);
2062 /* write elf file */
2063 if (file_type == TCC_OUTPUT_OBJ)
2064 mode = 0666;
2065 else
2066 mode = 0777;
2067 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2068 if (fd < 0) {
2069 error_noabort("could not write '%s'", filename);
2070 goto fail;
2072 f = fdopen(fd, "wb");
2073 if (s1->verbose)
2074 printf("<- %s\n", filename);
2076 #ifdef TCC_TARGET_COFF
2077 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2078 tcc_output_coff(s1, f);
2079 } else
2080 #endif
2081 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2082 sort_syms(s1, symtab_section);
2084 /* align to 4 */
2085 file_offset = (file_offset + 3) & -4;
2087 /* fill header */
2088 ehdr.e_ident[0] = ELFMAG0;
2089 ehdr.e_ident[1] = ELFMAG1;
2090 ehdr.e_ident[2] = ELFMAG2;
2091 ehdr.e_ident[3] = ELFMAG3;
2092 ehdr.e_ident[4] = TCC_ELFCLASS;
2093 ehdr.e_ident[5] = ELFDATA2LSB;
2094 ehdr.e_ident[6] = EV_CURRENT;
2095 #ifdef __FreeBSD__
2096 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2097 #endif
2098 #ifdef TCC_TARGET_ARM
2099 #ifdef TCC_ARM_EABI
2100 ehdr.e_ident[EI_OSABI] = 0;
2101 ehdr.e_flags = 4 << 24;
2102 #else
2103 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2104 #endif
2105 #endif
2106 switch(file_type) {
2107 default:
2108 case TCC_OUTPUT_EXE:
2109 ehdr.e_type = ET_EXEC;
2110 break;
2111 case TCC_OUTPUT_DLL:
2112 ehdr.e_type = ET_DYN;
2113 break;
2114 case TCC_OUTPUT_OBJ:
2115 ehdr.e_type = ET_REL;
2116 break;
2118 ehdr.e_machine = EM_TCC_TARGET;
2119 ehdr.e_version = EV_CURRENT;
2120 ehdr.e_shoff = file_offset;
2121 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2122 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2123 ehdr.e_shnum = shnum;
2124 ehdr.e_shstrndx = shnum - 1;
2126 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2127 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2128 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2130 for(i=1;i<s1->nb_sections;i++) {
2131 s = s1->sections[section_order[i]];
2132 if (s->sh_type != SHT_NOBITS) {
2133 #if defined(__FreeBSD__)
2134 if (s->sh_type == SHT_DYNSYM)
2135 patch_dynsym_undef(s1, s);
2136 #endif
2137 while (offset < s->sh_offset) {
2138 fputc(0, f);
2139 offset++;
2141 size = s->sh_size;
2142 fwrite(s->data, 1, size, f);
2143 offset += size;
2147 /* output section headers */
2148 while (offset < ehdr.e_shoff) {
2149 fputc(0, f);
2150 offset++;
2153 for(i=0;i<s1->nb_sections;i++) {
2154 sh = &shdr;
2155 memset(sh, 0, sizeof(ElfW(Shdr)));
2156 s = s1->sections[i];
2157 if (s) {
2158 sh->sh_name = s->sh_name;
2159 sh->sh_type = s->sh_type;
2160 sh->sh_flags = s->sh_flags;
2161 sh->sh_entsize = s->sh_entsize;
2162 sh->sh_info = s->sh_info;
2163 if (s->link)
2164 sh->sh_link = s->link->sh_num;
2165 sh->sh_addralign = s->sh_addralign;
2166 sh->sh_addr = s->sh_addr;
2167 sh->sh_offset = s->sh_offset;
2168 sh->sh_size = s->sh_size;
2170 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2172 } else {
2173 tcc_output_binary(s1, f, section_order);
2175 fclose(f);
2177 ret = 0;
2178 the_end:
2179 tcc_free(s1->symtab_to_dynsym);
2180 tcc_free(section_order);
2181 tcc_free(phdr);
2182 tcc_free(s1->got_offsets);
2183 return ret;
2186 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2188 int ret;
2189 #ifdef TCC_TARGET_PE
2190 if (s->output_type != TCC_OUTPUT_OBJ) {
2191 ret = pe_output_file(s, filename);
2192 } else
2193 #endif
2195 ret = elf_output_file(s, filename);
2197 return ret;
2200 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2202 void *data;
2204 data = tcc_malloc(size);
2205 lseek(fd, file_offset, SEEK_SET);
2206 read(fd, data, size);
2207 return data;
2210 typedef struct SectionMergeInfo {
2211 Section *s; /* corresponding existing section */
2212 unsigned long offset; /* offset of the new section in the existing section */
2213 uint8_t new_section; /* true if section 's' was added */
2214 uint8_t link_once; /* true if link once section */
2215 } SectionMergeInfo;
2217 /* load an object file and merge it with current files */
2218 /* XXX: handle correctly stab (debug) info */
2219 ST_FUNC int tcc_load_object_file(TCCState *s1,
2220 int fd, unsigned long file_offset)
2222 ElfW(Ehdr) ehdr;
2223 ElfW(Shdr) *shdr, *sh;
2224 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2225 unsigned char *strsec, *strtab;
2226 int *old_to_new_syms;
2227 char *sh_name, *name;
2228 SectionMergeInfo *sm_table, *sm;
2229 ElfW(Sym) *sym, *symtab;
2230 ElfW_Rel *rel, *rel_end;
2231 Section *s;
2233 int stab_index;
2234 int stabstr_index;
2236 stab_index = stabstr_index = 0;
2238 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2239 goto fail1;
2240 if (ehdr.e_ident[0] != ELFMAG0 ||
2241 ehdr.e_ident[1] != ELFMAG1 ||
2242 ehdr.e_ident[2] != ELFMAG2 ||
2243 ehdr.e_ident[3] != ELFMAG3)
2244 goto fail1;
2245 /* test if object file */
2246 if (ehdr.e_type != ET_REL)
2247 goto fail1;
2248 /* test CPU specific stuff */
2249 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2250 ehdr.e_machine != EM_TCC_TARGET) {
2251 fail1:
2252 error_noabort("invalid object file");
2253 return -1;
2255 /* read sections */
2256 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2257 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2258 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2260 /* load section names */
2261 sh = &shdr[ehdr.e_shstrndx];
2262 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2264 /* load symtab and strtab */
2265 old_to_new_syms = NULL;
2266 symtab = NULL;
2267 strtab = NULL;
2268 nb_syms = 0;
2269 for(i = 1; i < ehdr.e_shnum; i++) {
2270 sh = &shdr[i];
2271 if (sh->sh_type == SHT_SYMTAB) {
2272 if (symtab) {
2273 error_noabort("object must contain only one symtab");
2274 fail:
2275 ret = -1;
2276 goto the_end;
2278 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2279 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2280 sm_table[i].s = symtab_section;
2282 /* now load strtab */
2283 sh = &shdr[sh->sh_link];
2284 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2288 /* now examine each section and try to merge its content with the
2289 ones in memory */
2290 for(i = 1; i < ehdr.e_shnum; i++) {
2291 /* no need to examine section name strtab */
2292 if (i == ehdr.e_shstrndx)
2293 continue;
2294 sh = &shdr[i];
2295 sh_name = strsec + sh->sh_name;
2296 /* ignore sections types we do not handle */
2297 if (sh->sh_type != SHT_PROGBITS &&
2298 sh->sh_type != SHT_RELX &&
2299 #ifdef TCC_ARM_EABI
2300 sh->sh_type != SHT_ARM_EXIDX &&
2301 #endif
2302 sh->sh_type != SHT_NOBITS &&
2303 strcmp(sh_name, ".stabstr")
2305 continue;
2306 if (sh->sh_addralign < 1)
2307 sh->sh_addralign = 1;
2308 /* find corresponding section, if any */
2309 for(j = 1; j < s1->nb_sections;j++) {
2310 s = s1->sections[j];
2311 if (!strcmp(s->name, sh_name)) {
2312 if (!strncmp(sh_name, ".gnu.linkonce",
2313 sizeof(".gnu.linkonce") - 1)) {
2314 /* if a 'linkonce' section is already present, we
2315 do not add it again. It is a little tricky as
2316 symbols can still be defined in
2317 it. */
2318 sm_table[i].link_once = 1;
2319 goto next;
2320 } else {
2321 goto found;
2325 /* not found: create new section */
2326 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2327 /* take as much info as possible from the section. sh_link and
2328 sh_info will be updated later */
2329 s->sh_addralign = sh->sh_addralign;
2330 s->sh_entsize = sh->sh_entsize;
2331 sm_table[i].new_section = 1;
2332 found:
2333 if (sh->sh_type != s->sh_type) {
2334 error_noabort("invalid section type");
2335 goto fail;
2338 /* align start of section */
2339 offset = s->data_offset;
2341 if (0 == strcmp(sh_name, ".stab")) {
2342 stab_index = i;
2343 goto no_align;
2345 if (0 == strcmp(sh_name, ".stabstr")) {
2346 stabstr_index = i;
2347 goto no_align;
2350 size = sh->sh_addralign - 1;
2351 offset = (offset + size) & ~size;
2352 if (sh->sh_addralign > s->sh_addralign)
2353 s->sh_addralign = sh->sh_addralign;
2354 s->data_offset = offset;
2355 no_align:
2356 sm_table[i].offset = offset;
2357 sm_table[i].s = s;
2358 /* concatenate sections */
2359 size = sh->sh_size;
2360 if (sh->sh_type != SHT_NOBITS) {
2361 unsigned char *ptr;
2362 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2363 ptr = section_ptr_add(s, size);
2364 read(fd, ptr, size);
2365 } else {
2366 s->data_offset += size;
2368 next: ;
2371 /* //gr relocate stab strings */
2372 if (stab_index && stabstr_index) {
2373 Stab_Sym *a, *b;
2374 unsigned o;
2375 s = sm_table[stab_index].s;
2376 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2377 b = (Stab_Sym *)(s->data + s->data_offset);
2378 o = sm_table[stabstr_index].offset;
2379 while (a < b)
2380 a->n_strx += o, a++;
2383 /* second short pass to update sh_link and sh_info fields of new
2384 sections */
2385 for(i = 1; i < ehdr.e_shnum; i++) {
2386 s = sm_table[i].s;
2387 if (!s || !sm_table[i].new_section)
2388 continue;
2389 sh = &shdr[i];
2390 if (sh->sh_link > 0)
2391 s->link = sm_table[sh->sh_link].s;
2392 if (sh->sh_type == SHT_RELX) {
2393 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2394 /* update backward link */
2395 s1->sections[s->sh_info]->reloc = s;
2398 sm = sm_table;
2400 /* resolve symbols */
2401 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2403 sym = symtab + 1;
2404 for(i = 1; i < nb_syms; i++, sym++) {
2405 if (sym->st_shndx != SHN_UNDEF &&
2406 sym->st_shndx < SHN_LORESERVE) {
2407 sm = &sm_table[sym->st_shndx];
2408 if (sm->link_once) {
2409 /* if a symbol is in a link once section, we use the
2410 already defined symbol. It is very important to get
2411 correct relocations */
2412 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2413 name = strtab + sym->st_name;
2414 sym_index = find_elf_sym(symtab_section, name);
2415 if (sym_index)
2416 old_to_new_syms[i] = sym_index;
2418 continue;
2420 /* if no corresponding section added, no need to add symbol */
2421 if (!sm->s)
2422 continue;
2423 /* convert section number */
2424 sym->st_shndx = sm->s->sh_num;
2425 /* offset value */
2426 sym->st_value += sm->offset;
2428 /* add symbol */
2429 name = strtab + sym->st_name;
2430 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2431 sym->st_info, sym->st_other,
2432 sym->st_shndx, name);
2433 old_to_new_syms[i] = sym_index;
2436 /* third pass to patch relocation entries */
2437 for(i = 1; i < ehdr.e_shnum; i++) {
2438 s = sm_table[i].s;
2439 if (!s)
2440 continue;
2441 sh = &shdr[i];
2442 offset = sm_table[i].offset;
2443 switch(s->sh_type) {
2444 case SHT_RELX:
2445 /* take relocation offset information */
2446 offseti = sm_table[sh->sh_info].offset;
2447 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2448 for(rel = (ElfW_Rel *)(s->data + offset);
2449 rel < rel_end;
2450 rel++) {
2451 int type;
2452 unsigned sym_index;
2453 /* convert symbol index */
2454 type = ELFW(R_TYPE)(rel->r_info);
2455 sym_index = ELFW(R_SYM)(rel->r_info);
2456 /* NOTE: only one symtab assumed */
2457 if (sym_index >= nb_syms)
2458 goto invalid_reloc;
2459 sym_index = old_to_new_syms[sym_index];
2460 /* ignore link_once in rel section. */
2461 if (!sym_index && !sm->link_once) {
2462 invalid_reloc:
2463 error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2464 i, strsec + sh->sh_name, rel->r_offset);
2465 goto fail;
2467 rel->r_info = ELFW(R_INFO)(sym_index, type);
2468 /* offset the relocation offset */
2469 rel->r_offset += offseti;
2471 break;
2472 default:
2473 break;
2477 ret = 0;
2478 the_end:
2479 tcc_free(symtab);
2480 tcc_free(strtab);
2481 tcc_free(old_to_new_syms);
2482 tcc_free(sm_table);
2483 tcc_free(strsec);
2484 tcc_free(shdr);
2485 return ret;
2488 typedef struct ArchiveHeader {
2489 char ar_name[16]; /* name of this member */
2490 char ar_date[12]; /* file mtime */
2491 char ar_uid[6]; /* owner uid; printed as decimal */
2492 char ar_gid[6]; /* owner gid; printed as decimal */
2493 char ar_mode[8]; /* file mode, printed as octal */
2494 char ar_size[10]; /* file size, printed as decimal */
2495 char ar_fmag[2]; /* should contain ARFMAG */
2496 } ArchiveHeader;
2498 static int get_be32(const uint8_t *b)
2500 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2503 /* load only the objects which resolve undefined symbols */
2504 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2506 int i, bound, nsyms, sym_index, off, ret;
2507 uint8_t *data;
2508 const char *ar_names, *p;
2509 const uint8_t *ar_index;
2510 ElfW(Sym) *sym;
2512 data = tcc_malloc(size);
2513 if (read(fd, data, size) != size)
2514 goto fail;
2515 nsyms = get_be32(data);
2516 ar_index = data + 4;
2517 ar_names = ar_index + nsyms * 4;
2519 do {
2520 bound = 0;
2521 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2522 sym_index = find_elf_sym(symtab_section, p);
2523 if(sym_index) {
2524 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2525 if(sym->st_shndx == SHN_UNDEF) {
2526 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2527 #if 0
2528 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2529 #endif
2530 ++bound;
2531 lseek(fd, off, SEEK_SET);
2532 if(tcc_load_object_file(s1, fd, off) < 0) {
2533 fail:
2534 ret = -1;
2535 goto the_end;
2540 } while(bound);
2541 ret = 0;
2542 the_end:
2543 tcc_free(data);
2544 return ret;
2547 /* load a '.a' file */
2548 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2550 ArchiveHeader hdr;
2551 char ar_size[11];
2552 char ar_name[17];
2553 char magic[8];
2554 int size, len, i;
2555 unsigned long file_offset;
2557 /* skip magic which was already checked */
2558 read(fd, magic, sizeof(magic));
2560 for(;;) {
2561 len = read(fd, &hdr, sizeof(hdr));
2562 if (len == 0)
2563 break;
2564 if (len != sizeof(hdr)) {
2565 error_noabort("invalid archive");
2566 return -1;
2568 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2569 ar_size[sizeof(hdr.ar_size)] = '\0';
2570 size = strtol(ar_size, NULL, 0);
2571 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2572 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2573 if (ar_name[i] != ' ')
2574 break;
2576 ar_name[i + 1] = '\0';
2577 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2578 file_offset = lseek(fd, 0, SEEK_CUR);
2579 /* align to even */
2580 size = (size + 1) & ~1;
2581 if (!strcmp(ar_name, "/")) {
2582 /* coff symbol table : we handle it */
2583 if(s1->alacarte_link)
2584 return tcc_load_alacarte(s1, fd, size);
2585 } else if (!strcmp(ar_name, "//") ||
2586 !strcmp(ar_name, "__.SYMDEF") ||
2587 !strcmp(ar_name, "__.SYMDEF/") ||
2588 !strcmp(ar_name, "ARFILENAMES/")) {
2589 /* skip symbol table or archive names */
2590 } else {
2591 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2592 return -1;
2594 lseek(fd, file_offset + size, SEEK_SET);
2596 return 0;
2599 #ifndef TCC_TARGET_PE
2600 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2601 is referenced by the user (so it should be added as DT_NEEDED in
2602 the generated ELF file) */
2603 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2605 ElfW(Ehdr) ehdr;
2606 ElfW(Shdr) *shdr, *sh, *sh1;
2607 int i, j, nb_syms, nb_dts, sym_bind, ret;
2608 ElfW(Sym) *sym, *dynsym;
2609 ElfW(Dyn) *dt, *dynamic;
2610 unsigned char *dynstr;
2611 const char *name, *soname;
2612 DLLReference *dllref;
2614 read(fd, &ehdr, sizeof(ehdr));
2616 /* test CPU specific stuff */
2617 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2618 ehdr.e_machine != EM_TCC_TARGET) {
2619 error_noabort("bad architecture");
2620 return -1;
2623 /* read sections */
2624 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2626 /* load dynamic section and dynamic symbols */
2627 nb_syms = 0;
2628 nb_dts = 0;
2629 dynamic = NULL;
2630 dynsym = NULL; /* avoid warning */
2631 dynstr = NULL; /* avoid warning */
2632 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2633 switch(sh->sh_type) {
2634 case SHT_DYNAMIC:
2635 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2636 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2637 break;
2638 case SHT_DYNSYM:
2639 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2640 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2641 sh1 = &shdr[sh->sh_link];
2642 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2643 break;
2644 default:
2645 break;
2649 /* compute the real library name */
2650 soname = tcc_basename(filename);
2652 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2653 if (dt->d_tag == DT_SONAME) {
2654 soname = dynstr + dt->d_un.d_val;
2658 /* if the dll is already loaded, do not load it */
2659 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2660 dllref = s1->loaded_dlls[i];
2661 if (!strcmp(soname, dllref->name)) {
2662 /* but update level if needed */
2663 if (level < dllref->level)
2664 dllref->level = level;
2665 ret = 0;
2666 goto the_end;
2670 // printf("loading dll '%s'\n", soname);
2672 /* add the dll and its level */
2673 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2674 dllref->level = level;
2675 strcpy(dllref->name, soname);
2676 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2678 /* add dynamic symbols in dynsym_section */
2679 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2680 sym_bind = ELFW(ST_BIND)(sym->st_info);
2681 if (sym_bind == STB_LOCAL)
2682 continue;
2683 name = dynstr + sym->st_name;
2684 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2685 sym->st_info, sym->st_other, sym->st_shndx, name);
2688 /* load all referenced DLLs */
2689 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2690 switch(dt->d_tag) {
2691 case DT_NEEDED:
2692 name = dynstr + dt->d_un.d_val;
2693 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2694 dllref = s1->loaded_dlls[j];
2695 if (!strcmp(name, dllref->name))
2696 goto already_loaded;
2698 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2699 error_noabort("referenced dll '%s' not found", name);
2700 ret = -1;
2701 goto the_end;
2703 already_loaded:
2704 break;
2707 ret = 0;
2708 the_end:
2709 tcc_free(dynstr);
2710 tcc_free(dynsym);
2711 tcc_free(dynamic);
2712 tcc_free(shdr);
2713 return ret;
2716 #define LD_TOK_NAME 256
2717 #define LD_TOK_EOF (-1)
2719 /* return next ld script token */
2720 static int ld_next(TCCState *s1, char *name, int name_size)
2722 int c;
2723 char *q;
2725 redo:
2726 switch(ch) {
2727 case ' ':
2728 case '\t':
2729 case '\f':
2730 case '\v':
2731 case '\r':
2732 case '\n':
2733 inp();
2734 goto redo;
2735 case '/':
2736 minp();
2737 if (ch == '*') {
2738 file->buf_ptr = parse_comment(file->buf_ptr);
2739 ch = file->buf_ptr[0];
2740 goto redo;
2741 } else {
2742 q = name;
2743 *q++ = '/';
2744 goto parse_name;
2746 break;
2747 /* case 'a' ... 'z': */
2748 case 'a':
2749 case 'b':
2750 case 'c':
2751 case 'd':
2752 case 'e':
2753 case 'f':
2754 case 'g':
2755 case 'h':
2756 case 'i':
2757 case 'j':
2758 case 'k':
2759 case 'l':
2760 case 'm':
2761 case 'n':
2762 case 'o':
2763 case 'p':
2764 case 'q':
2765 case 'r':
2766 case 's':
2767 case 't':
2768 case 'u':
2769 case 'v':
2770 case 'w':
2771 case 'x':
2772 case 'y':
2773 case 'z':
2774 /* case 'A' ... 'z': */
2775 case 'A':
2776 case 'B':
2777 case 'C':
2778 case 'D':
2779 case 'E':
2780 case 'F':
2781 case 'G':
2782 case 'H':
2783 case 'I':
2784 case 'J':
2785 case 'K':
2786 case 'L':
2787 case 'M':
2788 case 'N':
2789 case 'O':
2790 case 'P':
2791 case 'Q':
2792 case 'R':
2793 case 'S':
2794 case 'T':
2795 case 'U':
2796 case 'V':
2797 case 'W':
2798 case 'X':
2799 case 'Y':
2800 case 'Z':
2801 case '_':
2802 case '\\':
2803 case '.':
2804 case '$':
2805 case '~':
2806 q = name;
2807 parse_name:
2808 for(;;) {
2809 if (!((ch >= 'a' && ch <= 'z') ||
2810 (ch >= 'A' && ch <= 'Z') ||
2811 (ch >= '0' && ch <= '9') ||
2812 strchr("/.-_+=$:\\,~", ch)))
2813 break;
2814 if ((q - name) < name_size - 1) {
2815 *q++ = ch;
2817 minp();
2819 *q = '\0';
2820 c = LD_TOK_NAME;
2821 break;
2822 case CH_EOF:
2823 c = LD_TOK_EOF;
2824 break;
2825 default:
2826 c = ch;
2827 inp();
2828 break;
2830 #if 0
2831 printf("tok=%c %d\n", c, c);
2832 if (c == LD_TOK_NAME)
2833 printf(" name=%s\n", name);
2834 #endif
2835 return c;
2838 char *tcc_strcpy_part(char *out, const char *in, size_t num)
2840 memcpy(out, in, num);
2841 out[num] = '\0';
2842 return out;
2846 * Extract the library name from the file name
2847 * Return 0 if the file isn't a library
2849 * /!\ No test on filename capacity, be careful
2851 static int filename_to_libname(TCCState *s1, const char filename[], char libname[])
2853 char *ext;
2854 int libprefix;
2856 /* already converted to library name */
2857 if (libname[0] != '\0')
2858 return 1;
2859 ext = tcc_fileextension(filename);
2860 if (*ext == '\0')
2861 return 0;
2862 libprefix = !strncmp(filename, "lib", 3);
2863 if (!s1->static_link) {
2864 #ifdef TCC_TARGET_PE
2865 if (!strcmp(ext, ".def")) {
2866 size_t len = ext - filename;
2867 tcc_strcpy_part(libname, filename, len);
2868 return 1;
2870 #else
2871 if (libprefix && (!strcmp(ext, ".so"))) {
2872 size_t len = ext - filename - 3;
2873 tcc_strcpy_part(libname, filename + 3, len);
2874 return 1;
2876 #endif
2877 } else {
2878 if (libprefix && (!strcmp(ext, ".a"))) {
2879 size_t len = ext - filename - 3;
2880 tcc_strcpy_part(libname, filename + 3, len);
2881 return 1;
2884 return 0;
2888 * Extract the file name from the library name
2890 * /!\ No test on filename capacity, be careful
2892 static void libname_to_filename(TCCState *s1, const char libname[], char filename[])
2894 if (!s1->static_link) {
2895 #ifdef TCC_TARGET_PE
2896 sprintf(filename, "%s.def", libname);
2897 #else
2898 sprintf(filename, "lib%s.so", libname);
2899 #endif
2900 } else {
2901 sprintf(filename, "lib%s.a", libname);
2905 static int ld_add_file(TCCState *s1, const char filename[], char libname[])
2907 int ret;
2909 ret = tcc_add_file_internal(s1, filename, 0);
2910 if (ret) {
2911 if (filename_to_libname(s1, filename, libname))
2912 ret = tcc_add_library(s1, libname);
2914 return ret;
2917 static inline int new_undef_syms(void)
2919 int ret = 0;
2920 ret = new_undef_sym;
2921 new_undef_sym = 0;
2922 return ret;
2925 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
2927 char filename[1024], libname[1024];
2928 int t, group, nblibs = 0, ret = 0;
2929 char **libs = NULL;
2931 group = !strcmp(cmd, "GROUP");
2932 if (!as_needed)
2933 new_undef_syms();
2934 t = ld_next(s1, filename, sizeof(filename));
2935 if (t != '(')
2936 expect("(");
2937 t = ld_next(s1, filename, sizeof(filename));
2938 for(;;) {
2939 libname[0] = '\0';
2940 if (t == LD_TOK_EOF) {
2941 error_noabort("unexpected end of file");
2942 ret = -1;
2943 goto lib_parse_error;
2944 } else if (t == ')') {
2945 break;
2946 } else if (t == '-') {
2947 t = ld_next(s1, filename, sizeof(filename));
2948 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
2949 error_noabort("library name expected");
2950 ret = -1;
2951 goto lib_parse_error;
2953 strcpy(libname, &filename[1]);
2954 libname_to_filename(s1, libname, filename);
2955 } else if (t != LD_TOK_NAME) {
2956 error_noabort("filename expected");
2957 ret = -1;
2958 goto lib_parse_error;
2960 if (!strcmp(filename, "AS_NEEDED")) {
2961 ret = ld_add_file_list(s1, cmd, 1);
2962 if (ret)
2963 goto lib_parse_error;
2964 } else {
2965 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2966 if (!as_needed) {
2967 ret = ld_add_file(s1, filename, libname);
2968 if (ret)
2969 goto lib_parse_error;
2970 if (group) {
2971 /* Add the filename *and* the libname to avoid future conversions */
2972 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
2973 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
2977 t = ld_next(s1, filename, sizeof(filename));
2978 if (t == ',') {
2979 t = ld_next(s1, filename, sizeof(filename));
2982 if (group && !as_needed) {
2983 while (new_undef_syms()) {
2984 int i;
2986 for (i = 0; i < nblibs; i += 2)
2987 ld_add_file(s1, libs[i], libs[i+1]);
2990 lib_parse_error:
2991 dynarray_reset(&libs, &nblibs);
2992 return ret;
2995 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
2996 files */
2997 ST_FUNC int tcc_load_ldscript(TCCState *s1)
2999 char cmd[64];
3000 char filename[1024];
3001 int t, ret;
3003 ch = file->buf_ptr[0];
3004 ch = handle_eob();
3005 for(;;) {
3006 t = ld_next(s1, cmd, sizeof(cmd));
3007 if (t == LD_TOK_EOF)
3008 return 0;
3009 else if (t != LD_TOK_NAME)
3010 return -1;
3011 if (!strcmp(cmd, "INPUT") ||
3012 !strcmp(cmd, "GROUP")) {
3013 ret = ld_add_file_list(s1, cmd, 0);
3014 if (ret)
3015 return ret;
3016 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3017 !strcmp(cmd, "TARGET")) {
3018 /* ignore some commands */
3019 t = ld_next(s1, cmd, sizeof(cmd));
3020 if (t != '(')
3021 expect("(");
3022 for(;;) {
3023 t = ld_next(s1, filename, sizeof(filename));
3024 if (t == LD_TOK_EOF) {
3025 error_noabort("unexpected end of file");
3026 return -1;
3027 } else if (t == ')') {
3028 break;
3031 } else {
3032 return -1;
3035 return 0;
3037 #endif