Add support for --help
[tinycc.git] / tccelf.c
blob2d884d2d81683d233511cc4567c37be94e089b2c
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);
1579 if (s1->symbolic)
1580 put_dt(dynamic, DT_SYMBOLIC, 0);
1582 /* add necessary space for other entries */
1583 saved_dynamic_data_offset = dynamic->data_offset;
1584 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1585 } else {
1586 /* still need to build got entries in case of static link */
1587 build_got_entries(s1);
1591 memset(&ehdr, 0, sizeof(ehdr));
1593 /* we add a section for symbols */
1594 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1595 put_elf_str(strsec, "");
1597 /* compute number of sections */
1598 shnum = s1->nb_sections;
1600 /* this array is used to reorder sections in the output file */
1601 section_order = tcc_malloc(sizeof(int) * shnum);
1602 section_order[0] = 0;
1603 sh_order_index = 1;
1605 /* compute number of program headers */
1606 switch(file_type) {
1607 default:
1608 case TCC_OUTPUT_OBJ:
1609 phnum = 0;
1610 break;
1611 case TCC_OUTPUT_EXE:
1612 if (!s1->static_link)
1613 phnum = 4 + HAVE_PHDR;
1614 else
1615 phnum = 2;
1616 break;
1617 case TCC_OUTPUT_DLL:
1618 phnum = 3;
1619 break;
1622 /* allocate strings for section names and decide if an unallocated
1623 section should be output */
1624 /* NOTE: the strsec section comes last, so its size is also
1625 correct ! */
1626 for(i = 1; i < s1->nb_sections; i++) {
1627 s = s1->sections[i];
1628 s->sh_name = put_elf_str(strsec, s->name);
1629 #if 0 //gr
1630 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1631 s->sh_flags,
1632 s->sh_type,
1633 s->sh_info,
1634 s->name,
1635 s->reloc ? s->reloc->name : "n"
1637 #endif
1638 /* when generating a DLL, we include relocations but we may
1639 patch them */
1640 if (file_type == TCC_OUTPUT_DLL &&
1641 s->sh_type == SHT_RELX &&
1642 !(s->sh_flags & SHF_ALLOC)) {
1643 /* //gr: avoid bogus relocs for empty (debug) sections */
1644 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1645 prepare_dynamic_rel(s1, s);
1646 else if (s1->do_debug)
1647 s->sh_size = s->data_offset;
1648 } else if (s1->do_debug ||
1649 file_type == TCC_OUTPUT_OBJ ||
1650 (s->sh_flags & SHF_ALLOC) ||
1651 i == (s1->nb_sections - 1)) {
1652 /* we output all sections if debug or object file */
1653 s->sh_size = s->data_offset;
1657 /* allocate program segment headers */
1658 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1660 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1661 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1662 } else {
1663 file_offset = 0;
1665 if (phnum > 0) {
1666 /* compute section to program header mapping */
1667 if (s1->has_text_addr) {
1668 int a_offset, p_offset;
1669 addr = s1->text_addr;
1670 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1671 ELF_PAGE_SIZE */
1672 a_offset = addr & (s1->section_align - 1);
1673 p_offset = file_offset & (s1->section_align - 1);
1674 if (a_offset < p_offset)
1675 a_offset += s1->section_align;
1676 file_offset += (a_offset - p_offset);
1677 } else {
1678 if (file_type == TCC_OUTPUT_DLL)
1679 addr = 0;
1680 else
1681 addr = ELF_START_ADDR;
1682 /* compute address after headers */
1683 addr += (file_offset & (s1->section_align - 1));
1686 /* dynamic relocation table information, for .dynamic section */
1687 rel_size = 0;
1688 rel_addr = 0;
1690 bss_addr = bss_size = 0;
1691 /* leave one program header for the program interpreter */
1692 ph = &phdr[0];
1693 if (interp)
1694 ph += 1 + HAVE_PHDR;
1696 for(j = 0; j < 2; j++) {
1697 ph->p_type = PT_LOAD;
1698 if (j == 0)
1699 ph->p_flags = PF_R | PF_X;
1700 else
1701 ph->p_flags = PF_R | PF_W;
1702 ph->p_align = s1->section_align;
1704 /* we do the following ordering: interp, symbol tables,
1705 relocations, progbits, nobits */
1706 /* XXX: do faster and simpler sorting */
1707 for(k = 0; k < 5; k++) {
1708 for(i = 1; i < s1->nb_sections; i++) {
1709 s = s1->sections[i];
1710 /* compute if section should be included */
1711 if (j == 0) {
1712 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1713 SHF_ALLOC)
1714 continue;
1715 } else {
1716 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1717 (SHF_ALLOC | SHF_WRITE))
1718 continue;
1720 if (s == interp) {
1721 if (k != 0)
1722 continue;
1723 } else if (s->sh_type == SHT_DYNSYM ||
1724 s->sh_type == SHT_STRTAB ||
1725 s->sh_type == SHT_HASH) {
1726 if (k != 1)
1727 continue;
1728 } else if (s->sh_type == SHT_RELX) {
1729 if (k != 2)
1730 continue;
1731 } else if (s->sh_type == SHT_NOBITS) {
1732 if (k != 4)
1733 continue;
1734 } else {
1735 if (k != 3)
1736 continue;
1738 section_order[sh_order_index++] = i;
1740 /* section matches: we align it and add its size */
1741 tmp = addr;
1742 addr = (addr + s->sh_addralign - 1) &
1743 ~(s->sh_addralign - 1);
1744 file_offset += addr - tmp;
1745 s->sh_offset = file_offset;
1746 s->sh_addr = addr;
1748 /* update program header infos */
1749 if (ph->p_offset == 0) {
1750 ph->p_offset = file_offset;
1751 ph->p_vaddr = addr;
1752 ph->p_paddr = ph->p_vaddr;
1754 /* update dynamic relocation infos */
1755 if (s->sh_type == SHT_RELX) {
1756 #if defined(__FreeBSD__)
1757 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1758 rel_addr = addr;
1759 rel_size += s->sh_size; // XXX only first rel.
1761 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1762 bss_addr = addr;
1763 bss_size = s->sh_size; // XXX only first rel.
1765 #else
1766 if (rel_size == 0)
1767 rel_addr = addr;
1768 rel_size += s->sh_size;
1769 #endif
1771 addr += s->sh_size;
1772 if (s->sh_type != SHT_NOBITS)
1773 file_offset += s->sh_size;
1776 ph->p_filesz = file_offset - ph->p_offset;
1777 ph->p_memsz = addr - ph->p_vaddr;
1778 ph++;
1779 if (j == 0) {
1780 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1781 /* if in the middle of a page, we duplicate the page in
1782 memory so that one copy is RX and the other is RW */
1783 if ((addr & (s1->section_align - 1)) != 0)
1784 addr += s1->section_align;
1785 } else {
1786 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1787 file_offset = (file_offset + s1->section_align - 1) &
1788 ~(s1->section_align - 1);
1793 /* if interpreter, then add corresponing program header */
1794 if (interp) {
1795 ph = &phdr[0];
1797 #if defined(__FreeBSD__)
1799 int len = phnum * sizeof(ElfW(Phdr));
1801 ph->p_type = PT_PHDR;
1802 ph->p_offset = sizeof(ElfW(Ehdr));
1803 ph->p_vaddr = interp->sh_addr - len;
1804 ph->p_paddr = ph->p_vaddr;
1805 ph->p_filesz = ph->p_memsz = len;
1806 ph->p_flags = PF_R | PF_X;
1807 ph->p_align = 4; // interp->sh_addralign;
1808 ph++;
1810 #endif
1812 ph->p_type = PT_INTERP;
1813 ph->p_offset = interp->sh_offset;
1814 ph->p_vaddr = interp->sh_addr;
1815 ph->p_paddr = ph->p_vaddr;
1816 ph->p_filesz = interp->sh_size;
1817 ph->p_memsz = interp->sh_size;
1818 ph->p_flags = PF_R;
1819 ph->p_align = interp->sh_addralign;
1822 /* if dynamic section, then add corresponing program header */
1823 if (dynamic) {
1824 ElfW(Sym) *sym_end;
1826 ph = &phdr[phnum - 1];
1828 ph->p_type = PT_DYNAMIC;
1829 ph->p_offset = dynamic->sh_offset;
1830 ph->p_vaddr = dynamic->sh_addr;
1831 ph->p_paddr = ph->p_vaddr;
1832 ph->p_filesz = dynamic->sh_size;
1833 ph->p_memsz = dynamic->sh_size;
1834 ph->p_flags = PF_R | PF_W;
1835 ph->p_align = dynamic->sh_addralign;
1837 /* put GOT dynamic section address */
1838 put32(s1->got->data, dynamic->sh_addr);
1840 /* relocate the PLT */
1841 if (file_type == TCC_OUTPUT_EXE
1842 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1843 || file_type == TCC_OUTPUT_DLL
1844 #endif
1846 uint8_t *p, *p_end;
1848 p = s1->plt->data;
1849 p_end = p + s1->plt->data_offset;
1850 if (p < p_end) {
1851 #if defined(TCC_TARGET_I386)
1852 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1853 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1854 p += 16;
1855 while (p < p_end) {
1856 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1857 p += 16;
1859 #elif defined(TCC_TARGET_X86_64)
1860 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1861 put32(p + 2, get32(p + 2) + x);
1862 put32(p + 8, get32(p + 8) + x - 6);
1863 p += 16;
1864 while (p < p_end) {
1865 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1866 p += 16;
1868 #elif defined(TCC_TARGET_ARM)
1869 int x;
1870 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1871 p +=16;
1872 while (p < p_end) {
1873 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1874 p += 16;
1876 #elif defined(TCC_TARGET_C67)
1877 /* XXX: TODO */
1878 #else
1879 #error unsupported CPU
1880 #endif
1884 /* relocate symbols in .dynsym */
1885 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
1886 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
1887 sym < sym_end;
1888 sym++) {
1889 if (sym->st_shndx == SHN_UNDEF) {
1890 /* relocate to the PLT if the symbol corresponds
1891 to a PLT entry */
1892 if (sym->st_value)
1893 sym->st_value += s1->plt->sh_addr;
1894 } else if (sym->st_shndx < SHN_LORESERVE) {
1895 /* do symbol relocation */
1896 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
1900 /* put dynamic section entries */
1901 dynamic->data_offset = saved_dynamic_data_offset;
1902 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
1903 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
1904 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
1905 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
1906 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
1907 #ifdef TCC_TARGET_X86_64
1908 put_dt(dynamic, DT_RELA, rel_addr);
1909 put_dt(dynamic, DT_RELASZ, rel_size);
1910 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
1911 #else
1912 #if defined(__FreeBSD__)
1913 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
1914 put_dt(dynamic, DT_PLTRELSZ, rel_size);
1915 put_dt(dynamic, DT_JMPREL, rel_addr);
1916 put_dt(dynamic, DT_PLTREL, DT_REL);
1917 put_dt(dynamic, DT_REL, bss_addr);
1918 put_dt(dynamic, DT_RELSZ, bss_size);
1919 #else
1920 put_dt(dynamic, DT_REL, rel_addr);
1921 put_dt(dynamic, DT_RELSZ, rel_size);
1922 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
1923 #endif
1924 #endif
1925 if (s1->do_debug)
1926 put_dt(dynamic, DT_DEBUG, 0);
1927 put_dt(dynamic, DT_NULL, 0);
1930 ehdr.e_phentsize = sizeof(ElfW(Phdr));
1931 ehdr.e_phnum = phnum;
1932 ehdr.e_phoff = sizeof(ElfW(Ehdr));
1935 /* all other sections come after */
1936 for(i = 1; i < s1->nb_sections; i++) {
1937 s = s1->sections[i];
1938 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
1939 continue;
1940 section_order[sh_order_index++] = i;
1942 file_offset = (file_offset + s->sh_addralign - 1) &
1943 ~(s->sh_addralign - 1);
1944 s->sh_offset = file_offset;
1945 if (s->sh_type != SHT_NOBITS)
1946 file_offset += s->sh_size;
1949 /* if building executable or DLL, then relocate each section
1950 except the GOT which is already relocated */
1951 if (file_type != TCC_OUTPUT_OBJ) {
1952 relocate_syms(s1, 0);
1954 if (s1->nb_errors != 0) {
1955 fail:
1956 ret = -1;
1957 goto the_end;
1960 /* relocate sections */
1961 /* XXX: ignore sections with allocated relocations ? */
1962 for(i = 1; i < s1->nb_sections; i++) {
1963 s = s1->sections[i];
1964 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
1965 relocate_section(s1, s);
1968 /* relocate relocation entries if the relocation tables are
1969 allocated in the executable */
1970 for(i = 1; i < s1->nb_sections; i++) {
1971 s = s1->sections[i];
1972 if ((s->sh_flags & SHF_ALLOC) &&
1973 s->sh_type == SHT_RELX) {
1974 relocate_rel(s1, s);
1978 /* get entry point address */
1979 if (file_type == TCC_OUTPUT_EXE)
1980 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
1981 else
1982 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
1985 /* write elf file */
1986 if (file_type == TCC_OUTPUT_OBJ)
1987 mode = 0666;
1988 else
1989 mode = 0777;
1990 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
1991 if (fd < 0) {
1992 error_noabort("could not write '%s'", filename);
1993 goto fail;
1995 f = fdopen(fd, "wb");
1996 if (s1->verbose)
1997 printf("<- %s\n", filename);
1999 #ifdef TCC_TARGET_COFF
2000 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2001 tcc_output_coff(s1, f);
2002 } else
2003 #endif
2004 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2005 sort_syms(s1, symtab_section);
2007 /* align to 4 */
2008 file_offset = (file_offset + 3) & -4;
2010 /* fill header */
2011 ehdr.e_ident[0] = ELFMAG0;
2012 ehdr.e_ident[1] = ELFMAG1;
2013 ehdr.e_ident[2] = ELFMAG2;
2014 ehdr.e_ident[3] = ELFMAG3;
2015 ehdr.e_ident[4] = TCC_ELFCLASS;
2016 ehdr.e_ident[5] = ELFDATA2LSB;
2017 ehdr.e_ident[6] = EV_CURRENT;
2018 #ifdef __FreeBSD__
2019 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2020 #endif
2021 #ifdef TCC_TARGET_ARM
2022 #ifdef TCC_ARM_EABI
2023 ehdr.e_ident[EI_OSABI] = 0;
2024 ehdr.e_flags = 4 << 24;
2025 #else
2026 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2027 #endif
2028 #endif
2029 switch(file_type) {
2030 default:
2031 case TCC_OUTPUT_EXE:
2032 ehdr.e_type = ET_EXEC;
2033 break;
2034 case TCC_OUTPUT_DLL:
2035 ehdr.e_type = ET_DYN;
2036 break;
2037 case TCC_OUTPUT_OBJ:
2038 ehdr.e_type = ET_REL;
2039 break;
2041 ehdr.e_machine = EM_TCC_TARGET;
2042 ehdr.e_version = EV_CURRENT;
2043 ehdr.e_shoff = file_offset;
2044 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2045 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2046 ehdr.e_shnum = shnum;
2047 ehdr.e_shstrndx = shnum - 1;
2049 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2050 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2051 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2053 for(i=1;i<s1->nb_sections;i++) {
2054 s = s1->sections[section_order[i]];
2055 if (s->sh_type != SHT_NOBITS) {
2056 #if defined(__FreeBSD__)
2057 if (s->sh_type == SHT_DYNSYM)
2058 patch_dynsym_undef(s1, s);
2059 #endif
2060 while (offset < s->sh_offset) {
2061 fputc(0, f);
2062 offset++;
2064 size = s->sh_size;
2065 fwrite(s->data, 1, size, f);
2066 offset += size;
2070 /* output section headers */
2071 while (offset < ehdr.e_shoff) {
2072 fputc(0, f);
2073 offset++;
2076 for(i=0;i<s1->nb_sections;i++) {
2077 sh = &shdr;
2078 memset(sh, 0, sizeof(ElfW(Shdr)));
2079 s = s1->sections[i];
2080 if (s) {
2081 sh->sh_name = s->sh_name;
2082 sh->sh_type = s->sh_type;
2083 sh->sh_flags = s->sh_flags;
2084 sh->sh_entsize = s->sh_entsize;
2085 sh->sh_info = s->sh_info;
2086 if (s->link)
2087 sh->sh_link = s->link->sh_num;
2088 sh->sh_addralign = s->sh_addralign;
2089 sh->sh_addr = s->sh_addr;
2090 sh->sh_offset = s->sh_offset;
2091 sh->sh_size = s->sh_size;
2093 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2095 } else {
2096 tcc_output_binary(s1, f, section_order);
2098 fclose(f);
2100 ret = 0;
2101 the_end:
2102 tcc_free(s1->symtab_to_dynsym);
2103 tcc_free(section_order);
2104 tcc_free(phdr);
2105 tcc_free(s1->got_offsets);
2106 return ret;
2109 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2111 int ret;
2112 #ifdef TCC_TARGET_PE
2113 if (s->output_type != TCC_OUTPUT_OBJ) {
2114 ret = pe_output_file(s, filename);
2115 } else
2116 #endif
2118 ret = elf_output_file(s, filename);
2120 return ret;
2123 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2125 void *data;
2127 data = tcc_malloc(size);
2128 lseek(fd, file_offset, SEEK_SET);
2129 read(fd, data, size);
2130 return data;
2133 typedef struct SectionMergeInfo {
2134 Section *s; /* corresponding existing section */
2135 unsigned long offset; /* offset of the new section in the existing section */
2136 uint8_t new_section; /* true if section 's' was added */
2137 uint8_t link_once; /* true if link once section */
2138 } SectionMergeInfo;
2140 /* load an object file and merge it with current files */
2141 /* XXX: handle correctly stab (debug) info */
2142 ST_FUNC int tcc_load_object_file(TCCState *s1,
2143 int fd, unsigned long file_offset)
2145 ElfW(Ehdr) ehdr;
2146 ElfW(Shdr) *shdr, *sh;
2147 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2148 unsigned char *strsec, *strtab;
2149 int *old_to_new_syms;
2150 char *sh_name, *name;
2151 SectionMergeInfo *sm_table, *sm;
2152 ElfW(Sym) *sym, *symtab;
2153 ElfW_Rel *rel, *rel_end;
2154 Section *s;
2156 int stab_index;
2157 int stabstr_index;
2159 stab_index = stabstr_index = 0;
2161 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2162 goto fail1;
2163 if (ehdr.e_ident[0] != ELFMAG0 ||
2164 ehdr.e_ident[1] != ELFMAG1 ||
2165 ehdr.e_ident[2] != ELFMAG2 ||
2166 ehdr.e_ident[3] != ELFMAG3)
2167 goto fail1;
2168 /* test if object file */
2169 if (ehdr.e_type != ET_REL)
2170 goto fail1;
2171 /* test CPU specific stuff */
2172 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2173 ehdr.e_machine != EM_TCC_TARGET) {
2174 fail1:
2175 error_noabort("invalid object file");
2176 return -1;
2178 /* read sections */
2179 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2180 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2181 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2183 /* load section names */
2184 sh = &shdr[ehdr.e_shstrndx];
2185 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2187 /* load symtab and strtab */
2188 old_to_new_syms = NULL;
2189 symtab = NULL;
2190 strtab = NULL;
2191 nb_syms = 0;
2192 for(i = 1; i < ehdr.e_shnum; i++) {
2193 sh = &shdr[i];
2194 if (sh->sh_type == SHT_SYMTAB) {
2195 if (symtab) {
2196 error_noabort("object must contain only one symtab");
2197 fail:
2198 ret = -1;
2199 goto the_end;
2201 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2202 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2203 sm_table[i].s = symtab_section;
2205 /* now load strtab */
2206 sh = &shdr[sh->sh_link];
2207 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2211 /* now examine each section and try to merge its content with the
2212 ones in memory */
2213 for(i = 1; i < ehdr.e_shnum; i++) {
2214 /* no need to examine section name strtab */
2215 if (i == ehdr.e_shstrndx)
2216 continue;
2217 sh = &shdr[i];
2218 sh_name = strsec + sh->sh_name;
2219 /* ignore sections types we do not handle */
2220 if (sh->sh_type != SHT_PROGBITS &&
2221 sh->sh_type != SHT_RELX &&
2222 #ifdef TCC_ARM_EABI
2223 sh->sh_type != SHT_ARM_EXIDX &&
2224 #endif
2225 sh->sh_type != SHT_NOBITS &&
2226 strcmp(sh_name, ".stabstr")
2228 continue;
2229 if (sh->sh_addralign < 1)
2230 sh->sh_addralign = 1;
2231 /* find corresponding section, if any */
2232 for(j = 1; j < s1->nb_sections;j++) {
2233 s = s1->sections[j];
2234 if (!strcmp(s->name, sh_name)) {
2235 if (!strncmp(sh_name, ".gnu.linkonce",
2236 sizeof(".gnu.linkonce") - 1)) {
2237 /* if a 'linkonce' section is already present, we
2238 do not add it again. It is a little tricky as
2239 symbols can still be defined in
2240 it. */
2241 sm_table[i].link_once = 1;
2242 goto next;
2243 } else {
2244 goto found;
2248 /* not found: create new section */
2249 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2250 /* take as much info as possible from the section. sh_link and
2251 sh_info will be updated later */
2252 s->sh_addralign = sh->sh_addralign;
2253 s->sh_entsize = sh->sh_entsize;
2254 sm_table[i].new_section = 1;
2255 found:
2256 if (sh->sh_type != s->sh_type) {
2257 error_noabort("invalid section type");
2258 goto fail;
2261 /* align start of section */
2262 offset = s->data_offset;
2264 if (0 == strcmp(sh_name, ".stab")) {
2265 stab_index = i;
2266 goto no_align;
2268 if (0 == strcmp(sh_name, ".stabstr")) {
2269 stabstr_index = i;
2270 goto no_align;
2273 size = sh->sh_addralign - 1;
2274 offset = (offset + size) & ~size;
2275 if (sh->sh_addralign > s->sh_addralign)
2276 s->sh_addralign = sh->sh_addralign;
2277 s->data_offset = offset;
2278 no_align:
2279 sm_table[i].offset = offset;
2280 sm_table[i].s = s;
2281 /* concatenate sections */
2282 size = sh->sh_size;
2283 if (sh->sh_type != SHT_NOBITS) {
2284 unsigned char *ptr;
2285 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2286 ptr = section_ptr_add(s, size);
2287 read(fd, ptr, size);
2288 } else {
2289 s->data_offset += size;
2291 next: ;
2294 /* //gr relocate stab strings */
2295 if (stab_index && stabstr_index) {
2296 Stab_Sym *a, *b;
2297 unsigned o;
2298 s = sm_table[stab_index].s;
2299 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2300 b = (Stab_Sym *)(s->data + s->data_offset);
2301 o = sm_table[stabstr_index].offset;
2302 while (a < b)
2303 a->n_strx += o, a++;
2306 /* second short pass to update sh_link and sh_info fields of new
2307 sections */
2308 for(i = 1; i < ehdr.e_shnum; i++) {
2309 s = sm_table[i].s;
2310 if (!s || !sm_table[i].new_section)
2311 continue;
2312 sh = &shdr[i];
2313 if (sh->sh_link > 0)
2314 s->link = sm_table[sh->sh_link].s;
2315 if (sh->sh_type == SHT_RELX) {
2316 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2317 /* update backward link */
2318 s1->sections[s->sh_info]->reloc = s;
2321 sm = sm_table;
2323 /* resolve symbols */
2324 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2326 sym = symtab + 1;
2327 for(i = 1; i < nb_syms; i++, sym++) {
2328 if (sym->st_shndx != SHN_UNDEF &&
2329 sym->st_shndx < SHN_LORESERVE) {
2330 sm = &sm_table[sym->st_shndx];
2331 if (sm->link_once) {
2332 /* if a symbol is in a link once section, we use the
2333 already defined symbol. It is very important to get
2334 correct relocations */
2335 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2336 name = strtab + sym->st_name;
2337 sym_index = find_elf_sym(symtab_section, name);
2338 if (sym_index)
2339 old_to_new_syms[i] = sym_index;
2341 continue;
2343 /* if no corresponding section added, no need to add symbol */
2344 if (!sm->s)
2345 continue;
2346 /* convert section number */
2347 sym->st_shndx = sm->s->sh_num;
2348 /* offset value */
2349 sym->st_value += sm->offset;
2351 /* add symbol */
2352 name = strtab + sym->st_name;
2353 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2354 sym->st_info, sym->st_other,
2355 sym->st_shndx, name);
2356 old_to_new_syms[i] = sym_index;
2359 /* third pass to patch relocation entries */
2360 for(i = 1; i < ehdr.e_shnum; i++) {
2361 s = sm_table[i].s;
2362 if (!s)
2363 continue;
2364 sh = &shdr[i];
2365 offset = sm_table[i].offset;
2366 switch(s->sh_type) {
2367 case SHT_RELX:
2368 /* take relocation offset information */
2369 offseti = sm_table[sh->sh_info].offset;
2370 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2371 for(rel = (ElfW_Rel *)(s->data + offset);
2372 rel < rel_end;
2373 rel++) {
2374 int type;
2375 unsigned sym_index;
2376 /* convert symbol index */
2377 type = ELFW(R_TYPE)(rel->r_info);
2378 sym_index = ELFW(R_SYM)(rel->r_info);
2379 /* NOTE: only one symtab assumed */
2380 if (sym_index >= nb_syms)
2381 goto invalid_reloc;
2382 sym_index = old_to_new_syms[sym_index];
2383 /* ignore link_once in rel section. */
2384 if (!sym_index && !sm->link_once) {
2385 invalid_reloc:
2386 error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2387 i, strsec + sh->sh_name, rel->r_offset);
2388 goto fail;
2390 rel->r_info = ELFW(R_INFO)(sym_index, type);
2391 /* offset the relocation offset */
2392 rel->r_offset += offseti;
2394 break;
2395 default:
2396 break;
2400 ret = 0;
2401 the_end:
2402 tcc_free(symtab);
2403 tcc_free(strtab);
2404 tcc_free(old_to_new_syms);
2405 tcc_free(sm_table);
2406 tcc_free(strsec);
2407 tcc_free(shdr);
2408 return ret;
2411 typedef struct ArchiveHeader {
2412 char ar_name[16]; /* name of this member */
2413 char ar_date[12]; /* file mtime */
2414 char ar_uid[6]; /* owner uid; printed as decimal */
2415 char ar_gid[6]; /* owner gid; printed as decimal */
2416 char ar_mode[8]; /* file mode, printed as octal */
2417 char ar_size[10]; /* file size, printed as decimal */
2418 char ar_fmag[2]; /* should contain ARFMAG */
2419 } ArchiveHeader;
2421 static int get_be32(const uint8_t *b)
2423 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2426 /* load only the objects which resolve undefined symbols */
2427 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2429 int i, bound, nsyms, sym_index, off, ret;
2430 uint8_t *data;
2431 const char *ar_names, *p;
2432 const uint8_t *ar_index;
2433 ElfW(Sym) *sym;
2435 data = tcc_malloc(size);
2436 if (read(fd, data, size) != size)
2437 goto fail;
2438 nsyms = get_be32(data);
2439 ar_index = data + 4;
2440 ar_names = ar_index + nsyms * 4;
2442 do {
2443 bound = 0;
2444 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2445 sym_index = find_elf_sym(symtab_section, p);
2446 if(sym_index) {
2447 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2448 if(sym->st_shndx == SHN_UNDEF) {
2449 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2450 #if 0
2451 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2452 #endif
2453 ++bound;
2454 lseek(fd, off, SEEK_SET);
2455 if(tcc_load_object_file(s1, fd, off) < 0) {
2456 fail:
2457 ret = -1;
2458 goto the_end;
2463 } while(bound);
2464 ret = 0;
2465 the_end:
2466 tcc_free(data);
2467 return ret;
2470 /* load a '.a' file */
2471 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2473 ArchiveHeader hdr;
2474 char ar_size[11];
2475 char ar_name[17];
2476 char magic[8];
2477 int size, len, i;
2478 unsigned long file_offset;
2480 /* skip magic which was already checked */
2481 read(fd, magic, sizeof(magic));
2483 for(;;) {
2484 len = read(fd, &hdr, sizeof(hdr));
2485 if (len == 0)
2486 break;
2487 if (len != sizeof(hdr)) {
2488 error_noabort("invalid archive");
2489 return -1;
2491 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2492 ar_size[sizeof(hdr.ar_size)] = '\0';
2493 size = strtol(ar_size, NULL, 0);
2494 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2495 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2496 if (ar_name[i] != ' ')
2497 break;
2499 ar_name[i + 1] = '\0';
2500 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2501 file_offset = lseek(fd, 0, SEEK_CUR);
2502 /* align to even */
2503 size = (size + 1) & ~1;
2504 if (!strcmp(ar_name, "/")) {
2505 /* coff symbol table : we handle it */
2506 if(s1->alacarte_link)
2507 return tcc_load_alacarte(s1, fd, size);
2508 } else if (!strcmp(ar_name, "//") ||
2509 !strcmp(ar_name, "__.SYMDEF") ||
2510 !strcmp(ar_name, "__.SYMDEF/") ||
2511 !strcmp(ar_name, "ARFILENAMES/")) {
2512 /* skip symbol table or archive names */
2513 } else {
2514 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2515 return -1;
2517 lseek(fd, file_offset + size, SEEK_SET);
2519 return 0;
2522 #ifndef TCC_TARGET_PE
2523 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2524 is referenced by the user (so it should be added as DT_NEEDED in
2525 the generated ELF file) */
2526 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2528 ElfW(Ehdr) ehdr;
2529 ElfW(Shdr) *shdr, *sh, *sh1;
2530 int i, j, nb_syms, nb_dts, sym_bind, ret;
2531 ElfW(Sym) *sym, *dynsym;
2532 ElfW(Dyn) *dt, *dynamic;
2533 unsigned char *dynstr;
2534 const char *name, *soname;
2535 DLLReference *dllref;
2537 read(fd, &ehdr, sizeof(ehdr));
2539 /* test CPU specific stuff */
2540 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2541 ehdr.e_machine != EM_TCC_TARGET) {
2542 error_noabort("bad architecture");
2543 return -1;
2546 /* read sections */
2547 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2549 /* load dynamic section and dynamic symbols */
2550 nb_syms = 0;
2551 nb_dts = 0;
2552 dynamic = NULL;
2553 dynsym = NULL; /* avoid warning */
2554 dynstr = NULL; /* avoid warning */
2555 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2556 switch(sh->sh_type) {
2557 case SHT_DYNAMIC:
2558 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2559 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2560 break;
2561 case SHT_DYNSYM:
2562 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2563 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2564 sh1 = &shdr[sh->sh_link];
2565 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2566 break;
2567 default:
2568 break;
2572 /* compute the real library name */
2573 soname = tcc_basename(filename);
2575 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2576 if (dt->d_tag == DT_SONAME) {
2577 soname = dynstr + dt->d_un.d_val;
2581 /* if the dll is already loaded, do not load it */
2582 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2583 dllref = s1->loaded_dlls[i];
2584 if (!strcmp(soname, dllref->name)) {
2585 /* but update level if needed */
2586 if (level < dllref->level)
2587 dllref->level = level;
2588 ret = 0;
2589 goto the_end;
2593 // printf("loading dll '%s'\n", soname);
2595 /* add the dll and its level */
2596 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2597 dllref->level = level;
2598 strcpy(dllref->name, soname);
2599 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2601 /* add dynamic symbols in dynsym_section */
2602 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2603 sym_bind = ELFW(ST_BIND)(sym->st_info);
2604 if (sym_bind == STB_LOCAL)
2605 continue;
2606 name = dynstr + sym->st_name;
2607 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2608 sym->st_info, sym->st_other, sym->st_shndx, name);
2611 /* load all referenced DLLs */
2612 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2613 switch(dt->d_tag) {
2614 case DT_NEEDED:
2615 name = dynstr + dt->d_un.d_val;
2616 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2617 dllref = s1->loaded_dlls[j];
2618 if (!strcmp(name, dllref->name))
2619 goto already_loaded;
2621 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2622 error_noabort("referenced dll '%s' not found", name);
2623 ret = -1;
2624 goto the_end;
2626 already_loaded:
2627 break;
2630 ret = 0;
2631 the_end:
2632 tcc_free(dynstr);
2633 tcc_free(dynsym);
2634 tcc_free(dynamic);
2635 tcc_free(shdr);
2636 return ret;
2639 #define LD_TOK_NAME 256
2640 #define LD_TOK_EOF (-1)
2642 /* return next ld script token */
2643 static int ld_next(TCCState *s1, char *name, int name_size)
2645 int c;
2646 char *q;
2648 redo:
2649 switch(ch) {
2650 case ' ':
2651 case '\t':
2652 case '\f':
2653 case '\v':
2654 case '\r':
2655 case '\n':
2656 inp();
2657 goto redo;
2658 case '/':
2659 minp();
2660 if (ch == '*') {
2661 file->buf_ptr = parse_comment(file->buf_ptr);
2662 ch = file->buf_ptr[0];
2663 goto redo;
2664 } else {
2665 q = name;
2666 *q++ = '/';
2667 goto parse_name;
2669 break;
2670 /* case 'a' ... 'z': */
2671 case 'a':
2672 case 'b':
2673 case 'c':
2674 case 'd':
2675 case 'e':
2676 case 'f':
2677 case 'g':
2678 case 'h':
2679 case 'i':
2680 case 'j':
2681 case 'k':
2682 case 'l':
2683 case 'm':
2684 case 'n':
2685 case 'o':
2686 case 'p':
2687 case 'q':
2688 case 'r':
2689 case 's':
2690 case 't':
2691 case 'u':
2692 case 'v':
2693 case 'w':
2694 case 'x':
2695 case 'y':
2696 case 'z':
2697 /* case 'A' ... 'z': */
2698 case 'A':
2699 case 'B':
2700 case 'C':
2701 case 'D':
2702 case 'E':
2703 case 'F':
2704 case 'G':
2705 case 'H':
2706 case 'I':
2707 case 'J':
2708 case 'K':
2709 case 'L':
2710 case 'M':
2711 case 'N':
2712 case 'O':
2713 case 'P':
2714 case 'Q':
2715 case 'R':
2716 case 'S':
2717 case 'T':
2718 case 'U':
2719 case 'V':
2720 case 'W':
2721 case 'X':
2722 case 'Y':
2723 case 'Z':
2724 case '_':
2725 case '\\':
2726 case '.':
2727 case '$':
2728 case '~':
2729 q = name;
2730 parse_name:
2731 for(;;) {
2732 if (!((ch >= 'a' && ch <= 'z') ||
2733 (ch >= 'A' && ch <= 'Z') ||
2734 (ch >= '0' && ch <= '9') ||
2735 strchr("/.-_+=$:\\,~", ch)))
2736 break;
2737 if ((q - name) < name_size - 1) {
2738 *q++ = ch;
2740 minp();
2742 *q = '\0';
2743 c = LD_TOK_NAME;
2744 break;
2745 case CH_EOF:
2746 c = LD_TOK_EOF;
2747 break;
2748 default:
2749 c = ch;
2750 inp();
2751 break;
2753 #if 0
2754 printf("tok=%c %d\n", c, c);
2755 if (c == LD_TOK_NAME)
2756 printf(" name=%s\n", name);
2757 #endif
2758 return c;
2761 static int ld_add_file_list(TCCState *s1, int as_needed)
2763 char filename[1024];
2764 int t, ret;
2766 t = ld_next(s1, filename, sizeof(filename));
2767 if (t != '(')
2768 expect("(");
2769 t = ld_next(s1, filename, sizeof(filename));
2770 for(;;) {
2771 if (t == LD_TOK_EOF) {
2772 error_noabort("unexpected end of file");
2773 return -1;
2774 } else if (t == ')') {
2775 break;
2776 } else if (t != LD_TOK_NAME) {
2777 error_noabort("filename expected");
2778 return -1;
2780 if (!strcmp(filename, "AS_NEEDED")) {
2781 ret = ld_add_file_list(s1, 1);
2782 if (ret)
2783 return ret;
2784 } else {
2785 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2786 if (!as_needed)
2787 tcc_add_file(s1, filename);
2789 t = ld_next(s1, filename, sizeof(filename));
2790 if (t == ',') {
2791 t = ld_next(s1, filename, sizeof(filename));
2794 return 0;
2797 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
2798 files */
2799 ST_FUNC int tcc_load_ldscript(TCCState *s1)
2801 char cmd[64];
2802 char filename[1024];
2803 int t, ret;
2805 ch = file->buf_ptr[0];
2806 ch = handle_eob();
2807 for(;;) {
2808 t = ld_next(s1, cmd, sizeof(cmd));
2809 if (t == LD_TOK_EOF)
2810 return 0;
2811 else if (t != LD_TOK_NAME)
2812 return -1;
2813 if (!strcmp(cmd, "INPUT") ||
2814 !strcmp(cmd, "GROUP")) {
2815 ret = ld_add_file_list(s1, 0);
2816 if (ret)
2817 return ret;
2818 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
2819 !strcmp(cmd, "TARGET")) {
2820 /* ignore some commands */
2821 t = ld_next(s1, cmd, sizeof(cmd));
2822 if (t != '(')
2823 expect("(");
2824 for(;;) {
2825 t = ld_next(s1, filename, sizeof(filename));
2826 if (t == LD_TOK_EOF) {
2827 error_noabort("unexpected end of file");
2828 return -1;
2829 } else if (t == ')') {
2830 break;
2833 } else {
2834 return -1;
2837 return 0;
2839 #endif