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 static int new_undef_sym
= 0; /* Is there a new undefined sym since last new_undef_sym() */
25 ST_FUNC
int put_elf_str(Section
*s
, const char *sym
)
30 len
= strlen(sym
) + 1;
31 offset
= s
->data_offset
;
32 ptr
= section_ptr_add(s
, len
);
33 memcpy(ptr
, sym
, len
);
37 /* elf symbol hashing function */
38 static unsigned long elf_hash(const unsigned char *name
)
40 unsigned long h
= 0, g
;
43 h
= (h
<< 4) + *name
++;
52 /* rebuild hash table of section s */
53 /* NOTE: we do factorize the hash table code to go faster */
54 static void rebuild_hash(Section
*s
, unsigned int nb_buckets
)
57 int *ptr
, *hash
, nb_syms
, sym_index
, h
;
60 strtab
= s
->link
->data
;
61 nb_syms
= s
->data_offset
/ sizeof(ElfW(Sym
));
63 s
->hash
->data_offset
= 0;
64 ptr
= section_ptr_add(s
->hash
, (2 + nb_buckets
+ nb_syms
) * sizeof(int));
69 memset(hash
, 0, (nb_buckets
+ 1) * sizeof(int));
70 ptr
+= nb_buckets
+ 1;
72 sym
= (ElfW(Sym
) *)s
->data
+ 1;
73 for(sym_index
= 1; sym_index
< nb_syms
; sym_index
++) {
74 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
75 h
= elf_hash(strtab
+ sym
->st_name
) % nb_buckets
;
86 /* return the symbol number */
87 ST_FUNC
int put_elf_sym(Section
*s
, uplong value
, unsigned long size
,
88 int info
, int other
, int shndx
, const char *name
)
90 int name_offset
, sym_index
;
95 sym
= section_ptr_add(s
, sizeof(ElfW(Sym
)));
97 name_offset
= put_elf_str(s
->link
, name
);
100 /* XXX: endianness */
101 sym
->st_name
= name_offset
;
102 sym
->st_value
= value
;
105 sym
->st_other
= other
;
106 sym
->st_shndx
= shndx
;
107 sym_index
= sym
- (ElfW(Sym
) *)s
->data
;
111 ptr
= section_ptr_add(hs
, sizeof(int));
112 base
= (int *)hs
->data
;
113 /* only add global or weak symbols */
114 if (ELFW(ST_BIND
)(info
) != STB_LOCAL
) {
115 /* add another hashing entry */
117 h
= elf_hash(name
) % nbuckets
;
119 base
[2 + h
] = sym_index
;
121 /* we resize the hash table */
122 hs
->nb_hashed_syms
++;
123 if (hs
->nb_hashed_syms
> 2 * nbuckets
) {
124 rebuild_hash(s
, 2 * nbuckets
);
134 /* find global ELF symbol 'name' and return its index. Return 0 if not
136 ST_FUNC
int find_elf_sym(Section
*s
, const char *name
)
140 int nbuckets
, sym_index
, h
;
146 nbuckets
= ((int *)hs
->data
)[0];
147 h
= elf_hash(name
) % nbuckets
;
148 sym_index
= ((int *)hs
->data
)[2 + h
];
149 while (sym_index
!= 0) {
150 sym
= &((ElfW(Sym
) *)s
->data
)[sym_index
];
151 name1
= s
->link
->data
+ sym
->st_name
;
152 if (!strcmp(name
, name1
))
154 sym_index
= ((int *)hs
->data
)[2 + nbuckets
+ sym_index
];
159 /* return elf symbol value, signal error if 'err' is nonzero */
160 static void *get_elf_sym_addr(TCCState
*s
, const char *name
, int err
)
165 sym_index
= find_elf_sym(symtab_section
, name
);
166 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
167 if (!sym_index
|| sym
->st_shndx
== SHN_UNDEF
) {
169 tcc_error("%s not defined", name
);
172 return (void*)(uplong
)sym
->st_value
;
175 /* return elf symbol value */
176 LIBTCCAPI
void *tcc_get_symbol(TCCState
*s
, const char *name
)
178 return get_elf_sym_addr(s
, name
, 0);
181 /* return elf symbol value or error */
182 ST_FUNC
void *tcc_get_symbol_err(TCCState
*s
, const char *name
)
184 return get_elf_sym_addr(s
, name
, 1);
187 /* add an elf symbol : check if it is already defined and patch
188 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
189 ST_FUNC
int add_elf_sym(Section
*s
, uplong value
, unsigned long size
,
190 int info
, int other
, int sh_num
, const char *name
)
193 int sym_bind
, sym_index
, sym_type
, esym_bind
;
194 unsigned char sym_vis
, esym_vis
, new_vis
;
196 sym_bind
= ELFW(ST_BIND
)(info
);
197 sym_type
= ELFW(ST_TYPE
)(info
);
198 sym_vis
= ELFW(ST_VISIBILITY
)(other
);
200 if (sym_bind
!= STB_LOCAL
) {
201 /* we search global or weak symbols */
202 sym_index
= find_elf_sym(s
, name
);
205 esym
= &((ElfW(Sym
) *)s
->data
)[sym_index
];
206 if (esym
->st_shndx
!= SHN_UNDEF
) {
207 esym_bind
= ELFW(ST_BIND
)(esym
->st_info
);
208 /* propagate the most constraining visibility */
209 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
210 esym_vis
= ELFW(ST_VISIBILITY
)(esym
->st_other
);
211 if (esym_vis
== STV_DEFAULT
) {
213 } else if (sym_vis
== STV_DEFAULT
) {
216 new_vis
= (esym_vis
< sym_vis
) ? esym_vis
: sym_vis
;
218 esym
->st_other
= (esym
->st_other
& ~ELFW(ST_VISIBILITY
)(-1))
220 other
= esym
->st_other
; /* in case we have to patch esym */
221 if (sh_num
== SHN_UNDEF
) {
222 /* ignore adding of undefined symbol if the
223 corresponding symbol is already defined */
224 } else if (sym_bind
== STB_GLOBAL
&& esym_bind
== STB_WEAK
) {
225 /* global overrides weak, so patch */
227 } else if (sym_bind
== STB_WEAK
&& esym_bind
== STB_GLOBAL
) {
228 /* weak is ignored if already global */
229 } else if (sym_bind
== STB_WEAK
&& esym_bind
== STB_WEAK
) {
230 /* keep first-found weak definition, ignore subsequents */
231 } else if (sym_vis
== STV_HIDDEN
|| sym_vis
== STV_INTERNAL
) {
232 /* ignore hidden symbols after */
233 } else if (esym
->st_shndx
== SHN_COMMON
234 && (sh_num
< SHN_LORESERVE
|| sh_num
== SHN_COMMON
)) {
235 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
236 No idea if this is the correct solution ... */
238 } else if (s
== tcc_state
->dynsymtab_section
) {
239 /* we accept that two DLL define the same symbol */
242 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
243 sym_bind
, sh_num
, new_vis
, esym_bind
, esym
->st_shndx
, esym_vis
);
245 tcc_error_noabort("'%s' defined twice", name
);
249 esym
->st_info
= ELFW(ST_INFO
)(sym_bind
, sym_type
);
250 esym
->st_shndx
= sh_num
;
252 esym
->st_value
= value
;
253 esym
->st_size
= size
;
254 esym
->st_other
= other
;
258 sym_index
= put_elf_sym(s
, value
, size
,
259 ELFW(ST_INFO
)(sym_bind
, sym_type
), other
,
266 ST_FUNC
void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
267 int type
, int symbol
)
275 /* if no relocation section, create it */
276 snprintf(buf
, sizeof(buf
), REL_SECTION_FMT
, s
->name
);
277 /* if the symtab is allocated, then we consider the relocation
279 sr
= new_section(tcc_state
, buf
, SHT_RELX
, symtab
->sh_flags
);
280 sr
->sh_entsize
= sizeof(ElfW_Rel
);
282 sr
->sh_info
= s
->sh_num
;
285 rel
= section_ptr_add(sr
, sizeof(ElfW_Rel
));
286 rel
->r_offset
= offset
;
287 rel
->r_info
= ELFW(R_INFO
)(symbol
, type
);
288 #ifdef TCC_TARGET_X86_64
293 /* put stab debug information */
295 ST_FUNC
void put_stabs(const char *str
, int type
, int other
, int desc
,
300 sym
= section_ptr_add(stab_section
, sizeof(Stab_Sym
));
302 sym
->n_strx
= put_elf_str(stabstr_section
, str
);
307 sym
->n_other
= other
;
309 sym
->n_value
= value
;
312 ST_FUNC
void put_stabs_r(const char *str
, int type
, int other
, int desc
,
313 unsigned long value
, Section
*sec
, int sym_index
)
315 put_stabs(str
, type
, other
, desc
, value
);
316 put_elf_reloc(symtab_section
, stab_section
,
317 stab_section
->data_offset
- sizeof(unsigned int),
318 R_DATA_32
, sym_index
);
321 ST_FUNC
void put_stabn(int type
, int other
, int desc
, int value
)
323 put_stabs(NULL
, type
, other
, desc
, value
);
326 ST_FUNC
void put_stabd(int type
, int other
, int desc
)
328 put_stabs(NULL
, type
, other
, desc
, 0);
331 /* In an ELF file symbol table, the local symbols must appear below
332 the global and weak ones. Since TCC cannot sort it while generating
333 the code, we must do it after. All the relocation tables are also
334 modified to take into account the symbol table sorting */
335 static void sort_syms(TCCState
*s1
, Section
*s
)
337 int *old_to_new_syms
;
341 ElfW_Rel
*rel
, *rel_end
;
345 nb_syms
= s
->data_offset
/ sizeof(ElfW(Sym
));
346 new_syms
= tcc_malloc(nb_syms
* sizeof(ElfW(Sym
)));
347 old_to_new_syms
= tcc_malloc(nb_syms
* sizeof(int));
349 /* first pass for local symbols */
350 p
= (ElfW(Sym
) *)s
->data
;
352 for(i
= 0; i
< nb_syms
; i
++) {
353 if (ELFW(ST_BIND
)(p
->st_info
) == STB_LOCAL
) {
354 old_to_new_syms
[i
] = q
- new_syms
;
359 /* save the number of local symbols in section header */
360 s
->sh_info
= q
- new_syms
;
362 /* then second pass for non local symbols */
363 p
= (ElfW(Sym
) *)s
->data
;
364 for(i
= 0; i
< nb_syms
; i
++) {
365 if (ELFW(ST_BIND
)(p
->st_info
) != STB_LOCAL
) {
366 old_to_new_syms
[i
] = q
- new_syms
;
372 /* we copy the new symbols to the old */
373 memcpy(s
->data
, new_syms
, nb_syms
* sizeof(ElfW(Sym
)));
376 /* now we modify all the relocations */
377 for(i
= 1; i
< s1
->nb_sections
; i
++) {
378 sr
= s1
->sections
[i
];
379 if (sr
->sh_type
== SHT_RELX
&& sr
->link
== s
) {
380 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
381 for(rel
= (ElfW_Rel
*)sr
->data
;
384 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
385 type
= ELFW(R_TYPE
)(rel
->r_info
);
386 sym_index
= old_to_new_syms
[sym_index
];
387 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
392 tcc_free(old_to_new_syms
);
395 /* relocate common symbols in the .bss section */
396 ST_FUNC
void relocate_common_syms(void)
398 ElfW(Sym
) *sym
, *sym_end
;
399 unsigned long offset
, align
;
401 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+ symtab_section
->data_offset
);
402 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
405 if (sym
->st_shndx
== SHN_COMMON
) {
407 align
= sym
->st_value
;
408 offset
= bss_section
->data_offset
;
409 offset
= (offset
+ align
- 1) & -align
;
410 sym
->st_value
= offset
;
411 sym
->st_shndx
= bss_section
->sh_num
;
412 offset
+= sym
->st_size
;
413 bss_section
->data_offset
= offset
;
418 /* relocate symbol table, resolve undefined symbols if do_resolve is
419 true and output error if undefined symbol. */
420 ST_FUNC
void relocate_syms(TCCState
*s1
, int do_resolve
)
422 ElfW(Sym
) *sym
, *esym
, *sym_end
;
423 int sym_bind
, sh_num
, sym_index
;
426 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+ symtab_section
->data_offset
);
427 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
430 sh_num
= sym
->st_shndx
;
431 if (sh_num
== SHN_UNDEF
) {
432 name
= strtab_section
->data
+ sym
->st_name
;
434 #if !defined TCC_TARGET_PE || !defined _WIN32
436 name
= symtab_section
->link
->data
+ sym
->st_name
;
437 addr
= resolve_sym(s1
, name
);
439 sym
->st_value
= (uplong
)addr
;
443 } else if (s1
->dynsym
) {
444 /* if dynamic symbol exist, then use it */
445 sym_index
= find_elf_sym(s1
->dynsym
, name
);
447 esym
= &((ElfW(Sym
) *)s1
->dynsym
->data
)[sym_index
];
448 sym
->st_value
= esym
->st_value
;
452 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
454 if (!strcmp(name
, "_fp_hw"))
456 /* only weak symbols are accepted to be undefined. Their
458 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
459 if (sym_bind
== STB_WEAK
) {
462 tcc_error_noabort("undefined symbol '%s'", name
);
464 } else if (sh_num
< SHN_LORESERVE
) {
465 /* add section base */
466 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
472 #ifndef TCC_TARGET_PE
473 #ifdef TCC_TARGET_X86_64
474 #define JMP_TABLE_ENTRY_SIZE 14
475 static uplong
add_jmp_table(TCCState
*s1
, uplong val
)
477 char *p
= s1
->runtime_plt_and_got
+ s1
->runtime_plt_and_got_offset
;
478 s1
->runtime_plt_and_got_offset
+= JMP_TABLE_ENTRY_SIZE
;
483 *(uplong
*)(p
+ 6) = val
;
487 static uplong
add_got_table(TCCState
*s1
, uplong val
)
489 uplong
*p
= (uplong
*)(s1
->runtime_plt_and_got
+ s1
->runtime_plt_and_got_offset
);
490 s1
->runtime_plt_and_got_offset
+= sizeof(uplong
);
494 #elif defined TCC_TARGET_ARM
495 #define JMP_TABLE_ENTRY_SIZE 8
496 static uplong
add_jmp_table(TCCState
*s1
, int val
)
498 uint32_t *p
= (uint32_t *)(s1
->runtime_plt_and_got
+ s1
->runtime_plt_and_got_offset
);
499 s1
->runtime_plt_and_got_offset
+= JMP_TABLE_ENTRY_SIZE
;
500 /* ldr pc, [pc, #-4] */
508 /* relocate a given section (CPU dependent) */
509 ST_FUNC
void relocate_section(TCCState
*s1
, Section
*s
)
512 ElfW_Rel
*rel
, *rel_end
, *qrel
;
517 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
522 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
523 qrel
= (ElfW_Rel
*)sr
->data
;
527 ptr
= s
->data
+ rel
->r_offset
;
529 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
530 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
532 #ifdef TCC_TARGET_X86_64
533 val
+= rel
->r_addend
;
535 type
= ELFW(R_TYPE
)(rel
->r_info
);
536 addr
= s
->sh_addr
+ rel
->r_offset
;
540 #if defined(TCC_TARGET_I386)
542 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
543 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
544 qrel
->r_offset
= rel
->r_offset
;
546 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_386_32
);
550 qrel
->r_info
= ELFW(R_INFO
)(0, R_386_RELATIVE
);
557 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
559 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
561 qrel
->r_offset
= rel
->r_offset
;
562 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_386_PC32
);
567 *(int *)ptr
+= val
- addr
;
570 *(int *)ptr
+= val
- addr
;
577 *(int *)ptr
+= s1
->got
->sh_addr
- addr
;
580 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
583 /* we load the got offset */
584 *(int *)ptr
+= s1
->got_offsets
[sym_index
];
587 if (s1
->output_format
!= TCC_OUTPUT_FORMAT_BINARY
) {
589 tcc_error("can only produce 16-bit binary files");
591 *(short *)ptr
+= val
;
594 if (s1
->output_format
!= TCC_OUTPUT_FORMAT_BINARY
)
596 *(short *)ptr
+= val
- addr
;
598 #elif defined(TCC_TARGET_ARM)
605 x
= (*(int *)ptr
)&0xffffff;
606 (*(int *)ptr
) &= 0xff000000;
611 #ifndef TCC_TARGET_PE
612 if((x
& 3) != 0 || x
>= 0x4000000 || x
< -0x4000000)
613 if (s1
->output_type
== TCC_OUTPUT_MEMORY
)
614 x
+= add_jmp_table(s1
, val
) - val
; /* add veneer */
616 if((x
& 3) != 0 || x
>= 0x4000000 || x
< -0x4000000)
617 tcc_error("can't relocate value at %x",addr
);
626 x
= (*(int *)ptr
) & 0x7fffffff;
627 (*(int *)ptr
) &= 0x80000000;
630 if((x
^(x
>>1))&0x40000000)
631 tcc_error("can't relocate value at %x",addr
);
632 (*(int *)ptr
) |= x
& 0x7fffffff;
637 case R_ARM_BASE_PREL
:
638 *(int *)ptr
+= s1
->got
->sh_addr
- addr
;
641 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
644 /* we load the got offset */
645 *(int *)ptr
+= s1
->got_offsets
[sym_index
];
650 /* trade Thumb support for ARMv4 support */
651 if ((0x0ffffff0 & *(int*)ptr
) == 0x012FFF10)
652 *(int*)ptr
^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
655 fprintf(stderr
,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
656 type
, (unsigned)addr
, (unsigned)(uplong
)ptr
, (unsigned)val
);
658 #elif defined(TCC_TARGET_C67)
666 /* put the low 16 bits of the absolute address */
667 // add to what is already there
669 orig
= ((*(int *)(ptr
)) >> 7) & 0xffff;
670 orig
|= (((*(int *)(ptr
+4)) >> 7) & 0xffff) << 16;
672 //patch both at once - assumes always in pairs Low - High
674 *(int *) ptr
= (*(int *) ptr
& (~(0xffff << 7)) ) | (((val
+orig
) & 0xffff) << 7);
675 *(int *)(ptr
+4) = (*(int *)(ptr
+4) & (~(0xffff << 7)) ) | ((((val
+orig
)>>16) & 0xffff) << 7);
681 fprintf(stderr
,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
682 type
, (unsigned)addr
, (unsigned)(uplong
)ptr
, (unsigned)val
);
684 #elif defined(TCC_TARGET_X86_64)
686 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
687 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
688 qrel
->r_addend
= *(long long *)ptr
+ val
;
691 *(long long *)ptr
+= val
;
695 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
696 /* XXX: this logic may depend on TCC's codegen
697 now TCC uses R_X86_64_32 even for a 64bit pointer */
698 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
699 qrel
->r_addend
= *(int *)ptr
+ val
;
706 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
708 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
710 qrel
->r_offset
= rel
->r_offset
;
711 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_X86_64_PC32
);
712 qrel
->r_addend
= *(int *)ptr
;
718 case R_X86_64_PLT32
: {
720 diff
= (long long)val
- addr
;
721 if (diff
<= -2147483647 || diff
> 2147483647) {
722 #ifndef TCC_TARGET_PE
723 /* XXX: naive support for over 32bit jump */
724 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
725 val
= (add_jmp_table(s1
, val
- rel
->r_addend
) +
730 if (diff
<= -2147483647 || diff
> 2147483647) {
731 tcc_error("internal error: relocation failed");
737 case R_X86_64_GLOB_DAT
:
738 case R_X86_64_JUMP_SLOT
:
739 /* They don't need addend */
740 *(int *)ptr
= val
- rel
->r_addend
;
742 case R_X86_64_GOTPCREL
:
743 #ifndef TCC_TARGET_PE
744 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
745 val
= add_got_table(s1
, val
- rel
->r_addend
) + rel
->r_addend
;
746 *(int *)ptr
+= val
- addr
;
750 *(int *)ptr
+= (s1
->got
->sh_addr
- addr
+
751 s1
->got_offsets
[sym_index
] - 4);
753 case R_X86_64_GOTTPOFF
:
754 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
757 /* we load the got offset */
758 *(int *)ptr
+= s1
->got_offsets
[sym_index
];
761 #error unsupported processor
765 /* if the relocation is allocated, we change its symbol table */
766 if (sr
->sh_flags
& SHF_ALLOC
)
767 sr
->link
= s1
->dynsym
;
770 /* relocate relocation table in 'sr' */
771 static void relocate_rel(TCCState
*s1
, Section
*sr
)
774 ElfW_Rel
*rel
, *rel_end
;
776 s
= s1
->sections
[sr
->sh_info
];
777 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
778 for(rel
= (ElfW_Rel
*)sr
->data
;
781 rel
->r_offset
+= s
->sh_addr
;
785 /* count the number of dynamic relocations so that we can reserve
787 static int prepare_dynamic_rel(TCCState
*s1
, Section
*sr
)
789 ElfW_Rel
*rel
, *rel_end
;
790 int sym_index
, esym_index
, type
, count
;
793 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
794 for(rel
= (ElfW_Rel
*)sr
->data
; rel
< rel_end
; rel
++) {
795 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
796 type
= ELFW(R_TYPE
)(rel
->r_info
);
798 #if defined(TCC_TARGET_I386)
800 #elif defined(TCC_TARGET_X86_64)
807 #if defined(TCC_TARGET_I386)
809 #elif defined(TCC_TARGET_X86_64)
812 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
821 /* allocate the section */
822 sr
->sh_flags
|= SHF_ALLOC
;
823 sr
->sh_size
= count
* sizeof(ElfW_Rel
);
828 static void put_got_offset(TCCState
*s1
, int index
, unsigned long val
)
833 if (index
>= s1
->nb_got_offsets
) {
834 /* find immediately bigger power of 2 and reallocate array */
838 tab
= tcc_realloc(s1
->got_offsets
, n
* sizeof(unsigned long));
840 tcc_error("memory full");
841 s1
->got_offsets
= tab
;
842 memset(s1
->got_offsets
+ s1
->nb_got_offsets
, 0,
843 (n
- s1
->nb_got_offsets
) * sizeof(unsigned long));
844 s1
->nb_got_offsets
= n
;
846 s1
->got_offsets
[index
] = val
;
849 /* XXX: suppress that */
850 static void put32(unsigned char *p
, uint32_t val
)
858 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
859 defined(TCC_TARGET_X86_64)
860 static uint32_t get32(unsigned char *p
)
862 return p
[0] | (p
[1] << 8) | (p
[2] << 16) | (p
[3] << 24);
866 static void build_got(TCCState
*s1
)
870 /* if no got, then create it */
871 s1
->got
= new_section(s1
, ".got", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
872 s1
->got
->sh_entsize
= 4;
873 add_elf_sym(symtab_section
, 0, 4, ELFW(ST_INFO
)(STB_GLOBAL
, STT_OBJECT
),
874 0, s1
->got
->sh_num
, "_GLOBAL_OFFSET_TABLE_");
875 ptr
= section_ptr_add(s1
->got
, 3 * PTR_SIZE
);
877 /* keep space for _DYNAMIC pointer, if present */
879 /* two dummy got entries */
883 /* keep space for _DYNAMIC pointer, if present */
886 /* two dummy got entries */
894 /* put a got entry corresponding to a symbol in symtab_section. 'size'
895 and 'info' can be modifed if more precise info comes from the DLL */
896 static void put_got_entry(TCCState
*s1
,
897 int reloc_type
, unsigned long size
, int info
,
903 unsigned long offset
;
909 /* if a got entry already exists for that symbol, no need to add one */
910 if (sym_index
< s1
->nb_got_offsets
&&
911 s1
->got_offsets
[sym_index
] != 0)
914 put_got_offset(s1
, sym_index
, s1
->got
->data_offset
);
917 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
918 name
= symtab_section
->link
->data
+ sym
->st_name
;
919 offset
= sym
->st_value
;
920 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
922 #ifdef TCC_TARGET_X86_64
932 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
935 /* if we build a DLL, we add a %ebx offset */
936 if (s1
->output_type
== TCC_OUTPUT_DLL
)
942 /* add a PLT entry */
944 if (plt
->data_offset
== 0) {
945 /* first plt entry */
946 p
= section_ptr_add(plt
, 16);
947 p
[0] = 0xff; /* pushl got + PTR_SIZE */
949 put32(p
+ 2, PTR_SIZE
);
950 p
[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
952 put32(p
+ 8, PTR_SIZE
* 2);
955 p
= section_ptr_add(plt
, 16);
956 p
[0] = 0xff; /* jmp *(got + x) */
958 put32(p
+ 2, s1
->got
->data_offset
);
959 p
[6] = 0x68; /* push $xxx */
960 put32(p
+ 7, (plt
->data_offset
- 32) >> 1);
961 p
[11] = 0xe9; /* jmp plt_start */
962 put32(p
+ 12, -(plt
->data_offset
));
964 /* the symbol is modified so that it will be relocated to
966 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
967 if (s1
->output_type
== TCC_OUTPUT_EXE
)
969 offset
= plt
->data_offset
- 16;
971 #elif defined(TCC_TARGET_ARM)
972 if (reloc_type
== R_ARM_JUMP_SLOT
) {
976 /* if we build a DLL, we add a %ebx offset */
977 if (s1
->output_type
== TCC_OUTPUT_DLL
)
978 tcc_error("DLLs unimplemented!");
980 /* add a PLT entry */
982 if (plt
->data_offset
== 0) {
983 /* first plt entry */
984 p
= section_ptr_add(plt
, 16);
985 put32(p
, 0xe52de004);
986 put32(p
+ 4, 0xe59fe010);
987 put32(p
+ 8, 0xe08fe00e);
988 put32(p
+ 12, 0xe5bef008);
991 p
= section_ptr_add(plt
, 16);
992 put32(p
, 0xe59fc004);
993 put32(p
+4, 0xe08fc00c);
994 put32(p
+8, 0xe59cf000);
995 put32(p
+12, s1
->got
->data_offset
);
997 /* the symbol is modified so that it will be relocated to
999 if (s1
->output_type
== TCC_OUTPUT_EXE
)
1000 offset
= plt
->data_offset
- 16;
1002 #elif defined(TCC_TARGET_C67)
1003 tcc_error("C67 got not implemented");
1005 #error unsupported CPU
1007 index
= put_elf_sym(s1
->dynsym
, offset
,
1008 size
, info
, 0, sym
->st_shndx
, name
);
1009 /* put a got entry */
1010 put_elf_reloc(s1
->dynsym
, s1
->got
,
1011 s1
->got
->data_offset
,
1014 ptr
= section_ptr_add(s1
->got
, PTR_SIZE
);
1018 /* build GOT and PLT entries */
1019 ST_FUNC
void build_got_entries(TCCState
*s1
)
1022 ElfW_Rel
*rel
, *rel_end
;
1024 int i
, type
, reloc_type
, sym_index
;
1026 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1027 s
= s1
->sections
[i
];
1028 if (s
->sh_type
!= SHT_RELX
)
1030 /* no need to handle got relocations */
1031 if (s
->link
!= symtab_section
)
1033 rel_end
= (ElfW_Rel
*)(s
->data
+ s
->data_offset
);
1034 for(rel
= (ElfW_Rel
*)s
->data
;
1037 type
= ELFW(R_TYPE
)(rel
->r_info
);
1039 #if defined(TCC_TARGET_I386)
1046 if (type
== R_386_GOT32
|| type
== R_386_PLT32
) {
1047 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1048 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1049 /* look at the symbol got offset. If none, then add one */
1050 if (type
== R_386_GOT32
)
1051 reloc_type
= R_386_GLOB_DAT
;
1053 reloc_type
= R_386_JMP_SLOT
;
1054 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1058 #elif defined(TCC_TARGET_ARM)
1059 case R_ARM_GOT_BREL
:
1060 case R_ARM_GOTOFF32
:
1061 case R_ARM_BASE_PREL
:
1065 if (type
== R_ARM_GOT_BREL
|| type
== R_ARM_PLT32
) {
1066 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1067 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1068 /* look at the symbol got offset. If none, then add one */
1069 if (type
== R_ARM_GOT_BREL
)
1070 reloc_type
= R_ARM_GLOB_DAT
;
1072 reloc_type
= R_ARM_JUMP_SLOT
;
1073 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1077 #elif defined(TCC_TARGET_C67)
1084 if (type
== R_C60_GOT32
|| type
== R_C60_PLT32
) {
1085 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1086 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1087 /* look at the symbol got offset. If none, then add one */
1088 if (type
== R_C60_GOT32
)
1089 reloc_type
= R_C60_GLOB_DAT
;
1091 reloc_type
= R_C60_JMP_SLOT
;
1092 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1096 #elif defined(TCC_TARGET_X86_64)
1097 case R_X86_64_GOT32
:
1098 case R_X86_64_GOTTPOFF
:
1099 case R_X86_64_GOTPCREL
:
1100 case R_X86_64_PLT32
:
1103 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
||
1104 type
== R_X86_64_PLT32
) {
1105 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1106 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1107 /* look at the symbol got offset. If none, then add one */
1108 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
)
1109 reloc_type
= R_X86_64_GLOB_DAT
;
1111 reloc_type
= R_X86_64_JUMP_SLOT
;
1112 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1117 #error unsupported CPU
1126 ST_FUNC Section
*new_symtab(TCCState
*s1
,
1127 const char *symtab_name
, int sh_type
, int sh_flags
,
1128 const char *strtab_name
,
1129 const char *hash_name
, int hash_sh_flags
)
1131 Section
*symtab
, *strtab
, *hash
;
1132 int *ptr
, nb_buckets
;
1134 symtab
= new_section(s1
, symtab_name
, sh_type
, sh_flags
);
1135 symtab
->sh_entsize
= sizeof(ElfW(Sym
));
1136 strtab
= new_section(s1
, strtab_name
, SHT_STRTAB
, sh_flags
);
1137 put_elf_str(strtab
, "");
1138 symtab
->link
= strtab
;
1139 put_elf_sym(symtab
, 0, 0, 0, 0, 0, NULL
);
1143 hash
= new_section(s1
, hash_name
, SHT_HASH
, hash_sh_flags
);
1144 hash
->sh_entsize
= sizeof(int);
1145 symtab
->hash
= hash
;
1146 hash
->link
= symtab
;
1148 ptr
= section_ptr_add(hash
, (2 + nb_buckets
+ 1) * sizeof(int));
1149 ptr
[0] = nb_buckets
;
1151 memset(ptr
+ 2, 0, (nb_buckets
+ 1) * sizeof(int));
1155 /* put dynamic tag */
1156 static void put_dt(Section
*dynamic
, int dt
, unsigned long val
)
1159 dyn
= section_ptr_add(dynamic
, sizeof(ElfW(Dyn
)));
1161 dyn
->d_un
.d_val
= val
;
1164 static void add_init_array_defines(TCCState
*s1
, const char *section_name
)
1168 char sym_start
[1024];
1171 snprintf(sym_start
, sizeof(sym_start
), "__%s_start", section_name
+ 1);
1172 snprintf(sym_end
, sizeof(sym_end
), "__%s_end", section_name
+ 1);
1174 s
= find_section(s1
, section_name
);
1179 end_offset
= s
->data_offset
;
1182 add_elf_sym(symtab_section
,
1184 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1185 s
->sh_num
, sym_start
);
1186 add_elf_sym(symtab_section
,
1188 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1189 s
->sh_num
, sym_end
);
1192 static int tcc_add_support(TCCState
*s1
, const char *filename
)
1195 snprintf(buf
, sizeof(buf
), "%s/%s", s1
->tcc_lib_path
, filename
);
1196 return tcc_add_file(s1
, buf
);
1199 ST_FUNC
void tcc_add_bcheck(TCCState
*s1
)
1201 #ifdef CONFIG_TCC_BCHECK
1203 Section
*init_section
;
1204 unsigned char *pinit
;
1207 if (0 == s1
->do_bounds_check
)
1210 /* XXX: add an object file to do that */
1211 ptr
= section_ptr_add(bounds_section
, sizeof(unsigned long));
1213 add_elf_sym(symtab_section
, 0, 0,
1214 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1215 bounds_section
->sh_num
, "__bounds_start");
1216 /* add bound check code */
1217 #ifndef TCC_TARGET_PE
1218 tcc_add_support(s1
, "bcheck.o");
1220 #ifdef TCC_TARGET_I386
1221 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
) {
1222 /* add 'call __bound_init()' in .init section */
1223 init_section
= find_section(s1
, ".init");
1224 pinit
= section_ptr_add(init_section
, 5);
1226 put32(pinit
+ 1, -4);
1227 sym_index
= find_elf_sym(symtab_section
, "__bound_init");
1228 put_elf_reloc(symtab_section
, init_section
,
1229 init_section
->data_offset
- 4, R_386_PC32
, sym_index
);
1235 /* add tcc runtime libraries */
1236 ST_FUNC
void tcc_add_runtime(TCCState
*s1
)
1241 if (!s1
->nostdlib
) {
1242 tcc_add_library(s1
, "c");
1243 #ifdef CONFIG_USE_LIBGCC
1244 tcc_add_file(s1
, TCC_LIBGCC
);
1245 #elif !defined WITHOUT_LIBTCC
1246 tcc_add_support(s1
, "libtcc1.a");
1248 /* add crt end if not memory output */
1249 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
)
1250 tcc_add_crt(s1
, "crtn.o");
1254 /* add various standard linker symbols (must be done after the
1255 sections are filled (for example after allocating common
1257 ST_FUNC
void tcc_add_linker_symbols(TCCState
*s1
)
1263 add_elf_sym(symtab_section
,
1264 text_section
->data_offset
, 0,
1265 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1266 text_section
->sh_num
, "_etext");
1267 add_elf_sym(symtab_section
,
1268 data_section
->data_offset
, 0,
1269 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1270 data_section
->sh_num
, "_edata");
1271 add_elf_sym(symtab_section
,
1272 bss_section
->data_offset
, 0,
1273 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1274 bss_section
->sh_num
, "_end");
1275 /* horrible new standard ldscript defines */
1276 add_init_array_defines(s1
, ".preinit_array");
1277 add_init_array_defines(s1
, ".init_array");
1278 add_init_array_defines(s1
, ".fini_array");
1280 /* add start and stop symbols for sections whose name can be
1282 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1283 s
= s1
->sections
[i
];
1284 if (s
->sh_type
== SHT_PROGBITS
&&
1285 (s
->sh_flags
& SHF_ALLOC
)) {
1289 /* check if section name can be expressed in C */
1295 if (!isid(ch
) && !isnum(ch
))
1299 snprintf(buf
, sizeof(buf
), "__start_%s", s
->name
);
1300 add_elf_sym(symtab_section
,
1302 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1304 snprintf(buf
, sizeof(buf
), "__stop_%s", s
->name
);
1305 add_elf_sym(symtab_section
,
1307 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1314 static void tcc_output_binary(TCCState
*s1
, FILE *f
,
1315 const int *section_order
)
1318 int i
, offset
, size
;
1321 for(i
=1;i
<s1
->nb_sections
;i
++) {
1322 s
= s1
->sections
[section_order
[i
]];
1323 if (s
->sh_type
!= SHT_NOBITS
&&
1324 (s
->sh_flags
& SHF_ALLOC
)) {
1325 while (offset
< s
->sh_offset
) {
1330 fwrite(s
->data
, 1, size
, f
);
1336 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1338 #define EXTRA_RELITEMS 14
1340 /* move the relocation value from .dynsym to .got */
1341 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1343 uint32_t *gotd
= (void *)s1
->got
->data
;
1344 ElfW(Sym
) *sym
, *sym_end
;
1346 gotd
+= 3; // dummy entries in .got
1347 /* relocate symbols in .dynsym */
1348 sym_end
= (ElfW(Sym
) *)(s
->data
+ s
->data_offset
);
1349 for (sym
= (ElfW(Sym
) *)s
->data
+ 1; sym
< sym_end
; sym
++) {
1350 if (sym
->st_shndx
== SHN_UNDEF
) {
1351 *gotd
++ = sym
->st_value
+ 6; // XXX 6 is magic ?
1358 #define EXTRA_RELITEMS 9
1361 ST_FUNC
void fill_got_entry(TCCState
*s1
, ElfW_Rel
*rel
)
1363 int sym_index
= ELFW(R_SYM
) (rel
->r_info
);
1364 ElfW(Sym
) *sym
= &((ElfW(Sym
) *) symtab_section
->data
)[sym_index
];
1365 unsigned long offset
;
1367 if (sym_index
>= s1
->nb_got_offsets
)
1369 offset
= s1
->got_offsets
[sym_index
];
1370 section_reserve(s1
->got
, offset
+ PTR_SIZE
);
1371 #ifdef TCC_TARGET_X86_64
1372 /* only works for x86-64 */
1373 put32(s1
->got
->data
+ offset
, sym
->st_value
>> 32);
1375 put32(s1
->got
->data
+ offset
, sym
->st_value
& 0xffffffff);
1378 ST_FUNC
void fill_got(TCCState
*s1
)
1381 ElfW_Rel
*rel
, *rel_end
;
1384 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1385 s
= s1
->sections
[i
];
1386 if (s
->sh_type
!= SHT_RELX
)
1388 /* no need to handle got relocations */
1389 if (s
->link
!= symtab_section
)
1391 rel_end
= (ElfW_Rel
*) (s
->data
+ s
->data_offset
);
1392 for(rel
= (ElfW_Rel
*) s
->data
; rel
< rel_end
; rel
++) {
1393 switch (ELFW(R_TYPE
) (rel
->r_info
)) {
1394 case R_X86_64_GOT32
:
1395 case R_X86_64_GOTPCREL
:
1396 case R_X86_64_PLT32
:
1397 fill_got_entry(s1
, rel
);
1405 /* output an ELF file */
1406 /* XXX: suppress unneeded sections */
1407 static int elf_output_file(TCCState
*s1
, const char *filename
)
1413 int shnum
, i
, phnum
, file_offset
, offset
, size
, j
, tmp
, sh_order_index
, k
;
1415 Section
*strsec
, *s
;
1416 ElfW(Shdr
) shdr
, *sh
;
1417 ElfW(Phdr
) *phdr
, *ph
;
1418 Section
*interp
, *dynamic
, *dynstr
;
1419 unsigned long saved_dynamic_data_offset
;
1421 int type
, file_type
;
1422 unsigned long rel_addr
, rel_size
;
1423 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1424 unsigned long bss_addr
, bss_size
;
1427 file_type
= s1
->output_type
;
1430 if (file_type
!= TCC_OUTPUT_OBJ
) {
1431 tcc_add_runtime(s1
);
1435 section_order
= NULL
;
1438 dynstr
= NULL
; /* avoid warning */
1439 saved_dynamic_data_offset
= 0; /* avoid warning */
1441 if (file_type
!= TCC_OUTPUT_OBJ
) {
1442 relocate_common_syms();
1444 tcc_add_linker_symbols(s1
);
1446 if (!s1
->static_link
) {
1448 int sym_index
, index
;
1449 ElfW(Sym
) *esym
, *sym_end
;
1451 if (file_type
== TCC_OUTPUT_EXE
) {
1453 /* allow override the dynamic loader */
1454 const char *elfint
= getenv("LD_SO");
1456 elfint
= CONFIG_TCC_ELFINTERP
;
1457 /* add interpreter section only if executable */
1458 interp
= new_section(s1
, ".interp", SHT_PROGBITS
, SHF_ALLOC
);
1459 interp
->sh_addralign
= 1;
1460 ptr
= section_ptr_add(interp
, 1+strlen(elfint
));
1461 strcpy(ptr
, elfint
);
1464 /* add dynamic symbol table */
1465 s1
->dynsym
= new_symtab(s1
, ".dynsym", SHT_DYNSYM
, SHF_ALLOC
,
1467 ".hash", SHF_ALLOC
);
1468 dynstr
= s1
->dynsym
->link
;
1470 /* add dynamic section */
1471 dynamic
= new_section(s1
, ".dynamic", SHT_DYNAMIC
,
1472 SHF_ALLOC
| SHF_WRITE
);
1473 dynamic
->link
= dynstr
;
1474 dynamic
->sh_entsize
= sizeof(ElfW(Dyn
));
1477 s1
->plt
= new_section(s1
, ".plt", SHT_PROGBITS
,
1478 SHF_ALLOC
| SHF_EXECINSTR
);
1479 s1
->plt
->sh_entsize
= 4;
1483 /* scan for undefined symbols and see if they are in the
1484 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1485 is found, then we add it in the PLT. If a symbol
1486 STT_OBJECT is found, we add it in the .bss section with
1487 a suitable relocation */
1488 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+
1489 symtab_section
->data_offset
);
1490 if (file_type
== TCC_OUTPUT_EXE
) {
1491 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
1494 if (sym
->st_shndx
== SHN_UNDEF
) {
1495 name
= symtab_section
->link
->data
+ sym
->st_name
;
1496 sym_index
= find_elf_sym(s1
->dynsymtab_section
, name
);
1498 esym
= &((ElfW(Sym
) *)s1
->dynsymtab_section
->data
)[sym_index
];
1499 type
= ELFW(ST_TYPE
)(esym
->st_info
);
1500 if ((type
== STT_FUNC
) || (type
== STT_GNU_IFUNC
)) {
1501 put_got_entry(s1
, R_JMP_SLOT
, esym
->st_size
,
1503 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1504 } else if (type
== STT_OBJECT
) {
1505 unsigned long offset
;
1506 ElfW(Sym
) *dynsym
, *dynsym_end
;
1507 offset
= bss_section
->data_offset
;
1508 /* XXX: which alignment ? */
1509 offset
= (offset
+ 16 - 1) & -16;
1510 index
= put_elf_sym(s1
->dynsym
, offset
, esym
->st_size
,
1512 bss_section
->sh_num
, name
);
1513 // Ensure R_COPY works for weak symbol aliases
1514 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1515 dynsym_end
= (ElfW(Sym
) *)
1516 (s1
->dynsymtab_section
->data
+
1517 s1
->dynsymtab_section
->data_offset
);
1518 for(dynsym
= (ElfW(Sym
) *)s1
->dynsymtab_section
->data
+ 1;
1519 dynsym
< dynsym_end
; dynsym
++) {
1520 if ((dynsym
->st_value
== esym
->st_value
)
1521 && (ELFW(ST_BIND
)(dynsym
->st_info
) == STB_GLOBAL
)) {
1523 dynname
= s1
->dynsymtab_section
->link
->data
1525 put_elf_sym(s1
->dynsym
, offset
,
1528 bss_section
->sh_num
,
1534 put_elf_reloc(s1
->dynsym
, bss_section
,
1535 offset
, R_COPY
, index
);
1536 offset
+= esym
->st_size
;
1537 bss_section
->data_offset
= offset
;
1540 /* STB_WEAK undefined symbols are accepted */
1541 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1543 if (ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
||
1544 !strcmp(name
, "_fp_hw")) {
1546 tcc_error_noabort("undefined symbol '%s'", name
);
1549 } else if (s1
->rdynamic
&&
1550 ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1551 /* if -rdynamic option, then export all non
1553 name
= symtab_section
->link
->data
+ sym
->st_name
;
1554 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1556 sym
->st_shndx
, name
);
1563 /* now look at unresolved dynamic symbols and export
1564 corresponding symbol */
1565 sym_end
= (ElfW(Sym
) *)(s1
->dynsymtab_section
->data
+
1566 s1
->dynsymtab_section
->data_offset
);
1567 for(esym
= (ElfW(Sym
) *)s1
->dynsymtab_section
->data
+ 1;
1570 if (esym
->st_shndx
== SHN_UNDEF
) {
1571 name
= s1
->dynsymtab_section
->link
->data
+ esym
->st_name
;
1572 sym_index
= find_elf_sym(symtab_section
, name
);
1574 /* XXX: avoid adding a symbol if already
1575 present because of -rdynamic ? */
1576 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1577 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1579 sym
->st_shndx
, name
);
1581 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1582 /* weak symbols can stay undefined */
1584 tcc_warning("undefined dynamic symbol '%s'", name
);
1591 /* shared library case : we simply export all the global symbols */
1592 nb_syms
= symtab_section
->data_offset
/ sizeof(ElfW(Sym
));
1593 s1
->symtab_to_dynsym
= tcc_mallocz(sizeof(int) * nb_syms
);
1594 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
1597 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1598 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1599 if ((ELFW(ST_TYPE
)(sym
->st_info
) == STT_FUNC
||
1600 ELFW(ST_TYPE
)(sym
->st_info
) == STT_GNU_IFUNC
)
1601 && sym
->st_shndx
== SHN_UNDEF
) {
1602 put_got_entry(s1
, R_JMP_SLOT
, sym
->st_size
,
1604 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1606 else if (ELFW(ST_TYPE
)(sym
->st_info
) == STT_OBJECT
) {
1607 put_got_entry(s1
, R_X86_64_GLOB_DAT
, sym
->st_size
,
1609 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1614 name
= symtab_section
->link
->data
+ sym
->st_name
;
1615 index
= put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1617 sym
->st_shndx
, name
);
1618 s1
->symtab_to_dynsym
[sym
-
1619 (ElfW(Sym
) *)symtab_section
->data
] =
1626 build_got_entries(s1
);
1628 /* add a list of needed dlls */
1629 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
1630 DLLReference
*dllref
= s1
->loaded_dlls
[i
];
1631 if (dllref
->level
== 0)
1632 put_dt(dynamic
, DT_NEEDED
, put_elf_str(dynstr
, dllref
->name
));
1636 put_dt(dynamic
, DT_RPATH
, put_elf_str(dynstr
, s1
->rpath
));
1638 /* XXX: currently, since we do not handle PIC code, we
1639 must relocate the readonly segments */
1640 if (file_type
== TCC_OUTPUT_DLL
) {
1642 put_dt(dynamic
, DT_SONAME
, put_elf_str(dynstr
, s1
->soname
));
1643 put_dt(dynamic
, DT_TEXTREL
, 0);
1647 put_dt(dynamic
, DT_SYMBOLIC
, 0);
1649 /* add necessary space for other entries */
1650 saved_dynamic_data_offset
= dynamic
->data_offset
;
1651 dynamic
->data_offset
+= sizeof(ElfW(Dyn
)) * EXTRA_RELITEMS
;
1653 /* still need to build got entries in case of static link */
1654 build_got_entries(s1
);
1658 memset(&ehdr
, 0, sizeof(ehdr
));
1660 /* we add a section for symbols */
1661 strsec
= new_section(s1
, ".shstrtab", SHT_STRTAB
, 0);
1662 put_elf_str(strsec
, "");
1664 /* compute number of sections */
1665 shnum
= s1
->nb_sections
;
1667 /* this array is used to reorder sections in the output file */
1668 section_order
= tcc_malloc(sizeof(int) * shnum
);
1669 section_order
[0] = 0;
1672 /* compute number of program headers */
1675 case TCC_OUTPUT_OBJ
:
1678 case TCC_OUTPUT_EXE
:
1679 if (!s1
->static_link
)
1680 phnum
= 4 + HAVE_PHDR
;
1684 case TCC_OUTPUT_DLL
:
1689 /* allocate strings for section names and decide if an unallocated
1690 section should be output */
1691 /* NOTE: the strsec section comes last, so its size is also
1693 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1694 s
= s1
->sections
[i
];
1695 s
->sh_name
= put_elf_str(strsec
, s
->name
);
1697 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1702 s
->reloc
? s
->reloc
->name
: "n"
1705 /* when generating a DLL, we include relocations but we may
1707 if (file_type
== TCC_OUTPUT_DLL
&&
1708 s
->sh_type
== SHT_RELX
&&
1709 !(s
->sh_flags
& SHF_ALLOC
)) {
1710 /* //gr: avoid bogus relocs for empty (debug) sections */
1711 if (s1
->sections
[s
->sh_info
]->sh_flags
& SHF_ALLOC
)
1712 prepare_dynamic_rel(s1
, s
);
1713 else if (s1
->do_debug
)
1714 s
->sh_size
= s
->data_offset
;
1715 } else if (s1
->do_debug
||
1716 file_type
== TCC_OUTPUT_OBJ
||
1717 (s
->sh_flags
& SHF_ALLOC
) ||
1718 i
== (s1
->nb_sections
- 1)) {
1719 /* we output all sections if debug or object file */
1720 s
->sh_size
= s
->data_offset
;
1724 /* allocate program segment headers */
1725 phdr
= tcc_mallocz(phnum
* sizeof(ElfW(Phdr
)));
1727 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1728 file_offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
1733 /* compute section to program header mapping */
1734 if (s1
->has_text_addr
) {
1735 int a_offset
, p_offset
;
1736 addr
= s1
->text_addr
;
1737 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1739 a_offset
= addr
& (s1
->section_align
- 1);
1740 p_offset
= file_offset
& (s1
->section_align
- 1);
1741 if (a_offset
< p_offset
)
1742 a_offset
+= s1
->section_align
;
1743 file_offset
+= (a_offset
- p_offset
);
1745 if (file_type
== TCC_OUTPUT_DLL
)
1748 addr
= ELF_START_ADDR
;
1749 /* compute address after headers */
1750 addr
+= (file_offset
& (s1
->section_align
- 1));
1753 /* dynamic relocation table information, for .dynamic section */
1757 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1758 bss_addr
= bss_size
= 0;
1760 /* leave one program header for the program interpreter */
1763 ph
+= 1 + HAVE_PHDR
;
1765 for(j
= 0; j
< 2; j
++) {
1766 ph
->p_type
= PT_LOAD
;
1768 ph
->p_flags
= PF_R
| PF_X
;
1770 ph
->p_flags
= PF_R
| PF_W
;
1771 ph
->p_align
= s1
->section_align
;
1773 /* we do the following ordering: interp, symbol tables,
1774 relocations, progbits, nobits */
1775 /* XXX: do faster and simpler sorting */
1776 for(k
= 0; k
< 5; k
++) {
1777 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1778 s
= s1
->sections
[i
];
1779 /* compute if section should be included */
1781 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1785 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1786 (SHF_ALLOC
| SHF_WRITE
))
1792 } else if (s
->sh_type
== SHT_DYNSYM
||
1793 s
->sh_type
== SHT_STRTAB
||
1794 s
->sh_type
== SHT_HASH
) {
1797 } else if (s
->sh_type
== SHT_RELX
) {
1800 } else if (s
->sh_type
== SHT_NOBITS
) {
1807 section_order
[sh_order_index
++] = i
;
1809 /* section matches: we align it and add its size */
1811 addr
= (addr
+ s
->sh_addralign
- 1) &
1812 ~(s
->sh_addralign
- 1);
1813 file_offset
+= addr
- tmp
;
1814 s
->sh_offset
= file_offset
;
1817 /* update program header infos */
1818 if (ph
->p_offset
== 0) {
1819 ph
->p_offset
= file_offset
;
1821 ph
->p_paddr
= ph
->p_vaddr
;
1823 /* update dynamic relocation infos */
1824 if (s
->sh_type
== SHT_RELX
) {
1825 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1826 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.got")) { // rel_size == 0) {
1828 rel_size
+= s
->sh_size
; // XXX only first rel.
1830 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.bss")) { // rel_size == 0) {
1832 bss_size
= s
->sh_size
; // XXX only first rel.
1837 rel_size
+= s
->sh_size
;
1841 if (s
->sh_type
!= SHT_NOBITS
)
1842 file_offset
+= s
->sh_size
;
1845 ph
->p_filesz
= file_offset
- ph
->p_offset
;
1846 ph
->p_memsz
= addr
- ph
->p_vaddr
;
1849 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1850 /* if in the middle of a page, we duplicate the page in
1851 memory so that one copy is RX and the other is RW */
1852 if ((addr
& (s1
->section_align
- 1)) != 0)
1853 addr
+= s1
->section_align
;
1855 addr
= (addr
+ s1
->section_align
- 1) & ~(s1
->section_align
- 1);
1856 file_offset
= (file_offset
+ s1
->section_align
- 1) &
1857 ~(s1
->section_align
- 1);
1862 /* if interpreter, then add corresponing program header */
1866 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1868 int len
= phnum
* sizeof(ElfW(Phdr
));
1870 ph
->p_type
= PT_PHDR
;
1871 ph
->p_offset
= sizeof(ElfW(Ehdr
));
1872 ph
->p_vaddr
= interp
->sh_addr
- len
;
1873 ph
->p_paddr
= ph
->p_vaddr
;
1874 ph
->p_filesz
= ph
->p_memsz
= len
;
1875 ph
->p_flags
= PF_R
| PF_X
;
1876 ph
->p_align
= 4; // interp->sh_addralign;
1881 ph
->p_type
= PT_INTERP
;
1882 ph
->p_offset
= interp
->sh_offset
;
1883 ph
->p_vaddr
= interp
->sh_addr
;
1884 ph
->p_paddr
= ph
->p_vaddr
;
1885 ph
->p_filesz
= interp
->sh_size
;
1886 ph
->p_memsz
= interp
->sh_size
;
1888 ph
->p_align
= interp
->sh_addralign
;
1891 /* if dynamic section, then add corresponing program header */
1895 ph
= &phdr
[phnum
- 1];
1897 ph
->p_type
= PT_DYNAMIC
;
1898 ph
->p_offset
= dynamic
->sh_offset
;
1899 ph
->p_vaddr
= dynamic
->sh_addr
;
1900 ph
->p_paddr
= ph
->p_vaddr
;
1901 ph
->p_filesz
= dynamic
->sh_size
;
1902 ph
->p_memsz
= dynamic
->sh_size
;
1903 ph
->p_flags
= PF_R
| PF_W
;
1904 ph
->p_align
= dynamic
->sh_addralign
;
1906 /* put GOT dynamic section address */
1907 put32(s1
->got
->data
, dynamic
->sh_addr
);
1909 /* relocate the PLT */
1910 if (file_type
== TCC_OUTPUT_EXE
1911 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1912 || file_type
== TCC_OUTPUT_DLL
1918 p_end
= p
+ s1
->plt
->data_offset
;
1920 #if defined(TCC_TARGET_I386)
1921 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
1922 put32(p
+ 8, get32(p
+ 8) + s1
->got
->sh_addr
);
1925 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
1928 #elif defined(TCC_TARGET_X86_64)
1929 int x
= s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 6;
1930 put32(p
+ 2, get32(p
+ 2) + x
);
1931 put32(p
+ 8, get32(p
+ 8) + x
- 6);
1934 put32(p
+ 2, get32(p
+ 2) + x
+ s1
->plt
->data
- p
);
1937 #elif defined(TCC_TARGET_ARM)
1939 x
=s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 12;
1942 put32(p
+ 12, x
+ get32(p
+ 12) + s1
->plt
->data
- p
);
1945 #elif defined(TCC_TARGET_C67)
1948 #error unsupported CPU
1953 /* relocate symbols in .dynsym */
1954 sym_end
= (ElfW(Sym
) *)(s1
->dynsym
->data
+ s1
->dynsym
->data_offset
);
1955 for(sym
= (ElfW(Sym
) *)s1
->dynsym
->data
+ 1;
1958 if (sym
->st_shndx
== SHN_UNDEF
) {
1959 /* relocate to the PLT if the symbol corresponds
1962 sym
->st_value
+= s1
->plt
->sh_addr
;
1963 } else if (sym
->st_shndx
< SHN_LORESERVE
) {
1964 /* do symbol relocation */
1965 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
1969 /* put dynamic section entries */
1970 dynamic
->data_offset
= saved_dynamic_data_offset
;
1971 put_dt(dynamic
, DT_HASH
, s1
->dynsym
->hash
->sh_addr
);
1972 put_dt(dynamic
, DT_STRTAB
, dynstr
->sh_addr
);
1973 put_dt(dynamic
, DT_SYMTAB
, s1
->dynsym
->sh_addr
);
1974 put_dt(dynamic
, DT_STRSZ
, dynstr
->data_offset
);
1975 put_dt(dynamic
, DT_SYMENT
, sizeof(ElfW(Sym
)));
1976 #ifdef TCC_TARGET_X86_64
1977 put_dt(dynamic
, DT_RELA
, rel_addr
);
1978 put_dt(dynamic
, DT_RELASZ
, rel_size
);
1979 put_dt(dynamic
, DT_RELAENT
, sizeof(ElfW_Rel
));
1981 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1982 put_dt(dynamic
, DT_PLTGOT
, s1
->got
->sh_addr
);
1983 put_dt(dynamic
, DT_PLTRELSZ
, rel_size
);
1984 put_dt(dynamic
, DT_JMPREL
, rel_addr
);
1985 put_dt(dynamic
, DT_PLTREL
, DT_REL
);
1986 put_dt(dynamic
, DT_REL
, bss_addr
);
1987 put_dt(dynamic
, DT_RELSZ
, bss_size
);
1989 put_dt(dynamic
, DT_REL
, rel_addr
);
1990 put_dt(dynamic
, DT_RELSZ
, rel_size
);
1991 put_dt(dynamic
, DT_RELENT
, sizeof(ElfW_Rel
));
1995 put_dt(dynamic
, DT_DEBUG
, 0);
1996 put_dt(dynamic
, DT_NULL
, 0);
1999 ehdr
.e_phentsize
= sizeof(ElfW(Phdr
));
2000 ehdr
.e_phnum
= phnum
;
2001 ehdr
.e_phoff
= sizeof(ElfW(Ehdr
));
2004 /* all other sections come after */
2005 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2006 s
= s1
->sections
[i
];
2007 if (phnum
> 0 && (s
->sh_flags
& SHF_ALLOC
))
2009 section_order
[sh_order_index
++] = i
;
2011 file_offset
= (file_offset
+ s
->sh_addralign
- 1) &
2012 ~(s
->sh_addralign
- 1);
2013 s
->sh_offset
= file_offset
;
2014 if (s
->sh_type
!= SHT_NOBITS
)
2015 file_offset
+= s
->sh_size
;
2018 /* if building executable or DLL, then relocate each section
2019 except the GOT which is already relocated */
2020 if (file_type
!= TCC_OUTPUT_OBJ
) {
2021 relocate_syms(s1
, 0);
2023 if (s1
->nb_errors
!= 0) {
2029 /* relocate sections */
2030 /* XXX: ignore sections with allocated relocations ? */
2031 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2032 s
= s1
->sections
[i
];
2033 if (s
->reloc
&& s
!= s1
->got
&& (s
->sh_flags
& SHF_ALLOC
)) //gr
2034 relocate_section(s1
, s
);
2037 /* relocate relocation entries if the relocation tables are
2038 allocated in the executable */
2039 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2040 s
= s1
->sections
[i
];
2041 if ((s
->sh_flags
& SHF_ALLOC
) &&
2042 s
->sh_type
== SHT_RELX
) {
2043 relocate_rel(s1
, s
);
2047 /* get entry point address */
2048 if (file_type
== TCC_OUTPUT_EXE
)
2049 ehdr
.e_entry
= (uplong
)tcc_get_symbol_err(s1
, "_start");
2051 ehdr
.e_entry
= text_section
->sh_addr
; /* XXX: is it correct ? */
2053 if (file_type
== TCC_OUTPUT_EXE
&& s1
->static_link
)
2056 /* write elf file */
2057 if (file_type
== TCC_OUTPUT_OBJ
)
2062 fd
= open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
, mode
);
2064 tcc_error_noabort("could not write '%s'", filename
);
2067 f
= fdopen(fd
, "wb");
2069 printf("<- %s\n", filename
);
2071 #ifdef TCC_TARGET_COFF
2072 if (s1
->output_format
== TCC_OUTPUT_FORMAT_COFF
) {
2073 tcc_output_coff(s1
, f
);
2076 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
2077 sort_syms(s1
, symtab_section
);
2080 file_offset
= (file_offset
+ 3) & -4;
2083 ehdr
.e_ident
[0] = ELFMAG0
;
2084 ehdr
.e_ident
[1] = ELFMAG1
;
2085 ehdr
.e_ident
[2] = ELFMAG2
;
2086 ehdr
.e_ident
[3] = ELFMAG3
;
2087 ehdr
.e_ident
[4] = ELFCLASSW
;
2088 ehdr
.e_ident
[5] = ELFDATA2LSB
;
2089 ehdr
.e_ident
[6] = EV_CURRENT
;
2090 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2091 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_FREEBSD
;
2093 #ifdef TCC_TARGET_ARM
2095 ehdr
.e_ident
[EI_OSABI
] = 0;
2096 ehdr
.e_flags
= 4 << 24;
2098 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_ARM
;
2103 case TCC_OUTPUT_EXE
:
2104 ehdr
.e_type
= ET_EXEC
;
2106 case TCC_OUTPUT_DLL
:
2107 ehdr
.e_type
= ET_DYN
;
2109 case TCC_OUTPUT_OBJ
:
2110 ehdr
.e_type
= ET_REL
;
2113 ehdr
.e_machine
= EM_TCC_TARGET
;
2114 ehdr
.e_version
= EV_CURRENT
;
2115 ehdr
.e_shoff
= file_offset
;
2116 ehdr
.e_ehsize
= sizeof(ElfW(Ehdr
));
2117 ehdr
.e_shentsize
= sizeof(ElfW(Shdr
));
2118 ehdr
.e_shnum
= shnum
;
2119 ehdr
.e_shstrndx
= shnum
- 1;
2121 fwrite(&ehdr
, 1, sizeof(ElfW(Ehdr
)), f
);
2122 fwrite(phdr
, 1, phnum
* sizeof(ElfW(Phdr
)), f
);
2123 offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
2125 for(i
=1;i
<s1
->nb_sections
;i
++) {
2126 s
= s1
->sections
[section_order
[i
]];
2127 if (s
->sh_type
!= SHT_NOBITS
) {
2128 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2129 if (s
->sh_type
== SHT_DYNSYM
)
2130 patch_dynsym_undef(s1
, s
);
2132 while (offset
< s
->sh_offset
) {
2137 fwrite(s
->data
, 1, size
, f
);
2142 /* output section headers */
2143 while (offset
< ehdr
.e_shoff
) {
2148 for(i
=0;i
<s1
->nb_sections
;i
++) {
2150 memset(sh
, 0, sizeof(ElfW(Shdr
)));
2151 s
= s1
->sections
[i
];
2153 sh
->sh_name
= s
->sh_name
;
2154 sh
->sh_type
= s
->sh_type
;
2155 sh
->sh_flags
= s
->sh_flags
;
2156 sh
->sh_entsize
= s
->sh_entsize
;
2157 sh
->sh_info
= s
->sh_info
;
2159 sh
->sh_link
= s
->link
->sh_num
;
2160 sh
->sh_addralign
= s
->sh_addralign
;
2161 sh
->sh_addr
= s
->sh_addr
;
2162 sh
->sh_offset
= s
->sh_offset
;
2163 sh
->sh_size
= s
->sh_size
;
2165 fwrite(sh
, 1, sizeof(ElfW(Shdr
)), f
);
2168 tcc_output_binary(s1
, f
, section_order
);
2174 tcc_free(s1
->symtab_to_dynsym
);
2175 tcc_free(section_order
);
2177 tcc_free(s1
->got_offsets
);
2181 LIBTCCAPI
int tcc_output_file(TCCState
*s
, const char *filename
)
2184 #ifdef TCC_TARGET_PE
2185 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
2186 ret
= pe_output_file(s
, filename
);
2190 ret
= elf_output_file(s
, filename
);
2195 static void *load_data(int fd
, unsigned long file_offset
, unsigned long size
)
2199 data
= tcc_malloc(size
);
2200 lseek(fd
, file_offset
, SEEK_SET
);
2201 read(fd
, data
, size
);
2205 typedef struct SectionMergeInfo
{
2206 Section
*s
; /* corresponding existing section */
2207 unsigned long offset
; /* offset of the new section in the existing section */
2208 uint8_t new_section
; /* true if section 's' was added */
2209 uint8_t link_once
; /* true if link once section */
2212 /* load an object file and merge it with current files */
2213 /* XXX: handle correctly stab (debug) info */
2214 ST_FUNC
int tcc_load_object_file(TCCState
*s1
,
2215 int fd
, unsigned long file_offset
)
2218 ElfW(Shdr
) *shdr
, *sh
;
2219 int size
, i
, j
, offset
, offseti
, nb_syms
, sym_index
, ret
;
2220 unsigned char *strsec
, *strtab
;
2221 int *old_to_new_syms
;
2222 char *sh_name
, *name
;
2223 SectionMergeInfo
*sm_table
, *sm
;
2224 ElfW(Sym
) *sym
, *symtab
;
2225 ElfW_Rel
*rel
, *rel_end
;
2231 stab_index
= stabstr_index
= 0;
2233 if (read(fd
, &ehdr
, sizeof(ehdr
)) != sizeof(ehdr
))
2235 if (ehdr
.e_ident
[0] != ELFMAG0
||
2236 ehdr
.e_ident
[1] != ELFMAG1
||
2237 ehdr
.e_ident
[2] != ELFMAG2
||
2238 ehdr
.e_ident
[3] != ELFMAG3
)
2240 /* test if object file */
2241 if (ehdr
.e_type
!= ET_REL
)
2243 /* test CPU specific stuff */
2244 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2245 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2247 tcc_error_noabort("invalid object file");
2251 shdr
= load_data(fd
, file_offset
+ ehdr
.e_shoff
,
2252 sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2253 sm_table
= tcc_mallocz(sizeof(SectionMergeInfo
) * ehdr
.e_shnum
);
2255 /* load section names */
2256 sh
= &shdr
[ehdr
.e_shstrndx
];
2257 strsec
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2259 /* load symtab and strtab */
2260 old_to_new_syms
= NULL
;
2264 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2266 if (sh
->sh_type
== SHT_SYMTAB
) {
2268 tcc_error_noabort("object must contain only one symtab");
2273 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2274 symtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2275 sm_table
[i
].s
= symtab_section
;
2277 /* now load strtab */
2278 sh
= &shdr
[sh
->sh_link
];
2279 strtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2283 /* now examine each section and try to merge its content with the
2285 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2286 /* no need to examine section name strtab */
2287 if (i
== ehdr
.e_shstrndx
)
2290 sh_name
= strsec
+ sh
->sh_name
;
2291 /* ignore sections types we do not handle */
2292 if (sh
->sh_type
!= SHT_PROGBITS
&&
2293 sh
->sh_type
!= SHT_RELX
&&
2295 sh
->sh_type
!= SHT_ARM_EXIDX
&&
2297 sh
->sh_type
!= SHT_NOBITS
&&
2298 sh
->sh_type
!= SHT_PREINIT_ARRAY
&&
2299 sh
->sh_type
!= SHT_INIT_ARRAY
&&
2300 sh
->sh_type
!= SHT_FINI_ARRAY
&&
2301 strcmp(sh_name
, ".stabstr")
2304 if (sh
->sh_addralign
< 1)
2305 sh
->sh_addralign
= 1;
2306 /* find corresponding section, if any */
2307 for(j
= 1; j
< s1
->nb_sections
;j
++) {
2308 s
= s1
->sections
[j
];
2309 if (!strcmp(s
->name
, sh_name
)) {
2310 if (!strncmp(sh_name
, ".gnu.linkonce",
2311 sizeof(".gnu.linkonce") - 1)) {
2312 /* if a 'linkonce' section is already present, we
2313 do not add it again. It is a little tricky as
2314 symbols can still be defined in
2316 sm_table
[i
].link_once
= 1;
2323 /* not found: create new section */
2324 s
= new_section(s1
, sh_name
, sh
->sh_type
, sh
->sh_flags
);
2325 /* take as much info as possible from the section. sh_link and
2326 sh_info will be updated later */
2327 s
->sh_addralign
= sh
->sh_addralign
;
2328 s
->sh_entsize
= sh
->sh_entsize
;
2329 sm_table
[i
].new_section
= 1;
2331 if (sh
->sh_type
!= s
->sh_type
) {
2332 tcc_error_noabort("invalid section type");
2336 /* align start of section */
2337 offset
= s
->data_offset
;
2339 if (0 == strcmp(sh_name
, ".stab")) {
2343 if (0 == strcmp(sh_name
, ".stabstr")) {
2348 size
= sh
->sh_addralign
- 1;
2349 offset
= (offset
+ size
) & ~size
;
2350 if (sh
->sh_addralign
> s
->sh_addralign
)
2351 s
->sh_addralign
= sh
->sh_addralign
;
2352 s
->data_offset
= offset
;
2354 sm_table
[i
].offset
= offset
;
2356 /* concatenate sections */
2358 if (sh
->sh_type
!= SHT_NOBITS
) {
2360 lseek(fd
, file_offset
+ sh
->sh_offset
, SEEK_SET
);
2361 ptr
= section_ptr_add(s
, size
);
2362 read(fd
, ptr
, size
);
2364 s
->data_offset
+= size
;
2369 /* //gr relocate stab strings */
2370 if (stab_index
&& stabstr_index
) {
2373 s
= sm_table
[stab_index
].s
;
2374 a
= (Stab_Sym
*)(s
->data
+ sm_table
[stab_index
].offset
);
2375 b
= (Stab_Sym
*)(s
->data
+ s
->data_offset
);
2376 o
= sm_table
[stabstr_index
].offset
;
2378 a
->n_strx
+= o
, a
++;
2381 /* second short pass to update sh_link and sh_info fields of new
2383 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2385 if (!s
|| !sm_table
[i
].new_section
)
2388 if (sh
->sh_link
> 0)
2389 s
->link
= sm_table
[sh
->sh_link
].s
;
2390 if (sh
->sh_type
== SHT_RELX
) {
2391 s
->sh_info
= sm_table
[sh
->sh_info
].s
->sh_num
;
2392 /* update backward link */
2393 s1
->sections
[s
->sh_info
]->reloc
= s
;
2398 /* resolve symbols */
2399 old_to_new_syms
= tcc_mallocz(nb_syms
* sizeof(int));
2402 for(i
= 1; i
< nb_syms
; i
++, sym
++) {
2403 if (sym
->st_shndx
!= SHN_UNDEF
&&
2404 sym
->st_shndx
< SHN_LORESERVE
) {
2405 sm
= &sm_table
[sym
->st_shndx
];
2406 if (sm
->link_once
) {
2407 /* if a symbol is in a link once section, we use the
2408 already defined symbol. It is very important to get
2409 correct relocations */
2410 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
2411 name
= strtab
+ sym
->st_name
;
2412 sym_index
= find_elf_sym(symtab_section
, name
);
2414 old_to_new_syms
[i
] = sym_index
;
2418 /* if no corresponding section added, no need to add symbol */
2421 /* convert section number */
2422 sym
->st_shndx
= sm
->s
->sh_num
;
2424 sym
->st_value
+= sm
->offset
;
2427 name
= strtab
+ sym
->st_name
;
2428 sym_index
= add_elf_sym(symtab_section
, sym
->st_value
, sym
->st_size
,
2429 sym
->st_info
, sym
->st_other
,
2430 sym
->st_shndx
, name
);
2431 old_to_new_syms
[i
] = sym_index
;
2434 /* third pass to patch relocation entries */
2435 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2440 offset
= sm_table
[i
].offset
;
2441 switch(s
->sh_type
) {
2443 /* take relocation offset information */
2444 offseti
= sm_table
[sh
->sh_info
].offset
;
2445 rel_end
= (ElfW_Rel
*)(s
->data
+ s
->data_offset
);
2446 for(rel
= (ElfW_Rel
*)(s
->data
+ offset
);
2451 /* convert symbol index */
2452 type
= ELFW(R_TYPE
)(rel
->r_info
);
2453 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
2454 /* NOTE: only one symtab assumed */
2455 if (sym_index
>= nb_syms
)
2457 sym_index
= old_to_new_syms
[sym_index
];
2458 /* ignore link_once in rel section. */
2459 if (!sym_index
&& !sm
->link_once
2460 #ifdef TCC_TARGET_ARM
2461 && type
!= R_ARM_V4BX
2465 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2466 i
, strsec
+ sh
->sh_name
, rel
->r_offset
);
2469 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
2470 /* offset the relocation offset */
2471 rel
->r_offset
+= offseti
;
2483 tcc_free(old_to_new_syms
);
2490 typedef struct ArchiveHeader
{
2491 char ar_name
[16]; /* name of this member */
2492 char ar_date
[12]; /* file mtime */
2493 char ar_uid
[6]; /* owner uid; printed as decimal */
2494 char ar_gid
[6]; /* owner gid; printed as decimal */
2495 char ar_mode
[8]; /* file mode, printed as octal */
2496 char ar_size
[10]; /* file size, printed as decimal */
2497 char ar_fmag
[2]; /* should contain ARFMAG */
2500 static int get_be32(const uint8_t *b
)
2502 return b
[3] | (b
[2] << 8) | (b
[1] << 16) | (b
[0] << 24);
2505 /* load only the objects which resolve undefined symbols */
2506 static int tcc_load_alacarte(TCCState
*s1
, int fd
, int size
)
2508 int i
, bound
, nsyms
, sym_index
, off
, ret
;
2510 const char *ar_names
, *p
;
2511 const uint8_t *ar_index
;
2514 data
= tcc_malloc(size
);
2515 if (read(fd
, data
, size
) != size
)
2517 nsyms
= get_be32(data
);
2518 ar_index
= data
+ 4;
2519 ar_names
= ar_index
+ nsyms
* 4;
2523 for(p
= ar_names
, i
= 0; i
< nsyms
; i
++, p
+= strlen(p
)+1) {
2524 sym_index
= find_elf_sym(symtab_section
, p
);
2526 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
2527 if(sym
->st_shndx
== SHN_UNDEF
) {
2528 off
= get_be32(ar_index
+ i
* 4) + sizeof(ArchiveHeader
);
2530 printf("%5d\t%s\t%08x\n", i
, p
, sym
->st_shndx
);
2533 lseek(fd
, off
, SEEK_SET
);
2534 if(tcc_load_object_file(s1
, fd
, off
) < 0) {
2549 /* load a '.a' file */
2550 ST_FUNC
int tcc_load_archive(TCCState
*s1
, int fd
)
2557 unsigned long file_offset
;
2559 /* skip magic which was already checked */
2560 read(fd
, magic
, sizeof(magic
));
2563 len
= read(fd
, &hdr
, sizeof(hdr
));
2566 if (len
!= sizeof(hdr
)) {
2567 tcc_error_noabort("invalid archive");
2570 memcpy(ar_size
, hdr
.ar_size
, sizeof(hdr
.ar_size
));
2571 ar_size
[sizeof(hdr
.ar_size
)] = '\0';
2572 size
= strtol(ar_size
, NULL
, 0);
2573 memcpy(ar_name
, hdr
.ar_name
, sizeof(hdr
.ar_name
));
2574 for(i
= sizeof(hdr
.ar_name
) - 1; i
>= 0; i
--) {
2575 if (ar_name
[i
] != ' ')
2578 ar_name
[i
+ 1] = '\0';
2579 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2580 file_offset
= lseek(fd
, 0, SEEK_CUR
);
2582 size
= (size
+ 1) & ~1;
2583 if (!strcmp(ar_name
, "/")) {
2584 /* coff symbol table : we handle it */
2585 if(s1
->alacarte_link
)
2586 return tcc_load_alacarte(s1
, fd
, size
);
2587 } else if (!strcmp(ar_name
, "//") ||
2588 !strcmp(ar_name
, "__.SYMDEF") ||
2589 !strcmp(ar_name
, "__.SYMDEF/") ||
2590 !strcmp(ar_name
, "ARFILENAMES/")) {
2591 /* skip symbol table or archive names */
2593 if (tcc_load_object_file(s1
, fd
, file_offset
) < 0)
2596 lseek(fd
, file_offset
+ size
, SEEK_SET
);
2601 #ifndef TCC_TARGET_PE
2602 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2603 is referenced by the user (so it should be added as DT_NEEDED in
2604 the generated ELF file) */
2605 ST_FUNC
int tcc_load_dll(TCCState
*s1
, int fd
, const char *filename
, int level
)
2608 ElfW(Shdr
) *shdr
, *sh
, *sh1
;
2609 int i
, j
, nb_syms
, nb_dts
, sym_bind
, ret
;
2610 ElfW(Sym
) *sym
, *dynsym
;
2611 ElfW(Dyn
) *dt
, *dynamic
;
2612 unsigned char *dynstr
;
2613 const char *name
, *soname
;
2614 DLLReference
*dllref
;
2616 read(fd
, &ehdr
, sizeof(ehdr
));
2618 /* test CPU specific stuff */
2619 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2620 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2621 tcc_error_noabort("bad architecture");
2626 shdr
= load_data(fd
, ehdr
.e_shoff
, sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2628 /* load dynamic section and dynamic symbols */
2632 dynsym
= NULL
; /* avoid warning */
2633 dynstr
= NULL
; /* avoid warning */
2634 for(i
= 0, sh
= shdr
; i
< ehdr
.e_shnum
; i
++, sh
++) {
2635 switch(sh
->sh_type
) {
2637 nb_dts
= sh
->sh_size
/ sizeof(ElfW(Dyn
));
2638 dynamic
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2641 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2642 dynsym
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2643 sh1
= &shdr
[sh
->sh_link
];
2644 dynstr
= load_data(fd
, sh1
->sh_offset
, sh1
->sh_size
);
2651 /* compute the real library name */
2652 soname
= tcc_basename(filename
);
2654 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2655 if (dt
->d_tag
== DT_SONAME
) {
2656 soname
= dynstr
+ dt
->d_un
.d_val
;
2660 /* if the dll is already loaded, do not load it */
2661 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
2662 dllref
= s1
->loaded_dlls
[i
];
2663 if (!strcmp(soname
, dllref
->name
)) {
2664 /* but update level if needed */
2665 if (level
< dllref
->level
)
2666 dllref
->level
= level
;
2672 // printf("loading dll '%s'\n", soname);
2674 /* add the dll and its level */
2675 dllref
= tcc_mallocz(sizeof(DLLReference
) + strlen(soname
));
2676 dllref
->level
= level
;
2677 strcpy(dllref
->name
, soname
);
2678 dynarray_add((void ***)&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
, dllref
);
2680 /* add dynamic symbols in dynsym_section */
2681 for(i
= 1, sym
= dynsym
+ 1; i
< nb_syms
; i
++, sym
++) {
2682 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
2683 if (sym_bind
== STB_LOCAL
)
2685 name
= dynstr
+ sym
->st_name
;
2686 add_elf_sym(s1
->dynsymtab_section
, sym
->st_value
, sym
->st_size
,
2687 sym
->st_info
, sym
->st_other
, sym
->st_shndx
, name
);
2690 /* load all referenced DLLs */
2691 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2694 name
= dynstr
+ dt
->d_un
.d_val
;
2695 for(j
= 0; j
< s1
->nb_loaded_dlls
; j
++) {
2696 dllref
= s1
->loaded_dlls
[j
];
2697 if (!strcmp(name
, dllref
->name
))
2698 goto already_loaded
;
2700 if (tcc_add_dll(s1
, name
, AFF_REFERENCED_DLL
) < 0) {
2701 tcc_error_noabort("referenced dll '%s' not found", name
);
2718 #define LD_TOK_NAME 256
2719 #define LD_TOK_EOF (-1)
2721 /* return next ld script token */
2722 static int ld_next(TCCState
*s1
, char *name
, int name_size
)
2740 file
->buf_ptr
= parse_comment(file
->buf_ptr
);
2741 ch
= file
->buf_ptr
[0];
2749 /* case 'a' ... 'z': */
2776 /* case 'A' ... 'z': */
2811 if (!((ch
>= 'a' && ch
<= 'z') ||
2812 (ch
>= 'A' && ch
<= 'Z') ||
2813 (ch
>= '0' && ch
<= '9') ||
2814 strchr("/.-_+=$:\\,~", ch
)))
2816 if ((q
- name
) < name_size
- 1) {
2833 printf("tok=%c %d\n", c
, c
);
2834 if (c
== LD_TOK_NAME
)
2835 printf(" name=%s\n", name
);
2841 * Extract the library name from the file name
2842 * Return 0 if the file isn't a library
2844 * /!\ No test on filename capacity, be careful
2846 static int filename_to_libname(TCCState
*s1
, const char filename
[], char libname
[])
2851 /* already converted to library name */
2852 if (libname
[0] != '\0')
2854 ext
= tcc_fileextension(filename
);
2857 libprefix
= !strncmp(filename
, "lib", 3);
2858 if (!s1
->static_link
) {
2859 if (libprefix
&& (!strcmp(ext
, ".so"))) {
2860 size_t len
= ext
- filename
- 3;
2861 pstrncpy(libname
, filename
+ 3, len
);
2865 if (libprefix
&& (!strcmp(ext
, ".a"))) {
2866 size_t len
= ext
- filename
- 3;
2867 pstrncpy(libname
, filename
+ 3, len
);
2875 * Extract the file name from the library name
2877 * /!\ No test on filename capacity, be careful
2879 static void libname_to_filename(TCCState
*s1
, const char libname
[], char filename
[])
2881 if (!s1
->static_link
) {
2882 sprintf(filename
, "lib%s.so", libname
);
2884 sprintf(filename
, "lib%s.a", libname
);
2888 static int ld_add_file(TCCState
*s1
, const char filename
[], char libname
[])
2892 ret
= tcc_add_file_internal(s1
, filename
, 0);
2894 if (filename_to_libname(s1
, filename
, libname
))
2895 ret
= tcc_add_library(s1
, libname
);
2900 static inline int new_undef_syms(void)
2903 ret
= new_undef_sym
;
2908 static int ld_add_file_list(TCCState
*s1
, const char *cmd
, int as_needed
)
2910 char filename
[1024], libname
[1024];
2911 int t
, group
, nblibs
= 0, ret
= 0;
2914 group
= !strcmp(cmd
, "GROUP");
2917 t
= ld_next(s1
, filename
, sizeof(filename
));
2920 t
= ld_next(s1
, filename
, sizeof(filename
));
2923 if (t
== LD_TOK_EOF
) {
2924 tcc_error_noabort("unexpected end of file");
2926 goto lib_parse_error
;
2927 } else if (t
== ')') {
2929 } else if (t
== '-') {
2930 t
= ld_next(s1
, filename
, sizeof(filename
));
2931 if ((t
!= LD_TOK_NAME
) || (filename
[0] != 'l')) {
2932 tcc_error_noabort("library name expected");
2934 goto lib_parse_error
;
2936 strcpy(libname
, &filename
[1]);
2937 libname_to_filename(s1
, libname
, filename
);
2938 } else if (t
!= LD_TOK_NAME
) {
2939 tcc_error_noabort("filename expected");
2941 goto lib_parse_error
;
2943 if (!strcmp(filename
, "AS_NEEDED")) {
2944 ret
= ld_add_file_list(s1
, cmd
, 1);
2946 goto lib_parse_error
;
2948 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2950 ret
= ld_add_file(s1
, filename
, libname
);
2952 goto lib_parse_error
;
2954 /* Add the filename *and* the libname to avoid future conversions */
2955 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(filename
));
2956 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(libname
));
2960 t
= ld_next(s1
, filename
, sizeof(filename
));
2962 t
= ld_next(s1
, filename
, sizeof(filename
));
2965 if (group
&& !as_needed
) {
2966 while (new_undef_syms()) {
2969 for (i
= 0; i
< nblibs
; i
+= 2)
2970 ld_add_file(s1
, libs
[i
], libs
[i
+1]);
2974 dynarray_reset(&libs
, &nblibs
);
2978 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
2980 ST_FUNC
int tcc_load_ldscript(TCCState
*s1
)
2983 char filename
[1024];
2986 ch
= file
->buf_ptr
[0];
2989 t
= ld_next(s1
, cmd
, sizeof(cmd
));
2990 if (t
== LD_TOK_EOF
)
2992 else if (t
!= LD_TOK_NAME
)
2994 if (!strcmp(cmd
, "INPUT") ||
2995 !strcmp(cmd
, "GROUP")) {
2996 ret
= ld_add_file_list(s1
, cmd
, 0);
2999 } else if (!strcmp(cmd
, "OUTPUT_FORMAT") ||
3000 !strcmp(cmd
, "TARGET")) {
3001 /* ignore some commands */
3002 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3006 t
= ld_next(s1
, filename
, sizeof(filename
));
3007 if (t
== LD_TOK_EOF
) {
3008 tcc_error_noabort("unexpected end of file");
3010 } else if (t
== ')') {
3020 #endif /* ndef TCC_TARGET_PE */