Add arm64 (AArch64) as a target architecture.
[tinycc.git] / tccelf.c
blob4f8922454886f2772e339ccfdca1d515f75456d1
1 /*
2 * ELF file handling for TCC
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "tcc.h"
23 /* Define this to get some debug output during relocation processing. */
24 #undef DEBUG_RELOC
26 /* XXX: avoid static variable */
27 static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */
29 ST_FUNC int put_elf_str(Section *s, const char *sym)
31 int offset, len;
32 char *ptr;
34 len = strlen(sym) + 1;
35 offset = s->data_offset;
36 ptr = section_ptr_add(s, len);
37 memcpy(ptr, sym, len);
38 return offset;
41 /* elf symbol hashing function */
42 static unsigned long elf_hash(const unsigned char *name)
44 unsigned long h = 0, g;
46 while (*name) {
47 h = (h << 4) + *name++;
48 g = h & 0xf0000000;
49 if (g)
50 h ^= g >> 24;
51 h &= ~g;
53 return h;
56 /* rebuild hash table of section s */
57 /* NOTE: we do factorize the hash table code to go faster */
58 static void rebuild_hash(Section *s, unsigned int nb_buckets)
60 ElfW(Sym) *sym;
61 int *ptr, *hash, nb_syms, sym_index, h;
62 unsigned char *strtab;
64 strtab = s->link->data;
65 nb_syms = s->data_offset / sizeof(ElfW(Sym));
67 s->hash->data_offset = 0;
68 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
69 ptr[0] = nb_buckets;
70 ptr[1] = nb_syms;
71 ptr += 2;
72 hash = ptr;
73 memset(hash, 0, (nb_buckets + 1) * sizeof(int));
74 ptr += nb_buckets + 1;
76 sym = (ElfW(Sym) *)s->data + 1;
77 for(sym_index = 1; sym_index < nb_syms; sym_index++) {
78 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
79 h = elf_hash(strtab + sym->st_name) % nb_buckets;
80 *ptr = hash[h];
81 hash[h] = sym_index;
82 } else {
83 *ptr = 0;
85 ptr++;
86 sym++;
90 /* return the symbol number */
91 ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size,
92 int info, int other, int shndx, const char *name)
94 int name_offset, sym_index;
95 int nbuckets, h;
96 ElfW(Sym) *sym;
97 Section *hs;
99 sym = section_ptr_add(s, sizeof(ElfW(Sym)));
100 if (name)
101 name_offset = put_elf_str(s->link, name);
102 else
103 name_offset = 0;
104 /* XXX: endianness */
105 sym->st_name = name_offset;
106 sym->st_value = value;
107 sym->st_size = size;
108 sym->st_info = info;
109 sym->st_other = other;
110 sym->st_shndx = shndx;
111 sym_index = sym - (ElfW(Sym) *)s->data;
112 hs = s->hash;
113 if (hs) {
114 int *ptr, *base;
115 ptr = section_ptr_add(hs, sizeof(int));
116 base = (int *)hs->data;
117 /* only add global or weak symbols */
118 if (ELFW(ST_BIND)(info) != STB_LOCAL) {
119 /* add another hashing entry */
120 nbuckets = base[0];
121 h = elf_hash((unsigned char *) name) % nbuckets;
122 *ptr = base[2 + h];
123 base[2 + h] = sym_index;
124 base[1]++;
125 /* we resize the hash table */
126 hs->nb_hashed_syms++;
127 if (hs->nb_hashed_syms > 2 * nbuckets) {
128 rebuild_hash(s, 2 * nbuckets);
130 } else {
131 *ptr = 0;
132 base[1]++;
135 return sym_index;
138 /* find global ELF symbol 'name' and return its index. Return 0 if not
139 found. */
140 ST_FUNC int find_elf_sym(Section *s, const char *name)
142 ElfW(Sym) *sym;
143 Section *hs;
144 int nbuckets, sym_index, h;
145 const char *name1;
147 hs = s->hash;
148 if (!hs)
149 return 0;
150 nbuckets = ((int *)hs->data)[0];
151 h = elf_hash((unsigned char *) name) % nbuckets;
152 sym_index = ((int *)hs->data)[2 + h];
153 while (sym_index != 0) {
154 sym = &((ElfW(Sym) *)s->data)[sym_index];
155 name1 = (char *) s->link->data + sym->st_name;
156 if (!strcmp(name, name1))
157 return sym_index;
158 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
160 return 0;
163 /* return elf symbol value, signal error if 'err' is nonzero */
164 ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err)
166 int sym_index;
167 ElfW(Sym) *sym;
169 sym_index = find_elf_sym(s->symtab, name);
170 sym = &((ElfW(Sym) *)s->symtab->data)[sym_index];
171 if (!sym_index || sym->st_shndx == SHN_UNDEF) {
172 if (err)
173 tcc_error("%s not defined", name);
174 return 0;
176 return sym->st_value;
179 /* return elf symbol value */
180 LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
182 return (void*)(uintptr_t)get_elf_sym_addr(s, name, 0);
185 #if defined TCC_IS_NATIVE || defined TCC_TARGET_PE
186 /* return elf symbol value or error */
187 ST_FUNC void* tcc_get_symbol_err(TCCState *s, const char *name)
189 return (void*)(uintptr_t)get_elf_sym_addr(s, name, 1);
191 #endif
193 /* add an elf symbol : check if it is already defined and patch
194 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
195 ST_FUNC int add_elf_sym(Section *s, addr_t value, unsigned long size,
196 int info, int other, int sh_num, const char *name)
198 ElfW(Sym) *esym;
199 int sym_bind, sym_index, sym_type, esym_bind;
200 unsigned char sym_vis, esym_vis, new_vis;
202 sym_bind = ELFW(ST_BIND)(info);
203 sym_type = ELFW(ST_TYPE)(info);
204 sym_vis = ELFW(ST_VISIBILITY)(other);
206 if (sym_bind != STB_LOCAL) {
207 /* we search global or weak symbols */
208 sym_index = find_elf_sym(s, name);
209 if (!sym_index)
210 goto do_def;
211 esym = &((ElfW(Sym) *)s->data)[sym_index];
212 if (esym->st_shndx != SHN_UNDEF) {
213 esym_bind = ELFW(ST_BIND)(esym->st_info);
214 /* propagate the most constraining visibility */
215 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
216 esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
217 if (esym_vis == STV_DEFAULT) {
218 new_vis = sym_vis;
219 } else if (sym_vis == STV_DEFAULT) {
220 new_vis = esym_vis;
221 } else {
222 new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
224 esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
225 | new_vis;
226 other = esym->st_other; /* in case we have to patch esym */
227 if (sh_num == SHN_UNDEF) {
228 /* ignore adding of undefined symbol if the
229 corresponding symbol is already defined */
230 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
231 /* global overrides weak, so patch */
232 goto do_patch;
233 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
234 /* weak is ignored if already global */
235 } else if (sym_bind == STB_WEAK && esym_bind == STB_WEAK) {
236 /* keep first-found weak definition, ignore subsequents */
237 } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
238 /* ignore hidden symbols after */
239 } else if (esym->st_shndx == SHN_COMMON
240 && (sh_num < SHN_LORESERVE || sh_num == SHN_COMMON)) {
241 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
242 No idea if this is the correct solution ... */
243 goto do_patch;
244 } else if (s == tcc_state->dynsymtab_section) {
245 /* we accept that two DLL define the same symbol */
246 } else {
247 #if 0
248 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
249 sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
250 #endif
251 tcc_error_noabort("'%s' defined twice", name);
253 } else {
254 do_patch:
255 esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
256 esym->st_shndx = sh_num;
257 new_undef_sym = 1;
258 esym->st_value = value;
259 esym->st_size = size;
260 esym->st_other = other;
262 } else {
263 do_def:
264 sym_index = put_elf_sym(s, value, size,
265 ELFW(ST_INFO)(sym_bind, sym_type), other,
266 sh_num, name);
268 return sym_index;
271 /* put relocation */
272 ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset,
273 int type, int symbol, unsigned long addend)
275 char buf[256];
276 Section *sr;
277 ElfW_Rel *rel;
279 sr = s->reloc;
280 if (!sr) {
281 /* if no relocation section, create it */
282 snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
283 /* if the symtab is allocated, then we consider the relocation
284 are also */
285 sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
286 sr->sh_entsize = sizeof(ElfW_Rel);
287 sr->link = symtab;
288 sr->sh_info = s->sh_num;
289 s->reloc = sr;
291 rel = section_ptr_add(sr, sizeof(ElfW_Rel));
292 rel->r_offset = offset;
293 rel->r_info = ELFW(R_INFO)(symbol, type);
294 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
295 rel->r_addend = addend;
296 #else
297 if (addend)
298 tcc_error("non-zero addend on REL architecture");
299 #endif
302 ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
303 int type, int symbol)
305 put_elf_reloca(symtab, s, offset, type, symbol, 0);
308 /* put stab debug information */
310 ST_FUNC void put_stabs(const char *str, int type, int other, int desc,
311 unsigned long value)
313 Stab_Sym *sym;
315 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
316 if (str) {
317 sym->n_strx = put_elf_str(stabstr_section, str);
318 } else {
319 sym->n_strx = 0;
321 sym->n_type = type;
322 sym->n_other = other;
323 sym->n_desc = desc;
324 sym->n_value = value;
327 ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc,
328 unsigned long value, Section *sec, int sym_index)
330 put_stabs(str, type, other, desc, value);
331 put_elf_reloc(symtab_section, stab_section,
332 stab_section->data_offset - sizeof(unsigned int),
333 R_DATA_32, sym_index);
336 ST_FUNC void put_stabn(int type, int other, int desc, int value)
338 put_stabs(NULL, type, other, desc, value);
341 ST_FUNC void put_stabd(int type, int other, int desc)
343 put_stabs(NULL, type, other, desc, 0);
346 /* Browse each elem of type <type> in section <sec> starting at elem <startoff>
347 using variable <elem> */
348 #define for_each_elem(sec, startoff, elem, type) \
349 for (elem = (type *) sec->data + startoff; \
350 elem < (type *) (sec->data + sec->data_offset); elem++)
352 /* In an ELF file symbol table, the local symbols must appear below
353 the global and weak ones. Since TCC cannot sort it while generating
354 the code, we must do it after. All the relocation tables are also
355 modified to take into account the symbol table sorting */
356 static void sort_syms(TCCState *s1, Section *s)
358 int *old_to_new_syms;
359 ElfW(Sym) *new_syms;
360 int nb_syms, i;
361 ElfW(Sym) *p, *q;
362 ElfW_Rel *rel;
363 Section *sr;
364 int type, sym_index;
366 nb_syms = s->data_offset / sizeof(ElfW(Sym));
367 new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
368 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
370 /* first pass for local symbols */
371 p = (ElfW(Sym) *)s->data;
372 q = new_syms;
373 for(i = 0; i < nb_syms; i++) {
374 if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
375 old_to_new_syms[i] = q - new_syms;
376 *q++ = *p;
378 p++;
380 /* save the number of local symbols in section header */
381 s->sh_info = q - new_syms;
383 /* then second pass for non local symbols */
384 p = (ElfW(Sym) *)s->data;
385 for(i = 0; i < nb_syms; i++) {
386 if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
387 old_to_new_syms[i] = q - new_syms;
388 *q++ = *p;
390 p++;
393 /* we copy the new symbols to the old */
394 memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
395 tcc_free(new_syms);
397 /* now we modify all the relocations */
398 for(i = 1; i < s1->nb_sections; i++) {
399 sr = s1->sections[i];
400 if (sr->sh_type == SHT_RELX && sr->link == s) {
401 for_each_elem(sr, 0, rel, ElfW_Rel) {
402 sym_index = ELFW(R_SYM)(rel->r_info);
403 type = ELFW(R_TYPE)(rel->r_info);
404 sym_index = old_to_new_syms[sym_index];
405 rel->r_info = ELFW(R_INFO)(sym_index, type);
410 tcc_free(old_to_new_syms);
413 /* relocate common symbols in the .bss section */
414 ST_FUNC void relocate_common_syms(void)
416 ElfW(Sym) *sym;
417 unsigned long offset, align;
419 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
420 if (sym->st_shndx == SHN_COMMON) {
421 /* align symbol */
422 align = sym->st_value;
423 offset = bss_section->data_offset;
424 offset = (offset + align - 1) & -align;
425 sym->st_value = offset;
426 sym->st_shndx = bss_section->sh_num;
427 offset += sym->st_size;
428 bss_section->data_offset = offset;
433 /* relocate symbol table, resolve undefined symbols if do_resolve is
434 true and output error if undefined symbol. */
435 ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
437 ElfW(Sym) *sym, *esym;
438 int sym_bind, sh_num, sym_index;
439 const char *name;
441 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
442 sh_num = sym->st_shndx;
443 if (sh_num == SHN_UNDEF) {
444 name = (char *) strtab_section->data + sym->st_name;
445 /* Use ld.so to resolve symbol for us (for tcc -run) */
446 if (do_resolve) {
447 #if defined TCC_IS_NATIVE && !defined _WIN32
448 void *addr;
449 name = (char *) symtab_section->link->data + sym->st_name;
450 addr = resolve_sym(s1, name);
451 if (addr) {
452 sym->st_value = (addr_t)addr;
453 #ifdef DEBUG_RELOC
454 printf ("relocate_sym: %s -> 0x%x\n", name, sym->st_value);
455 #endif
456 goto found;
458 #endif
459 } else if (s1->dynsym) {
460 /* if dynamic symbol exist, then use it */
461 sym_index = find_elf_sym(s1->dynsym, name);
462 if (sym_index) {
463 esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
464 sym->st_value = esym->st_value;
465 goto found;
468 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
469 it */
470 if (!strcmp(name, "_fp_hw"))
471 goto found;
472 /* only weak symbols are accepted to be undefined. Their
473 value is zero */
474 sym_bind = ELFW(ST_BIND)(sym->st_info);
475 if (sym_bind == STB_WEAK) {
476 sym->st_value = 0;
477 } else {
478 tcc_error_noabort("undefined symbol '%s'", name);
480 } else if (sh_num < SHN_LORESERVE) {
481 /* add section base */
482 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
484 found: ;
488 /* relocate a given section (CPU dependent) by applying the relocations
489 in the associated relocation section */
490 ST_FUNC void relocate_section(TCCState *s1, Section *s)
492 Section *sr = s->reloc;
493 ElfW_Rel *rel;
494 ElfW(Sym) *sym;
495 int type, sym_index;
496 unsigned char *ptr;
497 addr_t val, addr;
498 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
499 ElfW_Rel *qrel = (ElfW_Rel *) sr->data; /* ptr to next reloc entry reused */
500 int esym_index;
501 #endif
503 for_each_elem(sr, 0, rel, ElfW_Rel) {
504 ptr = s->data + rel->r_offset;
506 sym_index = ELFW(R_SYM)(rel->r_info);
507 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
508 val = sym->st_value;
509 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
510 val += rel->r_addend;
511 #endif
512 type = ELFW(R_TYPE)(rel->r_info);
513 addr = s->sh_addr + rel->r_offset;
515 /* CPU specific */
516 switch(type) {
517 #if defined(TCC_TARGET_I386)
518 case R_386_32:
519 if (s1->output_type == TCC_OUTPUT_DLL) {
520 esym_index = s1->symtab_to_dynsym[sym_index];
521 qrel->r_offset = rel->r_offset;
522 if (esym_index) {
523 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
524 qrel++;
525 break;
526 } else {
527 qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
528 qrel++;
531 *(int *)ptr += val;
532 break;
533 case R_386_PC32:
534 if (s1->output_type == TCC_OUTPUT_DLL) {
535 /* DLL relocation */
536 esym_index = s1->symtab_to_dynsym[sym_index];
537 if (esym_index) {
538 qrel->r_offset = rel->r_offset;
539 qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
540 qrel++;
541 break;
544 *(int *)ptr += val - addr;
545 break;
546 case R_386_PLT32:
547 *(int *)ptr += val - addr;
548 break;
549 case R_386_GLOB_DAT:
550 case R_386_JMP_SLOT:
551 *(int *)ptr = val;
552 break;
553 case R_386_GOTPC:
554 *(int *)ptr += s1->got->sh_addr - addr;
555 break;
556 case R_386_GOTOFF:
557 *(int *)ptr += val - s1->got->sh_addr;
558 break;
559 case R_386_GOT32:
560 /* we load the got offset */
561 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
562 break;
563 case R_386_16:
564 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
565 output_file:
566 tcc_error("can only produce 16-bit binary files");
568 *(short *)ptr += val;
569 break;
570 case R_386_PC16:
571 if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
572 goto output_file;
573 *(short *)ptr += val - addr;
574 break;
575 #elif defined(TCC_TARGET_ARM)
576 case R_ARM_PC24:
577 case R_ARM_CALL:
578 case R_ARM_JUMP24:
579 case R_ARM_PLT32:
581 int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko;
582 x = (*(int *) ptr) & 0xffffff;
583 if (sym->st_shndx == SHN_UNDEF)
584 val = s1->plt->sh_addr;
585 #ifdef DEBUG_RELOC
586 printf ("reloc %d: x=0x%x val=0x%x ", type, x, val);
587 #endif
588 (*(int *)ptr) &= 0xff000000;
589 if (x & 0x800000)
590 x -= 0x1000000;
591 x <<= 2;
592 blx_avail = (TCC_ARM_VERSION >= 5);
593 is_thumb = val & 1;
594 is_bl = (*(unsigned *) ptr) >> 24 == 0xeb;
595 is_call = (type == R_ARM_CALL || (type == R_ARM_PC24 && is_bl));
596 x += val - addr;
597 #ifdef DEBUG_RELOC
598 printf (" newx=0x%x name=%s\n", x,
599 (char *) symtab_section->link->data + sym->st_name);
600 #endif
601 h = x & 2;
602 th_ko = (x & 3) && (!blx_avail || !is_call);
603 if (th_ko || x >= 0x2000000 || x < -0x2000000)
604 tcc_error("can't relocate value at %x,%d",addr, type);
605 x >>= 2;
606 x &= 0xffffff;
607 /* Only reached if blx is avail and it is a call */
608 if (is_thumb) {
609 x |= h << 24;
610 (*(int *)ptr) = 0xfa << 24; /* bl -> blx */
612 (*(int *) ptr) |= x;
614 break;
615 /* Since these relocations only concern Thumb-2 and blx instruction was
616 introduced before Thumb-2, we can assume blx is available and not
617 guard its use */
618 case R_ARM_THM_PC22:
619 case R_ARM_THM_JUMP24:
621 int x, hi, lo, s, j1, j2, i1, i2, imm10, imm11;
622 int to_thumb, is_call, to_plt, blx_bit = 1 << 12;
623 Section *plt;
625 /* weak reference */
626 if (sym->st_shndx == SHN_UNDEF &&
627 ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
628 break;
630 /* Get initial offset */
631 hi = (*(uint16_t *)ptr);
632 lo = (*(uint16_t *)(ptr+2));
633 s = (hi >> 10) & 1;
634 j1 = (lo >> 13) & 1;
635 j2 = (lo >> 11) & 1;
636 i1 = (j1 ^ s) ^ 1;
637 i2 = (j2 ^ s) ^ 1;
638 imm10 = hi & 0x3ff;
639 imm11 = lo & 0x7ff;
640 x = (s << 24) | (i1 << 23) | (i2 << 22) |
641 (imm10 << 12) | (imm11 << 1);
642 if (x & 0x01000000)
643 x -= 0x02000000;
645 /* Relocation infos */
646 to_thumb = val & 1;
647 plt = s1->plt;
648 to_plt = (val >= plt->sh_addr) &&
649 (val < plt->sh_addr + plt->data_offset);
650 is_call = (type == R_ARM_THM_PC22);
652 /* Compute final offset */
653 if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */
654 x -= 4;
655 x += val - addr;
656 if (!to_thumb && is_call) {
657 blx_bit = 0; /* bl -> blx */
658 x = (x + 3) & -4; /* Compute offset from aligned PC */
661 /* Check that relocation is possible
662 * offset must not be out of range
663 * if target is to be entered in arm mode:
664 - bit 1 must not set
665 - instruction must be a call (bl) or a jump to PLT */
666 if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
667 if (to_thumb || (val & 2) || (!is_call && !to_plt))
668 tcc_error("can't relocate value at %x,%d",addr, type);
670 /* Compute and store final offset */
671 s = (x >> 24) & 1;
672 i1 = (x >> 23) & 1;
673 i2 = (x >> 22) & 1;
674 j1 = s ^ (i1 ^ 1);
675 j2 = s ^ (i2 ^ 1);
676 imm10 = (x >> 12) & 0x3ff;
677 imm11 = (x >> 1) & 0x7ff;
678 (*(uint16_t *)ptr) = (uint16_t) ((hi & 0xf800) |
679 (s << 10) | imm10);
680 (*(uint16_t *)(ptr+2)) = (uint16_t) ((lo & 0xc000) |
681 (j1 << 13) | blx_bit | (j2 << 11) |
682 imm11);
684 break;
685 case R_ARM_MOVT_ABS:
686 case R_ARM_MOVW_ABS_NC:
688 int x, imm4, imm12;
689 if (type == R_ARM_MOVT_ABS)
690 val >>= 16;
691 imm12 = val & 0xfff;
692 imm4 = (val >> 12) & 0xf;
693 x = (imm4 << 16) | imm12;
694 if (type == R_ARM_THM_MOVT_ABS)
695 *(int *)ptr |= x;
696 else
697 *(int *)ptr += x;
699 break;
700 case R_ARM_THM_MOVT_ABS:
701 case R_ARM_THM_MOVW_ABS_NC:
703 int x, i, imm4, imm3, imm8;
704 if (type == R_ARM_THM_MOVT_ABS)
705 val >>= 16;
706 imm8 = val & 0xff;
707 imm3 = (val >> 8) & 0x7;
708 i = (val >> 11) & 1;
709 imm4 = (val >> 12) & 0xf;
710 x = (imm3 << 28) | (imm8 << 16) | (i << 10) | imm4;
711 if (type == R_ARM_THM_MOVT_ABS)
712 *(int *)ptr |= x;
713 else
714 *(int *)ptr += x;
716 break;
717 case R_ARM_PREL31:
719 int x;
720 x = (*(int *)ptr) & 0x7fffffff;
721 (*(int *)ptr) &= 0x80000000;
722 x = (x * 2) / 2;
723 x += val - addr;
724 if((x^(x>>1))&0x40000000)
725 tcc_error("can't relocate value at %x,%d",addr, type);
726 (*(int *)ptr) |= x & 0x7fffffff;
728 case R_ARM_ABS32:
729 *(int *)ptr += val;
730 break;
731 case R_ARM_REL32:
732 *(int *)ptr += val - addr;
733 break;
734 case R_ARM_GOTPC:
735 *(int *)ptr += s1->got->sh_addr - addr;
736 break;
737 case R_ARM_GOTOFF:
738 *(int *)ptr += val - s1->got->sh_addr;
739 break;
740 case R_ARM_GOT32:
741 /* we load the got offset */
742 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
743 break;
744 case R_ARM_COPY:
745 break;
746 case R_ARM_V4BX:
747 /* trade Thumb support for ARMv4 support */
748 if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
749 *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
750 break;
751 case R_ARM_GLOB_DAT:
752 case R_ARM_JUMP_SLOT:
753 *(addr_t *)ptr = val;
754 break;
755 case R_ARM_NONE:
756 /* Nothing to do. Normally used to indicate a dependency
757 on a certain symbol (like for exception handling under EABI). */
758 break;
759 default:
760 fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
761 type, (unsigned)addr, ptr, (unsigned)val);
762 break;
763 #elif defined(TCC_TARGET_ARM64)
764 case R_AARCH64_ABS64:
765 *(uint64_t *)ptr = val;
766 break;
767 case R_AARCH64_ABS32:
768 *(uint32_t *)ptr = val;
769 break;
770 case R_AARCH64_MOVW_UABS_G0_NC:
771 *(uint32_t *)ptr = (*(uint32_t *)ptr & 0xffe0001f) |
772 (val & 0xffff) << 5;
773 break;
774 case R_AARCH64_MOVW_UABS_G1_NC:
775 *(uint32_t *)ptr = (*(uint32_t *)ptr & 0xffe0001f) |
776 (val >> 16 & 0xffff) << 5;
777 break;
778 case R_AARCH64_MOVW_UABS_G2_NC:
779 *(uint32_t *)ptr = (*(uint32_t *)ptr & 0xffe0001f) |
780 (val >> 32 & 0xffff) << 5;
781 break;
782 case R_AARCH64_MOVW_UABS_G3:
783 *(uint32_t *)ptr = (*(uint32_t *)ptr & 0xffe0001f) |
784 (val >> 48 & 0xffff) << 5;
785 break;
786 case R_AARCH64_ADR_PREL_PG_HI21: {
787 uint64_t off = (val >> 12) - (addr >> 12);
788 if ((off + ((uint64_t)1 << 20)) >> 21)
789 tcc_error("R_AARCH64_ADR_PREL_PG_HI21 relocation failed");
790 *(uint32_t *)ptr = (*(uint32_t *)ptr & 0x9f00001f) |
791 (off & 0x1ffffc) << 3 | (off & 3) << 29;
792 break;
794 case R_AARCH64_ADD_ABS_LO12_NC:
795 *(uint32_t *)ptr = (*(uint32_t *)ptr & 0xffc003ff) |
796 (val & 0xfff) << 10;
797 break;
798 case R_AARCH64_JUMP26:
799 case R_AARCH64_CALL26:
800 if (((val - addr) + ((uint64_t)1 << 27)) & ~(uint64_t)0xffffffc)
801 tcc_error("R_AARCH64_(JUMP|CALL)26 relocation failed");
802 *(uint32_t *)ptr = 0x14000000 | (type == R_AARCH64_CALL26) << 31 |
803 ((val - addr) >> 2 & 0x3ffffff);
804 break;
805 case R_AARCH64_ADR_GOT_PAGE: {
806 uint64_t off =
807 (((s1->got->sh_addr +
808 s1->sym_attrs[sym_index].got_offset) >> 12) - (addr >> 12));
809 if ((off + ((uint64_t)1 << 20)) >> 21)
810 tcc_error("R_AARCH64_ADR_GOT_PAGE relocation failed");
811 *(uint32_t *)ptr = (*(uint32_t *)ptr & 0x9f00001f) |
812 (off & 0x1ffffc) << 3 | (off & 3) << 29;
813 break;
815 case R_AARCH64_LD64_GOT_LO12_NC:
816 *(uint32_t *)ptr = (*(uint32_t *)ptr & 0xfff803ff) |
817 ((s1->got->sh_addr + s1->sym_attrs[sym_index].got_offset)
818 & 0xff8) << 7;
819 break;
820 case R_AARCH64_COPY:
821 break;
822 default:
823 fprintf(stderr, "FIXME: handle reloc type %x at %x [%p] to %x\n",
824 type, (unsigned)addr, ptr, (unsigned)val);
825 break;
826 #elif defined(TCC_TARGET_C67)
827 case R_C60_32:
828 *(int *)ptr += val;
829 break;
830 case R_C60LO16:
832 uint32_t orig;
834 /* put the low 16 bits of the absolute address
835 add to what is already there */
837 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
838 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
840 /* patch both at once - assumes always in pairs Low - High */
842 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
843 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
845 break;
846 case R_C60HI16:
847 break;
848 default:
849 fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
850 type, (unsigned)addr, ptr, (unsigned)val);
851 break;
852 #elif defined(TCC_TARGET_X86_64)
853 case R_X86_64_64:
854 if (s1->output_type == TCC_OUTPUT_DLL) {
855 esym_index = s1->symtab_to_dynsym[sym_index];
856 qrel->r_offset = rel->r_offset;
857 if (esym_index) {
858 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_64);
859 qrel->r_addend = rel->r_addend;
860 qrel++;
861 break;
862 } else {
863 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
864 qrel->r_addend = *(long long *)ptr + val;
865 qrel++;
868 *(long long *)ptr += val;
869 break;
870 case R_X86_64_32:
871 case R_X86_64_32S:
872 if (s1->output_type == TCC_OUTPUT_DLL) {
873 /* XXX: this logic may depend on TCC's codegen
874 now TCC uses R_X86_64_32 even for a 64bit pointer */
875 qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
876 qrel->r_addend = *(int *)ptr + val;
877 qrel++;
879 *(int *)ptr += val;
880 break;
882 case R_X86_64_PC32:
883 if (s1->output_type == TCC_OUTPUT_DLL) {
884 /* DLL relocation */
885 esym_index = s1->symtab_to_dynsym[sym_index];
886 if (esym_index) {
887 qrel->r_offset = rel->r_offset;
888 qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
889 qrel->r_addend = *(int *)ptr;
890 qrel++;
891 break;
894 goto plt32pc32;
896 case R_X86_64_PLT32:
897 /* We've put the PLT slot offset into r_addend when generating
898 it, and that's what we must use as relocation value (adjusted
899 by section offset of course). */
900 val = s1->plt->sh_addr + rel->r_addend;
901 /* fallthrough. */
903 plt32pc32:
905 long long diff;
906 diff = (long long)val - addr;
907 if (diff <= -2147483647 || diff > 2147483647) {
908 tcc_error("internal error: relocation failed");
910 *(int *)ptr += diff;
912 break;
913 case R_X86_64_GLOB_DAT:
914 case R_X86_64_JUMP_SLOT:
915 /* They don't need addend */
916 *(addr_t *)ptr = val - rel->r_addend;
917 break;
918 case R_X86_64_GOTPCREL:
919 *(int *)ptr += (s1->got->sh_addr - addr +
920 s1->sym_attrs[sym_index].got_offset - 4);
921 break;
922 case R_X86_64_GOTTPOFF:
923 *(int *)ptr += val - s1->got->sh_addr;
924 break;
925 case R_X86_64_GOT32:
926 /* we load the got offset */
927 *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
928 break;
929 #else
930 #error unsupported processor
931 #endif
934 /* if the relocation is allocated, we change its symbol table */
935 if (sr->sh_flags & SHF_ALLOC)
936 sr->link = s1->dynsym;
939 /* relocate relocation table in 'sr' */
940 static void relocate_rel(TCCState *s1, Section *sr)
942 Section *s;
943 ElfW_Rel *rel;
945 s = s1->sections[sr->sh_info];
946 for_each_elem(sr, 0, rel, ElfW_Rel)
947 rel->r_offset += s->sh_addr;
950 /* count the number of dynamic relocations so that we can reserve
951 their space */
952 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
954 ElfW_Rel *rel;
955 int sym_index, esym_index, type, count;
957 count = 0;
958 for_each_elem(sr, 0, rel, ElfW_Rel) {
959 sym_index = ELFW(R_SYM)(rel->r_info);
960 type = ELFW(R_TYPE)(rel->r_info);
961 switch(type) {
962 #if defined(TCC_TARGET_I386)
963 case R_386_32:
964 #elif defined(TCC_TARGET_X86_64)
965 case R_X86_64_32:
966 case R_X86_64_32S:
967 case R_X86_64_64:
968 #endif
969 count++;
970 break;
971 #if defined(TCC_TARGET_I386)
972 case R_386_PC32:
973 #elif defined(TCC_TARGET_X86_64)
974 case R_X86_64_PC32:
975 #endif
976 esym_index = s1->symtab_to_dynsym[sym_index];
977 if (esym_index)
978 count++;
979 break;
980 default:
981 break;
984 if (count) {
985 /* allocate the section */
986 sr->sh_flags |= SHF_ALLOC;
987 sr->sh_size = count * sizeof(ElfW_Rel);
989 return count;
992 static struct sym_attr *alloc_sym_attr(TCCState *s1, int index)
994 int n;
995 struct sym_attr *tab;
997 if (index >= s1->nb_sym_attrs) {
998 /* find immediately bigger power of 2 and reallocate array */
999 n = 1;
1000 while (index >= n)
1001 n *= 2;
1002 tab = tcc_realloc(s1->sym_attrs, n * sizeof(*s1->sym_attrs));
1003 s1->sym_attrs = tab;
1004 memset(s1->sym_attrs + s1->nb_sym_attrs, 0,
1005 (n - s1->nb_sym_attrs) * sizeof(*s1->sym_attrs));
1006 s1->nb_sym_attrs = n;
1008 return &s1->sym_attrs[index];
1011 /* XXX: suppress that */
1012 static void put32(unsigned char *p, uint32_t val)
1014 p[0] = val;
1015 p[1] = val >> 8;
1016 p[2] = val >> 16;
1017 p[3] = val >> 24;
1020 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
1021 defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
1022 static uint32_t get32(unsigned char *p)
1024 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
1026 #endif
1028 static void build_got(TCCState *s1)
1030 unsigned char *ptr;
1032 /* if no got, then create it */
1033 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
1034 s1->got->sh_entsize = 4;
1035 add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
1036 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
1037 ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
1038 #if PTR_SIZE == 4
1039 /* keep space for _DYNAMIC pointer, if present */
1040 put32(ptr, 0);
1041 /* two dummy got entries */
1042 put32(ptr + 4, 0);
1043 put32(ptr + 8, 0);
1044 #else
1045 /* keep space for _DYNAMIC pointer, if present */
1046 put32(ptr, 0);
1047 put32(ptr + 4, 0);
1048 /* two dummy got entries */
1049 put32(ptr + 8, 0);
1050 put32(ptr + 12, 0);
1051 put32(ptr + 16, 0);
1052 put32(ptr + 20, 0);
1053 #endif
1056 /* put a got or plt entry corresponding to a symbol in symtab_section. 'size'
1057 and 'info' can be modifed if more precise info comes from the DLL.
1058 Returns offset of GOT or PLT slot. */
1059 static unsigned long put_got_entry(TCCState *s1,
1060 int reloc_type, unsigned long size, int info,
1061 int sym_index)
1063 int index, need_plt_entry;
1064 const char *name;
1065 ElfW(Sym) *sym;
1066 unsigned long offset;
1067 int *ptr;
1068 struct sym_attr *symattr;
1070 if (!s1->got)
1071 build_got(s1);
1073 need_plt_entry =
1074 #ifdef TCC_TARGET_X86_64
1075 (reloc_type == R_X86_64_JUMP_SLOT);
1076 #elif defined(TCC_TARGET_I386)
1077 (reloc_type == R_386_JMP_SLOT);
1078 #elif defined(TCC_TARGET_ARM)
1079 (reloc_type == R_ARM_JUMP_SLOT);
1080 #elif defined(TCC_TARGET_ARM64)
1081 (reloc_type == R_AARCH64_JUMP_SLOT);
1082 #else
1084 #endif
1086 if (need_plt_entry && !s1->plt) {
1087 /* add PLT */
1088 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1089 SHF_ALLOC | SHF_EXECINSTR);
1090 s1->plt->sh_entsize = 4;
1093 /* If a got/plt entry already exists for that symbol, no need to add one */
1094 if (sym_index < s1->nb_sym_attrs) {
1095 if (need_plt_entry && s1->sym_attrs[sym_index].plt_offset)
1096 return s1->sym_attrs[sym_index].plt_offset;
1097 else if (!need_plt_entry && s1->sym_attrs[sym_index].got_offset)
1098 return s1->sym_attrs[sym_index].got_offset;
1101 symattr = alloc_sym_attr(s1, sym_index);
1103 /* Only store the GOT offset if it's not generated for the PLT entry. */
1104 if (!need_plt_entry)
1105 symattr->got_offset = s1->got->data_offset;
1107 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1108 name = (char *) symtab_section->link->data + sym->st_name;
1109 offset = sym->st_value;
1110 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1111 if (need_plt_entry) {
1112 Section *plt;
1113 uint8_t *p;
1114 int modrm;
1115 unsigned long relofs;
1117 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1118 modrm = 0x25;
1119 #else
1120 /* if we build a DLL, we add a %ebx offset */
1121 if (s1->output_type == TCC_OUTPUT_DLL)
1122 modrm = 0xa3;
1123 else
1124 modrm = 0x25;
1125 #endif
1127 /* add a PLT entry */
1128 plt = s1->plt;
1129 if (plt->data_offset == 0) {
1130 /* first plt entry */
1131 p = section_ptr_add(plt, 16);
1132 p[0] = 0xff; /* pushl got + PTR_SIZE */
1133 p[1] = modrm + 0x10;
1134 put32(p + 2, PTR_SIZE);
1135 p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1136 p[7] = modrm;
1137 put32(p + 8, PTR_SIZE * 2);
1140 /* The PLT slot refers to the relocation entry it needs
1141 via offset. The reloc entry is created below, so its
1142 offset is the current data_offset. */
1143 relofs = s1->got->reloc ? s1->got->reloc->data_offset : 0;
1144 symattr->plt_offset = plt->data_offset;
1145 p = section_ptr_add(plt, 16);
1146 p[0] = 0xff; /* jmp *(got + x) */
1147 p[1] = modrm;
1148 put32(p + 2, s1->got->data_offset);
1149 p[6] = 0x68; /* push $xxx */
1150 #ifdef TCC_TARGET_X86_64
1151 /* On x86-64, the relocation is referred to by _index_. */
1152 put32(p + 7, relofs / sizeof (ElfW_Rel));
1153 #else
1154 put32(p + 7, relofs);
1155 #endif
1156 p[11] = 0xe9; /* jmp plt_start */
1157 put32(p + 12, -(plt->data_offset));
1159 /* If this was an UNDEF symbol set the offset in the
1160 dynsymtab to the PLT slot, so that PC32 relocs to it
1161 can be resolved. */
1162 if (sym->st_shndx == SHN_UNDEF)
1163 offset = plt->data_offset - 16;
1165 #elif defined(TCC_TARGET_ARM)
1166 if (need_plt_entry) {
1167 Section *plt;
1168 uint8_t *p;
1170 /* if we build a DLL, we add a %ebx offset */
1171 if (s1->output_type == TCC_OUTPUT_DLL)
1172 tcc_error("DLLs unimplemented!");
1174 /* add a PLT entry */
1175 plt = s1->plt;
1176 if (plt->data_offset == 0) {
1177 /* first plt entry */
1178 p = section_ptr_add(plt, 16);
1179 put32(p, 0xe52de004); /* push {lr} */
1180 put32(p+4, 0xe59fe010); /* ldr lr, [pc, #16] */
1181 put32(p+8, 0xe08fe00e); /* add lr, pc, lr */
1182 put32(p+12, 0xe5bef008); /* ldr pc, [lr, #8]! */
1185 symattr->plt_offset = plt->data_offset;
1186 if (symattr->plt_thumb_stub) {
1187 p = section_ptr_add(plt, 20);
1188 put32(p, 0x4778); /* bx pc */
1189 put32(p+2, 0x46c0); /* nop */
1190 p += 4;
1191 } else
1192 p = section_ptr_add(plt, 16);
1193 put32(p, 0xe59fc004); /* ldr ip, [pc, #4] ; GOT entry offset */
1194 put32(p+4, 0xe08fc00c); /* add ip, pc, ip ; addr of GOT entry */
1195 put32(p+8, 0xe59cf000); /* ldr pc, [ip] ; jump to GOT entry */
1196 put32(p+12, s1->got->data_offset); /* GOT entry off once patched */
1198 /* the symbol is modified so that it will be relocated to
1199 the PLT */
1200 if (sym->st_shndx == SHN_UNDEF)
1201 offset = plt->data_offset - 16;
1203 #elif defined(TCC_TARGET_ARM64)
1204 if (need_plt_entry) {
1205 Section *plt;
1206 uint8_t *p;
1208 if (s1->output_type == TCC_OUTPUT_DLL)
1209 tcc_error("DLLs unimplemented!");
1211 plt = s1->plt;
1212 if (plt->data_offset == 0)
1213 section_ptr_add(plt, 32);
1214 p = section_ptr_add(plt, 16);
1215 put32(p, s1->got->data_offset);
1216 put32(p + 4, (uint64_t)s1->got->data_offset >> 32);
1218 if (sym->st_shndx == SHN_UNDEF)
1219 offset = plt->data_offset - 16;
1221 #elif defined(TCC_TARGET_C67)
1222 if (s1->dynsym) {
1223 tcc_error("C67 got not implemented");
1225 #else
1226 #error unsupported CPU
1227 #endif
1228 if (s1->dynsym) {
1229 /* XXX This might generate multiple syms for name. */
1230 index = put_elf_sym(s1->dynsym, offset,
1231 size, info, 0, sym->st_shndx, name);
1232 /* Create the relocation (it's against the GOT for PLT
1233 and GOT relocs). */
1234 put_elf_reloc(s1->dynsym, s1->got,
1235 s1->got->data_offset,
1236 reloc_type, index);
1237 } else {
1238 /* Without .dynsym (i.e. static link or memory output) we
1239 still need relocs against the generated got, so as to fill
1240 the entries with the symbol values (determined later). */
1241 put_elf_reloc(symtab_section, s1->got,
1242 s1->got->data_offset,
1243 reloc_type, sym_index);
1245 /* And now create the GOT slot itself. */
1246 ptr = section_ptr_add(s1->got, PTR_SIZE);
1247 *ptr = 0;
1248 if (need_plt_entry)
1249 return symattr->plt_offset;
1250 else
1251 return symattr->got_offset;
1254 /* build GOT and PLT entries */
1255 ST_FUNC void build_got_entries(TCCState *s1)
1257 Section *s;
1258 ElfW_Rel *rel;
1259 ElfW(Sym) *sym;
1260 int i, type, reloc_type, sym_index;
1262 for(i = 1; i < s1->nb_sections; i++) {
1263 s = s1->sections[i];
1264 if (s->sh_type != SHT_RELX)
1265 continue;
1266 /* no need to handle got relocations */
1267 if (s->link != symtab_section)
1268 continue;
1269 for_each_elem(s, 0, rel, ElfW_Rel) {
1270 type = ELFW(R_TYPE)(rel->r_info);
1271 switch(type) {
1272 #if defined(TCC_TARGET_I386)
1273 case R_386_GOT32:
1274 case R_386_GOTOFF:
1275 case R_386_GOTPC:
1276 case R_386_PLT32:
1277 if (!s1->got)
1278 build_got(s1);
1279 if (type == R_386_GOT32 || type == R_386_PLT32) {
1280 sym_index = ELFW(R_SYM)(rel->r_info);
1281 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1282 /* look at the symbol got offset. If none, then add one */
1283 if (type == R_386_GOT32)
1284 reloc_type = R_386_GLOB_DAT;
1285 else
1286 reloc_type = R_386_JMP_SLOT;
1287 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1288 sym_index);
1290 break;
1291 #elif defined(TCC_TARGET_ARM)
1292 case R_ARM_PC24:
1293 case R_ARM_CALL:
1294 case R_ARM_JUMP24:
1295 case R_ARM_GOT32:
1296 case R_ARM_GOTOFF:
1297 case R_ARM_GOTPC:
1298 case R_ARM_PLT32:
1299 if (!s1->got)
1300 build_got(s1);
1301 sym_index = ELFW(R_SYM)(rel->r_info);
1302 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1303 if (type != R_ARM_GOTOFF && type != R_ARM_GOTPC
1304 && sym->st_shndx == SHN_UNDEF) {
1305 unsigned long ofs;
1306 /* look at the symbol got offset. If none, then add one */
1307 if (type == R_ARM_GOT32)
1308 reloc_type = R_ARM_GLOB_DAT;
1309 else
1310 reloc_type = R_ARM_JUMP_SLOT;
1311 ofs = put_got_entry(s1, reloc_type, sym->st_size,
1312 sym->st_info, sym_index);
1313 #ifdef DEBUG_RELOC
1314 printf ("maybegot: %s, %d, %d --> ofs=0x%x\n",
1315 (char *) symtab_section->link->data + sym->st_name,
1316 type, sym->st_shndx, ofs);
1317 #endif
1318 if (type != R_ARM_GOT32) {
1319 addr_t *ptr = (addr_t*)(s1->sections[s->sh_info]->data
1320 + rel->r_offset);
1321 /* x must be signed! */
1322 int x = *ptr & 0xffffff;
1323 x = (x << 8) >> 8;
1324 x <<= 2;
1325 x += ofs;
1326 x >>= 2;
1327 #ifdef DEBUG_RELOC
1328 printf ("insn=0x%x --> 0x%x (x==0x%x)\n", *ptr,
1329 (*ptr & 0xff000000) | x, x);
1330 #endif
1331 *ptr = (*ptr & 0xff000000) | x;
1334 break;
1335 case R_ARM_THM_JUMP24:
1336 sym_index = ELFW(R_SYM)(rel->r_info);
1337 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1338 /* We are relocating a jump from thumb code to arm code */
1339 if (sym->st_shndx != SHN_UNDEF && !(sym->st_value & 1)) {
1340 int index;
1341 uint8_t *p;
1342 char *name, buf[1024];
1343 Section *text_section;
1345 name = (char *) symtab_section->link->data + sym->st_name;
1346 text_section = s1->sections[sym->st_shndx];
1347 /* Modify reloc to target a thumb stub to switch to ARM */
1348 snprintf(buf, sizeof(buf), "%s_from_thumb", name);
1349 index = put_elf_sym(symtab_section,
1350 text_section->data_offset + 1,
1351 sym->st_size, sym->st_info, 0,
1352 sym->st_shndx, buf);
1353 rel->r_info = ELFW(R_INFO)(index, type);
1354 /* Create a thumb stub fonction to switch to ARM mode */
1355 put_elf_reloc(symtab_section, text_section,
1356 text_section->data_offset + 4, R_ARM_JUMP24,
1357 sym_index);
1358 p = section_ptr_add(text_section, 8);
1359 put32(p, 0x4778); /* bx pc */
1360 put32(p+2, 0x46c0); /* nop */
1361 put32(p+4, 0xeafffffe); /* b $sym */
1363 #elif defined(TCC_TARGET_ARM64)
1364 //xx Other cases may be required here:
1365 case R_AARCH64_ADR_GOT_PAGE:
1366 case R_AARCH64_LD64_GOT_LO12_NC:
1367 if (!s1->got)
1368 build_got(s1);
1369 sym_index = ELFW(R_SYM)(rel->r_info);
1370 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1371 reloc_type = R_AARCH64_GLOB_DAT;
1372 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1373 sym_index);
1374 break;
1375 #elif defined(TCC_TARGET_C67)
1376 case R_C60_GOT32:
1377 case R_C60_GOTOFF:
1378 case R_C60_GOTPC:
1379 case R_C60_PLT32:
1380 if (!s1->got)
1381 build_got(s1);
1382 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1383 sym_index = ELFW(R_SYM)(rel->r_info);
1384 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1385 /* look at the symbol got offset. If none, then add one */
1386 if (type == R_C60_GOT32)
1387 reloc_type = R_C60_GLOB_DAT;
1388 else
1389 reloc_type = R_C60_JMP_SLOT;
1390 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1391 sym_index);
1393 break;
1394 #elif defined(TCC_TARGET_X86_64)
1395 case R_X86_64_GOT32:
1396 case R_X86_64_GOTTPOFF:
1397 case R_X86_64_GOTPCREL:
1398 case R_X86_64_PLT32:
1399 sym_index = ELFW(R_SYM)(rel->r_info);
1400 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1401 if (type == R_X86_64_PLT32 &&
1402 ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT)
1404 rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32);
1405 break;
1408 if (!s1->got)
1409 build_got(s1);
1410 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1411 type == R_X86_64_PLT32) {
1412 unsigned long ofs;
1413 /* look at the symbol got offset. If none, then add one */
1414 if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1415 reloc_type = R_X86_64_GLOB_DAT;
1416 else
1417 reloc_type = R_X86_64_JUMP_SLOT;
1418 ofs = put_got_entry(s1, reloc_type, sym->st_size,
1419 sym->st_info, sym_index);
1420 if (type == R_X86_64_PLT32)
1421 /* We store the place of the generated PLT slot
1422 in our addend. */
1423 rel->r_addend += ofs;
1425 break;
1426 #else
1427 #error unsupported CPU
1428 #endif
1429 default:
1430 break;
1436 ST_FUNC Section *new_symtab(TCCState *s1,
1437 const char *symtab_name, int sh_type, int sh_flags,
1438 const char *strtab_name,
1439 const char *hash_name, int hash_sh_flags)
1441 Section *symtab, *strtab, *hash;
1442 int *ptr, nb_buckets;
1444 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1445 symtab->sh_entsize = sizeof(ElfW(Sym));
1446 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1447 put_elf_str(strtab, "");
1448 symtab->link = strtab;
1449 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1451 nb_buckets = 1;
1453 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1454 hash->sh_entsize = sizeof(int);
1455 symtab->hash = hash;
1456 hash->link = symtab;
1458 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1459 ptr[0] = nb_buckets;
1460 ptr[1] = 1;
1461 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1462 return symtab;
1465 /* put dynamic tag */
1466 static void put_dt(Section *dynamic, int dt, addr_t val)
1468 ElfW(Dyn) *dyn;
1469 dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1470 dyn->d_tag = dt;
1471 dyn->d_un.d_val = val;
1474 static void add_init_array_defines(TCCState *s1, const char *section_name)
1476 Section *s;
1477 long end_offset;
1478 char sym_start[1024];
1479 char sym_end[1024];
1481 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1482 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1484 s = find_section(s1, section_name);
1485 if (!s) {
1486 end_offset = 0;
1487 s = data_section;
1488 } else {
1489 end_offset = s->data_offset;
1492 add_elf_sym(symtab_section,
1493 0, 0,
1494 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1495 s->sh_num, sym_start);
1496 add_elf_sym(symtab_section,
1497 end_offset, 0,
1498 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1499 s->sh_num, sym_end);
1502 ST_FUNC void tcc_add_bcheck(TCCState *s1)
1504 #ifdef CONFIG_TCC_BCHECK
1505 unsigned long *ptr;
1506 Section *init_section;
1507 unsigned char *pinit;
1508 int sym_index;
1510 if (0 == s1->do_bounds_check)
1511 return;
1513 /* XXX: add an object file to do that */
1514 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1515 *ptr = 0;
1516 add_elf_sym(symtab_section, 0, 0,
1517 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1518 bounds_section->sh_num, "__bounds_start");
1519 #ifdef TCC_TARGET_I386
1520 if (s1->output_type != TCC_OUTPUT_MEMORY) {
1521 /* add 'call __bound_init()' in .init section */
1522 init_section = find_section(s1, ".init");
1523 pinit = section_ptr_add(init_section, 5);
1524 pinit[0] = 0xe8;
1525 put32(pinit + 1, -4);
1526 sym_index = find_elf_sym(symtab_section, "__bound_init");
1527 put_elf_reloc(symtab_section, init_section,
1528 init_section->data_offset - 4, R_386_PC32, sym_index);
1530 #endif
1531 #endif
1534 static inline int tcc_add_support(TCCState *s1, const char *filename)
1536 char buf[1024];
1537 snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, filename);
1538 return tcc_add_file(s1, buf);
1541 /* add tcc runtime libraries */
1542 ST_FUNC void tcc_add_runtime(TCCState *s1)
1544 /* add libc */
1545 if (!s1->nostdlib) {
1546 tcc_add_library(s1, "c");
1547 #ifdef CONFIG_USE_LIBGCC
1548 if (!s1->static_link) {
1549 tcc_add_file(s1, TCC_LIBGCC);
1550 tcc_add_support(s1, "libtcc1.a");
1551 } else
1552 tcc_add_support(s1, "libtcc1.a");
1553 #else
1554 tcc_add_support(s1, "libtcc1.a");
1555 #endif
1558 /* tcc_add_bcheck tries to relocate a call to __bound_init in _init so
1559 libtcc1.a must be loaded before for __bound_init to be defined and
1560 crtn.o must be loaded after to not finalize _init too early. */
1561 tcc_add_bcheck(s1);
1563 if (!s1->nostdlib) {
1564 /* add crt end if not memory output */
1565 if (s1->output_type != TCC_OUTPUT_MEMORY)
1566 tcc_add_crt(s1, "crtn.o");
1570 /* add various standard linker symbols (must be done after the
1571 sections are filled (for example after allocating common
1572 symbols)) */
1573 ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1575 char buf[1024];
1576 int i;
1577 Section *s;
1579 add_elf_sym(symtab_section,
1580 text_section->data_offset, 0,
1581 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1582 text_section->sh_num, "_etext");
1583 add_elf_sym(symtab_section,
1584 data_section->data_offset, 0,
1585 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1586 data_section->sh_num, "_edata");
1587 add_elf_sym(symtab_section,
1588 bss_section->data_offset, 0,
1589 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1590 bss_section->sh_num, "_end");
1591 /* horrible new standard ldscript defines */
1592 add_init_array_defines(s1, ".preinit_array");
1593 add_init_array_defines(s1, ".init_array");
1594 add_init_array_defines(s1, ".fini_array");
1596 /* add start and stop symbols for sections whose name can be
1597 expressed in C */
1598 for(i = 1; i < s1->nb_sections; i++) {
1599 s = s1->sections[i];
1600 if (s->sh_type == SHT_PROGBITS &&
1601 (s->sh_flags & SHF_ALLOC)) {
1602 const char *p;
1603 int ch;
1605 /* check if section name can be expressed in C */
1606 p = s->name;
1607 for(;;) {
1608 ch = *p;
1609 if (!ch)
1610 break;
1611 if (!isid(ch) && !isnum(ch))
1612 goto next_sec;
1613 p++;
1615 snprintf(buf, sizeof(buf), "__start_%s", s->name);
1616 add_elf_sym(symtab_section,
1617 0, 0,
1618 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1619 s->sh_num, buf);
1620 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1621 add_elf_sym(symtab_section,
1622 s->data_offset, 0,
1623 ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1624 s->sh_num, buf);
1626 next_sec: ;
1630 static void tcc_output_binary(TCCState *s1, FILE *f,
1631 const int *sec_order)
1633 Section *s;
1634 int i, offset, size;
1636 offset = 0;
1637 for(i=1;i<s1->nb_sections;i++) {
1638 s = s1->sections[sec_order[i]];
1639 if (s->sh_type != SHT_NOBITS &&
1640 (s->sh_flags & SHF_ALLOC)) {
1641 while (offset < s->sh_offset) {
1642 fputc(0, f);
1643 offset++;
1645 size = s->sh_size;
1646 fwrite(s->data, 1, size, f);
1647 offset += size;
1652 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1653 #define HAVE_PHDR 1
1654 #define EXTRA_RELITEMS 14
1656 /* move the relocation value from .dynsym to .got */
1657 void patch_dynsym_undef(TCCState *s1, Section *s)
1659 uint32_t *gotd = (void *)s1->got->data;
1660 ElfW(Sym) *sym;
1662 gotd += 3; /* dummy entries in .got */
1663 /* relocate symbols in .dynsym */
1664 for_each_elem(s, 1, sym, ElfW(Sym)) {
1665 if (sym->st_shndx == SHN_UNDEF) {
1666 *gotd++ = sym->st_value + 6; /* XXX 6 is magic ? */
1667 sym->st_value = 0;
1671 #else
1672 #define HAVE_PHDR 1
1673 #define EXTRA_RELITEMS 9
1675 /* zero plt offsets of weak symbols in .dynsym */
1676 void patch_dynsym_undef(TCCState *s1, Section *s)
1678 ElfW(Sym) *sym;
1680 for_each_elem(s, 1, sym, ElfW(Sym))
1681 if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
1682 sym->st_value = 0;
1684 #endif
1686 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1688 int sym_index = ELFW(R_SYM) (rel->r_info);
1689 ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1690 unsigned long offset;
1692 if (sym_index >= s1->nb_sym_attrs)
1693 return;
1694 offset = s1->sym_attrs[sym_index].got_offset;
1695 section_reserve(s1->got, offset + PTR_SIZE);
1696 #ifdef TCC_TARGET_X86_64
1697 /* only works for x86-64 */
1698 put32(s1->got->data + offset + 4, sym->st_value >> 32);
1699 #endif
1700 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1703 /* Perform relocation to GOT or PLT entries */
1704 ST_FUNC void fill_got(TCCState *s1)
1706 Section *s;
1707 ElfW_Rel *rel;
1708 int i;
1710 for(i = 1; i < s1->nb_sections; i++) {
1711 s = s1->sections[i];
1712 if (s->sh_type != SHT_RELX)
1713 continue;
1714 /* no need to handle got relocations */
1715 if (s->link != symtab_section)
1716 continue;
1717 for_each_elem(s, 0, rel, ElfW_Rel) {
1718 switch (ELFW(R_TYPE) (rel->r_info)) {
1719 case R_X86_64_GOT32:
1720 case R_X86_64_GOTPCREL:
1721 case R_X86_64_PLT32:
1722 fill_got_entry(s1, rel);
1723 break;
1729 /* Bind symbols of executable: resolve undefined symbols from exported symbols
1730 in shared libraries and export non local defined symbols to shared libraries
1731 if -rdynamic switch was given on command line */
1732 static void bind_exe_dynsyms(TCCState *s1)
1734 const char *name;
1735 int sym_index, index;
1736 ElfW(Sym) *sym, *esym;
1737 int type;
1739 /* Resolve undefined symbols from dynamic symbols. When there is a match:
1740 - if STT_FUNC or STT_GNU_IFUNC symbol -> add it in PLT
1741 - if STT_OBJECT symbol -> add it in .bss section with suitable reloc */
1742 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
1743 if (sym->st_shndx == SHN_UNDEF) {
1744 name = (char *) symtab_section->link->data + sym->st_name;
1745 sym_index = find_elf_sym(s1->dynsymtab_section, name);
1746 if (sym_index) {
1747 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1748 type = ELFW(ST_TYPE)(esym->st_info);
1749 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1750 /* Indirect functions shall have STT_FUNC type in executable
1751 * dynsym section. Indeed, a dlsym call following a lazy
1752 * resolution would pick the symbol value from the
1753 * executable dynsym entry which would contain the address
1754 * of the function wanted by the caller of dlsym instead of
1755 * the address of the function that would return that
1756 * address */
1757 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1758 ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC),
1759 sym - (ElfW(Sym) *)symtab_section->data);
1760 } else if (type == STT_OBJECT) {
1761 unsigned long offset;
1762 ElfW(Sym) *dynsym;
1763 offset = bss_section->data_offset;
1764 /* XXX: which alignment ? */
1765 offset = (offset + 16 - 1) & -16;
1766 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1767 esym->st_info, 0, bss_section->sh_num,
1768 name);
1769 /* Ensure R_COPY works for weak symbol aliases */
1770 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1771 for_each_elem(s1->dynsymtab_section, 1, dynsym, ElfW(Sym)) {
1772 if ((dynsym->st_value == esym->st_value)
1773 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1774 char *dynname = (char *) s1->dynsymtab_section->link->data
1775 + dynsym->st_name;
1776 put_elf_sym(s1->dynsym, offset, dynsym->st_size,
1777 dynsym->st_info, 0,
1778 bss_section->sh_num, dynname);
1779 break;
1783 put_elf_reloc(s1->dynsym, bss_section,
1784 offset, R_COPY, index);
1785 offset += esym->st_size;
1786 bss_section->data_offset = offset;
1788 } else {
1789 /* STB_WEAK undefined symbols are accepted */
1790 /* XXX: _fp_hw seems to be part of the ABI, so we ignore it */
1791 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1792 !strcmp(name, "_fp_hw")) {
1793 } else {
1794 tcc_error_noabort("undefined symbol '%s'", name);
1797 } else if (s1->rdynamic && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1798 /* if -rdynamic option, then export all non local symbols */
1799 name = (char *) symtab_section->link->data + sym->st_name;
1800 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, sym->st_info,
1801 0, sym->st_shndx, name);
1806 /* Bind symbols of libraries: export non local symbols of executable that
1807 resolve undefined symbols of shared libraries */
1808 static void bind_libs_dynsyms(TCCState *s1)
1810 const char *name;
1811 int sym_index;
1812 ElfW(Sym) *sym, *esym;
1814 /* now look at unresolved dynamic symbols and export
1815 corresponding symbol */
1816 for_each_elem(s1->dynsymtab_section, 1, esym, ElfW(Sym)) {
1817 if (esym->st_shndx == SHN_UNDEF) {
1818 name = (char *) s1->dynsymtab_section->link->data + esym->st_name;
1819 sym_index = find_elf_sym(symtab_section, name);
1820 if (sym_index) {
1821 /* XXX: avoid adding a symbol if already present because of
1822 -rdynamic ? */
1823 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1824 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1825 sym->st_info, 0, sym->st_shndx, name);
1826 } else {
1827 /* weak symbols can stay undefined */
1828 if (ELFW(ST_BIND)(esym->st_info) != STB_WEAK)
1829 tcc_warning("undefined dynamic symbol '%s'", name);
1835 /* Export all non local symbols (for shared libraries) */
1836 static void export_global_syms(TCCState *s1)
1838 int nb_syms, dynindex, index;
1839 const char *name;
1840 ElfW(Sym) *sym;
1842 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1843 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1844 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
1845 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1846 name = (char *) symtab_section->link->data + sym->st_name;
1847 dynindex = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1848 sym->st_info, 0, sym->st_shndx, name);
1849 index = sym - (ElfW(Sym) *) symtab_section->data;
1850 s1->symtab_to_dynsym[index] = dynindex;
1855 /* relocate the PLT: compute addresses and offsets in the PLT now that final
1856 address for PLT and GOT are known (see fill_program_header) */
1857 ST_FUNC void relocate_plt(TCCState *s1)
1859 uint8_t *p, *p_end;
1861 if (!s1->plt)
1862 return;
1864 p = s1->plt->data;
1865 p_end = p + s1->plt->data_offset;
1866 if (p < p_end) {
1867 #if defined(TCC_TARGET_I386)
1868 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1869 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1870 p += 16;
1871 while (p < p_end) {
1872 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1873 p += 16;
1875 #elif defined(TCC_TARGET_X86_64)
1876 int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1877 put32(p + 2, get32(p + 2) + x);
1878 put32(p + 8, get32(p + 8) + x - 6);
1879 p += 16;
1880 while (p < p_end) {
1881 put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1882 p += 16;
1884 #elif defined(TCC_TARGET_ARM)
1885 int x;
1886 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1887 p += 16;
1888 while (p < p_end) {
1889 if (get32(p) == 0x46c04778) /* PLT Thumb stub present */
1890 p += 4;
1891 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1892 p += 16;
1894 #elif defined(TCC_TARGET_ARM64)
1895 uint64_t plt = s1->plt->sh_addr;
1896 uint64_t got = s1->got->sh_addr;
1897 uint64_t off = (got >> 12) - (plt >> 12);
1898 if ((off + ((uint64_t)1 << 20)) >> 21)
1899 tcc_error("Failed relocating PLT");
1900 put32(p, 0xa9bf7bf0); // stp x16,x30,[sp,#-16]!
1901 put32(p + 4, (0x90000010 | // adrp x16,...
1902 (off & 0x1ffffc) << 3 | (off & 3) << 29));
1903 put32(p + 8, (0xf9400211 | // ldr x17,[x16,#...]
1904 (got & 0xff8) << 7));
1905 put32(p + 12, (0x91000210 | // add x16,x16,#...
1906 (got & 0xfff) << 10));
1907 put32(p + 16, 0xd61f0220); // br x17
1908 put32(p + 20, 0xd503201f); // nop
1909 put32(p + 24, 0xd503201f); // nop
1910 put32(p + 28, 0xd503201f); // nop
1911 p += 32;
1912 while (p < p_end) {
1913 uint64_t pc = plt + (p - s1->plt->data);
1914 uint64_t addr = got +
1915 (get32(p) | (uint64_t)get32(p + 4) << 32);
1916 uint32_t off = (addr >> 12) - (pc >> 12);
1917 if ((off + ((uint64_t)1 << 20)) >> 21)
1918 tcc_error("Failed relocating PLT");
1919 put32(p, (0x90000010 | // adrp x16,...
1920 (off & 0x1ffffc) << 3 | (off & 3) << 29));
1921 put32(p + 4, (0xf9400211 | // ldr x17,[x16,#...]
1922 (addr & 0xff8) << 7));
1923 put32(p + 8, (0x91000210 | // add x16,x16,#...
1924 (addr & 0xfff) << 10));
1925 put32(p + 12, 0xd61f0220); // br x17
1926 p += 16;
1928 #elif defined(TCC_TARGET_C67)
1929 /* XXX: TODO */
1930 #else
1931 #error unsupported CPU
1932 #endif
1936 /* Allocate strings for section names and decide if an unallocated section
1937 should be output.
1939 NOTE: the strsec section comes last, so its size is also correct ! */
1940 static void alloc_sec_names(TCCState *s1, int file_type, Section *strsec)
1942 int i;
1943 Section *s;
1945 /* Allocate strings for section names */
1946 for(i = 1; i < s1->nb_sections; i++) {
1947 s = s1->sections[i];
1948 s->sh_name = put_elf_str(strsec, s->name);
1949 /* when generating a DLL, we include relocations but we may
1950 patch them */
1951 if (file_type == TCC_OUTPUT_DLL &&
1952 s->sh_type == SHT_RELX &&
1953 !(s->sh_flags & SHF_ALLOC)) {
1954 /* gr: avoid bogus relocs for empty (debug) sections */
1955 if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1956 prepare_dynamic_rel(s1, s);
1957 else if (s1->do_debug)
1958 s->sh_size = s->data_offset;
1959 } else if (s1->do_debug ||
1960 file_type == TCC_OUTPUT_OBJ ||
1961 (s->sh_flags & SHF_ALLOC) ||
1962 i == (s1->nb_sections - 1)) {
1963 /* we output all sections if debug or object file */
1964 s->sh_size = s->data_offset;
1969 /* Info to be copied in dynamic section */
1970 struct dyn_inf {
1971 Section *dynamic;
1972 Section *dynstr;
1973 unsigned long dyn_rel_off;
1974 addr_t rel_addr;
1975 addr_t rel_size;
1976 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1977 addr_t bss_addr;
1978 addr_t bss_size;
1979 #endif
1982 /* Assign sections to segments and decide how are sections laid out when loaded
1983 in memory. This function also fills corresponding program headers. */
1984 static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
1985 Section *interp, Section* strsec,
1986 struct dyn_inf *dyninf, int *sec_order)
1988 int i, j, k, file_type, sh_order_index, file_offset;
1989 unsigned long s_align;
1990 long long tmp;
1991 addr_t addr;
1992 ElfW(Phdr) *ph;
1993 Section *s;
1995 file_type = s1->output_type;
1996 sh_order_index = 1;
1997 file_offset = 0;
1998 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
1999 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2000 s_align = ELF_PAGE_SIZE;
2001 if (s1->section_align)
2002 s_align = s1->section_align;
2004 if (phnum > 0) {
2005 if (s1->has_text_addr) {
2006 int a_offset, p_offset;
2007 addr = s1->text_addr;
2008 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
2009 ELF_PAGE_SIZE */
2010 a_offset = (int) (addr & (s_align - 1));
2011 p_offset = file_offset & (s_align - 1);
2012 if (a_offset < p_offset)
2013 a_offset += s_align;
2014 file_offset += (a_offset - p_offset);
2015 } else {
2016 if (file_type == TCC_OUTPUT_DLL)
2017 addr = 0;
2018 else
2019 addr = ELF_START_ADDR;
2020 /* compute address after headers */
2021 addr += (file_offset & (s_align - 1));
2024 ph = &phdr[0];
2025 /* Leave one program headers for the program interpreter and one for
2026 the program header table itself if needed. These are done later as
2027 they require section layout to be done first. */
2028 if (interp)
2029 ph += 1 + HAVE_PHDR;
2031 /* dynamic relocation table information, for .dynamic section */
2032 dyninf->rel_addr = dyninf->rel_size = 0;
2033 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2034 dyninf->bss_addr = dyninf->bss_size = 0;
2035 #endif
2037 for(j = 0; j < 2; j++) {
2038 ph->p_type = PT_LOAD;
2039 if (j == 0)
2040 ph->p_flags = PF_R | PF_X;
2041 else
2042 ph->p_flags = PF_R | PF_W;
2043 ph->p_align = s_align;
2045 /* Decide the layout of sections loaded in memory. This must
2046 be done before program headers are filled since they contain
2047 info about the layout. We do the following ordering: interp,
2048 symbol tables, relocations, progbits, nobits */
2049 /* XXX: do faster and simpler sorting */
2050 for(k = 0; k < 5; k++) {
2051 for(i = 1; i < s1->nb_sections; i++) {
2052 s = s1->sections[i];
2053 /* compute if section should be included */
2054 if (j == 0) {
2055 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
2056 SHF_ALLOC)
2057 continue;
2058 } else {
2059 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
2060 (SHF_ALLOC | SHF_WRITE))
2061 continue;
2063 if (s == interp) {
2064 if (k != 0)
2065 continue;
2066 } else if (s->sh_type == SHT_DYNSYM ||
2067 s->sh_type == SHT_STRTAB ||
2068 s->sh_type == SHT_HASH) {
2069 if (k != 1)
2070 continue;
2071 } else if (s->sh_type == SHT_RELX) {
2072 if (k != 2)
2073 continue;
2074 } else if (s->sh_type == SHT_NOBITS) {
2075 if (k != 4)
2076 continue;
2077 } else {
2078 if (k != 3)
2079 continue;
2081 sec_order[sh_order_index++] = i;
2083 /* section matches: we align it and add its size */
2084 tmp = addr;
2085 addr = (addr + s->sh_addralign - 1) &
2086 ~(s->sh_addralign - 1);
2087 file_offset += (int) ( addr - tmp );
2088 s->sh_offset = file_offset;
2089 s->sh_addr = addr;
2091 /* update program header infos */
2092 if (ph->p_offset == 0) {
2093 ph->p_offset = file_offset;
2094 ph->p_vaddr = addr;
2095 ph->p_paddr = ph->p_vaddr;
2097 /* update dynamic relocation infos */
2098 if (s->sh_type == SHT_RELX) {
2099 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2100 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) {
2101 dyninf->rel_addr = addr;
2102 dyninf->rel_size += s->sh_size; /* XXX only first rel. */
2104 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) {
2105 dyninf->bss_addr = addr;
2106 dyninf->bss_size = s->sh_size; /* XXX only first rel. */
2108 #else
2109 if (dyninf->rel_size == 0)
2110 dyninf->rel_addr = addr;
2111 dyninf->rel_size += s->sh_size;
2112 #endif
2114 addr += s->sh_size;
2115 if (s->sh_type != SHT_NOBITS)
2116 file_offset += s->sh_size;
2119 if (j == 0) {
2120 /* Make the first PT_LOAD segment include the program
2121 headers itself (and the ELF header as well), it'll
2122 come out with same memory use but will make various
2123 tools like binutils strip work better. */
2124 ph->p_offset &= ~(ph->p_align - 1);
2125 ph->p_vaddr &= ~(ph->p_align - 1);
2126 ph->p_paddr &= ~(ph->p_align - 1);
2128 ph->p_filesz = file_offset - ph->p_offset;
2129 ph->p_memsz = addr - ph->p_vaddr;
2130 ph++;
2131 if (j == 0) {
2132 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2133 /* if in the middle of a page, we duplicate the page in
2134 memory so that one copy is RX and the other is RW */
2135 if ((addr & (s_align - 1)) != 0)
2136 addr += s_align;
2137 } else {
2138 addr = (addr + s_align - 1) & ~(s_align - 1);
2139 file_offset = (file_offset + s_align - 1) & ~(s_align - 1);
2145 /* all other sections come after */
2146 for(i = 1; i < s1->nb_sections; i++) {
2147 s = s1->sections[i];
2148 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2149 continue;
2150 sec_order[sh_order_index++] = i;
2152 file_offset = (file_offset + s->sh_addralign - 1) &
2153 ~(s->sh_addralign - 1);
2154 s->sh_offset = file_offset;
2155 if (s->sh_type != SHT_NOBITS)
2156 file_offset += s->sh_size;
2159 return file_offset;
2162 static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp,
2163 Section *dynamic)
2165 ElfW(Phdr) *ph;
2167 /* if interpreter, then add corresponding program header */
2168 if (interp) {
2169 ph = &phdr[0];
2171 if (HAVE_PHDR)
2173 int len = phnum * sizeof(ElfW(Phdr));
2175 ph->p_type = PT_PHDR;
2176 ph->p_offset = sizeof(ElfW(Ehdr));
2177 ph->p_vaddr = interp->sh_addr - len;
2178 ph->p_paddr = ph->p_vaddr;
2179 ph->p_filesz = ph->p_memsz = len;
2180 ph->p_flags = PF_R | PF_X;
2181 ph->p_align = 4; /* interp->sh_addralign; */
2182 ph++;
2185 ph->p_type = PT_INTERP;
2186 ph->p_offset = interp->sh_offset;
2187 ph->p_vaddr = interp->sh_addr;
2188 ph->p_paddr = ph->p_vaddr;
2189 ph->p_filesz = interp->sh_size;
2190 ph->p_memsz = interp->sh_size;
2191 ph->p_flags = PF_R;
2192 ph->p_align = interp->sh_addralign;
2195 /* if dynamic section, then add corresponding program header */
2196 if (dynamic) {
2197 ph = &phdr[phnum - 1];
2199 ph->p_type = PT_DYNAMIC;
2200 ph->p_offset = dynamic->sh_offset;
2201 ph->p_vaddr = dynamic->sh_addr;
2202 ph->p_paddr = ph->p_vaddr;
2203 ph->p_filesz = dynamic->sh_size;
2204 ph->p_memsz = dynamic->sh_size;
2205 ph->p_flags = PF_R | PF_W;
2206 ph->p_align = dynamic->sh_addralign;
2210 /* Fill the dynamic section with tags describing the address and size of
2211 sections */
2212 static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
2214 Section *dynamic;
2216 dynamic = dyninf->dynamic;
2218 /* put dynamic section entries */
2219 dynamic->data_offset = dyninf->dyn_rel_off;
2220 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
2221 put_dt(dynamic, DT_STRTAB, dyninf->dynstr->sh_addr);
2222 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2223 put_dt(dynamic, DT_STRSZ, dyninf->dynstr->data_offset);
2224 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2225 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
2226 put_dt(dynamic, DT_RELA, dyninf->rel_addr);
2227 put_dt(dynamic, DT_RELASZ, dyninf->rel_size);
2228 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2229 #else
2230 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2231 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2232 put_dt(dynamic, DT_PLTRELSZ, dyninf->rel_size);
2233 put_dt(dynamic, DT_JMPREL, dyninf->rel_addr);
2234 put_dt(dynamic, DT_PLTREL, DT_REL);
2235 put_dt(dynamic, DT_REL, dyninf->bss_addr);
2236 put_dt(dynamic, DT_RELSZ, dyninf->bss_size);
2237 #else
2238 put_dt(dynamic, DT_REL, dyninf->rel_addr);
2239 put_dt(dynamic, DT_RELSZ, dyninf->rel_size);
2240 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2241 #endif
2242 #endif
2243 if (s1->do_debug)
2244 put_dt(dynamic, DT_DEBUG, 0);
2245 put_dt(dynamic, DT_NULL, 0);
2248 /* Relocate remaining sections and symbols (that is those not related to
2249 dynamic linking) */
2250 static int final_sections_reloc(TCCState *s1)
2252 int i;
2253 Section *s;
2255 relocate_syms(s1, 0);
2257 if (s1->nb_errors != 0)
2258 return -1;
2260 /* relocate sections */
2261 /* XXX: ignore sections with allocated relocations ? */
2262 for(i = 1; i < s1->nb_sections; i++) {
2263 s = s1->sections[i];
2264 if (s->reloc && s != s1->got)
2265 relocate_section(s1, s);
2268 /* relocate relocation entries if the relocation tables are
2269 allocated in the executable */
2270 for(i = 1; i < s1->nb_sections; i++) {
2271 s = s1->sections[i];
2272 if ((s->sh_flags & SHF_ALLOC) &&
2273 s->sh_type == SHT_RELX) {
2274 relocate_rel(s1, s);
2277 return 0;
2280 /* Create an ELF file on disk.
2281 This function handle ELF specific layout requirements */
2282 static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
2283 int file_offset, int *sec_order)
2285 int i, shnum, offset, size, file_type;
2286 Section *s;
2287 ElfW(Ehdr) ehdr;
2288 ElfW(Shdr) shdr, *sh;
2290 file_type = s1->output_type;
2291 shnum = s1->nb_sections;
2293 memset(&ehdr, 0, sizeof(ehdr));
2295 if (phnum > 0) {
2296 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2297 ehdr.e_phnum = phnum;
2298 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2301 /* align to 4 */
2302 file_offset = (file_offset + 3) & -4;
2304 /* fill header */
2305 ehdr.e_ident[0] = ELFMAG0;
2306 ehdr.e_ident[1] = ELFMAG1;
2307 ehdr.e_ident[2] = ELFMAG2;
2308 ehdr.e_ident[3] = ELFMAG3;
2309 ehdr.e_ident[4] = ELFCLASSW;
2310 ehdr.e_ident[5] = ELFDATA2LSB;
2311 ehdr.e_ident[6] = EV_CURRENT;
2312 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2313 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2314 #endif
2315 #ifdef TCC_TARGET_ARM
2316 #ifdef TCC_ARM_EABI
2317 ehdr.e_ident[EI_OSABI] = 0;
2318 ehdr.e_flags = EF_ARM_EABI_VER4;
2319 if (file_type == TCC_OUTPUT_EXE || file_type == TCC_OUTPUT_DLL)
2320 ehdr.e_flags |= EF_ARM_HASENTRY;
2321 if (s1->float_abi == ARM_HARD_FLOAT)
2322 ehdr.e_flags |= EF_ARM_VFP_FLOAT;
2323 else
2324 ehdr.e_flags |= EF_ARM_SOFT_FLOAT;
2325 #else
2326 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2327 #endif
2328 #endif
2329 switch(file_type) {
2330 default:
2331 case TCC_OUTPUT_EXE:
2332 ehdr.e_type = ET_EXEC;
2333 ehdr.e_entry = get_elf_sym_addr(s1, "_start", 1);
2334 break;
2335 case TCC_OUTPUT_DLL:
2336 ehdr.e_type = ET_DYN;
2337 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2338 break;
2339 case TCC_OUTPUT_OBJ:
2340 ehdr.e_type = ET_REL;
2341 break;
2343 ehdr.e_machine = EM_TCC_TARGET;
2344 ehdr.e_version = EV_CURRENT;
2345 ehdr.e_shoff = file_offset;
2346 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2347 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2348 ehdr.e_shnum = shnum;
2349 ehdr.e_shstrndx = shnum - 1;
2351 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2352 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2353 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2355 sort_syms(s1, symtab_section);
2356 for(i = 1; i < s1->nb_sections; i++) {
2357 s = s1->sections[sec_order[i]];
2358 if (s->sh_type != SHT_NOBITS) {
2359 if (s->sh_type == SHT_DYNSYM)
2360 patch_dynsym_undef(s1, s);
2361 while (offset < s->sh_offset) {
2362 fputc(0, f);
2363 offset++;
2365 size = s->sh_size;
2366 fwrite(s->data, 1, size, f);
2367 offset += size;
2371 /* output section headers */
2372 while (offset < ehdr.e_shoff) {
2373 fputc(0, f);
2374 offset++;
2377 for(i = 0; i < s1->nb_sections; i++) {
2378 sh = &shdr;
2379 memset(sh, 0, sizeof(ElfW(Shdr)));
2380 s = s1->sections[i];
2381 if (s) {
2382 sh->sh_name = s->sh_name;
2383 sh->sh_type = s->sh_type;
2384 sh->sh_flags = s->sh_flags;
2385 sh->sh_entsize = s->sh_entsize;
2386 sh->sh_info = s->sh_info;
2387 if (s->link)
2388 sh->sh_link = s->link->sh_num;
2389 sh->sh_addralign = s->sh_addralign;
2390 sh->sh_addr = s->sh_addr;
2391 sh->sh_offset = s->sh_offset;
2392 sh->sh_size = s->sh_size;
2394 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2398 /* Write an elf, coff or "binary" file */
2399 static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum,
2400 ElfW(Phdr) *phdr, int file_offset, int *sec_order)
2402 int fd, mode, file_type;
2403 FILE *f;
2405 file_type = s1->output_type;
2406 if (file_type == TCC_OUTPUT_OBJ)
2407 mode = 0666;
2408 else
2409 mode = 0777;
2410 unlink(filename);
2411 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2412 if (fd < 0) {
2413 tcc_error_noabort("could not write '%s'", filename);
2414 return -1;
2416 f = fdopen(fd, "wb");
2417 if (s1->verbose)
2418 printf("<- %s\n", filename);
2420 #ifdef TCC_TARGET_COFF
2421 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF)
2422 tcc_output_coff(s1, f);
2423 else
2424 #endif
2425 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
2426 tcc_output_elf(s1, f, phnum, phdr, file_offset, sec_order);
2427 else
2428 tcc_output_binary(s1, f, sec_order);
2429 fclose(f);
2431 return 0;
2434 /* Output an elf, coff or binary file */
2435 /* XXX: suppress unneeded sections */
2436 static int elf_output_file(TCCState *s1, const char *filename)
2438 int i, ret, phnum, shnum, file_type, file_offset, *sec_order;
2439 struct dyn_inf dyninf;
2440 ElfW(Phdr) *phdr;
2441 ElfW(Sym) *sym;
2442 Section *strsec, *interp, *dynamic, *dynstr;
2444 file_type = s1->output_type;
2445 s1->nb_errors = 0;
2447 /* if linking, also link in runtime libraries (libc, libgcc, etc.) */
2448 if (file_type != TCC_OUTPUT_OBJ) {
2449 tcc_add_runtime(s1);
2452 phdr = NULL;
2453 sec_order = NULL;
2454 interp = dynamic = dynstr = NULL; /* avoid warning */
2455 dyninf.dyn_rel_off = 0; /* avoid warning */
2457 if (file_type != TCC_OUTPUT_OBJ) {
2458 relocate_common_syms();
2460 tcc_add_linker_symbols(s1);
2462 if (!s1->static_link) {
2463 if (file_type == TCC_OUTPUT_EXE) {
2464 char *ptr;
2465 /* allow override the dynamic loader */
2466 const char *elfint = getenv("LD_SO");
2467 if (elfint == NULL)
2468 elfint = DEFAULT_ELFINTERP(s1);
2469 /* add interpreter section only if executable */
2470 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
2471 interp->sh_addralign = 1;
2472 ptr = section_ptr_add(interp, 1 + strlen(elfint));
2473 strcpy(ptr, elfint);
2476 /* add dynamic symbol table */
2477 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
2478 ".dynstr",
2479 ".hash", SHF_ALLOC);
2480 dynstr = s1->dynsym->link;
2482 /* add dynamic section */
2483 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
2484 SHF_ALLOC | SHF_WRITE);
2485 dynamic->link = dynstr;
2486 dynamic->sh_entsize = sizeof(ElfW(Dyn));
2488 build_got(s1);
2490 if (file_type == TCC_OUTPUT_EXE) {
2491 bind_exe_dynsyms(s1);
2493 if (s1->nb_errors) {
2494 ret = -1;
2495 goto the_end;
2498 bind_libs_dynsyms(s1);
2499 } else /* shared library case: simply export all global symbols */
2500 export_global_syms(s1);
2502 build_got_entries(s1);
2504 /* add a list of needed dlls */
2505 for(i = 0; i < s1->nb_loaded_dlls; i++) {
2506 DLLReference *dllref = s1->loaded_dlls[i];
2507 if (dllref->level == 0)
2508 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
2511 if (s1->rpath)
2512 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
2514 /* XXX: currently, since we do not handle PIC code, we
2515 must relocate the readonly segments */
2516 if (file_type == TCC_OUTPUT_DLL) {
2517 if (s1->soname)
2518 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
2519 put_dt(dynamic, DT_TEXTREL, 0);
2522 if (s1->symbolic)
2523 put_dt(dynamic, DT_SYMBOLIC, 0);
2525 /* add necessary space for other entries */
2526 dyninf.dyn_rel_off = dynamic->data_offset;
2527 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
2528 } else {
2529 /* still need to build got entries in case of static link */
2530 build_got_entries(s1);
2534 /* we add a section for symbols */
2535 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
2536 put_elf_str(strsec, "");
2538 /* compute number of sections */
2539 shnum = s1->nb_sections;
2541 /* this array is used to reorder sections in the output file */
2542 sec_order = tcc_malloc(sizeof(int) * shnum);
2543 sec_order[0] = 0;
2545 /* compute number of program headers */
2546 switch(file_type) {
2547 default:
2548 case TCC_OUTPUT_OBJ:
2549 phnum = 0;
2550 break;
2551 case TCC_OUTPUT_EXE:
2552 if (!s1->static_link)
2553 phnum = 4 + HAVE_PHDR;
2554 else
2555 phnum = 2;
2556 break;
2557 case TCC_OUTPUT_DLL:
2558 phnum = 3;
2559 break;
2562 /* Allocate strings for section names */
2563 alloc_sec_names(s1, file_type, strsec);
2565 /* allocate program segment headers */
2566 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
2568 /* compute section to program header mapping */
2569 file_offset = layout_sections(s1, phdr, phnum, interp, strsec, &dyninf,
2570 sec_order);
2572 /* Fill remaining program header and finalize relocation related to dynamic
2573 linking. */
2574 if (phnum > 0) {
2575 fill_unloadable_phdr(phdr, phnum, interp, dynamic);
2576 if (dynamic) {
2577 dyninf.dynamic = dynamic;
2578 dyninf.dynstr = dynstr;
2580 fill_dynamic(s1, &dyninf);
2582 /* put in GOT the dynamic section address and relocate PLT */
2583 put32(s1->got->data, dynamic->sh_addr);
2584 if (file_type == TCC_OUTPUT_EXE
2585 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2586 || file_type == TCC_OUTPUT_DLL
2587 #endif
2589 relocate_plt(s1);
2591 /* relocate symbols in .dynsym now that final addresses are known */
2592 for_each_elem(s1->dynsym, 1, sym, ElfW(Sym)) {
2593 /* relocate to PLT if symbol corresponds to a PLT entry */
2594 if (sym->st_shndx == SHN_UNDEF) {
2595 if (sym->st_value)
2596 sym->st_value += s1->plt->sh_addr;
2597 } else if (sym->st_shndx < SHN_LORESERVE) {
2598 /* do symbol relocation */
2599 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
2605 /* if building executable or DLL, then relocate each section
2606 except the GOT which is already relocated */
2607 if (file_type != TCC_OUTPUT_OBJ) {
2608 ret = final_sections_reloc(s1);
2609 if (ret)
2610 goto the_end;
2613 /* Perform relocation to GOT or PLT entries */
2614 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2615 fill_got(s1);
2617 /* Create the ELF file with name 'filename' */
2618 ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order);
2619 the_end:
2620 tcc_free(s1->symtab_to_dynsym);
2621 tcc_free(sec_order);
2622 tcc_free(phdr);
2623 tcc_free(s1->sym_attrs);
2624 s1->sym_attrs = NULL;
2625 return ret;
2628 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2630 int ret;
2631 #ifdef TCC_TARGET_PE
2632 if (s->output_type != TCC_OUTPUT_OBJ) {
2633 ret = pe_output_file(s, filename);
2634 } else
2635 #endif
2636 ret = elf_output_file(s, filename);
2637 return ret;
2640 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2642 void *data;
2644 data = tcc_malloc(size);
2645 lseek(fd, file_offset, SEEK_SET);
2646 read(fd, data, size);
2647 return data;
2650 typedef struct SectionMergeInfo {
2651 Section *s; /* corresponding existing section */
2652 unsigned long offset; /* offset of the new section in the existing section */
2653 uint8_t new_section; /* true if section 's' was added */
2654 uint8_t link_once; /* true if link once section */
2655 } SectionMergeInfo;
2657 /* load an object file and merge it with current files */
2658 /* XXX: handle correctly stab (debug) info */
2659 ST_FUNC int tcc_load_object_file(TCCState *s1,
2660 int fd, unsigned long file_offset)
2662 ElfW(Ehdr) ehdr;
2663 ElfW(Shdr) *shdr, *sh;
2664 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2665 unsigned char *strsec, *strtab;
2666 int *old_to_new_syms;
2667 char *sh_name, *name;
2668 SectionMergeInfo *sm_table, *sm;
2669 ElfW(Sym) *sym, *symtab;
2670 ElfW_Rel *rel;
2671 Section *s;
2673 int stab_index;
2674 int stabstr_index;
2676 stab_index = stabstr_index = 0;
2678 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2679 goto fail1;
2680 if (ehdr.e_ident[0] != ELFMAG0 ||
2681 ehdr.e_ident[1] != ELFMAG1 ||
2682 ehdr.e_ident[2] != ELFMAG2 ||
2683 ehdr.e_ident[3] != ELFMAG3)
2684 goto fail1;
2685 /* test if object file */
2686 if (ehdr.e_type != ET_REL)
2687 goto fail1;
2688 /* test CPU specific stuff */
2689 if (ehdr.e_ident[5] != ELFDATA2LSB ||
2690 ehdr.e_machine != EM_TCC_TARGET) {
2691 fail1:
2692 tcc_error_noabort("invalid object file");
2693 return -1;
2695 /* read sections */
2696 shdr = load_data(fd, file_offset + ehdr.e_shoff,
2697 sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2698 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2700 /* load section names */
2701 sh = &shdr[ehdr.e_shstrndx];
2702 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2704 /* load symtab and strtab */
2705 old_to_new_syms = NULL;
2706 symtab = NULL;
2707 strtab = NULL;
2708 nb_syms = 0;
2709 for(i = 1; i < ehdr.e_shnum; i++) {
2710 sh = &shdr[i];
2711 if (sh->sh_type == SHT_SYMTAB) {
2712 if (symtab) {
2713 tcc_error_noabort("object must contain only one symtab");
2714 fail:
2715 ret = -1;
2716 goto the_end;
2718 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2719 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2720 sm_table[i].s = symtab_section;
2722 /* now load strtab */
2723 sh = &shdr[sh->sh_link];
2724 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2728 /* now examine each section and try to merge its content with the
2729 ones in memory */
2730 for(i = 1; i < ehdr.e_shnum; i++) {
2731 /* no need to examine section name strtab */
2732 if (i == ehdr.e_shstrndx)
2733 continue;
2734 sh = &shdr[i];
2735 sh_name = (char *) strsec + sh->sh_name;
2736 /* ignore sections types we do not handle */
2737 if (sh->sh_type != SHT_PROGBITS &&
2738 sh->sh_type != SHT_RELX &&
2739 #ifdef TCC_ARM_EABI
2740 sh->sh_type != SHT_ARM_EXIDX &&
2741 #endif
2742 sh->sh_type != SHT_NOBITS &&
2743 sh->sh_type != SHT_PREINIT_ARRAY &&
2744 sh->sh_type != SHT_INIT_ARRAY &&
2745 sh->sh_type != SHT_FINI_ARRAY &&
2746 strcmp(sh_name, ".stabstr")
2748 continue;
2749 if (sh->sh_addralign < 1)
2750 sh->sh_addralign = 1;
2751 /* find corresponding section, if any */
2752 for(j = 1; j < s1->nb_sections;j++) {
2753 s = s1->sections[j];
2754 if (!strcmp(s->name, sh_name)) {
2755 if (!strncmp(sh_name, ".gnu.linkonce",
2756 sizeof(".gnu.linkonce") - 1)) {
2757 /* if a 'linkonce' section is already present, we
2758 do not add it again. It is a little tricky as
2759 symbols can still be defined in
2760 it. */
2761 sm_table[i].link_once = 1;
2762 goto next;
2763 } else {
2764 goto found;
2768 /* not found: create new section */
2769 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2770 /* take as much info as possible from the section. sh_link and
2771 sh_info will be updated later */
2772 s->sh_addralign = sh->sh_addralign;
2773 s->sh_entsize = sh->sh_entsize;
2774 sm_table[i].new_section = 1;
2775 found:
2776 if (sh->sh_type != s->sh_type) {
2777 tcc_error_noabort("invalid section type");
2778 goto fail;
2781 /* align start of section */
2782 offset = s->data_offset;
2784 if (0 == strcmp(sh_name, ".stab")) {
2785 stab_index = i;
2786 goto no_align;
2788 if (0 == strcmp(sh_name, ".stabstr")) {
2789 stabstr_index = i;
2790 goto no_align;
2793 size = sh->sh_addralign - 1;
2794 offset = (offset + size) & ~size;
2795 if (sh->sh_addralign > s->sh_addralign)
2796 s->sh_addralign = sh->sh_addralign;
2797 s->data_offset = offset;
2798 no_align:
2799 sm_table[i].offset = offset;
2800 sm_table[i].s = s;
2801 /* concatenate sections */
2802 size = sh->sh_size;
2803 if (sh->sh_type != SHT_NOBITS) {
2804 unsigned char *ptr;
2805 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2806 ptr = section_ptr_add(s, size);
2807 read(fd, ptr, size);
2808 } else {
2809 s->data_offset += size;
2811 next: ;
2814 /* gr relocate stab strings */
2815 if (stab_index && stabstr_index) {
2816 Stab_Sym *a, *b;
2817 unsigned o;
2818 s = sm_table[stab_index].s;
2819 a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2820 b = (Stab_Sym *)(s->data + s->data_offset);
2821 o = sm_table[stabstr_index].offset;
2822 while (a < b)
2823 a->n_strx += o, a++;
2826 /* second short pass to update sh_link and sh_info fields of new
2827 sections */
2828 for(i = 1; i < ehdr.e_shnum; i++) {
2829 s = sm_table[i].s;
2830 if (!s || !sm_table[i].new_section)
2831 continue;
2832 sh = &shdr[i];
2833 if (sh->sh_link > 0)
2834 s->link = sm_table[sh->sh_link].s;
2835 if (sh->sh_type == SHT_RELX) {
2836 s->sh_info = sm_table[sh->sh_info].s->sh_num;
2837 /* update backward link */
2838 s1->sections[s->sh_info]->reloc = s;
2841 sm = sm_table;
2843 /* resolve symbols */
2844 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2846 sym = symtab + 1;
2847 for(i = 1; i < nb_syms; i++, sym++) {
2848 if (sym->st_shndx != SHN_UNDEF &&
2849 sym->st_shndx < SHN_LORESERVE) {
2850 sm = &sm_table[sym->st_shndx];
2851 if (sm->link_once) {
2852 /* if a symbol is in a link once section, we use the
2853 already defined symbol. It is very important to get
2854 correct relocations */
2855 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2856 name = (char *) strtab + sym->st_name;
2857 sym_index = find_elf_sym(symtab_section, name);
2858 if (sym_index)
2859 old_to_new_syms[i] = sym_index;
2861 continue;
2863 /* if no corresponding section added, no need to add symbol */
2864 if (!sm->s)
2865 continue;
2866 /* convert section number */
2867 sym->st_shndx = sm->s->sh_num;
2868 /* offset value */
2869 sym->st_value += sm->offset;
2871 /* add symbol */
2872 name = (char *) strtab + sym->st_name;
2873 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2874 sym->st_info, sym->st_other,
2875 sym->st_shndx, name);
2876 old_to_new_syms[i] = sym_index;
2879 /* third pass to patch relocation entries */
2880 for(i = 1; i < ehdr.e_shnum; i++) {
2881 s = sm_table[i].s;
2882 if (!s)
2883 continue;
2884 sh = &shdr[i];
2885 offset = sm_table[i].offset;
2886 switch(s->sh_type) {
2887 case SHT_RELX:
2888 /* take relocation offset information */
2889 offseti = sm_table[sh->sh_info].offset;
2890 for_each_elem(s, (offset / sizeof(*rel)), rel, ElfW_Rel) {
2891 int type;
2892 unsigned sym_index;
2893 /* convert symbol index */
2894 type = ELFW(R_TYPE)(rel->r_info);
2895 sym_index = ELFW(R_SYM)(rel->r_info);
2896 /* NOTE: only one symtab assumed */
2897 if (sym_index >= nb_syms)
2898 goto invalid_reloc;
2899 sym_index = old_to_new_syms[sym_index];
2900 /* ignore link_once in rel section. */
2901 if (!sym_index && !sm->link_once
2902 #ifdef TCC_TARGET_ARM
2903 && type != R_ARM_V4BX
2904 #endif
2906 invalid_reloc:
2907 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2908 i, strsec + sh->sh_name, rel->r_offset);
2909 goto fail;
2911 rel->r_info = ELFW(R_INFO)(sym_index, type);
2912 /* offset the relocation offset */
2913 rel->r_offset += offseti;
2914 #ifdef TCC_TARGET_ARM
2915 /* Jumps and branches from a Thumb code to a PLT entry need
2916 special handling since PLT entries are ARM code.
2917 Unconditional bl instructions referencing PLT entries are
2918 handled by converting these instructions into blx
2919 instructions. Other case of instructions referencing a PLT
2920 entry require to add a Thumb stub before the PLT entry to
2921 switch to ARM mode. We set bit plt_thumb_stub of the
2922 attribute of a symbol to indicate such a case. */
2923 if (type == R_ARM_THM_JUMP24)
2924 alloc_sym_attr(s1, sym_index)->plt_thumb_stub = 1;
2925 #endif
2927 break;
2928 default:
2929 break;
2933 ret = 0;
2934 the_end:
2935 tcc_free(symtab);
2936 tcc_free(strtab);
2937 tcc_free(old_to_new_syms);
2938 tcc_free(sm_table);
2939 tcc_free(strsec);
2940 tcc_free(shdr);
2941 return ret;
2944 typedef struct ArchiveHeader {
2945 char ar_name[16]; /* name of this member */
2946 char ar_date[12]; /* file mtime */
2947 char ar_uid[6]; /* owner uid; printed as decimal */
2948 char ar_gid[6]; /* owner gid; printed as decimal */
2949 char ar_mode[8]; /* file mode, printed as octal */
2950 char ar_size[10]; /* file size, printed as decimal */
2951 char ar_fmag[2]; /* should contain ARFMAG */
2952 } ArchiveHeader;
2954 static int get_be32(const uint8_t *b)
2956 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2959 /* load only the objects which resolve undefined symbols */
2960 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2962 int i, bound, nsyms, sym_index, off, ret;
2963 uint8_t *data;
2964 const char *ar_names, *p;
2965 const uint8_t *ar_index;
2966 ElfW(Sym) *sym;
2968 data = tcc_malloc(size);
2969 if (read(fd, data, size) != size)
2970 goto fail;
2971 nsyms = get_be32(data);
2972 ar_index = data + 4;
2973 ar_names = (char *) ar_index + nsyms * 4;
2975 do {
2976 bound = 0;
2977 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2978 sym_index = find_elf_sym(symtab_section, p);
2979 if(sym_index) {
2980 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2981 if(sym->st_shndx == SHN_UNDEF) {
2982 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2983 ++bound;
2984 lseek(fd, off, SEEK_SET);
2985 if(tcc_load_object_file(s1, fd, off) < 0) {
2986 fail:
2987 ret = -1;
2988 goto the_end;
2993 } while(bound);
2994 ret = 0;
2995 the_end:
2996 tcc_free(data);
2997 return ret;
3000 /* load a '.a' file */
3001 ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
3003 ArchiveHeader hdr;
3004 char ar_size[11];
3005 char ar_name[17];
3006 char magic[8];
3007 int size, len, i;
3008 unsigned long file_offset;
3010 /* skip magic which was already checked */
3011 read(fd, magic, sizeof(magic));
3013 for(;;) {
3014 len = read(fd, &hdr, sizeof(hdr));
3015 if (len == 0)
3016 break;
3017 if (len != sizeof(hdr)) {
3018 tcc_error_noabort("invalid archive");
3019 return -1;
3021 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
3022 ar_size[sizeof(hdr.ar_size)] = '\0';
3023 size = strtol(ar_size, NULL, 0);
3024 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
3025 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
3026 if (ar_name[i] != ' ')
3027 break;
3029 ar_name[i + 1] = '\0';
3030 file_offset = lseek(fd, 0, SEEK_CUR);
3031 /* align to even */
3032 size = (size + 1) & ~1;
3033 if (!strcmp(ar_name, "/")) {
3034 /* coff symbol table : we handle it */
3035 if(s1->alacarte_link)
3036 return tcc_load_alacarte(s1, fd, size);
3037 } else if (!strcmp(ar_name, "//") ||
3038 !strcmp(ar_name, "__.SYMDEF") ||
3039 !strcmp(ar_name, "__.SYMDEF/") ||
3040 !strcmp(ar_name, "ARFILENAMES/")) {
3041 /* skip symbol table or archive names */
3042 } else {
3043 if (tcc_load_object_file(s1, fd, file_offset) < 0)
3044 return -1;
3046 lseek(fd, file_offset + size, SEEK_SET);
3048 return 0;
3051 #ifndef TCC_TARGET_PE
3052 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
3053 is referenced by the user (so it should be added as DT_NEEDED in
3054 the generated ELF file) */
3055 ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
3057 ElfW(Ehdr) ehdr;
3058 ElfW(Shdr) *shdr, *sh, *sh1;
3059 int i, j, nb_syms, nb_dts, sym_bind, ret;
3060 ElfW(Sym) *sym, *dynsym;
3061 ElfW(Dyn) *dt, *dynamic;
3062 unsigned char *dynstr;
3063 const char *name, *soname;
3064 DLLReference *dllref;
3066 read(fd, &ehdr, sizeof(ehdr));
3068 /* test CPU specific stuff */
3069 if (ehdr.e_ident[5] != ELFDATA2LSB ||
3070 ehdr.e_machine != EM_TCC_TARGET) {
3071 tcc_error_noabort("bad architecture");
3072 return -1;
3075 /* read sections */
3076 shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
3078 /* load dynamic section and dynamic symbols */
3079 nb_syms = 0;
3080 nb_dts = 0;
3081 dynamic = NULL;
3082 dynsym = NULL; /* avoid warning */
3083 dynstr = NULL; /* avoid warning */
3084 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
3085 switch(sh->sh_type) {
3086 case SHT_DYNAMIC:
3087 nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
3088 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
3089 break;
3090 case SHT_DYNSYM:
3091 nb_syms = sh->sh_size / sizeof(ElfW(Sym));
3092 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
3093 sh1 = &shdr[sh->sh_link];
3094 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
3095 break;
3096 default:
3097 break;
3101 /* compute the real library name */
3102 soname = tcc_basename(filename);
3104 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
3105 if (dt->d_tag == DT_SONAME) {
3106 soname = (char *) dynstr + dt->d_un.d_val;
3110 /* if the dll is already loaded, do not load it */
3111 for(i = 0; i < s1->nb_loaded_dlls; i++) {
3112 dllref = s1->loaded_dlls[i];
3113 if (!strcmp(soname, dllref->name)) {
3114 /* but update level if needed */
3115 if (level < dllref->level)
3116 dllref->level = level;
3117 ret = 0;
3118 goto the_end;
3122 /* add the dll and its level */
3123 dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
3124 dllref->level = level;
3125 strcpy(dllref->name, soname);
3126 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
3128 /* add dynamic symbols in dynsym_section */
3129 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
3130 sym_bind = ELFW(ST_BIND)(sym->st_info);
3131 if (sym_bind == STB_LOCAL)
3132 continue;
3133 name = (char *) dynstr + sym->st_name;
3134 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
3135 sym->st_info, sym->st_other, sym->st_shndx, name);
3138 /* load all referenced DLLs */
3139 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
3140 switch(dt->d_tag) {
3141 case DT_NEEDED:
3142 name = (char *) dynstr + dt->d_un.d_val;
3143 for(j = 0; j < s1->nb_loaded_dlls; j++) {
3144 dllref = s1->loaded_dlls[j];
3145 if (!strcmp(name, dllref->name))
3146 goto already_loaded;
3148 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
3149 tcc_error_noabort("referenced dll '%s' not found", name);
3150 ret = -1;
3151 goto the_end;
3153 already_loaded:
3154 break;
3157 ret = 0;
3158 the_end:
3159 tcc_free(dynstr);
3160 tcc_free(dynsym);
3161 tcc_free(dynamic);
3162 tcc_free(shdr);
3163 return ret;
3166 #define LD_TOK_NAME 256
3167 #define LD_TOK_EOF (-1)
3169 /* return next ld script token */
3170 static int ld_next(TCCState *s1, char *name, int name_size)
3172 int c;
3173 char *q;
3175 redo:
3176 switch(ch) {
3177 case ' ':
3178 case '\t':
3179 case '\f':
3180 case '\v':
3181 case '\r':
3182 case '\n':
3183 inp();
3184 goto redo;
3185 case '/':
3186 minp();
3187 if (ch == '*') {
3188 file->buf_ptr = parse_comment(file->buf_ptr);
3189 ch = file->buf_ptr[0];
3190 goto redo;
3191 } else {
3192 q = name;
3193 *q++ = '/';
3194 goto parse_name;
3196 break;
3197 /* case 'a' ... 'z': */
3198 case 'a':
3199 case 'b':
3200 case 'c':
3201 case 'd':
3202 case 'e':
3203 case 'f':
3204 case 'g':
3205 case 'h':
3206 case 'i':
3207 case 'j':
3208 case 'k':
3209 case 'l':
3210 case 'm':
3211 case 'n':
3212 case 'o':
3213 case 'p':
3214 case 'q':
3215 case 'r':
3216 case 's':
3217 case 't':
3218 case 'u':
3219 case 'v':
3220 case 'w':
3221 case 'x':
3222 case 'y':
3223 case 'z':
3224 /* case 'A' ... 'z': */
3225 case 'A':
3226 case 'B':
3227 case 'C':
3228 case 'D':
3229 case 'E':
3230 case 'F':
3231 case 'G':
3232 case 'H':
3233 case 'I':
3234 case 'J':
3235 case 'K':
3236 case 'L':
3237 case 'M':
3238 case 'N':
3239 case 'O':
3240 case 'P':
3241 case 'Q':
3242 case 'R':
3243 case 'S':
3244 case 'T':
3245 case 'U':
3246 case 'V':
3247 case 'W':
3248 case 'X':
3249 case 'Y':
3250 case 'Z':
3251 case '_':
3252 case '\\':
3253 case '.':
3254 case '$':
3255 case '~':
3256 q = name;
3257 parse_name:
3258 for(;;) {
3259 if (!((ch >= 'a' && ch <= 'z') ||
3260 (ch >= 'A' && ch <= 'Z') ||
3261 (ch >= '0' && ch <= '9') ||
3262 strchr("/.-_+=$:\\,~", ch)))
3263 break;
3264 if ((q - name) < name_size - 1) {
3265 *q++ = ch;
3267 minp();
3269 *q = '\0';
3270 c = LD_TOK_NAME;
3271 break;
3272 case CH_EOF:
3273 c = LD_TOK_EOF;
3274 break;
3275 default:
3276 c = ch;
3277 inp();
3278 break;
3280 return c;
3283 static int ld_add_file(TCCState *s1, const char filename[])
3285 int ret;
3287 ret = tcc_add_file_internal(s1, filename, 0);
3288 if (ret)
3289 ret = tcc_add_dll(s1, filename, 0);
3290 return ret;
3293 static inline int new_undef_syms(void)
3295 int ret = 0;
3296 ret = new_undef_sym;
3297 new_undef_sym = 0;
3298 return ret;
3301 static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
3303 char filename[1024], libname[1024];
3304 int t, group, nblibs = 0, ret = 0;
3305 char **libs = NULL;
3307 group = !strcmp(cmd, "GROUP");
3308 if (!as_needed)
3309 new_undef_syms();
3310 t = ld_next(s1, filename, sizeof(filename));
3311 if (t != '(')
3312 expect("(");
3313 t = ld_next(s1, filename, sizeof(filename));
3314 for(;;) {
3315 libname[0] = '\0';
3316 if (t == LD_TOK_EOF) {
3317 tcc_error_noabort("unexpected end of file");
3318 ret = -1;
3319 goto lib_parse_error;
3320 } else if (t == ')') {
3321 break;
3322 } else if (t == '-') {
3323 t = ld_next(s1, filename, sizeof(filename));
3324 if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
3325 tcc_error_noabort("library name expected");
3326 ret = -1;
3327 goto lib_parse_error;
3329 pstrcpy(libname, sizeof libname, &filename[1]);
3330 if (s1->static_link) {
3331 snprintf(filename, sizeof filename, "lib%s.a", libname);
3332 } else {
3333 snprintf(filename, sizeof filename, "lib%s.so", libname);
3335 } else if (t != LD_TOK_NAME) {
3336 tcc_error_noabort("filename expected");
3337 ret = -1;
3338 goto lib_parse_error;
3340 if (!strcmp(filename, "AS_NEEDED")) {
3341 ret = ld_add_file_list(s1, cmd, 1);
3342 if (ret)
3343 goto lib_parse_error;
3344 } else {
3345 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3346 if (!as_needed) {
3347 ret = ld_add_file(s1, filename);
3348 if (ret)
3349 goto lib_parse_error;
3350 if (group) {
3351 /* Add the filename *and* the libname to avoid future conversions */
3352 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
3353 if (libname[0] != '\0')
3354 dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
3358 t = ld_next(s1, filename, sizeof(filename));
3359 if (t == ',') {
3360 t = ld_next(s1, filename, sizeof(filename));
3363 if (group && !as_needed) {
3364 while (new_undef_syms()) {
3365 int i;
3367 for (i = 0; i < nblibs; i ++)
3368 ld_add_file(s1, libs[i]);
3371 lib_parse_error:
3372 dynarray_reset(&libs, &nblibs);
3373 return ret;
3376 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3377 files */
3378 ST_FUNC int tcc_load_ldscript(TCCState *s1)
3380 char cmd[64];
3381 char filename[1024];
3382 int t, ret;
3384 ch = file->buf_ptr[0];
3385 ch = handle_eob();
3386 for(;;) {
3387 t = ld_next(s1, cmd, sizeof(cmd));
3388 if (t == LD_TOK_EOF)
3389 return 0;
3390 else if (t != LD_TOK_NAME)
3391 return -1;
3392 if (!strcmp(cmd, "INPUT") ||
3393 !strcmp(cmd, "GROUP")) {
3394 ret = ld_add_file_list(s1, cmd, 0);
3395 if (ret)
3396 return ret;
3397 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3398 !strcmp(cmd, "TARGET")) {
3399 /* ignore some commands */
3400 t = ld_next(s1, cmd, sizeof(cmd));
3401 if (t != '(')
3402 expect("(");
3403 for(;;) {
3404 t = ld_next(s1, filename, sizeof(filename));
3405 if (t == LD_TOK_EOF) {
3406 tcc_error_noabort("unexpected end of file");
3407 return -1;
3408 } else if (t == ')') {
3409 break;
3412 } else {
3413 return -1;
3416 return 0;
3418 #endif /* !TCC_TARGET_PE */