x86-64: use r8/r9 as generic integer registers
[tinycc.git] / tccelf.c
blob25d80d7c6baa2cc204d9ed5a07422834f7a9d2ca
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,
101 unsigned long value, unsigned long size,
102 int info, int other, int shndx, const char *name)
104 int name_offset, sym_index;
105 int nbuckets, h;
106 ElfW(Sym) *sym;
107 Section *hs;
109 sym = section_ptr_add(s, sizeof(ElfW(Sym)));
110 if (name)
111 name_offset = put_elf_str(s->link, name);
112 else
113 name_offset = 0;
114 /* XXX: endianness */
115 sym->st_name = name_offset;
116 sym->st_value = value;
117 sym->st_size = size;
118 sym->st_info = info;
119 sym->st_other = other;
120 sym->st_shndx = shndx;
121 sym_index = sym - (ElfW(Sym) *)s->data;
122 hs = s->hash;
123 if (hs) {
124 int *ptr, *base;
125 ptr = section_ptr_add(hs, sizeof(int));
126 base = (int *)hs->data;
127 /* only add global or weak symbols */
128 if (ELFW(ST_BIND)(info) != STB_LOCAL) {
129 /* add another hashing entry */
130 nbuckets = base[0];
131 h = elf_hash(name) % nbuckets;
132 *ptr = base[2 + h];
133 base[2 + h] = sym_index;
134 base[1]++;
135 /* we resize the hash table */
136 hs->nb_hashed_syms++;
137 if (hs->nb_hashed_syms > 2 * nbuckets) {
138 rebuild_hash(s, 2 * nbuckets);
140 } else {
141 *ptr = 0;
142 base[1]++;
145 return sym_index;
148 /* find global ELF symbol 'name' and return its index. Return 0 if not
149 found. */
150 ST_FUNC int find_elf_sym(Section *s, const char *name)
152 ElfW(Sym) *sym;
153 Section *hs;
154 int nbuckets, sym_index, h;
155 const char *name1;
157 hs = s->hash;
158 if (!hs)
159 return 0;
160 nbuckets = ((int *)hs->data)[0];
161 h = elf_hash(name) % nbuckets;
162 sym_index = ((int *)hs->data)[2 + h];
163 while (sym_index != 0) {
164 sym = &((ElfW(Sym) *)s->data)[sym_index];
165 name1 = s->link->data + sym->st_name;
166 if (!strcmp(name, name1))
167 return sym_index;
168 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
170 return 0;
173 /* return elf symbol value, signal error if 'err' is nonzero */
174 static void *get_elf_sym_addr(TCCState *s, const char *name, int err)
176 int sym_index;
177 ElfW(Sym) *sym;
179 sym_index = find_elf_sym(symtab_section, name);
180 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
181 if (!sym_index || sym->st_shndx == SHN_UNDEF) {
182 if (err)
183 error("%s not defined", name);
184 return NULL;
186 return (void*)(uplong)sym->st_value;
189 /* return elf symbol value */
190 LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
192 return get_elf_sym_addr(s, name, 0);
195 /* return elf symbol value or error */
196 ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name)
198 return get_elf_sym_addr(s, name, 1);
201 /* add an elf symbol : check if it is already defined and patch
202 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
203 ST_FUNC int add_elf_sym(Section *s, uplong value, unsigned long size,
204 int info, int other, int sh_num, const char *name)
206 ElfW(Sym) *esym;
207 int sym_bind, sym_index, sym_type, esym_bind;
208 unsigned char sym_vis, esym_vis, new_vis;
210 sym_bind = ELFW(ST_BIND)(info);
211 sym_type = ELFW(ST_TYPE)(info);
212 sym_vis = ELFW(ST_VISIBILITY)(other);
214 if (sym_bind != STB_LOCAL) {
215 /* we search global or weak symbols */
216 sym_index = find_elf_sym(s, name);
217 if (!sym_index)
218 goto do_def;
219 esym = &((ElfW(Sym) *)s->data)[sym_index];
220 if (esym->st_shndx != SHN_UNDEF) {
221 esym_bind = ELFW(ST_BIND)(esym->st_info);
222 /* propagate the most constraining visibility */
223 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
224 esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
225 if (esym_vis == STV_DEFAULT) {
226 new_vis = sym_vis;
227 } else if (sym_vis == STV_DEFAULT) {
228 new_vis = esym_vis;
229 } else {
230 new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
232 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
233 | new_vis;
234 other = esym->st_other; /* in case we have to patch esym */
235 if (sh_num == SHN_UNDEF) {
236 /* ignore adding of undefined symbol if the
237 corresponding symbol is already defined */
238 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
239 /* global overrides weak, so patch */
240 goto do_patch;
241 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
242 /* weak is ignored if already global */
243 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
244 /* ignore hidden symbols after */
245 } else if (esym->st_shndx == SHN_COMMON
246 && (sh_num < SHN_LORESERVE || sh_num == SHN_COMMON)) {
247 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
248 No idea if this is the correct solution ... */
249 goto do_patch;
250 } else if (s == tcc_state->dynsymtab_section) {
251 /* we accept that two DLL define the same symbol */
252 } else {
253 #if 1
254 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
255 sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
256 #endif
257 error_noabort("'%s' defined twice", name);
259 } else {
260 do_patch:
261 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
262 esym->st_shndx = sh_num;
263 esym->st_value = value;
264 esym->st_size = size;
265 esym->st_other = other;
267 } else {
268 do_def:
269 sym_index = put_elf_sym(s, value, size,
270 ELFW(ST_INFO)(sym_bind, sym_type), other,
271 sh_num, name);
273 return sym_index;
276 /* put relocation */
277 ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
278 int type, int symbol)
280 char buf[256];
281 Section *sr;
282 ElfW_Rel *rel;
284 sr = s->reloc;
285 if (!sr) {
286 /* if no relocation section, create it */
287 snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
288 /* if the symtab is allocated, then we consider the relocation
289 are also */
290 sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
291 sr->sh_entsize = sizeof(ElfW_Rel);
292 sr->link = symtab;
293 sr->sh_info = s->sh_num;
294 s->reloc = sr;
296 rel = section_ptr_add(sr, sizeof(ElfW_Rel));
297 rel->r_offset = offset;
298 rel->r_info = ELFW(R_INFO)(symbol, type);
299 #ifdef TCC_TARGET_X86_64
300 rel->r_addend = 0;
301 #endif
304 /* put stab debug information */
306 ST_FUNC void put_stabs(const char *str, int type, int other, int desc,
307 unsigned long value)
309 Stab_Sym *sym;
311 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
312 if (str) {
313 sym->n_strx = put_elf_str(stabstr_section, str);
314 } else {
315 sym->n_strx = 0;
317 sym->n_type = type;
318 sym->n_other = other;
319 sym->n_desc = desc;
320 sym->n_value = value;
323 ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc,
324 unsigned long value, Section *sec, int sym_index)
326 put_stabs(str, type, other, desc, value);
327 put_elf_reloc(symtab_section, stab_section,
328 stab_section->data_offset - sizeof(unsigned int),
329 R_DATA_32, sym_index);
332 ST_FUNC void put_stabn(int type, int other, int desc, int value)
334 put_stabs(NULL, type, other, desc, value);
337 ST_FUNC void put_stabd(int type, int other, int desc)
339 put_stabs(NULL, type, other, desc, 0);
342 /* In an ELF file symbol table, the local symbols must appear below
343 the global and weak ones. Since TCC cannot sort it while generating
344 the code, we must do it after. All the relocation tables are also
345 modified to take into account the symbol table sorting */
346 static void sort_syms(TCCState *s1, Section *s)
348 int *old_to_new_syms;
349 ElfW(Sym) *new_syms;
350 int nb_syms, i;
351 ElfW(Sym) *p, *q;
352 ElfW_Rel *rel, *rel_end;
353 Section *sr;
354 int type, sym_index;
356 nb_syms = s->data_offset / sizeof(ElfW(Sym));
357 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
358 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
360 /* first pass for local symbols */
361 p = (ElfW(Sym) *)s->data;
362 q = new_syms;
363 for(i = 0; i < nb_syms; i++) {
364 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
365 old_to_new_syms[i] = q - new_syms;
366 *q++ = *p;
368 p++;
370 /* save the number of local symbols in section header */
371 s->sh_info = q - new_syms;
373 /* then second pass for non local symbols */
374 p = (ElfW(Sym) *)s->data;
375 for(i = 0; i < nb_syms; i++) {
376 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
377 old_to_new_syms[i] = q - new_syms;
378 *q++ = *p;
380 p++;
383 /* we copy the new symbols to the old */
384 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
385 tcc_free(new_syms);
387 /* now we modify all the relocations */
388 for(i = 1; i < s1->nb_sections; i++) {
389 sr = s1->sections[i];
390 if (sr->sh_type == SHT_RELX && sr->link == s) {
391 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
392 for(rel = (ElfW_Rel *)sr->data;
393 rel < rel_end;
394 rel++) {
395 sym_index = ELFW(R_SYM)(rel->r_info);
396 type = ELFW(R_TYPE)(rel->r_info);
397 sym_index = old_to_new_syms[sym_index];
398 rel->r_info = ELFW(R_INFO)(sym_index, type);
403 tcc_free(old_to_new_syms);
406 /* relocate common symbols in the .bss section */
407 ST_FUNC void relocate_common_syms(void)
409 ElfW(Sym) *sym, *sym_end;
410 unsigned long offset, align;
412 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
413 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
414 sym < sym_end;
415 sym++) {
416 if (sym->st_shndx == SHN_COMMON) {
417 /* align symbol */
418 align = sym->st_value;
419 offset = bss_section->data_offset;
420 offset = (offset + align - 1) & -align;
421 sym->st_value = offset;
422 sym->st_shndx = bss_section->sh_num;
423 offset += sym->st_size;
424 bss_section->data_offset = offset;
429 /* relocate symbol table, resolve undefined symbols if do_resolve is
430 true and output error if undefined symbol. */
431 ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
433 ElfW(Sym) *sym, *esym, *sym_end;
434 int sym_bind, sh_num, sym_index;
435 const char *name;
437 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
438 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
439 sym < sym_end;
440 sym++) {
441 sh_num = sym->st_shndx;
442 if (sh_num == SHN_UNDEF) {
443 name = strtab_section->data + sym->st_name;
444 if (do_resolve) {
445 #ifndef _WIN32
446 void *addr;
447 name = symtab_section->link->data + sym->st_name;
448 addr = resolve_sym(s1, name);
449 if (addr) {
450 sym->st_value = (uplong)addr;
451 goto found;
453 #endif
454 } else if (s1->dynsym) {
455 /* if dynamic symbol exist, then use it */
456 sym_index = find_elf_sym(s1->dynsym, name);
457 if (sym_index) {
458 esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
459 sym->st_value = esym->st_value;
460 goto found;
463 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
464 it */
465 if (!strcmp(name, "_fp_hw"))
466 goto found;
467 /* only weak symbols are accepted to be undefined. Their
468 value is zero */
469 sym_bind = ELFW(ST_BIND)(sym->st_info);
470 if (sym_bind == STB_WEAK) {
471 sym->st_value = 0;
472 } else {
473 error_noabort("undefined symbol '%s'", name);
475 } else if (sh_num < SHN_LORESERVE) {
476 /* add section base */
477 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
479 found: ;
483 #ifndef TCC_TARGET_PE
484 #ifdef TCC_TARGET_X86_64
485 #define JMP_TABLE_ENTRY_SIZE 14
486 static unsigned long add_jmp_table(TCCState *s1, unsigned long val)
488 char *p = s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset;
489 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
490 /* jmp *0x0(%rip) */
491 p[0] = 0xff;
492 p[1] = 0x25;
493 *(int *)(p + 2) = 0;
494 *(unsigned long *)(p + 6) = val;
495 return (unsigned long)p;
498 static unsigned long add_got_table(TCCState *s1, unsigned long val)
500 unsigned long *p =(unsigned long *)(s1->runtime_plt_and_got +
501 s1->runtime_plt_and_got_offset);
502 s1->runtime_plt_and_got_offset += sizeof(void *);
503 *p = val;
504 return (unsigned long)p;
506 #endif
507 #endif
509 /* relocate a given section (CPU dependent) */
510 ST_FUNC void relocate_section(TCCState *s1, Section *s)
512 Section *sr;
513 ElfW_Rel *rel, *rel_end, *qrel;
514 ElfW(Sym) *sym;
515 int type, sym_index;
516 unsigned char *ptr;
517 unsigned long val, addr;
518 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
519 int esym_index;
520 #endif
522 sr = s->reloc;
523 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
524 qrel = (ElfW_Rel *)sr->data;
525 for(rel = qrel;
526 rel < rel_end;
527 rel++) {
528 ptr = s->data + rel->r_offset;
530 sym_index = ELFW(R_SYM)(rel->r_info);
531 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
532 val = sym->st_value;
533 #ifdef TCC_TARGET_X86_64
534 /* XXX: not tested */
535 val += rel->r_addend;
536 #endif
537 type = ELFW(R_TYPE)(rel->r_info);
538 addr = s->sh_addr + rel->r_offset;
540 /* CPU specific */
541 switch(type) {
542 #if defined(TCC_TARGET_I386)
543 case R_386_32:
544 if (s1->output_type == TCC_OUTPUT_DLL) {
545 esym_index = s1->symtab_to_dynsym[sym_index];
546 qrel->r_offset = rel->r_offset;
547 if (esym_index) {
548 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
549 qrel++;
550 break;
551 } else {
552 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
553 qrel++;
556 *(int *)ptr += val;
557 break;
558 case R_386_PC32:
559 if (s1->output_type == TCC_OUTPUT_DLL) {
560 /* DLL relocation */
561 esym_index = s1->symtab_to_dynsym[sym_index];
562 if (esym_index) {
563 qrel->r_offset = rel->r_offset;
564 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
565 qrel++;
566 break;
569 *(int *)ptr += val - addr;
570 break;
571 case R_386_PLT32:
572 *(int *)ptr += val - addr;
573 break;
574 case R_386_GLOB_DAT:
575 case R_386_JMP_SLOT:
576 *(int *)ptr = val;
577 break;
578 case R_386_GOTPC:
579 *(int *)ptr += s1->got->sh_addr - addr;
580 break;
581 case R_386_GOTOFF:
582 *(int *)ptr += val - s1->got->sh_addr;
583 break;
584 case R_386_GOT32:
585 /* we load the got offset */
586 *(int *)ptr += s1->got_offsets[sym_index];
587 break;
588 case R_386_16:
589 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
590 output_file:
591 error("can only produce 16-bit binary files");
593 *(short *)ptr += val;
594 break;
595 case R_386_PC16:
596 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
597 goto output_file;
598 *(short *)ptr += val - addr;
599 break;
600 #elif defined(TCC_TARGET_ARM)
601 case R_ARM_PC24:
602 case R_ARM_CALL:
603 case R_ARM_JUMP24:
604 case R_ARM_PLT32:
606 int x;
607 x = (*(int *)ptr)&0xffffff;
608 (*(int *)ptr) &= 0xff000000;
609 if (x & 0x800000)
610 x -= 0x1000000;
611 x *= 4;
612 x += val - addr;
613 if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
614 error("can't relocate value at %x",addr);
615 x >>= 2;
616 x &= 0xffffff;
617 (*(int *)ptr) |= x;
619 break;
620 case R_ARM_PREL31:
622 int x;
623 x = (*(int *)ptr) & 0x7fffffff;
624 (*(int *)ptr) &= 0x80000000;
625 x = (x * 2) / 2;
626 x += val - addr;
627 if((x^(x>>1))&0x40000000)
628 error("can't relocate value at %x",addr);
629 (*(int *)ptr) |= x & 0x7fffffff;
631 case R_ARM_ABS32:
632 *(int *)ptr += val;
633 break;
634 case R_ARM_BASE_PREL:
635 *(int *)ptr += s1->got->sh_addr - addr;
636 break;
637 case R_ARM_GOTOFF32:
638 *(int *)ptr += val - s1->got->sh_addr;
639 break;
640 case R_ARM_GOT_BREL:
641 /* we load the got offset */
642 *(int *)ptr += s1->got_offsets[sym_index];
643 break;
644 case R_ARM_COPY:
645 break;
646 default:
647 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
648 type,addr,(unsigned int)(long)ptr,val);
649 break;
650 #elif defined(TCC_TARGET_C67)
651 case R_C60_32:
652 *(int *)ptr += val;
653 break;
654 case R_C60LO16:
656 uint32_t orig;
658 /* put the low 16 bits of the absolute address */
659 // add to what is already there
661 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
662 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
664 //patch both at once - assumes always in pairs Low - High
666 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
667 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
669 break;
670 case R_C60HI16:
671 break;
672 default:
673 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
674 type,addr,(unsigned int)(long)ptr, val);
675 break;
676 #elif defined(TCC_TARGET_X86_64)
677 case R_X86_64_64:
678 if (s1->output_type == TCC_OUTPUT_DLL) {
679 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
680 qrel->r_addend = *(long long *)ptr + val;
681 qrel++;
683 *(long long *)ptr += val;
684 break;
685 case R_X86_64_32:
686 case R_X86_64_32S:
687 if (s1->output_type == TCC_OUTPUT_DLL) {
688 /* XXX: this logic may depend on TCC's codegen
689 now TCC uses R_X86_64_32 even for a 64bit pointer */
690 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
691 qrel->r_addend = *(int *)ptr + val;
692 qrel++;
694 *(int *)ptr += val;
695 break;
696 case R_X86_64_PC32: {
697 long long diff;
698 if (s1->output_type == TCC_OUTPUT_DLL) {
699 /* DLL relocation */
700 esym_index = s1->symtab_to_dynsym[sym_index];
701 if (esym_index) {
702 qrel->r_offset = rel->r_offset;
703 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
704 qrel->r_addend = *(int *)ptr;
705 qrel++;
706 break;
709 diff = (long long)val - addr;
710 if (diff <= -2147483647 || diff > 2147483647) {
711 #ifndef TCC_TARGET_PE
712 /* XXX: naive support for over 32bit jump */
713 if (s1->output_type == TCC_OUTPUT_MEMORY) {
714 val = add_jmp_table(s1, val);
715 diff = val - addr;
717 #endif
718 if (diff <= -2147483647 || diff > 2147483647) {
719 error("internal error: relocation failed");
722 *(int *)ptr += diff;
724 break;
725 case R_X86_64_PLT32:
726 *(int *)ptr += val - addr;
727 break;
728 case R_X86_64_GLOB_DAT:
729 case R_X86_64_JUMP_SLOT:
730 *(int *)ptr = val;
731 break;
732 case R_X86_64_GOTPCREL:
733 #ifndef TCC_TARGET_PE
734 if (s1->output_type == TCC_OUTPUT_MEMORY) {
735 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
736 *(int *)ptr += val - addr;
737 break;
739 #endif
740 *(int *)ptr += (s1->got->sh_addr - addr +
741 s1->got_offsets[sym_index] - 4);
742 break;
743 case R_X86_64_GOTTPOFF:
744 *(int *)ptr += val - s1->got->sh_addr;
745 break;
746 case R_X86_64_GOT32:
747 /* we load the got offset */
748 *(int *)ptr += s1->got_offsets[sym_index];
749 break;
750 #else
751 #error unsupported processor
752 #endif
755 /* if the relocation is allocated, we change its symbol table */
756 if (sr->sh_flags & SHF_ALLOC)
757 sr->link = s1->dynsym;
760 /* relocate relocation table in 'sr' */
761 static void relocate_rel(TCCState *s1, Section *sr)
763 Section *s;
764 ElfW_Rel *rel, *rel_end;
766 s = s1->sections[sr->sh_info];
767 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
768 for(rel = (ElfW_Rel *)sr->data;
769 rel < rel_end;
770 rel++) {
771 rel->r_offset += s->sh_addr;
775 /* count the number of dynamic relocations so that we can reserve
776 their space */
777 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
779 ElfW_Rel *rel, *rel_end;
780 int sym_index, esym_index, type, count;
782 count = 0;
783 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
784 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
785 sym_index = ELFW(R_SYM)(rel->r_info);
786 type = ELFW(R_TYPE)(rel->r_info);
787 switch(type) {
788 #if defined(TCC_TARGET_I386)
789 case R_386_32:
790 #elif defined(TCC_TARGET_X86_64)
791 case R_X86_64_32:
792 case R_X86_64_32S:
793 case R_X86_64_64:
794 #endif
795 count++;
796 break;
797 #if defined(TCC_TARGET_I386)
798 case R_386_PC32:
799 #elif defined(TCC_TARGET_X86_64)
800 case R_X86_64_PC32:
801 #endif
802 esym_index = s1->symtab_to_dynsym[sym_index];
803 if (esym_index)
804 count++;
805 break;
806 default:
807 break;
810 if (count) {
811 /* allocate the section */
812 sr->sh_flags |= SHF_ALLOC;
813 sr->sh_size = count * sizeof(ElfW_Rel);
815 return count;
818 static void put_got_offset(TCCState *s1, int index, unsigned long val)
820 int n;
821 unsigned long *tab;
823 if (index >= s1->nb_got_offsets) {
824 /* find immediately bigger power of 2 and reallocate array */
825 n = 1;
826 while (index >= n)
827 n *= 2;
828 tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
829 if (!tab)
830 error("memory full");
831 s1->got_offsets = tab;
832 memset(s1->got_offsets + s1->nb_got_offsets, 0,
833 (n - s1->nb_got_offsets) * sizeof(unsigned long));
834 s1->nb_got_offsets = n;
836 s1->got_offsets[index] = val;
839 /* XXX: suppress that */
840 static void put32(unsigned char *p, uint32_t val)
842 p[0] = val;
843 p[1] = val >> 8;
844 p[2] = val >> 16;
845 p[3] = val >> 24;
848 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
849 defined(TCC_TARGET_X86_64)
850 static uint32_t get32(unsigned char *p)
852 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
854 #endif
856 static void build_got(TCCState *s1)
858 unsigned char *ptr;
860 /* if no got, then create it */
861 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
862 s1->got->sh_entsize = 4;
863 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
864 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
865 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
866 #if PTR_SIZE == 4
867 /* keep space for _DYNAMIC pointer, if present */
868 put32(ptr, 0);
869 /* two dummy got entries */
870 put32(ptr + 4, 0);
871 put32(ptr + 8, 0);
872 #else
873 /* keep space for _DYNAMIC pointer, if present */
874 put32(ptr, 0);
875 put32(ptr + 4, 0);
876 /* two dummy got entries */
877 put32(ptr + 8, 0);
878 put32(ptr + 12, 0);
879 put32(ptr + 16, 0);
880 put32(ptr + 20, 0);
881 #endif
884 /* put a got entry corresponding to a symbol in symtab_section. 'size'
885 and 'info' can be modifed if more precise info comes from the DLL */
886 static void put_got_entry(TCCState *s1,
887 int reloc_type, unsigned long size, int info,
888 int sym_index)
890 int index;
891 const char *name;
892 ElfW(Sym) *sym;
893 unsigned long offset;
894 int *ptr;
896 if (!s1->got)
897 build_got(s1);
899 /* if a got entry already exists for that symbol, no need to add one */
900 if (sym_index < s1->nb_got_offsets &&
901 s1->got_offsets[sym_index] != 0)
902 return;
904 put_got_offset(s1, sym_index, s1->got->data_offset);
906 if (s1->dynsym) {
907 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
908 name = symtab_section->link->data + sym->st_name;
909 offset = sym->st_value;
910 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
911 if (reloc_type ==
912 #ifdef TCC_TARGET_X86_64
913 R_X86_64_JUMP_SLOT
914 #else
915 R_386_JMP_SLOT
916 #endif
918 Section *plt;
919 uint8_t *p;
920 int modrm;
922 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
923 modrm = 0x25;
924 #else
925 /* if we build a DLL, we add a %ebx offset */
926 if (s1->output_type == TCC_OUTPUT_DLL)
927 modrm = 0xa3;
928 else
929 modrm = 0x25;
930 #endif
932 /* add a PLT entry */
933 plt = s1->plt;
934 if (plt->data_offset == 0) {
935 /* first plt entry */
936 p = section_ptr_add(plt, 16);
937 p[0] = 0xff; /* pushl got + PTR_SIZE */
938 p[1] = modrm + 0x10;
939 put32(p + 2, PTR_SIZE);
940 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
941 p[7] = modrm;
942 put32(p + 8, PTR_SIZE * 2);
945 p = section_ptr_add(plt, 16);
946 p[0] = 0xff; /* jmp *(got + x) */
947 p[1] = modrm;
948 put32(p + 2, s1->got->data_offset);
949 p[6] = 0x68; /* push $xxx */
950 put32(p + 7, (plt->data_offset - 32) >> 1);
951 p[11] = 0xe9; /* jmp plt_start */
952 put32(p + 12, -(plt->data_offset));
954 /* the symbol is modified so that it will be relocated to
955 the PLT */
956 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
957 if (s1->output_type == TCC_OUTPUT_EXE)
958 #endif
959 offset = plt->data_offset - 16;
961 #elif defined(TCC_TARGET_ARM)
962 if (reloc_type == R_ARM_JUMP_SLOT) {
963 Section *plt;
964 uint8_t *p;
966 /* if we build a DLL, we add a %ebx offset */
967 if (s1->output_type == TCC_OUTPUT_DLL)
968 error("DLLs unimplemented!");
970 /* add a PLT entry */
971 plt = s1->plt;
972 if (plt->data_offset == 0) {
973 /* first plt entry */
974 p = section_ptr_add(plt, 16);
975 put32(p , 0xe52de004);
976 put32(p + 4, 0xe59fe010);
977 put32(p + 8, 0xe08fe00e);
978 put32(p + 12, 0xe5bef008);
981 p = section_ptr_add(plt, 16);
982 put32(p , 0xe59fc004);
983 put32(p+4, 0xe08fc00c);
984 put32(p+8, 0xe59cf000);
985 put32(p+12, s1->got->data_offset);
987 /* the symbol is modified so that it will be relocated to
988 the PLT */
989 if (s1->output_type == TCC_OUTPUT_EXE)
990 offset = plt->data_offset - 16;
992 #elif defined(TCC_TARGET_C67)
993 error("C67 got not implemented");
994 #else
995 #error unsupported CPU
996 #endif
997 index = put_elf_sym(s1->dynsym, offset,
998 size, info, 0, sym->st_shndx, name);
999 /* put a got entry */
1000 put_elf_reloc(s1->dynsym, s1->got,
1001 s1->got->data_offset,
1002 reloc_type, index);
1004 ptr = section_ptr_add(s1->got, PTR_SIZE);
1005 *ptr = 0;
1008 /* build GOT and PLT entries */
1009 ST_FUNC void build_got_entries(TCCState *s1)
1011 Section *s, *symtab;
1012 ElfW_Rel *rel, *rel_end;
1013 ElfW(Sym) *sym;
1014 int i, type, reloc_type, sym_index;
1016 for(i = 1; i < s1->nb_sections; i++) {
1017 s = s1->sections[i];
1018 if (s->sh_type != SHT_RELX)
1019 continue;
1020 /* no need to handle got relocations */
1021 if (s->link != symtab_section)
1022 continue;
1023 symtab = s->link;
1024 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1025 for(rel = (ElfW_Rel *)s->data;
1026 rel < rel_end;
1027 rel++) {
1028 type = ELFW(R_TYPE)(rel->r_info);
1029 switch(type) {
1030 #if defined(TCC_TARGET_I386)
1031 case R_386_GOT32:
1032 case R_386_GOTOFF:
1033 case R_386_GOTPC:
1034 case R_386_PLT32:
1035 if (!s1->got)
1036 build_got(s1);
1037 if (type == R_386_GOT32 || type == R_386_PLT32) {
1038 sym_index = ELFW(R_SYM)(rel->r_info);
1039 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1040 /* look at the symbol got offset. If none, then add one */
1041 if (type == R_386_GOT32)
1042 reloc_type = R_386_GLOB_DAT;
1043 else
1044 reloc_type = R_386_JMP_SLOT;
1045 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1046 sym_index);
1048 break;
1049 #elif defined(TCC_TARGET_ARM)
1050 case R_ARM_GOT_BREL:
1051 case R_ARM_GOTOFF32:
1052 case R_ARM_BASE_PREL:
1053 case R_ARM_PLT32:
1054 if (!s1->got)
1055 build_got(s1);
1056 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1057 sym_index = ELFW(R_SYM)(rel->r_info);
1058 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1059 /* look at the symbol got offset. If none, then add one */
1060 if (type == R_ARM_GOT_BREL)
1061 reloc_type = R_ARM_GLOB_DAT;
1062 else
1063 reloc_type = R_ARM_JUMP_SLOT;
1064 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1065 sym_index);
1067 break;
1068 #elif defined(TCC_TARGET_C67)
1069 case R_C60_GOT32:
1070 case R_C60_GOTOFF:
1071 case R_C60_GOTPC:
1072 case R_C60_PLT32:
1073 if (!s1->got)
1074 build_got(s1);
1075 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1076 sym_index = ELFW(R_SYM)(rel->r_info);
1077 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1078 /* look at the symbol got offset. If none, then add one */
1079 if (type == R_C60_GOT32)
1080 reloc_type = R_C60_GLOB_DAT;
1081 else
1082 reloc_type = R_C60_JMP_SLOT;
1083 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1084 sym_index);
1086 break;
1087 #elif defined(TCC_TARGET_X86_64)
1088 case R_X86_64_GOT32:
1089 case R_X86_64_GOTTPOFF:
1090 case R_X86_64_GOTPCREL:
1091 case R_X86_64_PLT32:
1092 if (!s1->got)
1093 build_got(s1);
1094 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1095 type == R_X86_64_PLT32) {
1096 sym_index = ELFW(R_SYM)(rel->r_info);
1097 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1098 /* look at the symbol got offset. If none, then add one */
1099 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1100 reloc_type = R_X86_64_GLOB_DAT;
1101 else
1102 reloc_type = R_X86_64_JUMP_SLOT;
1103 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1104 sym_index);
1106 break;
1107 #else
1108 #error unsupported CPU
1109 #endif
1110 default:
1111 break;
1117 ST_FUNC Section *new_symtab(TCCState *s1,
1118 const char *symtab_name, int sh_type, int sh_flags,
1119 const char *strtab_name,
1120 const char *hash_name, int hash_sh_flags)
1122 Section *symtab, *strtab, *hash;
1123 int *ptr, nb_buckets;
1125 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1126 symtab->sh_entsize = sizeof(ElfW(Sym));
1127 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1128 put_elf_str(strtab, "");
1129 symtab->link = strtab;
1130 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1132 nb_buckets = 1;
1134 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1135 hash->sh_entsize = sizeof(int);
1136 symtab->hash = hash;
1137 hash->link = symtab;
1139 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1140 ptr[0] = nb_buckets;
1141 ptr[1] = 1;
1142 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1143 return symtab;
1146 /* put dynamic tag */
1147 static void put_dt(Section *dynamic, int dt, unsigned long val)
1149 ElfW(Dyn) *dyn;
1150 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1151 dyn->d_tag = dt;
1152 dyn->d_un.d_val = val;
1155 static void add_init_array_defines(TCCState *s1, const char *section_name)
1157 Section *s;
1158 long end_offset;
1159 char sym_start[1024];
1160 char sym_end[1024];
1162 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1163 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1165 s = find_section(s1, section_name);
1166 if (!s) {
1167 end_offset = 0;
1168 s = data_section;
1169 } else {
1170 end_offset = s->data_offset;
1173 add_elf_sym(symtab_section,
1174 0, 0,
1175 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1176 s->sh_num, sym_start);
1177 add_elf_sym(symtab_section,
1178 end_offset, 0,
1179 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1180 s->sh_num, sym_end);
1183 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1185 #ifdef CONFIG_TCC_BCHECK
1186 unsigned long *ptr;
1187 Section *init_section;
1188 unsigned char *pinit;
1189 int sym_index;
1191 if (0 == s1->do_bounds_check)
1192 return;
1194 /* XXX: add an object file to do that */
1195 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1196 *ptr = 0;
1197 add_elf_sym(symtab_section, 0, 0,
1198 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1199 bounds_section->sh_num, "__bounds_start");
1200 /* add bound check code */
1201 #ifndef TCC_TARGET_PE
1203 char buf[1024];
1204 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "bcheck.o");
1205 tcc_add_file(s1, buf);
1207 #endif
1208 #ifdef TCC_TARGET_I386
1209 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1210 /* add 'call __bound_init()' in .init section */
1211 init_section = find_section(s1, ".init");
1212 pinit = section_ptr_add(init_section, 5);
1213 pinit[0] = 0xe8;
1214 put32(pinit + 1, -4);
1215 sym_index = find_elf_sym(symtab_section, "__bound_init");
1216 put_elf_reloc(symtab_section, init_section,
1217 init_section->data_offset - 4, R_386_PC32, sym_index);
1219 #endif
1220 #endif
1223 /* add tcc runtime libraries */
1224 ST_FUNC void tcc_add_runtime(TCCState *s1)
1226 tcc_add_bcheck(s1);
1228 /* add libc */
1229 if (!s1->nostdlib) {
1230 #ifdef CONFIG_USE_LIBGCC
1231 tcc_add_library(s1, "c");
1232 tcc_add_file(s1, CONFIG_SYSROOT "/lib/libgcc_s.so.1");
1233 #else
1234 char buf[1024];
1235 tcc_add_library(s1, "c");
1236 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "libtcc1.a");
1237 tcc_add_file(s1, buf);
1238 #endif
1240 /* add crt end if not memory output */
1241 if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) {
1242 tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
1246 /* add various standard linker symbols (must be done after the
1247 sections are filled (for example after allocating common
1248 symbols)) */
1249 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1251 char buf[1024];
1252 int i;
1253 Section *s;
1255 add_elf_sym(symtab_section,
1256 text_section->data_offset, 0,
1257 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1258 text_section->sh_num, "_etext");
1259 add_elf_sym(symtab_section,
1260 data_section->data_offset, 0,
1261 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1262 data_section->sh_num, "_edata");
1263 add_elf_sym(symtab_section,
1264 bss_section->data_offset, 0,
1265 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1266 bss_section->sh_num, "_end");
1267 /* horrible new standard ldscript defines */
1268 add_init_array_defines(s1, ".preinit_array");
1269 add_init_array_defines(s1, ".init_array");
1270 add_init_array_defines(s1, ".fini_array");
1272 /* add start and stop symbols for sections whose name can be
1273 expressed in C */
1274 for(i = 1; i < s1->nb_sections; i++) {
1275 s = s1->sections[i];
1276 if (s->sh_type == SHT_PROGBITS &&
1277 (s->sh_flags & SHF_ALLOC)) {
1278 const char *p;
1279 int ch;
1281 /* check if section name can be expressed in C */
1282 p = s->name;
1283 for(;;) {
1284 ch = *p;
1285 if (!ch)
1286 break;
1287 if (!isid(ch) && !isnum(ch))
1288 goto next_sec;
1289 p++;
1291 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1292 add_elf_sym(symtab_section,
1293 0, 0,
1294 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1295 s->sh_num, buf);
1296 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1297 add_elf_sym(symtab_section,
1298 s->data_offset, 0,
1299 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1300 s->sh_num, buf);
1302 next_sec: ;
1306 /* name of ELF interpreter */
1307 #if defined __FreeBSD__
1308 static const char elf_interp[] = "/libexec/ld-elf.so.1";
1309 #elif defined TCC_ARM_EABI
1310 static const char elf_interp[] = "/lib/ld-linux.so.3";
1311 #elif defined(TCC_TARGET_X86_64)
1312 static const char elf_interp[] = "/lib/ld-linux-x86-64.so.2";
1313 #elif defined(TCC_UCLIBC)
1314 static const char elf_interp[] = "/lib/ld-uClibc.so.0";
1315 #else
1316 static const char elf_interp[] = "/lib/ld-linux.so.2";
1317 #endif
1319 static void tcc_output_binary(TCCState *s1, FILE *f,
1320 const int *section_order)
1322 Section *s;
1323 int i, offset, size;
1325 offset = 0;
1326 for(i=1;i<s1->nb_sections;i++) {
1327 s = s1->sections[section_order[i]];
1328 if (s->sh_type != SHT_NOBITS &&
1329 (s->sh_flags & SHF_ALLOC)) {
1330 while (offset < s->sh_offset) {
1331 fputc(0, f);
1332 offset++;
1334 size = s->sh_size;
1335 fwrite(s->data, 1, size, f);
1336 offset += size;
1341 #if defined(__FreeBSD__)
1342 #define HAVE_PHDR 1
1343 #define EXTRA_RELITEMS 14
1345 /* move the relocation value from .dynsym to .got */
1346 void patch_dynsym_undef(TCCState *s1, Section *s)
1348 uint32_t *gotd = (void *)s1->got->data;
1349 ElfW(Sym) *sym, *sym_end;
1351 gotd += 3; // dummy entries in .got
1352 /* relocate symbols in .dynsym */
1353 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1354 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1355 if (sym->st_shndx == SHN_UNDEF) {
1356 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1357 sym->st_value = 0;
1361 #else
1362 #define HAVE_PHDR 0
1363 #define EXTRA_RELITEMS 9
1364 #endif
1366 /* output an ELF file */
1367 /* XXX: suppress unneeded sections */
1368 static int elf_output_file(TCCState *s1, const char *filename)
1370 ElfW(Ehdr) ehdr;
1371 FILE *f;
1372 int fd, mode, ret;
1373 int *section_order;
1374 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
1375 unsigned long addr;
1376 Section *strsec, *s;
1377 ElfW(Shdr) shdr, *sh;
1378 ElfW(Phdr) *phdr, *ph;
1379 Section *interp, *dynamic, *dynstr;
1380 unsigned long saved_dynamic_data_offset;
1381 ElfW(Sym) *sym;
1382 int type, file_type;
1383 unsigned long rel_addr, rel_size;
1384 unsigned long bss_addr, bss_size;
1386 file_type = s1->output_type;
1387 s1->nb_errors = 0;
1389 if (file_type != TCC_OUTPUT_OBJ) {
1390 tcc_add_runtime(s1);
1393 phdr = NULL;
1394 section_order = NULL;
1395 interp = NULL;
1396 dynamic = NULL;
1397 dynstr = NULL; /* avoid warning */
1398 saved_dynamic_data_offset = 0; /* avoid warning */
1400 if (file_type != TCC_OUTPUT_OBJ) {
1401 relocate_common_syms();
1403 tcc_add_linker_symbols(s1);
1405 if (!s1->static_link) {
1406 const char *name;
1407 int sym_index, index;
1408 ElfW(Sym) *esym, *sym_end;
1410 if (file_type == TCC_OUTPUT_EXE) {
1411 char *ptr;
1412 /* allow override the dynamic loader */
1413 const char *elfint = getenv("LD_SO");
1414 if (elfint == NULL)
1415 elfint = elf_interp;
1416 /* add interpreter section only if executable */
1417 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1418 interp->sh_addralign = 1;
1419 ptr = section_ptr_add(interp, 1+strlen(elfint));
1420 strcpy(ptr, elfint);
1423 /* add dynamic symbol table */
1424 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1425 ".dynstr",
1426 ".hash", SHF_ALLOC);
1427 dynstr = s1->dynsym->link;
1429 /* add dynamic section */
1430 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1431 SHF_ALLOC | SHF_WRITE);
1432 dynamic->link = dynstr;
1433 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1435 /* add PLT */
1436 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1437 SHF_ALLOC | SHF_EXECINSTR);
1438 s1->plt->sh_entsize = 4;
1440 build_got(s1);
1442 /* scan for undefined symbols and see if they are in the
1443 dynamic symbols. If a symbol STT_FUNC is found, then we
1444 add it in the PLT. If a symbol STT_OBJECT is found, we
1445 add it in the .bss section with a suitable relocation */
1446 sym_end = (ElfW(Sym) *)(symtab_section->data +
1447 symtab_section->data_offset);
1448 if (file_type == TCC_OUTPUT_EXE) {
1449 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1450 sym < sym_end;
1451 sym++) {
1452 if (sym->st_shndx == SHN_UNDEF) {
1453 name = symtab_section->link->data + sym->st_name;
1454 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1455 if (sym_index) {
1456 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1457 type = ELFW(ST_TYPE)(esym->st_info);
1458 if (type == STT_FUNC) {
1459 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1460 esym->st_info,
1461 sym - (ElfW(Sym) *)symtab_section->data);
1462 } else if (type == STT_OBJECT) {
1463 unsigned long offset;
1464 offset = bss_section->data_offset;
1465 /* XXX: which alignment ? */
1466 offset = (offset + 16 - 1) & -16;
1467 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1468 esym->st_info, 0,
1469 bss_section->sh_num, name);
1470 put_elf_reloc(s1->dynsym, bss_section,
1471 offset, R_COPY, index);
1472 offset += esym->st_size;
1473 bss_section->data_offset = offset;
1475 } else {
1476 /* STB_WEAK undefined symbols are accepted */
1477 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1478 it */
1479 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1480 !strcmp(name, "_fp_hw")) {
1481 } else {
1482 error_noabort("undefined symbol '%s'", name);
1485 } else if (s1->rdynamic &&
1486 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1487 /* if -rdynamic option, then export all non
1488 local symbols */
1489 name = symtab_section->link->data + sym->st_name;
1490 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1491 sym->st_info, 0,
1492 sym->st_shndx, name);
1496 if (s1->nb_errors)
1497 goto fail;
1499 /* now look at unresolved dynamic symbols and export
1500 corresponding symbol */
1501 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1502 s1->dynsymtab_section->data_offset);
1503 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1504 esym < sym_end;
1505 esym++) {
1506 if (esym->st_shndx == SHN_UNDEF) {
1507 name = s1->dynsymtab_section->link->data + esym->st_name;
1508 sym_index = find_elf_sym(symtab_section, name);
1509 if (sym_index) {
1510 /* XXX: avoid adding a symbol if already
1511 present because of -rdynamic ? */
1512 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1513 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1514 sym->st_info, 0,
1515 sym->st_shndx, name);
1516 } else {
1517 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1518 /* weak symbols can stay undefined */
1519 } else {
1520 warning("undefined dynamic symbol '%s'", name);
1525 } else {
1526 int nb_syms;
1527 /* shared library case : we simply export all the global symbols */
1528 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1529 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1530 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1531 sym < sym_end;
1532 sym++) {
1533 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1534 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1535 if (ELFW(ST_TYPE)(sym->st_info) == STT_FUNC &&
1536 sym->st_shndx == SHN_UNDEF) {
1537 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1538 sym->st_info,
1539 sym - (ElfW(Sym) *)symtab_section->data);
1541 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1542 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1543 sym->st_info,
1544 sym - (ElfW(Sym) *)symtab_section->data);
1546 else
1547 #endif
1549 name = symtab_section->link->data + sym->st_name;
1550 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1551 sym->st_info, 0,
1552 sym->st_shndx, name);
1553 s1->symtab_to_dynsym[sym -
1554 (ElfW(Sym) *)symtab_section->data] =
1555 index;
1561 build_got_entries(s1);
1563 /* add a list of needed dlls */
1564 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1565 DLLReference *dllref = s1->loaded_dlls[i];
1566 if (dllref->level == 0)
1567 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1570 if (s1->rpath)
1571 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1573 /* XXX: currently, since we do not handle PIC code, we
1574 must relocate the readonly segments */
1575 if (file_type == TCC_OUTPUT_DLL) {
1576 if (s1->soname)
1577 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1578 put_dt(dynamic, DT_TEXTREL, 0);
1580 /* add necessary space for other entries */
1581 saved_dynamic_data_offset = dynamic->data_offset;
1582 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1583 } else {
1584 /* still need to build got entries in case of static link */
1585 build_got_entries(s1);
1589 memset(&ehdr, 0, sizeof(ehdr));
1591 /* we add a section for symbols */
1592 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1593 put_elf_str(strsec, "");
1595 /* compute number of sections */
1596 shnum = s1->nb_sections;
1598 /* this array is used to reorder sections in the output file */
1599 section_order = tcc_malloc(sizeof(int) * shnum);
1600 section_order[0] = 0;
1601 sh_order_index = 1;
1603 /* compute number of program headers */
1604 switch(file_type) {
1605 default:
1606 case TCC_OUTPUT_OBJ:
1607 phnum = 0;
1608 break;
1609 case TCC_OUTPUT_EXE:
1610 if (!s1->static_link)
1611 phnum = 4 + HAVE_PHDR;
1612 else
1613 phnum = 2;
1614 break;
1615 case TCC_OUTPUT_DLL:
1616 phnum = 3;
1617 break;
1620 /* allocate strings for section names and decide if an unallocated
1621 section should be output */
1622 /* NOTE: the strsec section comes last, so its size is also
1623 correct ! */
1624 for(i = 1; i < s1->nb_sections; i++) {
1625 s = s1->sections[i];
1626 s->sh_name = put_elf_str(strsec, s->name);
1627 #if 0 //gr
1628 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1629 s->sh_flags,
1630 s->sh_type,
1631 s->sh_info,
1632 s->name,
1633 s->reloc ? s->reloc->name : "n"
1635 #endif
1636 /* when generating a DLL, we include relocations but we may
1637 patch them */
1638 if (file_type == TCC_OUTPUT_DLL &&
1639 s->sh_type == SHT_RELX &&
1640 !(s->sh_flags & SHF_ALLOC)) {
1641 /* //gr: avoid bogus relocs for empty (debug) sections */
1642 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1643 prepare_dynamic_rel(s1, s);
1644 else if (s1->do_debug)
1645 s->sh_size = s->data_offset;
1646 } else if (s1->do_debug ||
1647 file_type == TCC_OUTPUT_OBJ ||
1648 (s->sh_flags & SHF_ALLOC) ||
1649 i == (s1->nb_sections - 1)) {
1650 /* we output all sections if debug or object file */
1651 s->sh_size = s->data_offset;
1655 /* allocate program segment headers */
1656 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1658 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1659 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1660 } else {
1661 file_offset = 0;
1663 if (phnum > 0) {
1664 /* compute section to program header mapping */
1665 if (s1->has_text_addr) {
1666 int a_offset, p_offset;
1667 addr = s1->text_addr;
1668 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1669 ELF_PAGE_SIZE */
1670 a_offset = addr & (s1->section_align - 1);
1671 p_offset = file_offset & (s1->section_align - 1);
1672 if (a_offset < p_offset)
1673 a_offset += s1->section_align;
1674 file_offset += (a_offset - p_offset);
1675 } else {
1676 if (file_type == TCC_OUTPUT_DLL)
1677 addr = 0;
1678 else
1679 addr = ELF_START_ADDR;
1680 /* compute address after headers */
1681 addr += (file_offset & (s1->section_align - 1));
1684 /* dynamic relocation table information, for .dynamic section */
1685 rel_size = 0;
1686 rel_addr = 0;
1688 bss_addr = bss_size = 0;
1689 /* leave one program header for the program interpreter */
1690 ph = &phdr[0];
1691 if (interp)
1692 ph += 1 + HAVE_PHDR;
1694 for(j = 0; j < 2; j++) {
1695 ph->p_type = PT_LOAD;
1696 if (j == 0)
1697 ph->p_flags = PF_R | PF_X;
1698 else
1699 ph->p_flags = PF_R | PF_W;
1700 ph->p_align = s1->section_align;
1702 /* we do the following ordering: interp, symbol tables,
1703 relocations, progbits, nobits */
1704 /* XXX: do faster and simpler sorting */
1705 for(k = 0; k < 5; k++) {
1706 for(i = 1; i < s1->nb_sections; i++) {
1707 s = s1->sections[i];
1708 /* compute if section should be included */
1709 if (j == 0) {
1710 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1711 SHF_ALLOC)
1712 continue;
1713 } else {
1714 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1715 (SHF_ALLOC | SHF_WRITE))
1716 continue;
1718 if (s == interp) {
1719 if (k != 0)
1720 continue;
1721 } else if (s->sh_type == SHT_DYNSYM ||
1722 s->sh_type == SHT_STRTAB ||
1723 s->sh_type == SHT_HASH) {
1724 if (k != 1)
1725 continue;
1726 } else if (s->sh_type == SHT_RELX) {
1727 if (k != 2)
1728 continue;
1729 } else if (s->sh_type == SHT_NOBITS) {
1730 if (k != 4)
1731 continue;
1732 } else {
1733 if (k != 3)
1734 continue;
1736 section_order[sh_order_index++] = i;
1738 /* section matches: we align it and add its size */
1739 tmp = addr;
1740 addr = (addr + s->sh_addralign - 1) &
1741 ~(s->sh_addralign - 1);
1742 file_offset += addr - tmp;
1743 s->sh_offset = file_offset;
1744 s->sh_addr = addr;
1746 /* update program header infos */
1747 if (ph->p_offset == 0) {
1748 ph->p_offset = file_offset;
1749 ph->p_vaddr = addr;
1750 ph->p_paddr = ph->p_vaddr;
1752 /* update dynamic relocation infos */
1753 if (s->sh_type == SHT_RELX) {
1754 #if defined(__FreeBSD__)
1755 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1756 rel_addr = addr;
1757 rel_size += s->sh_size; // XXX only first rel.
1759 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1760 bss_addr = addr;
1761 bss_size = s->sh_size; // XXX only first rel.
1763 #else
1764 if (rel_size == 0)
1765 rel_addr = addr;
1766 rel_size += s->sh_size;
1767 #endif
1769 addr += s->sh_size;
1770 if (s->sh_type != SHT_NOBITS)
1771 file_offset += s->sh_size;
1774 ph->p_filesz = file_offset - ph->p_offset;
1775 ph->p_memsz = addr - ph->p_vaddr;
1776 ph++;
1777 if (j == 0) {
1778 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1779 /* if in the middle of a page, we duplicate the page in
1780 memory so that one copy is RX and the other is RW */
1781 if ((addr & (s1->section_align - 1)) != 0)
1782 addr += s1->section_align;
1783 } else {
1784 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1785 file_offset = (file_offset + s1->section_align - 1) &
1786 ~(s1->section_align - 1);
1791 /* if interpreter, then add corresponing program header */
1792 if (interp) {
1793 ph = &phdr[0];
1795 #if defined(__FreeBSD__)
1797 int len = phnum * sizeof(ElfW(Phdr));
1799 ph->p_type = PT_PHDR;
1800 ph->p_offset = sizeof(ElfW(Ehdr));
1801 ph->p_vaddr = interp->sh_addr - len;
1802 ph->p_paddr = ph->p_vaddr;
1803 ph->p_filesz = ph->p_memsz = len;
1804 ph->p_flags = PF_R | PF_X;
1805 ph->p_align = 4; // interp->sh_addralign;
1806 ph++;
1808 #endif
1810 ph->p_type = PT_INTERP;
1811 ph->p_offset = interp->sh_offset;
1812 ph->p_vaddr = interp->sh_addr;
1813 ph->p_paddr = ph->p_vaddr;
1814 ph->p_filesz = interp->sh_size;
1815 ph->p_memsz = interp->sh_size;
1816 ph->p_flags = PF_R;
1817 ph->p_align = interp->sh_addralign;
1820 /* if dynamic section, then add corresponing program header */
1821 if (dynamic) {
1822 ElfW(Sym) *sym_end;
1824 ph = &phdr[phnum - 1];
1826 ph->p_type = PT_DYNAMIC;
1827 ph->p_offset = dynamic->sh_offset;
1828 ph->p_vaddr = dynamic->sh_addr;
1829 ph->p_paddr = ph->p_vaddr;
1830 ph->p_filesz = dynamic->sh_size;
1831 ph->p_memsz = dynamic->sh_size;
1832 ph->p_flags = PF_R | PF_W;
1833 ph->p_align = dynamic->sh_addralign;
1835 /* put GOT dynamic section address */
1836 put32(s1->got->data, dynamic->sh_addr);
1838 /* relocate the PLT */
1839 if (file_type == TCC_OUTPUT_EXE
1840 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1841 || file_type == TCC_OUTPUT_DLL
1842 #endif
1844 uint8_t *p, *p_end;
1846 p = s1->plt->data;
1847 p_end = p + s1->plt->data_offset;
1848 if (p < p_end) {
1849 #if defined(TCC_TARGET_I386)
1850 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1851 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1852 p += 16;
1853 while (p < p_end) {
1854 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1855 p += 16;
1857 #elif defined(TCC_TARGET_X86_64)
1858 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1859 put32(p + 2, get32(p + 2) + x);
1860 put32(p + 8, get32(p + 8) + x - 6);
1861 p += 16;
1862 while (p < p_end) {
1863 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1864 p += 16;
1866 #elif defined(TCC_TARGET_ARM)
1867 int x;
1868 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1869 p +=16;
1870 while (p < p_end) {
1871 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1872 p += 16;
1874 #elif defined(TCC_TARGET_C67)
1875 /* XXX: TODO */
1876 #else
1877 #error unsupported CPU
1878 #endif
1882 /* relocate symbols in .dynsym */
1883 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
1884 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
1885 sym < sym_end;
1886 sym++) {
1887 if (sym->st_shndx == SHN_UNDEF) {
1888 /* relocate to the PLT if the symbol corresponds
1889 to a PLT entry */
1890 if (sym->st_value)
1891 sym->st_value += s1->plt->sh_addr;
1892 } else if (sym->st_shndx < SHN_LORESERVE) {
1893 /* do symbol relocation */
1894 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
1898 /* put dynamic section entries */
1899 dynamic->data_offset = saved_dynamic_data_offset;
1900 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
1901 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
1902 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
1903 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
1904 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
1905 #ifdef TCC_TARGET_X86_64
1906 put_dt(dynamic, DT_RELA, rel_addr);
1907 put_dt(dynamic, DT_RELASZ, rel_size);
1908 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
1909 #else
1910 #if defined(__FreeBSD__)
1911 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
1912 put_dt(dynamic, DT_PLTRELSZ, rel_size);
1913 put_dt(dynamic, DT_JMPREL, rel_addr);
1914 put_dt(dynamic, DT_PLTREL, DT_REL);
1915 put_dt(dynamic, DT_REL, bss_addr);
1916 put_dt(dynamic, DT_RELSZ, bss_size);
1917 #else
1918 put_dt(dynamic, DT_REL, rel_addr);
1919 put_dt(dynamic, DT_RELSZ, rel_size);
1920 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
1921 #endif
1922 #endif
1923 if (s1->do_debug)
1924 put_dt(dynamic, DT_DEBUG, 0);
1925 put_dt(dynamic, DT_NULL, 0);
1928 ehdr.e_phentsize = sizeof(ElfW(Phdr));
1929 ehdr.e_phnum = phnum;
1930 ehdr.e_phoff = sizeof(ElfW(Ehdr));
1933 /* all other sections come after */
1934 for(i = 1; i < s1->nb_sections; i++) {
1935 s = s1->sections[i];
1936 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
1937 continue;
1938 section_order[sh_order_index++] = i;
1940 file_offset = (file_offset + s->sh_addralign - 1) &
1941 ~(s->sh_addralign - 1);
1942 s->sh_offset = file_offset;
1943 if (s->sh_type != SHT_NOBITS)
1944 file_offset += s->sh_size;
1947 /* if building executable or DLL, then relocate each section
1948 except the GOT which is already relocated */
1949 if (file_type != TCC_OUTPUT_OBJ) {
1950 relocate_syms(s1, 0);
1952 if (s1->nb_errors != 0) {
1953 fail:
1954 ret = -1;
1955 goto the_end;
1958 /* relocate sections */
1959 /* XXX: ignore sections with allocated relocations ? */
1960 for(i = 1; i < s1->nb_sections; i++) {
1961 s = s1->sections[i];
1962 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
1963 relocate_section(s1, s);
1966 /* relocate relocation entries if the relocation tables are
1967 allocated in the executable */
1968 for(i = 1; i < s1->nb_sections; i++) {
1969 s = s1->sections[i];
1970 if ((s->sh_flags & SHF_ALLOC) &&
1971 s->sh_type == SHT_RELX) {
1972 relocate_rel(s1, s);
1976 /* get entry point address */
1977 if (file_type == TCC_OUTPUT_EXE)
1978 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
1979 else
1980 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
1983 /* write elf file */
1984 if (file_type == TCC_OUTPUT_OBJ)
1985 mode = 0666;
1986 else
1987 mode = 0777;
1988 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
1989 if (fd < 0) {
1990 error_noabort("could not write '%s'", filename);
1991 goto fail;
1993 f = fdopen(fd, "wb");
1994 if (s1->verbose)
1995 printf("<- %s\n", filename);
1997 #ifdef TCC_TARGET_COFF
1998 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
1999 tcc_output_coff(s1, f);
2000 } else
2001 #endif
2002 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2003 sort_syms(s1, symtab_section);
2005 /* align to 4 */
2006 file_offset = (file_offset + 3) & -4;
2008 /* fill header */
2009 ehdr.e_ident[0] = ELFMAG0;
2010 ehdr.e_ident[1] = ELFMAG1;
2011 ehdr.e_ident[2] = ELFMAG2;
2012 ehdr.e_ident[3] = ELFMAG3;
2013 ehdr.e_ident[4] = TCC_ELFCLASS;
2014 ehdr.e_ident[5] = ELFDATA2LSB;
2015 ehdr.e_ident[6] = EV_CURRENT;
2016 #ifdef __FreeBSD__
2017 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2018 #endif
2019 #ifdef TCC_TARGET_ARM
2020 #ifdef TCC_ARM_EABI
2021 ehdr.e_ident[EI_OSABI] = 0;
2022 ehdr.e_flags = 4 << 24;
2023 #else
2024 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2025 #endif
2026 #endif
2027 switch(file_type) {
2028 default:
2029 case TCC_OUTPUT_EXE:
2030 ehdr.e_type = ET_EXEC;
2031 break;
2032 case TCC_OUTPUT_DLL:
2033 ehdr.e_type = ET_DYN;
2034 break;
2035 case TCC_OUTPUT_OBJ:
2036 ehdr.e_type = ET_REL;
2037 break;
2039 ehdr.e_machine = EM_TCC_TARGET;
2040 ehdr.e_version = EV_CURRENT;
2041 ehdr.e_shoff = file_offset;
2042 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2043 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2044 ehdr.e_shnum = shnum;
2045 ehdr.e_shstrndx = shnum - 1;
2047 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2048 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2049 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2051 for(i=1;i<s1->nb_sections;i++) {
2052 s = s1->sections[section_order[i]];
2053 if (s->sh_type != SHT_NOBITS) {
2054 #if defined(__FreeBSD__)
2055 if (s->sh_type == SHT_DYNSYM)
2056 patch_dynsym_undef(s1, s);
2057 #endif
2058 while (offset < s->sh_offset) {
2059 fputc(0, f);
2060 offset++;
2062 size = s->sh_size;
2063 fwrite(s->data, 1, size, f);
2064 offset += size;
2068 /* output section headers */
2069 while (offset < ehdr.e_shoff) {
2070 fputc(0, f);
2071 offset++;
2074 for(i=0;i<s1->nb_sections;i++) {
2075 sh = &shdr;
2076 memset(sh, 0, sizeof(ElfW(Shdr)));
2077 s = s1->sections[i];
2078 if (s) {
2079 sh->sh_name = s->sh_name;
2080 sh->sh_type = s->sh_type;
2081 sh->sh_flags = s->sh_flags;
2082 sh->sh_entsize = s->sh_entsize;
2083 sh->sh_info = s->sh_info;
2084 if (s->link)
2085 sh->sh_link = s->link->sh_num;
2086 sh->sh_addralign = s->sh_addralign;
2087 sh->sh_addr = s->sh_addr;
2088 sh->sh_offset = s->sh_offset;
2089 sh->sh_size = s->sh_size;
2091 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2093 } else {
2094 tcc_output_binary(s1, f, section_order);
2096 fclose(f);
2098 ret = 0;
2099 the_end:
2100 tcc_free(s1->symtab_to_dynsym);
2101 tcc_free(section_order);
2102 tcc_free(phdr);
2103 tcc_free(s1->got_offsets);
2104 return ret;
2107 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2109 int ret;
2110 #ifdef TCC_TARGET_PE
2111 if (s->output_type != TCC_OUTPUT_OBJ) {
2112 ret = pe_output_file(s, filename);
2113 } else
2114 #endif
2116 ret = elf_output_file(s, filename);
2118 return ret;
2121 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2123 void *data;
2125 data = tcc_malloc(size);
2126 lseek(fd, file_offset, SEEK_SET);
2127 read(fd, data, size);
2128 return data;
2131 typedef struct SectionMergeInfo {
2132 Section *s; /* corresponding existing section */
2133 unsigned long offset; /* offset of the new section in the existing section */
2134 uint8_t new_section; /* true if section 's' was added */
2135 uint8_t link_once; /* true if link once section */
2136 } SectionMergeInfo;
2138 /* load an object file and merge it with current files */
2139 /* XXX: handle correctly stab (debug) info */
2140 ST_FUNC int tcc_load_object_file(TCCState *s1,
2141 int fd, unsigned long file_offset)
2143 ElfW(Ehdr) ehdr;
2144 ElfW(Shdr) *shdr, *sh;
2145 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2146 unsigned char *strsec, *strtab;
2147 int *old_to_new_syms;
2148 char *sh_name, *name;
2149 SectionMergeInfo *sm_table, *sm;
2150 ElfW(Sym) *sym, *symtab;
2151 ElfW_Rel *rel, *rel_end;
2152 Section *s;
2154 int stab_index;
2155 int stabstr_index;
2157 stab_index = stabstr_index = 0;
2159 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2160 goto fail1;
2161 if (ehdr.e_ident[0] != ELFMAG0 ||
2162 ehdr.e_ident[1] != ELFMAG1 ||
2163 ehdr.e_ident[2] != ELFMAG2 ||
2164 ehdr.e_ident[3] != ELFMAG3)
2165 goto fail1;
2166 /* test if object file */
2167 if (ehdr.e_type != ET_REL)
2168 goto fail1;
2169 /* test CPU specific stuff */
2170 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2171 ehdr.e_machine != EM_TCC_TARGET) {
2172 fail1:
2173 error_noabort("invalid object file");
2174 return -1;
2176 /* read sections */
2177 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2178 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2179 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2181 /* load section names */
2182 sh = &shdr[ehdr.e_shstrndx];
2183 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2185 /* load symtab and strtab */
2186 old_to_new_syms = NULL;
2187 symtab = NULL;
2188 strtab = NULL;
2189 nb_syms = 0;
2190 for(i = 1; i < ehdr.e_shnum; i++) {
2191 sh = &shdr[i];
2192 if (sh->sh_type == SHT_SYMTAB) {
2193 if (symtab) {
2194 error_noabort("object must contain only one symtab");
2195 fail:
2196 ret = -1;
2197 goto the_end;
2199 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2200 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2201 sm_table[i].s = symtab_section;
2203 /* now load strtab */
2204 sh = &shdr[sh->sh_link];
2205 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2209 /* now examine each section and try to merge its content with the
2210 ones in memory */
2211 for(i = 1; i < ehdr.e_shnum; i++) {
2212 /* no need to examine section name strtab */
2213 if (i == ehdr.e_shstrndx)
2214 continue;
2215 sh = &shdr[i];
2216 sh_name = strsec + sh->sh_name;
2217 /* ignore sections types we do not handle */
2218 if (sh->sh_type != SHT_PROGBITS &&
2219 sh->sh_type != SHT_RELX &&
2220 #ifdef TCC_ARM_EABI
2221 sh->sh_type != SHT_ARM_EXIDX &&
2222 #endif
2223 sh->sh_type != SHT_NOBITS &&
2224 strcmp(sh_name, ".stabstr")
2226 continue;
2227 if (sh->sh_addralign < 1)
2228 sh->sh_addralign = 1;
2229 /* find corresponding section, if any */
2230 for(j = 1; j < s1->nb_sections;j++) {
2231 s = s1->sections[j];
2232 if (!strcmp(s->name, sh_name)) {
2233 if (!strncmp(sh_name, ".gnu.linkonce",
2234 sizeof(".gnu.linkonce") - 1)) {
2235 /* if a 'linkonce' section is already present, we
2236 do not add it again. It is a little tricky as
2237 symbols can still be defined in
2238 it. */
2239 sm_table[i].link_once = 1;
2240 goto next;
2241 } else {
2242 goto found;
2246 /* not found: create new section */
2247 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2248 /* take as much info as possible from the section. sh_link and
2249 sh_info will be updated later */
2250 s->sh_addralign = sh->sh_addralign;
2251 s->sh_entsize = sh->sh_entsize;
2252 sm_table[i].new_section = 1;
2253 found:
2254 if (sh->sh_type != s->sh_type) {
2255 error_noabort("invalid section type");
2256 goto fail;
2259 /* align start of section */
2260 offset = s->data_offset;
2262 if (0 == strcmp(sh_name, ".stab")) {
2263 stab_index = i;
2264 goto no_align;
2266 if (0 == strcmp(sh_name, ".stabstr")) {
2267 stabstr_index = i;
2268 goto no_align;
2271 size = sh->sh_addralign - 1;
2272 offset = (offset + size) & ~size;
2273 if (sh->sh_addralign > s->sh_addralign)
2274 s->sh_addralign = sh->sh_addralign;
2275 s->data_offset = offset;
2276 no_align:
2277 sm_table[i].offset = offset;
2278 sm_table[i].s = s;
2279 /* concatenate sections */
2280 size = sh->sh_size;
2281 if (sh->sh_type != SHT_NOBITS) {
2282 unsigned char *ptr;
2283 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2284 ptr = section_ptr_add(s, size);
2285 read(fd, ptr, size);
2286 } else {
2287 s->data_offset += size;
2289 next: ;
2292 /* //gr relocate stab strings */
2293 if (stab_index && stabstr_index) {
2294 Stab_Sym *a, *b;
2295 unsigned o;
2296 s = sm_table[stab_index].s;
2297 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2298 b = (Stab_Sym *)(s->data + s->data_offset);
2299 o = sm_table[stabstr_index].offset;
2300 while (a < b)
2301 a->n_strx += o, a++;
2304 /* second short pass to update sh_link and sh_info fields of new
2305 sections */
2306 for(i = 1; i < ehdr.e_shnum; i++) {
2307 s = sm_table[i].s;
2308 if (!s || !sm_table[i].new_section)
2309 continue;
2310 sh = &shdr[i];
2311 if (sh->sh_link > 0)
2312 s->link = sm_table[sh->sh_link].s;
2313 if (sh->sh_type == SHT_RELX) {
2314 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2315 /* update backward link */
2316 s1->sections[s->sh_info]->reloc = s;
2319 sm = sm_table;
2321 /* resolve symbols */
2322 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2324 sym = symtab + 1;
2325 for(i = 1; i < nb_syms; i++, sym++) {
2326 if (sym->st_shndx != SHN_UNDEF &&
2327 sym->st_shndx < SHN_LORESERVE) {
2328 sm = &sm_table[sym->st_shndx];
2329 if (sm->link_once) {
2330 /* if a symbol is in a link once section, we use the
2331 already defined symbol. It is very important to get
2332 correct relocations */
2333 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2334 name = strtab + sym->st_name;
2335 sym_index = find_elf_sym(symtab_section, name);
2336 if (sym_index)
2337 old_to_new_syms[i] = sym_index;
2339 continue;
2341 /* if no corresponding section added, no need to add symbol */
2342 if (!sm->s)
2343 continue;
2344 /* convert section number */
2345 sym->st_shndx = sm->s->sh_num;
2346 /* offset value */
2347 sym->st_value += sm->offset;
2349 /* add symbol */
2350 name = strtab + sym->st_name;
2351 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2352 sym->st_info, sym->st_other,
2353 sym->st_shndx, name);
2354 old_to_new_syms[i] = sym_index;
2357 /* third pass to patch relocation entries */
2358 for(i = 1; i < ehdr.e_shnum; i++) {
2359 s = sm_table[i].s;
2360 if (!s)
2361 continue;
2362 sh = &shdr[i];
2363 offset = sm_table[i].offset;
2364 switch(s->sh_type) {
2365 case SHT_RELX:
2366 /* take relocation offset information */
2367 offseti = sm_table[sh->sh_info].offset;
2368 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2369 for(rel = (ElfW_Rel *)(s->data + offset);
2370 rel < rel_end;
2371 rel++) {
2372 int type;
2373 unsigned sym_index;
2374 /* convert symbol index */
2375 type = ELFW(R_TYPE)(rel->r_info);
2376 sym_index = ELFW(R_SYM)(rel->r_info);
2377 /* NOTE: only one symtab assumed */
2378 if (sym_index >= nb_syms)
2379 goto invalid_reloc;
2380 sym_index = old_to_new_syms[sym_index];
2381 /* ignore link_once in rel section. */
2382 if (!sym_index && !sm->link_once) {
2383 invalid_reloc:
2384 error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2385 i, strsec + sh->sh_name, rel->r_offset);
2386 goto fail;
2388 rel->r_info = ELFW(R_INFO)(sym_index, type);
2389 /* offset the relocation offset */
2390 rel->r_offset += offseti;
2392 break;
2393 default:
2394 break;
2398 ret = 0;
2399 the_end:
2400 tcc_free(symtab);
2401 tcc_free(strtab);
2402 tcc_free(old_to_new_syms);
2403 tcc_free(sm_table);
2404 tcc_free(strsec);
2405 tcc_free(shdr);
2406 return ret;
2409 typedef struct ArchiveHeader {
2410 char ar_name[16]; /* name of this member */
2411 char ar_date[12]; /* file mtime */
2412 char ar_uid[6]; /* owner uid; printed as decimal */
2413 char ar_gid[6]; /* owner gid; printed as decimal */
2414 char ar_mode[8]; /* file mode, printed as octal */
2415 char ar_size[10]; /* file size, printed as decimal */
2416 char ar_fmag[2]; /* should contain ARFMAG */
2417 } ArchiveHeader;
2419 static int get_be32(const uint8_t *b)
2421 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2424 /* load only the objects which resolve undefined symbols */
2425 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2427 int i, bound, nsyms, sym_index, off, ret;
2428 uint8_t *data;
2429 const char *ar_names, *p;
2430 const uint8_t *ar_index;
2431 ElfW(Sym) *sym;
2433 data = tcc_malloc(size);
2434 if (read(fd, data, size) != size)
2435 goto fail;
2436 nsyms = get_be32(data);
2437 ar_index = data + 4;
2438 ar_names = ar_index + nsyms * 4;
2440 do {
2441 bound = 0;
2442 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2443 sym_index = find_elf_sym(symtab_section, p);
2444 if(sym_index) {
2445 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2446 if(sym->st_shndx == SHN_UNDEF) {
2447 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2448 #if 0
2449 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2450 #endif
2451 ++bound;
2452 lseek(fd, off, SEEK_SET);
2453 if(tcc_load_object_file(s1, fd, off) < 0) {
2454 fail:
2455 ret = -1;
2456 goto the_end;
2461 } while(bound);
2462 ret = 0;
2463 the_end:
2464 tcc_free(data);
2465 return ret;
2468 /* load a '.a' file */
2469 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2471 ArchiveHeader hdr;
2472 char ar_size[11];
2473 char ar_name[17];
2474 char magic[8];
2475 int size, len, i;
2476 unsigned long file_offset;
2478 /* skip magic which was already checked */
2479 read(fd, magic, sizeof(magic));
2481 for(;;) {
2482 len = read(fd, &hdr, sizeof(hdr));
2483 if (len == 0)
2484 break;
2485 if (len != sizeof(hdr)) {
2486 error_noabort("invalid archive");
2487 return -1;
2489 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2490 ar_size[sizeof(hdr.ar_size)] = '\0';
2491 size = strtol(ar_size, NULL, 0);
2492 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2493 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2494 if (ar_name[i] != ' ')
2495 break;
2497 ar_name[i + 1] = '\0';
2498 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2499 file_offset = lseek(fd, 0, SEEK_CUR);
2500 /* align to even */
2501 size = (size + 1) & ~1;
2502 if (!strcmp(ar_name, "/")) {
2503 /* coff symbol table : we handle it */
2504 if(s1->alacarte_link)
2505 return tcc_load_alacarte(s1, fd, size);
2506 } else if (!strcmp(ar_name, "//") ||
2507 !strcmp(ar_name, "__.SYMDEF") ||
2508 !strcmp(ar_name, "__.SYMDEF/") ||
2509 !strcmp(ar_name, "ARFILENAMES/")) {
2510 /* skip symbol table or archive names */
2511 } else {
2512 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2513 return -1;
2515 lseek(fd, file_offset + size, SEEK_SET);
2517 return 0;
2520 #ifndef TCC_TARGET_PE
2521 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2522 is referenced by the user (so it should be added as DT_NEEDED in
2523 the generated ELF file) */
2524 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2526 ElfW(Ehdr) ehdr;
2527 ElfW(Shdr) *shdr, *sh, *sh1;
2528 int i, j, nb_syms, nb_dts, sym_bind, ret;
2529 ElfW(Sym) *sym, *dynsym;
2530 ElfW(Dyn) *dt, *dynamic;
2531 unsigned char *dynstr;
2532 const char *name, *soname;
2533 DLLReference *dllref;
2535 read(fd, &ehdr, sizeof(ehdr));
2537 /* test CPU specific stuff */
2538 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2539 ehdr.e_machine != EM_TCC_TARGET) {
2540 error_noabort("bad architecture");
2541 return -1;
2544 /* read sections */
2545 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2547 /* load dynamic section and dynamic symbols */
2548 nb_syms = 0;
2549 nb_dts = 0;
2550 dynamic = NULL;
2551 dynsym = NULL; /* avoid warning */
2552 dynstr = NULL; /* avoid warning */
2553 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2554 switch(sh->sh_type) {
2555 case SHT_DYNAMIC:
2556 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2557 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2558 break;
2559 case SHT_DYNSYM:
2560 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2561 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2562 sh1 = &shdr[sh->sh_link];
2563 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2564 break;
2565 default:
2566 break;
2570 /* compute the real library name */
2571 soname = tcc_basename(filename);
2573 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2574 if (dt->d_tag == DT_SONAME) {
2575 soname = dynstr + dt->d_un.d_val;
2579 /* if the dll is already loaded, do not load it */
2580 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2581 dllref = s1->loaded_dlls[i];
2582 if (!strcmp(soname, dllref->name)) {
2583 /* but update level if needed */
2584 if (level < dllref->level)
2585 dllref->level = level;
2586 ret = 0;
2587 goto the_end;
2591 // printf("loading dll '%s'\n", soname);
2593 /* add the dll and its level */
2594 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2595 dllref->level = level;
2596 strcpy(dllref->name, soname);
2597 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2599 /* add dynamic symbols in dynsym_section */
2600 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2601 sym_bind = ELFW(ST_BIND)(sym->st_info);
2602 if (sym_bind == STB_LOCAL)
2603 continue;
2604 name = dynstr + sym->st_name;
2605 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2606 sym->st_info, sym->st_other, sym->st_shndx, name);
2609 /* load all referenced DLLs */
2610 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2611 switch(dt->d_tag) {
2612 case DT_NEEDED:
2613 name = dynstr + dt->d_un.d_val;
2614 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2615 dllref = s1->loaded_dlls[j];
2616 if (!strcmp(name, dllref->name))
2617 goto already_loaded;
2619 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2620 error_noabort("referenced dll '%s' not found", name);
2621 ret = -1;
2622 goto the_end;
2624 already_loaded:
2625 break;
2628 ret = 0;
2629 the_end:
2630 tcc_free(dynstr);
2631 tcc_free(dynsym);
2632 tcc_free(dynamic);
2633 tcc_free(shdr);
2634 return ret;
2637 #define LD_TOK_NAME 256
2638 #define LD_TOK_EOF (-1)
2640 /* return next ld script token */
2641 static int ld_next(TCCState *s1, char *name, int name_size)
2643 int c;
2644 char *q;
2646 redo:
2647 switch(ch) {
2648 case ' ':
2649 case '\t':
2650 case '\f':
2651 case '\v':
2652 case '\r':
2653 case '\n':
2654 inp();
2655 goto redo;
2656 case '/':
2657 minp();
2658 if (ch == '*') {
2659 file->buf_ptr = parse_comment(file->buf_ptr);
2660 ch = file->buf_ptr[0];
2661 goto redo;
2662 } else {
2663 q = name;
2664 *q++ = '/';
2665 goto parse_name;
2667 break;
2668 /* case 'a' ... 'z': */
2669 case 'a':
2670 case 'b':
2671 case 'c':
2672 case 'd':
2673 case 'e':
2674 case 'f':
2675 case 'g':
2676 case 'h':
2677 case 'i':
2678 case 'j':
2679 case 'k':
2680 case 'l':
2681 case 'm':
2682 case 'n':
2683 case 'o':
2684 case 'p':
2685 case 'q':
2686 case 'r':
2687 case 's':
2688 case 't':
2689 case 'u':
2690 case 'v':
2691 case 'w':
2692 case 'x':
2693 case 'y':
2694 case 'z':
2695 /* case 'A' ... 'z': */
2696 case 'A':
2697 case 'B':
2698 case 'C':
2699 case 'D':
2700 case 'E':
2701 case 'F':
2702 case 'G':
2703 case 'H':
2704 case 'I':
2705 case 'J':
2706 case 'K':
2707 case 'L':
2708 case 'M':
2709 case 'N':
2710 case 'O':
2711 case 'P':
2712 case 'Q':
2713 case 'R':
2714 case 'S':
2715 case 'T':
2716 case 'U':
2717 case 'V':
2718 case 'W':
2719 case 'X':
2720 case 'Y':
2721 case 'Z':
2722 case '_':
2723 case '\\':
2724 case '.':
2725 case '$':
2726 case '~':
2727 q = name;
2728 parse_name:
2729 for(;;) {
2730 if (!((ch >= 'a' && ch <= 'z') ||
2731 (ch >= 'A' && ch <= 'Z') ||
2732 (ch >= '0' && ch <= '9') ||
2733 strchr("/.-_+=$:\\,~", ch)))
2734 break;
2735 if ((q - name) < name_size - 1) {
2736 *q++ = ch;
2738 minp();
2740 *q = '\0';
2741 c = LD_TOK_NAME;
2742 break;
2743 case CH_EOF:
2744 c = LD_TOK_EOF;
2745 break;
2746 default:
2747 c = ch;
2748 inp();
2749 break;
2751 #if 0
2752 printf("tok=%c %d\n", c, c);
2753 if (c == LD_TOK_NAME)
2754 printf(" name=%s\n", name);
2755 #endif
2756 return c;
2759 static int ld_add_file_list(TCCState *s1, int as_needed)
2761 char filename[1024];
2762 int t, ret;
2764 t = ld_next(s1, filename, sizeof(filename));
2765 if (t != '(')
2766 expect("(");
2767 t = ld_next(s1, filename, sizeof(filename));
2768 for(;;) {
2769 if (t == LD_TOK_EOF) {
2770 error_noabort("unexpected end of file");
2771 return -1;
2772 } else if (t == ')') {
2773 break;
2774 } else if (t != LD_TOK_NAME) {
2775 error_noabort("filename expected");
2776 return -1;
2778 if (!strcmp(filename, "AS_NEEDED")) {
2779 ret = ld_add_file_list(s1, 1);
2780 if (ret)
2781 return ret;
2782 } else {
2783 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2784 if (!as_needed)
2785 tcc_add_file(s1, filename);
2787 t = ld_next(s1, filename, sizeof(filename));
2788 if (t == ',') {
2789 t = ld_next(s1, filename, sizeof(filename));
2792 return 0;
2795 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
2796 files */
2797 ST_FUNC int tcc_load_ldscript(TCCState *s1)
2799 char cmd[64];
2800 char filename[1024];
2801 int t, ret;
2803 ch = file->buf_ptr[0];
2804 ch = handle_eob();
2805 for(;;) {
2806 t = ld_next(s1, cmd, sizeof(cmd));
2807 if (t == LD_TOK_EOF)
2808 return 0;
2809 else if (t != LD_TOK_NAME)
2810 return -1;
2811 if (!strcmp(cmd, "INPUT") ||
2812 !strcmp(cmd, "GROUP")) {
2813 ret = ld_add_file_list(s1, 0);
2814 if (ret)
2815 return ret;
2816 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
2817 !strcmp(cmd, "TARGET")) {
2818 /* ignore some commands */
2819 t = ld_next(s1, cmd, sizeof(cmd));
2820 if (t != '(')
2821 expect("(");
2822 for(;;) {
2823 t = ld_next(s1, filename, sizeof(filename));
2824 if (t == LD_TOK_EOF) {
2825 error_noabort("unexpected end of file");
2826 return -1;
2827 } else if (t == ')') {
2828 break;
2831 } else {
2832 return -1;
2835 return 0;
2837 #endif