Fixed compilation error in i386-asm.c
[tinycc/kirr.git] / tccelf.c
blob5d73b4ad875a33978e1cb49867f7c7b880b08be5
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 case R_386_16:
595 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
596 output_file:
597 error("can only produce 16-bit binary files");
599 *(short *)ptr += val;
600 break;
601 case R_386_PC16:
602 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
603 goto output_file;
604 *(short *)ptr += val - addr;
605 break;
606 #elif defined(TCC_TARGET_ARM)
607 case R_ARM_PC24:
608 case R_ARM_CALL:
609 case R_ARM_JUMP24:
610 case R_ARM_PLT32:
612 int x;
613 x = (*(int *)ptr)&0xffffff;
614 (*(int *)ptr) &= 0xff000000;
615 if (x & 0x800000)
616 x -= 0x1000000;
617 x *= 4;
618 x += val - addr;
619 if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
620 error("can't relocate value at %x",addr);
621 x >>= 2;
622 x &= 0xffffff;
623 (*(int *)ptr) |= x;
625 break;
626 case R_ARM_PREL31:
628 int x;
629 x = (*(int *)ptr) & 0x7fffffff;
630 (*(int *)ptr) &= 0x80000000;
631 x = (x * 2) / 2;
632 x += val - addr;
633 if((x^(x>>1))&0x40000000)
634 error("can't relocate value at %x",addr);
635 (*(int *)ptr) |= x & 0x7fffffff;
637 case R_ARM_ABS32:
638 *(int *)ptr += val;
639 break;
640 case R_ARM_BASE_PREL:
641 *(int *)ptr += s1->got->sh_addr - addr;
642 break;
643 case R_ARM_GOTOFF32:
644 *(int *)ptr += val - s1->got->sh_addr;
645 break;
646 case R_ARM_GOT_BREL:
647 /* we load the got offset */
648 *(int *)ptr += s1->got_offsets[sym_index];
649 break;
650 case R_ARM_COPY:
651 break;
652 default:
653 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
654 type,addr,(unsigned int)(long)ptr,val);
655 break;
656 #elif defined(TCC_TARGET_C67)
657 case R_C60_32:
658 *(int *)ptr += val;
659 break;
660 case R_C60LO16:
662 uint32_t orig;
664 /* put the low 16 bits of the absolute address */
665 // add to what is already there
667 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
668 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
670 //patch both at once - assumes always in pairs Low - High
672 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
673 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
675 break;
676 case R_C60HI16:
677 break;
678 default:
679 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
680 type,addr,(unsigned int)(long)ptr, val);
681 break;
682 #elif defined(TCC_TARGET_X86_64)
683 case R_X86_64_64:
684 if (s1->output_type == TCC_OUTPUT_DLL) {
685 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
686 qrel->r_addend = *(long long *)ptr + val;
687 qrel++;
689 *(long long *)ptr += val;
690 break;
691 case R_X86_64_32:
692 case R_X86_64_32S:
693 if (s1->output_type == TCC_OUTPUT_DLL) {
694 /* XXX: this logic may depend on TCC's codegen
695 now TCC uses R_X86_64_32 even for a 64bit pointer */
696 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
697 qrel->r_addend = *(int *)ptr + val;
698 qrel++;
700 *(int *)ptr += val;
701 break;
702 case R_X86_64_PC32: {
703 long long diff;
704 if (s1->output_type == TCC_OUTPUT_DLL) {
705 /* DLL relocation */
706 esym_index = s1->symtab_to_dynsym[sym_index];
707 if (esym_index) {
708 qrel->r_offset = rel->r_offset;
709 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
710 qrel->r_addend = *(int *)ptr;
711 qrel++;
712 break;
715 diff = (long long)val - addr;
716 if (diff <= -2147483647 || diff > 2147483647) {
717 #ifndef TCC_TARGET_PE
718 /* XXX: naive support for over 32bit jump */
719 if (s1->output_type == TCC_OUTPUT_MEMORY) {
720 val = add_jmp_table(s1, val);
721 diff = val - addr;
723 #endif
724 if (diff <= -2147483647 || diff > 2147483647) {
725 error("internal error: relocation failed");
728 *(int *)ptr += diff;
730 break;
731 case R_X86_64_PLT32:
732 *(int *)ptr += val - addr;
733 break;
734 case R_X86_64_GLOB_DAT:
735 case R_X86_64_JUMP_SLOT:
736 *(int *)ptr = val;
737 break;
738 case R_X86_64_GOTPCREL:
739 #ifndef TCC_TARGET_PE
740 if (s1->output_type == TCC_OUTPUT_MEMORY) {
741 val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
742 *(int *)ptr += val - addr;
743 break;
745 #endif
746 *(int *)ptr += (s1->got->sh_addr - addr +
747 s1->got_offsets[sym_index] - 4);
748 break;
749 case R_X86_64_GOTTPOFF:
750 *(int *)ptr += val - s1->got->sh_addr;
751 break;
752 case R_X86_64_GOT32:
753 /* we load the got offset */
754 *(int *)ptr += s1->got_offsets[sym_index];
755 break;
756 #else
757 #error unsupported processor
758 #endif
761 /* if the relocation is allocated, we change its symbol table */
762 if (sr->sh_flags & SHF_ALLOC)
763 sr->link = s1->dynsym;
766 /* relocate relocation table in 'sr' */
767 static void relocate_rel(TCCState *s1, Section *sr)
769 Section *s;
770 ElfW_Rel *rel, *rel_end;
772 s = s1->sections[sr->sh_info];
773 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
774 for(rel = (ElfW_Rel *)sr->data;
775 rel < rel_end;
776 rel++) {
777 rel->r_offset += s->sh_addr;
781 /* count the number of dynamic relocations so that we can reserve
782 their space */
783 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
785 ElfW_Rel *rel, *rel_end;
786 int sym_index, esym_index, type, count;
788 count = 0;
789 rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
790 for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
791 sym_index = ELFW(R_SYM)(rel->r_info);
792 type = ELFW(R_TYPE)(rel->r_info);
793 switch(type) {
794 #if defined(TCC_TARGET_I386)
795 case R_386_32:
796 #elif defined(TCC_TARGET_X86_64)
797 case R_X86_64_32:
798 case R_X86_64_32S:
799 case R_X86_64_64:
800 #endif
801 count++;
802 break;
803 #if defined(TCC_TARGET_I386)
804 case R_386_PC32:
805 #elif defined(TCC_TARGET_X86_64)
806 case R_X86_64_PC32:
807 #endif
808 esym_index = s1->symtab_to_dynsym[sym_index];
809 if (esym_index)
810 count++;
811 break;
812 default:
813 break;
816 if (count) {
817 /* allocate the section */
818 sr->sh_flags |= SHF_ALLOC;
819 sr->sh_size = count * sizeof(ElfW_Rel);
821 return count;
824 static void put_got_offset(TCCState *s1, int index, unsigned long val)
826 int n;
827 unsigned long *tab;
829 if (index >= s1->nb_got_offsets) {
830 /* find immediately bigger power of 2 and reallocate array */
831 n = 1;
832 while (index >= n)
833 n *= 2;
834 tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
835 if (!tab)
836 error("memory full");
837 s1->got_offsets = tab;
838 memset(s1->got_offsets + s1->nb_got_offsets, 0,
839 (n - s1->nb_got_offsets) * sizeof(unsigned long));
840 s1->nb_got_offsets = n;
842 s1->got_offsets[index] = val;
845 /* XXX: suppress that */
846 static void put32(unsigned char *p, uint32_t val)
848 p[0] = val;
849 p[1] = val >> 8;
850 p[2] = val >> 16;
851 p[3] = val >> 24;
854 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
855 defined(TCC_TARGET_X86_64)
856 static uint32_t get32(unsigned char *p)
858 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
860 #endif
862 static void build_got(TCCState *s1)
864 unsigned char *ptr;
866 /* if no got, then create it */
867 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
868 s1->got->sh_entsize = 4;
869 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
870 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
871 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
872 #if PTR_SIZE == 4
873 /* keep space for _DYNAMIC pointer, if present */
874 put32(ptr, 0);
875 /* two dummy got entries */
876 put32(ptr + 4, 0);
877 put32(ptr + 8, 0);
878 #else
879 /* keep space for _DYNAMIC pointer, if present */
880 put32(ptr, 0);
881 put32(ptr + 4, 0);
882 /* two dummy got entries */
883 put32(ptr + 8, 0);
884 put32(ptr + 12, 0);
885 put32(ptr + 16, 0);
886 put32(ptr + 20, 0);
887 #endif
890 /* put a got entry corresponding to a symbol in symtab_section. 'size'
891 and 'info' can be modifed if more precise info comes from the DLL */
892 static void put_got_entry(TCCState *s1,
893 int reloc_type, unsigned long size, int info,
894 int sym_index)
896 int index;
897 const char *name;
898 ElfW(Sym) *sym;
899 unsigned long offset;
900 int *ptr;
902 if (!s1->got)
903 build_got(s1);
905 /* if a got entry already exists for that symbol, no need to add one */
906 if (sym_index < s1->nb_got_offsets &&
907 s1->got_offsets[sym_index] != 0)
908 return;
910 put_got_offset(s1, sym_index, s1->got->data_offset);
912 if (s1->dynsym) {
913 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
914 name = symtab_section->link->data + sym->st_name;
915 offset = sym->st_value;
916 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
917 if (reloc_type ==
918 #ifdef TCC_TARGET_X86_64
919 R_X86_64_JUMP_SLOT
920 #else
921 R_386_JMP_SLOT
922 #endif
924 Section *plt;
925 uint8_t *p;
926 int modrm;
928 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
929 modrm = 0x25;
930 #else
931 /* if we build a DLL, we add a %ebx offset */
932 if (s1->output_type == TCC_OUTPUT_DLL)
933 modrm = 0xa3;
934 else
935 modrm = 0x25;
936 #endif
938 /* add a PLT entry */
939 plt = s1->plt;
940 if (plt->data_offset == 0) {
941 /* first plt entry */
942 p = section_ptr_add(plt, 16);
943 p[0] = 0xff; /* pushl got + PTR_SIZE */
944 p[1] = modrm + 0x10;
945 put32(p + 2, PTR_SIZE);
946 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
947 p[7] = modrm;
948 put32(p + 8, PTR_SIZE * 2);
951 p = section_ptr_add(plt, 16);
952 p[0] = 0xff; /* jmp *(got + x) */
953 p[1] = modrm;
954 put32(p + 2, s1->got->data_offset);
955 p[6] = 0x68; /* push $xxx */
956 put32(p + 7, (plt->data_offset - 32) >> 1);
957 p[11] = 0xe9; /* jmp plt_start */
958 put32(p + 12, -(plt->data_offset));
960 /* the symbol is modified so that it will be relocated to
961 the PLT */
962 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
963 if (s1->output_type == TCC_OUTPUT_EXE)
964 #endif
965 offset = plt->data_offset - 16;
967 #elif defined(TCC_TARGET_ARM)
968 if (reloc_type == R_ARM_JUMP_SLOT) {
969 Section *plt;
970 uint8_t *p;
972 /* if we build a DLL, we add a %ebx offset */
973 if (s1->output_type == TCC_OUTPUT_DLL)
974 error("DLLs unimplemented!");
976 /* add a PLT entry */
977 plt = s1->plt;
978 if (plt->data_offset == 0) {
979 /* first plt entry */
980 p = section_ptr_add(plt, 16);
981 put32(p , 0xe52de004);
982 put32(p + 4, 0xe59fe010);
983 put32(p + 8, 0xe08fe00e);
984 put32(p + 12, 0xe5bef008);
987 p = section_ptr_add(plt, 16);
988 put32(p , 0xe59fc004);
989 put32(p+4, 0xe08fc00c);
990 put32(p+8, 0xe59cf000);
991 put32(p+12, s1->got->data_offset);
993 /* the symbol is modified so that it will be relocated to
994 the PLT */
995 if (s1->output_type == TCC_OUTPUT_EXE)
996 offset = plt->data_offset - 16;
998 #elif defined(TCC_TARGET_C67)
999 error("C67 got not implemented");
1000 #else
1001 #error unsupported CPU
1002 #endif
1003 index = put_elf_sym(s1->dynsym, offset,
1004 size, info, 0, sym->st_shndx, name);
1005 /* put a got entry */
1006 put_elf_reloc(s1->dynsym, s1->got,
1007 s1->got->data_offset,
1008 reloc_type, index);
1010 ptr = section_ptr_add(s1->got, PTR_SIZE);
1011 *ptr = 0;
1014 /* build GOT and PLT entries */
1015 static void build_got_entries(TCCState *s1)
1017 Section *s, *symtab;
1018 ElfW_Rel *rel, *rel_end;
1019 ElfW(Sym) *sym;
1020 int i, type, reloc_type, sym_index;
1022 for(i = 1; i < s1->nb_sections; i++) {
1023 s = s1->sections[i];
1024 if (s->sh_type != SHT_RELX)
1025 continue;
1026 /* no need to handle got relocations */
1027 if (s->link != symtab_section)
1028 continue;
1029 symtab = s->link;
1030 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1031 for(rel = (ElfW_Rel *)s->data;
1032 rel < rel_end;
1033 rel++) {
1034 type = ELFW(R_TYPE)(rel->r_info);
1035 switch(type) {
1036 #if defined(TCC_TARGET_I386)
1037 case R_386_GOT32:
1038 case R_386_GOTOFF:
1039 case R_386_GOTPC:
1040 case R_386_PLT32:
1041 if (!s1->got)
1042 build_got(s1);
1043 if (type == R_386_GOT32 || type == R_386_PLT32) {
1044 sym_index = ELFW(R_SYM)(rel->r_info);
1045 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1046 /* look at the symbol got offset. If none, then add one */
1047 if (type == R_386_GOT32)
1048 reloc_type = R_386_GLOB_DAT;
1049 else
1050 reloc_type = R_386_JMP_SLOT;
1051 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1052 sym_index);
1054 break;
1055 #elif defined(TCC_TARGET_ARM)
1056 case R_ARM_GOT_BREL:
1057 case R_ARM_GOTOFF32:
1058 case R_ARM_BASE_PREL:
1059 case R_ARM_PLT32:
1060 if (!s1->got)
1061 build_got(s1);
1062 if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1063 sym_index = ELFW(R_SYM)(rel->r_info);
1064 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1065 /* look at the symbol got offset. If none, then add one */
1066 if (type == R_ARM_GOT_BREL)
1067 reloc_type = R_ARM_GLOB_DAT;
1068 else
1069 reloc_type = R_ARM_JUMP_SLOT;
1070 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1071 sym_index);
1073 break;
1074 #elif defined(TCC_TARGET_C67)
1075 case R_C60_GOT32:
1076 case R_C60_GOTOFF:
1077 case R_C60_GOTPC:
1078 case R_C60_PLT32:
1079 if (!s1->got)
1080 build_got(s1);
1081 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1082 sym_index = ELFW(R_SYM)(rel->r_info);
1083 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1084 /* look at the symbol got offset. If none, then add one */
1085 if (type == R_C60_GOT32)
1086 reloc_type = R_C60_GLOB_DAT;
1087 else
1088 reloc_type = R_C60_JMP_SLOT;
1089 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1090 sym_index);
1092 break;
1093 #elif defined(TCC_TARGET_X86_64)
1094 case R_X86_64_GOT32:
1095 case R_X86_64_GOTTPOFF:
1096 case R_X86_64_GOTPCREL:
1097 case R_X86_64_PLT32:
1098 if (!s1->got)
1099 build_got(s1);
1100 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1101 type == R_X86_64_PLT32) {
1102 sym_index = ELFW(R_SYM)(rel->r_info);
1103 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1104 /* look at the symbol got offset. If none, then add one */
1105 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1106 reloc_type = R_X86_64_GLOB_DAT;
1107 else
1108 reloc_type = R_X86_64_JUMP_SLOT;
1109 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1110 sym_index);
1112 break;
1113 #else
1114 #error unsupported CPU
1115 #endif
1116 default:
1117 break;
1123 static Section *new_symtab(TCCState *s1,
1124 const char *symtab_name, int sh_type, int sh_flags,
1125 const char *strtab_name,
1126 const char *hash_name, int hash_sh_flags)
1128 Section *symtab, *strtab, *hash;
1129 int *ptr, nb_buckets;
1131 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1132 symtab->sh_entsize = sizeof(ElfW(Sym));
1133 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1134 put_elf_str(strtab, "");
1135 symtab->link = strtab;
1136 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1138 nb_buckets = 1;
1140 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1141 hash->sh_entsize = sizeof(int);
1142 symtab->hash = hash;
1143 hash->link = symtab;
1145 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1146 ptr[0] = nb_buckets;
1147 ptr[1] = 1;
1148 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1149 return symtab;
1152 /* put dynamic tag */
1153 static void put_dt(Section *dynamic, int dt, unsigned long val)
1155 ElfW(Dyn) *dyn;
1156 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1157 dyn->d_tag = dt;
1158 dyn->d_un.d_val = val;
1161 static void add_init_array_defines(TCCState *s1, const char *section_name)
1163 Section *s;
1164 long end_offset;
1165 char sym_start[1024];
1166 char sym_end[1024];
1168 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1169 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1171 s = find_section(s1, section_name);
1172 if (!s) {
1173 end_offset = 0;
1174 s = data_section;
1175 } else {
1176 end_offset = s->data_offset;
1179 add_elf_sym(symtab_section,
1180 0, 0,
1181 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1182 s->sh_num, sym_start);
1183 add_elf_sym(symtab_section,
1184 end_offset, 0,
1185 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1186 s->sh_num, sym_end);
1189 /* add tcc runtime libraries */
1190 static void tcc_add_runtime(TCCState *s1)
1192 #if defined(CONFIG_TCC_BCHECK) || !defined(CONFIG_USE_LIBGCC)
1193 char buf[1024];
1194 #endif
1196 #ifdef CONFIG_TCC_BCHECK
1197 if (s1->do_bounds_check) {
1198 unsigned long *ptr;
1199 Section *init_section;
1200 unsigned char *pinit;
1201 int sym_index;
1203 /* XXX: add an object file to do that */
1204 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1205 *ptr = 0;
1206 add_elf_sym(symtab_section, 0, 0,
1207 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1208 bounds_section->sh_num, "__bounds_start");
1209 /* add bound check code */
1210 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "bcheck.o");
1211 tcc_add_file(s1, buf);
1212 #ifdef TCC_TARGET_I386
1213 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1214 /* add 'call __bound_init()' in .init section */
1215 init_section = find_section(s1, ".init");
1216 pinit = section_ptr_add(init_section, 5);
1217 pinit[0] = 0xe8;
1218 put32(pinit + 1, -4);
1219 sym_index = find_elf_sym(symtab_section, "__bound_init");
1220 put_elf_reloc(symtab_section, init_section,
1221 init_section->data_offset - 4, R_386_PC32, sym_index);
1223 #endif
1225 #endif
1226 /* add libc */
1227 if (!s1->nostdlib) {
1228 tcc_add_library(s1, "c");
1230 #ifdef CONFIG_USE_LIBGCC
1231 tcc_add_file(s1, CONFIG_SYSROOT "/lib/libgcc_s.so.1");
1232 #else
1233 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "libtcc1.a");
1234 tcc_add_file(s1, buf);
1235 #endif
1237 /* add crt end if not memory output */
1238 if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) {
1239 tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
1243 /* add various standard linker symbols (must be done after the
1244 sections are filled (for example after allocating common
1245 symbols)) */
1246 static void tcc_add_linker_symbols(TCCState *s1)
1248 char buf[1024];
1249 int i;
1250 Section *s;
1252 add_elf_sym(symtab_section,
1253 text_section->data_offset, 0,
1254 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1255 text_section->sh_num, "_etext");
1256 add_elf_sym(symtab_section,
1257 data_section->data_offset, 0,
1258 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1259 data_section->sh_num, "_edata");
1260 add_elf_sym(symtab_section,
1261 bss_section->data_offset, 0,
1262 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1263 bss_section->sh_num, "_end");
1264 /* horrible new standard ldscript defines */
1265 add_init_array_defines(s1, ".preinit_array");
1266 add_init_array_defines(s1, ".init_array");
1267 add_init_array_defines(s1, ".fini_array");
1269 /* add start and stop symbols for sections whose name can be
1270 expressed in C */
1271 for(i = 1; i < s1->nb_sections; i++) {
1272 s = s1->sections[i];
1273 if (s->sh_type == SHT_PROGBITS &&
1274 (s->sh_flags & SHF_ALLOC)) {
1275 const char *p;
1276 int ch;
1278 /* check if section name can be expressed in C */
1279 p = s->name;
1280 for(;;) {
1281 ch = *p;
1282 if (!ch)
1283 break;
1284 if (!isid(ch) && !isnum(ch))
1285 goto next_sec;
1286 p++;
1288 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1289 add_elf_sym(symtab_section,
1290 0, 0,
1291 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1292 s->sh_num, buf);
1293 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1294 add_elf_sym(symtab_section,
1295 s->data_offset, 0,
1296 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1297 s->sh_num, buf);
1299 next_sec: ;
1303 /* name of ELF interpreter */
1304 #if defined __FreeBSD__
1305 static const char elf_interp[] = "/usr/libexec/ld-elf.so.1";
1306 #elif defined TCC_ARM_EABI
1307 static const char elf_interp[] = "/lib/ld-linux.so.3";
1308 #elif defined(TCC_TARGET_X86_64)
1309 static const char elf_interp[] = "/lib/ld-linux-x86-64.so.2";
1310 #elif defined(TCC_UCLIBC)
1311 static const char elf_interp[] = "/lib/ld-uClibc.so.0";
1312 #else
1313 static const char elf_interp[] = "/lib/ld-linux.so.2";
1314 #endif
1316 static void tcc_output_binary(TCCState *s1, FILE *f,
1317 const int *section_order)
1319 Section *s;
1320 int i, offset, size;
1322 offset = 0;
1323 for(i=1;i<s1->nb_sections;i++) {
1324 s = s1->sections[section_order[i]];
1325 if (s->sh_type != SHT_NOBITS &&
1326 (s->sh_flags & SHF_ALLOC)) {
1327 while (offset < s->sh_offset) {
1328 fputc(0, f);
1329 offset++;
1331 size = s->sh_size;
1332 fwrite(s->data, 1, size, f);
1333 offset += size;
1338 /* output an ELF file */
1339 /* XXX: suppress unneeded sections */
1340 int elf_output_file(TCCState *s1, const char *filename)
1342 ElfW(Ehdr) ehdr;
1343 FILE *f;
1344 int fd, mode, ret;
1345 int *section_order;
1346 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
1347 unsigned long addr;
1348 Section *strsec, *s;
1349 ElfW(Shdr) shdr, *sh;
1350 ElfW(Phdr) *phdr, *ph;
1351 Section *interp, *dynamic, *dynstr;
1352 unsigned long saved_dynamic_data_offset;
1353 ElfW(Sym) *sym;
1354 int type, file_type;
1355 unsigned long rel_addr, rel_size;
1357 file_type = s1->output_type;
1358 s1->nb_errors = 0;
1360 if ((file_type != TCC_OUTPUT_OBJ) && (s1->output_type != TCC_OUTPUT_FORMAT_BINARY)) {
1361 tcc_add_runtime(s1);
1364 phdr = NULL;
1365 section_order = NULL;
1366 interp = NULL;
1367 dynamic = NULL;
1368 dynstr = NULL; /* avoid warning */
1369 saved_dynamic_data_offset = 0; /* avoid warning */
1371 if (file_type != TCC_OUTPUT_OBJ) {
1372 relocate_common_syms();
1374 if (s1->output_type != TCC_OUTPUT_FORMAT_BINARY)
1375 tcc_add_linker_symbols(s1);
1377 if ((!s1->static_link) && (s1->output_type != TCC_OUTPUT_FORMAT_BINARY)) {
1378 const char *name;
1379 int sym_index, index;
1380 ElfW(Sym) *esym, *sym_end;
1382 if ((file_type == TCC_OUTPUT_EXE) && (s1->output_type != TCC_OUTPUT_FORMAT_BINARY)) {
1383 char *ptr;
1384 /* add interpreter section only if executable */
1385 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1386 interp->sh_addralign = 1;
1387 ptr = section_ptr_add(interp, sizeof(elf_interp));
1388 strcpy(ptr, elf_interp);
1391 /* add dynamic symbol table */
1392 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1393 ".dynstr",
1394 ".hash", SHF_ALLOC);
1395 dynstr = s1->dynsym->link;
1397 /* add dynamic section */
1398 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1399 SHF_ALLOC | SHF_WRITE);
1400 dynamic->link = dynstr;
1401 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1403 /* add PLT */
1404 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1405 SHF_ALLOC | SHF_EXECINSTR);
1406 s1->plt->sh_entsize = 4;
1408 build_got(s1);
1410 /* scan for undefined symbols and see if they are in the
1411 dynamic symbols. If a symbol STT_FUNC is found, then we
1412 add it in the PLT. If a symbol STT_OBJECT is found, we
1413 add it in the .bss section with a suitable relocation */
1414 sym_end = (ElfW(Sym) *)(symtab_section->data +
1415 symtab_section->data_offset);
1416 if (file_type == TCC_OUTPUT_EXE) {
1417 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1418 sym < sym_end;
1419 sym++) {
1420 if (sym->st_shndx == SHN_UNDEF) {
1421 name = symtab_section->link->data + sym->st_name;
1422 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1423 if (sym_index) {
1424 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1425 type = ELFW(ST_TYPE)(esym->st_info);
1426 if (type == STT_FUNC) {
1427 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1428 esym->st_info,
1429 sym - (ElfW(Sym) *)symtab_section->data);
1430 } else if (type == STT_OBJECT) {
1431 unsigned long offset;
1432 offset = bss_section->data_offset;
1433 /* XXX: which alignment ? */
1434 offset = (offset + 16 - 1) & -16;
1435 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1436 esym->st_info, 0,
1437 bss_section->sh_num, name);
1438 put_elf_reloc(s1->dynsym, bss_section,
1439 offset, R_COPY, index);
1440 offset += esym->st_size;
1441 bss_section->data_offset = offset;
1443 } else {
1444 /* STB_WEAK undefined symbols are accepted */
1445 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1446 it */
1447 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1448 !strcmp(name, "_fp_hw")) {
1449 } else {
1450 error_noabort("undefined symbol '%s'", name);
1453 } else if (s1->rdynamic &&
1454 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1455 /* if -rdynamic option, then export all non
1456 local symbols */
1457 name = symtab_section->link->data + sym->st_name;
1458 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1459 sym->st_info, 0,
1460 sym->st_shndx, name);
1464 if (s1->nb_errors)
1465 goto fail;
1467 /* now look at unresolved dynamic symbols and export
1468 corresponding symbol */
1469 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1470 s1->dynsymtab_section->data_offset);
1471 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1472 esym < sym_end;
1473 esym++) {
1474 if (esym->st_shndx == SHN_UNDEF) {
1475 name = s1->dynsymtab_section->link->data + esym->st_name;
1476 sym_index = find_elf_sym(symtab_section, name);
1477 if (sym_index) {
1478 /* XXX: avoid adding a symbol if already
1479 present because of -rdynamic ? */
1480 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1481 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1482 sym->st_info, 0,
1483 sym->st_shndx, name);
1484 } else {
1485 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1486 /* weak symbols can stay undefined */
1487 } else {
1488 warning("undefined dynamic symbol '%s'", name);
1493 } else {
1494 int nb_syms;
1495 /* shared library case : we simply export all the global symbols */
1496 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1497 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1498 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1499 sym < sym_end;
1500 sym++) {
1501 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1502 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1503 if (ELFW(ST_TYPE)(sym->st_info) == STT_FUNC &&
1504 sym->st_shndx == SHN_UNDEF) {
1505 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1506 sym->st_info,
1507 sym - (ElfW(Sym) *)symtab_section->data);
1509 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1510 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1511 sym->st_info,
1512 sym - (ElfW(Sym) *)symtab_section->data);
1514 else
1515 #endif
1517 name = symtab_section->link->data + sym->st_name;
1518 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1519 sym->st_info, 0,
1520 sym->st_shndx, name);
1521 s1->symtab_to_dynsym[sym -
1522 (ElfW(Sym) *)symtab_section->data] =
1523 index;
1529 build_got_entries(s1);
1531 /* add a list of needed dlls */
1532 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1533 DLLReference *dllref = s1->loaded_dlls[i];
1534 if (dllref->level == 0)
1535 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1537 /* XXX: currently, since we do not handle PIC code, we
1538 must relocate the readonly segments */
1539 if (file_type == TCC_OUTPUT_DLL) {
1540 if (s1->soname)
1541 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1542 put_dt(dynamic, DT_TEXTREL, 0);
1545 /* add necessary space for other entries */
1546 saved_dynamic_data_offset = dynamic->data_offset;
1547 dynamic->data_offset += sizeof(ElfW(Dyn)) * 9;
1548 } else {
1549 /* still need to build got entries in case of static link */
1550 build_got_entries(s1);
1554 memset(&ehdr, 0, sizeof(ehdr));
1556 /* we add a section for symbols */
1557 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1558 put_elf_str(strsec, "");
1560 /* compute number of sections */
1561 shnum = s1->nb_sections;
1563 /* this array is used to reorder sections in the output file */
1564 section_order = tcc_malloc(sizeof(int) * shnum);
1565 section_order[0] = 0;
1566 sh_order_index = 1;
1568 /* compute number of program headers */
1569 switch(file_type) {
1570 default:
1571 case TCC_OUTPUT_OBJ:
1572 phnum = 0;
1573 break;
1574 case TCC_OUTPUT_EXE:
1575 if (!s1->static_link)
1576 phnum = 4;
1577 else
1578 phnum = 2;
1579 break;
1580 case TCC_OUTPUT_DLL:
1581 phnum = 3;
1582 break;
1585 /* allocate strings for section names and decide if an unallocated
1586 section should be output */
1587 /* NOTE: the strsec section comes last, so its size is also
1588 correct ! */
1589 for(i = 1; i < s1->nb_sections; i++) {
1590 s = s1->sections[i];
1591 s->sh_name = put_elf_str(strsec, s->name);
1592 #if 0 //gr
1593 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1594 s->sh_flags,
1595 s->sh_type,
1596 s->sh_info,
1597 s->name,
1598 s->reloc ? s->reloc->name : "n"
1600 #endif
1601 /* when generating a DLL, we include relocations but we may
1602 patch them */
1603 if (file_type == TCC_OUTPUT_DLL &&
1604 s->sh_type == SHT_RELX &&
1605 !(s->sh_flags & SHF_ALLOC)) {
1606 /* //gr: avoid bogus relocs for empty (debug) sections */
1607 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1608 prepare_dynamic_rel(s1, s);
1609 else if (s1->do_debug)
1610 s->sh_size = s->data_offset;
1611 } else if (s1->do_debug ||
1612 file_type == TCC_OUTPUT_OBJ ||
1613 (s->sh_flags & SHF_ALLOC) ||
1614 i == (s1->nb_sections - 1)) {
1615 /* we output all sections if debug or object file */
1616 s->sh_size = s->data_offset;
1620 /* allocate program segment headers */
1621 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1623 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1624 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1625 } else {
1626 file_offset = 0;
1628 if (phnum > 0) {
1629 /* compute section to program header mapping */
1630 if (s1->has_text_addr) {
1631 int a_offset, p_offset;
1632 addr = s1->text_addr;
1633 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1634 ELF_PAGE_SIZE */
1635 a_offset = addr & (s1->section_align - 1);
1636 p_offset = file_offset & (s1->section_align - 1);
1637 if (a_offset < p_offset)
1638 a_offset += s1->section_align;
1639 file_offset += (a_offset - p_offset);
1640 } else {
1641 if (file_type == TCC_OUTPUT_DLL)
1642 addr = 0;
1643 else
1644 addr = ELF_START_ADDR;
1645 /* compute address after headers */
1646 addr += (file_offset & (s1->section_align - 1));
1649 /* dynamic relocation table information, for .dynamic section */
1650 rel_size = 0;
1651 rel_addr = 0;
1653 /* leave one program header for the program interpreter */
1654 ph = &phdr[0];
1655 if (interp)
1656 ph++;
1658 for(j = 0; j < 2; j++) {
1659 ph->p_type = PT_LOAD;
1660 if (j == 0)
1661 ph->p_flags = PF_R | PF_X;
1662 else
1663 ph->p_flags = PF_R | PF_W;
1664 ph->p_align = s1->section_align;
1666 /* we do the following ordering: interp, symbol tables,
1667 relocations, progbits, nobits */
1668 /* XXX: do faster and simpler sorting */
1669 for(k = 0; k < 5; k++) {
1670 for(i = 1; i < s1->nb_sections; i++) {
1671 s = s1->sections[i];
1672 /* compute if section should be included */
1673 if (j == 0) {
1674 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1675 SHF_ALLOC)
1676 continue;
1677 } else {
1678 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1679 (SHF_ALLOC | SHF_WRITE))
1680 continue;
1682 if (s == interp) {
1683 if (k != 0)
1684 continue;
1685 } else if (s->sh_type == SHT_DYNSYM ||
1686 s->sh_type == SHT_STRTAB ||
1687 s->sh_type == SHT_HASH) {
1688 if (k != 1)
1689 continue;
1690 } else if (s->sh_type == SHT_RELX) {
1691 if (k != 2)
1692 continue;
1693 } else if (s->sh_type == SHT_NOBITS) {
1694 if (k != 4)
1695 continue;
1696 } else {
1697 if (k != 3)
1698 continue;
1700 section_order[sh_order_index++] = i;
1702 /* section matches: we align it and add its size */
1703 tmp = addr;
1704 addr = (addr + s->sh_addralign - 1) &
1705 ~(s->sh_addralign - 1);
1706 file_offset += addr - tmp;
1707 s->sh_offset = file_offset;
1708 s->sh_addr = addr;
1710 /* update program header infos */
1711 if (ph->p_offset == 0) {
1712 ph->p_offset = file_offset;
1713 ph->p_vaddr = addr;
1714 ph->p_paddr = ph->p_vaddr;
1716 /* update dynamic relocation infos */
1717 if (s->sh_type == SHT_RELX) {
1718 if (rel_size == 0)
1719 rel_addr = addr;
1720 rel_size += s->sh_size;
1722 addr += s->sh_size;
1723 if (s->sh_type != SHT_NOBITS)
1724 file_offset += s->sh_size;
1727 ph->p_filesz = file_offset - ph->p_offset;
1728 ph->p_memsz = addr - ph->p_vaddr;
1729 ph++;
1730 if (j == 0) {
1731 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1732 /* if in the middle of a page, we duplicate the page in
1733 memory so that one copy is RX and the other is RW */
1734 if ((addr & (s1->section_align - 1)) != 0)
1735 addr += s1->section_align;
1736 } else {
1737 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1738 file_offset = (file_offset + s1->section_align - 1) &
1739 ~(s1->section_align - 1);
1744 /* if interpreter, then add corresponing program header */
1745 if (interp) {
1746 ph = &phdr[0];
1748 ph->p_type = PT_INTERP;
1749 ph->p_offset = interp->sh_offset;
1750 ph->p_vaddr = interp->sh_addr;
1751 ph->p_paddr = ph->p_vaddr;
1752 ph->p_filesz = interp->sh_size;
1753 ph->p_memsz = interp->sh_size;
1754 ph->p_flags = PF_R;
1755 ph->p_align = interp->sh_addralign;
1758 /* if dynamic section, then add corresponing program header */
1759 if (dynamic) {
1760 ElfW(Sym) *sym_end;
1762 ph = &phdr[phnum - 1];
1764 ph->p_type = PT_DYNAMIC;
1765 ph->p_offset = dynamic->sh_offset;
1766 ph->p_vaddr = dynamic->sh_addr;
1767 ph->p_paddr = ph->p_vaddr;
1768 ph->p_filesz = dynamic->sh_size;
1769 ph->p_memsz = dynamic->sh_size;
1770 ph->p_flags = PF_R | PF_W;
1771 ph->p_align = dynamic->sh_addralign;
1773 /* put GOT dynamic section address */
1774 put32(s1->got->data, dynamic->sh_addr);
1776 /* relocate the PLT */
1777 if (file_type == TCC_OUTPUT_EXE
1778 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1779 || file_type == TCC_OUTPUT_DLL
1780 #endif
1782 uint8_t *p, *p_end;
1784 p = s1->plt->data;
1785 p_end = p + s1->plt->data_offset;
1786 if (p < p_end) {
1787 #if defined(TCC_TARGET_I386)
1788 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1789 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1790 p += 16;
1791 while (p < p_end) {
1792 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1793 p += 16;
1795 #elif defined(TCC_TARGET_X86_64)
1796 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1797 put32(p + 2, get32(p + 2) + x);
1798 put32(p + 8, get32(p + 8) + x - 6);
1799 p += 16;
1800 while (p < p_end) {
1801 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1802 p += 16;
1804 #elif defined(TCC_TARGET_ARM)
1805 int x;
1806 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1807 p +=16;
1808 while (p < p_end) {
1809 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1810 p += 16;
1812 #elif defined(TCC_TARGET_C67)
1813 /* XXX: TODO */
1814 #else
1815 #error unsupported CPU
1816 #endif
1820 /* relocate symbols in .dynsym */
1821 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
1822 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
1823 sym < sym_end;
1824 sym++) {
1825 if (sym->st_shndx == SHN_UNDEF) {
1826 /* relocate to the PLT if the symbol corresponds
1827 to a PLT entry */
1828 if (sym->st_value)
1829 sym->st_value += s1->plt->sh_addr;
1830 } else if (sym->st_shndx < SHN_LORESERVE) {
1831 /* do symbol relocation */
1832 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
1836 /* put dynamic section entries */
1837 dynamic->data_offset = saved_dynamic_data_offset;
1838 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
1839 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
1840 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
1841 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
1842 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
1843 #ifdef TCC_TARGET_X86_64
1844 put_dt(dynamic, DT_RELA, rel_addr);
1845 put_dt(dynamic, DT_RELASZ, rel_size);
1846 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
1847 #else
1848 put_dt(dynamic, DT_REL, rel_addr);
1849 put_dt(dynamic, DT_RELSZ, rel_size);
1850 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
1851 #endif
1852 if (s1->do_debug)
1853 put_dt(dynamic, DT_DEBUG, 0);
1854 put_dt(dynamic, DT_NULL, 0);
1857 ehdr.e_phentsize = sizeof(ElfW(Phdr));
1858 ehdr.e_phnum = phnum;
1859 ehdr.e_phoff = sizeof(ElfW(Ehdr));
1862 /* all other sections come after */
1863 for(i = 1; i < s1->nb_sections; i++) {
1864 s = s1->sections[i];
1865 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
1866 continue;
1867 section_order[sh_order_index++] = i;
1869 file_offset = (file_offset + s->sh_addralign - 1) &
1870 ~(s->sh_addralign - 1);
1871 s->sh_offset = file_offset;
1872 if (s->sh_type != SHT_NOBITS)
1873 file_offset += s->sh_size;
1876 /* if building executable or DLL, then relocate each section
1877 except the GOT which is already relocated */
1878 if (file_type != TCC_OUTPUT_OBJ) {
1879 relocate_syms(s1, 0);
1881 if (s1->nb_errors != 0) {
1882 fail:
1883 ret = -1;
1884 goto the_end;
1887 /* relocate sections */
1888 /* XXX: ignore sections with allocated relocations ? */
1889 for(i = 1; i < s1->nb_sections; i++) {
1890 s = s1->sections[i];
1891 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
1892 relocate_section(s1, s);
1895 /* relocate relocation entries if the relocation tables are
1896 allocated in the executable */
1897 for(i = 1; i < s1->nb_sections; i++) {
1898 s = s1->sections[i];
1899 if ((s->sh_flags & SHF_ALLOC) &&
1900 s->sh_type == SHT_RELX) {
1901 relocate_rel(s1, s);
1905 /* get entry point address */
1906 if (file_type == TCC_OUTPUT_EXE)
1907 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
1908 else
1909 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
1912 /* write elf file */
1913 if (file_type == TCC_OUTPUT_OBJ)
1914 mode = 0666;
1915 else
1916 mode = 0777;
1917 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
1918 if (fd < 0) {
1919 error_noabort("could not write '%s'", filename);
1920 goto fail;
1922 f = fdopen(fd, "wb");
1923 if (s1->verbose)
1924 printf("<- %s\n", filename);
1926 #ifdef TCC_TARGET_COFF
1927 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
1928 tcc_output_coff(s1, f);
1929 } else
1930 #endif
1931 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1932 sort_syms(s1, symtab_section);
1934 /* align to 4 */
1935 file_offset = (file_offset + 3) & -4;
1937 /* fill header */
1938 ehdr.e_ident[0] = ELFMAG0;
1939 ehdr.e_ident[1] = ELFMAG1;
1940 ehdr.e_ident[2] = ELFMAG2;
1941 ehdr.e_ident[3] = ELFMAG3;
1942 ehdr.e_ident[4] = TCC_ELFCLASS;
1943 ehdr.e_ident[5] = ELFDATA2LSB;
1944 ehdr.e_ident[6] = EV_CURRENT;
1945 #ifdef __FreeBSD__
1946 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
1947 #endif
1948 #ifdef TCC_TARGET_ARM
1949 #ifdef TCC_ARM_EABI
1950 ehdr.e_ident[EI_OSABI] = 0;
1951 ehdr.e_flags = 4 << 24;
1952 #else
1953 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
1954 #endif
1955 #endif
1956 switch(file_type) {
1957 default:
1958 case TCC_OUTPUT_EXE:
1959 ehdr.e_type = ET_EXEC;
1960 break;
1961 case TCC_OUTPUT_DLL:
1962 ehdr.e_type = ET_DYN;
1963 break;
1964 case TCC_OUTPUT_OBJ:
1965 ehdr.e_type = ET_REL;
1966 break;
1968 ehdr.e_machine = EM_TCC_TARGET;
1969 ehdr.e_version = EV_CURRENT;
1970 ehdr.e_shoff = file_offset;
1971 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
1972 ehdr.e_shentsize = sizeof(ElfW(Shdr));
1973 ehdr.e_shnum = shnum;
1974 ehdr.e_shstrndx = shnum - 1;
1976 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
1977 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
1978 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1980 for(i=1;i<s1->nb_sections;i++) {
1981 s = s1->sections[section_order[i]];
1982 if (s->sh_type != SHT_NOBITS) {
1983 while (offset < s->sh_offset) {
1984 fputc(0, f);
1985 offset++;
1987 size = s->sh_size;
1988 fwrite(s->data, 1, size, f);
1989 offset += size;
1993 /* output section headers */
1994 while (offset < ehdr.e_shoff) {
1995 fputc(0, f);
1996 offset++;
1999 for(i=0;i<s1->nb_sections;i++) {
2000 sh = &shdr;
2001 memset(sh, 0, sizeof(ElfW(Shdr)));
2002 s = s1->sections[i];
2003 if (s) {
2004 sh->sh_name = s->sh_name;
2005 sh->sh_type = s->sh_type;
2006 sh->sh_flags = s->sh_flags;
2007 sh->sh_entsize = s->sh_entsize;
2008 sh->sh_info = s->sh_info;
2009 if (s->link)
2010 sh->sh_link = s->link->sh_num;
2011 sh->sh_addralign = s->sh_addralign;
2012 sh->sh_addr = s->sh_addr;
2013 sh->sh_offset = s->sh_offset;
2014 sh->sh_size = s->sh_size;
2016 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2018 } else {
2019 tcc_output_binary(s1, f, section_order);
2021 fclose(f);
2023 ret = 0;
2024 the_end:
2025 tcc_free(s1->symtab_to_dynsym);
2026 tcc_free(section_order);
2027 tcc_free(phdr);
2028 tcc_free(s1->got_offsets);
2029 return ret;
2032 int tcc_output_file(TCCState *s, const char *filename)
2034 int ret;
2035 #ifdef TCC_TARGET_PE
2036 if (s->output_type != TCC_OUTPUT_OBJ) {
2037 ret = pe_output_file(s, filename);
2038 } else
2039 #endif
2041 ret = elf_output_file(s, filename);
2043 return ret;
2046 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2048 void *data;
2050 data = tcc_malloc(size);
2051 lseek(fd, file_offset, SEEK_SET);
2052 read(fd, data, size);
2053 return data;
2056 typedef struct SectionMergeInfo {
2057 Section *s; /* corresponding existing section */
2058 unsigned long offset; /* offset of the new section in the existing section */
2059 uint8_t new_section; /* true if section 's' was added */
2060 uint8_t link_once; /* true if link once section */
2061 } SectionMergeInfo;
2063 /* load an object file and merge it with current files */
2064 /* XXX: handle correctly stab (debug) info */
2065 static int tcc_load_object_file(TCCState *s1,
2066 int fd, unsigned long file_offset)
2068 ElfW(Ehdr) ehdr;
2069 ElfW(Shdr) *shdr, *sh;
2070 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2071 unsigned char *strsec, *strtab;
2072 int *old_to_new_syms;
2073 char *sh_name, *name;
2074 SectionMergeInfo *sm_table, *sm;
2075 ElfW(Sym) *sym, *symtab;
2076 ElfW_Rel *rel, *rel_end;
2077 Section *s;
2079 int stab_index;
2080 int stabstr_index;
2082 stab_index = stabstr_index = 0;
2084 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2085 goto fail1;
2086 if (ehdr.e_ident[0] != ELFMAG0 ||
2087 ehdr.e_ident[1] != ELFMAG1 ||
2088 ehdr.e_ident[2] != ELFMAG2 ||
2089 ehdr.e_ident[3] != ELFMAG3)
2090 goto fail1;
2091 /* test if object file */
2092 if (ehdr.e_type != ET_REL)
2093 goto fail1;
2094 /* test CPU specific stuff */
2095 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2096 ehdr.e_machine != EM_TCC_TARGET) {
2097 fail1:
2098 error_noabort("invalid object file");
2099 return -1;
2101 /* read sections */
2102 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2103 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2104 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2106 /* load section names */
2107 sh = &shdr[ehdr.e_shstrndx];
2108 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2110 /* load symtab and strtab */
2111 old_to_new_syms = NULL;
2112 symtab = NULL;
2113 strtab = NULL;
2114 nb_syms = 0;
2115 for(i = 1; i < ehdr.e_shnum; i++) {
2116 sh = &shdr[i];
2117 if (sh->sh_type == SHT_SYMTAB) {
2118 if (symtab) {
2119 error_noabort("object must contain only one symtab");
2120 fail:
2121 ret = -1;
2122 goto the_end;
2124 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2125 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2126 sm_table[i].s = symtab_section;
2128 /* now load strtab */
2129 sh = &shdr[sh->sh_link];
2130 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2134 /* now examine each section and try to merge its content with the
2135 ones in memory */
2136 for(i = 1; i < ehdr.e_shnum; i++) {
2137 /* no need to examine section name strtab */
2138 if (i == ehdr.e_shstrndx)
2139 continue;
2140 sh = &shdr[i];
2141 sh_name = strsec + sh->sh_name;
2142 /* ignore sections types we do not handle */
2143 if (sh->sh_type != SHT_PROGBITS &&
2144 sh->sh_type != SHT_RELX &&
2145 #ifdef TCC_ARM_EABI
2146 sh->sh_type != SHT_ARM_EXIDX &&
2147 #endif
2148 sh->sh_type != SHT_NOBITS &&
2149 strcmp(sh_name, ".stabstr")
2151 continue;
2152 if (sh->sh_addralign < 1)
2153 sh->sh_addralign = 1;
2154 /* find corresponding section, if any */
2155 for(j = 1; j < s1->nb_sections;j++) {
2156 s = s1->sections[j];
2157 if (!strcmp(s->name, sh_name)) {
2158 if (!strncmp(sh_name, ".gnu.linkonce",
2159 sizeof(".gnu.linkonce") - 1)) {
2160 /* if a 'linkonce' section is already present, we
2161 do not add it again. It is a little tricky as
2162 symbols can still be defined in
2163 it. */
2164 sm_table[i].link_once = 1;
2165 goto next;
2166 } else {
2167 goto found;
2171 /* not found: create new section */
2172 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2173 /* take as much info as possible from the section. sh_link and
2174 sh_info will be updated later */
2175 s->sh_addralign = sh->sh_addralign;
2176 s->sh_entsize = sh->sh_entsize;
2177 sm_table[i].new_section = 1;
2178 found:
2179 if (sh->sh_type != s->sh_type) {
2180 error_noabort("invalid section type");
2181 goto fail;
2184 /* align start of section */
2185 offset = s->data_offset;
2187 if (0 == strcmp(sh_name, ".stab")) {
2188 stab_index = i;
2189 goto no_align;
2191 if (0 == strcmp(sh_name, ".stabstr")) {
2192 stabstr_index = i;
2193 goto no_align;
2196 size = sh->sh_addralign - 1;
2197 offset = (offset + size) & ~size;
2198 if (sh->sh_addralign > s->sh_addralign)
2199 s->sh_addralign = sh->sh_addralign;
2200 s->data_offset = offset;
2201 no_align:
2202 sm_table[i].offset = offset;
2203 sm_table[i].s = s;
2204 /* concatenate sections */
2205 size = sh->sh_size;
2206 if (sh->sh_type != SHT_NOBITS) {
2207 unsigned char *ptr;
2208 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2209 ptr = section_ptr_add(s, size);
2210 read(fd, ptr, size);
2211 } else {
2212 s->data_offset += size;
2214 next: ;
2217 /* //gr relocate stab strings */
2218 if (stab_index && stabstr_index) {
2219 Stab_Sym *a, *b;
2220 unsigned o;
2221 s = sm_table[stab_index].s;
2222 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2223 b = (Stab_Sym *)(s->data + s->data_offset);
2224 o = sm_table[stabstr_index].offset;
2225 while (a < b)
2226 a->n_strx += o, a++;
2229 /* second short pass to update sh_link and sh_info fields of new
2230 sections */
2231 for(i = 1; i < ehdr.e_shnum; i++) {
2232 s = sm_table[i].s;
2233 if (!s || !sm_table[i].new_section)
2234 continue;
2235 sh = &shdr[i];
2236 if (sh->sh_link > 0)
2237 s->link = sm_table[sh->sh_link].s;
2238 if (sh->sh_type == SHT_RELX) {
2239 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2240 /* update backward link */
2241 s1->sections[s->sh_info]->reloc = s;
2244 sm = sm_table;
2246 /* resolve symbols */
2247 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2249 sym = symtab + 1;
2250 for(i = 1; i < nb_syms; i++, sym++) {
2251 if (sym->st_shndx != SHN_UNDEF &&
2252 sym->st_shndx < SHN_LORESERVE) {
2253 sm = &sm_table[sym->st_shndx];
2254 if (sm->link_once) {
2255 /* if a symbol is in a link once section, we use the
2256 already defined symbol. It is very important to get
2257 correct relocations */
2258 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2259 name = strtab + sym->st_name;
2260 sym_index = find_elf_sym(symtab_section, name);
2261 if (sym_index)
2262 old_to_new_syms[i] = sym_index;
2264 continue;
2266 /* if no corresponding section added, no need to add symbol */
2267 if (!sm->s)
2268 continue;
2269 /* convert section number */
2270 sym->st_shndx = sm->s->sh_num;
2271 /* offset value */
2272 sym->st_value += sm->offset;
2274 /* add symbol */
2275 name = strtab + sym->st_name;
2276 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2277 sym->st_info, sym->st_other,
2278 sym->st_shndx, name);
2279 old_to_new_syms[i] = sym_index;
2282 /* third pass to patch relocation entries */
2283 for(i = 1; i < ehdr.e_shnum; i++) {
2284 s = sm_table[i].s;
2285 if (!s)
2286 continue;
2287 sh = &shdr[i];
2288 offset = sm_table[i].offset;
2289 switch(s->sh_type) {
2290 case SHT_RELX:
2291 /* take relocation offset information */
2292 offseti = sm_table[sh->sh_info].offset;
2293 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2294 for(rel = (ElfW_Rel *)(s->data + offset);
2295 rel < rel_end;
2296 rel++) {
2297 int type;
2298 unsigned sym_index;
2299 /* convert symbol index */
2300 type = ELFW(R_TYPE)(rel->r_info);
2301 sym_index = ELFW(R_SYM)(rel->r_info);
2302 /* NOTE: only one symtab assumed */
2303 if (sym_index >= nb_syms)
2304 goto invalid_reloc;
2305 sym_index = old_to_new_syms[sym_index];
2306 /* ignore link_once in rel section. */
2307 if (!sym_index && !sm->link_once) {
2308 invalid_reloc:
2309 error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2310 i, strsec + sh->sh_name, rel->r_offset);
2311 goto fail;
2313 rel->r_info = ELFW(R_INFO)(sym_index, type);
2314 /* offset the relocation offset */
2315 rel->r_offset += offseti;
2317 break;
2318 default:
2319 break;
2323 ret = 0;
2324 the_end:
2325 tcc_free(symtab);
2326 tcc_free(strtab);
2327 tcc_free(old_to_new_syms);
2328 tcc_free(sm_table);
2329 tcc_free(strsec);
2330 tcc_free(shdr);
2331 return ret;
2334 #define ARMAG "!<arch>\012" /* For COFF and a.out archives */
2336 typedef struct ArchiveHeader {
2337 char ar_name[16]; /* name of this member */
2338 char ar_date[12]; /* file mtime */
2339 char ar_uid[6]; /* owner uid; printed as decimal */
2340 char ar_gid[6]; /* owner gid; printed as decimal */
2341 char ar_mode[8]; /* file mode, printed as octal */
2342 char ar_size[10]; /* file size, printed as decimal */
2343 char ar_fmag[2]; /* should contain ARFMAG */
2344 } ArchiveHeader;
2346 static int get_be32(const uint8_t *b)
2348 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2351 /* load only the objects which resolve undefined symbols */
2352 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2354 int i, bound, nsyms, sym_index, off, ret;
2355 uint8_t *data;
2356 const char *ar_names, *p;
2357 const uint8_t *ar_index;
2358 ElfW(Sym) *sym;
2360 data = tcc_malloc(size);
2361 if (read(fd, data, size) != size)
2362 goto fail;
2363 nsyms = get_be32(data);
2364 ar_index = data + 4;
2365 ar_names = ar_index + nsyms * 4;
2367 do {
2368 bound = 0;
2369 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2370 sym_index = find_elf_sym(symtab_section, p);
2371 if(sym_index) {
2372 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2373 if(sym->st_shndx == SHN_UNDEF) {
2374 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2375 #if 0
2376 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2377 #endif
2378 ++bound;
2379 lseek(fd, off, SEEK_SET);
2380 if(tcc_load_object_file(s1, fd, off) < 0) {
2381 fail:
2382 ret = -1;
2383 goto the_end;
2388 } while(bound);
2389 ret = 0;
2390 the_end:
2391 tcc_free(data);
2392 return ret;
2395 /* load a '.a' file */
2396 static int tcc_load_archive(TCCState *s1, int fd)
2398 ArchiveHeader hdr;
2399 char ar_size[11];
2400 char ar_name[17];
2401 char magic[8];
2402 int size, len, i;
2403 unsigned long file_offset;
2405 /* skip magic which was already checked */
2406 read(fd, magic, sizeof(magic));
2408 for(;;) {
2409 len = read(fd, &hdr, sizeof(hdr));
2410 if (len == 0)
2411 break;
2412 if (len != sizeof(hdr)) {
2413 error_noabort("invalid archive");
2414 return -1;
2416 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2417 ar_size[sizeof(hdr.ar_size)] = '\0';
2418 size = strtol(ar_size, NULL, 0);
2419 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2420 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2421 if (ar_name[i] != ' ')
2422 break;
2424 ar_name[i + 1] = '\0';
2425 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2426 file_offset = lseek(fd, 0, SEEK_CUR);
2427 /* align to even */
2428 size = (size + 1) & ~1;
2429 if (!strcmp(ar_name, "/")) {
2430 /* coff symbol table : we handle it */
2431 if(s1->alacarte_link)
2432 return tcc_load_alacarte(s1, fd, size);
2433 } else if (!strcmp(ar_name, "//") ||
2434 !strcmp(ar_name, "__.SYMDEF") ||
2435 !strcmp(ar_name, "__.SYMDEF/") ||
2436 !strcmp(ar_name, "ARFILENAMES/")) {
2437 /* skip symbol table or archive names */
2438 } else {
2439 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2440 return -1;
2442 lseek(fd, file_offset + size, SEEK_SET);
2444 return 0;
2447 #ifndef TCC_TARGET_PE
2448 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2449 is referenced by the user (so it should be added as DT_NEEDED in
2450 the generated ELF file) */
2451 static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2453 ElfW(Ehdr) ehdr;
2454 ElfW(Shdr) *shdr, *sh, *sh1;
2455 int i, j, nb_syms, nb_dts, sym_bind, ret;
2456 ElfW(Sym) *sym, *dynsym;
2457 ElfW(Dyn) *dt, *dynamic;
2458 unsigned char *dynstr;
2459 const char *name, *soname;
2460 DLLReference *dllref;
2462 read(fd, &ehdr, sizeof(ehdr));
2464 /* test CPU specific stuff */
2465 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2466 ehdr.e_machine != EM_TCC_TARGET) {
2467 error_noabort("bad architecture");
2468 return -1;
2471 /* read sections */
2472 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2474 /* load dynamic section and dynamic symbols */
2475 nb_syms = 0;
2476 nb_dts = 0;
2477 dynamic = NULL;
2478 dynsym = NULL; /* avoid warning */
2479 dynstr = NULL; /* avoid warning */
2480 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2481 switch(sh->sh_type) {
2482 case SHT_DYNAMIC:
2483 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2484 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2485 break;
2486 case SHT_DYNSYM:
2487 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2488 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2489 sh1 = &shdr[sh->sh_link];
2490 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2491 break;
2492 default:
2493 break;
2497 /* compute the real library name */
2498 soname = tcc_basename(filename);
2500 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2501 if (dt->d_tag == DT_SONAME) {
2502 soname = dynstr + dt->d_un.d_val;
2506 /* if the dll is already loaded, do not load it */
2507 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2508 dllref = s1->loaded_dlls[i];
2509 if (!strcmp(soname, dllref->name)) {
2510 /* but update level if needed */
2511 if (level < dllref->level)
2512 dllref->level = level;
2513 ret = 0;
2514 goto the_end;
2518 // printf("loading dll '%s'\n", soname);
2520 /* add the dll and its level */
2521 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2522 dllref->level = level;
2523 strcpy(dllref->name, soname);
2524 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2526 /* add dynamic symbols in dynsym_section */
2527 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2528 sym_bind = ELFW(ST_BIND)(sym->st_info);
2529 if (sym_bind == STB_LOCAL)
2530 continue;
2531 name = dynstr + sym->st_name;
2532 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2533 sym->st_info, sym->st_other, sym->st_shndx, name);
2536 /* load all referenced DLLs */
2537 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2538 switch(dt->d_tag) {
2539 case DT_NEEDED:
2540 name = dynstr + dt->d_un.d_val;
2541 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2542 dllref = s1->loaded_dlls[j];
2543 if (!strcmp(name, dllref->name))
2544 goto already_loaded;
2546 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2547 error_noabort("referenced dll '%s' not found", name);
2548 ret = -1;
2549 goto the_end;
2551 already_loaded:
2552 break;
2555 ret = 0;
2556 the_end:
2557 tcc_free(dynstr);
2558 tcc_free(dynsym);
2559 tcc_free(dynamic);
2560 tcc_free(shdr);
2561 return ret;
2564 #define LD_TOK_NAME 256
2565 #define LD_TOK_EOF (-1)
2567 /* return next ld script token */
2568 static int ld_next(TCCState *s1, char *name, int name_size)
2570 int c;
2571 char *q;
2573 redo:
2574 switch(ch) {
2575 case ' ':
2576 case '\t':
2577 case '\f':
2578 case '\v':
2579 case '\r':
2580 case '\n':
2581 inp();
2582 goto redo;
2583 case '/':
2584 minp();
2585 if (ch == '*') {
2586 file->buf_ptr = parse_comment(file->buf_ptr);
2587 ch = file->buf_ptr[0];
2588 goto redo;
2589 } else {
2590 q = name;
2591 *q++ = '/';
2592 goto parse_name;
2594 break;
2595 /* case 'a' ... 'z': */
2596 case 'a':
2597 case 'b':
2598 case 'c':
2599 case 'd':
2600 case 'e':
2601 case 'f':
2602 case 'g':
2603 case 'h':
2604 case 'i':
2605 case 'j':
2606 case 'k':
2607 case 'l':
2608 case 'm':
2609 case 'n':
2610 case 'o':
2611 case 'p':
2612 case 'q':
2613 case 'r':
2614 case 's':
2615 case 't':
2616 case 'u':
2617 case 'v':
2618 case 'w':
2619 case 'x':
2620 case 'y':
2621 case 'z':
2622 /* case 'A' ... 'z': */
2623 case 'A':
2624 case 'B':
2625 case 'C':
2626 case 'D':
2627 case 'E':
2628 case 'F':
2629 case 'G':
2630 case 'H':
2631 case 'I':
2632 case 'J':
2633 case 'K':
2634 case 'L':
2635 case 'M':
2636 case 'N':
2637 case 'O':
2638 case 'P':
2639 case 'Q':
2640 case 'R':
2641 case 'S':
2642 case 'T':
2643 case 'U':
2644 case 'V':
2645 case 'W':
2646 case 'X':
2647 case 'Y':
2648 case 'Z':
2649 case '_':
2650 case '\\':
2651 case '.':
2652 case '$':
2653 case '~':
2654 q = name;
2655 parse_name:
2656 for(;;) {
2657 if (!((ch >= 'a' && ch <= 'z') ||
2658 (ch >= 'A' && ch <= 'Z') ||
2659 (ch >= '0' && ch <= '9') ||
2660 strchr("/.-_+=$:\\,~", ch)))
2661 break;
2662 if ((q - name) < name_size - 1) {
2663 *q++ = ch;
2665 minp();
2667 *q = '\0';
2668 c = LD_TOK_NAME;
2669 break;
2670 case CH_EOF:
2671 c = LD_TOK_EOF;
2672 break;
2673 default:
2674 c = ch;
2675 inp();
2676 break;
2678 #if 0
2679 printf("tok=%c %d\n", c, c);
2680 if (c == LD_TOK_NAME)
2681 printf(" name=%s\n", name);
2682 #endif
2683 return c;
2686 static int ld_add_file_list(TCCState *s1, int as_needed)
2688 char filename[1024];
2689 int t, ret;
2691 t = ld_next(s1, filename, sizeof(filename));
2692 if (t != '(')
2693 expect("(");
2694 t = ld_next(s1, filename, sizeof(filename));
2695 for(;;) {
2696 if (t == LD_TOK_EOF) {
2697 error_noabort("unexpected end of file");
2698 return -1;
2699 } else if (t == ')') {
2700 break;
2701 } else if (t != LD_TOK_NAME) {
2702 error_noabort("filename expected");
2703 return -1;
2705 if (!strcmp(filename, "AS_NEEDED")) {
2706 ret = ld_add_file_list(s1, 1);
2707 if (ret)
2708 return ret;
2709 } else {
2710 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2711 if (!as_needed)
2712 tcc_add_file(s1, filename);
2714 t = ld_next(s1, filename, sizeof(filename));
2715 if (t == ',') {
2716 t = ld_next(s1, filename, sizeof(filename));
2719 return 0;
2722 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
2723 files */
2724 static int tcc_load_ldscript(TCCState *s1)
2726 char cmd[64];
2727 char filename[1024];
2728 int t, ret;
2730 ch = file->buf_ptr[0];
2731 ch = handle_eob();
2732 for(;;) {
2733 t = ld_next(s1, cmd, sizeof(cmd));
2734 if (t == LD_TOK_EOF)
2735 return 0;
2736 else if (t != LD_TOK_NAME)
2737 return -1;
2738 if (!strcmp(cmd, "INPUT") ||
2739 !strcmp(cmd, "GROUP")) {
2740 ret = ld_add_file_list(s1, 0);
2741 if (ret)
2742 return ret;
2743 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
2744 !strcmp(cmd, "TARGET")) {
2745 /* ignore some commands */
2746 t = ld_next(s1, cmd, sizeof(cmd));
2747 if (t != '(')
2748 expect("(");
2749 for(;;) {
2750 t = ld_next(s1, filename, sizeof(filename));
2751 if (t == LD_TOK_EOF) {
2752 error_noabort("unexpected end of file");
2753 return -1;
2754 } else if (t == ')') {
2755 break;
2758 } else {
2759 return -1;
2762 return 0;
2764 #endif