tccpp: signal missing #endif error
[tinycc/kirr.git] / tccelf.c
bloba5385b19ea1e2c9a74af7b23dee4cbde7274a7a4
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 static const char elf_interp[] = "/lib/ld-linux-x86-64.so.2";
1311 #elif defined(TCC_UCLIBC)
1312 static const char elf_interp[] = "/lib/ld-uClibc.so.0";
1313 #else
1314 static const char elf_interp[] = "/lib/ld-linux.so.2";
1315 #endif
1317 static void tcc_output_binary(TCCState *s1, FILE *f,
1318 const int *section_order)
1320 Section *s;
1321 int i, offset, size;
1323 offset = 0;
1324 for(i=1;i<s1->nb_sections;i++) {
1325 s = s1->sections[section_order[i]];
1326 if (s->sh_type != SHT_NOBITS &&
1327 (s->sh_flags & SHF_ALLOC)) {
1328 while (offset < s->sh_offset) {
1329 fputc(0, f);
1330 offset++;
1332 size = s->sh_size;
1333 fwrite(s->data, 1, size, f);
1334 offset += size;
1339 #if defined(__FreeBSD__)
1340 #define HAVE_PHDR 1
1341 #define EXTRA_RELITEMS 14
1343 /* move the relocation value from .dynsym to .got */
1344 void patch_dynsym_undef(TCCState *s1, Section *s)
1346 uint32_t *gotd = (void *)s1->got->data;
1347 ElfW(Sym) *sym, *sym_end;
1349 gotd += 3; // dummy entries in .got
1350 /* relocate symbols in .dynsym */
1351 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1352 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1353 if (sym->st_shndx == SHN_UNDEF) {
1354 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1355 sym->st_value = 0;
1359 #else
1360 #define HAVE_PHDR 0
1361 #define EXTRA_RELITEMS 9
1362 #endif
1364 /* output an ELF file */
1365 /* XXX: suppress unneeded sections */
1366 static int elf_output_file(TCCState *s1, const char *filename)
1368 ElfW(Ehdr) ehdr;
1369 FILE *f;
1370 int fd, mode, ret;
1371 int *section_order;
1372 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
1373 unsigned long addr;
1374 Section *strsec, *s;
1375 ElfW(Shdr) shdr, *sh;
1376 ElfW(Phdr) *phdr, *ph;
1377 Section *interp, *dynamic, *dynstr;
1378 unsigned long saved_dynamic_data_offset;
1379 ElfW(Sym) *sym;
1380 int type, file_type;
1381 unsigned long rel_addr, rel_size;
1382 unsigned long bss_addr, bss_size;
1384 file_type = s1->output_type;
1385 s1->nb_errors = 0;
1387 if (file_type != TCC_OUTPUT_OBJ) {
1388 tcc_add_runtime(s1);
1391 phdr = NULL;
1392 section_order = NULL;
1393 interp = NULL;
1394 dynamic = NULL;
1395 dynstr = NULL; /* avoid warning */
1396 saved_dynamic_data_offset = 0; /* avoid warning */
1398 if (file_type != TCC_OUTPUT_OBJ) {
1399 relocate_common_syms();
1401 tcc_add_linker_symbols(s1);
1403 if (!s1->static_link) {
1404 const char *name;
1405 int sym_index, index;
1406 ElfW(Sym) *esym, *sym_end;
1408 if (file_type == TCC_OUTPUT_EXE) {
1409 char *ptr;
1410 /* allow override the dynamic loader */
1411 const char *elfint = getenv("LD_SO");
1412 if (elfint == NULL)
1413 elfint = elf_interp;
1414 /* add interpreter section only if executable */
1415 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1416 interp->sh_addralign = 1;
1417 ptr = section_ptr_add(interp, 1+strlen(elfint));
1418 strcpy(ptr, elfint);
1421 /* add dynamic symbol table */
1422 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1423 ".dynstr",
1424 ".hash", SHF_ALLOC);
1425 dynstr = s1->dynsym->link;
1427 /* add dynamic section */
1428 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1429 SHF_ALLOC | SHF_WRITE);
1430 dynamic->link = dynstr;
1431 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1433 /* add PLT */
1434 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1435 SHF_ALLOC | SHF_EXECINSTR);
1436 s1->plt->sh_entsize = 4;
1438 build_got(s1);
1440 /* scan for undefined symbols and see if they are in the
1441 dynamic symbols. If a symbol STT_FUNC is found, then we
1442 add it in the PLT. If a symbol STT_OBJECT is found, we
1443 add it in the .bss section with a suitable relocation */
1444 sym_end = (ElfW(Sym) *)(symtab_section->data +
1445 symtab_section->data_offset);
1446 if (file_type == TCC_OUTPUT_EXE) {
1447 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1448 sym < sym_end;
1449 sym++) {
1450 if (sym->st_shndx == SHN_UNDEF) {
1451 name = symtab_section->link->data + sym->st_name;
1452 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1453 if (sym_index) {
1454 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1455 type = ELFW(ST_TYPE)(esym->st_info);
1456 if (type == STT_FUNC) {
1457 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1458 esym->st_info,
1459 sym - (ElfW(Sym) *)symtab_section->data);
1460 } else if (type == STT_OBJECT) {
1461 unsigned long offset;
1462 offset = bss_section->data_offset;
1463 /* XXX: which alignment ? */
1464 offset = (offset + 16 - 1) & -16;
1465 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1466 esym->st_info, 0,
1467 bss_section->sh_num, name);
1468 put_elf_reloc(s1->dynsym, bss_section,
1469 offset, R_COPY, index);
1470 offset += esym->st_size;
1471 bss_section->data_offset = offset;
1473 } else {
1474 /* STB_WEAK undefined symbols are accepted */
1475 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1476 it */
1477 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1478 !strcmp(name, "_fp_hw")) {
1479 } else {
1480 error_noabort("undefined symbol '%s'", name);
1483 } else if (s1->rdynamic &&
1484 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1485 /* if -rdynamic option, then export all non
1486 local symbols */
1487 name = symtab_section->link->data + sym->st_name;
1488 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1489 sym->st_info, 0,
1490 sym->st_shndx, name);
1494 if (s1->nb_errors)
1495 goto fail;
1497 /* now look at unresolved dynamic symbols and export
1498 corresponding symbol */
1499 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1500 s1->dynsymtab_section->data_offset);
1501 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1502 esym < sym_end;
1503 esym++) {
1504 if (esym->st_shndx == SHN_UNDEF) {
1505 name = s1->dynsymtab_section->link->data + esym->st_name;
1506 sym_index = find_elf_sym(symtab_section, name);
1507 if (sym_index) {
1508 /* XXX: avoid adding a symbol if already
1509 present because of -rdynamic ? */
1510 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1511 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1512 sym->st_info, 0,
1513 sym->st_shndx, name);
1514 } else {
1515 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1516 /* weak symbols can stay undefined */
1517 } else {
1518 warning("undefined dynamic symbol '%s'", name);
1523 } else {
1524 int nb_syms;
1525 /* shared library case : we simply export all the global symbols */
1526 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1527 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1528 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1529 sym < sym_end;
1530 sym++) {
1531 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1532 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1533 if (ELFW(ST_TYPE)(sym->st_info) == STT_FUNC &&
1534 sym->st_shndx == SHN_UNDEF) {
1535 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1536 sym->st_info,
1537 sym - (ElfW(Sym) *)symtab_section->data);
1539 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1540 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1541 sym->st_info,
1542 sym - (ElfW(Sym) *)symtab_section->data);
1544 else
1545 #endif
1547 name = symtab_section->link->data + sym->st_name;
1548 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1549 sym->st_info, 0,
1550 sym->st_shndx, name);
1551 s1->symtab_to_dynsym[sym -
1552 (ElfW(Sym) *)symtab_section->data] =
1553 index;
1559 build_got_entries(s1);
1561 /* add a list of needed dlls */
1562 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1563 DLLReference *dllref = s1->loaded_dlls[i];
1564 if (dllref->level == 0)
1565 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1568 if (s1->rpath)
1569 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1571 /* XXX: currently, since we do not handle PIC code, we
1572 must relocate the readonly segments */
1573 if (file_type == TCC_OUTPUT_DLL) {
1574 if (s1->soname)
1575 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1576 put_dt(dynamic, DT_TEXTREL, 0);
1578 /* add necessary space for other entries */
1579 saved_dynamic_data_offset = dynamic->data_offset;
1580 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1581 } else {
1582 /* still need to build got entries in case of static link */
1583 build_got_entries(s1);
1587 memset(&ehdr, 0, sizeof(ehdr));
1589 /* we add a section for symbols */
1590 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1591 put_elf_str(strsec, "");
1593 /* compute number of sections */
1594 shnum = s1->nb_sections;
1596 /* this array is used to reorder sections in the output file */
1597 section_order = tcc_malloc(sizeof(int) * shnum);
1598 section_order[0] = 0;
1599 sh_order_index = 1;
1601 /* compute number of program headers */
1602 switch(file_type) {
1603 default:
1604 case TCC_OUTPUT_OBJ:
1605 phnum = 0;
1606 break;
1607 case TCC_OUTPUT_EXE:
1608 if (!s1->static_link)
1609 phnum = 4 + HAVE_PHDR;
1610 else
1611 phnum = 2;
1612 break;
1613 case TCC_OUTPUT_DLL:
1614 phnum = 3;
1615 break;
1618 /* allocate strings for section names and decide if an unallocated
1619 section should be output */
1620 /* NOTE: the strsec section comes last, so its size is also
1621 correct ! */
1622 for(i = 1; i < s1->nb_sections; i++) {
1623 s = s1->sections[i];
1624 s->sh_name = put_elf_str(strsec, s->name);
1625 #if 0 //gr
1626 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1627 s->sh_flags,
1628 s->sh_type,
1629 s->sh_info,
1630 s->name,
1631 s->reloc ? s->reloc->name : "n"
1633 #endif
1634 /* when generating a DLL, we include relocations but we may
1635 patch them */
1636 if (file_type == TCC_OUTPUT_DLL &&
1637 s->sh_type == SHT_RELX &&
1638 !(s->sh_flags & SHF_ALLOC)) {
1639 /* //gr: avoid bogus relocs for empty (debug) sections */
1640 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1641 prepare_dynamic_rel(s1, s);
1642 else if (s1->do_debug)
1643 s->sh_size = s->data_offset;
1644 } else if (s1->do_debug ||
1645 file_type == TCC_OUTPUT_OBJ ||
1646 (s->sh_flags & SHF_ALLOC) ||
1647 i == (s1->nb_sections - 1)) {
1648 /* we output all sections if debug or object file */
1649 s->sh_size = s->data_offset;
1653 /* allocate program segment headers */
1654 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1656 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1657 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1658 } else {
1659 file_offset = 0;
1661 if (phnum > 0) {
1662 /* compute section to program header mapping */
1663 if (s1->has_text_addr) {
1664 int a_offset, p_offset;
1665 addr = s1->text_addr;
1666 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1667 ELF_PAGE_SIZE */
1668 a_offset = addr & (s1->section_align - 1);
1669 p_offset = file_offset & (s1->section_align - 1);
1670 if (a_offset < p_offset)
1671 a_offset += s1->section_align;
1672 file_offset += (a_offset - p_offset);
1673 } else {
1674 if (file_type == TCC_OUTPUT_DLL)
1675 addr = 0;
1676 else
1677 addr = ELF_START_ADDR;
1678 /* compute address after headers */
1679 addr += (file_offset & (s1->section_align - 1));
1682 /* dynamic relocation table information, for .dynamic section */
1683 rel_size = 0;
1684 rel_addr = 0;
1686 bss_addr = bss_size = 0;
1687 /* leave one program header for the program interpreter */
1688 ph = &phdr[0];
1689 if (interp)
1690 ph += 1 + HAVE_PHDR;
1692 for(j = 0; j < 2; j++) {
1693 ph->p_type = PT_LOAD;
1694 if (j == 0)
1695 ph->p_flags = PF_R | PF_X;
1696 else
1697 ph->p_flags = PF_R | PF_W;
1698 ph->p_align = s1->section_align;
1700 /* we do the following ordering: interp, symbol tables,
1701 relocations, progbits, nobits */
1702 /* XXX: do faster and simpler sorting */
1703 for(k = 0; k < 5; k++) {
1704 for(i = 1; i < s1->nb_sections; i++) {
1705 s = s1->sections[i];
1706 /* compute if section should be included */
1707 if (j == 0) {
1708 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1709 SHF_ALLOC)
1710 continue;
1711 } else {
1712 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1713 (SHF_ALLOC | SHF_WRITE))
1714 continue;
1716 if (s == interp) {
1717 if (k != 0)
1718 continue;
1719 } else if (s->sh_type == SHT_DYNSYM ||
1720 s->sh_type == SHT_STRTAB ||
1721 s->sh_type == SHT_HASH) {
1722 if (k != 1)
1723 continue;
1724 } else if (s->sh_type == SHT_RELX) {
1725 if (k != 2)
1726 continue;
1727 } else if (s->sh_type == SHT_NOBITS) {
1728 if (k != 4)
1729 continue;
1730 } else {
1731 if (k != 3)
1732 continue;
1734 section_order[sh_order_index++] = i;
1736 /* section matches: we align it and add its size */
1737 tmp = addr;
1738 addr = (addr + s->sh_addralign - 1) &
1739 ~(s->sh_addralign - 1);
1740 file_offset += addr - tmp;
1741 s->sh_offset = file_offset;
1742 s->sh_addr = addr;
1744 /* update program header infos */
1745 if (ph->p_offset == 0) {
1746 ph->p_offset = file_offset;
1747 ph->p_vaddr = addr;
1748 ph->p_paddr = ph->p_vaddr;
1750 /* update dynamic relocation infos */
1751 if (s->sh_type == SHT_RELX) {
1752 #if defined(__FreeBSD__)
1753 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1754 rel_addr = addr;
1755 rel_size += s->sh_size; // XXX only first rel.
1757 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1758 bss_addr = addr;
1759 bss_size = s->sh_size; // XXX only first rel.
1761 #else
1762 if (rel_size == 0)
1763 rel_addr = addr;
1764 rel_size += s->sh_size;
1765 #endif
1767 addr += s->sh_size;
1768 if (s->sh_type != SHT_NOBITS)
1769 file_offset += s->sh_size;
1772 ph->p_filesz = file_offset - ph->p_offset;
1773 ph->p_memsz = addr - ph->p_vaddr;
1774 ph++;
1775 if (j == 0) {
1776 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1777 /* if in the middle of a page, we duplicate the page in
1778 memory so that one copy is RX and the other is RW */
1779 if ((addr & (s1->section_align - 1)) != 0)
1780 addr += s1->section_align;
1781 } else {
1782 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1783 file_offset = (file_offset + s1->section_align - 1) &
1784 ~(s1->section_align - 1);
1789 /* if interpreter, then add corresponing program header */
1790 if (interp) {
1791 ph = &phdr[0];
1793 #if defined(__FreeBSD__)
1795 int len = phnum * sizeof(ElfW(Phdr));
1797 ph->p_type = PT_PHDR;
1798 ph->p_offset = sizeof(ElfW(Ehdr));
1799 ph->p_vaddr = interp->sh_addr - len;
1800 ph->p_paddr = ph->p_vaddr;
1801 ph->p_filesz = ph->p_memsz = len;
1802 ph->p_flags = PF_R | PF_X;
1803 ph->p_align = 4; // interp->sh_addralign;
1804 ph++;
1806 #endif
1808 ph->p_type = PT_INTERP;
1809 ph->p_offset = interp->sh_offset;
1810 ph->p_vaddr = interp->sh_addr;
1811 ph->p_paddr = ph->p_vaddr;
1812 ph->p_filesz = interp->sh_size;
1813 ph->p_memsz = interp->sh_size;
1814 ph->p_flags = PF_R;
1815 ph->p_align = interp->sh_addralign;
1818 /* if dynamic section, then add corresponing program header */
1819 if (dynamic) {
1820 ElfW(Sym) *sym_end;
1822 ph = &phdr[phnum - 1];
1824 ph->p_type = PT_DYNAMIC;
1825 ph->p_offset = dynamic->sh_offset;
1826 ph->p_vaddr = dynamic->sh_addr;
1827 ph->p_paddr = ph->p_vaddr;
1828 ph->p_filesz = dynamic->sh_size;
1829 ph->p_memsz = dynamic->sh_size;
1830 ph->p_flags = PF_R | PF_W;
1831 ph->p_align = dynamic->sh_addralign;
1833 /* put GOT dynamic section address */
1834 put32(s1->got->data, dynamic->sh_addr);
1836 /* relocate the PLT */
1837 if (file_type == TCC_OUTPUT_EXE
1838 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1839 || file_type == TCC_OUTPUT_DLL
1840 #endif
1842 uint8_t *p, *p_end;
1844 p = s1->plt->data;
1845 p_end = p + s1->plt->data_offset;
1846 if (p < p_end) {
1847 #if defined(TCC_TARGET_I386)
1848 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1849 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1850 p += 16;
1851 while (p < p_end) {
1852 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1853 p += 16;
1855 #elif defined(TCC_TARGET_X86_64)
1856 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1857 put32(p + 2, get32(p + 2) + x);
1858 put32(p + 8, get32(p + 8) + x - 6);
1859 p += 16;
1860 while (p < p_end) {
1861 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1862 p += 16;
1864 #elif defined(TCC_TARGET_ARM)
1865 int x;
1866 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1867 p +=16;
1868 while (p < p_end) {
1869 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1870 p += 16;
1872 #elif defined(TCC_TARGET_C67)
1873 /* XXX: TODO */
1874 #else
1875 #error unsupported CPU
1876 #endif
1880 /* relocate symbols in .dynsym */
1881 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
1882 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
1883 sym < sym_end;
1884 sym++) {
1885 if (sym->st_shndx == SHN_UNDEF) {
1886 /* relocate to the PLT if the symbol corresponds
1887 to a PLT entry */
1888 if (sym->st_value)
1889 sym->st_value += s1->plt->sh_addr;
1890 } else if (sym->st_shndx < SHN_LORESERVE) {
1891 /* do symbol relocation */
1892 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
1896 /* put dynamic section entries */
1897 dynamic->data_offset = saved_dynamic_data_offset;
1898 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
1899 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
1900 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
1901 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
1902 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
1903 #ifdef TCC_TARGET_X86_64
1904 put_dt(dynamic, DT_RELA, rel_addr);
1905 put_dt(dynamic, DT_RELASZ, rel_size);
1906 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
1907 #else
1908 #if defined(__FreeBSD__)
1909 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
1910 put_dt(dynamic, DT_PLTRELSZ, rel_size);
1911 put_dt(dynamic, DT_JMPREL, rel_addr);
1912 put_dt(dynamic, DT_PLTREL, DT_REL);
1913 put_dt(dynamic, DT_REL, bss_addr);
1914 put_dt(dynamic, DT_RELSZ, bss_size);
1915 #else
1916 put_dt(dynamic, DT_REL, rel_addr);
1917 put_dt(dynamic, DT_RELSZ, rel_size);
1918 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
1919 #endif
1920 #endif
1921 if (s1->do_debug)
1922 put_dt(dynamic, DT_DEBUG, 0);
1923 put_dt(dynamic, DT_NULL, 0);
1926 ehdr.e_phentsize = sizeof(ElfW(Phdr));
1927 ehdr.e_phnum = phnum;
1928 ehdr.e_phoff = sizeof(ElfW(Ehdr));
1931 /* all other sections come after */
1932 for(i = 1; i < s1->nb_sections; i++) {
1933 s = s1->sections[i];
1934 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
1935 continue;
1936 section_order[sh_order_index++] = i;
1938 file_offset = (file_offset + s->sh_addralign - 1) &
1939 ~(s->sh_addralign - 1);
1940 s->sh_offset = file_offset;
1941 if (s->sh_type != SHT_NOBITS)
1942 file_offset += s->sh_size;
1945 /* if building executable or DLL, then relocate each section
1946 except the GOT which is already relocated */
1947 if (file_type != TCC_OUTPUT_OBJ) {
1948 relocate_syms(s1, 0);
1950 if (s1->nb_errors != 0) {
1951 fail:
1952 ret = -1;
1953 goto the_end;
1956 /* relocate sections */
1957 /* XXX: ignore sections with allocated relocations ? */
1958 for(i = 1; i < s1->nb_sections; i++) {
1959 s = s1->sections[i];
1960 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
1961 relocate_section(s1, s);
1964 /* relocate relocation entries if the relocation tables are
1965 allocated in the executable */
1966 for(i = 1; i < s1->nb_sections; i++) {
1967 s = s1->sections[i];
1968 if ((s->sh_flags & SHF_ALLOC) &&
1969 s->sh_type == SHT_RELX) {
1970 relocate_rel(s1, s);
1974 /* get entry point address */
1975 if (file_type == TCC_OUTPUT_EXE)
1976 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
1977 else
1978 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
1981 /* write elf file */
1982 if (file_type == TCC_OUTPUT_OBJ)
1983 mode = 0666;
1984 else
1985 mode = 0777;
1986 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
1987 if (fd < 0) {
1988 error_noabort("could not write '%s'", filename);
1989 goto fail;
1991 f = fdopen(fd, "wb");
1992 if (s1->verbose)
1993 printf("<- %s\n", filename);
1995 #ifdef TCC_TARGET_COFF
1996 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
1997 tcc_output_coff(s1, f);
1998 } else
1999 #endif
2000 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2001 sort_syms(s1, symtab_section);
2003 /* align to 4 */
2004 file_offset = (file_offset + 3) & -4;
2006 /* fill header */
2007 ehdr.e_ident[0] = ELFMAG0;
2008 ehdr.e_ident[1] = ELFMAG1;
2009 ehdr.e_ident[2] = ELFMAG2;
2010 ehdr.e_ident[3] = ELFMAG3;
2011 ehdr.e_ident[4] = TCC_ELFCLASS;
2012 ehdr.e_ident[5] = ELFDATA2LSB;
2013 ehdr.e_ident[6] = EV_CURRENT;
2014 #ifdef __FreeBSD__
2015 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2016 #endif
2017 #ifdef TCC_TARGET_ARM
2018 #ifdef TCC_ARM_EABI
2019 ehdr.e_ident[EI_OSABI] = 0;
2020 ehdr.e_flags = 4 << 24;
2021 #else
2022 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2023 #endif
2024 #endif
2025 switch(file_type) {
2026 default:
2027 case TCC_OUTPUT_EXE:
2028 ehdr.e_type = ET_EXEC;
2029 break;
2030 case TCC_OUTPUT_DLL:
2031 ehdr.e_type = ET_DYN;
2032 break;
2033 case TCC_OUTPUT_OBJ:
2034 ehdr.e_type = ET_REL;
2035 break;
2037 ehdr.e_machine = EM_TCC_TARGET;
2038 ehdr.e_version = EV_CURRENT;
2039 ehdr.e_shoff = file_offset;
2040 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2041 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2042 ehdr.e_shnum = shnum;
2043 ehdr.e_shstrndx = shnum - 1;
2045 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2046 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2047 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2049 for(i=1;i<s1->nb_sections;i++) {
2050 s = s1->sections[section_order[i]];
2051 if (s->sh_type != SHT_NOBITS) {
2052 #if defined(__FreeBSD__)
2053 if (s->sh_type == SHT_DYNSYM)
2054 patch_dynsym_undef(s1, s);
2055 #endif
2056 while (offset < s->sh_offset) {
2057 fputc(0, f);
2058 offset++;
2060 size = s->sh_size;
2061 fwrite(s->data, 1, size, f);
2062 offset += size;
2066 /* output section headers */
2067 while (offset < ehdr.e_shoff) {
2068 fputc(0, f);
2069 offset++;
2072 for(i=0;i<s1->nb_sections;i++) {
2073 sh = &shdr;
2074 memset(sh, 0, sizeof(ElfW(Shdr)));
2075 s = s1->sections[i];
2076 if (s) {
2077 sh->sh_name = s->sh_name;
2078 sh->sh_type = s->sh_type;
2079 sh->sh_flags = s->sh_flags;
2080 sh->sh_entsize = s->sh_entsize;
2081 sh->sh_info = s->sh_info;
2082 if (s->link)
2083 sh->sh_link = s->link->sh_num;
2084 sh->sh_addralign = s->sh_addralign;
2085 sh->sh_addr = s->sh_addr;
2086 sh->sh_offset = s->sh_offset;
2087 sh->sh_size = s->sh_size;
2089 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2091 } else {
2092 tcc_output_binary(s1, f, section_order);
2094 fclose(f);
2096 ret = 0;
2097 the_end:
2098 tcc_free(s1->symtab_to_dynsym);
2099 tcc_free(section_order);
2100 tcc_free(phdr);
2101 tcc_free(s1->got_offsets);
2102 return ret;
2105 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2107 int ret;
2108 #ifdef TCC_TARGET_PE
2109 if (s->output_type != TCC_OUTPUT_OBJ) {
2110 ret = pe_output_file(s, filename);
2111 } else
2112 #endif
2114 ret = elf_output_file(s, filename);
2116 return ret;
2119 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2121 void *data;
2123 data = tcc_malloc(size);
2124 lseek(fd, file_offset, SEEK_SET);
2125 read(fd, data, size);
2126 return data;
2129 typedef struct SectionMergeInfo {
2130 Section *s; /* corresponding existing section */
2131 unsigned long offset; /* offset of the new section in the existing section */
2132 uint8_t new_section; /* true if section 's' was added */
2133 uint8_t link_once; /* true if link once section */
2134 } SectionMergeInfo;
2136 /* load an object file and merge it with current files */
2137 /* XXX: handle correctly stab (debug) info */
2138 ST_FUNC int tcc_load_object_file(TCCState *s1,
2139 int fd, unsigned long file_offset)
2141 ElfW(Ehdr) ehdr;
2142 ElfW(Shdr) *shdr, *sh;
2143 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2144 unsigned char *strsec, *strtab;
2145 int *old_to_new_syms;
2146 char *sh_name, *name;
2147 SectionMergeInfo *sm_table, *sm;
2148 ElfW(Sym) *sym, *symtab;
2149 ElfW_Rel *rel, *rel_end;
2150 Section *s;
2152 int stab_index;
2153 int stabstr_index;
2155 stab_index = stabstr_index = 0;
2157 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2158 goto fail1;
2159 if (ehdr.e_ident[0] != ELFMAG0 ||
2160 ehdr.e_ident[1] != ELFMAG1 ||
2161 ehdr.e_ident[2] != ELFMAG2 ||
2162 ehdr.e_ident[3] != ELFMAG3)
2163 goto fail1;
2164 /* test if object file */
2165 if (ehdr.e_type != ET_REL)
2166 goto fail1;
2167 /* test CPU specific stuff */
2168 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2169 ehdr.e_machine != EM_TCC_TARGET) {
2170 fail1:
2171 error_noabort("invalid object file");
2172 return -1;
2174 /* read sections */
2175 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2176 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2177 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2179 /* load section names */
2180 sh = &shdr[ehdr.e_shstrndx];
2181 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2183 /* load symtab and strtab */
2184 old_to_new_syms = NULL;
2185 symtab = NULL;
2186 strtab = NULL;
2187 nb_syms = 0;
2188 for(i = 1; i < ehdr.e_shnum; i++) {
2189 sh = &shdr[i];
2190 if (sh->sh_type == SHT_SYMTAB) {
2191 if (symtab) {
2192 error_noabort("object must contain only one symtab");
2193 fail:
2194 ret = -1;
2195 goto the_end;
2197 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2198 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2199 sm_table[i].s = symtab_section;
2201 /* now load strtab */
2202 sh = &shdr[sh->sh_link];
2203 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2207 /* now examine each section and try to merge its content with the
2208 ones in memory */
2209 for(i = 1; i < ehdr.e_shnum; i++) {
2210 /* no need to examine section name strtab */
2211 if (i == ehdr.e_shstrndx)
2212 continue;
2213 sh = &shdr[i];
2214 sh_name = strsec + sh->sh_name;
2215 /* ignore sections types we do not handle */
2216 if (sh->sh_type != SHT_PROGBITS &&
2217 sh->sh_type != SHT_RELX &&
2218 #ifdef TCC_ARM_EABI
2219 sh->sh_type != SHT_ARM_EXIDX &&
2220 #endif
2221 sh->sh_type != SHT_NOBITS &&
2222 strcmp(sh_name, ".stabstr")
2224 continue;
2225 if (sh->sh_addralign < 1)
2226 sh->sh_addralign = 1;
2227 /* find corresponding section, if any */
2228 for(j = 1; j < s1->nb_sections;j++) {
2229 s = s1->sections[j];
2230 if (!strcmp(s->name, sh_name)) {
2231 if (!strncmp(sh_name, ".gnu.linkonce",
2232 sizeof(".gnu.linkonce") - 1)) {
2233 /* if a 'linkonce' section is already present, we
2234 do not add it again. It is a little tricky as
2235 symbols can still be defined in
2236 it. */
2237 sm_table[i].link_once = 1;
2238 goto next;
2239 } else {
2240 goto found;
2244 /* not found: create new section */
2245 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2246 /* take as much info as possible from the section. sh_link and
2247 sh_info will be updated later */
2248 s->sh_addralign = sh->sh_addralign;
2249 s->sh_entsize = sh->sh_entsize;
2250 sm_table[i].new_section = 1;
2251 found:
2252 if (sh->sh_type != s->sh_type) {
2253 error_noabort("invalid section type");
2254 goto fail;
2257 /* align start of section */
2258 offset = s->data_offset;
2260 if (0 == strcmp(sh_name, ".stab")) {
2261 stab_index = i;
2262 goto no_align;
2264 if (0 == strcmp(sh_name, ".stabstr")) {
2265 stabstr_index = i;
2266 goto no_align;
2269 size = sh->sh_addralign - 1;
2270 offset = (offset + size) & ~size;
2271 if (sh->sh_addralign > s->sh_addralign)
2272 s->sh_addralign = sh->sh_addralign;
2273 s->data_offset = offset;
2274 no_align:
2275 sm_table[i].offset = offset;
2276 sm_table[i].s = s;
2277 /* concatenate sections */
2278 size = sh->sh_size;
2279 if (sh->sh_type != SHT_NOBITS) {
2280 unsigned char *ptr;
2281 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2282 ptr = section_ptr_add(s, size);
2283 read(fd, ptr, size);
2284 } else {
2285 s->data_offset += size;
2287 next: ;
2290 /* //gr relocate stab strings */
2291 if (stab_index && stabstr_index) {
2292 Stab_Sym *a, *b;
2293 unsigned o;
2294 s = sm_table[stab_index].s;
2295 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2296 b = (Stab_Sym *)(s->data + s->data_offset);
2297 o = sm_table[stabstr_index].offset;
2298 while (a < b)
2299 a->n_strx += o, a++;
2302 /* second short pass to update sh_link and sh_info fields of new
2303 sections */
2304 for(i = 1; i < ehdr.e_shnum; i++) {
2305 s = sm_table[i].s;
2306 if (!s || !sm_table[i].new_section)
2307 continue;
2308 sh = &shdr[i];
2309 if (sh->sh_link > 0)
2310 s->link = sm_table[sh->sh_link].s;
2311 if (sh->sh_type == SHT_RELX) {
2312 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2313 /* update backward link */
2314 s1->sections[s->sh_info]->reloc = s;
2317 sm = sm_table;
2319 /* resolve symbols */
2320 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2322 sym = symtab + 1;
2323 for(i = 1; i < nb_syms; i++, sym++) {
2324 if (sym->st_shndx != SHN_UNDEF &&
2325 sym->st_shndx < SHN_LORESERVE) {
2326 sm = &sm_table[sym->st_shndx];
2327 if (sm->link_once) {
2328 /* if a symbol is in a link once section, we use the
2329 already defined symbol. It is very important to get
2330 correct relocations */
2331 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2332 name = strtab + sym->st_name;
2333 sym_index = find_elf_sym(symtab_section, name);
2334 if (sym_index)
2335 old_to_new_syms[i] = sym_index;
2337 continue;
2339 /* if no corresponding section added, no need to add symbol */
2340 if (!sm->s)
2341 continue;
2342 /* convert section number */
2343 sym->st_shndx = sm->s->sh_num;
2344 /* offset value */
2345 sym->st_value += sm->offset;
2347 /* add symbol */
2348 name = strtab + sym->st_name;
2349 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2350 sym->st_info, sym->st_other,
2351 sym->st_shndx, name);
2352 old_to_new_syms[i] = sym_index;
2355 /* third pass to patch relocation entries */
2356 for(i = 1; i < ehdr.e_shnum; i++) {
2357 s = sm_table[i].s;
2358 if (!s)
2359 continue;
2360 sh = &shdr[i];
2361 offset = sm_table[i].offset;
2362 switch(s->sh_type) {
2363 case SHT_RELX:
2364 /* take relocation offset information */
2365 offseti = sm_table[sh->sh_info].offset;
2366 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2367 for(rel = (ElfW_Rel *)(s->data + offset);
2368 rel < rel_end;
2369 rel++) {
2370 int type;
2371 unsigned sym_index;
2372 /* convert symbol index */
2373 type = ELFW(R_TYPE)(rel->r_info);
2374 sym_index = ELFW(R_SYM)(rel->r_info);
2375 /* NOTE: only one symtab assumed */
2376 if (sym_index >= nb_syms)
2377 goto invalid_reloc;
2378 sym_index = old_to_new_syms[sym_index];
2379 /* ignore link_once in rel section. */
2380 if (!sym_index && !sm->link_once) {
2381 invalid_reloc:
2382 error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2383 i, strsec + sh->sh_name, rel->r_offset);
2384 goto fail;
2386 rel->r_info = ELFW(R_INFO)(sym_index, type);
2387 /* offset the relocation offset */
2388 rel->r_offset += offseti;
2390 break;
2391 default:
2392 break;
2396 ret = 0;
2397 the_end:
2398 tcc_free(symtab);
2399 tcc_free(strtab);
2400 tcc_free(old_to_new_syms);
2401 tcc_free(sm_table);
2402 tcc_free(strsec);
2403 tcc_free(shdr);
2404 return ret;
2407 typedef struct ArchiveHeader {
2408 char ar_name[16]; /* name of this member */
2409 char ar_date[12]; /* file mtime */
2410 char ar_uid[6]; /* owner uid; printed as decimal */
2411 char ar_gid[6]; /* owner gid; printed as decimal */
2412 char ar_mode[8]; /* file mode, printed as octal */
2413 char ar_size[10]; /* file size, printed as decimal */
2414 char ar_fmag[2]; /* should contain ARFMAG */
2415 } ArchiveHeader;
2417 static int get_be32(const uint8_t *b)
2419 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2422 /* load only the objects which resolve undefined symbols */
2423 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2425 int i, bound, nsyms, sym_index, off, ret;
2426 uint8_t *data;
2427 const char *ar_names, *p;
2428 const uint8_t *ar_index;
2429 ElfW(Sym) *sym;
2431 data = tcc_malloc(size);
2432 if (read(fd, data, size) != size)
2433 goto fail;
2434 nsyms = get_be32(data);
2435 ar_index = data + 4;
2436 ar_names = ar_index + nsyms * 4;
2438 do {
2439 bound = 0;
2440 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2441 sym_index = find_elf_sym(symtab_section, p);
2442 if(sym_index) {
2443 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2444 if(sym->st_shndx == SHN_UNDEF) {
2445 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2446 #if 0
2447 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2448 #endif
2449 ++bound;
2450 lseek(fd, off, SEEK_SET);
2451 if(tcc_load_object_file(s1, fd, off) < 0) {
2452 fail:
2453 ret = -1;
2454 goto the_end;
2459 } while(bound);
2460 ret = 0;
2461 the_end:
2462 tcc_free(data);
2463 return ret;
2466 /* load a '.a' file */
2467 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2469 ArchiveHeader hdr;
2470 char ar_size[11];
2471 char ar_name[17];
2472 char magic[8];
2473 int size, len, i;
2474 unsigned long file_offset;
2476 /* skip magic which was already checked */
2477 read(fd, magic, sizeof(magic));
2479 for(;;) {
2480 len = read(fd, &hdr, sizeof(hdr));
2481 if (len == 0)
2482 break;
2483 if (len != sizeof(hdr)) {
2484 error_noabort("invalid archive");
2485 return -1;
2487 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2488 ar_size[sizeof(hdr.ar_size)] = '\0';
2489 size = strtol(ar_size, NULL, 0);
2490 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2491 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2492 if (ar_name[i] != ' ')
2493 break;
2495 ar_name[i + 1] = '\0';
2496 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2497 file_offset = lseek(fd, 0, SEEK_CUR);
2498 /* align to even */
2499 size = (size + 1) & ~1;
2500 if (!strcmp(ar_name, "/")) {
2501 /* coff symbol table : we handle it */
2502 if(s1->alacarte_link)
2503 return tcc_load_alacarte(s1, fd, size);
2504 } else if (!strcmp(ar_name, "//") ||
2505 !strcmp(ar_name, "__.SYMDEF") ||
2506 !strcmp(ar_name, "__.SYMDEF/") ||
2507 !strcmp(ar_name, "ARFILENAMES/")) {
2508 /* skip symbol table or archive names */
2509 } else {
2510 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2511 return -1;
2513 lseek(fd, file_offset + size, SEEK_SET);
2515 return 0;
2518 #ifndef TCC_TARGET_PE
2519 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2520 is referenced by the user (so it should be added as DT_NEEDED in
2521 the generated ELF file) */
2522 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2524 ElfW(Ehdr) ehdr;
2525 ElfW(Shdr) *shdr, *sh, *sh1;
2526 int i, j, nb_syms, nb_dts, sym_bind, ret;
2527 ElfW(Sym) *sym, *dynsym;
2528 ElfW(Dyn) *dt, *dynamic;
2529 unsigned char *dynstr;
2530 const char *name, *soname;
2531 DLLReference *dllref;
2533 read(fd, &ehdr, sizeof(ehdr));
2535 /* test CPU specific stuff */
2536 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2537 ehdr.e_machine != EM_TCC_TARGET) {
2538 error_noabort("bad architecture");
2539 return -1;
2542 /* read sections */
2543 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2545 /* load dynamic section and dynamic symbols */
2546 nb_syms = 0;
2547 nb_dts = 0;
2548 dynamic = NULL;
2549 dynsym = NULL; /* avoid warning */
2550 dynstr = NULL; /* avoid warning */
2551 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2552 switch(sh->sh_type) {
2553 case SHT_DYNAMIC:
2554 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2555 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2556 break;
2557 case SHT_DYNSYM:
2558 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2559 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2560 sh1 = &shdr[sh->sh_link];
2561 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2562 break;
2563 default:
2564 break;
2568 /* compute the real library name */
2569 soname = tcc_basename(filename);
2571 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2572 if (dt->d_tag == DT_SONAME) {
2573 soname = dynstr + dt->d_un.d_val;
2577 /* if the dll is already loaded, do not load it */
2578 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2579 dllref = s1->loaded_dlls[i];
2580 if (!strcmp(soname, dllref->name)) {
2581 /* but update level if needed */
2582 if (level < dllref->level)
2583 dllref->level = level;
2584 ret = 0;
2585 goto the_end;
2589 // printf("loading dll '%s'\n", soname);
2591 /* add the dll and its level */
2592 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2593 dllref->level = level;
2594 strcpy(dllref->name, soname);
2595 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2597 /* add dynamic symbols in dynsym_section */
2598 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2599 sym_bind = ELFW(ST_BIND)(sym->st_info);
2600 if (sym_bind == STB_LOCAL)
2601 continue;
2602 name = dynstr + sym->st_name;
2603 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2604 sym->st_info, sym->st_other, sym->st_shndx, name);
2607 /* load all referenced DLLs */
2608 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2609 switch(dt->d_tag) {
2610 case DT_NEEDED:
2611 name = dynstr + dt->d_un.d_val;
2612 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2613 dllref = s1->loaded_dlls[j];
2614 if (!strcmp(name, dllref->name))
2615 goto already_loaded;
2617 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2618 error_noabort("referenced dll '%s' not found", name);
2619 ret = -1;
2620 goto the_end;
2622 already_loaded:
2623 break;
2626 ret = 0;
2627 the_end:
2628 tcc_free(dynstr);
2629 tcc_free(dynsym);
2630 tcc_free(dynamic);
2631 tcc_free(shdr);
2632 return ret;
2635 #define LD_TOK_NAME 256
2636 #define LD_TOK_EOF (-1)
2638 /* return next ld script token */
2639 static int ld_next(TCCState *s1, char *name, int name_size)
2641 int c;
2642 char *q;
2644 redo:
2645 switch(ch) {
2646 case ' ':
2647 case '\t':
2648 case '\f':
2649 case '\v':
2650 case '\r':
2651 case '\n':
2652 inp();
2653 goto redo;
2654 case '/':
2655 minp();
2656 if (ch == '*') {
2657 file->buf_ptr = parse_comment(file->buf_ptr);
2658 ch = file->buf_ptr[0];
2659 goto redo;
2660 } else {
2661 q = name;
2662 *q++ = '/';
2663 goto parse_name;
2665 break;
2666 /* case 'a' ... 'z': */
2667 case 'a':
2668 case 'b':
2669 case 'c':
2670 case 'd':
2671 case 'e':
2672 case 'f':
2673 case 'g':
2674 case 'h':
2675 case 'i':
2676 case 'j':
2677 case 'k':
2678 case 'l':
2679 case 'm':
2680 case 'n':
2681 case 'o':
2682 case 'p':
2683 case 'q':
2684 case 'r':
2685 case 's':
2686 case 't':
2687 case 'u':
2688 case 'v':
2689 case 'w':
2690 case 'x':
2691 case 'y':
2692 case 'z':
2693 /* case 'A' ... 'z': */
2694 case 'A':
2695 case 'B':
2696 case 'C':
2697 case 'D':
2698 case 'E':
2699 case 'F':
2700 case 'G':
2701 case 'H':
2702 case 'I':
2703 case 'J':
2704 case 'K':
2705 case 'L':
2706 case 'M':
2707 case 'N':
2708 case 'O':
2709 case 'P':
2710 case 'Q':
2711 case 'R':
2712 case 'S':
2713 case 'T':
2714 case 'U':
2715 case 'V':
2716 case 'W':
2717 case 'X':
2718 case 'Y':
2719 case 'Z':
2720 case '_':
2721 case '\\':
2722 case '.':
2723 case '$':
2724 case '~':
2725 q = name;
2726 parse_name:
2727 for(;;) {
2728 if (!((ch >= 'a' && ch <= 'z') ||
2729 (ch >= 'A' && ch <= 'Z') ||
2730 (ch >= '0' && ch <= '9') ||
2731 strchr("/.-_+=$:\\,~", ch)))
2732 break;
2733 if ((q - name) < name_size - 1) {
2734 *q++ = ch;
2736 minp();
2738 *q = '\0';
2739 c = LD_TOK_NAME;
2740 break;
2741 case CH_EOF:
2742 c = LD_TOK_EOF;
2743 break;
2744 default:
2745 c = ch;
2746 inp();
2747 break;
2749 #if 0
2750 printf("tok=%c %d\n", c, c);
2751 if (c == LD_TOK_NAME)
2752 printf(" name=%s\n", name);
2753 #endif
2754 return c;
2757 static int ld_add_file_list(TCCState *s1, int as_needed)
2759 char filename[1024];
2760 int t, ret;
2762 t = ld_next(s1, filename, sizeof(filename));
2763 if (t != '(')
2764 expect("(");
2765 t = ld_next(s1, filename, sizeof(filename));
2766 for(;;) {
2767 if (t == LD_TOK_EOF) {
2768 error_noabort("unexpected end of file");
2769 return -1;
2770 } else if (t == ')') {
2771 break;
2772 } else if (t != LD_TOK_NAME) {
2773 error_noabort("filename expected");
2774 return -1;
2776 if (!strcmp(filename, "AS_NEEDED")) {
2777 ret = ld_add_file_list(s1, 1);
2778 if (ret)
2779 return ret;
2780 } else {
2781 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2782 if (!as_needed)
2783 tcc_add_file(s1, filename);
2785 t = ld_next(s1, filename, sizeof(filename));
2786 if (t == ',') {
2787 t = ld_next(s1, filename, sizeof(filename));
2790 return 0;
2793 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
2794 files */
2795 ST_FUNC int tcc_load_ldscript(TCCState *s1)
2797 char cmd[64];
2798 char filename[1024];
2799 int t, ret;
2801 ch = file->buf_ptr[0];
2802 ch = handle_eob();
2803 for(;;) {
2804 t = ld_next(s1, cmd, sizeof(cmd));
2805 if (t == LD_TOK_EOF)
2806 return 0;
2807 else if (t != LD_TOK_NAME)
2808 return -1;
2809 if (!strcmp(cmd, "INPUT") ||
2810 !strcmp(cmd, "GROUP")) {
2811 ret = ld_add_file_list(s1, 0);
2812 if (ret)
2813 return ret;
2814 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
2815 !strcmp(cmd, "TARGET")) {
2816 /* ignore some commands */
2817 t = ld_next(s1, cmd, sizeof(cmd));
2818 if (t != '(')
2819 expect("(");
2820 for(;;) {
2821 t = ld_next(s1, filename, sizeof(filename));
2822 if (t == LD_TOK_EOF) {
2823 error_noabort("unexpected end of file");
2824 return -1;
2825 } else if (t == ')') {
2826 break;
2829 } else {
2830 return -1;
2833 return 0;
2835 #endif