win32: enable bounds checker & exception handler
[tinycc.git] / tccelf.c
blob1b4a804c500711779d6ae39d77d367f1b1422acf
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 static void tcc_add_bcheck(TCCState *s1)
1191 #ifdef CONFIG_TCC_BCHECK
1192 unsigned long *ptr;
1193 Section *init_section;
1194 unsigned char *pinit;
1195 int sym_index;
1197 if (0 == s1->do_bounds_check)
1198 return;
1200 /* XXX: add an object file to do that */
1201 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1202 *ptr = 0;
1203 add_elf_sym(symtab_section, 0, 0,
1204 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1205 bounds_section->sh_num, "__bounds_start");
1206 /* add bound check code */
1207 #ifndef TCC_TARGET_PE
1209 char buf[1024];
1210 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "bcheck.o");
1211 tcc_add_file(s1, buf);
1213 #endif
1214 #ifdef TCC_TARGET_I386
1215 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1216 /* add 'call __bound_init()' in .init section */
1217 init_section = find_section(s1, ".init");
1218 pinit = section_ptr_add(init_section, 5);
1219 pinit[0] = 0xe8;
1220 put32(pinit + 1, -4);
1221 sym_index = find_elf_sym(symtab_section, "__bound_init");
1222 put_elf_reloc(symtab_section, init_section,
1223 init_section->data_offset - 4, R_386_PC32, sym_index);
1225 #endif
1226 #endif
1229 /* add tcc runtime libraries */
1230 static void tcc_add_runtime(TCCState *s1)
1232 tcc_add_bcheck(s1);
1234 /* add libc */
1235 if (!s1->nostdlib) {
1236 #ifdef CONFIG_USE_LIBGCC
1237 tcc_add_library(s1, "c");
1238 tcc_add_file(s1, CONFIG_SYSROOT "/lib/libgcc_s.so.1");
1239 #else
1240 char buf[1024];
1241 tcc_add_library(s1, "c");
1242 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "libtcc1.a");
1243 tcc_add_file(s1, buf);
1244 #endif
1246 /* add crt end if not memory output */
1247 if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) {
1248 tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
1252 /* add various standard linker symbols (must be done after the
1253 sections are filled (for example after allocating common
1254 symbols)) */
1255 static void tcc_add_linker_symbols(TCCState *s1)
1257 char buf[1024];
1258 int i;
1259 Section *s;
1261 add_elf_sym(symtab_section,
1262 text_section->data_offset, 0,
1263 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1264 text_section->sh_num, "_etext");
1265 add_elf_sym(symtab_section,
1266 data_section->data_offset, 0,
1267 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1268 data_section->sh_num, "_edata");
1269 add_elf_sym(symtab_section,
1270 bss_section->data_offset, 0,
1271 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1272 bss_section->sh_num, "_end");
1273 /* horrible new standard ldscript defines */
1274 add_init_array_defines(s1, ".preinit_array");
1275 add_init_array_defines(s1, ".init_array");
1276 add_init_array_defines(s1, ".fini_array");
1278 /* add start and stop symbols for sections whose name can be
1279 expressed in C */
1280 for(i = 1; i < s1->nb_sections; i++) {
1281 s = s1->sections[i];
1282 if (s->sh_type == SHT_PROGBITS &&
1283 (s->sh_flags & SHF_ALLOC)) {
1284 const char *p;
1285 int ch;
1287 /* check if section name can be expressed in C */
1288 p = s->name;
1289 for(;;) {
1290 ch = *p;
1291 if (!ch)
1292 break;
1293 if (!isid(ch) && !isnum(ch))
1294 goto next_sec;
1295 p++;
1297 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1298 add_elf_sym(symtab_section,
1299 0, 0,
1300 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1301 s->sh_num, buf);
1302 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1303 add_elf_sym(symtab_section,
1304 s->data_offset, 0,
1305 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1306 s->sh_num, buf);
1308 next_sec: ;
1312 /* name of ELF interpreter */
1313 #if defined __FreeBSD__
1314 static const char elf_interp[] = "/libexec/ld-elf.so.1";
1315 #elif defined TCC_ARM_EABI
1316 static const char elf_interp[] = "/lib/ld-linux.so.3";
1317 #elif defined(TCC_TARGET_X86_64)
1318 static const char elf_interp[] = "/lib/ld-linux-x86-64.so.2";
1319 #elif defined(TCC_UCLIBC)
1320 static const char elf_interp[] = "/lib/ld-uClibc.so.0";
1321 #else
1322 static const char elf_interp[] = "/lib/ld-linux.so.2";
1323 #endif
1325 static void tcc_output_binary(TCCState *s1, FILE *f,
1326 const int *section_order)
1328 Section *s;
1329 int i, offset, size;
1331 offset = 0;
1332 for(i=1;i<s1->nb_sections;i++) {
1333 s = s1->sections[section_order[i]];
1334 if (s->sh_type != SHT_NOBITS &&
1335 (s->sh_flags & SHF_ALLOC)) {
1336 while (offset < s->sh_offset) {
1337 fputc(0, f);
1338 offset++;
1340 size = s->sh_size;
1341 fwrite(s->data, 1, size, f);
1342 offset += size;
1347 #if defined(__FreeBSD__)
1348 #define HAVE_PHDR 1
1349 #define EXTRA_RELITEMS 14
1351 /* move the relocation value from .dynsym to .got */
1352 void patch_dynsym_undef(TCCState *s1, Section *s)
1354 uint32_t *gotd = (void *)s1->got->data;
1355 ElfW(Sym) *sym, *sym_end;
1357 gotd += 3; // dummy entries in .got
1358 /* relocate symbols in .dynsym */
1359 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1360 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1361 if (sym->st_shndx == SHN_UNDEF) {
1362 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1363 sym->st_value = 0;
1367 #else
1368 #define HAVE_PHDR 0
1369 #define EXTRA_RELITEMS 9
1370 #endif
1372 /* output an ELF file */
1373 /* XXX: suppress unneeded sections */
1374 int elf_output_file(TCCState *s1, const char *filename)
1376 ElfW(Ehdr) ehdr;
1377 FILE *f;
1378 int fd, mode, ret;
1379 int *section_order;
1380 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
1381 unsigned long addr;
1382 Section *strsec, *s;
1383 ElfW(Shdr) shdr, *sh;
1384 ElfW(Phdr) *phdr, *ph;
1385 Section *interp, *dynamic, *dynstr;
1386 unsigned long saved_dynamic_data_offset;
1387 ElfW(Sym) *sym;
1388 int type, file_type;
1389 unsigned long rel_addr, rel_size;
1390 unsigned long bss_addr, bss_size;
1392 file_type = s1->output_type;
1393 s1->nb_errors = 0;
1395 if (file_type != TCC_OUTPUT_OBJ) {
1396 tcc_add_runtime(s1);
1399 phdr = NULL;
1400 section_order = NULL;
1401 interp = NULL;
1402 dynamic = NULL;
1403 dynstr = NULL; /* avoid warning */
1404 saved_dynamic_data_offset = 0; /* avoid warning */
1406 if (file_type != TCC_OUTPUT_OBJ) {
1407 relocate_common_syms();
1409 tcc_add_linker_symbols(s1);
1411 if (!s1->static_link) {
1412 const char *name;
1413 int sym_index, index;
1414 ElfW(Sym) *esym, *sym_end;
1416 if (file_type == TCC_OUTPUT_EXE) {
1417 char *ptr;
1418 /* allow override the dynamic loader */
1419 const char *elfint = getenv("LD_SO");
1420 if (elfint == NULL)
1421 elfint = elf_interp;
1422 /* add interpreter section only if executable */
1423 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1424 interp->sh_addralign = 1;
1425 ptr = section_ptr_add(interp, 1+strlen(elfint));
1426 strcpy(ptr, elfint);
1429 /* add dynamic symbol table */
1430 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1431 ".dynstr",
1432 ".hash", SHF_ALLOC);
1433 dynstr = s1->dynsym->link;
1435 /* add dynamic section */
1436 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1437 SHF_ALLOC | SHF_WRITE);
1438 dynamic->link = dynstr;
1439 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1441 /* add PLT */
1442 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1443 SHF_ALLOC | SHF_EXECINSTR);
1444 s1->plt->sh_entsize = 4;
1446 build_got(s1);
1448 /* scan for undefined symbols and see if they are in the
1449 dynamic symbols. If a symbol STT_FUNC is found, then we
1450 add it in the PLT. If a symbol STT_OBJECT is found, we
1451 add it in the .bss section with a suitable relocation */
1452 sym_end = (ElfW(Sym) *)(symtab_section->data +
1453 symtab_section->data_offset);
1454 if (file_type == TCC_OUTPUT_EXE) {
1455 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1456 sym < sym_end;
1457 sym++) {
1458 if (sym->st_shndx == SHN_UNDEF) {
1459 name = symtab_section->link->data + sym->st_name;
1460 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1461 if (sym_index) {
1462 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1463 type = ELFW(ST_TYPE)(esym->st_info);
1464 if (type == STT_FUNC) {
1465 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1466 esym->st_info,
1467 sym - (ElfW(Sym) *)symtab_section->data);
1468 } else if (type == STT_OBJECT) {
1469 unsigned long offset;
1470 offset = bss_section->data_offset;
1471 /* XXX: which alignment ? */
1472 offset = (offset + 16 - 1) & -16;
1473 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1474 esym->st_info, 0,
1475 bss_section->sh_num, name);
1476 put_elf_reloc(s1->dynsym, bss_section,
1477 offset, R_COPY, index);
1478 offset += esym->st_size;
1479 bss_section->data_offset = offset;
1481 } else {
1482 /* STB_WEAK undefined symbols are accepted */
1483 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1484 it */
1485 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1486 !strcmp(name, "_fp_hw")) {
1487 } else {
1488 error_noabort("undefined symbol '%s'", name);
1491 } else if (s1->rdynamic &&
1492 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1493 /* if -rdynamic option, then export all non
1494 local symbols */
1495 name = symtab_section->link->data + sym->st_name;
1496 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1497 sym->st_info, 0,
1498 sym->st_shndx, name);
1502 if (s1->nb_errors)
1503 goto fail;
1505 /* now look at unresolved dynamic symbols and export
1506 corresponding symbol */
1507 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1508 s1->dynsymtab_section->data_offset);
1509 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1510 esym < sym_end;
1511 esym++) {
1512 if (esym->st_shndx == SHN_UNDEF) {
1513 name = s1->dynsymtab_section->link->data + esym->st_name;
1514 sym_index = find_elf_sym(symtab_section, name);
1515 if (sym_index) {
1516 /* XXX: avoid adding a symbol if already
1517 present because of -rdynamic ? */
1518 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1519 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1520 sym->st_info, 0,
1521 sym->st_shndx, name);
1522 } else {
1523 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1524 /* weak symbols can stay undefined */
1525 } else {
1526 warning("undefined dynamic symbol '%s'", name);
1531 } else {
1532 int nb_syms;
1533 /* shared library case : we simply export all the global symbols */
1534 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1535 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1536 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1537 sym < sym_end;
1538 sym++) {
1539 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1540 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1541 if (ELFW(ST_TYPE)(sym->st_info) == STT_FUNC &&
1542 sym->st_shndx == SHN_UNDEF) {
1543 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1544 sym->st_info,
1545 sym - (ElfW(Sym) *)symtab_section->data);
1547 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1548 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1549 sym->st_info,
1550 sym - (ElfW(Sym) *)symtab_section->data);
1552 else
1553 #endif
1555 name = symtab_section->link->data + sym->st_name;
1556 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1557 sym->st_info, 0,
1558 sym->st_shndx, name);
1559 s1->symtab_to_dynsym[sym -
1560 (ElfW(Sym) *)symtab_section->data] =
1561 index;
1567 build_got_entries(s1);
1569 /* add a list of needed dlls */
1570 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1571 DLLReference *dllref = s1->loaded_dlls[i];
1572 if (dllref->level == 0)
1573 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1576 if (s1->rpath)
1577 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1579 /* XXX: currently, since we do not handle PIC code, we
1580 must relocate the readonly segments */
1581 if (file_type == TCC_OUTPUT_DLL) {
1582 if (s1->soname)
1583 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1584 put_dt(dynamic, DT_TEXTREL, 0);
1586 /* add necessary space for other entries */
1587 saved_dynamic_data_offset = dynamic->data_offset;
1588 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1589 } else {
1590 /* still need to build got entries in case of static link */
1591 build_got_entries(s1);
1595 memset(&ehdr, 0, sizeof(ehdr));
1597 /* we add a section for symbols */
1598 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1599 put_elf_str(strsec, "");
1601 /* compute number of sections */
1602 shnum = s1->nb_sections;
1604 /* this array is used to reorder sections in the output file */
1605 section_order = tcc_malloc(sizeof(int) * shnum);
1606 section_order[0] = 0;
1607 sh_order_index = 1;
1609 /* compute number of program headers */
1610 switch(file_type) {
1611 default:
1612 case TCC_OUTPUT_OBJ:
1613 phnum = 0;
1614 break;
1615 case TCC_OUTPUT_EXE:
1616 if (!s1->static_link)
1617 phnum = 4 + HAVE_PHDR;
1618 else
1619 phnum = 2;
1620 break;
1621 case TCC_OUTPUT_DLL:
1622 phnum = 3;
1623 break;
1626 /* allocate strings for section names and decide if an unallocated
1627 section should be output */
1628 /* NOTE: the strsec section comes last, so its size is also
1629 correct ! */
1630 for(i = 1; i < s1->nb_sections; i++) {
1631 s = s1->sections[i];
1632 s->sh_name = put_elf_str(strsec, s->name);
1633 #if 0 //gr
1634 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1635 s->sh_flags,
1636 s->sh_type,
1637 s->sh_info,
1638 s->name,
1639 s->reloc ? s->reloc->name : "n"
1641 #endif
1642 /* when generating a DLL, we include relocations but we may
1643 patch them */
1644 if (file_type == TCC_OUTPUT_DLL &&
1645 s->sh_type == SHT_RELX &&
1646 !(s->sh_flags & SHF_ALLOC)) {
1647 /* //gr: avoid bogus relocs for empty (debug) sections */
1648 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1649 prepare_dynamic_rel(s1, s);
1650 else if (s1->do_debug)
1651 s->sh_size = s->data_offset;
1652 } else if (s1->do_debug ||
1653 file_type == TCC_OUTPUT_OBJ ||
1654 (s->sh_flags & SHF_ALLOC) ||
1655 i == (s1->nb_sections - 1)) {
1656 /* we output all sections if debug or object file */
1657 s->sh_size = s->data_offset;
1661 /* allocate program segment headers */
1662 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1664 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1665 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1666 } else {
1667 file_offset = 0;
1669 if (phnum > 0) {
1670 /* compute section to program header mapping */
1671 if (s1->has_text_addr) {
1672 int a_offset, p_offset;
1673 addr = s1->text_addr;
1674 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1675 ELF_PAGE_SIZE */
1676 a_offset = addr & (s1->section_align - 1);
1677 p_offset = file_offset & (s1->section_align - 1);
1678 if (a_offset < p_offset)
1679 a_offset += s1->section_align;
1680 file_offset += (a_offset - p_offset);
1681 } else {
1682 if (file_type == TCC_OUTPUT_DLL)
1683 addr = 0;
1684 else
1685 addr = ELF_START_ADDR;
1686 /* compute address after headers */
1687 addr += (file_offset & (s1->section_align - 1));
1690 /* dynamic relocation table information, for .dynamic section */
1691 rel_size = 0;
1692 rel_addr = 0;
1694 bss_addr = bss_size = 0;
1695 /* leave one program header for the program interpreter */
1696 ph = &phdr[0];
1697 if (interp)
1698 ph += 1 + HAVE_PHDR;
1700 for(j = 0; j < 2; j++) {
1701 ph->p_type = PT_LOAD;
1702 if (j == 0)
1703 ph->p_flags = PF_R | PF_X;
1704 else
1705 ph->p_flags = PF_R | PF_W;
1706 ph->p_align = s1->section_align;
1708 /* we do the following ordering: interp, symbol tables,
1709 relocations, progbits, nobits */
1710 /* XXX: do faster and simpler sorting */
1711 for(k = 0; k < 5; k++) {
1712 for(i = 1; i < s1->nb_sections; i++) {
1713 s = s1->sections[i];
1714 /* compute if section should be included */
1715 if (j == 0) {
1716 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1717 SHF_ALLOC)
1718 continue;
1719 } else {
1720 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1721 (SHF_ALLOC | SHF_WRITE))
1722 continue;
1724 if (s == interp) {
1725 if (k != 0)
1726 continue;
1727 } else if (s->sh_type == SHT_DYNSYM ||
1728 s->sh_type == SHT_STRTAB ||
1729 s->sh_type == SHT_HASH) {
1730 if (k != 1)
1731 continue;
1732 } else if (s->sh_type == SHT_RELX) {
1733 if (k != 2)
1734 continue;
1735 } else if (s->sh_type == SHT_NOBITS) {
1736 if (k != 4)
1737 continue;
1738 } else {
1739 if (k != 3)
1740 continue;
1742 section_order[sh_order_index++] = i;
1744 /* section matches: we align it and add its size */
1745 tmp = addr;
1746 addr = (addr + s->sh_addralign - 1) &
1747 ~(s->sh_addralign - 1);
1748 file_offset += addr - tmp;
1749 s->sh_offset = file_offset;
1750 s->sh_addr = addr;
1752 /* update program header infos */
1753 if (ph->p_offset == 0) {
1754 ph->p_offset = file_offset;
1755 ph->p_vaddr = addr;
1756 ph->p_paddr = ph->p_vaddr;
1758 /* update dynamic relocation infos */
1759 if (s->sh_type == SHT_RELX) {
1760 #if defined(__FreeBSD__)
1761 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1762 rel_addr = addr;
1763 rel_size += s->sh_size; // XXX only first rel.
1765 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1766 bss_addr = addr;
1767 bss_size = s->sh_size; // XXX only first rel.
1769 #else
1770 if (rel_size == 0)
1771 rel_addr = addr;
1772 rel_size += s->sh_size;
1773 #endif
1775 addr += s->sh_size;
1776 if (s->sh_type != SHT_NOBITS)
1777 file_offset += s->sh_size;
1780 ph->p_filesz = file_offset - ph->p_offset;
1781 ph->p_memsz = addr - ph->p_vaddr;
1782 ph++;
1783 if (j == 0) {
1784 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1785 /* if in the middle of a page, we duplicate the page in
1786 memory so that one copy is RX and the other is RW */
1787 if ((addr & (s1->section_align - 1)) != 0)
1788 addr += s1->section_align;
1789 } else {
1790 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1791 file_offset = (file_offset + s1->section_align - 1) &
1792 ~(s1->section_align - 1);
1797 /* if interpreter, then add corresponing program header */
1798 if (interp) {
1799 ph = &phdr[0];
1801 #if defined(__FreeBSD__)
1803 int len = phnum * sizeof(ElfW(Phdr));
1805 ph->p_type = PT_PHDR;
1806 ph->p_offset = sizeof(ElfW(Ehdr));
1807 ph->p_vaddr = interp->sh_addr - len;
1808 ph->p_paddr = ph->p_vaddr;
1809 ph->p_filesz = ph->p_memsz = len;
1810 ph->p_flags = PF_R | PF_X;
1811 ph->p_align = 4; // interp->sh_addralign;
1812 ph++;
1814 #endif
1816 ph->p_type = PT_INTERP;
1817 ph->p_offset = interp->sh_offset;
1818 ph->p_vaddr = interp->sh_addr;
1819 ph->p_paddr = ph->p_vaddr;
1820 ph->p_filesz = interp->sh_size;
1821 ph->p_memsz = interp->sh_size;
1822 ph->p_flags = PF_R;
1823 ph->p_align = interp->sh_addralign;
1826 /* if dynamic section, then add corresponing program header */
1827 if (dynamic) {
1828 ElfW(Sym) *sym_end;
1830 ph = &phdr[phnum - 1];
1832 ph->p_type = PT_DYNAMIC;
1833 ph->p_offset = dynamic->sh_offset;
1834 ph->p_vaddr = dynamic->sh_addr;
1835 ph->p_paddr = ph->p_vaddr;
1836 ph->p_filesz = dynamic->sh_size;
1837 ph->p_memsz = dynamic->sh_size;
1838 ph->p_flags = PF_R | PF_W;
1839 ph->p_align = dynamic->sh_addralign;
1841 /* put GOT dynamic section address */
1842 put32(s1->got->data, dynamic->sh_addr);
1844 /* relocate the PLT */
1845 if (file_type == TCC_OUTPUT_EXE
1846 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1847 || file_type == TCC_OUTPUT_DLL
1848 #endif
1850 uint8_t *p, *p_end;
1852 p = s1->plt->data;
1853 p_end = p + s1->plt->data_offset;
1854 if (p < p_end) {
1855 #if defined(TCC_TARGET_I386)
1856 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1857 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1858 p += 16;
1859 while (p < p_end) {
1860 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1861 p += 16;
1863 #elif defined(TCC_TARGET_X86_64)
1864 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1865 put32(p + 2, get32(p + 2) + x);
1866 put32(p + 8, get32(p + 8) + x - 6);
1867 p += 16;
1868 while (p < p_end) {
1869 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1870 p += 16;
1872 #elif defined(TCC_TARGET_ARM)
1873 int x;
1874 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1875 p +=16;
1876 while (p < p_end) {
1877 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1878 p += 16;
1880 #elif defined(TCC_TARGET_C67)
1881 /* XXX: TODO */
1882 #else
1883 #error unsupported CPU
1884 #endif
1888 /* relocate symbols in .dynsym */
1889 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
1890 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
1891 sym < sym_end;
1892 sym++) {
1893 if (sym->st_shndx == SHN_UNDEF) {
1894 /* relocate to the PLT if the symbol corresponds
1895 to a PLT entry */
1896 if (sym->st_value)
1897 sym->st_value += s1->plt->sh_addr;
1898 } else if (sym->st_shndx < SHN_LORESERVE) {
1899 /* do symbol relocation */
1900 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
1904 /* put dynamic section entries */
1905 dynamic->data_offset = saved_dynamic_data_offset;
1906 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
1907 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
1908 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
1909 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
1910 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
1911 #ifdef TCC_TARGET_X86_64
1912 put_dt(dynamic, DT_RELA, rel_addr);
1913 put_dt(dynamic, DT_RELASZ, rel_size);
1914 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
1915 #else
1916 #if defined(__FreeBSD__)
1917 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
1918 put_dt(dynamic, DT_PLTRELSZ, rel_size);
1919 put_dt(dynamic, DT_JMPREL, rel_addr);
1920 put_dt(dynamic, DT_PLTREL, DT_REL);
1921 put_dt(dynamic, DT_REL, bss_addr);
1922 put_dt(dynamic, DT_RELSZ, bss_size);
1923 #else
1924 put_dt(dynamic, DT_REL, rel_addr);
1925 put_dt(dynamic, DT_RELSZ, rel_size);
1926 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
1927 #endif
1928 #endif
1929 if (s1->do_debug)
1930 put_dt(dynamic, DT_DEBUG, 0);
1931 put_dt(dynamic, DT_NULL, 0);
1934 ehdr.e_phentsize = sizeof(ElfW(Phdr));
1935 ehdr.e_phnum = phnum;
1936 ehdr.e_phoff = sizeof(ElfW(Ehdr));
1939 /* all other sections come after */
1940 for(i = 1; i < s1->nb_sections; i++) {
1941 s = s1->sections[i];
1942 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
1943 continue;
1944 section_order[sh_order_index++] = i;
1946 file_offset = (file_offset + s->sh_addralign - 1) &
1947 ~(s->sh_addralign - 1);
1948 s->sh_offset = file_offset;
1949 if (s->sh_type != SHT_NOBITS)
1950 file_offset += s->sh_size;
1953 /* if building executable or DLL, then relocate each section
1954 except the GOT which is already relocated */
1955 if (file_type != TCC_OUTPUT_OBJ) {
1956 relocate_syms(s1, 0);
1958 if (s1->nb_errors != 0) {
1959 fail:
1960 ret = -1;
1961 goto the_end;
1964 /* relocate sections */
1965 /* XXX: ignore sections with allocated relocations ? */
1966 for(i = 1; i < s1->nb_sections; i++) {
1967 s = s1->sections[i];
1968 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
1969 relocate_section(s1, s);
1972 /* relocate relocation entries if the relocation tables are
1973 allocated in the executable */
1974 for(i = 1; i < s1->nb_sections; i++) {
1975 s = s1->sections[i];
1976 if ((s->sh_flags & SHF_ALLOC) &&
1977 s->sh_type == SHT_RELX) {
1978 relocate_rel(s1, s);
1982 /* get entry point address */
1983 if (file_type == TCC_OUTPUT_EXE)
1984 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
1985 else
1986 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
1989 /* write elf file */
1990 if (file_type == TCC_OUTPUT_OBJ)
1991 mode = 0666;
1992 else
1993 mode = 0777;
1994 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
1995 if (fd < 0) {
1996 error_noabort("could not write '%s'", filename);
1997 goto fail;
1999 f = fdopen(fd, "wb");
2000 if (s1->verbose)
2001 printf("<- %s\n", filename);
2003 #ifdef TCC_TARGET_COFF
2004 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2005 tcc_output_coff(s1, f);
2006 } else
2007 #endif
2008 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2009 sort_syms(s1, symtab_section);
2011 /* align to 4 */
2012 file_offset = (file_offset + 3) & -4;
2014 /* fill header */
2015 ehdr.e_ident[0] = ELFMAG0;
2016 ehdr.e_ident[1] = ELFMAG1;
2017 ehdr.e_ident[2] = ELFMAG2;
2018 ehdr.e_ident[3] = ELFMAG3;
2019 ehdr.e_ident[4] = TCC_ELFCLASS;
2020 ehdr.e_ident[5] = ELFDATA2LSB;
2021 ehdr.e_ident[6] = EV_CURRENT;
2022 #ifdef __FreeBSD__
2023 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2024 #endif
2025 #ifdef TCC_TARGET_ARM
2026 #ifdef TCC_ARM_EABI
2027 ehdr.e_ident[EI_OSABI] = 0;
2028 ehdr.e_flags = 4 << 24;
2029 #else
2030 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2031 #endif
2032 #endif
2033 switch(file_type) {
2034 default:
2035 case TCC_OUTPUT_EXE:
2036 ehdr.e_type = ET_EXEC;
2037 break;
2038 case TCC_OUTPUT_DLL:
2039 ehdr.e_type = ET_DYN;
2040 break;
2041 case TCC_OUTPUT_OBJ:
2042 ehdr.e_type = ET_REL;
2043 break;
2045 ehdr.e_machine = EM_TCC_TARGET;
2046 ehdr.e_version = EV_CURRENT;
2047 ehdr.e_shoff = file_offset;
2048 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2049 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2050 ehdr.e_shnum = shnum;
2051 ehdr.e_shstrndx = shnum - 1;
2053 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2054 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2055 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2057 for(i=1;i<s1->nb_sections;i++) {
2058 s = s1->sections[section_order[i]];
2059 if (s->sh_type != SHT_NOBITS) {
2060 #if defined(__FreeBSD__)
2061 if (s->sh_type == SHT_DYNSYM)
2062 patch_dynsym_undef(s1, s);
2063 #endif
2064 while (offset < s->sh_offset) {
2065 fputc(0, f);
2066 offset++;
2068 size = s->sh_size;
2069 fwrite(s->data, 1, size, f);
2070 offset += size;
2074 /* output section headers */
2075 while (offset < ehdr.e_shoff) {
2076 fputc(0, f);
2077 offset++;
2080 for(i=0;i<s1->nb_sections;i++) {
2081 sh = &shdr;
2082 memset(sh, 0, sizeof(ElfW(Shdr)));
2083 s = s1->sections[i];
2084 if (s) {
2085 sh->sh_name = s->sh_name;
2086 sh->sh_type = s->sh_type;
2087 sh->sh_flags = s->sh_flags;
2088 sh->sh_entsize = s->sh_entsize;
2089 sh->sh_info = s->sh_info;
2090 if (s->link)
2091 sh->sh_link = s->link->sh_num;
2092 sh->sh_addralign = s->sh_addralign;
2093 sh->sh_addr = s->sh_addr;
2094 sh->sh_offset = s->sh_offset;
2095 sh->sh_size = s->sh_size;
2097 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2099 } else {
2100 tcc_output_binary(s1, f, section_order);
2102 fclose(f);
2104 ret = 0;
2105 the_end:
2106 tcc_free(s1->symtab_to_dynsym);
2107 tcc_free(section_order);
2108 tcc_free(phdr);
2109 tcc_free(s1->got_offsets);
2110 return ret;
2113 int tcc_output_file(TCCState *s, const char *filename)
2115 int ret;
2116 #ifdef TCC_TARGET_PE
2117 if (s->output_type != TCC_OUTPUT_OBJ) {
2118 ret = pe_output_file(s, filename);
2119 } else
2120 #endif
2122 ret = elf_output_file(s, filename);
2124 return ret;
2127 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2129 void *data;
2131 data = tcc_malloc(size);
2132 lseek(fd, file_offset, SEEK_SET);
2133 read(fd, data, size);
2134 return data;
2137 typedef struct SectionMergeInfo {
2138 Section *s; /* corresponding existing section */
2139 unsigned long offset; /* offset of the new section in the existing section */
2140 uint8_t new_section; /* true if section 's' was added */
2141 uint8_t link_once; /* true if link once section */
2142 } SectionMergeInfo;
2144 /* load an object file and merge it with current files */
2145 /* XXX: handle correctly stab (debug) info */
2146 static int tcc_load_object_file(TCCState *s1,
2147 int fd, unsigned long file_offset)
2149 ElfW(Ehdr) ehdr;
2150 ElfW(Shdr) *shdr, *sh;
2151 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2152 unsigned char *strsec, *strtab;
2153 int *old_to_new_syms;
2154 char *sh_name, *name;
2155 SectionMergeInfo *sm_table, *sm;
2156 ElfW(Sym) *sym, *symtab;
2157 ElfW_Rel *rel, *rel_end;
2158 Section *s;
2160 int stab_index;
2161 int stabstr_index;
2163 stab_index = stabstr_index = 0;
2165 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2166 goto fail1;
2167 if (ehdr.e_ident[0] != ELFMAG0 ||
2168 ehdr.e_ident[1] != ELFMAG1 ||
2169 ehdr.e_ident[2] != ELFMAG2 ||
2170 ehdr.e_ident[3] != ELFMAG3)
2171 goto fail1;
2172 /* test if object file */
2173 if (ehdr.e_type != ET_REL)
2174 goto fail1;
2175 /* test CPU specific stuff */
2176 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2177 ehdr.e_machine != EM_TCC_TARGET) {
2178 fail1:
2179 error_noabort("invalid object file");
2180 return -1;
2182 /* read sections */
2183 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2184 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2185 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2187 /* load section names */
2188 sh = &shdr[ehdr.e_shstrndx];
2189 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2191 /* load symtab and strtab */
2192 old_to_new_syms = NULL;
2193 symtab = NULL;
2194 strtab = NULL;
2195 nb_syms = 0;
2196 for(i = 1; i < ehdr.e_shnum; i++) {
2197 sh = &shdr[i];
2198 if (sh->sh_type == SHT_SYMTAB) {
2199 if (symtab) {
2200 error_noabort("object must contain only one symtab");
2201 fail:
2202 ret = -1;
2203 goto the_end;
2205 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2206 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2207 sm_table[i].s = symtab_section;
2209 /* now load strtab */
2210 sh = &shdr[sh->sh_link];
2211 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2215 /* now examine each section and try to merge its content with the
2216 ones in memory */
2217 for(i = 1; i < ehdr.e_shnum; i++) {
2218 /* no need to examine section name strtab */
2219 if (i == ehdr.e_shstrndx)
2220 continue;
2221 sh = &shdr[i];
2222 sh_name = strsec + sh->sh_name;
2223 /* ignore sections types we do not handle */
2224 if (sh->sh_type != SHT_PROGBITS &&
2225 sh->sh_type != SHT_RELX &&
2226 #ifdef TCC_ARM_EABI
2227 sh->sh_type != SHT_ARM_EXIDX &&
2228 #endif
2229 sh->sh_type != SHT_NOBITS &&
2230 strcmp(sh_name, ".stabstr")
2232 continue;
2233 if (sh->sh_addralign < 1)
2234 sh->sh_addralign = 1;
2235 /* find corresponding section, if any */
2236 for(j = 1; j < s1->nb_sections;j++) {
2237 s = s1->sections[j];
2238 if (!strcmp(s->name, sh_name)) {
2239 if (!strncmp(sh_name, ".gnu.linkonce",
2240 sizeof(".gnu.linkonce") - 1)) {
2241 /* if a 'linkonce' section is already present, we
2242 do not add it again. It is a little tricky as
2243 symbols can still be defined in
2244 it. */
2245 sm_table[i].link_once = 1;
2246 goto next;
2247 } else {
2248 goto found;
2252 /* not found: create new section */
2253 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2254 /* take as much info as possible from the section. sh_link and
2255 sh_info will be updated later */
2256 s->sh_addralign = sh->sh_addralign;
2257 s->sh_entsize = sh->sh_entsize;
2258 sm_table[i].new_section = 1;
2259 found:
2260 if (sh->sh_type != s->sh_type) {
2261 error_noabort("invalid section type");
2262 goto fail;
2265 /* align start of section */
2266 offset = s->data_offset;
2268 if (0 == strcmp(sh_name, ".stab")) {
2269 stab_index = i;
2270 goto no_align;
2272 if (0 == strcmp(sh_name, ".stabstr")) {
2273 stabstr_index = i;
2274 goto no_align;
2277 size = sh->sh_addralign - 1;
2278 offset = (offset + size) & ~size;
2279 if (sh->sh_addralign > s->sh_addralign)
2280 s->sh_addralign = sh->sh_addralign;
2281 s->data_offset = offset;
2282 no_align:
2283 sm_table[i].offset = offset;
2284 sm_table[i].s = s;
2285 /* concatenate sections */
2286 size = sh->sh_size;
2287 if (sh->sh_type != SHT_NOBITS) {
2288 unsigned char *ptr;
2289 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2290 ptr = section_ptr_add(s, size);
2291 read(fd, ptr, size);
2292 } else {
2293 s->data_offset += size;
2295 next: ;
2298 /* //gr relocate stab strings */
2299 if (stab_index && stabstr_index) {
2300 Stab_Sym *a, *b;
2301 unsigned o;
2302 s = sm_table[stab_index].s;
2303 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2304 b = (Stab_Sym *)(s->data + s->data_offset);
2305 o = sm_table[stabstr_index].offset;
2306 while (a < b)
2307 a->n_strx += o, a++;
2310 /* second short pass to update sh_link and sh_info fields of new
2311 sections */
2312 for(i = 1; i < ehdr.e_shnum; i++) {
2313 s = sm_table[i].s;
2314 if (!s || !sm_table[i].new_section)
2315 continue;
2316 sh = &shdr[i];
2317 if (sh->sh_link > 0)
2318 s->link = sm_table[sh->sh_link].s;
2319 if (sh->sh_type == SHT_RELX) {
2320 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2321 /* update backward link */
2322 s1->sections[s->sh_info]->reloc = s;
2325 sm = sm_table;
2327 /* resolve symbols */
2328 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2330 sym = symtab + 1;
2331 for(i = 1; i < nb_syms; i++, sym++) {
2332 if (sym->st_shndx != SHN_UNDEF &&
2333 sym->st_shndx < SHN_LORESERVE) {
2334 sm = &sm_table[sym->st_shndx];
2335 if (sm->link_once) {
2336 /* if a symbol is in a link once section, we use the
2337 already defined symbol. It is very important to get
2338 correct relocations */
2339 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2340 name = strtab + sym->st_name;
2341 sym_index = find_elf_sym(symtab_section, name);
2342 if (sym_index)
2343 old_to_new_syms[i] = sym_index;
2345 continue;
2347 /* if no corresponding section added, no need to add symbol */
2348 if (!sm->s)
2349 continue;
2350 /* convert section number */
2351 sym->st_shndx = sm->s->sh_num;
2352 /* offset value */
2353 sym->st_value += sm->offset;
2355 /* add symbol */
2356 name = strtab + sym->st_name;
2357 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2358 sym->st_info, sym->st_other,
2359 sym->st_shndx, name);
2360 old_to_new_syms[i] = sym_index;
2363 /* third pass to patch relocation entries */
2364 for(i = 1; i < ehdr.e_shnum; i++) {
2365 s = sm_table[i].s;
2366 if (!s)
2367 continue;
2368 sh = &shdr[i];
2369 offset = sm_table[i].offset;
2370 switch(s->sh_type) {
2371 case SHT_RELX:
2372 /* take relocation offset information */
2373 offseti = sm_table[sh->sh_info].offset;
2374 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2375 for(rel = (ElfW_Rel *)(s->data + offset);
2376 rel < rel_end;
2377 rel++) {
2378 int type;
2379 unsigned sym_index;
2380 /* convert symbol index */
2381 type = ELFW(R_TYPE)(rel->r_info);
2382 sym_index = ELFW(R_SYM)(rel->r_info);
2383 /* NOTE: only one symtab assumed */
2384 if (sym_index >= nb_syms)
2385 goto invalid_reloc;
2386 sym_index = old_to_new_syms[sym_index];
2387 /* ignore link_once in rel section. */
2388 if (!sym_index && !sm->link_once) {
2389 invalid_reloc:
2390 error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2391 i, strsec + sh->sh_name, rel->r_offset);
2392 goto fail;
2394 rel->r_info = ELFW(R_INFO)(sym_index, type);
2395 /* offset the relocation offset */
2396 rel->r_offset += offseti;
2398 break;
2399 default:
2400 break;
2404 ret = 0;
2405 the_end:
2406 tcc_free(symtab);
2407 tcc_free(strtab);
2408 tcc_free(old_to_new_syms);
2409 tcc_free(sm_table);
2410 tcc_free(strsec);
2411 tcc_free(shdr);
2412 return ret;
2415 #define ARMAG "!<arch>\012" /* For COFF and a.out archives */
2417 typedef struct ArchiveHeader {
2418 char ar_name[16]; /* name of this member */
2419 char ar_date[12]; /* file mtime */
2420 char ar_uid[6]; /* owner uid; printed as decimal */
2421 char ar_gid[6]; /* owner gid; printed as decimal */
2422 char ar_mode[8]; /* file mode, printed as octal */
2423 char ar_size[10]; /* file size, printed as decimal */
2424 char ar_fmag[2]; /* should contain ARFMAG */
2425 } ArchiveHeader;
2427 static int get_be32(const uint8_t *b)
2429 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2432 /* load only the objects which resolve undefined symbols */
2433 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2435 int i, bound, nsyms, sym_index, off, ret;
2436 uint8_t *data;
2437 const char *ar_names, *p;
2438 const uint8_t *ar_index;
2439 ElfW(Sym) *sym;
2441 data = tcc_malloc(size);
2442 if (read(fd, data, size) != size)
2443 goto fail;
2444 nsyms = get_be32(data);
2445 ar_index = data + 4;
2446 ar_names = ar_index + nsyms * 4;
2448 do {
2449 bound = 0;
2450 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2451 sym_index = find_elf_sym(symtab_section, p);
2452 if(sym_index) {
2453 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2454 if(sym->st_shndx == SHN_UNDEF) {
2455 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2456 #if 0
2457 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2458 #endif
2459 ++bound;
2460 lseek(fd, off, SEEK_SET);
2461 if(tcc_load_object_file(s1, fd, off) < 0) {
2462 fail:
2463 ret = -1;
2464 goto the_end;
2469 } while(bound);
2470 ret = 0;
2471 the_end:
2472 tcc_free(data);
2473 return ret;
2476 /* load a '.a' file */
2477 static int tcc_load_archive(TCCState *s1, int fd)
2479 ArchiveHeader hdr;
2480 char ar_size[11];
2481 char ar_name[17];
2482 char magic[8];
2483 int size, len, i;
2484 unsigned long file_offset;
2486 /* skip magic which was already checked */
2487 read(fd, magic, sizeof(magic));
2489 for(;;) {
2490 len = read(fd, &hdr, sizeof(hdr));
2491 if (len == 0)
2492 break;
2493 if (len != sizeof(hdr)) {
2494 error_noabort("invalid archive");
2495 return -1;
2497 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2498 ar_size[sizeof(hdr.ar_size)] = '\0';
2499 size = strtol(ar_size, NULL, 0);
2500 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2501 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2502 if (ar_name[i] != ' ')
2503 break;
2505 ar_name[i + 1] = '\0';
2506 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2507 file_offset = lseek(fd, 0, SEEK_CUR);
2508 /* align to even */
2509 size = (size + 1) & ~1;
2510 if (!strcmp(ar_name, "/")) {
2511 /* coff symbol table : we handle it */
2512 if(s1->alacarte_link)
2513 return tcc_load_alacarte(s1, fd, size);
2514 } else if (!strcmp(ar_name, "//") ||
2515 !strcmp(ar_name, "__.SYMDEF") ||
2516 !strcmp(ar_name, "__.SYMDEF/") ||
2517 !strcmp(ar_name, "ARFILENAMES/")) {
2518 /* skip symbol table or archive names */
2519 } else {
2520 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2521 return -1;
2523 lseek(fd, file_offset + size, SEEK_SET);
2525 return 0;
2528 #ifndef TCC_TARGET_PE
2529 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2530 is referenced by the user (so it should be added as DT_NEEDED in
2531 the generated ELF file) */
2532 static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2534 ElfW(Ehdr) ehdr;
2535 ElfW(Shdr) *shdr, *sh, *sh1;
2536 int i, j, nb_syms, nb_dts, sym_bind, ret;
2537 ElfW(Sym) *sym, *dynsym;
2538 ElfW(Dyn) *dt, *dynamic;
2539 unsigned char *dynstr;
2540 const char *name, *soname;
2541 DLLReference *dllref;
2543 read(fd, &ehdr, sizeof(ehdr));
2545 /* test CPU specific stuff */
2546 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2547 ehdr.e_machine != EM_TCC_TARGET) {
2548 error_noabort("bad architecture");
2549 return -1;
2552 /* read sections */
2553 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2555 /* load dynamic section and dynamic symbols */
2556 nb_syms = 0;
2557 nb_dts = 0;
2558 dynamic = NULL;
2559 dynsym = NULL; /* avoid warning */
2560 dynstr = NULL; /* avoid warning */
2561 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2562 switch(sh->sh_type) {
2563 case SHT_DYNAMIC:
2564 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2565 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2566 break;
2567 case SHT_DYNSYM:
2568 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2569 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2570 sh1 = &shdr[sh->sh_link];
2571 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2572 break;
2573 default:
2574 break;
2578 /* compute the real library name */
2579 soname = tcc_basename(filename);
2581 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2582 if (dt->d_tag == DT_SONAME) {
2583 soname = dynstr + dt->d_un.d_val;
2587 /* if the dll is already loaded, do not load it */
2588 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2589 dllref = s1->loaded_dlls[i];
2590 if (!strcmp(soname, dllref->name)) {
2591 /* but update level if needed */
2592 if (level < dllref->level)
2593 dllref->level = level;
2594 ret = 0;
2595 goto the_end;
2599 // printf("loading dll '%s'\n", soname);
2601 /* add the dll and its level */
2602 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2603 dllref->level = level;
2604 strcpy(dllref->name, soname);
2605 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2607 /* add dynamic symbols in dynsym_section */
2608 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2609 sym_bind = ELFW(ST_BIND)(sym->st_info);
2610 if (sym_bind == STB_LOCAL)
2611 continue;
2612 name = dynstr + sym->st_name;
2613 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2614 sym->st_info, sym->st_other, sym->st_shndx, name);
2617 /* load all referenced DLLs */
2618 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2619 switch(dt->d_tag) {
2620 case DT_NEEDED:
2621 name = dynstr + dt->d_un.d_val;
2622 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2623 dllref = s1->loaded_dlls[j];
2624 if (!strcmp(name, dllref->name))
2625 goto already_loaded;
2627 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2628 error_noabort("referenced dll '%s' not found", name);
2629 ret = -1;
2630 goto the_end;
2632 already_loaded:
2633 break;
2636 ret = 0;
2637 the_end:
2638 tcc_free(dynstr);
2639 tcc_free(dynsym);
2640 tcc_free(dynamic);
2641 tcc_free(shdr);
2642 return ret;
2645 #define LD_TOK_NAME 256
2646 #define LD_TOK_EOF (-1)
2648 /* return next ld script token */
2649 static int ld_next(TCCState *s1, char *name, int name_size)
2651 int c;
2652 char *q;
2654 redo:
2655 switch(ch) {
2656 case ' ':
2657 case '\t':
2658 case '\f':
2659 case '\v':
2660 case '\r':
2661 case '\n':
2662 inp();
2663 goto redo;
2664 case '/':
2665 minp();
2666 if (ch == '*') {
2667 file->buf_ptr = parse_comment(file->buf_ptr);
2668 ch = file->buf_ptr[0];
2669 goto redo;
2670 } else {
2671 q = name;
2672 *q++ = '/';
2673 goto parse_name;
2675 break;
2676 /* case 'a' ... 'z': */
2677 case 'a':
2678 case 'b':
2679 case 'c':
2680 case 'd':
2681 case 'e':
2682 case 'f':
2683 case 'g':
2684 case 'h':
2685 case 'i':
2686 case 'j':
2687 case 'k':
2688 case 'l':
2689 case 'm':
2690 case 'n':
2691 case 'o':
2692 case 'p':
2693 case 'q':
2694 case 'r':
2695 case 's':
2696 case 't':
2697 case 'u':
2698 case 'v':
2699 case 'w':
2700 case 'x':
2701 case 'y':
2702 case 'z':
2703 /* case 'A' ... 'z': */
2704 case 'A':
2705 case 'B':
2706 case 'C':
2707 case 'D':
2708 case 'E':
2709 case 'F':
2710 case 'G':
2711 case 'H':
2712 case 'I':
2713 case 'J':
2714 case 'K':
2715 case 'L':
2716 case 'M':
2717 case 'N':
2718 case 'O':
2719 case 'P':
2720 case 'Q':
2721 case 'R':
2722 case 'S':
2723 case 'T':
2724 case 'U':
2725 case 'V':
2726 case 'W':
2727 case 'X':
2728 case 'Y':
2729 case 'Z':
2730 case '_':
2731 case '\\':
2732 case '.':
2733 case '$':
2734 case '~':
2735 q = name;
2736 parse_name:
2737 for(;;) {
2738 if (!((ch >= 'a' && ch <= 'z') ||
2739 (ch >= 'A' && ch <= 'Z') ||
2740 (ch >= '0' && ch <= '9') ||
2741 strchr("/.-_+=$:\\,~", ch)))
2742 break;
2743 if ((q - name) < name_size - 1) {
2744 *q++ = ch;
2746 minp();
2748 *q = '\0';
2749 c = LD_TOK_NAME;
2750 break;
2751 case CH_EOF:
2752 c = LD_TOK_EOF;
2753 break;
2754 default:
2755 c = ch;
2756 inp();
2757 break;
2759 #if 0
2760 printf("tok=%c %d\n", c, c);
2761 if (c == LD_TOK_NAME)
2762 printf(" name=%s\n", name);
2763 #endif
2764 return c;
2767 static int ld_add_file_list(TCCState *s1, int as_needed)
2769 char filename[1024];
2770 int t, ret;
2772 t = ld_next(s1, filename, sizeof(filename));
2773 if (t != '(')
2774 expect("(");
2775 t = ld_next(s1, filename, sizeof(filename));
2776 for(;;) {
2777 if (t == LD_TOK_EOF) {
2778 error_noabort("unexpected end of file");
2779 return -1;
2780 } else if (t == ')') {
2781 break;
2782 } else if (t != LD_TOK_NAME) {
2783 error_noabort("filename expected");
2784 return -1;
2786 if (!strcmp(filename, "AS_NEEDED")) {
2787 ret = ld_add_file_list(s1, 1);
2788 if (ret)
2789 return ret;
2790 } else {
2791 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2792 if (!as_needed)
2793 tcc_add_file(s1, filename);
2795 t = ld_next(s1, filename, sizeof(filename));
2796 if (t == ',') {
2797 t = ld_next(s1, filename, sizeof(filename));
2800 return 0;
2803 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
2804 files */
2805 static int tcc_load_ldscript(TCCState *s1)
2807 char cmd[64];
2808 char filename[1024];
2809 int t, ret;
2811 ch = file->buf_ptr[0];
2812 ch = handle_eob();
2813 for(;;) {
2814 t = ld_next(s1, cmd, sizeof(cmd));
2815 if (t == LD_TOK_EOF)
2816 return 0;
2817 else if (t != LD_TOK_NAME)
2818 return -1;
2819 if (!strcmp(cmd, "INPUT") ||
2820 !strcmp(cmd, "GROUP")) {
2821 ret = ld_add_file_list(s1, 0);
2822 if (ret)
2823 return ret;
2824 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
2825 !strcmp(cmd, "TARGET")) {
2826 /* ignore some commands */
2827 t = ld_next(s1, cmd, sizeof(cmd));
2828 if (t != '(')
2829 expect("(");
2830 for(;;) {
2831 t = ld_next(s1, filename, sizeof(filename));
2832 if (t == LD_TOK_EOF) {
2833 error_noabort("unexpected end of file");
2834 return -1;
2835 } else if (t == ')') {
2836 break;
2839 } else {
2840 return -1;
2843 return 0;
2845 #endif