tccelf: fix warning
[tinycc.git] / tccelf.c
blob4f16ecfa2e21e417f0d7aa639716f5fade8ec7b5
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 /* XXX: DLL with PLT would only work with x86-64 for now */
36 //#define TCC_OUTPUT_DLL_WITH_PLT
38 ST_FUNC int put_elf_str(Section *s, const char *sym)
40 int offset, len;
41 char *ptr;
43 len = strlen(sym) + 1;
44 offset = s->data_offset;
45 ptr = section_ptr_add(s, len);
46 memcpy(ptr, sym, len);
47 return offset;
50 /* elf symbol hashing function */
51 static unsigned long elf_hash(const unsigned char *name)
53 unsigned long h = 0, g;
55 while (*name) {
56 h = (h << 4) + *name++;
57 g = h & 0xf0000000;
58 if (g)
59 h ^= g >> 24;
60 h &= ~g;
62 return h;
65 /* rebuild hash table of section s */
66 /* NOTE: we do factorize the hash table code to go faster */
67 static void rebuild_hash(Section *s, unsigned int nb_buckets)
69 ElfW(Sym) *sym;
70 int *ptr, *hash, nb_syms, sym_index, h;
71 char *strtab;
73 strtab = s->link->data;
74 nb_syms = s->data_offset / sizeof(ElfW(Sym));
76 s->hash->data_offset = 0;
77 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
78 ptr[0] = nb_buckets;
79 ptr[1] = nb_syms;
80 ptr += 2;
81 hash = ptr;
82 memset(hash, 0, (nb_buckets + 1) * sizeof(int));
83 ptr += nb_buckets + 1;
85 sym = (ElfW(Sym) *)s->data + 1;
86 for(sym_index = 1; sym_index < nb_syms; sym_index++) {
87 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
88 h = elf_hash(strtab + sym->st_name) % nb_buckets;
89 *ptr = hash[h];
90 hash[h] = sym_index;
91 } else {
92 *ptr = 0;
94 ptr++;
95 sym++;
99 /* return the symbol number */
100 ST_FUNC int put_elf_sym(Section *s, uplong value, unsigned long size,
101 int info, int other, int shndx, const char *name)
103 int name_offset, sym_index;
104 int nbuckets, h;
105 ElfW(Sym) *sym;
106 Section *hs;
108 sym = section_ptr_add(s, sizeof(ElfW(Sym)));
109 if (name)
110 name_offset = put_elf_str(s->link, name);
111 else
112 name_offset = 0;
113 /* XXX: endianness */
114 sym->st_name = name_offset;
115 sym->st_value = value;
116 sym->st_size = size;
117 sym->st_info = info;
118 sym->st_other = other;
119 sym->st_shndx = shndx;
120 sym_index = sym - (ElfW(Sym) *)s->data;
121 hs = s->hash;
122 if (hs) {
123 int *ptr, *base;
124 ptr = section_ptr_add(hs, sizeof(int));
125 base = (int *)hs->data;
126 /* only add global or weak symbols */
127 if (ELFW(ST_BIND)(info) != STB_LOCAL) {
128 /* add another hashing entry */
129 nbuckets = base[0];
130 h = elf_hash(name) % nbuckets;
131 *ptr = base[2 + h];
132 base[2 + h] = sym_index;
133 base[1]++;
134 /* we resize the hash table */
135 hs->nb_hashed_syms++;
136 if (hs->nb_hashed_syms > 2 * nbuckets) {
137 rebuild_hash(s, 2 * nbuckets);
139 } else {
140 *ptr = 0;
141 base[1]++;
144 return sym_index;
147 /* find global ELF symbol 'name' and return its index. Return 0 if not
148 found. */
149 ST_FUNC int find_elf_sym(Section *s, const char *name)
151 ElfW(Sym) *sym;
152 Section *hs;
153 int nbuckets, sym_index, h;
154 const char *name1;
156 hs = s->hash;
157 if (!hs)
158 return 0;
159 nbuckets = ((int *)hs->data)[0];
160 h = elf_hash(name) % nbuckets;
161 sym_index = ((int *)hs->data)[2 + h];
162 while (sym_index != 0) {
163 sym = &((ElfW(Sym) *)s->data)[sym_index];
164 name1 = s->link->data + sym->st_name;
165 if (!strcmp(name, name1))
166 return sym_index;
167 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
169 return 0;
172 /* return elf symbol value, signal error if 'err' is nonzero */
173 static void *get_elf_sym_addr(TCCState *s, const char *name, int err)
175 int sym_index;
176 ElfW(Sym) *sym;
178 sym_index = find_elf_sym(symtab_section, name);
179 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
180 if (!sym_index || sym->st_shndx == SHN_UNDEF) {
181 if (err)
182 error("%s not defined", name);
183 return NULL;
185 return (void*)(uplong)sym->st_value;
188 /* return elf symbol value */
189 LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
191 return get_elf_sym_addr(s, name, 0);
194 /* return elf symbol value or error */
195 ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name)
197 return get_elf_sym_addr(s, name, 1);
200 /* add an elf symbol : check if it is already defined and patch
201 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
202 ST_FUNC int add_elf_sym(Section *s, uplong value, unsigned long size,
203 int info, int other, int sh_num, const char *name)
205 ElfW(Sym) *esym;
206 int sym_bind, sym_index, sym_type, esym_bind;
207 unsigned char sym_vis, esym_vis, new_vis;
209 sym_bind = ELFW(ST_BIND)(info);
210 sym_type = ELFW(ST_TYPE)(info);
211 sym_vis = ELFW(ST_VISIBILITY)(other);
213 if (sym_bind != STB_LOCAL) {
214 /* we search global or weak symbols */
215 sym_index = find_elf_sym(s, name);
216 if (!sym_index)
217 goto do_def;
218 esym = &((ElfW(Sym) *)s->data)[sym_index];
219 if (esym->st_shndx != SHN_UNDEF) {
220 esym_bind = ELFW(ST_BIND)(esym->st_info);
221 /* propagate the most constraining visibility */
222 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
223 esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
224 if (esym_vis == STV_DEFAULT) {
225 new_vis = sym_vis;
226 } else if (sym_vis == STV_DEFAULT) {
227 new_vis = esym_vis;
228 } else {
229 new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
231 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
232 | new_vis;
233 other = esym->st_other; /* in case we have to patch esym */
234 if (sh_num == SHN_UNDEF) {
235 /* ignore adding of undefined symbol if the
236 corresponding symbol is already defined */
237 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
238 /* global overrides weak, so patch */
239 goto do_patch;
240 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
241 /* weak is ignored if already global */
242 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
243 /* ignore hidden symbols after */
244 } else if (esym->st_shndx == SHN_COMMON
245 && (sh_num < SHN_LORESERVE || sh_num == SHN_COMMON)) {
246 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
247 No idea if this is the correct solution ... */
248 goto do_patch;
249 } else if (s == tcc_state->dynsymtab_section) {
250 /* we accept that two DLL define the same symbol */
251 } else {
252 #if 1
253 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
254 sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
255 #endif
256 error_noabort("'%s' defined twice", name);
258 } else {
259 do_patch:
260 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
261 esym->st_shndx = sh_num;
262 esym->st_value = value;
263 esym->st_size = size;
264 esym->st_other = other;
266 } else {
267 do_def:
268 sym_index = put_elf_sym(s, value, size,
269 ELFW(ST_INFO)(sym_bind, sym_type), other,
270 sh_num, name);
272 return sym_index;
275 /* put relocation */
276 ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
277 int type, int symbol)
279 char buf[256];
280 Section *sr;
281 ElfW_Rel *rel;
283 sr = s->reloc;
284 if (!sr) {
285 /* if no relocation section, create it */
286 snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
287 /* if the symtab is allocated, then we consider the relocation
288 are also */
289 sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
290 sr->sh_entsize = sizeof(ElfW_Rel);
291 sr->link = symtab;
292 sr->sh_info = s->sh_num;
293 s->reloc = sr;
295 rel = section_ptr_add(sr, sizeof(ElfW_Rel));
296 rel->r_offset = offset;
297 rel->r_info = ELFW(R_INFO)(symbol, type);
298 #ifdef TCC_TARGET_X86_64
299 rel->r_addend = 0;
300 #endif
303 /* put stab debug information */
305 ST_FUNC void put_stabs(const char *str, int type, int other, int desc,
306 unsigned long value)
308 Stab_Sym *sym;
310 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
311 if (str) {
312 sym->n_strx = put_elf_str(stabstr_section, str);
313 } else {
314 sym->n_strx = 0;
316 sym->n_type = type;
317 sym->n_other = other;
318 sym->n_desc = desc;
319 sym->n_value = value;
322 ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc,
323 unsigned long value, Section *sec, int sym_index)
325 put_stabs(str, type, other, desc, value);
326 put_elf_reloc(symtab_section, stab_section,
327 stab_section->data_offset - sizeof(unsigned int),
328 R_DATA_32, sym_index);
331 ST_FUNC void put_stabn(int type, int other, int desc, int value)
333 put_stabs(NULL, type, other, desc, value);
336 ST_FUNC void put_stabd(int type, int other, int desc)
338 put_stabs(NULL, type, other, desc, 0);
341 /* In an ELF file symbol table, the local symbols must appear below
342 the global and weak ones. Since TCC cannot sort it while generating
343 the code, we must do it after. All the relocation tables are also
344 modified to take into account the symbol table sorting */
345 static void sort_syms(TCCState *s1, Section *s)
347 int *old_to_new_syms;
348 ElfW(Sym) *new_syms;
349 int nb_syms, i;
350 ElfW(Sym) *p, *q;
351 ElfW_Rel *rel, *rel_end;
352 Section *sr;
353 int type, sym_index;
355 nb_syms = s->data_offset / sizeof(ElfW(Sym));
356 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
357 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
359 /* first pass for local symbols */
360 p = (ElfW(Sym) *)s->data;
361 q = new_syms;
362 for(i = 0; i < nb_syms; i++) {
363 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
364 old_to_new_syms[i] = q - new_syms;
365 *q++ = *p;
367 p++;
369 /* save the number of local symbols in section header */
370 s->sh_info = q - new_syms;
372 /* then second pass for non local symbols */
373 p = (ElfW(Sym) *)s->data;
374 for(i = 0; i < nb_syms; i++) {
375 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
376 old_to_new_syms[i] = q - new_syms;
377 *q++ = *p;
379 p++;
382 /* we copy the new symbols to the old */
383 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
384 tcc_free(new_syms);
386 /* now we modify all the relocations */
387 for(i = 1; i < s1->nb_sections; i++) {
388 sr = s1->sections[i];
389 if (sr->sh_type == SHT_RELX && sr->link == s) {
390 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
391 for(rel = (ElfW_Rel *)sr->data;
392 rel < rel_end;
393 rel++) {
394 sym_index = ELFW(R_SYM)(rel->r_info);
395 type = ELFW(R_TYPE)(rel->r_info);
396 sym_index = old_to_new_syms[sym_index];
397 rel->r_info = ELFW(R_INFO)(sym_index, type);
402 tcc_free(old_to_new_syms);
405 /* relocate common symbols in the .bss section */
406 ST_FUNC void relocate_common_syms(void)
408 ElfW(Sym) *sym, *sym_end;
409 unsigned long offset, align;
411 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
412 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
413 sym < sym_end;
414 sym++) {
415 if (sym->st_shndx == SHN_COMMON) {
416 /* align symbol */
417 align = sym->st_value;
418 offset = bss_section->data_offset;
419 offset = (offset + align - 1) & -align;
420 sym->st_value = offset;
421 sym->st_shndx = bss_section->sh_num;
422 offset += sym->st_size;
423 bss_section->data_offset = offset;
428 /* relocate symbol table, resolve undefined symbols if do_resolve is
429 true and output error if undefined symbol. */
430 ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
432 ElfW(Sym) *sym, *esym, *sym_end;
433 int sym_bind, sh_num, sym_index;
434 const char *name;
436 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
437 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
438 sym < sym_end;
439 sym++) {
440 sh_num = sym->st_shndx;
441 if (sh_num == SHN_UNDEF) {
442 name = strtab_section->data + sym->st_name;
443 if (do_resolve) {
444 #if !defined TCC_TARGET_PE || !defined _WIN32
445 void *addr;
446 name = symtab_section->link->data + sym->st_name;
447 addr = resolve_sym(s1, name);
448 if (addr) {
449 sym->st_value = (uplong)addr;
450 goto found;
452 #endif
453 } else if (s1->dynsym) {
454 /* if dynamic symbol exist, then use it */
455 sym_index = find_elf_sym(s1->dynsym, name);
456 if (sym_index) {
457 esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
458 sym->st_value = esym->st_value;
459 goto found;
462 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
463 it */
464 if (!strcmp(name, "_fp_hw"))
465 goto found;
466 /* only weak symbols are accepted to be undefined. Their
467 value is zero */
468 sym_bind = ELFW(ST_BIND)(sym->st_info);
469 if (sym_bind == STB_WEAK) {
470 sym->st_value = 0;
471 } else {
472 error_noabort("undefined symbol '%s'", name);
474 } else if (sh_num < SHN_LORESERVE) {
475 /* add section base */
476 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
478 found: ;
482 #ifndef TCC_TARGET_PE
483 #ifdef TCC_TARGET_X86_64
484 #define JMP_TABLE_ENTRY_SIZE 14
485 static uplong add_jmp_table(TCCState *s1, uplong val)
487 char *p = s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset;
488 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
489 /* jmp *0x0(%rip) */
490 p[0] = 0xff;
491 p[1] = 0x25;
492 *(int *)(p + 2) = 0;
493 *(uplong *)(p + 6) = val;
494 return (uplong)p;
497 static uplong add_got_table(TCCState *s1, uplong val)
499 uplong *p = (uplong *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
500 s1->runtime_plt_and_got_offset += sizeof(uplong);
501 *p = val;
502 return (uplong)p;
504 #endif
505 #endif
507 /* relocate a given section (CPU dependent) */
508 ST_FUNC void relocate_section(TCCState *s1, Section *s)
510 Section *sr;
511 ElfW_Rel *rel, *rel_end, *qrel;
512 ElfW(Sym) *sym;
513 int type, sym_index;
514 unsigned char *ptr;
515 uplong val, addr;
516 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
517 int esym_index;
518 #endif
520 sr = s->reloc;
521 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
522 qrel = (ElfW_Rel *)sr->data;
523 for(rel = qrel;
524 rel < rel_end;
525 rel++) {
526 ptr = s->data + rel->r_offset;
528 sym_index = ELFW(R_SYM)(rel->r_info);
529 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
530 val = sym->st_value;
531 #ifdef TCC_TARGET_X86_64
532 /* XXX: not tested */
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 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;
605 x = (*(int *)ptr)&0xffffff;
606 (*(int *)ptr) &= 0xff000000;
607 if (x & 0x800000)
608 x -= 0x1000000;
609 x *= 4;
610 x += val - addr;
611 if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
612 error("can't relocate value at %x",addr);
613 x >>= 2;
614 x &= 0xffffff;
615 (*(int *)ptr) |= x;
617 break;
618 case R_ARM_PREL31:
620 int x;
621 x = (*(int *)ptr) & 0x7fffffff;
622 (*(int *)ptr) &= 0x80000000;
623 x = (x * 2) / 2;
624 x += val - addr;
625 if((x^(x>>1))&0x40000000)
626 error("can't relocate value at %x",addr);
627 (*(int *)ptr) |= x & 0x7fffffff;
629 case R_ARM_ABS32:
630 *(int *)ptr += val;
631 break;
632 case R_ARM_BASE_PREL:
633 *(int *)ptr += s1->got->sh_addr - addr;
634 break;
635 case R_ARM_GOTOFF32:
636 *(int *)ptr += val - s1->got->sh_addr;
637 break;
638 case R_ARM_GOT_BREL:
639 /* we load the got offset */
640 *(int *)ptr += s1->got_offsets[sym_index];
641 break;
642 case R_ARM_COPY:
643 break;
644 default:
645 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
646 type,addr,(unsigned int)(long)ptr,val);
647 break;
648 #elif defined(TCC_TARGET_C67)
649 case R_C60_32:
650 *(int *)ptr += val;
651 break;
652 case R_C60LO16:
654 uint32_t orig;
656 /* put the low 16 bits of the absolute address */
657 // add to what is already there
659 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
660 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
662 //patch both at once - assumes always in pairs Low - High
664 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
665 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
667 break;
668 case R_C60HI16:
669 break;
670 default:
671 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
672 type,addr,(unsigned int)(long)ptr, val);
673 break;
674 #elif defined(TCC_TARGET_X86_64)
675 case R_X86_64_64:
676 if (s1->output_type == TCC_OUTPUT_DLL) {
677 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
678 qrel->r_addend = *(long long *)ptr + val;
679 qrel++;
681 *(long long *)ptr += val;
682 break;
683 case R_X86_64_32:
684 case R_X86_64_32S:
685 if (s1->output_type == TCC_OUTPUT_DLL) {
686 /* XXX: this logic may depend on TCC's codegen
687 now TCC uses R_X86_64_32 even for a 64bit pointer */
688 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
689 qrel->r_addend = *(int *)ptr + val;
690 qrel++;
692 *(int *)ptr += val;
693 break;
694 case R_X86_64_PC32: {
695 long long diff;
696 if (s1->output_type == TCC_OUTPUT_DLL) {
697 /* DLL relocation */
698 esym_index = s1->symtab_to_dynsym[sym_index];
699 if (esym_index) {
700 qrel->r_offset = rel->r_offset;
701 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
702 qrel->r_addend = *(int *)ptr;
703 qrel++;
704 break;
707 diff = (long long)val - addr;
708 if (diff <= -2147483647 || diff > 2147483647) {
709 #ifndef TCC_TARGET_PE
710 /* XXX: naive support for over 32bit jump */
711 if (s1->output_type == TCC_OUTPUT_MEMORY) {
712 val = add_jmp_table(s1, val);
713 diff = val - addr;
715 #endif
716 if (diff <= -2147483647 || diff > 2147483647) {
717 error("internal error: relocation failed");
720 *(int *)ptr += diff;
722 break;
723 case R_X86_64_PLT32:
724 *(int *)ptr += val - addr;
725 break;
726 case R_X86_64_GLOB_DAT:
727 case R_X86_64_JUMP_SLOT:
728 *(int *)ptr = val;
729 break;
730 case R_X86_64_GOTPCREL:
731 #ifndef TCC_TARGET_PE
732 if (s1->output_type == TCC_OUTPUT_MEMORY) {
733 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
734 *(int *)ptr += val - addr;
735 break;
737 #endif
738 *(int *)ptr += (s1->got->sh_addr - addr +
739 s1->got_offsets[sym_index] - 4);
740 break;
741 case R_X86_64_GOTTPOFF:
742 *(int *)ptr += val - s1->got->sh_addr;
743 break;
744 case R_X86_64_GOT32:
745 /* we load the got offset */
746 *(int *)ptr += s1->got_offsets[sym_index];
747 break;
748 #else
749 #error unsupported processor
750 #endif
753 /* if the relocation is allocated, we change its symbol table */
754 if (sr->sh_flags & SHF_ALLOC)
755 sr->link = s1->dynsym;
758 /* relocate relocation table in 'sr' */
759 static void relocate_rel(TCCState *s1, Section *sr)
761 Section *s;
762 ElfW_Rel *rel, *rel_end;
764 s = s1->sections[sr->sh_info];
765 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
766 for(rel = (ElfW_Rel *)sr->data;
767 rel < rel_end;
768 rel++) {
769 rel->r_offset += s->sh_addr;
773 /* count the number of dynamic relocations so that we can reserve
774 their space */
775 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
777 ElfW_Rel *rel, *rel_end;
778 int sym_index, esym_index, type, count;
780 count = 0;
781 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
782 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
783 sym_index = ELFW(R_SYM)(rel->r_info);
784 type = ELFW(R_TYPE)(rel->r_info);
785 switch(type) {
786 #if defined(TCC_TARGET_I386)
787 case R_386_32:
788 #elif defined(TCC_TARGET_X86_64)
789 case R_X86_64_32:
790 case R_X86_64_32S:
791 case R_X86_64_64:
792 #endif
793 count++;
794 break;
795 #if defined(TCC_TARGET_I386)
796 case R_386_PC32:
797 #elif defined(TCC_TARGET_X86_64)
798 case R_X86_64_PC32:
799 #endif
800 esym_index = s1->symtab_to_dynsym[sym_index];
801 if (esym_index)
802 count++;
803 break;
804 default:
805 break;
808 if (count) {
809 /* allocate the section */
810 sr->sh_flags |= SHF_ALLOC;
811 sr->sh_size = count * sizeof(ElfW_Rel);
813 return count;
816 static void put_got_offset(TCCState *s1, int index, unsigned long val)
818 int n;
819 unsigned long *tab;
821 if (index >= s1->nb_got_offsets) {
822 /* find immediately bigger power of 2 and reallocate array */
823 n = 1;
824 while (index >= n)
825 n *= 2;
826 tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
827 if (!tab)
828 error("memory full");
829 s1->got_offsets = tab;
830 memset(s1->got_offsets + s1->nb_got_offsets, 0,
831 (n - s1->nb_got_offsets) * sizeof(unsigned long));
832 s1->nb_got_offsets = n;
834 s1->got_offsets[index] = val;
837 /* XXX: suppress that */
838 static void put32(unsigned char *p, uint32_t val)
840 p[0] = val;
841 p[1] = val >> 8;
842 p[2] = val >> 16;
843 p[3] = val >> 24;
846 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
847 defined(TCC_TARGET_X86_64)
848 static uint32_t get32(unsigned char *p)
850 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
852 #endif
854 static void build_got(TCCState *s1)
856 unsigned char *ptr;
858 /* if no got, then create it */
859 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
860 s1->got->sh_entsize = 4;
861 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
862 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
863 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
864 #if PTR_SIZE == 4
865 /* keep space for _DYNAMIC pointer, if present */
866 put32(ptr, 0);
867 /* two dummy got entries */
868 put32(ptr + 4, 0);
869 put32(ptr + 8, 0);
870 #else
871 /* keep space for _DYNAMIC pointer, if present */
872 put32(ptr, 0);
873 put32(ptr + 4, 0);
874 /* two dummy got entries */
875 put32(ptr + 8, 0);
876 put32(ptr + 12, 0);
877 put32(ptr + 16, 0);
878 put32(ptr + 20, 0);
879 #endif
882 /* put a got entry corresponding to a symbol in symtab_section. 'size'
883 and 'info' can be modifed if more precise info comes from the DLL */
884 static void put_got_entry(TCCState *s1,
885 int reloc_type, unsigned long size, int info,
886 int sym_index)
888 int index;
889 const char *name;
890 ElfW(Sym) *sym;
891 unsigned long offset;
892 int *ptr;
894 if (!s1->got)
895 build_got(s1);
897 /* if a got entry already exists for that symbol, no need to add one */
898 if (sym_index < s1->nb_got_offsets &&
899 s1->got_offsets[sym_index] != 0)
900 return;
902 put_got_offset(s1, sym_index, s1->got->data_offset);
904 if (s1->dynsym) {
905 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
906 name = symtab_section->link->data + sym->st_name;
907 offset = sym->st_value;
908 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
909 if (reloc_type ==
910 #ifdef TCC_TARGET_X86_64
911 R_X86_64_JUMP_SLOT
912 #else
913 R_386_JMP_SLOT
914 #endif
916 Section *plt;
917 uint8_t *p;
918 int modrm;
920 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
921 modrm = 0x25;
922 #else
923 /* if we build a DLL, we add a %ebx offset */
924 if (s1->output_type == TCC_OUTPUT_DLL)
925 modrm = 0xa3;
926 else
927 modrm = 0x25;
928 #endif
930 /* add a PLT entry */
931 plt = s1->plt;
932 if (plt->data_offset == 0) {
933 /* first plt entry */
934 p = section_ptr_add(plt, 16);
935 p[0] = 0xff; /* pushl got + PTR_SIZE */
936 p[1] = modrm + 0x10;
937 put32(p + 2, PTR_SIZE);
938 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
939 p[7] = modrm;
940 put32(p + 8, PTR_SIZE * 2);
943 p = section_ptr_add(plt, 16);
944 p[0] = 0xff; /* jmp *(got + x) */
945 p[1] = modrm;
946 put32(p + 2, s1->got->data_offset);
947 p[6] = 0x68; /* push $xxx */
948 put32(p + 7, (plt->data_offset - 32) >> 1);
949 p[11] = 0xe9; /* jmp plt_start */
950 put32(p + 12, -(plt->data_offset));
952 /* the symbol is modified so that it will be relocated to
953 the PLT */
954 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
955 if (s1->output_type == TCC_OUTPUT_EXE)
956 #endif
957 offset = plt->data_offset - 16;
959 #elif defined(TCC_TARGET_ARM)
960 if (reloc_type == R_ARM_JUMP_SLOT) {
961 Section *plt;
962 uint8_t *p;
964 /* if we build a DLL, we add a %ebx offset */
965 if (s1->output_type == TCC_OUTPUT_DLL)
966 error("DLLs unimplemented!");
968 /* add a PLT entry */
969 plt = s1->plt;
970 if (plt->data_offset == 0) {
971 /* first plt entry */
972 p = section_ptr_add(plt, 16);
973 put32(p , 0xe52de004);
974 put32(p + 4, 0xe59fe010);
975 put32(p + 8, 0xe08fe00e);
976 put32(p + 12, 0xe5bef008);
979 p = section_ptr_add(plt, 16);
980 put32(p , 0xe59fc004);
981 put32(p+4, 0xe08fc00c);
982 put32(p+8, 0xe59cf000);
983 put32(p+12, s1->got->data_offset);
985 /* the symbol is modified so that it will be relocated to
986 the PLT */
987 if (s1->output_type == TCC_OUTPUT_EXE)
988 offset = plt->data_offset - 16;
990 #elif defined(TCC_TARGET_C67)
991 error("C67 got not implemented");
992 #else
993 #error unsupported CPU
994 #endif
995 index = put_elf_sym(s1->dynsym, offset,
996 size, info, 0, sym->st_shndx, name);
997 /* put a got entry */
998 put_elf_reloc(s1->dynsym, s1->got,
999 s1->got->data_offset,
1000 reloc_type, index);
1002 ptr = section_ptr_add(s1->got, PTR_SIZE);
1003 *ptr = 0;
1006 /* build GOT and PLT entries */
1007 ST_FUNC void build_got_entries(TCCState *s1)
1009 Section *s, *symtab;
1010 ElfW_Rel *rel, *rel_end;
1011 ElfW(Sym) *sym;
1012 int i, type, reloc_type, sym_index;
1014 for(i = 1; i < s1->nb_sections; i++) {
1015 s = s1->sections[i];
1016 if (s->sh_type != SHT_RELX)
1017 continue;
1018 /* no need to handle got relocations */
1019 if (s->link != symtab_section)
1020 continue;
1021 symtab = s->link;
1022 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1023 for(rel = (ElfW_Rel *)s->data;
1024 rel < rel_end;
1025 rel++) {
1026 type = ELFW(R_TYPE)(rel->r_info);
1027 switch(type) {
1028 #if defined(TCC_TARGET_I386)
1029 case R_386_GOT32:
1030 case R_386_GOTOFF:
1031 case R_386_GOTPC:
1032 case R_386_PLT32:
1033 if (!s1->got)
1034 build_got(s1);
1035 if (type == R_386_GOT32 || type == R_386_PLT32) {
1036 sym_index = ELFW(R_SYM)(rel->r_info);
1037 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1038 /* look at the symbol got offset. If none, then add one */
1039 if (type == R_386_GOT32)
1040 reloc_type = R_386_GLOB_DAT;
1041 else
1042 reloc_type = R_386_JMP_SLOT;
1043 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1044 sym_index);
1046 break;
1047 #elif defined(TCC_TARGET_ARM)
1048 case R_ARM_GOT_BREL:
1049 case R_ARM_GOTOFF32:
1050 case R_ARM_BASE_PREL:
1051 case R_ARM_PLT32:
1052 if (!s1->got)
1053 build_got(s1);
1054 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1055 sym_index = ELFW(R_SYM)(rel->r_info);
1056 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1057 /* look at the symbol got offset. If none, then add one */
1058 if (type == R_ARM_GOT_BREL)
1059 reloc_type = R_ARM_GLOB_DAT;
1060 else
1061 reloc_type = R_ARM_JUMP_SLOT;
1062 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1063 sym_index);
1065 break;
1066 #elif defined(TCC_TARGET_C67)
1067 case R_C60_GOT32:
1068 case R_C60_GOTOFF:
1069 case R_C60_GOTPC:
1070 case R_C60_PLT32:
1071 if (!s1->got)
1072 build_got(s1);
1073 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1074 sym_index = ELFW(R_SYM)(rel->r_info);
1075 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1076 /* look at the symbol got offset. If none, then add one */
1077 if (type == R_C60_GOT32)
1078 reloc_type = R_C60_GLOB_DAT;
1079 else
1080 reloc_type = R_C60_JMP_SLOT;
1081 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1082 sym_index);
1084 break;
1085 #elif defined(TCC_TARGET_X86_64)
1086 case R_X86_64_GOT32:
1087 case R_X86_64_GOTTPOFF:
1088 case R_X86_64_GOTPCREL:
1089 case R_X86_64_PLT32:
1090 if (!s1->got)
1091 build_got(s1);
1092 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1093 type == R_X86_64_PLT32) {
1094 sym_index = ELFW(R_SYM)(rel->r_info);
1095 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1096 /* look at the symbol got offset. If none, then add one */
1097 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1098 reloc_type = R_X86_64_GLOB_DAT;
1099 else
1100 reloc_type = R_X86_64_JUMP_SLOT;
1101 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1102 sym_index);
1104 break;
1105 #else
1106 #error unsupported CPU
1107 #endif
1108 default:
1109 break;
1115 ST_FUNC Section *new_symtab(TCCState *s1,
1116 const char *symtab_name, int sh_type, int sh_flags,
1117 const char *strtab_name,
1118 const char *hash_name, int hash_sh_flags)
1120 Section *symtab, *strtab, *hash;
1121 int *ptr, nb_buckets;
1123 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1124 symtab->sh_entsize = sizeof(ElfW(Sym));
1125 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1126 put_elf_str(strtab, "");
1127 symtab->link = strtab;
1128 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1130 nb_buckets = 1;
1132 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1133 hash->sh_entsize = sizeof(int);
1134 symtab->hash = hash;
1135 hash->link = symtab;
1137 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1138 ptr[0] = nb_buckets;
1139 ptr[1] = 1;
1140 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1141 return symtab;
1144 /* put dynamic tag */
1145 static void put_dt(Section *dynamic, int dt, unsigned long val)
1147 ElfW(Dyn) *dyn;
1148 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1149 dyn->d_tag = dt;
1150 dyn->d_un.d_val = val;
1153 static void add_init_array_defines(TCCState *s1, const char *section_name)
1155 Section *s;
1156 long end_offset;
1157 char sym_start[1024];
1158 char sym_end[1024];
1160 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1161 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1163 s = find_section(s1, section_name);
1164 if (!s) {
1165 end_offset = 0;
1166 s = data_section;
1167 } else {
1168 end_offset = s->data_offset;
1171 add_elf_sym(symtab_section,
1172 0, 0,
1173 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1174 s->sh_num, sym_start);
1175 add_elf_sym(symtab_section,
1176 end_offset, 0,
1177 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1178 s->sh_num, sym_end);
1181 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1183 #ifdef CONFIG_TCC_BCHECK
1184 unsigned long *ptr;
1185 Section *init_section;
1186 unsigned char *pinit;
1187 int sym_index;
1189 if (0 == s1->do_bounds_check)
1190 return;
1192 /* XXX: add an object file to do that */
1193 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1194 *ptr = 0;
1195 add_elf_sym(symtab_section, 0, 0,
1196 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1197 bounds_section->sh_num, "__bounds_start");
1198 /* add bound check code */
1199 #ifndef TCC_TARGET_PE
1201 char buf[1024];
1202 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "bcheck.o");
1203 tcc_add_file(s1, buf);
1205 #endif
1206 #ifdef TCC_TARGET_I386
1207 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1208 /* add 'call __bound_init()' in .init section */
1209 init_section = find_section(s1, ".init");
1210 pinit = section_ptr_add(init_section, 5);
1211 pinit[0] = 0xe8;
1212 put32(pinit + 1, -4);
1213 sym_index = find_elf_sym(symtab_section, "__bound_init");
1214 put_elf_reloc(symtab_section, init_section,
1215 init_section->data_offset - 4, R_386_PC32, sym_index);
1217 #endif
1218 #endif
1221 /* add tcc runtime libraries */
1222 ST_FUNC void tcc_add_runtime(TCCState *s1)
1224 tcc_add_bcheck(s1);
1226 /* add libc */
1227 if (!s1->nostdlib) {
1228 #ifdef CONFIG_USE_LIBGCC
1229 tcc_add_library(s1, "c");
1230 tcc_add_file(s1, CONFIG_SYSROOT "/lib/libgcc_s.so.1");
1231 #else
1232 char buf[1024];
1233 tcc_add_library(s1, "c");
1234 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "libtcc1.a");
1235 tcc_add_file(s1, buf);
1236 #endif
1238 /* add crt end if not memory output */
1239 if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) {
1240 tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
1244 /* add various standard linker symbols (must be done after the
1245 sections are filled (for example after allocating common
1246 symbols)) */
1247 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1249 char buf[1024];
1250 int i;
1251 Section *s;
1253 add_elf_sym(symtab_section,
1254 text_section->data_offset, 0,
1255 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1256 text_section->sh_num, "_etext");
1257 add_elf_sym(symtab_section,
1258 data_section->data_offset, 0,
1259 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1260 data_section->sh_num, "_edata");
1261 add_elf_sym(symtab_section,
1262 bss_section->data_offset, 0,
1263 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1264 bss_section->sh_num, "_end");
1265 /* horrible new standard ldscript defines */
1266 add_init_array_defines(s1, ".preinit_array");
1267 add_init_array_defines(s1, ".init_array");
1268 add_init_array_defines(s1, ".fini_array");
1270 /* add start and stop symbols for sections whose name can be
1271 expressed in C */
1272 for(i = 1; i < s1->nb_sections; i++) {
1273 s = s1->sections[i];
1274 if (s->sh_type == SHT_PROGBITS &&
1275 (s->sh_flags & SHF_ALLOC)) {
1276 const char *p;
1277 int ch;
1279 /* check if section name can be expressed in C */
1280 p = s->name;
1281 for(;;) {
1282 ch = *p;
1283 if (!ch)
1284 break;
1285 if (!isid(ch) && !isnum(ch))
1286 goto next_sec;
1287 p++;
1289 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1290 add_elf_sym(symtab_section,
1291 0, 0,
1292 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1293 s->sh_num, buf);
1294 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1295 add_elf_sym(symtab_section,
1296 s->data_offset, 0,
1297 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1298 s->sh_num, buf);
1300 next_sec: ;
1304 /* name of ELF interpreter */
1305 #if defined __FreeBSD__
1306 static const char elf_interp[] = "/libexec/ld-elf.so.1";
1307 #elif defined TCC_ARM_EABI
1308 static const char elf_interp[] = "/lib/ld-linux.so.3";
1309 #elif defined(TCC_TARGET_X86_64)
1310 # if defined(TCC_TARGET_X86_64_CENTOS)
1311 static const char elf_interp[] = "/lib64/ld-linux-x86-64.so.2";
1312 # else
1313 static const char elf_interp[] = "/lib/ld-linux-x86-64.so.2";
1314 # endif /* TCC_TARGET_X86_64_CENTOS */
1315 #elif defined(TCC_UCLIBC)
1316 static const char elf_interp[] = "/lib/ld-uClibc.so.0";
1317 #else
1318 static const char elf_interp[] = "/lib/ld-linux.so.2";
1319 #endif
1321 static void tcc_output_binary(TCCState *s1, FILE *f,
1322 const int *section_order)
1324 Section *s;
1325 int i, offset, size;
1327 offset = 0;
1328 for(i=1;i<s1->nb_sections;i++) {
1329 s = s1->sections[section_order[i]];
1330 if (s->sh_type != SHT_NOBITS &&
1331 (s->sh_flags & SHF_ALLOC)) {
1332 while (offset < s->sh_offset) {
1333 fputc(0, f);
1334 offset++;
1336 size = s->sh_size;
1337 fwrite(s->data, 1, size, f);
1338 offset += size;
1343 #if defined(__FreeBSD__)
1344 #define HAVE_PHDR 1
1345 #define EXTRA_RELITEMS 14
1347 /* move the relocation value from .dynsym to .got */
1348 void patch_dynsym_undef(TCCState *s1, Section *s)
1350 uint32_t *gotd = (void *)s1->got->data;
1351 ElfW(Sym) *sym, *sym_end;
1353 gotd += 3; // dummy entries in .got
1354 /* relocate symbols in .dynsym */
1355 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1356 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1357 if (sym->st_shndx == SHN_UNDEF) {
1358 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1359 sym->st_value = 0;
1363 #else
1364 #define HAVE_PHDR 0
1365 #define EXTRA_RELITEMS 9
1366 #endif
1368 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1370 int sym_index = ELFW(R_SYM) (rel->r_info);
1371 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1372 unsigned long offset;
1374 if (sym_index >= s1->nb_got_offsets)
1375 return;
1376 offset = s1->got_offsets[sym_index];
1377 section_reserve(s1->got, offset + PTR_SIZE);
1378 #ifdef TCC_TARGET_X86_64
1379 /* only works for x86-64 */
1380 put32(s1->got->data + offset, sym->st_value >> 32);
1381 #endif
1382 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1385 ST_FUNC void fill_got(TCCState *s1)
1387 Section *s;
1388 ElfW_Rel *rel, *rel_end;
1389 int i;
1391 for(i = 1; i < s1->nb_sections; i++) {
1392 s = s1->sections[i];
1393 if (s->sh_type != SHT_RELX)
1394 continue;
1395 /* no need to handle got relocations */
1396 if (s->link != symtab_section)
1397 continue;
1398 rel_end = (ElfW_Rel *) (s->data + s->data_offset);
1399 for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
1400 switch (ELFW(R_TYPE) (rel->r_info)) {
1401 case R_X86_64_GOT32:
1402 case R_X86_64_GOTPCREL:
1403 case R_X86_64_PLT32:
1404 fill_got_entry(s1, rel);
1405 break;
1412 /* output an ELF file */
1413 /* XXX: suppress unneeded sections */
1414 static int elf_output_file(TCCState *s1, const char *filename)
1416 ElfW(Ehdr) ehdr;
1417 FILE *f;
1418 int fd, mode, ret;
1419 int *section_order;
1420 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
1421 unsigned long addr;
1422 Section *strsec, *s;
1423 ElfW(Shdr) shdr, *sh;
1424 ElfW(Phdr) *phdr, *ph;
1425 Section *interp, *dynamic, *dynstr;
1426 unsigned long saved_dynamic_data_offset;
1427 ElfW(Sym) *sym;
1428 int type, file_type;
1429 unsigned long rel_addr, rel_size;
1430 unsigned long bss_addr, bss_size;
1432 file_type = s1->output_type;
1433 s1->nb_errors = 0;
1435 if (file_type != TCC_OUTPUT_OBJ) {
1436 tcc_add_runtime(s1);
1439 phdr = NULL;
1440 section_order = NULL;
1441 interp = NULL;
1442 dynamic = NULL;
1443 dynstr = NULL; /* avoid warning */
1444 saved_dynamic_data_offset = 0; /* avoid warning */
1446 if (file_type != TCC_OUTPUT_OBJ) {
1447 relocate_common_syms();
1449 tcc_add_linker_symbols(s1);
1451 if (!s1->static_link) {
1452 const char *name;
1453 int sym_index, index;
1454 ElfW(Sym) *esym, *sym_end;
1456 if (file_type == TCC_OUTPUT_EXE) {
1457 char *ptr;
1458 /* allow override the dynamic loader */
1459 const char *elfint = getenv("LD_SO");
1460 if (elfint == NULL)
1461 elfint = elf_interp;
1462 /* add interpreter section only if executable */
1463 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1464 interp->sh_addralign = 1;
1465 ptr = section_ptr_add(interp, 1+strlen(elfint));
1466 strcpy(ptr, elfint);
1469 /* add dynamic symbol table */
1470 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1471 ".dynstr",
1472 ".hash", SHF_ALLOC);
1473 dynstr = s1->dynsym->link;
1475 /* add dynamic section */
1476 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1477 SHF_ALLOC | SHF_WRITE);
1478 dynamic->link = dynstr;
1479 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1481 /* add PLT */
1482 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1483 SHF_ALLOC | SHF_EXECINSTR);
1484 s1->plt->sh_entsize = 4;
1486 build_got(s1);
1488 /* scan for undefined symbols and see if they are in the
1489 dynamic symbols. If a symbol STT_FUNC is found, then we
1490 add it in the PLT. If a symbol STT_OBJECT is found, we
1491 add it in the .bss section with a suitable relocation */
1492 sym_end = (ElfW(Sym) *)(symtab_section->data +
1493 symtab_section->data_offset);
1494 if (file_type == TCC_OUTPUT_EXE) {
1495 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1496 sym < sym_end;
1497 sym++) {
1498 if (sym->st_shndx == SHN_UNDEF) {
1499 name = symtab_section->link->data + sym->st_name;
1500 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1501 if (sym_index) {
1502 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1503 type = ELFW(ST_TYPE)(esym->st_info);
1504 if (type == STT_FUNC) {
1505 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1506 esym->st_info,
1507 sym - (ElfW(Sym) *)symtab_section->data);
1508 } else if (type == STT_OBJECT) {
1509 unsigned long offset;
1510 offset = bss_section->data_offset;
1511 /* XXX: which alignment ? */
1512 offset = (offset + 16 - 1) & -16;
1513 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1514 esym->st_info, 0,
1515 bss_section->sh_num, name);
1516 put_elf_reloc(s1->dynsym, bss_section,
1517 offset, R_COPY, index);
1518 offset += esym->st_size;
1519 bss_section->data_offset = offset;
1521 } else {
1522 /* STB_WEAK undefined symbols are accepted */
1523 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1524 it */
1525 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1526 !strcmp(name, "_fp_hw")) {
1527 } else {
1528 error_noabort("undefined symbol '%s'", name);
1531 } else if (s1->rdynamic &&
1532 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1533 /* if -rdynamic option, then export all non
1534 local symbols */
1535 name = symtab_section->link->data + sym->st_name;
1536 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1537 sym->st_info, 0,
1538 sym->st_shndx, name);
1542 if (s1->nb_errors)
1543 goto fail;
1545 /* now look at unresolved dynamic symbols and export
1546 corresponding symbol */
1547 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1548 s1->dynsymtab_section->data_offset);
1549 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1550 esym < sym_end;
1551 esym++) {
1552 if (esym->st_shndx == SHN_UNDEF) {
1553 name = s1->dynsymtab_section->link->data + esym->st_name;
1554 sym_index = find_elf_sym(symtab_section, name);
1555 if (sym_index) {
1556 /* XXX: avoid adding a symbol if already
1557 present because of -rdynamic ? */
1558 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1559 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1560 sym->st_info, 0,
1561 sym->st_shndx, name);
1562 } else {
1563 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1564 /* weak symbols can stay undefined */
1565 } else {
1566 warning("undefined dynamic symbol '%s'", name);
1571 } else {
1572 int nb_syms;
1573 /* shared library case : we simply export all the global symbols */
1574 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1575 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1576 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1577 sym < sym_end;
1578 sym++) {
1579 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1580 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1581 if (ELFW(ST_TYPE)(sym->st_info) == STT_FUNC &&
1582 sym->st_shndx == SHN_UNDEF) {
1583 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1584 sym->st_info,
1585 sym - (ElfW(Sym) *)symtab_section->data);
1587 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1588 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1589 sym->st_info,
1590 sym - (ElfW(Sym) *)symtab_section->data);
1592 else
1593 #endif
1595 name = symtab_section->link->data + sym->st_name;
1596 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1597 sym->st_info, 0,
1598 sym->st_shndx, name);
1599 s1->symtab_to_dynsym[sym -
1600 (ElfW(Sym) *)symtab_section->data] =
1601 index;
1607 build_got_entries(s1);
1609 /* add a list of needed dlls */
1610 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1611 DLLReference *dllref = s1->loaded_dlls[i];
1612 if (dllref->level == 0)
1613 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1616 if (s1->rpath)
1617 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1619 /* XXX: currently, since we do not handle PIC code, we
1620 must relocate the readonly segments */
1621 if (file_type == TCC_OUTPUT_DLL) {
1622 if (s1->soname)
1623 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1624 put_dt(dynamic, DT_TEXTREL, 0);
1627 if (s1->symbolic)
1628 put_dt(dynamic, DT_SYMBOLIC, 0);
1630 /* add necessary space for other entries */
1631 saved_dynamic_data_offset = dynamic->data_offset;
1632 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1633 } else {
1634 /* still need to build got entries in case of static link */
1635 build_got_entries(s1);
1639 memset(&ehdr, 0, sizeof(ehdr));
1641 /* we add a section for symbols */
1642 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1643 put_elf_str(strsec, "");
1645 /* compute number of sections */
1646 shnum = s1->nb_sections;
1648 /* this array is used to reorder sections in the output file */
1649 section_order = tcc_malloc(sizeof(int) * shnum);
1650 section_order[0] = 0;
1651 sh_order_index = 1;
1653 /* compute number of program headers */
1654 switch(file_type) {
1655 default:
1656 case TCC_OUTPUT_OBJ:
1657 phnum = 0;
1658 break;
1659 case TCC_OUTPUT_EXE:
1660 if (!s1->static_link)
1661 phnum = 4 + HAVE_PHDR;
1662 else
1663 phnum = 2;
1664 break;
1665 case TCC_OUTPUT_DLL:
1666 phnum = 3;
1667 break;
1670 /* allocate strings for section names and decide if an unallocated
1671 section should be output */
1672 /* NOTE: the strsec section comes last, so its size is also
1673 correct ! */
1674 for(i = 1; i < s1->nb_sections; i++) {
1675 s = s1->sections[i];
1676 s->sh_name = put_elf_str(strsec, s->name);
1677 #if 0 //gr
1678 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1679 s->sh_flags,
1680 s->sh_type,
1681 s->sh_info,
1682 s->name,
1683 s->reloc ? s->reloc->name : "n"
1685 #endif
1686 /* when generating a DLL, we include relocations but we may
1687 patch them */
1688 if (file_type == TCC_OUTPUT_DLL &&
1689 s->sh_type == SHT_RELX &&
1690 !(s->sh_flags & SHF_ALLOC)) {
1691 /* //gr: avoid bogus relocs for empty (debug) sections */
1692 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1693 prepare_dynamic_rel(s1, s);
1694 else if (s1->do_debug)
1695 s->sh_size = s->data_offset;
1696 } else if (s1->do_debug ||
1697 file_type == TCC_OUTPUT_OBJ ||
1698 (s->sh_flags & SHF_ALLOC) ||
1699 i == (s1->nb_sections - 1)) {
1700 /* we output all sections if debug or object file */
1701 s->sh_size = s->data_offset;
1705 /* allocate program segment headers */
1706 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1708 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1709 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1710 } else {
1711 file_offset = 0;
1713 if (phnum > 0) {
1714 /* compute section to program header mapping */
1715 if (s1->has_text_addr) {
1716 int a_offset, p_offset;
1717 addr = s1->text_addr;
1718 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1719 ELF_PAGE_SIZE */
1720 a_offset = addr & (s1->section_align - 1);
1721 p_offset = file_offset & (s1->section_align - 1);
1722 if (a_offset < p_offset)
1723 a_offset += s1->section_align;
1724 file_offset += (a_offset - p_offset);
1725 } else {
1726 if (file_type == TCC_OUTPUT_DLL)
1727 addr = 0;
1728 else
1729 addr = ELF_START_ADDR;
1730 /* compute address after headers */
1731 addr += (file_offset & (s1->section_align - 1));
1734 /* dynamic relocation table information, for .dynamic section */
1735 rel_size = 0;
1736 rel_addr = 0;
1738 bss_addr = bss_size = 0;
1739 /* leave one program header for the program interpreter */
1740 ph = &phdr[0];
1741 if (interp)
1742 ph += 1 + HAVE_PHDR;
1744 for(j = 0; j < 2; j++) {
1745 ph->p_type = PT_LOAD;
1746 if (j == 0)
1747 ph->p_flags = PF_R | PF_X;
1748 else
1749 ph->p_flags = PF_R | PF_W;
1750 ph->p_align = s1->section_align;
1752 /* we do the following ordering: interp, symbol tables,
1753 relocations, progbits, nobits */
1754 /* XXX: do faster and simpler sorting */
1755 for(k = 0; k < 5; k++) {
1756 for(i = 1; i < s1->nb_sections; i++) {
1757 s = s1->sections[i];
1758 /* compute if section should be included */
1759 if (j == 0) {
1760 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1761 SHF_ALLOC)
1762 continue;
1763 } else {
1764 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1765 (SHF_ALLOC | SHF_WRITE))
1766 continue;
1768 if (s == interp) {
1769 if (k != 0)
1770 continue;
1771 } else if (s->sh_type == SHT_DYNSYM ||
1772 s->sh_type == SHT_STRTAB ||
1773 s->sh_type == SHT_HASH) {
1774 if (k != 1)
1775 continue;
1776 } else if (s->sh_type == SHT_RELX) {
1777 if (k != 2)
1778 continue;
1779 } else if (s->sh_type == SHT_NOBITS) {
1780 if (k != 4)
1781 continue;
1782 } else {
1783 if (k != 3)
1784 continue;
1786 section_order[sh_order_index++] = i;
1788 /* section matches: we align it and add its size */
1789 tmp = addr;
1790 addr = (addr + s->sh_addralign - 1) &
1791 ~(s->sh_addralign - 1);
1792 file_offset += addr - tmp;
1793 s->sh_offset = file_offset;
1794 s->sh_addr = addr;
1796 /* update program header infos */
1797 if (ph->p_offset == 0) {
1798 ph->p_offset = file_offset;
1799 ph->p_vaddr = addr;
1800 ph->p_paddr = ph->p_vaddr;
1802 /* update dynamic relocation infos */
1803 if (s->sh_type == SHT_RELX) {
1804 #if defined(__FreeBSD__)
1805 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1806 rel_addr = addr;
1807 rel_size += s->sh_size; // XXX only first rel.
1809 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1810 bss_addr = addr;
1811 bss_size = s->sh_size; // XXX only first rel.
1813 #else
1814 if (rel_size == 0)
1815 rel_addr = addr;
1816 rel_size += s->sh_size;
1817 #endif
1819 addr += s->sh_size;
1820 if (s->sh_type != SHT_NOBITS)
1821 file_offset += s->sh_size;
1824 ph->p_filesz = file_offset - ph->p_offset;
1825 ph->p_memsz = addr - ph->p_vaddr;
1826 ph++;
1827 if (j == 0) {
1828 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1829 /* if in the middle of a page, we duplicate the page in
1830 memory so that one copy is RX and the other is RW */
1831 if ((addr & (s1->section_align - 1)) != 0)
1832 addr += s1->section_align;
1833 } else {
1834 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1835 file_offset = (file_offset + s1->section_align - 1) &
1836 ~(s1->section_align - 1);
1841 /* if interpreter, then add corresponing program header */
1842 if (interp) {
1843 ph = &phdr[0];
1845 #if defined(__FreeBSD__)
1847 int len = phnum * sizeof(ElfW(Phdr));
1849 ph->p_type = PT_PHDR;
1850 ph->p_offset = sizeof(ElfW(Ehdr));
1851 ph->p_vaddr = interp->sh_addr - len;
1852 ph->p_paddr = ph->p_vaddr;
1853 ph->p_filesz = ph->p_memsz = len;
1854 ph->p_flags = PF_R | PF_X;
1855 ph->p_align = 4; // interp->sh_addralign;
1856 ph++;
1858 #endif
1860 ph->p_type = PT_INTERP;
1861 ph->p_offset = interp->sh_offset;
1862 ph->p_vaddr = interp->sh_addr;
1863 ph->p_paddr = ph->p_vaddr;
1864 ph->p_filesz = interp->sh_size;
1865 ph->p_memsz = interp->sh_size;
1866 ph->p_flags = PF_R;
1867 ph->p_align = interp->sh_addralign;
1870 /* if dynamic section, then add corresponing program header */
1871 if (dynamic) {
1872 ElfW(Sym) *sym_end;
1874 ph = &phdr[phnum - 1];
1876 ph->p_type = PT_DYNAMIC;
1877 ph->p_offset = dynamic->sh_offset;
1878 ph->p_vaddr = dynamic->sh_addr;
1879 ph->p_paddr = ph->p_vaddr;
1880 ph->p_filesz = dynamic->sh_size;
1881 ph->p_memsz = dynamic->sh_size;
1882 ph->p_flags = PF_R | PF_W;
1883 ph->p_align = dynamic->sh_addralign;
1885 /* put GOT dynamic section address */
1886 put32(s1->got->data, dynamic->sh_addr);
1888 /* relocate the PLT */
1889 if (file_type == TCC_OUTPUT_EXE
1890 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1891 || file_type == TCC_OUTPUT_DLL
1892 #endif
1894 uint8_t *p, *p_end;
1896 p = s1->plt->data;
1897 p_end = p + s1->plt->data_offset;
1898 if (p < p_end) {
1899 #if defined(TCC_TARGET_I386)
1900 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1901 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1902 p += 16;
1903 while (p < p_end) {
1904 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1905 p += 16;
1907 #elif defined(TCC_TARGET_X86_64)
1908 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1909 put32(p + 2, get32(p + 2) + x);
1910 put32(p + 8, get32(p + 8) + x - 6);
1911 p += 16;
1912 while (p < p_end) {
1913 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1914 p += 16;
1916 #elif defined(TCC_TARGET_ARM)
1917 int x;
1918 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1919 p +=16;
1920 while (p < p_end) {
1921 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1922 p += 16;
1924 #elif defined(TCC_TARGET_C67)
1925 /* XXX: TODO */
1926 #else
1927 #error unsupported CPU
1928 #endif
1932 /* relocate symbols in .dynsym */
1933 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
1934 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
1935 sym < sym_end;
1936 sym++) {
1937 if (sym->st_shndx == SHN_UNDEF) {
1938 /* relocate to the PLT if the symbol corresponds
1939 to a PLT entry */
1940 if (sym->st_value)
1941 sym->st_value += s1->plt->sh_addr;
1942 } else if (sym->st_shndx < SHN_LORESERVE) {
1943 /* do symbol relocation */
1944 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
1948 /* put dynamic section entries */
1949 dynamic->data_offset = saved_dynamic_data_offset;
1950 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
1951 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
1952 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
1953 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
1954 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
1955 #ifdef TCC_TARGET_X86_64
1956 put_dt(dynamic, DT_RELA, rel_addr);
1957 put_dt(dynamic, DT_RELASZ, rel_size);
1958 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
1959 #else
1960 #if defined(__FreeBSD__)
1961 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
1962 put_dt(dynamic, DT_PLTRELSZ, rel_size);
1963 put_dt(dynamic, DT_JMPREL, rel_addr);
1964 put_dt(dynamic, DT_PLTREL, DT_REL);
1965 put_dt(dynamic, DT_REL, bss_addr);
1966 put_dt(dynamic, DT_RELSZ, bss_size);
1967 #else
1968 put_dt(dynamic, DT_REL, rel_addr);
1969 put_dt(dynamic, DT_RELSZ, rel_size);
1970 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
1971 #endif
1972 #endif
1973 if (s1->do_debug)
1974 put_dt(dynamic, DT_DEBUG, 0);
1975 put_dt(dynamic, DT_NULL, 0);
1978 ehdr.e_phentsize = sizeof(ElfW(Phdr));
1979 ehdr.e_phnum = phnum;
1980 ehdr.e_phoff = sizeof(ElfW(Ehdr));
1983 /* all other sections come after */
1984 for(i = 1; i < s1->nb_sections; i++) {
1985 s = s1->sections[i];
1986 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
1987 continue;
1988 section_order[sh_order_index++] = i;
1990 file_offset = (file_offset + s->sh_addralign - 1) &
1991 ~(s->sh_addralign - 1);
1992 s->sh_offset = file_offset;
1993 if (s->sh_type != SHT_NOBITS)
1994 file_offset += s->sh_size;
1997 /* if building executable or DLL, then relocate each section
1998 except the GOT which is already relocated */
1999 if (file_type != TCC_OUTPUT_OBJ) {
2000 relocate_syms(s1, 0);
2002 if (s1->nb_errors != 0) {
2003 fail:
2004 ret = -1;
2005 goto the_end;
2008 /* relocate sections */
2009 /* XXX: ignore sections with allocated relocations ? */
2010 for(i = 1; i < s1->nb_sections; i++) {
2011 s = s1->sections[i];
2012 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
2013 relocate_section(s1, s);
2016 /* relocate relocation entries if the relocation tables are
2017 allocated in the executable */
2018 for(i = 1; i < s1->nb_sections; i++) {
2019 s = s1->sections[i];
2020 if ((s->sh_flags & SHF_ALLOC) &&
2021 s->sh_type == SHT_RELX) {
2022 relocate_rel(s1, s);
2026 /* get entry point address */
2027 if (file_type == TCC_OUTPUT_EXE)
2028 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
2029 else
2030 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2032 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2033 fill_got(s1);
2035 /* write elf file */
2036 if (file_type == TCC_OUTPUT_OBJ)
2037 mode = 0666;
2038 else
2039 mode = 0777;
2040 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2041 if (fd < 0) {
2042 error_noabort("could not write '%s'", filename);
2043 goto fail;
2045 f = fdopen(fd, "wb");
2046 if (s1->verbose)
2047 printf("<- %s\n", filename);
2049 #ifdef TCC_TARGET_COFF
2050 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2051 tcc_output_coff(s1, f);
2052 } else
2053 #endif
2054 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2055 sort_syms(s1, symtab_section);
2057 /* align to 4 */
2058 file_offset = (file_offset + 3) & -4;
2060 /* fill header */
2061 ehdr.e_ident[0] = ELFMAG0;
2062 ehdr.e_ident[1] = ELFMAG1;
2063 ehdr.e_ident[2] = ELFMAG2;
2064 ehdr.e_ident[3] = ELFMAG3;
2065 ehdr.e_ident[4] = TCC_ELFCLASS;
2066 ehdr.e_ident[5] = ELFDATA2LSB;
2067 ehdr.e_ident[6] = EV_CURRENT;
2068 #ifdef __FreeBSD__
2069 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2070 #endif
2071 #ifdef TCC_TARGET_ARM
2072 #ifdef TCC_ARM_EABI
2073 ehdr.e_ident[EI_OSABI] = 0;
2074 ehdr.e_flags = 4 << 24;
2075 #else
2076 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2077 #endif
2078 #endif
2079 switch(file_type) {
2080 default:
2081 case TCC_OUTPUT_EXE:
2082 ehdr.e_type = ET_EXEC;
2083 break;
2084 case TCC_OUTPUT_DLL:
2085 ehdr.e_type = ET_DYN;
2086 break;
2087 case TCC_OUTPUT_OBJ:
2088 ehdr.e_type = ET_REL;
2089 break;
2091 ehdr.e_machine = EM_TCC_TARGET;
2092 ehdr.e_version = EV_CURRENT;
2093 ehdr.e_shoff = file_offset;
2094 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2095 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2096 ehdr.e_shnum = shnum;
2097 ehdr.e_shstrndx = shnum - 1;
2099 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2100 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2101 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2103 for(i=1;i<s1->nb_sections;i++) {
2104 s = s1->sections[section_order[i]];
2105 if (s->sh_type != SHT_NOBITS) {
2106 #if defined(__FreeBSD__)
2107 if (s->sh_type == SHT_DYNSYM)
2108 patch_dynsym_undef(s1, s);
2109 #endif
2110 while (offset < s->sh_offset) {
2111 fputc(0, f);
2112 offset++;
2114 size = s->sh_size;
2115 fwrite(s->data, 1, size, f);
2116 offset += size;
2120 /* output section headers */
2121 while (offset < ehdr.e_shoff) {
2122 fputc(0, f);
2123 offset++;
2126 for(i=0;i<s1->nb_sections;i++) {
2127 sh = &shdr;
2128 memset(sh, 0, sizeof(ElfW(Shdr)));
2129 s = s1->sections[i];
2130 if (s) {
2131 sh->sh_name = s->sh_name;
2132 sh->sh_type = s->sh_type;
2133 sh->sh_flags = s->sh_flags;
2134 sh->sh_entsize = s->sh_entsize;
2135 sh->sh_info = s->sh_info;
2136 if (s->link)
2137 sh->sh_link = s->link->sh_num;
2138 sh->sh_addralign = s->sh_addralign;
2139 sh->sh_addr = s->sh_addr;
2140 sh->sh_offset = s->sh_offset;
2141 sh->sh_size = s->sh_size;
2143 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2145 } else {
2146 tcc_output_binary(s1, f, section_order);
2148 fclose(f);
2150 ret = 0;
2151 the_end:
2152 tcc_free(s1->symtab_to_dynsym);
2153 tcc_free(section_order);
2154 tcc_free(phdr);
2155 tcc_free(s1->got_offsets);
2156 return ret;
2159 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2161 int ret;
2162 #ifdef TCC_TARGET_PE
2163 if (s->output_type != TCC_OUTPUT_OBJ) {
2164 ret = pe_output_file(s, filename);
2165 } else
2166 #endif
2168 ret = elf_output_file(s, filename);
2170 return ret;
2173 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2175 void *data;
2177 data = tcc_malloc(size);
2178 lseek(fd, file_offset, SEEK_SET);
2179 read(fd, data, size);
2180 return data;
2183 typedef struct SectionMergeInfo {
2184 Section *s; /* corresponding existing section */
2185 unsigned long offset; /* offset of the new section in the existing section */
2186 uint8_t new_section; /* true if section 's' was added */
2187 uint8_t link_once; /* true if link once section */
2188 } SectionMergeInfo;
2190 /* load an object file and merge it with current files */
2191 /* XXX: handle correctly stab (debug) info */
2192 ST_FUNC int tcc_load_object_file(TCCState *s1,
2193 int fd, unsigned long file_offset)
2195 ElfW(Ehdr) ehdr;
2196 ElfW(Shdr) *shdr, *sh;
2197 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2198 unsigned char *strsec, *strtab;
2199 int *old_to_new_syms;
2200 char *sh_name, *name;
2201 SectionMergeInfo *sm_table, *sm;
2202 ElfW(Sym) *sym, *symtab;
2203 ElfW_Rel *rel, *rel_end;
2204 Section *s;
2206 int stab_index;
2207 int stabstr_index;
2209 stab_index = stabstr_index = 0;
2211 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2212 goto fail1;
2213 if (ehdr.e_ident[0] != ELFMAG0 ||
2214 ehdr.e_ident[1] != ELFMAG1 ||
2215 ehdr.e_ident[2] != ELFMAG2 ||
2216 ehdr.e_ident[3] != ELFMAG3)
2217 goto fail1;
2218 /* test if object file */
2219 if (ehdr.e_type != ET_REL)
2220 goto fail1;
2221 /* test CPU specific stuff */
2222 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2223 ehdr.e_machine != EM_TCC_TARGET) {
2224 fail1:
2225 error_noabort("invalid object file");
2226 return -1;
2228 /* read sections */
2229 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2230 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2231 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2233 /* load section names */
2234 sh = &shdr[ehdr.e_shstrndx];
2235 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2237 /* load symtab and strtab */
2238 old_to_new_syms = NULL;
2239 symtab = NULL;
2240 strtab = NULL;
2241 nb_syms = 0;
2242 for(i = 1; i < ehdr.e_shnum; i++) {
2243 sh = &shdr[i];
2244 if (sh->sh_type == SHT_SYMTAB) {
2245 if (symtab) {
2246 error_noabort("object must contain only one symtab");
2247 fail:
2248 ret = -1;
2249 goto the_end;
2251 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2252 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2253 sm_table[i].s = symtab_section;
2255 /* now load strtab */
2256 sh = &shdr[sh->sh_link];
2257 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2261 /* now examine each section and try to merge its content with the
2262 ones in memory */
2263 for(i = 1; i < ehdr.e_shnum; i++) {
2264 /* no need to examine section name strtab */
2265 if (i == ehdr.e_shstrndx)
2266 continue;
2267 sh = &shdr[i];
2268 sh_name = strsec + sh->sh_name;
2269 /* ignore sections types we do not handle */
2270 if (sh->sh_type != SHT_PROGBITS &&
2271 sh->sh_type != SHT_RELX &&
2272 #ifdef TCC_ARM_EABI
2273 sh->sh_type != SHT_ARM_EXIDX &&
2274 #endif
2275 sh->sh_type != SHT_NOBITS &&
2276 strcmp(sh_name, ".stabstr")
2278 continue;
2279 if (sh->sh_addralign < 1)
2280 sh->sh_addralign = 1;
2281 /* find corresponding section, if any */
2282 for(j = 1; j < s1->nb_sections;j++) {
2283 s = s1->sections[j];
2284 if (!strcmp(s->name, sh_name)) {
2285 if (!strncmp(sh_name, ".gnu.linkonce",
2286 sizeof(".gnu.linkonce") - 1)) {
2287 /* if a 'linkonce' section is already present, we
2288 do not add it again. It is a little tricky as
2289 symbols can still be defined in
2290 it. */
2291 sm_table[i].link_once = 1;
2292 goto next;
2293 } else {
2294 goto found;
2298 /* not found: create new section */
2299 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2300 /* take as much info as possible from the section. sh_link and
2301 sh_info will be updated later */
2302 s->sh_addralign = sh->sh_addralign;
2303 s->sh_entsize = sh->sh_entsize;
2304 sm_table[i].new_section = 1;
2305 found:
2306 if (sh->sh_type != s->sh_type) {
2307 error_noabort("invalid section type");
2308 goto fail;
2311 /* align start of section */
2312 offset = s->data_offset;
2314 if (0 == strcmp(sh_name, ".stab")) {
2315 stab_index = i;
2316 goto no_align;
2318 if (0 == strcmp(sh_name, ".stabstr")) {
2319 stabstr_index = i;
2320 goto no_align;
2323 size = sh->sh_addralign - 1;
2324 offset = (offset + size) & ~size;
2325 if (sh->sh_addralign > s->sh_addralign)
2326 s->sh_addralign = sh->sh_addralign;
2327 s->data_offset = offset;
2328 no_align:
2329 sm_table[i].offset = offset;
2330 sm_table[i].s = s;
2331 /* concatenate sections */
2332 size = sh->sh_size;
2333 if (sh->sh_type != SHT_NOBITS) {
2334 unsigned char *ptr;
2335 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2336 ptr = section_ptr_add(s, size);
2337 read(fd, ptr, size);
2338 } else {
2339 s->data_offset += size;
2341 next: ;
2344 /* //gr relocate stab strings */
2345 if (stab_index && stabstr_index) {
2346 Stab_Sym *a, *b;
2347 unsigned o;
2348 s = sm_table[stab_index].s;
2349 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2350 b = (Stab_Sym *)(s->data + s->data_offset);
2351 o = sm_table[stabstr_index].offset;
2352 while (a < b)
2353 a->n_strx += o, a++;
2356 /* second short pass to update sh_link and sh_info fields of new
2357 sections */
2358 for(i = 1; i < ehdr.e_shnum; i++) {
2359 s = sm_table[i].s;
2360 if (!s || !sm_table[i].new_section)
2361 continue;
2362 sh = &shdr[i];
2363 if (sh->sh_link > 0)
2364 s->link = sm_table[sh->sh_link].s;
2365 if (sh->sh_type == SHT_RELX) {
2366 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2367 /* update backward link */
2368 s1->sections[s->sh_info]->reloc = s;
2371 sm = sm_table;
2373 /* resolve symbols */
2374 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2376 sym = symtab + 1;
2377 for(i = 1; i < nb_syms; i++, sym++) {
2378 if (sym->st_shndx != SHN_UNDEF &&
2379 sym->st_shndx < SHN_LORESERVE) {
2380 sm = &sm_table[sym->st_shndx];
2381 if (sm->link_once) {
2382 /* if a symbol is in a link once section, we use the
2383 already defined symbol. It is very important to get
2384 correct relocations */
2385 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2386 name = strtab + sym->st_name;
2387 sym_index = find_elf_sym(symtab_section, name);
2388 if (sym_index)
2389 old_to_new_syms[i] = sym_index;
2391 continue;
2393 /* if no corresponding section added, no need to add symbol */
2394 if (!sm->s)
2395 continue;
2396 /* convert section number */
2397 sym->st_shndx = sm->s->sh_num;
2398 /* offset value */
2399 sym->st_value += sm->offset;
2401 /* add symbol */
2402 name = strtab + sym->st_name;
2403 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2404 sym->st_info, sym->st_other,
2405 sym->st_shndx, name);
2406 old_to_new_syms[i] = sym_index;
2409 /* third pass to patch relocation entries */
2410 for(i = 1; i < ehdr.e_shnum; i++) {
2411 s = sm_table[i].s;
2412 if (!s)
2413 continue;
2414 sh = &shdr[i];
2415 offset = sm_table[i].offset;
2416 switch(s->sh_type) {
2417 case SHT_RELX:
2418 /* take relocation offset information */
2419 offseti = sm_table[sh->sh_info].offset;
2420 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2421 for(rel = (ElfW_Rel *)(s->data + offset);
2422 rel < rel_end;
2423 rel++) {
2424 int type;
2425 unsigned sym_index;
2426 /* convert symbol index */
2427 type = ELFW(R_TYPE)(rel->r_info);
2428 sym_index = ELFW(R_SYM)(rel->r_info);
2429 /* NOTE: only one symtab assumed */
2430 if (sym_index >= nb_syms)
2431 goto invalid_reloc;
2432 sym_index = old_to_new_syms[sym_index];
2433 /* ignore link_once in rel section. */
2434 if (!sym_index && !sm->link_once) {
2435 invalid_reloc:
2436 error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2437 i, strsec + sh->sh_name, rel->r_offset);
2438 goto fail;
2440 rel->r_info = ELFW(R_INFO)(sym_index, type);
2441 /* offset the relocation offset */
2442 rel->r_offset += offseti;
2444 break;
2445 default:
2446 break;
2450 ret = 0;
2451 the_end:
2452 tcc_free(symtab);
2453 tcc_free(strtab);
2454 tcc_free(old_to_new_syms);
2455 tcc_free(sm_table);
2456 tcc_free(strsec);
2457 tcc_free(shdr);
2458 return ret;
2461 typedef struct ArchiveHeader {
2462 char ar_name[16]; /* name of this member */
2463 char ar_date[12]; /* file mtime */
2464 char ar_uid[6]; /* owner uid; printed as decimal */
2465 char ar_gid[6]; /* owner gid; printed as decimal */
2466 char ar_mode[8]; /* file mode, printed as octal */
2467 char ar_size[10]; /* file size, printed as decimal */
2468 char ar_fmag[2]; /* should contain ARFMAG */
2469 } ArchiveHeader;
2471 static int get_be32(const uint8_t *b)
2473 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2476 /* load only the objects which resolve undefined symbols */
2477 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2479 int i, bound, nsyms, sym_index, off, ret;
2480 uint8_t *data;
2481 const char *ar_names, *p;
2482 const uint8_t *ar_index;
2483 ElfW(Sym) *sym;
2485 data = tcc_malloc(size);
2486 if (read(fd, data, size) != size)
2487 goto fail;
2488 nsyms = get_be32(data);
2489 ar_index = data + 4;
2490 ar_names = ar_index + nsyms * 4;
2492 do {
2493 bound = 0;
2494 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2495 sym_index = find_elf_sym(symtab_section, p);
2496 if(sym_index) {
2497 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2498 if(sym->st_shndx == SHN_UNDEF) {
2499 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2500 #if 0
2501 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2502 #endif
2503 ++bound;
2504 lseek(fd, off, SEEK_SET);
2505 if(tcc_load_object_file(s1, fd, off) < 0) {
2506 fail:
2507 ret = -1;
2508 goto the_end;
2513 } while(bound);
2514 ret = 0;
2515 the_end:
2516 tcc_free(data);
2517 return ret;
2520 /* load a '.a' file */
2521 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2523 ArchiveHeader hdr;
2524 char ar_size[11];
2525 char ar_name[17];
2526 char magic[8];
2527 int size, len, i;
2528 unsigned long file_offset;
2530 /* skip magic which was already checked */
2531 read(fd, magic, sizeof(magic));
2533 for(;;) {
2534 len = read(fd, &hdr, sizeof(hdr));
2535 if (len == 0)
2536 break;
2537 if (len != sizeof(hdr)) {
2538 error_noabort("invalid archive");
2539 return -1;
2541 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2542 ar_size[sizeof(hdr.ar_size)] = '\0';
2543 size = strtol(ar_size, NULL, 0);
2544 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2545 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2546 if (ar_name[i] != ' ')
2547 break;
2549 ar_name[i + 1] = '\0';
2550 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2551 file_offset = lseek(fd, 0, SEEK_CUR);
2552 /* align to even */
2553 size = (size + 1) & ~1;
2554 if (!strcmp(ar_name, "/")) {
2555 /* coff symbol table : we handle it */
2556 if(s1->alacarte_link)
2557 return tcc_load_alacarte(s1, fd, size);
2558 } else if (!strcmp(ar_name, "//") ||
2559 !strcmp(ar_name, "__.SYMDEF") ||
2560 !strcmp(ar_name, "__.SYMDEF/") ||
2561 !strcmp(ar_name, "ARFILENAMES/")) {
2562 /* skip symbol table or archive names */
2563 } else {
2564 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2565 return -1;
2567 lseek(fd, file_offset + size, SEEK_SET);
2569 return 0;
2572 #ifndef TCC_TARGET_PE
2573 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2574 is referenced by the user (so it should be added as DT_NEEDED in
2575 the generated ELF file) */
2576 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2578 ElfW(Ehdr) ehdr;
2579 ElfW(Shdr) *shdr, *sh, *sh1;
2580 int i, j, nb_syms, nb_dts, sym_bind, ret;
2581 ElfW(Sym) *sym, *dynsym;
2582 ElfW(Dyn) *dt, *dynamic;
2583 unsigned char *dynstr;
2584 const char *name, *soname;
2585 DLLReference *dllref;
2587 read(fd, &ehdr, sizeof(ehdr));
2589 /* test CPU specific stuff */
2590 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2591 ehdr.e_machine != EM_TCC_TARGET) {
2592 error_noabort("bad architecture");
2593 return -1;
2596 /* read sections */
2597 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2599 /* load dynamic section and dynamic symbols */
2600 nb_syms = 0;
2601 nb_dts = 0;
2602 dynamic = NULL;
2603 dynsym = NULL; /* avoid warning */
2604 dynstr = NULL; /* avoid warning */
2605 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2606 switch(sh->sh_type) {
2607 case SHT_DYNAMIC:
2608 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2609 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2610 break;
2611 case SHT_DYNSYM:
2612 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2613 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2614 sh1 = &shdr[sh->sh_link];
2615 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2616 break;
2617 default:
2618 break;
2622 /* compute the real library name */
2623 soname = tcc_basename(filename);
2625 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2626 if (dt->d_tag == DT_SONAME) {
2627 soname = dynstr + dt->d_un.d_val;
2631 /* if the dll is already loaded, do not load it */
2632 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2633 dllref = s1->loaded_dlls[i];
2634 if (!strcmp(soname, dllref->name)) {
2635 /* but update level if needed */
2636 if (level < dllref->level)
2637 dllref->level = level;
2638 ret = 0;
2639 goto the_end;
2643 // printf("loading dll '%s'\n", soname);
2645 /* add the dll and its level */
2646 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2647 dllref->level = level;
2648 strcpy(dllref->name, soname);
2649 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2651 /* add dynamic symbols in dynsym_section */
2652 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2653 sym_bind = ELFW(ST_BIND)(sym->st_info);
2654 if (sym_bind == STB_LOCAL)
2655 continue;
2656 name = dynstr + sym->st_name;
2657 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2658 sym->st_info, sym->st_other, sym->st_shndx, name);
2661 /* load all referenced DLLs */
2662 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2663 switch(dt->d_tag) {
2664 case DT_NEEDED:
2665 name = dynstr + dt->d_un.d_val;
2666 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2667 dllref = s1->loaded_dlls[j];
2668 if (!strcmp(name, dllref->name))
2669 goto already_loaded;
2671 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2672 error_noabort("referenced dll '%s' not found", name);
2673 ret = -1;
2674 goto the_end;
2676 already_loaded:
2677 break;
2680 ret = 0;
2681 the_end:
2682 tcc_free(dynstr);
2683 tcc_free(dynsym);
2684 tcc_free(dynamic);
2685 tcc_free(shdr);
2686 return ret;
2689 #define LD_TOK_NAME 256
2690 #define LD_TOK_EOF (-1)
2692 /* return next ld script token */
2693 static int ld_next(TCCState *s1, char *name, int name_size)
2695 int c;
2696 char *q;
2698 redo:
2699 switch(ch) {
2700 case ' ':
2701 case '\t':
2702 case '\f':
2703 case '\v':
2704 case '\r':
2705 case '\n':
2706 inp();
2707 goto redo;
2708 case '/':
2709 minp();
2710 if (ch == '*') {
2711 file->buf_ptr = parse_comment(file->buf_ptr);
2712 ch = file->buf_ptr[0];
2713 goto redo;
2714 } else {
2715 q = name;
2716 *q++ = '/';
2717 goto parse_name;
2719 break;
2720 /* case 'a' ... 'z': */
2721 case 'a':
2722 case 'b':
2723 case 'c':
2724 case 'd':
2725 case 'e':
2726 case 'f':
2727 case 'g':
2728 case 'h':
2729 case 'i':
2730 case 'j':
2731 case 'k':
2732 case 'l':
2733 case 'm':
2734 case 'n':
2735 case 'o':
2736 case 'p':
2737 case 'q':
2738 case 'r':
2739 case 's':
2740 case 't':
2741 case 'u':
2742 case 'v':
2743 case 'w':
2744 case 'x':
2745 case 'y':
2746 case 'z':
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 '_':
2775 case '\\':
2776 case '.':
2777 case '$':
2778 case '~':
2779 q = name;
2780 parse_name:
2781 for(;;) {
2782 if (!((ch >= 'a' && ch <= 'z') ||
2783 (ch >= 'A' && ch <= 'Z') ||
2784 (ch >= '0' && ch <= '9') ||
2785 strchr("/.-_+=$:\\,~", ch)))
2786 break;
2787 if ((q - name) < name_size - 1) {
2788 *q++ = ch;
2790 minp();
2792 *q = '\0';
2793 c = LD_TOK_NAME;
2794 break;
2795 case CH_EOF:
2796 c = LD_TOK_EOF;
2797 break;
2798 default:
2799 c = ch;
2800 inp();
2801 break;
2803 #if 0
2804 printf("tok=%c %d\n", c, c);
2805 if (c == LD_TOK_NAME)
2806 printf(" name=%s\n", name);
2807 #endif
2808 return c;
2811 static int ld_add_file_list(TCCState *s1, int as_needed)
2813 char filename[1024];
2814 int t, ret;
2816 t = ld_next(s1, filename, sizeof(filename));
2817 if (t != '(')
2818 expect("(");
2819 t = ld_next(s1, filename, sizeof(filename));
2820 for(;;) {
2821 if (t == LD_TOK_EOF) {
2822 error_noabort("unexpected end of file");
2823 return -1;
2824 } else if (t == ')') {
2825 break;
2826 } else if (t != LD_TOK_NAME) {
2827 error_noabort("filename expected");
2828 return -1;
2830 if (!strcmp(filename, "AS_NEEDED")) {
2831 ret = ld_add_file_list(s1, 1);
2832 if (ret)
2833 return ret;
2834 } else {
2835 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2836 if (!as_needed)
2837 tcc_add_file(s1, filename);
2839 t = ld_next(s1, filename, sizeof(filename));
2840 if (t == ',') {
2841 t = ld_next(s1, filename, sizeof(filename));
2844 return 0;
2847 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
2848 files */
2849 ST_FUNC int tcc_load_ldscript(TCCState *s1)
2851 char cmd[64];
2852 char filename[1024];
2853 int t, ret;
2855 ch = file->buf_ptr[0];
2856 ch = handle_eob();
2857 for(;;) {
2858 t = ld_next(s1, cmd, sizeof(cmd));
2859 if (t == LD_TOK_EOF)
2860 return 0;
2861 else if (t != LD_TOK_NAME)
2862 return -1;
2863 if (!strcmp(cmd, "INPUT") ||
2864 !strcmp(cmd, "GROUP")) {
2865 ret = ld_add_file_list(s1, 0);
2866 if (ret)
2867 return ret;
2868 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
2869 !strcmp(cmd, "TARGET")) {
2870 /* ignore some commands */
2871 t = ld_next(s1, cmd, sizeof(cmd));
2872 if (t != '(')
2873 expect("(");
2874 for(;;) {
2875 t = ld_next(s1, filename, sizeof(filename));
2876 if (t == LD_TOK_EOF) {
2877 error_noabort("unexpected end of file");
2878 return -1;
2879 } else if (t == ')') {
2880 break;
2883 } else {
2884 return -1;
2887 return 0;
2889 #endif