x86-64: fix udiv, add cqto instruction
[tinycc/kirr.git] / tccelf.c
blobdc0c948169fa235d2fd34848cc8d3e38ca0d45c7
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[] = "/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 #if defined(__FreeBSD__)
1339 #define HAVE_PHDR 1
1340 #define EXTRA_RELITEMS 14
1342 /* move the relocation value from .dynsym to .got */
1343 void patch_dynsym_undef(TCCState *s1, Section *s)
1345 uint32_t *gotd = (void *)s1->got->data;
1346 ElfW(Sym) *sym, *sym_end;
1348 gotd += 3; // dummy entries in .got
1349 /* relocate symbols in .dynsym */
1350 sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1351 for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1352 if (sym->st_shndx == SHN_UNDEF) {
1353 *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1354 sym->st_value = 0;
1358 #else
1359 #define HAVE_PHDR 0
1360 #define EXTRA_RELITEMS 9
1361 #endif
1363 /* output an ELF file */
1364 /* XXX: suppress unneeded sections */
1365 int elf_output_file(TCCState *s1, const char *filename)
1367 ElfW(Ehdr) ehdr;
1368 FILE *f;
1369 int fd, mode, ret;
1370 int *section_order;
1371 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
1372 unsigned long addr;
1373 Section *strsec, *s;
1374 ElfW(Shdr) shdr, *sh;
1375 ElfW(Phdr) *phdr, *ph;
1376 Section *interp, *dynamic, *dynstr;
1377 unsigned long saved_dynamic_data_offset;
1378 ElfW(Sym) *sym;
1379 int type, file_type;
1380 unsigned long rel_addr, rel_size;
1381 unsigned long bss_addr, bss_size;
1383 file_type = s1->output_type;
1384 s1->nb_errors = 0;
1386 if (file_type != TCC_OUTPUT_OBJ) {
1387 tcc_add_runtime(s1);
1390 phdr = NULL;
1391 section_order = NULL;
1392 interp = NULL;
1393 dynamic = NULL;
1394 dynstr = NULL; /* avoid warning */
1395 saved_dynamic_data_offset = 0; /* avoid warning */
1397 if (file_type != TCC_OUTPUT_OBJ) {
1398 relocate_common_syms();
1400 tcc_add_linker_symbols(s1);
1402 if (!s1->static_link) {
1403 const char *name;
1404 int sym_index, index;
1405 ElfW(Sym) *esym, *sym_end;
1407 if (file_type == TCC_OUTPUT_EXE) {
1408 char *ptr;
1409 /* allow override the dynamic loader */
1410 const char *elfint = getenv("LD_SO");
1411 if (elfint == NULL)
1412 elfint = elf_interp;
1413 /* add interpreter section only if executable */
1414 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1415 interp->sh_addralign = 1;
1416 ptr = section_ptr_add(interp, 1+strlen(elfint));
1417 strcpy(ptr, elfint);
1420 /* add dynamic symbol table */
1421 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1422 ".dynstr",
1423 ".hash", SHF_ALLOC);
1424 dynstr = s1->dynsym->link;
1426 /* add dynamic section */
1427 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1428 SHF_ALLOC | SHF_WRITE);
1429 dynamic->link = dynstr;
1430 dynamic->sh_entsize = sizeof(ElfW(Dyn));
1432 /* add PLT */
1433 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1434 SHF_ALLOC | SHF_EXECINSTR);
1435 s1->plt->sh_entsize = 4;
1437 build_got(s1);
1439 /* scan for undefined symbols and see if they are in the
1440 dynamic symbols. If a symbol STT_FUNC is found, then we
1441 add it in the PLT. If a symbol STT_OBJECT is found, we
1442 add it in the .bss section with a suitable relocation */
1443 sym_end = (ElfW(Sym) *)(symtab_section->data +
1444 symtab_section->data_offset);
1445 if (file_type == TCC_OUTPUT_EXE) {
1446 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1447 sym < sym_end;
1448 sym++) {
1449 if (sym->st_shndx == SHN_UNDEF) {
1450 name = symtab_section->link->data + sym->st_name;
1451 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1452 if (sym_index) {
1453 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1454 type = ELFW(ST_TYPE)(esym->st_info);
1455 if (type == STT_FUNC) {
1456 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1457 esym->st_info,
1458 sym - (ElfW(Sym) *)symtab_section->data);
1459 } else if (type == STT_OBJECT) {
1460 unsigned long offset;
1461 offset = bss_section->data_offset;
1462 /* XXX: which alignment ? */
1463 offset = (offset + 16 - 1) & -16;
1464 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1465 esym->st_info, 0,
1466 bss_section->sh_num, name);
1467 put_elf_reloc(s1->dynsym, bss_section,
1468 offset, R_COPY, index);
1469 offset += esym->st_size;
1470 bss_section->data_offset = offset;
1472 } else {
1473 /* STB_WEAK undefined symbols are accepted */
1474 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1475 it */
1476 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1477 !strcmp(name, "_fp_hw")) {
1478 } else {
1479 error_noabort("undefined symbol '%s'", name);
1482 } else if (s1->rdynamic &&
1483 ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1484 /* if -rdynamic option, then export all non
1485 local symbols */
1486 name = symtab_section->link->data + sym->st_name;
1487 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1488 sym->st_info, 0,
1489 sym->st_shndx, name);
1493 if (s1->nb_errors)
1494 goto fail;
1496 /* now look at unresolved dynamic symbols and export
1497 corresponding symbol */
1498 sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1499 s1->dynsymtab_section->data_offset);
1500 for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1501 esym < sym_end;
1502 esym++) {
1503 if (esym->st_shndx == SHN_UNDEF) {
1504 name = s1->dynsymtab_section->link->data + esym->st_name;
1505 sym_index = find_elf_sym(symtab_section, name);
1506 if (sym_index) {
1507 /* XXX: avoid adding a symbol if already
1508 present because of -rdynamic ? */
1509 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1510 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1511 sym->st_info, 0,
1512 sym->st_shndx, name);
1513 } else {
1514 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1515 /* weak symbols can stay undefined */
1516 } else {
1517 warning("undefined dynamic symbol '%s'", name);
1522 } else {
1523 int nb_syms;
1524 /* shared library case : we simply export all the global symbols */
1525 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1526 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1527 for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1528 sym < sym_end;
1529 sym++) {
1530 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1531 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1532 if (ELFW(ST_TYPE)(sym->st_info) == STT_FUNC &&
1533 sym->st_shndx == SHN_UNDEF) {
1534 put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1535 sym->st_info,
1536 sym - (ElfW(Sym) *)symtab_section->data);
1538 else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1539 put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1540 sym->st_info,
1541 sym - (ElfW(Sym) *)symtab_section->data);
1543 else
1544 #endif
1546 name = symtab_section->link->data + sym->st_name;
1547 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1548 sym->st_info, 0,
1549 sym->st_shndx, name);
1550 s1->symtab_to_dynsym[sym -
1551 (ElfW(Sym) *)symtab_section->data] =
1552 index;
1558 build_got_entries(s1);
1560 /* add a list of needed dlls */
1561 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1562 DLLReference *dllref = s1->loaded_dlls[i];
1563 if (dllref->level == 0)
1564 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1566 /* XXX: currently, since we do not handle PIC code, we
1567 must relocate the readonly segments */
1568 if (file_type == TCC_OUTPUT_DLL) {
1569 if (s1->soname)
1570 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1571 put_dt(dynamic, DT_TEXTREL, 0);
1574 /* add necessary space for other entries */
1575 saved_dynamic_data_offset = dynamic->data_offset;
1576 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1577 } else {
1578 /* still need to build got entries in case of static link */
1579 build_got_entries(s1);
1583 memset(&ehdr, 0, sizeof(ehdr));
1585 /* we add a section for symbols */
1586 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1587 put_elf_str(strsec, "");
1589 /* compute number of sections */
1590 shnum = s1->nb_sections;
1592 /* this array is used to reorder sections in the output file */
1593 section_order = tcc_malloc(sizeof(int) * shnum);
1594 section_order[0] = 0;
1595 sh_order_index = 1;
1597 /* compute number of program headers */
1598 switch(file_type) {
1599 default:
1600 case TCC_OUTPUT_OBJ:
1601 phnum = 0;
1602 break;
1603 case TCC_OUTPUT_EXE:
1604 if (!s1->static_link)
1605 phnum = 4 + HAVE_PHDR;
1606 else
1607 phnum = 2;
1608 break;
1609 case TCC_OUTPUT_DLL:
1610 phnum = 3;
1611 break;
1614 /* allocate strings for section names and decide if an unallocated
1615 section should be output */
1616 /* NOTE: the strsec section comes last, so its size is also
1617 correct ! */
1618 for(i = 1; i < s1->nb_sections; i++) {
1619 s = s1->sections[i];
1620 s->sh_name = put_elf_str(strsec, s->name);
1621 #if 0 //gr
1622 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1623 s->sh_flags,
1624 s->sh_type,
1625 s->sh_info,
1626 s->name,
1627 s->reloc ? s->reloc->name : "n"
1629 #endif
1630 /* when generating a DLL, we include relocations but we may
1631 patch them */
1632 if (file_type == TCC_OUTPUT_DLL &&
1633 s->sh_type == SHT_RELX &&
1634 !(s->sh_flags & SHF_ALLOC)) {
1635 /* //gr: avoid bogus relocs for empty (debug) sections */
1636 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1637 prepare_dynamic_rel(s1, s);
1638 else if (s1->do_debug)
1639 s->sh_size = s->data_offset;
1640 } else if (s1->do_debug ||
1641 file_type == TCC_OUTPUT_OBJ ||
1642 (s->sh_flags & SHF_ALLOC) ||
1643 i == (s1->nb_sections - 1)) {
1644 /* we output all sections if debug or object file */
1645 s->sh_size = s->data_offset;
1649 /* allocate program segment headers */
1650 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1652 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1653 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1654 } else {
1655 file_offset = 0;
1657 if (phnum > 0) {
1658 /* compute section to program header mapping */
1659 if (s1->has_text_addr) {
1660 int a_offset, p_offset;
1661 addr = s1->text_addr;
1662 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1663 ELF_PAGE_SIZE */
1664 a_offset = addr & (s1->section_align - 1);
1665 p_offset = file_offset & (s1->section_align - 1);
1666 if (a_offset < p_offset)
1667 a_offset += s1->section_align;
1668 file_offset += (a_offset - p_offset);
1669 } else {
1670 if (file_type == TCC_OUTPUT_DLL)
1671 addr = 0;
1672 else
1673 addr = ELF_START_ADDR;
1674 /* compute address after headers */
1675 addr += (file_offset & (s1->section_align - 1));
1678 /* dynamic relocation table information, for .dynamic section */
1679 rel_size = 0;
1680 rel_addr = 0;
1682 bss_addr = bss_size = 0;
1683 /* leave one program header for the program interpreter */
1684 ph = &phdr[0];
1685 if (interp)
1686 ph += 1 + HAVE_PHDR;
1688 for(j = 0; j < 2; j++) {
1689 ph->p_type = PT_LOAD;
1690 if (j == 0)
1691 ph->p_flags = PF_R | PF_X;
1692 else
1693 ph->p_flags = PF_R | PF_W;
1694 ph->p_align = s1->section_align;
1696 /* we do the following ordering: interp, symbol tables,
1697 relocations, progbits, nobits */
1698 /* XXX: do faster and simpler sorting */
1699 for(k = 0; k < 5; k++) {
1700 for(i = 1; i < s1->nb_sections; i++) {
1701 s = s1->sections[i];
1702 /* compute if section should be included */
1703 if (j == 0) {
1704 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1705 SHF_ALLOC)
1706 continue;
1707 } else {
1708 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1709 (SHF_ALLOC | SHF_WRITE))
1710 continue;
1712 if (s == interp) {
1713 if (k != 0)
1714 continue;
1715 } else if (s->sh_type == SHT_DYNSYM ||
1716 s->sh_type == SHT_STRTAB ||
1717 s->sh_type == SHT_HASH) {
1718 if (k != 1)
1719 continue;
1720 } else if (s->sh_type == SHT_RELX) {
1721 if (k != 2)
1722 continue;
1723 } else if (s->sh_type == SHT_NOBITS) {
1724 if (k != 4)
1725 continue;
1726 } else {
1727 if (k != 3)
1728 continue;
1730 section_order[sh_order_index++] = i;
1732 /* section matches: we align it and add its size */
1733 tmp = addr;
1734 addr = (addr + s->sh_addralign - 1) &
1735 ~(s->sh_addralign - 1);
1736 file_offset += addr - tmp;
1737 s->sh_offset = file_offset;
1738 s->sh_addr = addr;
1740 /* update program header infos */
1741 if (ph->p_offset == 0) {
1742 ph->p_offset = file_offset;
1743 ph->p_vaddr = addr;
1744 ph->p_paddr = ph->p_vaddr;
1746 /* update dynamic relocation infos */
1747 if (s->sh_type == SHT_RELX) {
1748 #if defined(__FreeBSD__)
1749 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1750 rel_addr = addr;
1751 rel_size += s->sh_size; // XXX only first rel.
1753 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1754 bss_addr = addr;
1755 bss_size = s->sh_size; // XXX only first rel.
1757 #else
1758 if (rel_size == 0)
1759 rel_addr = addr;
1760 rel_size += s->sh_size;
1761 #endif
1763 addr += s->sh_size;
1764 if (s->sh_type != SHT_NOBITS)
1765 file_offset += s->sh_size;
1768 ph->p_filesz = file_offset - ph->p_offset;
1769 ph->p_memsz = addr - ph->p_vaddr;
1770 ph++;
1771 if (j == 0) {
1772 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1773 /* if in the middle of a page, we duplicate the page in
1774 memory so that one copy is RX and the other is RW */
1775 if ((addr & (s1->section_align - 1)) != 0)
1776 addr += s1->section_align;
1777 } else {
1778 addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1779 file_offset = (file_offset + s1->section_align - 1) &
1780 ~(s1->section_align - 1);
1785 /* if interpreter, then add corresponing program header */
1786 if (interp) {
1787 ph = &phdr[0];
1789 #if defined(__FreeBSD__)
1791 int len = phnum * sizeof(ElfW(Phdr));
1793 ph->p_type = PT_PHDR;
1794 ph->p_offset = sizeof(ElfW(Ehdr));
1795 ph->p_vaddr = interp->sh_addr - len;
1796 ph->p_paddr = ph->p_vaddr;
1797 ph->p_filesz = ph->p_memsz = len;
1798 ph->p_flags = PF_R | PF_X;
1799 ph->p_align = 4; // interp->sh_addralign;
1800 ph++;
1802 #endif
1804 ph->p_type = PT_INTERP;
1805 ph->p_offset = interp->sh_offset;
1806 ph->p_vaddr = interp->sh_addr;
1807 ph->p_paddr = ph->p_vaddr;
1808 ph->p_filesz = interp->sh_size;
1809 ph->p_memsz = interp->sh_size;
1810 ph->p_flags = PF_R;
1811 ph->p_align = interp->sh_addralign;
1814 /* if dynamic section, then add corresponing program header */
1815 if (dynamic) {
1816 ElfW(Sym) *sym_end;
1818 ph = &phdr[phnum - 1];
1820 ph->p_type = PT_DYNAMIC;
1821 ph->p_offset = dynamic->sh_offset;
1822 ph->p_vaddr = dynamic->sh_addr;
1823 ph->p_paddr = ph->p_vaddr;
1824 ph->p_filesz = dynamic->sh_size;
1825 ph->p_memsz = dynamic->sh_size;
1826 ph->p_flags = PF_R | PF_W;
1827 ph->p_align = dynamic->sh_addralign;
1829 /* put GOT dynamic section address */
1830 put32(s1->got->data, dynamic->sh_addr);
1832 /* relocate the PLT */
1833 if (file_type == TCC_OUTPUT_EXE
1834 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1835 || file_type == TCC_OUTPUT_DLL
1836 #endif
1838 uint8_t *p, *p_end;
1840 p = s1->plt->data;
1841 p_end = p + s1->plt->data_offset;
1842 if (p < p_end) {
1843 #if defined(TCC_TARGET_I386)
1844 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1845 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1846 p += 16;
1847 while (p < p_end) {
1848 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1849 p += 16;
1851 #elif defined(TCC_TARGET_X86_64)
1852 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1853 put32(p + 2, get32(p + 2) + x);
1854 put32(p + 8, get32(p + 8) + x - 6);
1855 p += 16;
1856 while (p < p_end) {
1857 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1858 p += 16;
1860 #elif defined(TCC_TARGET_ARM)
1861 int x;
1862 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1863 p +=16;
1864 while (p < p_end) {
1865 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1866 p += 16;
1868 #elif defined(TCC_TARGET_C67)
1869 /* XXX: TODO */
1870 #else
1871 #error unsupported CPU
1872 #endif
1876 /* relocate symbols in .dynsym */
1877 sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
1878 for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
1879 sym < sym_end;
1880 sym++) {
1881 if (sym->st_shndx == SHN_UNDEF) {
1882 /* relocate to the PLT if the symbol corresponds
1883 to a PLT entry */
1884 if (sym->st_value)
1885 sym->st_value += s1->plt->sh_addr;
1886 } else if (sym->st_shndx < SHN_LORESERVE) {
1887 /* do symbol relocation */
1888 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
1892 /* put dynamic section entries */
1893 dynamic->data_offset = saved_dynamic_data_offset;
1894 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
1895 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
1896 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
1897 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
1898 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
1899 #ifdef TCC_TARGET_X86_64
1900 put_dt(dynamic, DT_RELA, rel_addr);
1901 put_dt(dynamic, DT_RELASZ, rel_size);
1902 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
1903 #else
1904 #if defined(__FreeBSD__)
1905 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
1906 put_dt(dynamic, DT_PLTRELSZ, rel_size);
1907 put_dt(dynamic, DT_JMPREL, rel_addr);
1908 put_dt(dynamic, DT_PLTREL, DT_REL);
1909 put_dt(dynamic, DT_REL, bss_addr);
1910 put_dt(dynamic, DT_RELSZ, bss_size);
1911 #else
1912 put_dt(dynamic, DT_REL, rel_addr);
1913 put_dt(dynamic, DT_RELSZ, rel_size);
1914 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
1915 #endif
1916 #endif
1917 if (s1->do_debug)
1918 put_dt(dynamic, DT_DEBUG, 0);
1919 put_dt(dynamic, DT_NULL, 0);
1922 ehdr.e_phentsize = sizeof(ElfW(Phdr));
1923 ehdr.e_phnum = phnum;
1924 ehdr.e_phoff = sizeof(ElfW(Ehdr));
1927 /* all other sections come after */
1928 for(i = 1; i < s1->nb_sections; i++) {
1929 s = s1->sections[i];
1930 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
1931 continue;
1932 section_order[sh_order_index++] = i;
1934 file_offset = (file_offset + s->sh_addralign - 1) &
1935 ~(s->sh_addralign - 1);
1936 s->sh_offset = file_offset;
1937 if (s->sh_type != SHT_NOBITS)
1938 file_offset += s->sh_size;
1941 /* if building executable or DLL, then relocate each section
1942 except the GOT which is already relocated */
1943 if (file_type != TCC_OUTPUT_OBJ) {
1944 relocate_syms(s1, 0);
1946 if (s1->nb_errors != 0) {
1947 fail:
1948 ret = -1;
1949 goto the_end;
1952 /* relocate sections */
1953 /* XXX: ignore sections with allocated relocations ? */
1954 for(i = 1; i < s1->nb_sections; i++) {
1955 s = s1->sections[i];
1956 if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
1957 relocate_section(s1, s);
1960 /* relocate relocation entries if the relocation tables are
1961 allocated in the executable */
1962 for(i = 1; i < s1->nb_sections; i++) {
1963 s = s1->sections[i];
1964 if ((s->sh_flags & SHF_ALLOC) &&
1965 s->sh_type == SHT_RELX) {
1966 relocate_rel(s1, s);
1970 /* get entry point address */
1971 if (file_type == TCC_OUTPUT_EXE)
1972 ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
1973 else
1974 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
1977 /* write elf file */
1978 if (file_type == TCC_OUTPUT_OBJ)
1979 mode = 0666;
1980 else
1981 mode = 0777;
1982 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
1983 if (fd < 0) {
1984 error_noabort("could not write '%s'", filename);
1985 goto fail;
1987 f = fdopen(fd, "wb");
1988 if (s1->verbose)
1989 printf("<- %s\n", filename);
1991 #ifdef TCC_TARGET_COFF
1992 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
1993 tcc_output_coff(s1, f);
1994 } else
1995 #endif
1996 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1997 sort_syms(s1, symtab_section);
1999 /* align to 4 */
2000 file_offset = (file_offset + 3) & -4;
2002 /* fill header */
2003 ehdr.e_ident[0] = ELFMAG0;
2004 ehdr.e_ident[1] = ELFMAG1;
2005 ehdr.e_ident[2] = ELFMAG2;
2006 ehdr.e_ident[3] = ELFMAG3;
2007 ehdr.e_ident[4] = TCC_ELFCLASS;
2008 ehdr.e_ident[5] = ELFDATA2LSB;
2009 ehdr.e_ident[6] = EV_CURRENT;
2010 #ifdef __FreeBSD__
2011 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2012 #endif
2013 #ifdef TCC_TARGET_ARM
2014 #ifdef TCC_ARM_EABI
2015 ehdr.e_ident[EI_OSABI] = 0;
2016 ehdr.e_flags = 4 << 24;
2017 #else
2018 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2019 #endif
2020 #endif
2021 switch(file_type) {
2022 default:
2023 case TCC_OUTPUT_EXE:
2024 ehdr.e_type = ET_EXEC;
2025 break;
2026 case TCC_OUTPUT_DLL:
2027 ehdr.e_type = ET_DYN;
2028 break;
2029 case TCC_OUTPUT_OBJ:
2030 ehdr.e_type = ET_REL;
2031 break;
2033 ehdr.e_machine = EM_TCC_TARGET;
2034 ehdr.e_version = EV_CURRENT;
2035 ehdr.e_shoff = file_offset;
2036 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2037 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2038 ehdr.e_shnum = shnum;
2039 ehdr.e_shstrndx = shnum - 1;
2041 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2042 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2043 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2045 for(i=1;i<s1->nb_sections;i++) {
2046 s = s1->sections[section_order[i]];
2047 if (s->sh_type != SHT_NOBITS) {
2048 #if defined(__FreeBSD__)
2049 if (s->sh_type == SHT_DYNSYM)
2050 patch_dynsym_undef(s1, s);
2051 #endif
2052 while (offset < s->sh_offset) {
2053 fputc(0, f);
2054 offset++;
2056 size = s->sh_size;
2057 fwrite(s->data, 1, size, f);
2058 offset += size;
2062 /* output section headers */
2063 while (offset < ehdr.e_shoff) {
2064 fputc(0, f);
2065 offset++;
2068 for(i=0;i<s1->nb_sections;i++) {
2069 sh = &shdr;
2070 memset(sh, 0, sizeof(ElfW(Shdr)));
2071 s = s1->sections[i];
2072 if (s) {
2073 sh->sh_name = s->sh_name;
2074 sh->sh_type = s->sh_type;
2075 sh->sh_flags = s->sh_flags;
2076 sh->sh_entsize = s->sh_entsize;
2077 sh->sh_info = s->sh_info;
2078 if (s->link)
2079 sh->sh_link = s->link->sh_num;
2080 sh->sh_addralign = s->sh_addralign;
2081 sh->sh_addr = s->sh_addr;
2082 sh->sh_offset = s->sh_offset;
2083 sh->sh_size = s->sh_size;
2085 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2087 } else {
2088 tcc_output_binary(s1, f, section_order);
2090 fclose(f);
2092 ret = 0;
2093 the_end:
2094 tcc_free(s1->symtab_to_dynsym);
2095 tcc_free(section_order);
2096 tcc_free(phdr);
2097 tcc_free(s1->got_offsets);
2098 return ret;
2101 int tcc_output_file(TCCState *s, const char *filename)
2103 int ret;
2104 #ifdef TCC_TARGET_PE
2105 if (s->output_type != TCC_OUTPUT_OBJ) {
2106 ret = pe_output_file(s, filename);
2107 } else
2108 #endif
2110 ret = elf_output_file(s, filename);
2112 return ret;
2115 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2117 void *data;
2119 data = tcc_malloc(size);
2120 lseek(fd, file_offset, SEEK_SET);
2121 read(fd, data, size);
2122 return data;
2125 typedef struct SectionMergeInfo {
2126 Section *s; /* corresponding existing section */
2127 unsigned long offset; /* offset of the new section in the existing section */
2128 uint8_t new_section; /* true if section 's' was added */
2129 uint8_t link_once; /* true if link once section */
2130 } SectionMergeInfo;
2132 /* load an object file and merge it with current files */
2133 /* XXX: handle correctly stab (debug) info */
2134 static int tcc_load_object_file(TCCState *s1,
2135 int fd, unsigned long file_offset)
2137 ElfW(Ehdr) ehdr;
2138 ElfW(Shdr) *shdr, *sh;
2139 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2140 unsigned char *strsec, *strtab;
2141 int *old_to_new_syms;
2142 char *sh_name, *name;
2143 SectionMergeInfo *sm_table, *sm;
2144 ElfW(Sym) *sym, *symtab;
2145 ElfW_Rel *rel, *rel_end;
2146 Section *s;
2148 int stab_index;
2149 int stabstr_index;
2151 stab_index = stabstr_index = 0;
2153 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2154 goto fail1;
2155 if (ehdr.e_ident[0] != ELFMAG0 ||
2156 ehdr.e_ident[1] != ELFMAG1 ||
2157 ehdr.e_ident[2] != ELFMAG2 ||
2158 ehdr.e_ident[3] != ELFMAG3)
2159 goto fail1;
2160 /* test if object file */
2161 if (ehdr.e_type != ET_REL)
2162 goto fail1;
2163 /* test CPU specific stuff */
2164 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2165 ehdr.e_machine != EM_TCC_TARGET) {
2166 fail1:
2167 error_noabort("invalid object file");
2168 return -1;
2170 /* read sections */
2171 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2172 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2173 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2175 /* load section names */
2176 sh = &shdr[ehdr.e_shstrndx];
2177 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2179 /* load symtab and strtab */
2180 old_to_new_syms = NULL;
2181 symtab = NULL;
2182 strtab = NULL;
2183 nb_syms = 0;
2184 for(i = 1; i < ehdr.e_shnum; i++) {
2185 sh = &shdr[i];
2186 if (sh->sh_type == SHT_SYMTAB) {
2187 if (symtab) {
2188 error_noabort("object must contain only one symtab");
2189 fail:
2190 ret = -1;
2191 goto the_end;
2193 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2194 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2195 sm_table[i].s = symtab_section;
2197 /* now load strtab */
2198 sh = &shdr[sh->sh_link];
2199 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2203 /* now examine each section and try to merge its content with the
2204 ones in memory */
2205 for(i = 1; i < ehdr.e_shnum; i++) {
2206 /* no need to examine section name strtab */
2207 if (i == ehdr.e_shstrndx)
2208 continue;
2209 sh = &shdr[i];
2210 sh_name = strsec + sh->sh_name;
2211 /* ignore sections types we do not handle */
2212 if (sh->sh_type != SHT_PROGBITS &&
2213 sh->sh_type != SHT_RELX &&
2214 #ifdef TCC_ARM_EABI
2215 sh->sh_type != SHT_ARM_EXIDX &&
2216 #endif
2217 sh->sh_type != SHT_NOBITS &&
2218 strcmp(sh_name, ".stabstr")
2220 continue;
2221 if (sh->sh_addralign < 1)
2222 sh->sh_addralign = 1;
2223 /* find corresponding section, if any */
2224 for(j = 1; j < s1->nb_sections;j++) {
2225 s = s1->sections[j];
2226 if (!strcmp(s->name, sh_name)) {
2227 if (!strncmp(sh_name, ".gnu.linkonce",
2228 sizeof(".gnu.linkonce") - 1)) {
2229 /* if a 'linkonce' section is already present, we
2230 do not add it again. It is a little tricky as
2231 symbols can still be defined in
2232 it. */
2233 sm_table[i].link_once = 1;
2234 goto next;
2235 } else {
2236 goto found;
2240 /* not found: create new section */
2241 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2242 /* take as much info as possible from the section. sh_link and
2243 sh_info will be updated later */
2244 s->sh_addralign = sh->sh_addralign;
2245 s->sh_entsize = sh->sh_entsize;
2246 sm_table[i].new_section = 1;
2247 found:
2248 if (sh->sh_type != s->sh_type) {
2249 error_noabort("invalid section type");
2250 goto fail;
2253 /* align start of section */
2254 offset = s->data_offset;
2256 if (0 == strcmp(sh_name, ".stab")) {
2257 stab_index = i;
2258 goto no_align;
2260 if (0 == strcmp(sh_name, ".stabstr")) {
2261 stabstr_index = i;
2262 goto no_align;
2265 size = sh->sh_addralign - 1;
2266 offset = (offset + size) & ~size;
2267 if (sh->sh_addralign > s->sh_addralign)
2268 s->sh_addralign = sh->sh_addralign;
2269 s->data_offset = offset;
2270 no_align:
2271 sm_table[i].offset = offset;
2272 sm_table[i].s = s;
2273 /* concatenate sections */
2274 size = sh->sh_size;
2275 if (sh->sh_type != SHT_NOBITS) {
2276 unsigned char *ptr;
2277 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2278 ptr = section_ptr_add(s, size);
2279 read(fd, ptr, size);
2280 } else {
2281 s->data_offset += size;
2283 next: ;
2286 /* //gr relocate stab strings */
2287 if (stab_index && stabstr_index) {
2288 Stab_Sym *a, *b;
2289 unsigned o;
2290 s = sm_table[stab_index].s;
2291 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2292 b = (Stab_Sym *)(s->data + s->data_offset);
2293 o = sm_table[stabstr_index].offset;
2294 while (a < b)
2295 a->n_strx += o, a++;
2298 /* second short pass to update sh_link and sh_info fields of new
2299 sections */
2300 for(i = 1; i < ehdr.e_shnum; i++) {
2301 s = sm_table[i].s;
2302 if (!s || !sm_table[i].new_section)
2303 continue;
2304 sh = &shdr[i];
2305 if (sh->sh_link > 0)
2306 s->link = sm_table[sh->sh_link].s;
2307 if (sh->sh_type == SHT_RELX) {
2308 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2309 /* update backward link */
2310 s1->sections[s->sh_info]->reloc = s;
2313 sm = sm_table;
2315 /* resolve symbols */
2316 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2318 sym = symtab + 1;
2319 for(i = 1; i < nb_syms; i++, sym++) {
2320 if (sym->st_shndx != SHN_UNDEF &&
2321 sym->st_shndx < SHN_LORESERVE) {
2322 sm = &sm_table[sym->st_shndx];
2323 if (sm->link_once) {
2324 /* if a symbol is in a link once section, we use the
2325 already defined symbol. It is very important to get
2326 correct relocations */
2327 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2328 name = strtab + sym->st_name;
2329 sym_index = find_elf_sym(symtab_section, name);
2330 if (sym_index)
2331 old_to_new_syms[i] = sym_index;
2333 continue;
2335 /* if no corresponding section added, no need to add symbol */
2336 if (!sm->s)
2337 continue;
2338 /* convert section number */
2339 sym->st_shndx = sm->s->sh_num;
2340 /* offset value */
2341 sym->st_value += sm->offset;
2343 /* add symbol */
2344 name = strtab + sym->st_name;
2345 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2346 sym->st_info, sym->st_other,
2347 sym->st_shndx, name);
2348 old_to_new_syms[i] = sym_index;
2351 /* third pass to patch relocation entries */
2352 for(i = 1; i < ehdr.e_shnum; i++) {
2353 s = sm_table[i].s;
2354 if (!s)
2355 continue;
2356 sh = &shdr[i];
2357 offset = sm_table[i].offset;
2358 switch(s->sh_type) {
2359 case SHT_RELX:
2360 /* take relocation offset information */
2361 offseti = sm_table[sh->sh_info].offset;
2362 rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2363 for(rel = (ElfW_Rel *)(s->data + offset);
2364 rel < rel_end;
2365 rel++) {
2366 int type;
2367 unsigned sym_index;
2368 /* convert symbol index */
2369 type = ELFW(R_TYPE)(rel->r_info);
2370 sym_index = ELFW(R_SYM)(rel->r_info);
2371 /* NOTE: only one symtab assumed */
2372 if (sym_index >= nb_syms)
2373 goto invalid_reloc;
2374 sym_index = old_to_new_syms[sym_index];
2375 /* ignore link_once in rel section. */
2376 if (!sym_index && !sm->link_once) {
2377 invalid_reloc:
2378 error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2379 i, strsec + sh->sh_name, rel->r_offset);
2380 goto fail;
2382 rel->r_info = ELFW(R_INFO)(sym_index, type);
2383 /* offset the relocation offset */
2384 rel->r_offset += offseti;
2386 break;
2387 default:
2388 break;
2392 ret = 0;
2393 the_end:
2394 tcc_free(symtab);
2395 tcc_free(strtab);
2396 tcc_free(old_to_new_syms);
2397 tcc_free(sm_table);
2398 tcc_free(strsec);
2399 tcc_free(shdr);
2400 return ret;
2403 #define ARMAG "!<arch>\012" /* For COFF and a.out archives */
2405 typedef struct ArchiveHeader {
2406 char ar_name[16]; /* name of this member */
2407 char ar_date[12]; /* file mtime */
2408 char ar_uid[6]; /* owner uid; printed as decimal */
2409 char ar_gid[6]; /* owner gid; printed as decimal */
2410 char ar_mode[8]; /* file mode, printed as octal */
2411 char ar_size[10]; /* file size, printed as decimal */
2412 char ar_fmag[2]; /* should contain ARFMAG */
2413 } ArchiveHeader;
2415 static int get_be32(const uint8_t *b)
2417 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2420 /* load only the objects which resolve undefined symbols */
2421 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2423 int i, bound, nsyms, sym_index, off, ret;
2424 uint8_t *data;
2425 const char *ar_names, *p;
2426 const uint8_t *ar_index;
2427 ElfW(Sym) *sym;
2429 data = tcc_malloc(size);
2430 if (read(fd, data, size) != size)
2431 goto fail;
2432 nsyms = get_be32(data);
2433 ar_index = data + 4;
2434 ar_names = ar_index + nsyms * 4;
2436 do {
2437 bound = 0;
2438 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2439 sym_index = find_elf_sym(symtab_section, p);
2440 if(sym_index) {
2441 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2442 if(sym->st_shndx == SHN_UNDEF) {
2443 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2444 #if 0
2445 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2446 #endif
2447 ++bound;
2448 lseek(fd, off, SEEK_SET);
2449 if(tcc_load_object_file(s1, fd, off) < 0) {
2450 fail:
2451 ret = -1;
2452 goto the_end;
2457 } while(bound);
2458 ret = 0;
2459 the_end:
2460 tcc_free(data);
2461 return ret;
2464 /* load a '.a' file */
2465 static int tcc_load_archive(TCCState *s1, int fd)
2467 ArchiveHeader hdr;
2468 char ar_size[11];
2469 char ar_name[17];
2470 char magic[8];
2471 int size, len, i;
2472 unsigned long file_offset;
2474 /* skip magic which was already checked */
2475 read(fd, magic, sizeof(magic));
2477 for(;;) {
2478 len = read(fd, &hdr, sizeof(hdr));
2479 if (len == 0)
2480 break;
2481 if (len != sizeof(hdr)) {
2482 error_noabort("invalid archive");
2483 return -1;
2485 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2486 ar_size[sizeof(hdr.ar_size)] = '\0';
2487 size = strtol(ar_size, NULL, 0);
2488 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2489 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2490 if (ar_name[i] != ' ')
2491 break;
2493 ar_name[i + 1] = '\0';
2494 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2495 file_offset = lseek(fd, 0, SEEK_CUR);
2496 /* align to even */
2497 size = (size + 1) & ~1;
2498 if (!strcmp(ar_name, "/")) {
2499 /* coff symbol table : we handle it */
2500 if(s1->alacarte_link)
2501 return tcc_load_alacarte(s1, fd, size);
2502 } else if (!strcmp(ar_name, "//") ||
2503 !strcmp(ar_name, "__.SYMDEF") ||
2504 !strcmp(ar_name, "__.SYMDEF/") ||
2505 !strcmp(ar_name, "ARFILENAMES/")) {
2506 /* skip symbol table or archive names */
2507 } else {
2508 if (tcc_load_object_file(s1, fd, file_offset) < 0)
2509 return -1;
2511 lseek(fd, file_offset + size, SEEK_SET);
2513 return 0;
2516 #ifndef TCC_TARGET_PE
2517 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2518 is referenced by the user (so it should be added as DT_NEEDED in
2519 the generated ELF file) */
2520 static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2522 ElfW(Ehdr) ehdr;
2523 ElfW(Shdr) *shdr, *sh, *sh1;
2524 int i, j, nb_syms, nb_dts, sym_bind, ret;
2525 ElfW(Sym) *sym, *dynsym;
2526 ElfW(Dyn) *dt, *dynamic;
2527 unsigned char *dynstr;
2528 const char *name, *soname;
2529 DLLReference *dllref;
2531 read(fd, &ehdr, sizeof(ehdr));
2533 /* test CPU specific stuff */
2534 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2535 ehdr.e_machine != EM_TCC_TARGET) {
2536 error_noabort("bad architecture");
2537 return -1;
2540 /* read sections */
2541 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2543 /* load dynamic section and dynamic symbols */
2544 nb_syms = 0;
2545 nb_dts = 0;
2546 dynamic = NULL;
2547 dynsym = NULL; /* avoid warning */
2548 dynstr = NULL; /* avoid warning */
2549 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2550 switch(sh->sh_type) {
2551 case SHT_DYNAMIC:
2552 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2553 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2554 break;
2555 case SHT_DYNSYM:
2556 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2557 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2558 sh1 = &shdr[sh->sh_link];
2559 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2560 break;
2561 default:
2562 break;
2566 /* compute the real library name */
2567 soname = tcc_basename(filename);
2569 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2570 if (dt->d_tag == DT_SONAME) {
2571 soname = dynstr + dt->d_un.d_val;
2575 /* if the dll is already loaded, do not load it */
2576 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2577 dllref = s1->loaded_dlls[i];
2578 if (!strcmp(soname, dllref->name)) {
2579 /* but update level if needed */
2580 if (level < dllref->level)
2581 dllref->level = level;
2582 ret = 0;
2583 goto the_end;
2587 // printf("loading dll '%s'\n", soname);
2589 /* add the dll and its level */
2590 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2591 dllref->level = level;
2592 strcpy(dllref->name, soname);
2593 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2595 /* add dynamic symbols in dynsym_section */
2596 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2597 sym_bind = ELFW(ST_BIND)(sym->st_info);
2598 if (sym_bind == STB_LOCAL)
2599 continue;
2600 name = dynstr + sym->st_name;
2601 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2602 sym->st_info, sym->st_other, sym->st_shndx, name);
2605 /* load all referenced DLLs */
2606 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2607 switch(dt->d_tag) {
2608 case DT_NEEDED:
2609 name = dynstr + dt->d_un.d_val;
2610 for(j = 0; j < s1->nb_loaded_dlls; j++) {
2611 dllref = s1->loaded_dlls[j];
2612 if (!strcmp(name, dllref->name))
2613 goto already_loaded;
2615 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2616 error_noabort("referenced dll '%s' not found", name);
2617 ret = -1;
2618 goto the_end;
2620 already_loaded:
2621 break;
2624 ret = 0;
2625 the_end:
2626 tcc_free(dynstr);
2627 tcc_free(dynsym);
2628 tcc_free(dynamic);
2629 tcc_free(shdr);
2630 return ret;
2633 #define LD_TOK_NAME 256
2634 #define LD_TOK_EOF (-1)
2636 /* return next ld script token */
2637 static int ld_next(TCCState *s1, char *name, int name_size)
2639 int c;
2640 char *q;
2642 redo:
2643 switch(ch) {
2644 case ' ':
2645 case '\t':
2646 case '\f':
2647 case '\v':
2648 case '\r':
2649 case '\n':
2650 inp();
2651 goto redo;
2652 case '/':
2653 minp();
2654 if (ch == '*') {
2655 file->buf_ptr = parse_comment(file->buf_ptr);
2656 ch = file->buf_ptr[0];
2657 goto redo;
2658 } else {
2659 q = name;
2660 *q++ = '/';
2661 goto parse_name;
2663 break;
2664 /* case 'a' ... 'z': */
2665 case 'a':
2666 case 'b':
2667 case 'c':
2668 case 'd':
2669 case 'e':
2670 case 'f':
2671 case 'g':
2672 case 'h':
2673 case 'i':
2674 case 'j':
2675 case 'k':
2676 case 'l':
2677 case 'm':
2678 case 'n':
2679 case 'o':
2680 case 'p':
2681 case 'q':
2682 case 'r':
2683 case 's':
2684 case 't':
2685 case 'u':
2686 case 'v':
2687 case 'w':
2688 case 'x':
2689 case 'y':
2690 case 'z':
2691 /* case 'A' ... 'z': */
2692 case 'A':
2693 case 'B':
2694 case 'C':
2695 case 'D':
2696 case 'E':
2697 case 'F':
2698 case 'G':
2699 case 'H':
2700 case 'I':
2701 case 'J':
2702 case 'K':
2703 case 'L':
2704 case 'M':
2705 case 'N':
2706 case 'O':
2707 case 'P':
2708 case 'Q':
2709 case 'R':
2710 case 'S':
2711 case 'T':
2712 case 'U':
2713 case 'V':
2714 case 'W':
2715 case 'X':
2716 case 'Y':
2717 case 'Z':
2718 case '_':
2719 case '\\':
2720 case '.':
2721 case '$':
2722 case '~':
2723 q = name;
2724 parse_name:
2725 for(;;) {
2726 if (!((ch >= 'a' && ch <= 'z') ||
2727 (ch >= 'A' && ch <= 'Z') ||
2728 (ch >= '0' && ch <= '9') ||
2729 strchr("/.-_+=$:\\,~", ch)))
2730 break;
2731 if ((q - name) < name_size - 1) {
2732 *q++ = ch;
2734 minp();
2736 *q = '\0';
2737 c = LD_TOK_NAME;
2738 break;
2739 case CH_EOF:
2740 c = LD_TOK_EOF;
2741 break;
2742 default:
2743 c = ch;
2744 inp();
2745 break;
2747 #if 0
2748 printf("tok=%c %d\n", c, c);
2749 if (c == LD_TOK_NAME)
2750 printf(" name=%s\n", name);
2751 #endif
2752 return c;
2755 static int ld_add_file_list(TCCState *s1, int as_needed)
2757 char filename[1024];
2758 int t, ret;
2760 t = ld_next(s1, filename, sizeof(filename));
2761 if (t != '(')
2762 expect("(");
2763 t = ld_next(s1, filename, sizeof(filename));
2764 for(;;) {
2765 if (t == LD_TOK_EOF) {
2766 error_noabort("unexpected end of file");
2767 return -1;
2768 } else if (t == ')') {
2769 break;
2770 } else if (t != LD_TOK_NAME) {
2771 error_noabort("filename expected");
2772 return -1;
2774 if (!strcmp(filename, "AS_NEEDED")) {
2775 ret = ld_add_file_list(s1, 1);
2776 if (ret)
2777 return ret;
2778 } else {
2779 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2780 if (!as_needed)
2781 tcc_add_file(s1, filename);
2783 t = ld_next(s1, filename, sizeof(filename));
2784 if (t == ',') {
2785 t = ld_next(s1, filename, sizeof(filename));
2788 return 0;
2791 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
2792 files */
2793 static int tcc_load_ldscript(TCCState *s1)
2795 char cmd[64];
2796 char filename[1024];
2797 int t, ret;
2799 ch = file->buf_ptr[0];
2800 ch = handle_eob();
2801 for(;;) {
2802 t = ld_next(s1, cmd, sizeof(cmd));
2803 if (t == LD_TOK_EOF)
2804 return 0;
2805 else if (t != LD_TOK_NAME)
2806 return -1;
2807 if (!strcmp(cmd, "INPUT") ||
2808 !strcmp(cmd, "GROUP")) {
2809 ret = ld_add_file_list(s1, 0);
2810 if (ret)
2811 return ret;
2812 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
2813 !strcmp(cmd, "TARGET")) {
2814 /* ignore some commands */
2815 t = ld_next(s1, cmd, sizeof(cmd));
2816 if (t != '(')
2817 expect("(");
2818 for(;;) {
2819 t = ld_next(s1, filename, sizeof(filename));
2820 if (t == LD_TOK_EOF) {
2821 error_noabort("unexpected end of file");
2822 return -1;
2823 } else if (t == ')') {
2824 break;
2827 } else {
2828 return -1;
2831 return 0;
2833 #endif