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
23 /* Define this to get some debug output during relocation processing. */
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
)
34 len
= strlen(sym
) + 1;
35 offset
= s
->data_offset
;
36 ptr
= section_ptr_add(s
, len
);
37 memcpy(ptr
, sym
, len
);
41 /* elf symbol hashing function */
42 static unsigned long elf_hash(const unsigned char *name
)
44 unsigned long h
= 0, g
;
47 h
= (h
<< 4) + *name
++;
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
)
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));
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
;
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
;
99 sym
= section_ptr_add(s
, sizeof(ElfW(Sym
)));
101 name_offset
= put_elf_str(s
->link
, name
);
104 /* XXX: endianness */
105 sym
->st_name
= name_offset
;
106 sym
->st_value
= value
;
109 sym
->st_other
= other
;
110 sym
->st_shndx
= shndx
;
111 sym_index
= sym
- (ElfW(Sym
) *)s
->data
;
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 */
121 h
= elf_hash((unsigned char *) name
) % nbuckets
;
123 base
[2 + h
] = sym_index
;
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
);
138 /* find global ELF symbol 'name' and return its index. Return 0 if not
140 ST_FUNC
int find_elf_sym(Section
*s
, const char *name
)
144 int nbuckets
, sym_index
, h
;
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
))
158 sym_index
= ((int *)hs
->data
)[2 + nbuckets
+ sym_index
];
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
)
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
) {
173 tcc_error("%s not defined", name
);
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);
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
)
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
);
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
) {
219 } else if (sym_vis
== STV_DEFAULT
) {
222 new_vis
= (esym_vis
< sym_vis
) ? esym_vis
: sym_vis
;
224 esym
->st_other
= (esym
->st_other
& ~ELFW(ST_VISIBILITY
)(-1))
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 */
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 || esym
->st_shndx
== bss_section
->sh_num
)
241 && (sh_num
< SHN_LORESERVE
242 && sh_num
!= bss_section
->sh_num
)) {
243 /* data symbol gets precedence over common/bss */
245 } else if (sh_num
== SHN_COMMON
|| sh_num
== bss_section
->sh_num
) {
246 /* data symbol keeps precedence over common/bss */
247 } else if (s
== tcc_state
->dynsymtab_section
) {
248 /* we accept that two DLL define the same symbol */
251 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
252 sym_bind
, sh_num
, new_vis
, esym_bind
, esym
->st_shndx
, esym_vis
);
254 tcc_error_noabort("'%s' defined twice", name
);
258 esym
->st_info
= ELFW(ST_INFO
)(sym_bind
, sym_type
);
259 esym
->st_shndx
= sh_num
;
261 esym
->st_value
= value
;
262 esym
->st_size
= size
;
263 esym
->st_other
= other
;
267 sym_index
= put_elf_sym(s
, value
, size
,
268 ELFW(ST_INFO
)(sym_bind
, sym_type
), other
,
275 ST_FUNC
void put_elf_reloca(Section
*symtab
, Section
*s
, unsigned long offset
,
276 int type
, int symbol
, addr_t addend
)
284 /* if no relocation section, create it */
285 snprintf(buf
, sizeof(buf
), REL_SECTION_FMT
, s
->name
);
286 /* if the symtab is allocated, then we consider the relocation
288 sr
= new_section(tcc_state
, buf
, SHT_RELX
, symtab
->sh_flags
);
289 sr
->sh_entsize
= sizeof(ElfW_Rel
);
291 sr
->sh_info
= s
->sh_num
;
294 rel
= section_ptr_add(sr
, sizeof(ElfW_Rel
));
295 rel
->r_offset
= offset
;
296 rel
->r_info
= ELFW(R_INFO
)(symbol
, type
);
297 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
298 rel
->r_addend
= addend
;
301 tcc_error("non-zero addend on REL architecture");
305 ST_FUNC
void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
306 int type
, int symbol
)
308 put_elf_reloca(symtab
, s
, offset
, type
, symbol
, 0);
311 /* put stab debug information */
313 ST_FUNC
void put_stabs(const char *str
, int type
, int other
, int desc
,
318 sym
= section_ptr_add(stab_section
, sizeof(Stab_Sym
));
320 sym
->n_strx
= put_elf_str(stabstr_section
, str
);
325 sym
->n_other
= other
;
327 sym
->n_value
= value
;
330 ST_FUNC
void put_stabs_r(const char *str
, int type
, int other
, int desc
,
331 unsigned long value
, Section
*sec
, int sym_index
)
333 put_stabs(str
, type
, other
, desc
, value
);
334 put_elf_reloc(symtab_section
, stab_section
,
335 stab_section
->data_offset
- sizeof(unsigned int),
336 R_DATA_32
, sym_index
);
339 ST_FUNC
void put_stabn(int type
, int other
, int desc
, int value
)
341 put_stabs(NULL
, type
, other
, desc
, value
);
344 ST_FUNC
void put_stabd(int type
, int other
, int desc
)
346 put_stabs(NULL
, type
, other
, desc
, 0);
349 /* Browse each elem of type <type> in section <sec> starting at elem <startoff>
350 using variable <elem> */
351 #define for_each_elem(sec, startoff, elem, type) \
352 for (elem = (type *) sec->data + startoff; \
353 elem < (type *) (sec->data + sec->data_offset); elem++)
355 /* In an ELF file symbol table, the local symbols must appear below
356 the global and weak ones. Since TCC cannot sort it while generating
357 the code, we must do it after. All the relocation tables are also
358 modified to take into account the symbol table sorting */
359 static void sort_syms(TCCState
*s1
, Section
*s
)
361 int *old_to_new_syms
;
369 nb_syms
= s
->data_offset
/ sizeof(ElfW(Sym
));
370 new_syms
= tcc_malloc(nb_syms
* sizeof(ElfW(Sym
)));
371 old_to_new_syms
= tcc_malloc(nb_syms
* sizeof(int));
373 /* first pass for local symbols */
374 p
= (ElfW(Sym
) *)s
->data
;
376 for(i
= 0; i
< nb_syms
; i
++) {
377 if (ELFW(ST_BIND
)(p
->st_info
) == STB_LOCAL
) {
378 old_to_new_syms
[i
] = q
- new_syms
;
383 /* save the number of local symbols in section header */
384 s
->sh_info
= q
- new_syms
;
386 /* then second pass for non local symbols */
387 p
= (ElfW(Sym
) *)s
->data
;
388 for(i
= 0; i
< nb_syms
; i
++) {
389 if (ELFW(ST_BIND
)(p
->st_info
) != STB_LOCAL
) {
390 old_to_new_syms
[i
] = q
- new_syms
;
396 /* we copy the new symbols to the old */
397 memcpy(s
->data
, new_syms
, nb_syms
* sizeof(ElfW(Sym
)));
400 /* now we modify all the relocations */
401 for(i
= 1; i
< s1
->nb_sections
; i
++) {
402 sr
= s1
->sections
[i
];
403 if (sr
->sh_type
== SHT_RELX
&& sr
->link
== s
) {
404 for_each_elem(sr
, 0, rel
, ElfW_Rel
) {
405 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
406 type
= ELFW(R_TYPE
)(rel
->r_info
);
407 sym_index
= old_to_new_syms
[sym_index
];
408 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
413 tcc_free(old_to_new_syms
);
416 /* relocate common symbols in the .bss section */
417 ST_FUNC
void relocate_common_syms(void)
420 unsigned long offset
, align
;
422 for_each_elem(symtab_section
, 1, sym
, ElfW(Sym
)) {
423 if (sym
->st_shndx
== SHN_COMMON
) {
425 align
= sym
->st_value
;
426 offset
= bss_section
->data_offset
;
427 offset
= (offset
+ align
- 1) & -align
;
428 sym
->st_value
= offset
;
429 sym
->st_shndx
= bss_section
->sh_num
;
430 offset
+= sym
->st_size
;
431 bss_section
->data_offset
= offset
;
436 /* relocate symbol table, resolve undefined symbols if do_resolve is
437 true and output error if undefined symbol. */
438 ST_FUNC
void relocate_syms(TCCState
*s1
, int do_resolve
)
440 ElfW(Sym
) *sym
, *esym
;
441 int sym_bind
, sh_num
, sym_index
;
444 for_each_elem(symtab_section
, 1, sym
, ElfW(Sym
)) {
445 sh_num
= sym
->st_shndx
;
446 if (sh_num
== SHN_UNDEF
) {
447 name
= (char *) strtab_section
->data
+ sym
->st_name
;
448 /* Use ld.so to resolve symbol for us (for tcc -run) */
450 #if defined TCC_IS_NATIVE && !defined _WIN32
452 name
= (char *) symtab_section
->link
->data
+ sym
->st_name
;
453 addr
= dlsym(RTLD_DEFAULT
, name
);
455 sym
->st_value
= (addr_t
)addr
;
457 printf ("relocate_sym: %s -> 0x%lx\n", name
, sym
->st_value
);
462 } else if (s1
->dynsym
) {
463 /* if dynamic symbol exist, then use it */
464 sym_index
= find_elf_sym(s1
->dynsym
, name
);
466 esym
= &((ElfW(Sym
) *)s1
->dynsym
->data
)[sym_index
];
467 sym
->st_value
= esym
->st_value
;
471 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
473 if (!strcmp(name
, "_fp_hw"))
475 /* only weak symbols are accepted to be undefined. Their
477 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
478 if (sym_bind
== STB_WEAK
) {
481 tcc_error_noabort("undefined symbol '%s'", name
);
483 } else if (sh_num
< SHN_LORESERVE
) {
484 /* add section base */
485 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
491 /* relocate a given section (CPU dependent) by applying the relocations
492 in the associated relocation section */
493 ST_FUNC
void relocate_section(TCCState
*s1
, Section
*s
)
495 Section
*sr
= s
->reloc
;
501 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
502 ElfW_Rel
*qrel
= (ElfW_Rel
*) sr
->data
; /* ptr to next reloc entry reused */
506 for_each_elem(sr
, 0, rel
, ElfW_Rel
) {
507 ptr
= s
->data
+ rel
->r_offset
;
509 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
510 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
512 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
513 val
+= rel
->r_addend
;
515 type
= ELFW(R_TYPE
)(rel
->r_info
);
516 addr
= s
->sh_addr
+ rel
->r_offset
;
520 #if defined(TCC_TARGET_I386)
522 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
523 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
524 qrel
->r_offset
= rel
->r_offset
;
526 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_386_32
);
530 qrel
->r_info
= ELFW(R_INFO
)(0, R_386_RELATIVE
);
534 write32le(ptr
, read32le(ptr
) + val
);
537 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
539 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
541 qrel
->r_offset
= rel
->r_offset
;
542 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_386_PC32
);
547 write32le(ptr
, read32le(ptr
) + val
- addr
);
550 write32le(ptr
, read32le(ptr
) + val
- addr
);
557 write32le(ptr
, read32le(ptr
) + s1
->got
->sh_addr
- addr
);
560 write32le(ptr
, read32le(ptr
) + val
- s1
->got
->sh_addr
);
564 /* we load the got offset */
565 write32le(ptr
, read32le(ptr
) + s1
->sym_attrs
[sym_index
].got_offset
);
568 if (s1
->output_format
!= TCC_OUTPUT_FORMAT_BINARY
) {
570 tcc_error("can only produce 16-bit binary files");
572 write16le(ptr
, read16le(ptr
) + val
);
575 if (s1
->output_format
!= TCC_OUTPUT_FORMAT_BINARY
)
577 write16le(ptr
, read16le(ptr
) + val
- addr
);
581 case R_386_RELATIVE
: /* handled in pe_relocate_rva() */
585 /* This reloction must copy initialized data from the library
586 to the program .bss segment. Currently made like for ARM
587 (to remove noise of defaukt case). Is this true?
592 fprintf(stderr
,"FIXME: handle reloc type %d at %x [%p] to %x\n",
593 type
, (unsigned)addr
, ptr
, (unsigned)val
);
595 #elif defined(TCC_TARGET_ARM)
601 int x
, is_thumb
, is_call
, h
, blx_avail
, is_bl
, th_ko
;
602 x
= (*(int *) ptr
) & 0xffffff;
603 if (sym
->st_shndx
== SHN_UNDEF
)
604 val
= s1
->plt
->sh_addr
;
606 printf ("reloc %d: x=0x%x val=0x%x ", type
, x
, val
);
608 (*(int *)ptr
) &= 0xff000000;
612 blx_avail
= (TCC_ARM_VERSION
>= 5);
614 is_bl
= (*(unsigned *) ptr
) >> 24 == 0xeb;
615 is_call
= (type
== R_ARM_CALL
|| (type
== R_ARM_PC24
&& is_bl
));
618 printf (" newx=0x%x name=%s\n", x
,
619 (char *) symtab_section
->link
->data
+ sym
->st_name
);
622 th_ko
= (x
& 3) && (!blx_avail
|| !is_call
);
623 if (th_ko
|| x
>= 0x2000000 || x
< -0x2000000)
624 tcc_error("can't relocate value at %x,%d",addr
, type
);
627 /* Only reached if blx is avail and it is a call */
630 (*(int *)ptr
) = 0xfa << 24; /* bl -> blx */
635 /* Since these relocations only concern Thumb-2 and blx instruction was
636 introduced before Thumb-2, we can assume blx is available and not
639 case R_ARM_THM_JUMP24
:
641 int x
, hi
, lo
, s
, j1
, j2
, i1
, i2
, imm10
, imm11
;
642 int to_thumb
, is_call
, to_plt
, blx_bit
= 1 << 12;
646 if (sym
->st_shndx
== SHN_UNDEF
&&
647 ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
650 /* Get initial offset */
651 hi
= (*(uint16_t *)ptr
);
652 lo
= (*(uint16_t *)(ptr
+2));
660 x
= (s
<< 24) | (i1
<< 23) | (i2
<< 22) |
661 (imm10
<< 12) | (imm11
<< 1);
665 /* Relocation infos */
668 to_plt
= (val
>= plt
->sh_addr
) &&
669 (val
< plt
->sh_addr
+ plt
->data_offset
);
670 is_call
= (type
== R_ARM_THM_PC22
);
672 /* Compute final offset */
673 if (to_plt
&& !is_call
) /* Point to 1st instr of Thumb stub */
676 if (!to_thumb
&& is_call
) {
677 blx_bit
= 0; /* bl -> blx */
678 x
= (x
+ 3) & -4; /* Compute offset from aligned PC */
681 /* Check that relocation is possible
682 * offset must not be out of range
683 * if target is to be entered in arm mode:
685 - instruction must be a call (bl) or a jump to PLT */
686 if (!to_thumb
|| x
>= 0x1000000 || x
< -0x1000000)
687 if (to_thumb
|| (val
& 2) || (!is_call
&& !to_plt
))
688 tcc_error("can't relocate value at %x,%d",addr
, type
);
690 /* Compute and store final offset */
696 imm10
= (x
>> 12) & 0x3ff;
697 imm11
= (x
>> 1) & 0x7ff;
698 (*(uint16_t *)ptr
) = (uint16_t) ((hi
& 0xf800) |
700 (*(uint16_t *)(ptr
+2)) = (uint16_t) ((lo
& 0xc000) |
701 (j1
<< 13) | blx_bit
| (j2
<< 11) |
706 case R_ARM_MOVW_ABS_NC
:
709 if (type
== R_ARM_MOVT_ABS
)
712 imm4
= (val
>> 12) & 0xf;
713 x
= (imm4
<< 16) | imm12
;
714 if (type
== R_ARM_THM_MOVT_ABS
)
720 case R_ARM_THM_MOVT_ABS
:
721 case R_ARM_THM_MOVW_ABS_NC
:
723 int x
, i
, imm4
, imm3
, imm8
;
724 if (type
== R_ARM_THM_MOVT_ABS
)
727 imm3
= (val
>> 8) & 0x7;
729 imm4
= (val
>> 12) & 0xf;
730 x
= (imm3
<< 28) | (imm8
<< 16) | (i
<< 10) | imm4
;
731 if (type
== R_ARM_THM_MOVT_ABS
)
740 x
= (*(int *)ptr
) & 0x7fffffff;
741 (*(int *)ptr
) &= 0x80000000;
744 if((x
^(x
>>1))&0x40000000)
745 tcc_error("can't relocate value at %x,%d",addr
, type
);
746 (*(int *)ptr
) |= x
& 0x7fffffff;
752 *(int *)ptr
+= val
- addr
;
755 *(int *)ptr
+= s1
->got
->sh_addr
- addr
;
758 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
761 /* we load the got offset */
762 *(int *)ptr
+= s1
->sym_attrs
[sym_index
].got_offset
;
767 /* trade Thumb support for ARMv4 support */
768 if ((0x0ffffff0 & *(int*)ptr
) == 0x012FFF10)
769 *(int*)ptr
^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
772 case R_ARM_JUMP_SLOT
:
773 *(addr_t
*)ptr
= val
;
776 /* Nothing to do. Normally used to indicate a dependency
777 on a certain symbol (like for exception handling under EABI). */
780 case R_ARM_RELATIVE
: /* handled in pe_relocate_rva() */
784 fprintf(stderr
,"FIXME: handle reloc type %x at %x [%p] to %x\n",
785 type
, (unsigned)addr
, ptr
, (unsigned)val
);
787 #elif defined(TCC_TARGET_ARM64)
788 case R_AARCH64_ABS64
:
791 case R_AARCH64_ABS32
:
794 case R_AARCH64_MOVW_UABS_G0_NC
:
795 write32le(ptr
, ((read32le(ptr
) & 0xffe0001f) |
796 (val
& 0xffff) << 5));
798 case R_AARCH64_MOVW_UABS_G1_NC
:
799 write32le(ptr
, ((read32le(ptr
) & 0xffe0001f) |
800 (val
>> 16 & 0xffff) << 5));
802 case R_AARCH64_MOVW_UABS_G2_NC
:
803 write32le(ptr
, ((read32le(ptr
) & 0xffe0001f) |
804 (val
>> 32 & 0xffff) << 5));
806 case R_AARCH64_MOVW_UABS_G3
:
807 write32le(ptr
, ((read32le(ptr
) & 0xffe0001f) |
808 (val
>> 48 & 0xffff) << 5));
810 case R_AARCH64_ADR_PREL_PG_HI21
: {
811 uint64_t off
= (val
>> 12) - (addr
>> 12);
812 if ((off
+ ((uint64_t)1 << 20)) >> 21)
813 tcc_error("R_AARCH64_ADR_PREL_PG_HI21 relocation failed");
814 write32le(ptr
, ((read32le(ptr
) & 0x9f00001f) |
815 (off
& 0x1ffffc) << 3 | (off
& 3) << 29));
818 case R_AARCH64_ADD_ABS_LO12_NC
:
819 write32le(ptr
, ((read32le(ptr
) & 0xffc003ff) |
820 (val
& 0xfff) << 10));
822 case R_AARCH64_JUMP26
:
823 case R_AARCH64_CALL26
:
824 /* This check must match the one in build_got_entries, testing
825 if we really need a PLT slot. */
826 if (sym
->st_shndx
== SHN_UNDEF
)
827 /* We've put the PLT slot offset into r_addend when generating
828 it, and that's what we must use as relocation value (adjusted
829 by section offset of course). */
830 val
= s1
->plt
->sh_addr
+ rel
->r_addend
;
832 printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type
, addr
, val
,
833 (char *) symtab_section
->link
->data
+ sym
->st_name
);
835 if (((val
- addr
) + ((uint64_t)1 << 27)) & ~(uint64_t)0xffffffc)
837 tcc_error("R_AARCH64_(JUMP|CALL)26 relocation failed (val=%lx, addr=%lx)", addr
, val
);
839 write32le(ptr
, (0x14000000 |
840 (uint32_t)(type
== R_AARCH64_CALL26
) << 31 |
841 ((val
- addr
) >> 2 & 0x3ffffff)));
843 case R_AARCH64_ADR_GOT_PAGE
: {
845 (((s1
->got
->sh_addr
+
846 s1
->sym_attrs
[sym_index
].got_offset
) >> 12) - (addr
>> 12));
847 if ((off
+ ((uint64_t)1 << 20)) >> 21)
848 tcc_error("R_AARCH64_ADR_GOT_PAGE relocation failed");
849 write32le(ptr
, ((read32le(ptr
) & 0x9f00001f) |
850 (off
& 0x1ffffc) << 3 | (off
& 3) << 29));
853 case R_AARCH64_LD64_GOT_LO12_NC
:
855 ((read32le(ptr
) & 0xfff803ff) |
857 s1
->sym_attrs
[sym_index
].got_offset
) & 0xff8) << 7));
861 case R_AARCH64_GLOB_DAT
:
862 case R_AARCH64_JUMP_SLOT
:
863 /* They don't need addend */
865 printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type
, addr
,
867 (char *) symtab_section
->link
->data
+ sym
->st_name
);
869 write64le(ptr
, val
- rel
->r_addend
);
872 fprintf(stderr
, "FIXME: handle reloc type %x at %x [%p] to %x\n",
873 type
, (unsigned)addr
, ptr
, (unsigned)val
);
875 #elif defined(TCC_TARGET_C67)
883 /* put the low 16 bits of the absolute address
884 add to what is already there */
886 orig
= ((*(int *)(ptr
)) >> 7) & 0xffff;
887 orig
|= (((*(int *)(ptr
+4)) >> 7) & 0xffff) << 16;
889 /* patch both at once - assumes always in pairs Low - High */
891 *(int *) ptr
= (*(int *) ptr
& (~(0xffff << 7)) ) | (((val
+orig
) & 0xffff) << 7);
892 *(int *)(ptr
+4) = (*(int *)(ptr
+4) & (~(0xffff << 7)) ) | ((((val
+orig
)>>16) & 0xffff) << 7);
898 fprintf(stderr
,"FIXME: handle reloc type %x at %x [%p] to %x\n",
899 type
, (unsigned)addr
, ptr
, (unsigned)val
);
901 #elif defined(TCC_TARGET_X86_64)
903 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
904 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
905 qrel
->r_offset
= rel
->r_offset
;
907 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_X86_64_64
);
908 qrel
->r_addend
= rel
->r_addend
;
912 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
913 qrel
->r_addend
= read64le(ptr
) + val
;
917 write64le(ptr
, read64le(ptr
) + val
);
921 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
922 /* XXX: this logic may depend on TCC's codegen
923 now TCC uses R_X86_64_32 even for a 64bit pointer */
924 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
925 /* Use sign extension! */
926 qrel
->r_addend
= (int)read32le(ptr
) + val
;
929 write32le(ptr
, read32le(ptr
) + val
);
933 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
935 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
937 qrel
->r_offset
= rel
->r_offset
;
938 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_X86_64_PC32
);
939 /* Use sign extension! */
940 qrel
->r_addend
= (int)read32le(ptr
) + rel
->r_addend
;
948 /* We've put the PLT slot offset into r_addend when generating
949 it, and that's what we must use as relocation value (adjusted
950 by section offset of course). */
951 val
= s1
->plt
->sh_addr
+ rel
->r_addend
;
957 diff
= (long long)val
- addr
;
958 if (diff
< -2147483648LL || diff
> 2147483647LL) {
959 tcc_error("internal error: relocation failed");
961 write32le(ptr
, read32le(ptr
) + diff
);
964 case R_X86_64_GLOB_DAT
:
965 case R_X86_64_JUMP_SLOT
:
966 /* They don't need addend */
967 write64le(ptr
, val
- rel
->r_addend
);
969 case R_X86_64_GOTPCREL
:
970 case R_X86_64_GOTPCRELX
:
971 case R_X86_64_REX_GOTPCRELX
:
972 write32le(ptr
, read32le(ptr
) +
973 (s1
->got
->sh_addr
- addr
+
974 s1
->sym_attrs
[sym_index
].got_offset
- 4));
976 case R_X86_64_GOTTPOFF
:
977 write32le(ptr
, read32le(ptr
) + val
- s1
->got
->sh_addr
);
980 /* we load the got offset */
981 write32le(ptr
, read32le(ptr
) + s1
->sym_attrs
[sym_index
].got_offset
);
984 case R_X86_64_RELATIVE
: /* handled in pe_relocate_rva() */
989 #error unsupported processor
993 /* if the relocation is allocated, we change its symbol table */
994 if (sr
->sh_flags
& SHF_ALLOC
)
995 sr
->link
= s1
->dynsym
;
998 /* relocate relocation table in 'sr' */
999 static void relocate_rel(TCCState
*s1
, Section
*sr
)
1004 s
= s1
->sections
[sr
->sh_info
];
1005 for_each_elem(sr
, 0, rel
, ElfW_Rel
)
1006 rel
->r_offset
+= s
->sh_addr
;
1009 /* count the number of dynamic relocations so that we can reserve
1011 static int prepare_dynamic_rel(TCCState
*s1
, Section
*sr
)
1014 int sym_index
, esym_index
, type
, count
;
1017 for_each_elem(sr
, 0, rel
, ElfW_Rel
) {
1018 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1019 type
= ELFW(R_TYPE
)(rel
->r_info
);
1021 #if defined(TCC_TARGET_I386)
1023 #elif defined(TCC_TARGET_X86_64)
1030 #if defined(TCC_TARGET_I386)
1032 #elif defined(TCC_TARGET_X86_64)
1035 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
1044 /* allocate the section */
1045 sr
->sh_flags
|= SHF_ALLOC
;
1046 sr
->sh_size
= count
* sizeof(ElfW_Rel
);
1051 static struct sym_attr
*alloc_sym_attr(TCCState
*s1
, int index
)
1054 struct sym_attr
*tab
;
1056 if (index
>= s1
->nb_sym_attrs
) {
1057 /* find immediately bigger power of 2 and reallocate array */
1061 tab
= tcc_realloc(s1
->sym_attrs
, n
* sizeof(*s1
->sym_attrs
));
1062 s1
->sym_attrs
= tab
;
1063 memset(s1
->sym_attrs
+ s1
->nb_sym_attrs
, 0,
1064 (n
- s1
->nb_sym_attrs
) * sizeof(*s1
->sym_attrs
));
1065 s1
->nb_sym_attrs
= n
;
1067 return &s1
->sym_attrs
[index
];
1070 static void build_got(TCCState
*s1
)
1074 /* if no got, then create it */
1075 s1
->got
= new_section(s1
, ".got", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
1076 s1
->got
->sh_entsize
= 4;
1077 add_elf_sym(symtab_section
, 0, 4, ELFW(ST_INFO
)(STB_GLOBAL
, STT_OBJECT
),
1078 0, s1
->got
->sh_num
, "_GLOBAL_OFFSET_TABLE_");
1079 ptr
= section_ptr_add(s1
->got
, 3 * PTR_SIZE
);
1081 /* keep space for _DYNAMIC pointer, if present */
1083 /* two dummy got entries */
1084 write32le(ptr
+ 4, 0);
1085 write32le(ptr
+ 8, 0);
1087 /* keep space for _DYNAMIC pointer, if present */
1089 write32le(ptr
+ 4, 0);
1090 /* two dummy got entries */
1091 write32le(ptr
+ 8, 0);
1092 write32le(ptr
+ 12, 0);
1093 write32le(ptr
+ 16, 0);
1094 write32le(ptr
+ 20, 0);
1098 /* put a got or plt entry corresponding to a symbol in symtab_section. 'size'
1099 and 'info' can be modifed if more precise info comes from the DLL.
1100 Returns offset of GOT or PLT slot. */
1101 static unsigned long put_got_entry(TCCState
*s1
,
1102 int reloc_type
, unsigned long size
, int info
,
1105 int index
, need_plt_entry
;
1108 unsigned long offset
;
1110 struct sym_attr
*symattr
;
1116 #ifdef TCC_TARGET_X86_64
1117 (reloc_type
== R_X86_64_JUMP_SLOT
);
1118 #elif defined(TCC_TARGET_I386)
1119 (reloc_type
== R_386_JMP_SLOT
);
1120 #elif defined(TCC_TARGET_ARM)
1121 (reloc_type
== R_ARM_JUMP_SLOT
);
1122 #elif defined(TCC_TARGET_ARM64)
1123 (reloc_type
== R_AARCH64_JUMP_SLOT
);
1128 if (need_plt_entry
&& !s1
->plt
) {
1130 s1
->plt
= new_section(s1
, ".plt", SHT_PROGBITS
,
1131 SHF_ALLOC
| SHF_EXECINSTR
);
1132 s1
->plt
->sh_entsize
= 4;
1135 /* If a got/plt entry already exists for that symbol, no need to add one */
1136 if (sym_index
< s1
->nb_sym_attrs
) {
1137 if (need_plt_entry
&& s1
->sym_attrs
[sym_index
].plt_offset
)
1138 return s1
->sym_attrs
[sym_index
].plt_offset
;
1139 else if (!need_plt_entry
&& s1
->sym_attrs
[sym_index
].got_offset
)
1140 return s1
->sym_attrs
[sym_index
].got_offset
;
1143 symattr
= alloc_sym_attr(s1
, sym_index
);
1145 /* Only store the GOT offset if it's not generated for the PLT entry. */
1146 if (!need_plt_entry
)
1147 symattr
->got_offset
= s1
->got
->data_offset
;
1149 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1150 name
= (char *) symtab_section
->link
->data
+ sym
->st_name
;
1151 offset
= sym
->st_value
;
1152 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1153 if (need_plt_entry
) {
1157 unsigned long relofs
;
1159 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1162 /* if we build a DLL, we add a %ebx offset */
1163 if (s1
->output_type
== TCC_OUTPUT_DLL
)
1169 /* add a PLT entry */
1171 if (plt
->data_offset
== 0) {
1172 /* first plt entry */
1173 p
= section_ptr_add(plt
, 16);
1174 p
[0] = 0xff; /* pushl got + PTR_SIZE */
1175 p
[1] = modrm
+ 0x10;
1176 write32le(p
+ 2, PTR_SIZE
);
1177 p
[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1179 write32le(p
+ 8, PTR_SIZE
* 2);
1182 /* The PLT slot refers to the relocation entry it needs
1183 via offset. The reloc entry is created below, so its
1184 offset is the current data_offset. */
1185 relofs
= s1
->got
->reloc
? s1
->got
->reloc
->data_offset
: 0;
1186 symattr
->plt_offset
= plt
->data_offset
;
1187 p
= section_ptr_add(plt
, 16);
1188 p
[0] = 0xff; /* jmp *(got + x) */
1190 write32le(p
+ 2, s1
->got
->data_offset
);
1191 p
[6] = 0x68; /* push $xxx */
1192 #ifdef TCC_TARGET_X86_64
1193 /* On x86-64, the relocation is referred to by _index_. */
1194 write32le(p
+ 7, relofs
/ sizeof (ElfW_Rel
));
1196 write32le(p
+ 7, relofs
);
1198 p
[11] = 0xe9; /* jmp plt_start */
1199 write32le(p
+ 12, -(plt
->data_offset
));
1201 /* If this was an UNDEF symbol set the offset in the
1202 dynsymtab to the PLT slot, so that PC32 relocs to it
1204 if (sym
->st_shndx
== SHN_UNDEF
)
1205 offset
= plt
->data_offset
- 16;
1207 #elif defined(TCC_TARGET_ARM)
1208 if (need_plt_entry
) {
1212 /* if we build a DLL, we add a %ebx offset */
1213 if (s1
->output_type
== TCC_OUTPUT_DLL
)
1214 tcc_error("DLLs unimplemented!");
1216 /* add a PLT entry */
1218 if (plt
->data_offset
== 0) {
1219 /* first plt entry */
1220 p
= section_ptr_add(plt
, 16);
1221 write32le(p
, 0xe52de004); /* push {lr} */
1222 write32le(p
+4, 0xe59fe010); /* ldr lr, [pc, #16] */
1223 write32le(p
+8, 0xe08fe00e); /* add lr, pc, lr */
1224 write32le(p
+12, 0xe5bef008); /* ldr pc, [lr, #8]! */
1227 symattr
->plt_offset
= plt
->data_offset
;
1228 if (symattr
->plt_thumb_stub
) {
1229 p
= section_ptr_add(plt
, 20);
1230 write32le(p
, 0x4778); /* bx pc */
1231 write32le(p
+2, 0x46c0); /* nop */
1234 p
= section_ptr_add(plt
, 16);
1235 write32le(p
, 0xe59fc004); /* ldr ip, [pc, #4] ; GOT entry offset */
1236 write32le(p
+4, 0xe08fc00c); /* add ip, pc, ip ; addr of GOT entry */
1237 write32le(p
+8, 0xe59cf000); /* ldr pc, [ip] ; jump to GOT entry */
1238 write32le(p
+12, s1
->got
->data_offset
); /* GOT entry off once patched */
1240 /* the symbol is modified so that it will be relocated to
1242 if (sym
->st_shndx
== SHN_UNDEF
)
1243 offset
= plt
->data_offset
- 16;
1245 #elif defined(TCC_TARGET_ARM64)
1246 if (need_plt_entry
) {
1250 if (s1
->output_type
== TCC_OUTPUT_DLL
)
1251 tcc_error("DLLs unimplemented!");
1254 if (plt
->data_offset
== 0)
1255 section_ptr_add(plt
, 32);
1256 symattr
->plt_offset
= plt
->data_offset
;
1257 p
= section_ptr_add(plt
, 16);
1258 write32le(p
, s1
->got
->data_offset
);
1259 write32le(p
+ 4, (uint64_t)s1
->got
->data_offset
>> 32);
1261 if (sym
->st_shndx
== SHN_UNDEF
)
1262 offset
= plt
->data_offset
- 16;
1264 #elif defined(TCC_TARGET_C67)
1266 tcc_error("C67 got not implemented");
1269 #error unsupported CPU
1272 /* XXX This might generate multiple syms for name. */
1273 index
= put_elf_sym(s1
->dynsym
, offset
,
1274 size
, info
, 0, sym
->st_shndx
, name
);
1275 /* Create the relocation (it's against the GOT for PLT
1277 put_elf_reloc(s1
->dynsym
, s1
->got
,
1278 s1
->got
->data_offset
,
1281 /* Without .dynsym (i.e. static link or memory output) we
1282 still need relocs against the generated got, so as to fill
1283 the entries with the symbol values (determined later). */
1284 put_elf_reloc(symtab_section
, s1
->got
,
1285 s1
->got
->data_offset
,
1286 reloc_type
, sym_index
);
1288 /* And now create the GOT slot itself. */
1289 ptr
= section_ptr_add(s1
->got
, PTR_SIZE
);
1292 return symattr
->plt_offset
;
1294 return symattr
->got_offset
;
1297 /* build GOT and PLT entries */
1298 ST_FUNC
void build_got_entries(TCCState
*s1
)
1303 int i
, type
, reloc_type
, sym_index
;
1305 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1306 s
= s1
->sections
[i
];
1307 if (s
->sh_type
!= SHT_RELX
)
1309 /* no need to handle got relocations */
1310 if (s
->link
!= symtab_section
)
1312 for_each_elem(s
, 0, rel
, ElfW_Rel
) {
1313 type
= ELFW(R_TYPE
)(rel
->r_info
);
1315 #if defined(TCC_TARGET_I386)
1323 if (type
== R_386_GOT32
|| type
== R_386_GOT32X
||
1324 type
== R_386_PLT32
) {
1325 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1326 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1327 /* look at the symbol got offset. If none, then add one */
1328 if (type
== R_386_GOT32
|| type
== R_386_GOT32X
)
1329 reloc_type
= R_386_GLOB_DAT
;
1331 reloc_type
= R_386_JMP_SLOT
;
1332 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1336 #elif defined(TCC_TARGET_ARM)
1346 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1347 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1348 if (type
!= R_ARM_GOTOFF
&& type
!= R_ARM_GOTPC
1349 && sym
->st_shndx
== SHN_UNDEF
) {
1351 /* look at the symbol got offset. If none, then add one */
1352 if (type
== R_ARM_GOT32
)
1353 reloc_type
= R_ARM_GLOB_DAT
;
1355 reloc_type
= R_ARM_JUMP_SLOT
;
1356 ofs
= put_got_entry(s1
, reloc_type
, sym
->st_size
,
1357 sym
->st_info
, sym_index
);
1359 printf ("maybegot: %s, %d, %d --> ofs=0x%x\n",
1360 (char *) symtab_section
->link
->data
+ sym
->st_name
,
1361 type
, sym
->st_shndx
, ofs
);
1363 if (type
!= R_ARM_GOT32
) {
1364 addr_t
*ptr
= (addr_t
*)(s1
->sections
[s
->sh_info
]->data
1366 /* x must be signed! */
1367 int x
= *ptr
& 0xffffff;
1373 printf ("insn=0x%x --> 0x%x (x==0x%x)\n", *ptr
,
1374 (*ptr
& 0xff000000) | x
, x
);
1376 *ptr
= (*ptr
& 0xff000000) | x
;
1380 case R_ARM_THM_JUMP24
:
1381 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1382 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1383 /* We are relocating a jump from thumb code to arm code */
1384 if (sym
->st_shndx
!= SHN_UNDEF
&& !(sym
->st_value
& 1)) {
1387 char *name
, buf
[1024];
1388 Section
*text_section
;
1390 name
= (char *) symtab_section
->link
->data
+ sym
->st_name
;
1391 text_section
= s1
->sections
[sym
->st_shndx
];
1392 /* Modify reloc to target a thumb stub to switch to ARM */
1393 snprintf(buf
, sizeof(buf
), "%s_from_thumb", name
);
1394 index
= put_elf_sym(symtab_section
,
1395 text_section
->data_offset
+ 1,
1396 sym
->st_size
, sym
->st_info
, 0,
1397 sym
->st_shndx
, buf
);
1398 rel
->r_info
= ELFW(R_INFO
)(index
, type
);
1399 /* Create a thumb stub fonction to switch to ARM mode */
1400 put_elf_reloc(symtab_section
, text_section
,
1401 text_section
->data_offset
+ 4, R_ARM_JUMP24
,
1403 p
= section_ptr_add(text_section
, 8);
1404 write32le(p
, 0x4778); /* bx pc */
1405 write32le(p
+2, 0x46c0); /* nop */
1406 write32le(p
+4, 0xeafffffe); /* b $sym */
1408 #elif defined(TCC_TARGET_ARM64)
1409 //xx Other cases may be required here:
1410 case R_AARCH64_ADR_GOT_PAGE
:
1411 case R_AARCH64_LD64_GOT_LO12_NC
:
1414 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1415 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1416 reloc_type
= R_AARCH64_GLOB_DAT
;
1417 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1421 case R_AARCH64_JUMP26
:
1422 case R_AARCH64_CALL26
:
1425 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1426 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1427 if (sym
->st_shndx
== SHN_UNDEF
) {
1429 reloc_type
= R_AARCH64_JUMP_SLOT
;
1430 ofs
= put_got_entry(s1
, reloc_type
, sym
->st_size
,
1431 sym
->st_info
, sym_index
);
1432 /* We store the place of the generated PLT slot
1434 rel
->r_addend
+= ofs
;
1437 #elif defined(TCC_TARGET_C67)
1444 if (type
== R_C60_GOT32
|| type
== R_C60_PLT32
) {
1445 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1446 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1447 /* look at the symbol got offset. If none, then add one */
1448 if (type
== R_C60_GOT32
)
1449 reloc_type
= R_C60_GLOB_DAT
;
1451 reloc_type
= R_C60_JMP_SLOT
;
1452 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1456 #elif defined(TCC_TARGET_X86_64)
1457 case R_X86_64_GOT32
:
1458 case R_X86_64_GOTTPOFF
:
1459 case R_X86_64_GOTPCREL
:
1460 case R_X86_64_GOTPCRELX
:
1461 case R_X86_64_REX_GOTPCRELX
:
1462 case R_X86_64_PLT32
:
1463 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1464 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1465 if (type
== R_X86_64_PLT32
&&
1466 ELFW(ST_VISIBILITY
)(sym
->st_other
) != STV_DEFAULT
)
1468 rel
->r_info
= ELFW(R_INFO
)(sym_index
, R_X86_64_PC32
);
1474 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1476 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
||
1477 type
== R_X86_64_GOTPCRELX
||
1478 type
== R_X86_64_REX_GOTPCRELX
||
1479 type
== R_X86_64_PLT32
) {
1481 /* look at the symbol got offset. If none, then add one */
1482 if (type
== R_X86_64_PLT32
)
1483 reloc_type
= R_X86_64_JUMP_SLOT
;
1485 reloc_type
= R_X86_64_GLOB_DAT
;
1486 ofs
= put_got_entry(s1
, reloc_type
, sym
->st_size
,
1487 sym
->st_info
, sym_index
);
1488 if (type
== R_X86_64_PLT32
)
1489 /* We store the place of the generated PLT slot
1491 rel
->r_addend
+= ofs
;
1495 #error unsupported CPU
1504 ST_FUNC Section
*new_symtab(TCCState
*s1
,
1505 const char *symtab_name
, int sh_type
, int sh_flags
,
1506 const char *strtab_name
,
1507 const char *hash_name
, int hash_sh_flags
)
1509 Section
*symtab
, *strtab
, *hash
;
1510 int *ptr
, nb_buckets
;
1512 symtab
= new_section(s1
, symtab_name
, sh_type
, sh_flags
);
1513 symtab
->sh_entsize
= sizeof(ElfW(Sym
));
1514 strtab
= new_section(s1
, strtab_name
, SHT_STRTAB
, sh_flags
);
1515 put_elf_str(strtab
, "");
1516 symtab
->link
= strtab
;
1517 put_elf_sym(symtab
, 0, 0, 0, 0, 0, NULL
);
1521 hash
= new_section(s1
, hash_name
, SHT_HASH
, hash_sh_flags
);
1522 hash
->sh_entsize
= sizeof(int);
1523 symtab
->hash
= hash
;
1524 hash
->link
= symtab
;
1526 ptr
= section_ptr_add(hash
, (2 + nb_buckets
+ 1) * sizeof(int));
1527 ptr
[0] = nb_buckets
;
1529 memset(ptr
+ 2, 0, (nb_buckets
+ 1) * sizeof(int));
1533 /* put dynamic tag */
1534 static void put_dt(Section
*dynamic
, int dt
, addr_t val
)
1537 dyn
= section_ptr_add(dynamic
, sizeof(ElfW(Dyn
)));
1539 dyn
->d_un
.d_val
= val
;
1542 static void add_init_array_defines(TCCState
*s1
, const char *section_name
)
1546 char sym_start
[1024];
1549 snprintf(sym_start
, sizeof(sym_start
), "__%s_start", section_name
+ 1);
1550 snprintf(sym_end
, sizeof(sym_end
), "__%s_end", section_name
+ 1);
1552 s
= find_section(s1
, section_name
);
1557 end_offset
= s
->data_offset
;
1560 add_elf_sym(symtab_section
,
1562 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1563 s
->sh_num
, sym_start
);
1564 add_elf_sym(symtab_section
,
1566 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1567 s
->sh_num
, sym_end
);
1570 static int tcc_add_support(TCCState
*s1
, const char *filename
)
1573 snprintf(buf
, sizeof(buf
), "%s/"TCC_ARCH_DIR
"%s", s1
->tcc_lib_path
, filename
);
1574 return tcc_add_file(s1
, buf
);
1577 ST_FUNC
void tcc_add_bcheck(TCCState
*s1
)
1579 #ifdef CONFIG_TCC_BCHECK
1583 if (0 == s1
->do_bounds_check
)
1585 /* XXX: add an object file to do that */
1586 ptr
= section_ptr_add(bounds_section
, sizeof(*ptr
));
1588 add_elf_sym(symtab_section
, 0, 0,
1589 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1590 bounds_section
->sh_num
, "__bounds_start");
1591 /* pull bcheck.o from libtcc1.a */
1592 sym_index
= add_elf_sym(symtab_section
, 0, 0,
1593 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1594 SHN_UNDEF
, "__bound_init");
1595 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
) {
1596 /* add 'call __bound_init()' in .init section */
1597 Section
*init_section
= find_section(s1
, ".init");
1598 unsigned char *pinit
= section_ptr_add(init_section
, 5);
1600 write32le(pinit
+ 1, -4);
1601 put_elf_reloc(symtab_section
, init_section
,
1602 init_section
->data_offset
- 4, R_386_PC32
, sym_index
);
1603 /* R_386_PC32 = R_X86_64_PC32 = 2 */
1608 /* add tcc runtime libraries */
1609 ST_FUNC
void tcc_add_runtime(TCCState
*s1
)
1612 tcc_add_pragma_libs(s1
);
1614 if (!s1
->nostdlib
) {
1615 tcc_add_library(s1
, "c");
1616 #ifdef CONFIG_USE_LIBGCC
1617 if (!s1
->static_link
) {
1618 tcc_add_file(s1
, TCC_LIBGCC
);
1621 tcc_add_support(s1
, "libtcc1.a");
1622 /* add crt end if not memory output */
1623 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
)
1624 tcc_add_crt(s1
, "crtn.o");
1628 /* add various standard linker symbols (must be done after the
1629 sections are filled (for example after allocating common
1631 ST_FUNC
void tcc_add_linker_symbols(TCCState
*s1
)
1637 add_elf_sym(symtab_section
,
1638 text_section
->data_offset
, 0,
1639 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1640 text_section
->sh_num
, "_etext");
1641 add_elf_sym(symtab_section
,
1642 data_section
->data_offset
, 0,
1643 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1644 data_section
->sh_num
, "_edata");
1645 add_elf_sym(symtab_section
,
1646 bss_section
->data_offset
, 0,
1647 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1648 bss_section
->sh_num
, "_end");
1649 /* horrible new standard ldscript defines */
1650 add_init_array_defines(s1
, ".preinit_array");
1651 add_init_array_defines(s1
, ".init_array");
1652 add_init_array_defines(s1
, ".fini_array");
1654 /* add start and stop symbols for sections whose name can be
1656 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1657 s
= s1
->sections
[i
];
1658 if (s
->sh_type
== SHT_PROGBITS
&&
1659 (s
->sh_flags
& SHF_ALLOC
)) {
1663 /* check if section name can be expressed in C */
1669 if (!isid(ch
) && !isnum(ch
))
1673 snprintf(buf
, sizeof(buf
), "__start_%s", s
->name
);
1674 add_elf_sym(symtab_section
,
1676 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1678 snprintf(buf
, sizeof(buf
), "__stop_%s", s
->name
);
1679 add_elf_sym(symtab_section
,
1681 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1688 static void tcc_output_binary(TCCState
*s1
, FILE *f
,
1689 const int *sec_order
)
1692 int i
, offset
, size
;
1695 for(i
=1;i
<s1
->nb_sections
;i
++) {
1696 s
= s1
->sections
[sec_order
[i
]];
1697 if (s
->sh_type
!= SHT_NOBITS
&&
1698 (s
->sh_flags
& SHF_ALLOC
)) {
1699 while (offset
< s
->sh_offset
) {
1704 fwrite(s
->data
, 1, size
, f
);
1710 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1712 #define EXTRA_RELITEMS 14
1714 /* move the relocation value from .dynsym to .got */
1715 static void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1717 uint32_t *gotd
= (void *)s1
->got
->data
;
1720 gotd
+= 3; /* dummy entries in .got */
1721 /* relocate symbols in .dynsym */
1722 for_each_elem(s
, 1, sym
, ElfW(Sym
)) {
1723 if (sym
->st_shndx
== SHN_UNDEF
) {
1724 *gotd
++ = sym
->st_value
+ 6; /* XXX 6 is magic ? */
1731 #define EXTRA_RELITEMS 9
1733 /* zero plt offsets of weak symbols in .dynsym */
1734 static void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1738 for_each_elem(s
, 1, sym
, ElfW(Sym
))
1739 if (sym
->st_shndx
== SHN_UNDEF
&& ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
1744 ST_FUNC
void fill_got_entry(TCCState
*s1
, ElfW_Rel
*rel
)
1746 int sym_index
= ELFW(R_SYM
) (rel
->r_info
);
1747 ElfW(Sym
) *sym
= &((ElfW(Sym
) *) symtab_section
->data
)[sym_index
];
1748 unsigned long offset
;
1750 if (sym_index
>= s1
->nb_sym_attrs
)
1752 offset
= s1
->sym_attrs
[sym_index
].got_offset
;
1753 section_reserve(s1
->got
, offset
+ PTR_SIZE
);
1754 #ifdef TCC_TARGET_X86_64
1755 /* only works for x86-64 */
1756 write32le(s1
->got
->data
+ offset
+ 4, sym
->st_value
>> 32);
1758 write32le(s1
->got
->data
+ offset
, sym
->st_value
& 0xffffffff);
1761 /* Perform relocation to GOT or PLT entries */
1762 ST_FUNC
void fill_got(TCCState
*s1
)
1768 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1769 s
= s1
->sections
[i
];
1770 if (s
->sh_type
!= SHT_RELX
)
1772 /* no need to handle got relocations */
1773 if (s
->link
!= symtab_section
)
1775 for_each_elem(s
, 0, rel
, ElfW_Rel
) {
1776 switch (ELFW(R_TYPE
) (rel
->r_info
)) {
1777 case R_X86_64_GOT32
:
1778 case R_X86_64_GOTPCREL
:
1779 case R_X86_64_GOTPCRELX
:
1780 case R_X86_64_REX_GOTPCRELX
:
1781 case R_X86_64_PLT32
:
1782 fill_got_entry(s1
, rel
);
1789 /* Bind symbols of executable: resolve undefined symbols from exported symbols
1790 in shared libraries and export non local defined symbols to shared libraries
1791 if -rdynamic switch was given on command line */
1792 static void bind_exe_dynsyms(TCCState
*s1
)
1795 int sym_index
, index
;
1796 ElfW(Sym
) *sym
, *esym
;
1799 /* Resolve undefined symbols from dynamic symbols. When there is a match:
1800 - if STT_FUNC or STT_GNU_IFUNC symbol -> add it in PLT
1801 - if STT_OBJECT symbol -> add it in .bss section with suitable reloc */
1802 for_each_elem(symtab_section
, 1, sym
, ElfW(Sym
)) {
1803 if (sym
->st_shndx
== SHN_UNDEF
) {
1804 name
= (char *) symtab_section
->link
->data
+ sym
->st_name
;
1805 sym_index
= find_elf_sym(s1
->dynsymtab_section
, name
);
1807 esym
= &((ElfW(Sym
) *)s1
->dynsymtab_section
->data
)[sym_index
];
1808 type
= ELFW(ST_TYPE
)(esym
->st_info
);
1809 if ((type
== STT_FUNC
) || (type
== STT_GNU_IFUNC
)) {
1810 /* Indirect functions shall have STT_FUNC type in executable
1811 * dynsym section. Indeed, a dlsym call following a lazy
1812 * resolution would pick the symbol value from the
1813 * executable dynsym entry which would contain the address
1814 * of the function wanted by the caller of dlsym instead of
1815 * the address of the function that would return that
1817 put_got_entry(s1
, R_JMP_SLOT
, esym
->st_size
,
1818 ELFW(ST_INFO
)(STB_GLOBAL
,STT_FUNC
),
1819 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1820 } else if (type
== STT_OBJECT
) {
1821 unsigned long offset
;
1823 offset
= bss_section
->data_offset
;
1824 /* XXX: which alignment ? */
1825 offset
= (offset
+ 16 - 1) & -16;
1826 index
= put_elf_sym(s1
->dynsym
, offset
, esym
->st_size
,
1827 esym
->st_info
, 0, bss_section
->sh_num
,
1829 /* Ensure R_COPY works for weak symbol aliases */
1830 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1831 for_each_elem(s1
->dynsymtab_section
, 1, dynsym
, ElfW(Sym
)) {
1832 if ((dynsym
->st_value
== esym
->st_value
)
1833 && (ELFW(ST_BIND
)(dynsym
->st_info
) == STB_GLOBAL
)) {
1834 char *dynname
= (char *) s1
->dynsymtab_section
->link
->data
1836 put_elf_sym(s1
->dynsym
, offset
, dynsym
->st_size
,
1838 bss_section
->sh_num
, dynname
);
1843 put_elf_reloc(s1
->dynsym
, bss_section
,
1844 offset
, R_COPY
, index
);
1845 offset
+= esym
->st_size
;
1846 bss_section
->data_offset
= offset
;
1849 /* STB_WEAK undefined symbols are accepted */
1850 /* XXX: _fp_hw seems to be part of the ABI, so we ignore it */
1851 if (ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
||
1852 !strcmp(name
, "_fp_hw")) {
1854 tcc_error_noabort("undefined symbol '%s'", name
);
1857 } else if (s1
->rdynamic
&& ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1858 /* if -rdynamic option, then export all non local symbols */
1859 name
= (char *) symtab_section
->link
->data
+ sym
->st_name
;
1860 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
, sym
->st_info
,
1861 0, sym
->st_shndx
, name
);
1866 /* Bind symbols of libraries: export non local symbols of executable that
1867 resolve undefined symbols of shared libraries */
1868 static void bind_libs_dynsyms(TCCState
*s1
)
1872 ElfW(Sym
) *sym
, *esym
;
1874 /* now look at unresolved dynamic symbols and export
1875 corresponding symbol */
1876 for_each_elem(s1
->dynsymtab_section
, 1, esym
, ElfW(Sym
)) {
1877 name
= (char *) s1
->dynsymtab_section
->link
->data
+ esym
->st_name
;
1878 sym_index
= find_elf_sym(symtab_section
, name
);
1880 /* XXX: avoid adding a symbol if already present because of
1882 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1883 if (sym
->st_shndx
!= SHN_UNDEF
)
1884 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1885 sym
->st_info
, 0, sym
->st_shndx
, name
);
1886 } else if (esym
->st_shndx
== SHN_UNDEF
) {
1887 /* weak symbols can stay undefined */
1888 if (ELFW(ST_BIND
)(esym
->st_info
) != STB_WEAK
)
1889 tcc_warning("undefined dynamic symbol '%s'", name
);
1894 /* Export all non local symbols (for shared libraries) */
1895 static void export_global_syms(TCCState
*s1
)
1897 int nb_syms
, dynindex
, index
;
1901 nb_syms
= symtab_section
->data_offset
/ sizeof(ElfW(Sym
));
1902 s1
->symtab_to_dynsym
= tcc_mallocz(sizeof(int) * nb_syms
);
1903 for_each_elem(symtab_section
, 1, sym
, ElfW(Sym
)) {
1904 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1905 name
= (char *) symtab_section
->link
->data
+ sym
->st_name
;
1906 dynindex
= put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1907 sym
->st_info
, 0, sym
->st_shndx
, name
);
1908 index
= sym
- (ElfW(Sym
) *) symtab_section
->data
;
1909 s1
->symtab_to_dynsym
[index
] = dynindex
;
1914 /* relocate the PLT: compute addresses and offsets in the PLT now that final
1915 address for PLT and GOT are known (see fill_program_header) */
1916 ST_FUNC
void relocate_plt(TCCState
*s1
)
1924 p_end
= p
+ s1
->plt
->data_offset
;
1926 #if defined(TCC_TARGET_I386)
1927 write32le(p
+ 2, read32le(p
+ 2) + s1
->got
->sh_addr
);
1928 write32le(p
+ 8, read32le(p
+ 8) + s1
->got
->sh_addr
);
1931 write32le(p
+ 2, read32le(p
+ 2) + s1
->got
->sh_addr
);
1934 #elif defined(TCC_TARGET_X86_64)
1935 int x
= s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 6;
1936 write32le(p
+ 2, read32le(p
+ 2) + x
);
1937 write32le(p
+ 8, read32le(p
+ 8) + x
- 6);
1940 write32le(p
+ 2, read32le(p
+ 2) + x
+ s1
->plt
->data
- p
);
1943 #elif defined(TCC_TARGET_ARM)
1945 x
=s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 12;
1948 if (read32le(p
) == 0x46c04778) /* PLT Thumb stub present */
1950 write32le(p
+ 12, x
+ read32le(p
+ 12) + s1
->plt
->data
- p
);
1953 #elif defined(TCC_TARGET_ARM64)
1954 uint64_t plt
= s1
->plt
->sh_addr
;
1955 uint64_t got
= s1
->got
->sh_addr
;
1956 uint64_t off
= (got
>> 12) - (plt
>> 12);
1957 if ((off
+ ((uint32_t)1 << 20)) >> 21)
1958 tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", off
, got
, plt
);
1959 write32le(p
, 0xa9bf7bf0); // stp x16,x30,[sp,#-16]!
1960 write32le(p
+ 4, (0x90000010 | // adrp x16,...
1961 (off
& 0x1ffffc) << 3 | (off
& 3) << 29));
1962 write32le(p
+ 8, (0xf9400211 | // ldr x17,[x16,#...]
1963 (got
& 0xff8) << 7));
1964 write32le(p
+ 12, (0x91000210 | // add x16,x16,#...
1965 (got
& 0xfff) << 10));
1966 write32le(p
+ 16, 0xd61f0220); // br x17
1967 write32le(p
+ 20, 0xd503201f); // nop
1968 write32le(p
+ 24, 0xd503201f); // nop
1969 write32le(p
+ 28, 0xd503201f); // nop
1972 uint64_t pc
= plt
+ (p
- s1
->plt
->data
);
1973 uint64_t addr
= got
+ read64le(p
);
1974 uint64_t off
= (addr
>> 12) - (pc
>> 12);
1975 if ((off
+ ((uint32_t)1 << 20)) >> 21)
1976 tcc_error("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", off
, addr
, pc
);
1977 write32le(p
, (0x90000010 | // adrp x16,...
1978 (off
& 0x1ffffc) << 3 | (off
& 3) << 29));
1979 write32le(p
+ 4, (0xf9400211 | // ldr x17,[x16,#...]
1980 (addr
& 0xff8) << 7));
1981 write32le(p
+ 8, (0x91000210 | // add x16,x16,#...
1982 (addr
& 0xfff) << 10));
1983 write32le(p
+ 12, 0xd61f0220); // br x17
1986 #elif defined(TCC_TARGET_C67)
1989 #error unsupported CPU
1994 /* Allocate strings for section names and decide if an unallocated section
1997 NOTE: the strsec section comes last, so its size is also correct ! */
1998 static void alloc_sec_names(TCCState
*s1
, int file_type
, Section
*strsec
)
2003 /* Allocate strings for section names */
2004 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2005 s
= s1
->sections
[i
];
2006 s
->sh_name
= put_elf_str(strsec
, s
->name
);
2007 /* when generating a DLL, we include relocations but we may
2009 if (file_type
== TCC_OUTPUT_DLL
&&
2010 s
->sh_type
== SHT_RELX
&&
2011 !(s
->sh_flags
& SHF_ALLOC
)) {
2012 /* gr: avoid bogus relocs for empty (debug) sections */
2013 if (s1
->sections
[s
->sh_info
]->sh_flags
& SHF_ALLOC
)
2014 prepare_dynamic_rel(s1
, s
);
2015 else if (s1
->do_debug
)
2016 s
->sh_size
= s
->data_offset
;
2017 } else if (s1
->do_debug
||
2018 file_type
== TCC_OUTPUT_OBJ
||
2019 (s
->sh_flags
& SHF_ALLOC
) ||
2020 i
== (s1
->nb_sections
- 1)) {
2021 /* we output all sections if debug or object file */
2022 s
->sh_size
= s
->data_offset
;
2027 /* Info to be copied in dynamic section */
2031 unsigned long dyn_rel_off
;
2034 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2040 /* Assign sections to segments and decide how are sections laid out when loaded
2041 in memory. This function also fills corresponding program headers. */
2042 static int layout_sections(TCCState
*s1
, ElfW(Phdr
) *phdr
, int phnum
,
2043 Section
*interp
, Section
* strsec
,
2044 struct dyn_inf
*dyninf
, int *sec_order
)
2046 int i
, j
, k
, file_type
, sh_order_index
, file_offset
;
2047 unsigned long s_align
;
2053 file_type
= s1
->output_type
;
2056 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
)
2057 file_offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
2058 s_align
= ELF_PAGE_SIZE
;
2059 if (s1
->section_align
)
2060 s_align
= s1
->section_align
;
2063 if (s1
->has_text_addr
) {
2064 int a_offset
, p_offset
;
2065 addr
= s1
->text_addr
;
2066 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
2068 a_offset
= (int) (addr
& (s_align
- 1));
2069 p_offset
= file_offset
& (s_align
- 1);
2070 if (a_offset
< p_offset
)
2071 a_offset
+= s_align
;
2072 file_offset
+= (a_offset
- p_offset
);
2074 if (file_type
== TCC_OUTPUT_DLL
)
2077 addr
= ELF_START_ADDR
;
2078 /* compute address after headers */
2079 addr
+= (file_offset
& (s_align
- 1));
2083 /* Leave one program headers for the program interpreter and one for
2084 the program header table itself if needed. These are done later as
2085 they require section layout to be done first. */
2087 ph
+= 1 + HAVE_PHDR
;
2089 /* dynamic relocation table information, for .dynamic section */
2090 dyninf
->rel_addr
= dyninf
->rel_size
= 0;
2091 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2092 dyninf
->bss_addr
= dyninf
->bss_size
= 0;
2095 for(j
= 0; j
< 2; j
++) {
2096 ph
->p_type
= PT_LOAD
;
2098 ph
->p_flags
= PF_R
| PF_X
;
2100 ph
->p_flags
= PF_R
| PF_W
;
2101 ph
->p_align
= s_align
;
2103 /* Decide the layout of sections loaded in memory. This must
2104 be done before program headers are filled since they contain
2105 info about the layout. We do the following ordering: interp,
2106 symbol tables, relocations, progbits, nobits */
2107 /* XXX: do faster and simpler sorting */
2108 for(k
= 0; k
< 5; k
++) {
2109 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2110 s
= s1
->sections
[i
];
2111 /* compute if section should be included */
2113 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
2117 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
2118 (SHF_ALLOC
| SHF_WRITE
))
2124 } else if (s
->sh_type
== SHT_DYNSYM
||
2125 s
->sh_type
== SHT_STRTAB
||
2126 s
->sh_type
== SHT_HASH
) {
2129 } else if (s
->sh_type
== SHT_RELX
) {
2132 } else if (s
->sh_type
== SHT_NOBITS
) {
2139 sec_order
[sh_order_index
++] = i
;
2141 /* section matches: we align it and add its size */
2143 addr
= (addr
+ s
->sh_addralign
- 1) &
2144 ~(s
->sh_addralign
- 1);
2145 file_offset
+= (int) ( addr
- tmp
);
2146 s
->sh_offset
= file_offset
;
2149 /* update program header infos */
2150 if (ph
->p_offset
== 0) {
2151 ph
->p_offset
= file_offset
;
2153 ph
->p_paddr
= ph
->p_vaddr
;
2155 /* update dynamic relocation infos */
2156 if (s
->sh_type
== SHT_RELX
) {
2157 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2158 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.got")) {
2159 dyninf
->rel_addr
= addr
;
2160 dyninf
->rel_size
+= s
->sh_size
; /* XXX only first rel. */
2162 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.bss")) {
2163 dyninf
->bss_addr
= addr
;
2164 dyninf
->bss_size
= s
->sh_size
; /* XXX only first rel. */
2167 if (dyninf
->rel_size
== 0)
2168 dyninf
->rel_addr
= addr
;
2169 dyninf
->rel_size
+= s
->sh_size
;
2173 if (s
->sh_type
!= SHT_NOBITS
)
2174 file_offset
+= s
->sh_size
;
2178 /* Make the first PT_LOAD segment include the program
2179 headers itself (and the ELF header as well), it'll
2180 come out with same memory use but will make various
2181 tools like binutils strip work better. */
2182 ph
->p_offset
&= ~(ph
->p_align
- 1);
2183 ph
->p_vaddr
&= ~(ph
->p_align
- 1);
2184 ph
->p_paddr
&= ~(ph
->p_align
- 1);
2186 ph
->p_filesz
= file_offset
- ph
->p_offset
;
2187 ph
->p_memsz
= addr
- ph
->p_vaddr
;
2190 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
2191 /* if in the middle of a page, we duplicate the page in
2192 memory so that one copy is RX and the other is RW */
2193 if ((addr
& (s_align
- 1)) != 0)
2196 addr
= (addr
+ s_align
- 1) & ~(s_align
- 1);
2197 file_offset
= (file_offset
+ s_align
- 1) & ~(s_align
- 1);
2203 /* all other sections come after */
2204 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2205 s
= s1
->sections
[i
];
2206 if (phnum
> 0 && (s
->sh_flags
& SHF_ALLOC
))
2208 sec_order
[sh_order_index
++] = i
;
2210 file_offset
= (file_offset
+ s
->sh_addralign
- 1) &
2211 ~(s
->sh_addralign
- 1);
2212 s
->sh_offset
= file_offset
;
2213 if (s
->sh_type
!= SHT_NOBITS
)
2214 file_offset
+= s
->sh_size
;
2220 static void fill_unloadable_phdr(ElfW(Phdr
) *phdr
, int phnum
, Section
*interp
,
2225 /* if interpreter, then add corresponding program header */
2231 int len
= phnum
* sizeof(ElfW(Phdr
));
2233 ph
->p_type
= PT_PHDR
;
2234 ph
->p_offset
= sizeof(ElfW(Ehdr
));
2235 ph
->p_vaddr
= interp
->sh_addr
- len
;
2236 ph
->p_paddr
= ph
->p_vaddr
;
2237 ph
->p_filesz
= ph
->p_memsz
= len
;
2238 ph
->p_flags
= PF_R
| PF_X
;
2239 ph
->p_align
= 4; /* interp->sh_addralign; */
2243 ph
->p_type
= PT_INTERP
;
2244 ph
->p_offset
= interp
->sh_offset
;
2245 ph
->p_vaddr
= interp
->sh_addr
;
2246 ph
->p_paddr
= ph
->p_vaddr
;
2247 ph
->p_filesz
= interp
->sh_size
;
2248 ph
->p_memsz
= interp
->sh_size
;
2250 ph
->p_align
= interp
->sh_addralign
;
2253 /* if dynamic section, then add corresponding program header */
2255 ph
= &phdr
[phnum
- 1];
2257 ph
->p_type
= PT_DYNAMIC
;
2258 ph
->p_offset
= dynamic
->sh_offset
;
2259 ph
->p_vaddr
= dynamic
->sh_addr
;
2260 ph
->p_paddr
= ph
->p_vaddr
;
2261 ph
->p_filesz
= dynamic
->sh_size
;
2262 ph
->p_memsz
= dynamic
->sh_size
;
2263 ph
->p_flags
= PF_R
| PF_W
;
2264 ph
->p_align
= dynamic
->sh_addralign
;
2268 /* Fill the dynamic section with tags describing the address and size of
2270 static void fill_dynamic(TCCState
*s1
, struct dyn_inf
*dyninf
)
2274 dynamic
= dyninf
->dynamic
;
2276 /* put dynamic section entries */
2277 dynamic
->data_offset
= dyninf
->dyn_rel_off
;
2278 put_dt(dynamic
, DT_HASH
, s1
->dynsym
->hash
->sh_addr
);
2279 put_dt(dynamic
, DT_STRTAB
, dyninf
->dynstr
->sh_addr
);
2280 put_dt(dynamic
, DT_SYMTAB
, s1
->dynsym
->sh_addr
);
2281 put_dt(dynamic
, DT_STRSZ
, dyninf
->dynstr
->data_offset
);
2282 put_dt(dynamic
, DT_SYMENT
, sizeof(ElfW(Sym
)));
2283 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
2284 put_dt(dynamic
, DT_RELA
, dyninf
->rel_addr
);
2285 put_dt(dynamic
, DT_RELASZ
, dyninf
->rel_size
);
2286 put_dt(dynamic
, DT_RELAENT
, sizeof(ElfW_Rel
));
2288 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2289 put_dt(dynamic
, DT_PLTGOT
, s1
->got
->sh_addr
);
2290 put_dt(dynamic
, DT_PLTRELSZ
, dyninf
->rel_size
);
2291 put_dt(dynamic
, DT_JMPREL
, dyninf
->rel_addr
);
2292 put_dt(dynamic
, DT_PLTREL
, DT_REL
);
2293 put_dt(dynamic
, DT_REL
, dyninf
->bss_addr
);
2294 put_dt(dynamic
, DT_RELSZ
, dyninf
->bss_size
);
2296 put_dt(dynamic
, DT_REL
, dyninf
->rel_addr
);
2297 put_dt(dynamic
, DT_RELSZ
, dyninf
->rel_size
);
2298 put_dt(dynamic
, DT_RELENT
, sizeof(ElfW_Rel
));
2302 put_dt(dynamic
, DT_DEBUG
, 0);
2303 put_dt(dynamic
, DT_NULL
, 0);
2306 /* Relocate remaining sections and symbols (that is those not related to
2308 static int final_sections_reloc(TCCState
*s1
)
2313 relocate_syms(s1
, 0);
2315 if (s1
->nb_errors
!= 0)
2318 /* relocate sections */
2319 /* XXX: ignore sections with allocated relocations ? */
2320 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2321 s
= s1
->sections
[i
];
2322 #ifdef TCC_TARGET_I386
2323 if (s
->reloc
&& s
!= s1
->got
&& (s
->sh_flags
& SHF_ALLOC
)) //gr
2324 /* On X86 gdb 7.3 works in any case but gdb 6.6 will crash if SHF_ALLOC
2325 checking is removed */
2327 if (s
->reloc
&& s
!= s1
->got
)
2328 /* On X86_64 gdb 7.3 will crash if SHF_ALLOC checking is present */
2330 relocate_section(s1
, s
);
2333 /* relocate relocation entries if the relocation tables are
2334 allocated in the executable */
2335 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2336 s
= s1
->sections
[i
];
2337 if ((s
->sh_flags
& SHF_ALLOC
) &&
2338 s
->sh_type
== SHT_RELX
) {
2339 relocate_rel(s1
, s
);
2345 /* Create an ELF file on disk.
2346 This function handle ELF specific layout requirements */
2347 static void tcc_output_elf(TCCState
*s1
, FILE *f
, int phnum
, ElfW(Phdr
) *phdr
,
2348 int file_offset
, int *sec_order
)
2350 int i
, shnum
, offset
, size
, file_type
;
2353 ElfW(Shdr
) shdr
, *sh
;
2355 file_type
= s1
->output_type
;
2356 shnum
= s1
->nb_sections
;
2358 memset(&ehdr
, 0, sizeof(ehdr
));
2361 ehdr
.e_phentsize
= sizeof(ElfW(Phdr
));
2362 ehdr
.e_phnum
= phnum
;
2363 ehdr
.e_phoff
= sizeof(ElfW(Ehdr
));
2367 file_offset
= (file_offset
+ 3) & -4;
2370 ehdr
.e_ident
[0] = ELFMAG0
;
2371 ehdr
.e_ident
[1] = ELFMAG1
;
2372 ehdr
.e_ident
[2] = ELFMAG2
;
2373 ehdr
.e_ident
[3] = ELFMAG3
;
2374 ehdr
.e_ident
[4] = ELFCLASSW
;
2375 ehdr
.e_ident
[5] = ELFDATA2LSB
;
2376 ehdr
.e_ident
[6] = EV_CURRENT
;
2377 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2378 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_FREEBSD
;
2380 #ifdef TCC_TARGET_ARM
2382 ehdr
.e_ident
[EI_OSABI
] = 0;
2383 ehdr
.e_flags
= EF_ARM_EABI_VER4
;
2384 if (file_type
== TCC_OUTPUT_EXE
|| file_type
== TCC_OUTPUT_DLL
)
2385 ehdr
.e_flags
|= EF_ARM_HASENTRY
;
2386 if (s1
->float_abi
== ARM_HARD_FLOAT
)
2387 ehdr
.e_flags
|= EF_ARM_VFP_FLOAT
;
2389 ehdr
.e_flags
|= EF_ARM_SOFT_FLOAT
;
2391 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_ARM
;
2396 case TCC_OUTPUT_EXE
:
2397 ehdr
.e_type
= ET_EXEC
;
2398 ehdr
.e_entry
= get_elf_sym_addr(s1
, "_start", 1);
2400 case TCC_OUTPUT_DLL
:
2401 ehdr
.e_type
= ET_DYN
;
2402 ehdr
.e_entry
= text_section
->sh_addr
; /* XXX: is it correct ? */
2404 case TCC_OUTPUT_OBJ
:
2405 ehdr
.e_type
= ET_REL
;
2408 ehdr
.e_machine
= EM_TCC_TARGET
;
2409 ehdr
.e_version
= EV_CURRENT
;
2410 ehdr
.e_shoff
= file_offset
;
2411 ehdr
.e_ehsize
= sizeof(ElfW(Ehdr
));
2412 ehdr
.e_shentsize
= sizeof(ElfW(Shdr
));
2413 ehdr
.e_shnum
= shnum
;
2414 ehdr
.e_shstrndx
= shnum
- 1;
2416 fwrite(&ehdr
, 1, sizeof(ElfW(Ehdr
)), f
);
2417 fwrite(phdr
, 1, phnum
* sizeof(ElfW(Phdr
)), f
);
2418 offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
2420 sort_syms(s1
, symtab_section
);
2421 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2422 s
= s1
->sections
[sec_order
[i
]];
2423 if (s
->sh_type
!= SHT_NOBITS
) {
2424 if (s
->sh_type
== SHT_DYNSYM
)
2425 patch_dynsym_undef(s1
, s
);
2426 while (offset
< s
->sh_offset
) {
2432 fwrite(s
->data
, 1, size
, f
);
2437 /* output section headers */
2438 while (offset
< ehdr
.e_shoff
) {
2443 for(i
= 0; i
< s1
->nb_sections
; i
++) {
2445 memset(sh
, 0, sizeof(ElfW(Shdr
)));
2446 s
= s1
->sections
[i
];
2448 sh
->sh_name
= s
->sh_name
;
2449 sh
->sh_type
= s
->sh_type
;
2450 sh
->sh_flags
= s
->sh_flags
;
2451 sh
->sh_entsize
= s
->sh_entsize
;
2452 sh
->sh_info
= s
->sh_info
;
2454 sh
->sh_link
= s
->link
->sh_num
;
2455 sh
->sh_addralign
= s
->sh_addralign
;
2456 sh
->sh_addr
= s
->sh_addr
;
2457 sh
->sh_offset
= s
->sh_offset
;
2458 sh
->sh_size
= s
->sh_size
;
2460 fwrite(sh
, 1, sizeof(ElfW(Shdr
)), f
);
2464 /* Write an elf, coff or "binary" file */
2465 static int tcc_write_elf_file(TCCState
*s1
, const char *filename
, int phnum
,
2466 ElfW(Phdr
) *phdr
, int file_offset
, int *sec_order
)
2468 int fd
, mode
, file_type
;
2471 file_type
= s1
->output_type
;
2472 if (file_type
== TCC_OUTPUT_OBJ
)
2477 fd
= open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
, mode
);
2479 tcc_error_noabort("could not write '%s'", filename
);
2482 f
= fdopen(fd
, "wb");
2484 printf("<- %s\n", filename
);
2486 #ifdef TCC_TARGET_COFF
2487 if (s1
->output_format
== TCC_OUTPUT_FORMAT_COFF
)
2488 tcc_output_coff(s1
, f
);
2491 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
)
2492 tcc_output_elf(s1
, f
, phnum
, phdr
, file_offset
, sec_order
);
2494 tcc_output_binary(s1
, f
, sec_order
);
2500 /* Output an elf, coff or binary file */
2501 /* XXX: suppress unneeded sections */
2502 static int elf_output_file(TCCState
*s1
, const char *filename
)
2504 int i
, ret
, phnum
, shnum
, file_type
, file_offset
, *sec_order
;
2505 struct dyn_inf dyninf
;
2508 Section
*strsec
, *interp
, *dynamic
, *dynstr
;
2510 file_type
= s1
->output_type
;
2513 /* if linking, also link in runtime libraries (libc, libgcc, etc.) */
2514 if (file_type
!= TCC_OUTPUT_OBJ
) {
2515 tcc_add_runtime(s1
);
2520 interp
= dynamic
= dynstr
= NULL
; /* avoid warning */
2521 dyninf
.dyn_rel_off
= 0; /* avoid warning */
2523 if (file_type
!= TCC_OUTPUT_OBJ
) {
2524 relocate_common_syms();
2526 tcc_add_linker_symbols(s1
);
2528 if (!s1
->static_link
) {
2529 if (file_type
== TCC_OUTPUT_EXE
) {
2531 /* allow override the dynamic loader */
2532 const char *elfint
= getenv("LD_SO");
2534 elfint
= DEFAULT_ELFINTERP(s1
);
2535 /* add interpreter section only if executable */
2536 interp
= new_section(s1
, ".interp", SHT_PROGBITS
, SHF_ALLOC
);
2537 interp
->sh_addralign
= 1;
2538 ptr
= section_ptr_add(interp
, 1 + strlen(elfint
));
2539 strcpy(ptr
, elfint
);
2542 /* add dynamic symbol table */
2543 s1
->dynsym
= new_symtab(s1
, ".dynsym", SHT_DYNSYM
, SHF_ALLOC
,
2545 ".hash", SHF_ALLOC
);
2546 dynstr
= s1
->dynsym
->link
;
2548 /* add dynamic section */
2549 dynamic
= new_section(s1
, ".dynamic", SHT_DYNAMIC
,
2550 SHF_ALLOC
| SHF_WRITE
);
2551 dynamic
->link
= dynstr
;
2552 dynamic
->sh_entsize
= sizeof(ElfW(Dyn
));
2556 if (file_type
== TCC_OUTPUT_EXE
) {
2557 bind_exe_dynsyms(s1
);
2559 if (s1
->nb_errors
) {
2564 bind_libs_dynsyms(s1
);
2565 } else /* shared library case: simply export all global symbols */
2566 export_global_syms(s1
);
2568 build_got_entries(s1
);
2570 /* add a list of needed dlls */
2571 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
2572 DLLReference
*dllref
= s1
->loaded_dlls
[i
];
2573 if (dllref
->level
== 0)
2574 put_dt(dynamic
, DT_NEEDED
, put_elf_str(dynstr
, dllref
->name
));
2578 put_dt(dynamic
, DT_RPATH
, put_elf_str(dynstr
, s1
->rpath
));
2580 /* XXX: currently, since we do not handle PIC code, we
2581 must relocate the readonly segments */
2582 if (file_type
== TCC_OUTPUT_DLL
) {
2584 put_dt(dynamic
, DT_SONAME
, put_elf_str(dynstr
, s1
->soname
));
2585 put_dt(dynamic
, DT_TEXTREL
, 0);
2589 put_dt(dynamic
, DT_SYMBOLIC
, 0);
2591 /* add necessary space for other entries */
2592 dyninf
.dyn_rel_off
= dynamic
->data_offset
;
2593 dynamic
->data_offset
+= sizeof(ElfW(Dyn
)) * EXTRA_RELITEMS
;
2595 /* still need to build got entries in case of static link */
2596 build_got_entries(s1
);
2600 /* we add a section for symbols */
2601 strsec
= new_section(s1
, ".shstrtab", SHT_STRTAB
, 0);
2602 put_elf_str(strsec
, "");
2604 /* compute number of sections */
2605 shnum
= s1
->nb_sections
;
2607 /* this array is used to reorder sections in the output file */
2608 sec_order
= tcc_malloc(sizeof(int) * shnum
);
2611 /* compute number of program headers */
2614 case TCC_OUTPUT_OBJ
:
2617 case TCC_OUTPUT_EXE
:
2618 if (!s1
->static_link
)
2619 phnum
= 4 + HAVE_PHDR
;
2623 case TCC_OUTPUT_DLL
:
2628 /* Allocate strings for section names */
2629 alloc_sec_names(s1
, file_type
, strsec
);
2631 /* allocate program segment headers */
2632 phdr
= tcc_mallocz(phnum
* sizeof(ElfW(Phdr
)));
2634 /* compute section to program header mapping */
2635 file_offset
= layout_sections(s1
, phdr
, phnum
, interp
, strsec
, &dyninf
,
2638 /* Fill remaining program header and finalize relocation related to dynamic
2641 fill_unloadable_phdr(phdr
, phnum
, interp
, dynamic
);
2643 dyninf
.dynamic
= dynamic
;
2644 dyninf
.dynstr
= dynstr
;
2646 fill_dynamic(s1
, &dyninf
);
2648 /* put in GOT the dynamic section address and relocate PLT */
2649 write32le(s1
->got
->data
, dynamic
->sh_addr
);
2650 if (file_type
== TCC_OUTPUT_EXE
2651 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2652 || file_type
== TCC_OUTPUT_DLL
2657 /* relocate symbols in .dynsym now that final addresses are known */
2658 for_each_elem(s1
->dynsym
, 1, sym
, ElfW(Sym
)) {
2659 if (sym
->st_shndx
== SHN_UNDEF
) {
2660 /* relocate to PLT if symbol corresponds to a PLT entry,
2661 but not if it's a weak symbol */
2662 if (ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
2664 else if (sym
->st_value
)
2665 sym
->st_value
+= s1
->plt
->sh_addr
;
2666 } else if (sym
->st_shndx
< SHN_LORESERVE
) {
2667 /* do symbol relocation */
2668 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
2674 /* if building executable or DLL, then relocate each section
2675 except the GOT which is already relocated */
2676 if (file_type
!= TCC_OUTPUT_OBJ
) {
2677 ret
= final_sections_reloc(s1
);
2682 /* Perform relocation to GOT or PLT entries */
2683 if (file_type
== TCC_OUTPUT_EXE
&& s1
->static_link
)
2686 /* Create the ELF file with name 'filename' */
2687 ret
= tcc_write_elf_file(s1
, filename
, phnum
, phdr
, file_offset
, sec_order
);
2689 tcc_free(s1
->symtab_to_dynsym
);
2690 tcc_free(sec_order
);
2692 tcc_free(s1
->sym_attrs
);
2693 s1
->sym_attrs
= NULL
;
2697 LIBTCCAPI
int tcc_output_file(TCCState
*s
, const char *filename
)
2700 #ifdef TCC_TARGET_PE
2701 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
2702 ret
= pe_output_file(s
, filename
);
2705 ret
= elf_output_file(s
, filename
);
2709 static void *load_data(int fd
, unsigned long file_offset
, unsigned long size
)
2713 data
= tcc_malloc(size
);
2714 lseek(fd
, file_offset
, SEEK_SET
);
2715 read(fd
, data
, size
);
2719 typedef struct SectionMergeInfo
{
2720 Section
*s
; /* corresponding existing section */
2721 unsigned long offset
; /* offset of the new section in the existing section */
2722 uint8_t new_section
; /* true if section 's' was added */
2723 uint8_t link_once
; /* true if link once section */
2726 ST_FUNC
int tcc_object_type(int fd
, ElfW(Ehdr
) *h
)
2728 int size
= read(fd
, h
, sizeof *h
);
2729 if (size
== sizeof *h
&& 0 == memcmp(h
, ELFMAG
, 4)) {
2730 if (h
->e_type
== ET_REL
)
2731 return AFF_BINTYPE_REL
;
2732 if (h
->e_type
== ET_DYN
)
2733 return AFF_BINTYPE_DYN
;
2734 } else if (size
>= 8) {
2735 if (0 == memcmp(h
, ARMAG
, 8))
2736 return AFF_BINTYPE_AR
;
2737 #ifdef TCC_TARGET_COFF
2738 if (((struct filehdr
*)h
)->f_magic
== COFF_C67_MAGIC
)
2739 return AFF_BINTYPE_C67
;
2745 /* load an object file and merge it with current files */
2746 /* XXX: handle correctly stab (debug) info */
2747 ST_FUNC
int tcc_load_object_file(TCCState
*s1
,
2748 int fd
, unsigned long file_offset
)
2751 ElfW(Shdr
) *shdr
, *sh
;
2752 int size
, i
, j
, offset
, offseti
, nb_syms
, sym_index
, ret
;
2753 unsigned char *strsec
, *strtab
;
2754 int *old_to_new_syms
;
2755 char *sh_name
, *name
;
2756 SectionMergeInfo
*sm_table
, *sm
;
2757 ElfW(Sym
) *sym
, *symtab
;
2764 stab_index
= stabstr_index
= 0;
2766 lseek(fd
, file_offset
, SEEK_SET
);
2767 if (tcc_object_type(fd
, &ehdr
) != AFF_BINTYPE_REL
)
2769 /* test CPU specific stuff */
2770 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2771 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2773 tcc_error_noabort("invalid object file");
2777 shdr
= load_data(fd
, file_offset
+ ehdr
.e_shoff
,
2778 sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2779 sm_table
= tcc_mallocz(sizeof(SectionMergeInfo
) * ehdr
.e_shnum
);
2781 /* load section names */
2782 sh
= &shdr
[ehdr
.e_shstrndx
];
2783 strsec
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2785 /* load symtab and strtab */
2786 old_to_new_syms
= NULL
;
2790 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2792 if (sh
->sh_type
== SHT_SYMTAB
) {
2794 tcc_error_noabort("object must contain only one symtab");
2799 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2800 symtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2801 sm_table
[i
].s
= symtab_section
;
2803 /* now load strtab */
2804 sh
= &shdr
[sh
->sh_link
];
2805 strtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2809 /* now examine each section and try to merge its content with the
2811 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2812 /* no need to examine section name strtab */
2813 if (i
== ehdr
.e_shstrndx
)
2816 sh_name
= (char *) strsec
+ sh
->sh_name
;
2817 /* ignore sections types we do not handle */
2818 if (sh
->sh_type
!= SHT_PROGBITS
&&
2819 sh
->sh_type
!= SHT_RELX
&&
2821 sh
->sh_type
!= SHT_ARM_EXIDX
&&
2823 sh
->sh_type
!= SHT_NOBITS
&&
2824 sh
->sh_type
!= SHT_PREINIT_ARRAY
&&
2825 sh
->sh_type
!= SHT_INIT_ARRAY
&&
2826 sh
->sh_type
!= SHT_FINI_ARRAY
&&
2827 strcmp(sh_name
, ".stabstr")
2830 if (sh
->sh_addralign
< 1)
2831 sh
->sh_addralign
= 1;
2832 /* find corresponding section, if any */
2833 for(j
= 1; j
< s1
->nb_sections
;j
++) {
2834 s
= s1
->sections
[j
];
2835 if (!strcmp(s
->name
, sh_name
)) {
2836 if (!strncmp(sh_name
, ".gnu.linkonce",
2837 sizeof(".gnu.linkonce") - 1)) {
2838 /* if a 'linkonce' section is already present, we
2839 do not add it again. It is a little tricky as
2840 symbols can still be defined in
2842 sm_table
[i
].link_once
= 1;
2849 /* not found: create new section */
2850 s
= new_section(s1
, sh_name
, sh
->sh_type
, sh
->sh_flags
);
2851 /* take as much info as possible from the section. sh_link and
2852 sh_info will be updated later */
2853 s
->sh_addralign
= sh
->sh_addralign
;
2854 s
->sh_entsize
= sh
->sh_entsize
;
2855 sm_table
[i
].new_section
= 1;
2857 if (sh
->sh_type
!= s
->sh_type
) {
2858 tcc_error_noabort("invalid section type");
2862 /* align start of section */
2863 offset
= s
->data_offset
;
2865 if (0 == strcmp(sh_name
, ".stab")) {
2869 if (0 == strcmp(sh_name
, ".stabstr")) {
2874 size
= sh
->sh_addralign
- 1;
2875 offset
= (offset
+ size
) & ~size
;
2876 if (sh
->sh_addralign
> s
->sh_addralign
)
2877 s
->sh_addralign
= sh
->sh_addralign
;
2878 s
->data_offset
= offset
;
2880 sm_table
[i
].offset
= offset
;
2882 /* concatenate sections */
2884 if (sh
->sh_type
!= SHT_NOBITS
) {
2886 lseek(fd
, file_offset
+ sh
->sh_offset
, SEEK_SET
);
2887 ptr
= section_ptr_add(s
, size
);
2888 read(fd
, ptr
, size
);
2890 s
->data_offset
+= size
;
2895 /* gr relocate stab strings */
2896 if (stab_index
&& stabstr_index
) {
2899 s
= sm_table
[stab_index
].s
;
2900 a
= (Stab_Sym
*)(s
->data
+ sm_table
[stab_index
].offset
);
2901 b
= (Stab_Sym
*)(s
->data
+ s
->data_offset
);
2902 o
= sm_table
[stabstr_index
].offset
;
2904 a
->n_strx
+= o
, a
++;
2907 /* second short pass to update sh_link and sh_info fields of new
2909 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2911 if (!s
|| !sm_table
[i
].new_section
)
2914 if (sh
->sh_link
> 0)
2915 s
->link
= sm_table
[sh
->sh_link
].s
;
2916 if (sh
->sh_type
== SHT_RELX
) {
2917 s
->sh_info
= sm_table
[sh
->sh_info
].s
->sh_num
;
2918 /* update backward link */
2919 s1
->sections
[s
->sh_info
]->reloc
= s
;
2924 /* resolve symbols */
2925 old_to_new_syms
= tcc_mallocz(nb_syms
* sizeof(int));
2928 for(i
= 1; i
< nb_syms
; i
++, sym
++) {
2929 if (sym
->st_shndx
!= SHN_UNDEF
&&
2930 sym
->st_shndx
< SHN_LORESERVE
) {
2931 sm
= &sm_table
[sym
->st_shndx
];
2932 if (sm
->link_once
) {
2933 /* if a symbol is in a link once section, we use the
2934 already defined symbol. It is very important to get
2935 correct relocations */
2936 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
2937 name
= (char *) strtab
+ sym
->st_name
;
2938 sym_index
= find_elf_sym(symtab_section
, name
);
2940 old_to_new_syms
[i
] = sym_index
;
2944 /* if no corresponding section added, no need to add symbol */
2947 /* convert section number */
2948 sym
->st_shndx
= sm
->s
->sh_num
;
2950 sym
->st_value
+= sm
->offset
;
2953 name
= (char *) strtab
+ sym
->st_name
;
2954 sym_index
= add_elf_sym(symtab_section
, sym
->st_value
, sym
->st_size
,
2955 sym
->st_info
, sym
->st_other
,
2956 sym
->st_shndx
, name
);
2957 old_to_new_syms
[i
] = sym_index
;
2960 /* third pass to patch relocation entries */
2961 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2966 offset
= sm_table
[i
].offset
;
2967 switch(s
->sh_type
) {
2969 /* take relocation offset information */
2970 offseti
= sm_table
[sh
->sh_info
].offset
;
2971 for_each_elem(s
, (offset
/ sizeof(*rel
)), rel
, ElfW_Rel
) {
2974 /* convert symbol index */
2975 type
= ELFW(R_TYPE
)(rel
->r_info
);
2976 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
2977 /* NOTE: only one symtab assumed */
2978 if (sym_index
>= nb_syms
)
2980 sym_index
= old_to_new_syms
[sym_index
];
2981 /* ignore link_once in rel section. */
2982 if (!sym_index
&& !sm
->link_once
2983 #ifdef TCC_TARGET_ARM
2984 && type
!= R_ARM_V4BX
2988 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2989 i
, strsec
+ sh
->sh_name
, rel
->r_offset
);
2992 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
2993 /* offset the relocation offset */
2994 rel
->r_offset
+= offseti
;
2995 #ifdef TCC_TARGET_ARM
2996 /* Jumps and branches from a Thumb code to a PLT entry need
2997 special handling since PLT entries are ARM code.
2998 Unconditional bl instructions referencing PLT entries are
2999 handled by converting these instructions into blx
3000 instructions. Other case of instructions referencing a PLT
3001 entry require to add a Thumb stub before the PLT entry to
3002 switch to ARM mode. We set bit plt_thumb_stub of the
3003 attribute of a symbol to indicate such a case. */
3004 if (type
== R_ARM_THM_JUMP24
)
3005 alloc_sym_attr(s1
, sym_index
)->plt_thumb_stub
= 1;
3018 tcc_free(old_to_new_syms
);
3025 typedef struct ArchiveHeader
{
3026 char ar_name
[16]; /* name of this member */
3027 char ar_date
[12]; /* file mtime */
3028 char ar_uid
[6]; /* owner uid; printed as decimal */
3029 char ar_gid
[6]; /* owner gid; printed as decimal */
3030 char ar_mode
[8]; /* file mode, printed as octal */
3031 char ar_size
[10]; /* file size, printed as decimal */
3032 char ar_fmag
[2]; /* should contain ARFMAG */
3035 static int get_be32(const uint8_t *b
)
3037 return b
[3] | (b
[2] << 8) | (b
[1] << 16) | (b
[0] << 24);
3040 /* load only the objects which resolve undefined symbols */
3041 static int tcc_load_alacarte(TCCState
*s1
, int fd
, int size
)
3043 int i
, bound
, nsyms
, sym_index
, off
, ret
;
3045 const char *ar_names
, *p
;
3046 const uint8_t *ar_index
;
3049 data
= tcc_malloc(size
);
3050 if (read(fd
, data
, size
) != size
)
3052 nsyms
= get_be32(data
);
3053 ar_index
= data
+ 4;
3054 ar_names
= (char *) ar_index
+ nsyms
* 4;
3058 for(p
= ar_names
, i
= 0; i
< nsyms
; i
++, p
+= strlen(p
)+1) {
3059 sym_index
= find_elf_sym(symtab_section
, p
);
3061 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
3062 if(sym
->st_shndx
== SHN_UNDEF
) {
3063 off
= get_be32(ar_index
+ i
* 4) + sizeof(ArchiveHeader
);
3065 if(tcc_load_object_file(s1
, fd
, off
) < 0) {
3080 /* load a '.a' file */
3081 ST_FUNC
int tcc_load_archive(TCCState
*s1
, int fd
)
3088 unsigned long file_offset
;
3090 /* skip magic which was already checked */
3091 read(fd
, magic
, sizeof(magic
));
3094 len
= read(fd
, &hdr
, sizeof(hdr
));
3097 if (len
!= sizeof(hdr
)) {
3098 tcc_error_noabort("invalid archive");
3101 memcpy(ar_size
, hdr
.ar_size
, sizeof(hdr
.ar_size
));
3102 ar_size
[sizeof(hdr
.ar_size
)] = '\0';
3103 size
= strtol(ar_size
, NULL
, 0);
3104 memcpy(ar_name
, hdr
.ar_name
, sizeof(hdr
.ar_name
));
3105 for(i
= sizeof(hdr
.ar_name
) - 1; i
>= 0; i
--) {
3106 if (ar_name
[i
] != ' ')
3109 ar_name
[i
+ 1] = '\0';
3110 file_offset
= lseek(fd
, 0, SEEK_CUR
);
3112 size
= (size
+ 1) & ~1;
3113 if (!strcmp(ar_name
, "/")) {
3114 /* coff symbol table : we handle it */
3115 if(s1
->alacarte_link
)
3116 return tcc_load_alacarte(s1
, fd
, size
);
3119 if (tcc_object_type(fd
, &ehdr
) == AFF_BINTYPE_REL
) {
3120 if (tcc_load_object_file(s1
, fd
, file_offset
) < 0)
3124 lseek(fd
, file_offset
+ size
, SEEK_SET
);
3129 #ifndef TCC_TARGET_PE
3130 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
3131 is referenced by the user (so it should be added as DT_NEEDED in
3132 the generated ELF file) */
3133 ST_FUNC
int tcc_load_dll(TCCState
*s1
, int fd
, const char *filename
, int level
)
3136 ElfW(Shdr
) *shdr
, *sh
, *sh1
;
3137 int i
, j
, nb_syms
, nb_dts
, sym_bind
, ret
;
3138 ElfW(Sym
) *sym
, *dynsym
;
3139 ElfW(Dyn
) *dt
, *dynamic
;
3140 unsigned char *dynstr
;
3141 const char *name
, *soname
;
3142 DLLReference
*dllref
;
3144 read(fd
, &ehdr
, sizeof(ehdr
));
3146 /* test CPU specific stuff */
3147 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
3148 ehdr
.e_machine
!= EM_TCC_TARGET
) {
3149 tcc_error_noabort("bad architecture");
3154 shdr
= load_data(fd
, ehdr
.e_shoff
, sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
3156 /* load dynamic section and dynamic symbols */
3160 dynsym
= NULL
; /* avoid warning */
3161 dynstr
= NULL
; /* avoid warning */
3162 for(i
= 0, sh
= shdr
; i
< ehdr
.e_shnum
; i
++, sh
++) {
3163 switch(sh
->sh_type
) {
3165 nb_dts
= sh
->sh_size
/ sizeof(ElfW(Dyn
));
3166 dynamic
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
3169 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
3170 dynsym
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
3171 sh1
= &shdr
[sh
->sh_link
];
3172 dynstr
= load_data(fd
, sh1
->sh_offset
, sh1
->sh_size
);
3179 /* compute the real library name */
3180 soname
= tcc_basename(filename
);
3182 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
3183 if (dt
->d_tag
== DT_SONAME
) {
3184 soname
= (char *) dynstr
+ dt
->d_un
.d_val
;
3188 /* if the dll is already loaded, do not load it */
3189 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
3190 dllref
= s1
->loaded_dlls
[i
];
3191 if (!strcmp(soname
, dllref
->name
)) {
3192 /* but update level if needed */
3193 if (level
< dllref
->level
)
3194 dllref
->level
= level
;
3200 /* add the dll and its level */
3201 dllref
= tcc_mallocz(sizeof(DLLReference
) + strlen(soname
));
3202 dllref
->level
= level
;
3203 strcpy(dllref
->name
, soname
);
3204 dynarray_add((void ***)&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
, dllref
);
3206 /* add dynamic symbols in dynsym_section */
3207 for(i
= 1, sym
= dynsym
+ 1; i
< nb_syms
; i
++, sym
++) {
3208 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
3209 if (sym_bind
== STB_LOCAL
)
3211 name
= (char *) dynstr
+ sym
->st_name
;
3212 add_elf_sym(s1
->dynsymtab_section
, sym
->st_value
, sym
->st_size
,
3213 sym
->st_info
, sym
->st_other
, sym
->st_shndx
, name
);
3216 /* load all referenced DLLs */
3217 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
3220 name
= (char *) dynstr
+ dt
->d_un
.d_val
;
3221 for(j
= 0; j
< s1
->nb_loaded_dlls
; j
++) {
3222 dllref
= s1
->loaded_dlls
[j
];
3223 if (!strcmp(name
, dllref
->name
))
3224 goto already_loaded
;
3226 if (tcc_add_dll(s1
, name
, AFF_REFERENCED_DLL
) < 0) {
3227 tcc_error_noabort("referenced dll '%s' not found", name
);
3244 #define LD_TOK_NAME 256
3245 #define LD_TOK_EOF (-1)
3247 /* return next ld script token */
3248 static int ld_next(TCCState
*s1
, char *name
, int name_size
)
3266 file
->buf_ptr
= parse_comment(file
->buf_ptr
);
3267 ch
= file
->buf_ptr
[0];
3280 /* case 'a' ... 'z': */
3307 /* case 'A' ... 'z': */
3341 if (!((ch
>= 'a' && ch
<= 'z') ||
3342 (ch
>= 'A' && ch
<= 'Z') ||
3343 (ch
>= '0' && ch
<= '9') ||
3344 strchr("/.-_+=$:\\,~", ch
)))
3346 if ((q
- name
) < name_size
- 1) {
3365 static int ld_add_file(TCCState
*s1
, const char filename
[])
3369 ret
= tcc_add_file_internal(s1
, filename
, AFF_TYPE_BIN
);
3371 ret
= tcc_add_dll(s1
, filename
, 0);
3375 static inline int new_undef_syms(void)
3378 ret
= new_undef_sym
;
3383 static int ld_add_file_list(TCCState
*s1
, const char *cmd
, int as_needed
)
3385 char filename
[1024], libname
[1024];
3386 int t
, group
, nblibs
= 0, ret
= 0;
3389 group
= !strcmp(cmd
, "GROUP");
3392 t
= ld_next(s1
, filename
, sizeof(filename
));
3395 t
= ld_next(s1
, filename
, sizeof(filename
));
3398 if (t
== LD_TOK_EOF
) {
3399 tcc_error_noabort("unexpected end of file");
3401 goto lib_parse_error
;
3402 } else if (t
== ')') {
3404 } else if (t
== '-') {
3405 t
= ld_next(s1
, filename
, sizeof(filename
));
3406 if ((t
!= LD_TOK_NAME
) || (filename
[0] != 'l')) {
3407 tcc_error_noabort("library name expected");
3409 goto lib_parse_error
;
3411 pstrcpy(libname
, sizeof libname
, &filename
[1]);
3412 if (s1
->static_link
) {
3413 snprintf(filename
, sizeof filename
, "lib%s.a", libname
);
3415 snprintf(filename
, sizeof filename
, "lib%s.so", libname
);
3417 } else if (t
!= LD_TOK_NAME
) {
3418 tcc_error_noabort("filename expected");
3420 goto lib_parse_error
;
3422 if (!strcmp(filename
, "AS_NEEDED")) {
3423 ret
= ld_add_file_list(s1
, cmd
, 1);
3425 goto lib_parse_error
;
3427 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3429 ret
= ld_add_file(s1
, filename
);
3431 goto lib_parse_error
;
3433 /* Add the filename *and* the libname to avoid future conversions */
3434 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(filename
));
3435 if (libname
[0] != '\0')
3436 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(libname
));
3440 t
= ld_next(s1
, filename
, sizeof(filename
));
3442 t
= ld_next(s1
, filename
, sizeof(filename
));
3445 if (group
&& !as_needed
) {
3446 while (new_undef_syms()) {
3449 for (i
= 0; i
< nblibs
; i
++)
3450 ld_add_file(s1
, libs
[i
]);
3454 dynarray_reset(&libs
, &nblibs
);
3458 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3460 ST_FUNC
int tcc_load_ldscript(TCCState
*s1
)
3463 char filename
[1024];
3468 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3469 if (t
== LD_TOK_EOF
)
3471 else if (t
!= LD_TOK_NAME
)
3473 if (!strcmp(cmd
, "INPUT") ||
3474 !strcmp(cmd
, "GROUP")) {
3475 ret
= ld_add_file_list(s1
, cmd
, 0);
3478 } else if (!strcmp(cmd
, "OUTPUT_FORMAT") ||
3479 !strcmp(cmd
, "TARGET")) {
3480 /* ignore some commands */
3481 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3485 t
= ld_next(s1
, filename
, sizeof(filename
));
3486 if (t
== LD_TOK_EOF
) {
3487 tcc_error_noabort("unexpected end of file");
3489 } else if (t
== ')') {
3499 #endif /* !TCC_TARGET_PE */