add binary executable output support
[tinycc/kirr.git] / tccelf.c
blobe87f2be585c34eb72018704ff98503d16b5993c2
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 #ifdef TCC_TARGET_X86_64
22 #define ElfW_Rel ElfW(Rela)
23 #define SHT_RELX SHT_RELA
24 #define REL_SECTION_FMT ".rela%s"
25 /* x86-64 requires PLT for DLLs */
26 #define TCC_OUTPUT_DLL_WITH_PLT
27 #else
28 #define ElfW_Rel ElfW(Rel)
29 #define SHT_RELX SHT_REL
30 #define REL_SECTION_FMT ".rel%s"
31 #endif
33 /* XXX: DLL with PLT would only work with x86-64 for now */
34 //#define TCC_OUTPUT_DLL_WITH_PLT
36 static int put_elf_str(Section *s, const char *sym)
38 int offset, len;
39 char *ptr;
41 len = strlen(sym) + 1;
42 offset = s->data_offset;
43 ptr = section_ptr_add(s, len);
44 memcpy(ptr, sym, len);
45 return offset;
48 /* elf symbol hashing function */
49 static unsigned long elf_hash(const unsigned char *name)
51 unsigned long h = 0, g;
53 while (*name) {
54 h = (h << 4) + *name++;
55 g = h & 0xf0000000;
56 if (g)
57 h ^= g >> 24;
58 h &= ~g;
60 return h;
63 /* rebuild hash table of section s */
64 /* NOTE: we do factorize the hash table code to go faster */
65 static void rebuild_hash(Section *s, unsigned int nb_buckets)
67 ElfW(Sym) *sym;
68 int *ptr, *hash, nb_syms, sym_index, h;
69 char *strtab;
71 strtab = s->link->data;
72 nb_syms = s->data_offset / sizeof(ElfW(Sym));
74 s->hash->data_offset = 0;
75 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
76 ptr[0] = nb_buckets;
77 ptr[1] = nb_syms;
78 ptr += 2;
79 hash = ptr;
80 memset(hash, 0, (nb_buckets + 1) * sizeof(int));
81 ptr += nb_buckets + 1;
83 sym = (ElfW(Sym) *)s->data + 1;
84 for(sym_index = 1; sym_index < nb_syms; sym_index++) {
85 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
86 h = elf_hash(strtab + sym->st_name) % nb_buckets;
87 *ptr = hash[h];
88 hash[h] = sym_index;
89 } else {
90 *ptr = 0;
92 ptr++;
93 sym++;
97 /* return the symbol number */
98 static int put_elf_sym(Section *s,
99 unsigned long value, unsigned long size,
100 int info, int other, int shndx, const char *name)
102 int name_offset, sym_index;
103 int nbuckets, h;
104 ElfW(Sym) *sym;
105 Section *hs;
107 sym = section_ptr_add(s, sizeof(ElfW(Sym)));
108 if (name)
109 name_offset = put_elf_str(s->link, name);
110 else
111 name_offset = 0;
112 /* XXX: endianness */
113 sym->st_name = name_offset;
114 sym->st_value = value;
115 sym->st_size = size;
116 sym->st_info = info;
117 sym->st_other = other;
118 sym->st_shndx = shndx;
119 sym_index = sym - (ElfW(Sym) *)s->data;
120 hs = s->hash;
121 if (hs) {
122 int *ptr, *base;
123 ptr = section_ptr_add(hs, sizeof(int));
124 base = (int *)hs->data;
125 /* only add global or weak symbols */
126 if (ELFW(ST_BIND)(info) != STB_LOCAL) {
127 /* add another hashing entry */
128 nbuckets = base[0];
129 h = elf_hash(name) % nbuckets;
130 *ptr = base[2 + h];
131 base[2 + h] = sym_index;
132 base[1]++;
133 /* we resize the hash table */
134 hs->nb_hashed_syms++;
135 if (hs->nb_hashed_syms > 2 * nbuckets) {
136 rebuild_hash(s, 2 * nbuckets);
138 } else {
139 *ptr = 0;
140 base[1]++;
143 return sym_index;
146 /* find global ELF symbol 'name' and return its index. Return 0 if not
147 found. */
148 static int find_elf_sym(Section *s, const char *name)
150 ElfW(Sym) *sym;
151 Section *hs;
152 int nbuckets, sym_index, h;
153 const char *name1;
155 hs = s->hash;
156 if (!hs)
157 return 0;
158 nbuckets = ((int *)hs->data)[0];
159 h = elf_hash(name) % nbuckets;
160 sym_index = ((int *)hs->data)[2 + h];
161 while (sym_index != 0) {
162 sym = &((ElfW(Sym) *)s->data)[sym_index];
163 name1 = s->link->data + sym->st_name;
164 if (!strcmp(name, name1))
165 return sym_index;
166 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
168 return 0;
171 /* return elf symbol value, signal error if 'err' is nonzero */
172 static void *get_elf_sym_addr(TCCState *s, const char *name, int err)
174 int sym_index;
175 ElfW(Sym) *sym;
177 sym_index = find_elf_sym(symtab_section, name);
178 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
179 if (!sym_index || sym->st_shndx == SHN_UNDEF) {
180 if (err)
181 error("%s not defined", name);
182 return NULL;
184 return (void*)(uplong)sym->st_value;
187 /* return elf symbol value */
188 void *tcc_get_symbol(TCCState *s, const char *name)
190 return get_elf_sym_addr(s, name, 0);
193 /* return elf symbol value or error */
194 void *tcc_get_symbol_err(TCCState *s, const char *name)
196 return get_elf_sym_addr(s, name, 1);
199 /* add an elf symbol : check if it is already defined and patch
200 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
201 static int add_elf_sym(Section *s, uplong value, unsigned long size,
202 int info, int other, int sh_num, const char *name)
204 ElfW(Sym) *esym;
205 int sym_bind, sym_index, sym_type, esym_bind;
206 unsigned char sym_vis, esym_vis, new_vis;
208 sym_bind = ELFW(ST_BIND)(info);
209 sym_type = ELFW(ST_TYPE)(info);
210 sym_vis = ELFW(ST_VISIBILITY)(other);
212 if (sym_bind != STB_LOCAL) {
213 /* we search global or weak symbols */
214 sym_index = find_elf_sym(s, name);
215 if (!sym_index)
216 goto do_def;
217 esym = &((ElfW(Sym) *)s->data)[sym_index];
218 if (esym->st_shndx != SHN_UNDEF) {
219 esym_bind = ELFW(ST_BIND)(esym->st_info);
220 /* propagate the most constraining visibility */
221 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
222 esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
223 if (esym_vis == STV_DEFAULT) {
224 new_vis = sym_vis;
225 } else if (sym_vis == STV_DEFAULT) {
226 new_vis = esym_vis;
227 } else {
228 new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
230 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
231 | new_vis;
232 other = esym->st_other; /* in case we have to patch esym */
233 if (sh_num == SHN_UNDEF) {
234 /* ignore adding of undefined symbol if the
235 corresponding symbol is already defined */
236 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
237 /* global overrides weak, so patch */
238 goto do_patch;
239 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
240 /* weak is ignored if already global */
241 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
242 /* ignore hidden symbols after */
243 } else if (esym->st_shndx == SHN_COMMON
244 && (sh_num < SHN_LORESERVE || sh_num == SHN_COMMON)) {
245 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
246 No idea if this is the correct solution ... */
247 goto do_patch;
248 } else if (s == tcc_state->dynsymtab_section) {
249 /* we accept that two DLL define the same symbol */
250 } else {
251 #if 1
252 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
253 sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
254 #endif
255 error_noabort("'%s' defined twice", name);
257 } else {
258 do_patch:
259 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
260 esym->st_shndx = sh_num;
261 esym->st_value = value;
262 esym->st_size = size;
263 esym->st_other = other;
265 } else {
266 do_def:
267 sym_index = put_elf_sym(s, value, size,
268 ELFW(ST_INFO)(sym_bind, sym_type), other,
269 sh_num, name);
271 return sym_index;
274 /* put relocation */
275 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
276 int type, int symbol)
278 char buf[256];
279 Section *sr;
280 ElfW_Rel *rel;
282 sr = s->reloc;
283 if (!sr) {
284 /* if no relocation section, create it */
285 snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
286 /* if the symtab is allocated, then we consider the relocation
287 are also */
288 sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
289 sr->sh_entsize = sizeof(ElfW_Rel);
290 sr->link = symtab;
291 sr->sh_info = s->sh_num;
292 s->reloc = sr;
294 rel = section_ptr_add(sr, sizeof(ElfW_Rel));
295 rel->r_offset = offset;
296 rel->r_info = ELFW(R_INFO)(symbol, type);
297 #ifdef TCC_TARGET_X86_64
298 rel->r_addend = 0;
299 #endif
302 /* put stab debug information */
304 typedef struct {
305 unsigned int n_strx; /* index into string table of name */
306 unsigned char n_type; /* type of symbol */
307 unsigned char n_other; /* misc info (usually empty) */
308 unsigned short n_desc; /* description field */
309 unsigned int n_value; /* value of symbol */
310 } Stab_Sym;
312 static void put_stabs(const char *str, int type, int other, int desc,
313 unsigned long value)
315 Stab_Sym *sym;
317 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
318 if (str) {
319 sym->n_strx = put_elf_str(stabstr_section, str);
320 } else {
321 sym->n_strx = 0;
323 sym->n_type = type;
324 sym->n_other = other;
325 sym->n_desc = desc;
326 sym->n_value = value;
329 static void put_stabs_r(const char *str, int type, int other, int desc,
330 unsigned long value, Section *sec, int sym_index)
332 put_stabs(str, type, other, desc, value);
333 put_elf_reloc(symtab_section, stab_section,
334 stab_section->data_offset - sizeof(unsigned int),
335 R_DATA_32, sym_index);
338 static void put_stabn(int type, int other, int desc, int value)
340 put_stabs(NULL, type, other, desc, value);
343 static void put_stabd(int type, int other, int desc)
345 put_stabs(NULL, type, other, desc, 0);
348 /* In an ELF file symbol table, the local symbols must appear below
349 the global and weak ones. Since TCC cannot sort it while generating
350 the code, we must do it after. All the relocation tables are also
351 modified to take into account the symbol table sorting */
352 static void sort_syms(TCCState *s1, Section *s)
354 int *old_to_new_syms;
355 ElfW(Sym) *new_syms;
356 int nb_syms, i;
357 ElfW(Sym) *p, *q;
358 ElfW_Rel *rel, *rel_end;
359 Section *sr;
360 int type, sym_index;
362 nb_syms = s->data_offset / sizeof(ElfW(Sym));
363 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
364 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
366 /* first pass for local symbols */
367 p = (ElfW(Sym) *)s->data;
368 q = new_syms;
369 for(i = 0; i < nb_syms; i++) {
370 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
371 old_to_new_syms[i] = q - new_syms;
372 *q++ = *p;
374 p++;
376 /* save the number of local symbols in section header */
377 s->sh_info = q - new_syms;
379 /* then second pass for non local symbols */
380 p = (ElfW(Sym) *)s->data;
381 for(i = 0; i < nb_syms; i++) {
382 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
383 old_to_new_syms[i] = q - new_syms;
384 *q++ = *p;
386 p++;
389 /* we copy the new symbols to the old */
390 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
391 tcc_free(new_syms);
393 /* now we modify all the relocations */
394 for(i = 1; i < s1->nb_sections; i++) {
395 sr = s1->sections[i];
396 if (sr->sh_type == SHT_RELX && sr->link == s) {
397 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
398 for(rel = (ElfW_Rel *)sr->data;
399 rel < rel_end;
400 rel++) {
401 sym_index = ELFW(R_SYM)(rel->r_info);
402 type = ELFW(R_TYPE)(rel->r_info);
403 sym_index = old_to_new_syms[sym_index];
404 rel->r_info = ELFW(R_INFO)(sym_index, type);
409 tcc_free(old_to_new_syms);
412 /* relocate common symbols in the .bss section */
413 static void relocate_common_syms(void)
415 ElfW(Sym) *sym, *sym_end;
416 unsigned long offset, align;
418 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
419 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
420 sym < sym_end;
421 sym++) {
422 if (sym->st_shndx == SHN_COMMON) {
423 /* align symbol */
424 align = sym->st_value;
425 offset = bss_section->data_offset;
426 offset = (offset + align - 1) & -align;
427 sym->st_value = offset;
428 sym->st_shndx = bss_section->sh_num;
429 offset += sym->st_size;
430 bss_section->data_offset = offset;
435 /* relocate symbol table, resolve undefined symbols if do_resolve is
436 true and output error if undefined symbol. */
437 static void relocate_syms(TCCState *s1, int do_resolve)
439 ElfW(Sym) *sym, *esym, *sym_end;
440 int sym_bind, sh_num, sym_index;
441 const char *name;
443 sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
444 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
445 sym < sym_end;
446 sym++) {
447 sh_num = sym->st_shndx;
448 if (sh_num == SHN_UNDEF) {
449 name = strtab_section->data + sym->st_name;
450 if (do_resolve) {
451 #ifndef _WIN32
452 void *addr;
453 name = symtab_section->link->data + sym->st_name;
454 addr = resolve_sym(s1, name);
455 if (addr) {
456 sym->st_value = (uplong)addr;
457 goto found;
459 #endif
460 } else if (s1->dynsym) {
461 /* if dynamic symbol exist, then use it */
462 sym_index = find_elf_sym(s1->dynsym, name);
463 if (sym_index) {
464 esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
465 sym->st_value = esym->st_value;
466 goto found;
469 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
470 it */
471 if (!strcmp(name, "_fp_hw"))
472 goto found;
473 /* only weak symbols are accepted to be undefined. Their
474 value is zero */
475 sym_bind = ELFW(ST_BIND)(sym->st_info);
476 if (sym_bind == STB_WEAK) {
477 sym->st_value = 0;
478 } else {
479 error_noabort("undefined symbol '%s'", name);
481 } else if (sh_num < SHN_LORESERVE) {
482 /* add section base */
483 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
485 found: ;
489 #ifndef TCC_TARGET_PE
490 #ifdef TCC_TARGET_X86_64
491 #define JMP_TABLE_ENTRY_SIZE 14
492 static unsigned long add_jmp_table(TCCState *s1, unsigned long val)
494 char *p = s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset;
495 s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
496 /* jmp *0x0(%rip) */
497 p[0] = 0xff;
498 p[1] = 0x25;
499 *(int *)(p + 2) = 0;
500 *(unsigned long *)(p + 6) = val;
501 return (unsigned long)p;
504 static unsigned long add_got_table(TCCState *s1, unsigned long val)
506 unsigned long *p =(unsigned long *)(s1->runtime_plt_and_got +
507 s1->runtime_plt_and_got_offset);
508 s1->runtime_plt_and_got_offset += sizeof(void *);
509 *p = val;
510 return (unsigned long)p;
512 #endif
513 #endif
515 /* relocate a given section (CPU dependent) */
516 static void relocate_section(TCCState *s1, Section *s)
518 Section *sr;
519 ElfW_Rel *rel, *rel_end, *qrel;
520 ElfW(Sym) *sym;
521 int type, sym_index;
522 unsigned char *ptr;
523 unsigned long val, addr;
524 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
525 int esym_index;
526 #endif
528 sr = s->reloc;
529 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
530 qrel = (ElfW_Rel *)sr->data;
531 for(rel = qrel;
532 rel < rel_end;
533 rel++) {
534 ptr = s->data + rel->r_offset;
536 sym_index = ELFW(R_SYM)(rel->r_info);
537 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
538 val = sym->st_value;
539 #ifdef TCC_TARGET_X86_64
540 /* XXX: not tested */
541 val += rel->r_addend;
542 #endif
543 type = ELFW(R_TYPE)(rel->r_info);
544 addr = s->sh_addr + rel->r_offset;
546 /* CPU specific */
547 switch(type) {
548 #if defined(TCC_TARGET_I386)
549 case R_386_32:
550 if (s1->output_type == TCC_OUTPUT_DLL) {
551 esym_index = s1->symtab_to_dynsym[sym_index];
552 qrel->r_offset = rel->r_offset;
553 if (esym_index) {
554 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
555 qrel++;
556 break;
557 } else {
558 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
559 qrel++;
562 *(int *)ptr += val;
563 break;
564 case R_386_PC32:
565 if (s1->output_type == TCC_OUTPUT_DLL) {
566 /* DLL relocation */
567 esym_index = s1->symtab_to_dynsym[sym_index];
568 if (esym_index) {
569 qrel->r_offset = rel->r_offset;
570 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
571 qrel++;
572 break;
575 *(int *)ptr += val - addr;
576 break;
577 case R_386_PLT32:
578 *(int *)ptr += val - addr;
579 break;
580 case R_386_GLOB_DAT:
581 case R_386_JMP_SLOT:
582 *(int *)ptr = val;
583 break;
584 case R_386_GOTPC:
585 *(int *)ptr += s1->got->sh_addr - addr;
586 break;
587 case R_386_GOTOFF:
588 *(int *)ptr += val - s1->got->sh_addr;
589 break;
590 case R_386_GOT32:
591 /* we load the got offset */
592 *(int *)ptr += s1->got_offsets[sym_index];
593 break;
594 #elif defined(TCC_TARGET_ARM)
595 case R_ARM_PC24:
596 case R_ARM_CALL:
597 case R_ARM_JUMP24:
598 case R_ARM_PLT32:
600 int x;
601 x = (*(int *)ptr)&0xffffff;
602 (*(int *)ptr) &= 0xff000000;
603 if (x & 0x800000)
604 x -= 0x1000000;
605 x *= 4;
606 x += val - addr;
607 if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
608 error("can't relocate value at %x",addr);
609 x >>= 2;
610 x &= 0xffffff;
611 (*(int *)ptr) |= x;
613 break;
614 case R_ARM_PREL31:
616 int x;
617 x = (*(int *)ptr) & 0x7fffffff;
618 (*(int *)ptr) &= 0x80000000;
619 x = (x * 2) / 2;
620 x += val - addr;
621 if((x^(x>>1))&0x40000000)
622 error("can't relocate value at %x",addr);
623 (*(int *)ptr) |= x & 0x7fffffff;
625 case R_ARM_ABS32:
626 *(int *)ptr += val;
627 break;
628 case R_ARM_BASE_PREL:
629 *(int *)ptr += s1->got->sh_addr - addr;
630 break;
631 case R_ARM_GOTOFF32:
632 *(int *)ptr += val - s1->got->sh_addr;
633 break;
634 case R_ARM_GOT_BREL:
635 /* we load the got offset */
636 *(int *)ptr += s1->got_offsets[sym_index];
637 break;
638 case R_ARM_COPY:
639 break;
640 default:
641 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
642 type,addr,(unsigned int)(long)ptr,val);
643 break;
644 #elif defined(TCC_TARGET_C67)
645 case R_C60_32:
646 *(int *)ptr += val;
647 break;
648 case R_C60LO16:
650 uint32_t orig;
652 /* put the low 16 bits of the absolute address */
653 // add to what is already there
655 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
656 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
658 //patch both at once - assumes always in pairs Low - High
660 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
661 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
663 break;
664 case R_C60HI16:
665 break;
666 default:
667 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
668 type,addr,(unsigned int)(long)ptr, val);
669 break;
670 #elif defined(TCC_TARGET_X86_64)
671 case R_X86_64_64:
672 if (s1->output_type == TCC_OUTPUT_DLL) {
673 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
674 qrel->r_addend = *(long long *)ptr + val;
675 qrel++;
677 *(long long *)ptr += val;
678 break;
679 case R_X86_64_32:
680 case R_X86_64_32S:
681 if (s1->output_type == TCC_OUTPUT_DLL) {
682 /* XXX: this logic may depend on TCC's codegen
683 now TCC uses R_X86_64_32 even for a 64bit pointer */
684 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
685 qrel->r_addend = *(int *)ptr + val;
686 qrel++;
688 *(int *)ptr += val;
689 break;
690 case R_X86_64_PC32: {
691 long long diff;
692 if (s1->output_type == TCC_OUTPUT_DLL) {
693 /* DLL relocation */
694 esym_index = s1->symtab_to_dynsym[sym_index];
695 if (esym_index) {
696 qrel->r_offset = rel->r_offset;
697 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
698 qrel->r_addend = *(int *)ptr;
699 qrel++;
700 break;
703 diff = (long long)val - addr;
704 if (diff <= -2147483647 || diff > 2147483647) {
705 #ifndef TCC_TARGET_PE
706 /* XXX: naive support for over 32bit jump */
707 if (s1->output_type == TCC_OUTPUT_MEMORY) {
708 val = add_jmp_table(s1, val);
709 diff = val - addr;
711 #endif
712 if (diff <= -2147483647 || diff > 2147483647) {
713 error("internal error: relocation failed");
716 *(int *)ptr += diff;
718 break;
719 case R_X86_64_PLT32:
720 *(int *)ptr += val - addr;
721 break;
722 case R_X86_64_GLOB_DAT:
723 case R_X86_64_JUMP_SLOT:
724 *(int *)ptr = val;
725 break;
726 case R_X86_64_GOTPCREL:
727 #ifndef TCC_TARGET_PE
728 if (s1->output_type == TCC_OUTPUT_MEMORY) {
729 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
730 *(int *)ptr += val - addr;
731 break;
733 #endif
734 *(int *)ptr += (s1->got->sh_addr - addr +
735 s1->got_offsets[sym_index] - 4);
736 break;
737 case R_X86_64_GOTTPOFF:
738 *(int *)ptr += val - s1->got->sh_addr;
739 break;
740 case R_X86_64_GOT32:
741 /* we load the got offset */
742 *(int *)ptr += s1->got_offsets[sym_index];
743 break;
744 #else
745 #error unsupported processor
746 #endif
749 /* if the relocation is allocated, we change its symbol table */
750 if (sr->sh_flags & SHF_ALLOC)
751 sr->link = s1->dynsym;
754 /* relocate relocation table in 'sr' */
755 static void relocate_rel(TCCState *s1, Section *sr)
757 Section *s;
758 ElfW_Rel *rel, *rel_end;
760 s = s1->sections[sr->sh_info];
761 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
762 for(rel = (ElfW_Rel *)sr->data;
763 rel < rel_end;
764 rel++) {
765 rel->r_offset += s->sh_addr;
769 /* count the number of dynamic relocations so that we can reserve
770 their space */
771 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
773 ElfW_Rel *rel, *rel_end;
774 int sym_index, esym_index, type, count;
776 count = 0;
777 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
778 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
779 sym_index = ELFW(R_SYM)(rel->r_info);
780 type = ELFW(R_TYPE)(rel->r_info);
781 switch(type) {
782 #if defined(TCC_TARGET_I386)
783 case R_386_32:
784 #elif defined(TCC_TARGET_X86_64)
785 case R_X86_64_32:
786 case R_X86_64_32S:
787 case R_X86_64_64:
788 #endif
789 count++;
790 break;
791 #if defined(TCC_TARGET_I386)
792 case R_386_PC32:
793 #elif defined(TCC_TARGET_X86_64)
794 case R_X86_64_PC32:
795 #endif
796 esym_index = s1->symtab_to_dynsym[sym_index];
797 if (esym_index)
798 count++;
799 break;
800 default:
801 break;
804 if (count) {
805 /* allocate the section */
806 sr->sh_flags |= SHF_ALLOC;
807 sr->sh_size = count * sizeof(ElfW_Rel);
809 return count;
812 static void put_got_offset(TCCState *s1, int index, unsigned long val)
814 int n;
815 unsigned long *tab;
817 if (index >= s1->nb_got_offsets) {
818 /* find immediately bigger power of 2 and reallocate array */
819 n = 1;
820 while (index >= n)
821 n *= 2;
822 tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
823 if (!tab)
824 error("memory full");
825 s1->got_offsets = tab;
826 memset(s1->got_offsets + s1->nb_got_offsets, 0,
827 (n - s1->nb_got_offsets) * sizeof(unsigned long));
828 s1->nb_got_offsets = n;
830 s1->got_offsets[index] = val;
833 /* XXX: suppress that */
834 static void put32(unsigned char *p, uint32_t val)
836 p[0] = val;
837 p[1] = val >> 8;
838 p[2] = val >> 16;
839 p[3] = val >> 24;
842 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
843 defined(TCC_TARGET_X86_64)
844 static uint32_t get32(unsigned char *p)
846 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
848 #endif
850 static void build_got(TCCState *s1)
852 unsigned char *ptr;
854 /* if no got, then create it */
855 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
856 s1->got->sh_entsize = 4;
857 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
858 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
859 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
860 #if PTR_SIZE == 4
861 /* keep space for _DYNAMIC pointer, if present */
862 put32(ptr, 0);
863 /* two dummy got entries */
864 put32(ptr + 4, 0);
865 put32(ptr + 8, 0);
866 #else
867 /* keep space for _DYNAMIC pointer, if present */
868 put32(ptr, 0);
869 put32(ptr + 4, 0);
870 /* two dummy got entries */
871 put32(ptr + 8, 0);
872 put32(ptr + 12, 0);
873 put32(ptr + 16, 0);
874 put32(ptr + 20, 0);
875 #endif
878 /* put a got entry corresponding to a symbol in symtab_section. 'size'
879 and 'info' can be modifed if more precise info comes from the DLL */
880 static void put_got_entry(TCCState *s1,
881 int reloc_type, unsigned long size, int info,
882 int sym_index)
884 int index;
885 const char *name;
886 ElfW(Sym) *sym;
887 unsigned long offset;
888 int *ptr;
890 if (!s1->got)
891 build_got(s1);
893 /* if a got entry already exists for that symbol, no need to add one */
894 if (sym_index < s1->nb_got_offsets &&
895 s1->got_offsets[sym_index] != 0)
896 return;
898 put_got_offset(s1, sym_index, s1->got->data_offset);
900 if (s1->dynsym) {
901 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
902 name = symtab_section->link->data + sym->st_name;
903 offset = sym->st_value;
904 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
905 if (reloc_type ==
906 #ifdef TCC_TARGET_X86_64
907 R_X86_64_JUMP_SLOT
908 #else
909 R_386_JMP_SLOT
910 #endif
912 Section *plt;
913 uint8_t *p;
914 int modrm;
916 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
917 modrm = 0x25;
918 #else
919 /* if we build a DLL, we add a %ebx offset */
920 if (s1->output_type == TCC_OUTPUT_DLL)
921 modrm = 0xa3;
922 else
923 modrm = 0x25;
924 #endif
926 /* add a PLT entry */
927 plt = s1->plt;
928 if (plt->data_offset == 0) {
929 /* first plt entry */
930 p = section_ptr_add(plt, 16);
931 p[0] = 0xff; /* pushl got + PTR_SIZE */
932 p[1] = modrm + 0x10;
933 put32(p + 2, PTR_SIZE);
934 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
935 p[7] = modrm;
936 put32(p + 8, PTR_SIZE * 2);
939 p = section_ptr_add(plt, 16);
940 p[0] = 0xff; /* jmp *(got + x) */
941 p[1] = modrm;
942 put32(p + 2, s1->got->data_offset);
943 p[6] = 0x68; /* push $xxx */
944 put32(p + 7, (plt->data_offset - 32) >> 1);
945 p[11] = 0xe9; /* jmp plt_start */
946 put32(p + 12, -(plt->data_offset));
948 /* the symbol is modified so that it will be relocated to
949 the PLT */
950 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
951 if (s1->output_type == TCC_OUTPUT_EXE)
952 #endif
953 offset = plt->data_offset - 16;
955 #elif defined(TCC_TARGET_ARM)
956 if (reloc_type == R_ARM_JUMP_SLOT) {
957 Section *plt;
958 uint8_t *p;
960 /* if we build a DLL, we add a %ebx offset */
961 if (s1->output_type == TCC_OUTPUT_DLL)
962 error("DLLs unimplemented!");
964 /* add a PLT entry */
965 plt = s1->plt;
966 if (plt->data_offset == 0) {
967 /* first plt entry */
968 p = section_ptr_add(plt, 16);
969 put32(p , 0xe52de004);
970 put32(p + 4, 0xe59fe010);
971 put32(p + 8, 0xe08fe00e);
972 put32(p + 12, 0xe5bef008);
975 p = section_ptr_add(plt, 16);
976 put32(p , 0xe59fc004);
977 put32(p+4, 0xe08fc00c);
978 put32(p+8, 0xe59cf000);
979 put32(p+12, s1->got->data_offset);
981 /* the symbol is modified so that it will be relocated to
982 the PLT */
983 if (s1->output_type == TCC_OUTPUT_EXE)
984 offset = plt->data_offset - 16;
986 #elif defined(TCC_TARGET_C67)
987 error("C67 got not implemented");
988 #else
989 #error unsupported CPU
990 #endif
991 index = put_elf_sym(s1->dynsym, offset,
992 size, info, 0, sym->st_shndx, name);
993 /* put a got entry */
994 put_elf_reloc(s1->dynsym, s1->got,
995 s1->got->data_offset,
996 reloc_type, index);
998 ptr = section_ptr_add(s1->got, PTR_SIZE);
999 *ptr = 0;
1002 /* build GOT and PLT entries */
1003 static void build_got_entries(TCCState *s1)
1005 Section *s, *symtab;
1006 ElfW_Rel *rel, *rel_end;
1007 ElfW(Sym) *sym;
1008 int i, type, reloc_type, sym_index;
1010 for(i = 1; i < s1->nb_sections; i++) {
1011 s = s1->sections[i];
1012 if (s->sh_type != SHT_RELX)
1013 continue;
1014 /* no need to handle got relocations */
1015 if (s->link != symtab_section)
1016 continue;
1017 symtab = s->link;
1018 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1019 for(rel = (ElfW_Rel *)s->data;
1020 rel < rel_end;
1021 rel++) {
1022 type = ELFW(R_TYPE)(rel->r_info);
1023 switch(type) {
1024 #if defined(TCC_TARGET_I386)
1025 case R_386_GOT32:
1026 case R_386_GOTOFF:
1027 case R_386_GOTPC:
1028 case R_386_PLT32:
1029 if (!s1->got)
1030 build_got(s1);
1031 if (type == R_386_GOT32 || type == R_386_PLT32) {
1032 sym_index = ELFW(R_SYM)(rel->r_info);
1033 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1034 /* look at the symbol got offset. If none, then add one */
1035 if (type == R_386_GOT32)
1036 reloc_type = R_386_GLOB_DAT;
1037 else
1038 reloc_type = R_386_JMP_SLOT;
1039 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1040 sym_index);
1042 break;
1043 #elif defined(TCC_TARGET_ARM)
1044 case R_ARM_GOT_BREL:
1045 case R_ARM_GOTOFF32:
1046 case R_ARM_BASE_PREL:
1047 case R_ARM_PLT32:
1048 if (!s1->got)
1049 build_got(s1);
1050 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1051 sym_index = ELFW(R_SYM)(rel->r_info);
1052 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1053 /* look at the symbol got offset. If none, then add one */
1054 if (type == R_ARM_GOT_BREL)
1055 reloc_type = R_ARM_GLOB_DAT;
1056 else
1057 reloc_type = R_ARM_JUMP_SLOT;
1058 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1059 sym_index);
1061 break;
1062 #elif defined(TCC_TARGET_C67)
1063 case R_C60_GOT32:
1064 case R_C60_GOTOFF:
1065 case R_C60_GOTPC:
1066 case R_C60_PLT32:
1067 if (!s1->got)
1068 build_got(s1);
1069 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1070 sym_index = ELFW(R_SYM)(rel->r_info);
1071 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1072 /* look at the symbol got offset. If none, then add one */
1073 if (type == R_C60_GOT32)
1074 reloc_type = R_C60_GLOB_DAT;
1075 else
1076 reloc_type = R_C60_JMP_SLOT;
1077 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1078 sym_index);
1080 break;
1081 #elif defined(TCC_TARGET_X86_64)
1082 case R_X86_64_GOT32:
1083 case R_X86_64_GOTTPOFF:
1084 case R_X86_64_GOTPCREL:
1085 case R_X86_64_PLT32:
1086 if (!s1->got)
1087 build_got(s1);
1088 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1089 type == R_X86_64_PLT32) {
1090 sym_index = ELFW(R_SYM)(rel->r_info);
1091 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1092 /* look at the symbol got offset. If none, then add one */
1093 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1094 reloc_type = R_X86_64_GLOB_DAT;
1095 else
1096 reloc_type = R_X86_64_JUMP_SLOT;
1097 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1098 sym_index);
1100 break;
1101 #else
1102 #error unsupported CPU
1103 #endif
1104 default:
1105 break;
1111 static Section *new_symtab(TCCState *s1,
1112 const char *symtab_name, int sh_type, int sh_flags,
1113 const char *strtab_name,
1114 const char *hash_name, int hash_sh_flags)
1116 Section *symtab, *strtab, *hash;
1117 int *ptr, nb_buckets;
1119 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1120 symtab->sh_entsize = sizeof(ElfW(Sym));
1121 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1122 put_elf_str(strtab, "");
1123 symtab->link = strtab;
1124 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1126 nb_buckets = 1;
1128 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1129 hash->sh_entsize = sizeof(int);
1130 symtab->hash = hash;
1131 hash->link = symtab;
1133 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1134 ptr[0] = nb_buckets;
1135 ptr[1] = 1;
1136 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1137 return symtab;
1140 /* put dynamic tag */
1141 static void put_dt(Section *dynamic, int dt, unsigned long val)
1143 ElfW(Dyn) *dyn;
1144 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1145 dyn->d_tag = dt;
1146 dyn->d_un.d_val = val;
1149 static void add_init_array_defines(TCCState *s1, const char *section_name)
1151 Section *s;
1152 long end_offset;
1153 char sym_start[1024];
1154 char sym_end[1024];
1156 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1157 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1159 s = find_section(s1, section_name);
1160 if (!s) {
1161 end_offset = 0;
1162 s = data_section;
1163 } else {
1164 end_offset = s->data_offset;
1167 add_elf_sym(symtab_section,
1168 0, 0,
1169 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1170 s->sh_num, sym_start);
1171 add_elf_sym(symtab_section,
1172 end_offset, 0,
1173 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1174 s->sh_num, sym_end);
1177 /* add tcc runtime libraries */
1178 static void tcc_add_runtime(TCCState *s1)
1180 #if defined(CONFIG_TCC_BCHECK) || !defined(CONFIG_USE_LIBGCC)
1181 char buf[1024];
1182 #endif
1184 #ifdef CONFIG_TCC_BCHECK
1185 if (s1->do_bounds_check) {
1186 unsigned long *ptr;
1187 Section *init_section;
1188 unsigned char *pinit;
1189 int sym_index;
1191 /* XXX: add an object file to do that */
1192 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1193 *ptr = 0;
1194 add_elf_sym(symtab_section, 0, 0,
1195 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1196 bounds_section->sh_num, "__bounds_start");
1197 /* add bound check code */
1198 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "bcheck.o");
1199 tcc_add_file(s1, buf);
1200 #ifdef TCC_TARGET_I386
1201 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1202 /* add 'call __bound_init()' in .init section */
1203 init_section = find_section(s1, ".init");
1204 pinit = section_ptr_add(init_section, 5);
1205 pinit[0] = 0xe8;
1206 put32(pinit + 1, -4);
1207 sym_index = find_elf_sym(symtab_section, "__bound_init");
1208 put_elf_reloc(symtab_section, init_section,
1209 init_section->data_offset - 4, R_386_PC32, sym_index);
1211 #endif
1213 #endif
1214 /* add libc */
1215 if (!s1->nostdlib) {
1216 tcc_add_library(s1, "c");
1218 #ifdef CONFIG_USE_LIBGCC
1219 tcc_add_file(s1, CONFIG_SYSROOT "/lib/libgcc_s.so.1");
1220 #else
1221 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "libtcc1.a");
1222 tcc_add_file(s1, buf);
1223 #endif
1225 /* add crt end if not memory output */
1226 if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) {
1227 tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
1231 /* add various standard linker symbols (must be done after the
1232 sections are filled (for example after allocating common
1233 symbols)) */
1234 static void tcc_add_linker_symbols(TCCState *s1)
1236 char buf[1024];
1237 int i;
1238 Section *s;
1240 add_elf_sym(symtab_section,
1241 text_section->data_offset, 0,
1242 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1243 text_section->sh_num, "_etext");
1244 add_elf_sym(symtab_section,
1245 data_section->data_offset, 0,
1246 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1247 data_section->sh_num, "_edata");
1248 add_elf_sym(symtab_section,
1249 bss_section->data_offset, 0,
1250 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1251 bss_section->sh_num, "_end");
1252 /* horrible new standard ldscript defines */
1253 add_init_array_defines(s1, ".preinit_array");
1254 add_init_array_defines(s1, ".init_array");
1255 add_init_array_defines(s1, ".fini_array");
1257 /* add start and stop symbols for sections whose name can be
1258 expressed in C */
1259 for(i = 1; i < s1->nb_sections; i++) {
1260 s = s1->sections[i];
1261 if (s->sh_type == SHT_PROGBITS &&
1262 (s->sh_flags & SHF_ALLOC)) {
1263 const char *p;
1264 int ch;
1266 /* check if section name can be expressed in C */
1267 p = s->name;
1268 for(;;) {
1269 ch = *p;
1270 if (!ch)
1271 break;
1272 if (!isid(ch) && !isnum(ch))
1273 goto next_sec;
1274 p++;
1276 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1277 add_elf_sym(symtab_section,
1278 0, 0,
1279 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1280 s->sh_num, buf);
1281 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1282 add_elf_sym(symtab_section,
1283 s->data_offset, 0,
1284 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1285 s->sh_num, buf);
1287 next_sec: ;
1291 /* name of ELF interpreter */
1292 #if defined __FreeBSD__
1293 static const char elf_interp[] = "/usr/libexec/ld-elf.so.1";
1294 #elif defined TCC_ARM_EABI
1295 static const char elf_interp[] = "/lib/ld-linux.so.3";
1296 #elif defined(TCC_TARGET_X86_64)
1297 static const char elf_interp[] = "/lib/ld-linux-x86-64.so.2";
1298 #elif defined(TCC_UCLIBC)
1299 static const char elf_interp[] = "/lib/ld-uClibc.so.0";
1300 #else
1301 static const char elf_interp[] = "/lib/ld-linux.so.2";
1302 #endif
1304 static void tcc_output_binary(TCCState *s1, FILE *f,
1305 const int *section_order)
1307 Section *s;
1308 int i, offset, size;
1310 offset = 0;
1311 for(i=1;i<s1->nb_sections;i++) {
1312 s = s1->sections[section_order[i]];
1313 if (s->sh_type != SHT_NOBITS &&
1314 (s->sh_flags & SHF_ALLOC)) {
1315 while (offset < s->sh_offset) {
1316 fputc(0, f);
1317 offset++;
1319 size = s->sh_size;
1320 fwrite(s->data, 1, size, f);
1321 offset += size;
1326 /* output an ELF file */
1327 /* XXX: suppress unneeded sections */
1328 int elf_output_file(TCCState *s1, const char *filename)
1330 ElfW(Ehdr) ehdr;
1331 FILE *f;
1332 int fd, mode, ret;
1333 int *section_order;
1334 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
1335 unsigned long addr;
1336 Section *strsec, *s;
1337 ElfW(Shdr) shdr, *sh;
1338 ElfW(Phdr) *phdr, *ph;
1339 Section *interp, *dynamic, *dynstr;
1340 unsigned long saved_dynamic_data_offset;
1341 ElfW(Sym) *sym;
1342 int type, file_type;
1343 unsigned long rel_addr, rel_size;
1345 file_type = s1->output_type;
1346 s1->nb_errors = 0;
1348 if ((file_type != TCC_OUTPUT_OBJ) && (s1->output_type != TCC_OUTPUT_FORMAT_BINARY)) {
1349 tcc_add_runtime(s1);
1352 phdr = NULL;
1353 section_order = NULL;
1354 interp = NULL;
1355 dynamic = NULL;
1356 dynstr = NULL; /* avoid warning */
1357 saved_dynamic_data_offset = 0; /* avoid warning */
1359 if (file_type != TCC_OUTPUT_OBJ) {
1360 relocate_common_syms();
1362 if (s1->output_type != TCC_OUTPUT_FORMAT_BINARY)
1363 tcc_add_linker_symbols(s1);
1365 if ((!s1->static_link) && (s1->output_type != TCC_OUTPUT_FORMAT_BINARY)) {
1366 const char *name;
1367 int sym_index, index;
1368 ElfW(Sym) *esym, *sym_end;
1370 if ((file_type == TCC_OUTPUT_EXE) && (s1->output_type != TCC_OUTPUT_FORMAT_BINARY)) {
1371 char *ptr;
1372 /* add interpreter section only if executable */
1373 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1374 interp->sh_addralign = 1;
1375 ptr = section_ptr_add(interp, sizeof(elf_interp));
1376 strcpy(ptr, elf_interp);
1379 /* add dynamic symbol table */
1380 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1381 ".dynstr",
1382 ".hash", SHF_ALLOC);
1383 dynstr = s1->dynsym->link;
1385 /* add dynamic section */
1386 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1387 SHF_ALLOC | SHF_WRITE);
1388 dynamic->link = dynstr;
1389 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1391 /* add PLT */
1392 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1393 SHF_ALLOC | SHF_EXECINSTR);
1394 s1->plt->sh_entsize = 4;
1396 build_got(s1);
1398 /* scan for undefined symbols and see if they are in the
1399 dynamic symbols. If a symbol STT_FUNC is found, then we
1400 add it in the PLT. If a symbol STT_OBJECT is found, we
1401 add it in the .bss section with a suitable relocation */
1402 sym_end = (ElfW(Sym) *)(symtab_section->data +
1403 symtab_section->data_offset);
1404 if (file_type == TCC_OUTPUT_EXE) {
1405 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1406 sym < sym_end;
1407 sym++) {
1408 if (sym->st_shndx == SHN_UNDEF) {
1409 name = symtab_section->link->data + sym->st_name;
1410 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1411 if (sym_index) {
1412 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1413 type = ELFW(ST_TYPE)(esym->st_info);
1414 if (type == STT_FUNC) {
1415 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1416 esym->st_info,
1417 sym - (ElfW(Sym) *)symtab_section->data);
1418 } else if (type == STT_OBJECT) {
1419 unsigned long offset;
1420 offset = bss_section->data_offset;
1421 /* XXX: which alignment ? */
1422 offset = (offset + 16 - 1) & -16;
1423 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1424 esym->st_info, 0,
1425 bss_section->sh_num, name);
1426 put_elf_reloc(s1->dynsym, bss_section,
1427 offset, R_COPY, index);
1428 offset += esym->st_size;
1429 bss_section->data_offset = offset;
1431 } else {
1432 /* STB_WEAK undefined symbols are accepted */
1433 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1434 it */
1435 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1436 !strcmp(name, "_fp_hw")) {
1437 } else {
1438 error_noabort("undefined symbol '%s'", name);
1441 } else if (s1->rdynamic &&
1442 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1443 /* if -rdynamic option, then export all non
1444 local symbols */
1445 name = symtab_section->link->data + sym->st_name;
1446 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1447 sym->st_info, 0,
1448 sym->st_shndx, name);
1452 if (s1->nb_errors)
1453 goto fail;
1455 /* now look at unresolved dynamic symbols and export
1456 corresponding symbol */
1457 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1458 s1->dynsymtab_section->data_offset);
1459 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1460 esym < sym_end;
1461 esym++) {
1462 if (esym->st_shndx == SHN_UNDEF) {
1463 name = s1->dynsymtab_section->link->data + esym->st_name;
1464 sym_index = find_elf_sym(symtab_section, name);
1465 if (sym_index) {
1466 /* XXX: avoid adding a symbol if already
1467 present because of -rdynamic ? */
1468 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1469 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1470 sym->st_info, 0,
1471 sym->st_shndx, name);
1472 } else {
1473 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1474 /* weak symbols can stay undefined */
1475 } else {
1476 warning("undefined dynamic symbol '%s'", name);
1481 } else {
1482 int nb_syms;
1483 /* shared library case : we simply export all the global symbols */
1484 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1485 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1486 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1487 sym < sym_end;
1488 sym++) {
1489 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1490 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1491 if (ELFW(ST_TYPE)(sym->st_info) == STT_FUNC &&
1492 sym->st_shndx == SHN_UNDEF) {
1493 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1494 sym->st_info,
1495 sym - (ElfW(Sym) *)symtab_section->data);
1497 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1498 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1499 sym->st_info,
1500 sym - (ElfW(Sym) *)symtab_section->data);
1502 else
1503 #endif
1505 name = symtab_section->link->data + sym->st_name;
1506 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1507 sym->st_info, 0,
1508 sym->st_shndx, name);
1509 s1->symtab_to_dynsym[sym -
1510 (ElfW(Sym) *)symtab_section->data] =
1511 index;
1517 build_got_entries(s1);
1519 /* add a list of needed dlls */
1520 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1521 DLLReference *dllref = s1->loaded_dlls[i];
1522 if (dllref->level == 0)
1523 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1525 /* XXX: currently, since we do not handle PIC code, we
1526 must relocate the readonly segments */
1527 if (file_type == TCC_OUTPUT_DLL) {
1528 if (s1->soname)
1529 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1530 put_dt(dynamic, DT_TEXTREL, 0);
1533 /* add necessary space for other entries */
1534 saved_dynamic_data_offset = dynamic->data_offset;
1535 dynamic->data_offset += sizeof(ElfW(Dyn)) * 9;
1536 } else {
1537 /* still need to build got entries in case of static link */
1538 build_got_entries(s1);
1542 memset(&ehdr, 0, sizeof(ehdr));
1544 /* we add a section for symbols */
1545 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1546 put_elf_str(strsec, "");
1548 /* compute number of sections */
1549 shnum = s1->nb_sections;
1551 /* this array is used to reorder sections in the output file */
1552 section_order = tcc_malloc(sizeof(int) * shnum);
1553 section_order[0] = 0;
1554 sh_order_index = 1;
1556 /* compute number of program headers */
1557 switch(file_type) {
1558 default:
1559 case TCC_OUTPUT_OBJ:
1560 phnum = 0;
1561 break;
1562 case TCC_OUTPUT_EXE:
1563 if (!s1->static_link)
1564 phnum = 4;
1565 else
1566 phnum = 2;
1567 break;
1568 case TCC_OUTPUT_DLL:
1569 phnum = 3;
1570 break;
1573 /* allocate strings for section names and decide if an unallocated
1574 section should be output */
1575 /* NOTE: the strsec section comes last, so its size is also
1576 correct ! */
1577 for(i = 1; i < s1->nb_sections; i++) {
1578 s = s1->sections[i];
1579 s->sh_name = put_elf_str(strsec, s->name);
1580 #if 0 //gr
1581 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1582 s->sh_flags,
1583 s->sh_type,
1584 s->sh_info,
1585 s->name,
1586 s->reloc ? s->reloc->name : "n"
1588 #endif
1589 /* when generating a DLL, we include relocations but we may
1590 patch them */
1591 if (file_type == TCC_OUTPUT_DLL &&
1592 s->sh_type == SHT_RELX &&
1593 !(s->sh_flags & SHF_ALLOC)) {
1594 /* //gr: avoid bogus relocs for empty (debug) sections */
1595 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1596 prepare_dynamic_rel(s1, s);
1597 else if (s1->do_debug)
1598 s->sh_size = s->data_offset;
1599 } else if (s1->do_debug ||
1600 file_type == TCC_OUTPUT_OBJ ||
1601 (s->sh_flags & SHF_ALLOC) ||
1602 i == (s1->nb_sections - 1)) {
1603 /* we output all sections if debug or object file */
1604 s->sh_size = s->data_offset;
1608 /* allocate program segment headers */
1609 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1611 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1612 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1613 } else {
1614 file_offset = 0;
1616 if (phnum > 0) {
1617 /* compute section to program header mapping */
1618 if (s1->has_text_addr) {
1619 int a_offset, p_offset;
1620 addr = s1->text_addr;
1621 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1622 ELF_PAGE_SIZE */
1623 a_offset = addr & (ELF_PAGE_SIZE - 1);
1624 p_offset = file_offset & (ELF_PAGE_SIZE - 1);
1625 if (a_offset < p_offset)
1626 a_offset += ELF_PAGE_SIZE;
1627 file_offset += (a_offset - p_offset);
1628 } else {
1629 if (file_type == TCC_OUTPUT_DLL)
1630 addr = 0;
1631 else
1632 addr = ELF_START_ADDR;
1633 /* compute address after headers */
1634 addr += (file_offset & (ELF_PAGE_SIZE - 1));
1637 /* dynamic relocation table information, for .dynamic section */
1638 rel_size = 0;
1639 rel_addr = 0;
1641 /* leave one program header for the program interpreter */
1642 ph = &phdr[0];
1643 if (interp)
1644 ph++;
1646 for(j = 0; j < 2; j++) {
1647 ph->p_type = PT_LOAD;
1648 if (j == 0)
1649 ph->p_flags = PF_R | PF_X;
1650 else
1651 ph->p_flags = PF_R | PF_W;
1652 ph->p_align = ELF_PAGE_SIZE;
1654 /* we do the following ordering: interp, symbol tables,
1655 relocations, progbits, nobits */
1656 /* XXX: do faster and simpler sorting */
1657 for(k = 0; k < 5; k++) {
1658 for(i = 1; i < s1->nb_sections; i++) {
1659 s = s1->sections[i];
1660 /* compute if section should be included */
1661 if (j == 0) {
1662 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1663 SHF_ALLOC)
1664 continue;
1665 } else {
1666 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1667 (SHF_ALLOC | SHF_WRITE))
1668 continue;
1670 if (s == interp) {
1671 if (k != 0)
1672 continue;
1673 } else if (s->sh_type == SHT_DYNSYM ||
1674 s->sh_type == SHT_STRTAB ||
1675 s->sh_type == SHT_HASH) {
1676 if (k != 1)
1677 continue;
1678 } else if (s->sh_type == SHT_RELX) {
1679 if (k != 2)
1680 continue;
1681 } else if (s->sh_type == SHT_NOBITS) {
1682 if (k != 4)
1683 continue;
1684 } else {
1685 if (k != 3)
1686 continue;
1688 section_order[sh_order_index++] = i;
1690 /* section matches: we align it and add its size */
1691 tmp = addr;
1692 addr = (addr + s->sh_addralign - 1) &
1693 ~(s->sh_addralign - 1);
1694 file_offset += addr - tmp;
1695 s->sh_offset = file_offset;
1696 s->sh_addr = addr;
1698 /* update program header infos */
1699 if (ph->p_offset == 0) {
1700 ph->p_offset = file_offset;
1701 ph->p_vaddr = addr;
1702 ph->p_paddr = ph->p_vaddr;
1704 /* update dynamic relocation infos */
1705 if (s->sh_type == SHT_RELX) {
1706 if (rel_size == 0)
1707 rel_addr = addr;
1708 rel_size += s->sh_size;
1710 addr += s->sh_size;
1711 if (s->sh_type != SHT_NOBITS)
1712 file_offset += s->sh_size;
1715 ph->p_filesz = file_offset - ph->p_offset;
1716 ph->p_memsz = addr - ph->p_vaddr;
1717 ph++;
1718 if (j == 0) {
1719 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1720 /* if in the middle of a page, we duplicate the page in
1721 memory so that one copy is RX and the other is RW */
1722 if ((addr & (ELF_PAGE_SIZE - 1)) != 0)
1723 addr += ELF_PAGE_SIZE;
1724 } else {
1725 addr = (addr + ELF_PAGE_SIZE - 1) & ~(ELF_PAGE_SIZE - 1);
1726 file_offset = (file_offset + ELF_PAGE_SIZE - 1) &
1727 ~(ELF_PAGE_SIZE - 1);
1732 /* if interpreter, then add corresponing program header */
1733 if (interp) {
1734 ph = &phdr[0];
1736 ph->p_type = PT_INTERP;
1737 ph->p_offset = interp->sh_offset;
1738 ph->p_vaddr = interp->sh_addr;
1739 ph->p_paddr = ph->p_vaddr;
1740 ph->p_filesz = interp->sh_size;
1741 ph->p_memsz = interp->sh_size;
1742 ph->p_flags = PF_R;
1743 ph->p_align = interp->sh_addralign;
1746 /* if dynamic section, then add corresponing program header */
1747 if (dynamic) {
1748 ElfW(Sym) *sym_end;
1750 ph = &phdr[phnum - 1];
1752 ph->p_type = PT_DYNAMIC;
1753 ph->p_offset = dynamic->sh_offset;
1754 ph->p_vaddr = dynamic->sh_addr;
1755 ph->p_paddr = ph->p_vaddr;
1756 ph->p_filesz = dynamic->sh_size;
1757 ph->p_memsz = dynamic->sh_size;
1758 ph->p_flags = PF_R | PF_W;
1759 ph->p_align = dynamic->sh_addralign;
1761 /* put GOT dynamic section address */
1762 put32(s1->got->data, dynamic->sh_addr);
1764 /* relocate the PLT */
1765 if (file_type == TCC_OUTPUT_EXE
1766 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1767 || file_type == TCC_OUTPUT_DLL
1768 #endif
1770 uint8_t *p, *p_end;
1772 p = s1->plt->data;
1773 p_end = p + s1->plt->data_offset;
1774 if (p < p_end) {
1775 #if defined(TCC_TARGET_I386)
1776 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1777 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1778 p += 16;
1779 while (p < p_end) {
1780 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1781 p += 16;
1783 #elif defined(TCC_TARGET_X86_64)
1784 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1785 put32(p + 2, get32(p + 2) + x);
1786 put32(p + 8, get32(p + 8) + x - 6);
1787 p += 16;
1788 while (p < p_end) {
1789 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1790 p += 16;
1792 #elif defined(TCC_TARGET_ARM)
1793 int x;
1794 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1795 p +=16;
1796 while (p < p_end) {
1797 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1798 p += 16;
1800 #elif defined(TCC_TARGET_C67)
1801 /* XXX: TODO */
1802 #else
1803 #error unsupported CPU
1804 #endif
1808 /* relocate symbols in .dynsym */
1809 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
1810 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
1811 sym < sym_end;
1812 sym++) {
1813 if (sym->st_shndx == SHN_UNDEF) {
1814 /* relocate to the PLT if the symbol corresponds
1815 to a PLT entry */
1816 if (sym->st_value)
1817 sym->st_value += s1->plt->sh_addr;
1818 } else if (sym->st_shndx < SHN_LORESERVE) {
1819 /* do symbol relocation */
1820 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
1824 /* put dynamic section entries */
1825 dynamic->data_offset = saved_dynamic_data_offset;
1826 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
1827 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
1828 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
1829 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
1830 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
1831 #ifdef TCC_TARGET_X86_64
1832 put_dt(dynamic, DT_RELA, rel_addr);
1833 put_dt(dynamic, DT_RELASZ, rel_size);
1834 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
1835 #else
1836 put_dt(dynamic, DT_REL, rel_addr);
1837 put_dt(dynamic, DT_RELSZ, rel_size);
1838 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
1839 #endif
1840 if (s1->do_debug)
1841 put_dt(dynamic, DT_DEBUG, 0);
1842 put_dt(dynamic, DT_NULL, 0);
1845 ehdr.e_phentsize = sizeof(ElfW(Phdr));
1846 ehdr.e_phnum = phnum;
1847 ehdr.e_phoff = sizeof(ElfW(Ehdr));
1850 /* all other sections come after */
1851 for(i = 1; i < s1->nb_sections; i++) {
1852 s = s1->sections[i];
1853 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
1854 continue;
1855 section_order[sh_order_index++] = i;
1857 file_offset = (file_offset + s->sh_addralign - 1) &
1858 ~(s->sh_addralign - 1);
1859 s->sh_offset = file_offset;
1860 if (s->sh_type != SHT_NOBITS)
1861 file_offset += s->sh_size;
1864 /* if building executable or DLL, then relocate each section
1865 except the GOT which is already relocated */
1866 if (file_type != TCC_OUTPUT_OBJ) {
1867 relocate_syms(s1, 0);
1869 if (s1->nb_errors != 0) {
1870 fail:
1871 ret = -1;
1872 goto the_end;
1875 /* relocate sections */
1876 /* XXX: ignore sections with allocated relocations ? */
1877 for(i = 1; i < s1->nb_sections; i++) {
1878 s = s1->sections[i];
1879 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
1880 relocate_section(s1, s);
1883 /* relocate relocation entries if the relocation tables are
1884 allocated in the executable */
1885 for(i = 1; i < s1->nb_sections; i++) {
1886 s = s1->sections[i];
1887 if ((s->sh_flags & SHF_ALLOC) &&
1888 s->sh_type == SHT_RELX) {
1889 relocate_rel(s1, s);
1893 /* get entry point address */
1894 if (file_type == TCC_OUTPUT_EXE)
1895 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
1896 else
1897 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
1900 /* write elf file */
1901 if (file_type == TCC_OUTPUT_OBJ)
1902 mode = 0666;
1903 else
1904 mode = 0777;
1905 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
1906 if (fd < 0) {
1907 error_noabort("could not write '%s'", filename);
1908 goto fail;
1910 f = fdopen(fd, "wb");
1911 if (s1->verbose)
1912 printf("<- %s\n", filename);
1914 #ifdef TCC_TARGET_COFF
1915 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
1916 tcc_output_coff(s1, f);
1917 } else
1918 #endif
1919 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1920 sort_syms(s1, symtab_section);
1922 /* align to 4 */
1923 file_offset = (file_offset + 3) & -4;
1925 /* fill header */
1926 ehdr.e_ident[0] = ELFMAG0;
1927 ehdr.e_ident[1] = ELFMAG1;
1928 ehdr.e_ident[2] = ELFMAG2;
1929 ehdr.e_ident[3] = ELFMAG3;
1930 ehdr.e_ident[4] = TCC_ELFCLASS;
1931 ehdr.e_ident[5] = ELFDATA2LSB;
1932 ehdr.e_ident[6] = EV_CURRENT;
1933 #ifdef __FreeBSD__
1934 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
1935 #endif
1936 #ifdef TCC_TARGET_ARM
1937 #ifdef TCC_ARM_EABI
1938 ehdr.e_ident[EI_OSABI] = 0;
1939 ehdr.e_flags = 4 << 24;
1940 #else
1941 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
1942 #endif
1943 #endif
1944 switch(file_type) {
1945 default:
1946 case TCC_OUTPUT_EXE:
1947 ehdr.e_type = ET_EXEC;
1948 break;
1949 case TCC_OUTPUT_DLL:
1950 ehdr.e_type = ET_DYN;
1951 break;
1952 case TCC_OUTPUT_OBJ:
1953 ehdr.e_type = ET_REL;
1954 break;
1956 ehdr.e_machine = EM_TCC_TARGET;
1957 ehdr.e_version = EV_CURRENT;
1958 ehdr.e_shoff = file_offset;
1959 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
1960 ehdr.e_shentsize = sizeof(ElfW(Shdr));
1961 ehdr.e_shnum = shnum;
1962 ehdr.e_shstrndx = shnum - 1;
1964 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
1965 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
1966 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1968 for(i=1;i<s1->nb_sections;i++) {
1969 s = s1->sections[section_order[i]];
1970 if (s->sh_type != SHT_NOBITS) {
1971 while (offset < s->sh_offset) {
1972 fputc(0, f);
1973 offset++;
1975 size = s->sh_size;
1976 fwrite(s->data, 1, size, f);
1977 offset += size;
1981 /* output section headers */
1982 while (offset < ehdr.e_shoff) {
1983 fputc(0, f);
1984 offset++;
1987 for(i=0;i<s1->nb_sections;i++) {
1988 sh = &shdr;
1989 memset(sh, 0, sizeof(ElfW(Shdr)));
1990 s = s1->sections[i];
1991 if (s) {
1992 sh->sh_name = s->sh_name;
1993 sh->sh_type = s->sh_type;
1994 sh->sh_flags = s->sh_flags;
1995 sh->sh_entsize = s->sh_entsize;
1996 sh->sh_info = s->sh_info;
1997 if (s->link)
1998 sh->sh_link = s->link->sh_num;
1999 sh->sh_addralign = s->sh_addralign;
2000 sh->sh_addr = s->sh_addr;
2001 sh->sh_offset = s->sh_offset;
2002 sh->sh_size = s->sh_size;
2004 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2006 } else {
2007 tcc_output_binary(s1, f, section_order);
2009 fclose(f);
2011 ret = 0;
2012 the_end:
2013 tcc_free(s1->symtab_to_dynsym);
2014 tcc_free(section_order);
2015 tcc_free(phdr);
2016 tcc_free(s1->got_offsets);
2017 return ret;
2020 int tcc_output_file(TCCState *s, const char *filename)
2022 int ret;
2023 #ifdef TCC_TARGET_PE
2024 if (s->output_type != TCC_OUTPUT_OBJ) {
2025 ret = pe_output_file(s, filename);
2026 } else
2027 #endif
2029 ret = elf_output_file(s, filename);
2031 return ret;
2034 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2036 void *data;
2038 data = tcc_malloc(size);
2039 lseek(fd, file_offset, SEEK_SET);
2040 read(fd, data, size);
2041 return data;
2044 typedef struct SectionMergeInfo {
2045 Section *s; /* corresponding existing section */
2046 unsigned long offset; /* offset of the new section in the existing section */
2047 uint8_t new_section; /* true if section 's' was added */
2048 uint8_t link_once; /* true if link once section */
2049 } SectionMergeInfo;
2051 /* load an object file and merge it with current files */
2052 /* XXX: handle correctly stab (debug) info */
2053 static int tcc_load_object_file(TCCState *s1,
2054 int fd, unsigned long file_offset)
2056 ElfW(Ehdr) ehdr;
2057 ElfW(Shdr) *shdr, *sh;
2058 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2059 unsigned char *strsec, *strtab;
2060 int *old_to_new_syms;
2061 char *sh_name, *name;
2062 SectionMergeInfo *sm_table, *sm;
2063 ElfW(Sym) *sym, *symtab;
2064 ElfW_Rel *rel, *rel_end;
2065 Section *s;
2067 int stab_index;
2068 int stabstr_index;
2070 stab_index = stabstr_index = 0;
2072 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2073 goto fail1;
2074 if (ehdr.e_ident[0] != ELFMAG0 ||
2075 ehdr.e_ident[1] != ELFMAG1 ||
2076 ehdr.e_ident[2] != ELFMAG2 ||
2077 ehdr.e_ident[3] != ELFMAG3)
2078 goto fail1;
2079 /* test if object file */
2080 if (ehdr.e_type != ET_REL)
2081 goto fail1;
2082 /* test CPU specific stuff */
2083 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2084 ehdr.e_machine != EM_TCC_TARGET) {
2085 fail1:
2086 error_noabort("invalid object file");
2087 return -1;
2089 /* read sections */
2090 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2091 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2092 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2094 /* load section names */
2095 sh = &shdr[ehdr.e_shstrndx];
2096 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2098 /* load symtab and strtab */
2099 old_to_new_syms = NULL;
2100 symtab = NULL;
2101 strtab = NULL;
2102 nb_syms = 0;
2103 for(i = 1; i < ehdr.e_shnum; i++) {
2104 sh = &shdr[i];
2105 if (sh->sh_type == SHT_SYMTAB) {
2106 if (symtab) {
2107 error_noabort("object must contain only one symtab");
2108 fail:
2109 ret = -1;
2110 goto the_end;
2112 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2113 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2114 sm_table[i].s = symtab_section;
2116 /* now load strtab */
2117 sh = &shdr[sh->sh_link];
2118 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2122 /* now examine each section and try to merge its content with the
2123 ones in memory */
2124 for(i = 1; i < ehdr.e_shnum; i++) {
2125 /* no need to examine section name strtab */
2126 if (i == ehdr.e_shstrndx)
2127 continue;
2128 sh = &shdr[i];
2129 sh_name = strsec + sh->sh_name;
2130 /* ignore sections types we do not handle */
2131 if (sh->sh_type != SHT_PROGBITS &&
2132 sh->sh_type != SHT_RELX &&
2133 #ifdef TCC_ARM_EABI
2134 sh->sh_type != SHT_ARM_EXIDX &&
2135 #endif
2136 sh->sh_type != SHT_NOBITS &&
2137 strcmp(sh_name, ".stabstr")
2139 continue;
2140 if (sh->sh_addralign < 1)
2141 sh->sh_addralign = 1;
2142 /* find corresponding section, if any */
2143 for(j = 1; j < s1->nb_sections;j++) {
2144 s = s1->sections[j];
2145 if (!strcmp(s->name, sh_name)) {
2146 if (!strncmp(sh_name, ".gnu.linkonce",
2147 sizeof(".gnu.linkonce") - 1)) {
2148 /* if a 'linkonce' section is already present, we
2149 do not add it again. It is a little tricky as
2150 symbols can still be defined in
2151 it. */
2152 sm_table[i].link_once = 1;
2153 goto next;
2154 } else {
2155 goto found;
2159 /* not found: create new section */
2160 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2161 /* take as much info as possible from the section. sh_link and
2162 sh_info will be updated later */
2163 s->sh_addralign = sh->sh_addralign;
2164 s->sh_entsize = sh->sh_entsize;
2165 sm_table[i].new_section = 1;
2166 found:
2167 if (sh->sh_type != s->sh_type) {
2168 error_noabort("invalid section type");
2169 goto fail;
2172 /* align start of section */
2173 offset = s->data_offset;
2175 if (0 == strcmp(sh_name, ".stab")) {
2176 stab_index = i;
2177 goto no_align;
2179 if (0 == strcmp(sh_name, ".stabstr")) {
2180 stabstr_index = i;
2181 goto no_align;
2184 size = sh->sh_addralign - 1;
2185 offset = (offset + size) & ~size;
2186 if (sh->sh_addralign > s->sh_addralign)
2187 s->sh_addralign = sh->sh_addralign;
2188 s->data_offset = offset;
2189 no_align:
2190 sm_table[i].offset = offset;
2191 sm_table[i].s = s;
2192 /* concatenate sections */
2193 size = sh->sh_size;
2194 if (sh->sh_type != SHT_NOBITS) {
2195 unsigned char *ptr;
2196 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2197 ptr = section_ptr_add(s, size);
2198 read(fd, ptr, size);
2199 } else {
2200 s->data_offset += size;
2202 next: ;
2205 /* //gr relocate stab strings */
2206 if (stab_index && stabstr_index) {
2207 Stab_Sym *a, *b;
2208 unsigned o;
2209 s = sm_table[stab_index].s;
2210 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2211 b = (Stab_Sym *)(s->data + s->data_offset);
2212 o = sm_table[stabstr_index].offset;
2213 while (a < b)
2214 a->n_strx += o, a++;
2217 /* second short pass to update sh_link and sh_info fields of new
2218 sections */
2219 for(i = 1; i < ehdr.e_shnum; i++) {
2220 s = sm_table[i].s;
2221 if (!s || !sm_table[i].new_section)
2222 continue;
2223 sh = &shdr[i];
2224 if (sh->sh_link > 0)
2225 s->link = sm_table[sh->sh_link].s;
2226 if (sh->sh_type == SHT_RELX) {
2227 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2228 /* update backward link */
2229 s1->sections[s->sh_info]->reloc = s;
2232 sm = sm_table;
2234 /* resolve symbols */
2235 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2237 sym = symtab + 1;
2238 for(i = 1; i < nb_syms; i++, sym++) {
2239 if (sym->st_shndx != SHN_UNDEF &&
2240 sym->st_shndx < SHN_LORESERVE) {
2241 sm = &sm_table[sym->st_shndx];
2242 if (sm->link_once) {
2243 /* if a symbol is in a link once section, we use the
2244 already defined symbol. It is very important to get
2245 correct relocations */
2246 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2247 name = strtab + sym->st_name;
2248 sym_index = find_elf_sym(symtab_section, name);
2249 if (sym_index)
2250 old_to_new_syms[i] = sym_index;
2252 continue;
2254 /* if no corresponding section added, no need to add symbol */
2255 if (!sm->s)
2256 continue;
2257 /* convert section number */
2258 sym->st_shndx = sm->s->sh_num;
2259 /* offset value */
2260 sym->st_value += sm->offset;
2262 /* add symbol */
2263 name = strtab + sym->st_name;
2264 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2265 sym->st_info, sym->st_other,
2266 sym->st_shndx, name);
2267 old_to_new_syms[i] = sym_index;
2270 /* third pass to patch relocation entries */
2271 for(i = 1; i < ehdr.e_shnum; i++) {
2272 s = sm_table[i].s;
2273 if (!s)
2274 continue;
2275 sh = &shdr[i];
2276 offset = sm_table[i].offset;
2277 switch(s->sh_type) {
2278 case SHT_RELX:
2279 /* take relocation offset information */
2280 offseti = sm_table[sh->sh_info].offset;
2281 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2282 for(rel = (ElfW_Rel *)(s->data + offset);
2283 rel < rel_end;
2284 rel++) {
2285 int type;
2286 unsigned sym_index;
2287 /* convert symbol index */
2288 type = ELFW(R_TYPE)(rel->r_info);
2289 sym_index = ELFW(R_SYM)(rel->r_info);
2290 /* NOTE: only one symtab assumed */
2291 if (sym_index >= nb_syms)
2292 goto invalid_reloc;
2293 sym_index = old_to_new_syms[sym_index];
2294 /* ignore link_once in rel section. */
2295 if (!sym_index && !sm->link_once) {
2296 invalid_reloc:
2297 error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2298 i, strsec + sh->sh_name, rel->r_offset);
2299 goto fail;
2301 rel->r_info = ELFW(R_INFO)(sym_index, type);
2302 /* offset the relocation offset */
2303 rel->r_offset += offseti;
2305 break;
2306 default:
2307 break;
2311 ret = 0;
2312 the_end:
2313 tcc_free(symtab);
2314 tcc_free(strtab);
2315 tcc_free(old_to_new_syms);
2316 tcc_free(sm_table);
2317 tcc_free(strsec);
2318 tcc_free(shdr);
2319 return ret;
2322 #define ARMAG "!<arch>\012" /* For COFF and a.out archives */
2324 typedef struct ArchiveHeader {
2325 char ar_name[16]; /* name of this member */
2326 char ar_date[12]; /* file mtime */
2327 char ar_uid[6]; /* owner uid; printed as decimal */
2328 char ar_gid[6]; /* owner gid; printed as decimal */
2329 char ar_mode[8]; /* file mode, printed as octal */
2330 char ar_size[10]; /* file size, printed as decimal */
2331 char ar_fmag[2]; /* should contain ARFMAG */
2332 } ArchiveHeader;
2334 static int get_be32(const uint8_t *b)
2336 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2339 /* load only the objects which resolve undefined symbols */
2340 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2342 int i, bound, nsyms, sym_index, off, ret;
2343 uint8_t *data;
2344 const char *ar_names, *p;
2345 const uint8_t *ar_index;
2346 ElfW(Sym) *sym;
2348 data = tcc_malloc(size);
2349 if (read(fd, data, size) != size)
2350 goto fail;
2351 nsyms = get_be32(data);
2352 ar_index = data + 4;
2353 ar_names = ar_index + nsyms * 4;
2355 do {
2356 bound = 0;
2357 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2358 sym_index = find_elf_sym(symtab_section, p);
2359 if(sym_index) {
2360 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2361 if(sym->st_shndx == SHN_UNDEF) {
2362 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2363 #if 0
2364 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2365 #endif
2366 ++bound;
2367 lseek(fd, off, SEEK_SET);
2368 if(tcc_load_object_file(s1, fd, off) < 0) {
2369 fail:
2370 ret = -1;
2371 goto the_end;
2376 } while(bound);
2377 ret = 0;
2378 the_end:
2379 tcc_free(data);
2380 return ret;
2383 /* load a '.a' file */
2384 static int tcc_load_archive(TCCState *s1, int fd)
2386 ArchiveHeader hdr;
2387 char ar_size[11];
2388 char ar_name[17];
2389 char magic[8];
2390 int size, len, i;
2391 unsigned long file_offset;
2393 /* skip magic which was already checked */
2394 read(fd, magic, sizeof(magic));
2396 for(;;) {
2397 len = read(fd, &hdr, sizeof(hdr));
2398 if (len == 0)
2399 break;
2400 if (len != sizeof(hdr)) {
2401 error_noabort("invalid archive");
2402 return -1;
2404 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2405 ar_size[sizeof(hdr.ar_size)] = '\0';
2406 size = strtol(ar_size, NULL, 0);
2407 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2408 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2409 if (ar_name[i] != ' ')
2410 break;
2412 ar_name[i + 1] = '\0';
2413 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2414 file_offset = lseek(fd, 0, SEEK_CUR);
2415 /* align to even */
2416 size = (size + 1) & ~1;
2417 if (!strcmp(ar_name, "/")) {
2418 /* coff symbol table : we handle it */
2419 if(s1->alacarte_link)
2420 return tcc_load_alacarte(s1, fd, size);
2421 } else if (!strcmp(ar_name, "//") ||
2422 !strcmp(ar_name, "__.SYMDEF") ||
2423 !strcmp(ar_name, "__.SYMDEF/") ||
2424 !strcmp(ar_name, "ARFILENAMES/")) {
2425 /* skip symbol table or archive names */
2426 } else {
2427 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2428 return -1;
2430 lseek(fd, file_offset + size, SEEK_SET);
2432 return 0;
2435 #ifndef TCC_TARGET_PE
2436 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2437 is referenced by the user (so it should be added as DT_NEEDED in
2438 the generated ELF file) */
2439 static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2441 ElfW(Ehdr) ehdr;
2442 ElfW(Shdr) *shdr, *sh, *sh1;
2443 int i, j, nb_syms, nb_dts, sym_bind, ret;
2444 ElfW(Sym) *sym, *dynsym;
2445 ElfW(Dyn) *dt, *dynamic;
2446 unsigned char *dynstr;
2447 const char *name, *soname;
2448 DLLReference *dllref;
2450 read(fd, &ehdr, sizeof(ehdr));
2452 /* test CPU specific stuff */
2453 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2454 ehdr.e_machine != EM_TCC_TARGET) {
2455 error_noabort("bad architecture");
2456 return -1;
2459 /* read sections */
2460 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2462 /* load dynamic section and dynamic symbols */
2463 nb_syms = 0;
2464 nb_dts = 0;
2465 dynamic = NULL;
2466 dynsym = NULL; /* avoid warning */
2467 dynstr = NULL; /* avoid warning */
2468 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2469 switch(sh->sh_type) {
2470 case SHT_DYNAMIC:
2471 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2472 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2473 break;
2474 case SHT_DYNSYM:
2475 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2476 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2477 sh1 = &shdr[sh->sh_link];
2478 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2479 break;
2480 default:
2481 break;
2485 /* compute the real library name */
2486 soname = tcc_basename(filename);
2488 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2489 if (dt->d_tag == DT_SONAME) {
2490 soname = dynstr + dt->d_un.d_val;
2494 /* if the dll is already loaded, do not load it */
2495 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2496 dllref = s1->loaded_dlls[i];
2497 if (!strcmp(soname, dllref->name)) {
2498 /* but update level if needed */
2499 if (level < dllref->level)
2500 dllref->level = level;
2501 ret = 0;
2502 goto the_end;
2506 // printf("loading dll '%s'\n", soname);
2508 /* add the dll and its level */
2509 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2510 dllref->level = level;
2511 strcpy(dllref->name, soname);
2512 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2514 /* add dynamic symbols in dynsym_section */
2515 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2516 sym_bind = ELFW(ST_BIND)(sym->st_info);
2517 if (sym_bind == STB_LOCAL)
2518 continue;
2519 name = dynstr + sym->st_name;
2520 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2521 sym->st_info, sym->st_other, sym->st_shndx, name);
2524 /* load all referenced DLLs */
2525 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2526 switch(dt->d_tag) {
2527 case DT_NEEDED:
2528 name = dynstr + dt->d_un.d_val;
2529 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2530 dllref = s1->loaded_dlls[j];
2531 if (!strcmp(name, dllref->name))
2532 goto already_loaded;
2534 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2535 error_noabort("referenced dll '%s' not found", name);
2536 ret = -1;
2537 goto the_end;
2539 already_loaded:
2540 break;
2543 ret = 0;
2544 the_end:
2545 tcc_free(dynstr);
2546 tcc_free(dynsym);
2547 tcc_free(dynamic);
2548 tcc_free(shdr);
2549 return ret;
2552 #define LD_TOK_NAME 256
2553 #define LD_TOK_EOF (-1)
2555 /* return next ld script token */
2556 static int ld_next(TCCState *s1, char *name, int name_size)
2558 int c;
2559 char *q;
2561 redo:
2562 switch(ch) {
2563 case ' ':
2564 case '\t':
2565 case '\f':
2566 case '\v':
2567 case '\r':
2568 case '\n':
2569 inp();
2570 goto redo;
2571 case '/':
2572 minp();
2573 if (ch == '*') {
2574 file->buf_ptr = parse_comment(file->buf_ptr);
2575 ch = file->buf_ptr[0];
2576 goto redo;
2577 } else {
2578 q = name;
2579 *q++ = '/';
2580 goto parse_name;
2582 break;
2583 /* case 'a' ... 'z': */
2584 case 'a':
2585 case 'b':
2586 case 'c':
2587 case 'd':
2588 case 'e':
2589 case 'f':
2590 case 'g':
2591 case 'h':
2592 case 'i':
2593 case 'j':
2594 case 'k':
2595 case 'l':
2596 case 'm':
2597 case 'n':
2598 case 'o':
2599 case 'p':
2600 case 'q':
2601 case 'r':
2602 case 's':
2603 case 't':
2604 case 'u':
2605 case 'v':
2606 case 'w':
2607 case 'x':
2608 case 'y':
2609 case 'z':
2610 /* case 'A' ... 'z': */
2611 case 'A':
2612 case 'B':
2613 case 'C':
2614 case 'D':
2615 case 'E':
2616 case 'F':
2617 case 'G':
2618 case 'H':
2619 case 'I':
2620 case 'J':
2621 case 'K':
2622 case 'L':
2623 case 'M':
2624 case 'N':
2625 case 'O':
2626 case 'P':
2627 case 'Q':
2628 case 'R':
2629 case 'S':
2630 case 'T':
2631 case 'U':
2632 case 'V':
2633 case 'W':
2634 case 'X':
2635 case 'Y':
2636 case 'Z':
2637 case '_':
2638 case '\\':
2639 case '.':
2640 case '$':
2641 case '~':
2642 q = name;
2643 parse_name:
2644 for(;;) {
2645 if (!((ch >= 'a' && ch <= 'z') ||
2646 (ch >= 'A' && ch <= 'Z') ||
2647 (ch >= '0' && ch <= '9') ||
2648 strchr("/.-_+=$:\\,~", ch)))
2649 break;
2650 if ((q - name) < name_size - 1) {
2651 *q++ = ch;
2653 minp();
2655 *q = '\0';
2656 c = LD_TOK_NAME;
2657 break;
2658 case CH_EOF:
2659 c = LD_TOK_EOF;
2660 break;
2661 default:
2662 c = ch;
2663 inp();
2664 break;
2666 #if 0
2667 printf("tok=%c %d\n", c, c);
2668 if (c == LD_TOK_NAME)
2669 printf(" name=%s\n", name);
2670 #endif
2671 return c;
2674 static int ld_add_file_list(TCCState *s1, int as_needed)
2676 char filename[1024];
2677 int t, ret;
2679 t = ld_next(s1, filename, sizeof(filename));
2680 if (t != '(')
2681 expect("(");
2682 t = ld_next(s1, filename, sizeof(filename));
2683 for(;;) {
2684 if (t == LD_TOK_EOF) {
2685 error_noabort("unexpected end of file");
2686 return -1;
2687 } else if (t == ')') {
2688 break;
2689 } else if (t != LD_TOK_NAME) {
2690 error_noabort("filename expected");
2691 return -1;
2693 if (!strcmp(filename, "AS_NEEDED")) {
2694 ret = ld_add_file_list(s1, 1);
2695 if (ret)
2696 return ret;
2697 } else {
2698 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2699 if (!as_needed)
2700 tcc_add_file(s1, filename);
2702 t = ld_next(s1, filename, sizeof(filename));
2703 if (t == ',') {
2704 t = ld_next(s1, filename, sizeof(filename));
2707 return 0;
2710 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
2711 files */
2712 static int tcc_load_ldscript(TCCState *s1)
2714 char cmd[64];
2715 char filename[1024];
2716 int t, ret;
2718 ch = file->buf_ptr[0];
2719 ch = handle_eob();
2720 for(;;) {
2721 t = ld_next(s1, cmd, sizeof(cmd));
2722 if (t == LD_TOK_EOF)
2723 return 0;
2724 else if (t != LD_TOK_NAME)
2725 return -1;
2726 if (!strcmp(cmd, "INPUT") ||
2727 !strcmp(cmd, "GROUP")) {
2728 ret = ld_add_file_list(s1, 0);
2729 if (ret)
2730 return ret;
2731 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
2732 !strcmp(cmd, "TARGET")) {
2733 /* ignore some commands */
2734 t = ld_next(s1, cmd, sizeof(cmd));
2735 if (t != '(')
2736 expect("(");
2737 for(;;) {
2738 t = ld_next(s1, filename, sizeof(filename));
2739 if (t == LD_TOK_EOF) {
2740 error_noabort("unexpected end of file");
2741 return -1;
2742 } else if (t == ')') {
2743 break;
2746 } else {
2747 return -1;
2750 return 0;
2752 #endif