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
1360 /* zero plt offsets of weak symbols in .dynsym */
1361 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1363 ElfW(Sym
) *sym
, *sym_end
;
1365 sym_end
= (ElfW(Sym
) *)(s
->data
+ s
->data_offset
);
1366 for (sym
= (ElfW(Sym
) *)s
->data
+ 1; sym
< sym_end
; sym
++)
1367 if (sym
->st_shndx
== SHN_UNDEF
&& ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
1372 ST_FUNC
void fill_got_entry(TCCState
*s1
, ElfW_Rel
*rel
)
1374 int sym_index
= ELFW(R_SYM
) (rel
->r_info
);
1375 ElfW(Sym
) *sym
= &((ElfW(Sym
) *) symtab_section
->data
)[sym_index
];
1376 unsigned long offset
;
1378 if (sym_index
>= s1
->nb_got_offsets
)
1380 offset
= s1
->got_offsets
[sym_index
];
1381 section_reserve(s1
->got
, offset
+ PTR_SIZE
);
1382 #ifdef TCC_TARGET_X86_64
1383 /* only works for x86-64 */
1384 put32(s1
->got
->data
+ offset
, sym
->st_value
>> 32);
1386 put32(s1
->got
->data
+ offset
, sym
->st_value
& 0xffffffff);
1389 ST_FUNC
void fill_got(TCCState
*s1
)
1392 ElfW_Rel
*rel
, *rel_end
;
1395 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1396 s
= s1
->sections
[i
];
1397 if (s
->sh_type
!= SHT_RELX
)
1399 /* no need to handle got relocations */
1400 if (s
->link
!= symtab_section
)
1402 rel_end
= (ElfW_Rel
*) (s
->data
+ s
->data_offset
);
1403 for(rel
= (ElfW_Rel
*) s
->data
; rel
< rel_end
; rel
++) {
1404 switch (ELFW(R_TYPE
) (rel
->r_info
)) {
1405 case R_X86_64_GOT32
:
1406 case R_X86_64_GOTPCREL
:
1407 case R_X86_64_PLT32
:
1408 fill_got_entry(s1
, rel
);
1416 /* output an ELF file */
1417 /* XXX: suppress unneeded sections */
1418 static int elf_output_file(TCCState
*s1
, const char *filename
)
1424 int shnum
, i
, phnum
, file_offset
, offset
, size
, j
, tmp
, sh_order_index
, k
;
1426 Section
*strsec
, *s
;
1427 ElfW(Shdr
) shdr
, *sh
;
1428 ElfW(Phdr
) *phdr
, *ph
;
1429 Section
*interp
, *dynamic
, *dynstr
;
1430 unsigned long saved_dynamic_data_offset
;
1432 int type
, file_type
;
1433 unsigned long rel_addr
, rel_size
;
1434 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1435 unsigned long bss_addr
, bss_size
;
1438 file_type
= s1
->output_type
;
1441 if (file_type
!= TCC_OUTPUT_OBJ
) {
1442 tcc_add_runtime(s1
);
1446 section_order
= NULL
;
1449 dynstr
= NULL
; /* avoid warning */
1450 saved_dynamic_data_offset
= 0; /* avoid warning */
1452 if (file_type
!= TCC_OUTPUT_OBJ
) {
1453 relocate_common_syms();
1455 tcc_add_linker_symbols(s1
);
1457 if (!s1
->static_link
) {
1459 int sym_index
, index
;
1460 ElfW(Sym
) *esym
, *sym_end
;
1462 if (file_type
== TCC_OUTPUT_EXE
) {
1464 /* allow override the dynamic loader */
1465 const char *elfint
= getenv("LD_SO");
1467 elfint
= CONFIG_TCC_ELFINTERP
;
1468 /* add interpreter section only if executable */
1469 interp
= new_section(s1
, ".interp", SHT_PROGBITS
, SHF_ALLOC
);
1470 interp
->sh_addralign
= 1;
1471 ptr
= section_ptr_add(interp
, 1+strlen(elfint
));
1472 strcpy(ptr
, elfint
);
1475 /* add dynamic symbol table */
1476 s1
->dynsym
= new_symtab(s1
, ".dynsym", SHT_DYNSYM
, SHF_ALLOC
,
1478 ".hash", SHF_ALLOC
);
1479 dynstr
= s1
->dynsym
->link
;
1481 /* add dynamic section */
1482 dynamic
= new_section(s1
, ".dynamic", SHT_DYNAMIC
,
1483 SHF_ALLOC
| SHF_WRITE
);
1484 dynamic
->link
= dynstr
;
1485 dynamic
->sh_entsize
= sizeof(ElfW(Dyn
));
1488 s1
->plt
= new_section(s1
, ".plt", SHT_PROGBITS
,
1489 SHF_ALLOC
| SHF_EXECINSTR
);
1490 s1
->plt
->sh_entsize
= 4;
1494 /* scan for undefined symbols and see if they are in the
1495 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1496 is found, then we add it in the PLT. If a symbol
1497 STT_OBJECT is found, we add it in the .bss section with
1498 a suitable relocation */
1499 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+
1500 symtab_section
->data_offset
);
1501 if (file_type
== TCC_OUTPUT_EXE
) {
1502 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
1505 if (sym
->st_shndx
== SHN_UNDEF
) {
1506 name
= symtab_section
->link
->data
+ sym
->st_name
;
1507 sym_index
= find_elf_sym(s1
->dynsymtab_section
, name
);
1509 esym
= &((ElfW(Sym
) *)s1
->dynsymtab_section
->data
)[sym_index
];
1510 type
= ELFW(ST_TYPE
)(esym
->st_info
);
1511 if ((type
== STT_FUNC
) || (type
== STT_GNU_IFUNC
)) {
1512 put_got_entry(s1
, R_JMP_SLOT
, esym
->st_size
,
1513 ELFW(ST_INFO
)(STB_GLOBAL
,type
),
1514 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1515 } else if (type
== STT_OBJECT
) {
1516 unsigned long offset
;
1517 ElfW(Sym
) *dynsym
, *dynsym_end
;
1518 offset
= bss_section
->data_offset
;
1519 /* XXX: which alignment ? */
1520 offset
= (offset
+ 16 - 1) & -16;
1521 index
= put_elf_sym(s1
->dynsym
, offset
, esym
->st_size
,
1523 bss_section
->sh_num
, name
);
1524 // Ensure R_COPY works for weak symbol aliases
1525 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1526 dynsym_end
= (ElfW(Sym
) *)
1527 (s1
->dynsymtab_section
->data
+
1528 s1
->dynsymtab_section
->data_offset
);
1529 for(dynsym
= (ElfW(Sym
) *)s1
->dynsymtab_section
->data
+ 1;
1530 dynsym
< dynsym_end
; dynsym
++) {
1531 if ((dynsym
->st_value
== esym
->st_value
)
1532 && (ELFW(ST_BIND
)(dynsym
->st_info
) == STB_GLOBAL
)) {
1534 dynname
= s1
->dynsymtab_section
->link
->data
1536 put_elf_sym(s1
->dynsym
, offset
,
1539 bss_section
->sh_num
,
1545 put_elf_reloc(s1
->dynsym
, bss_section
,
1546 offset
, R_COPY
, index
);
1547 offset
+= esym
->st_size
;
1548 bss_section
->data_offset
= offset
;
1551 /* STB_WEAK undefined symbols are accepted */
1552 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1554 if (ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
||
1555 !strcmp(name
, "_fp_hw")) {
1557 tcc_error_noabort("undefined symbol '%s'", name
);
1560 } else if (s1
->rdynamic
&&
1561 ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1562 /* if -rdynamic option, then export all non
1564 name
= symtab_section
->link
->data
+ sym
->st_name
;
1565 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1567 sym
->st_shndx
, name
);
1574 /* now look at unresolved dynamic symbols and export
1575 corresponding symbol */
1576 sym_end
= (ElfW(Sym
) *)(s1
->dynsymtab_section
->data
+
1577 s1
->dynsymtab_section
->data_offset
);
1578 for(esym
= (ElfW(Sym
) *)s1
->dynsymtab_section
->data
+ 1;
1581 if (esym
->st_shndx
== SHN_UNDEF
) {
1582 name
= s1
->dynsymtab_section
->link
->data
+ esym
->st_name
;
1583 sym_index
= find_elf_sym(symtab_section
, name
);
1585 /* XXX: avoid adding a symbol if already
1586 present because of -rdynamic ? */
1587 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1588 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1590 sym
->st_shndx
, name
);
1592 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1593 /* weak symbols can stay undefined */
1595 tcc_warning("undefined dynamic symbol '%s'", name
);
1602 /* shared library case : we simply export all the global symbols */
1603 nb_syms
= symtab_section
->data_offset
/ sizeof(ElfW(Sym
));
1604 s1
->symtab_to_dynsym
= tcc_mallocz(sizeof(int) * nb_syms
);
1605 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
1608 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1609 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1610 if ((ELFW(ST_TYPE
)(sym
->st_info
) == STT_FUNC
||
1611 ELFW(ST_TYPE
)(sym
->st_info
) == STT_GNU_IFUNC
)
1612 && sym
->st_shndx
== SHN_UNDEF
) {
1613 put_got_entry(s1
, R_JMP_SLOT
, sym
->st_size
,
1615 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1617 else if (ELFW(ST_TYPE
)(sym
->st_info
) == STT_OBJECT
) {
1618 put_got_entry(s1
, R_X86_64_GLOB_DAT
, sym
->st_size
,
1620 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1625 name
= symtab_section
->link
->data
+ sym
->st_name
;
1626 index
= put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1628 sym
->st_shndx
, name
);
1629 s1
->symtab_to_dynsym
[sym
-
1630 (ElfW(Sym
) *)symtab_section
->data
] =
1637 build_got_entries(s1
);
1639 /* add a list of needed dlls */
1640 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
1641 DLLReference
*dllref
= s1
->loaded_dlls
[i
];
1642 if (dllref
->level
== 0)
1643 put_dt(dynamic
, DT_NEEDED
, put_elf_str(dynstr
, dllref
->name
));
1647 put_dt(dynamic
, DT_RPATH
, put_elf_str(dynstr
, s1
->rpath
));
1649 /* XXX: currently, since we do not handle PIC code, we
1650 must relocate the readonly segments */
1651 if (file_type
== TCC_OUTPUT_DLL
) {
1653 put_dt(dynamic
, DT_SONAME
, put_elf_str(dynstr
, s1
->soname
));
1654 put_dt(dynamic
, DT_TEXTREL
, 0);
1658 put_dt(dynamic
, DT_SYMBOLIC
, 0);
1660 /* add necessary space for other entries */
1661 saved_dynamic_data_offset
= dynamic
->data_offset
;
1662 dynamic
->data_offset
+= sizeof(ElfW(Dyn
)) * EXTRA_RELITEMS
;
1664 /* still need to build got entries in case of static link */
1665 build_got_entries(s1
);
1669 memset(&ehdr
, 0, sizeof(ehdr
));
1671 /* we add a section for symbols */
1672 strsec
= new_section(s1
, ".shstrtab", SHT_STRTAB
, 0);
1673 put_elf_str(strsec
, "");
1675 /* compute number of sections */
1676 shnum
= s1
->nb_sections
;
1678 /* this array is used to reorder sections in the output file */
1679 section_order
= tcc_malloc(sizeof(int) * shnum
);
1680 section_order
[0] = 0;
1683 /* compute number of program headers */
1686 case TCC_OUTPUT_OBJ
:
1689 case TCC_OUTPUT_EXE
:
1690 if (!s1
->static_link
)
1691 phnum
= 4 + HAVE_PHDR
;
1695 case TCC_OUTPUT_DLL
:
1700 /* allocate strings for section names and decide if an unallocated
1701 section should be output */
1702 /* NOTE: the strsec section comes last, so its size is also
1704 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1705 s
= s1
->sections
[i
];
1706 s
->sh_name
= put_elf_str(strsec
, s
->name
);
1708 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1713 s
->reloc
? s
->reloc
->name
: "n"
1716 /* when generating a DLL, we include relocations but we may
1718 if (file_type
== TCC_OUTPUT_DLL
&&
1719 s
->sh_type
== SHT_RELX
&&
1720 !(s
->sh_flags
& SHF_ALLOC
)) {
1721 /* //gr: avoid bogus relocs for empty (debug) sections */
1722 if (s1
->sections
[s
->sh_info
]->sh_flags
& SHF_ALLOC
)
1723 prepare_dynamic_rel(s1
, s
);
1724 else if (s1
->do_debug
)
1725 s
->sh_size
= s
->data_offset
;
1726 } else if (s1
->do_debug
||
1727 file_type
== TCC_OUTPUT_OBJ
||
1728 (s
->sh_flags
& SHF_ALLOC
) ||
1729 i
== (s1
->nb_sections
- 1)) {
1730 /* we output all sections if debug or object file */
1731 s
->sh_size
= s
->data_offset
;
1735 /* allocate program segment headers */
1736 phdr
= tcc_mallocz(phnum
* sizeof(ElfW(Phdr
)));
1738 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1739 file_offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
1744 /* compute section to program header mapping */
1745 if (s1
->has_text_addr
) {
1746 int a_offset
, p_offset
;
1747 addr
= s1
->text_addr
;
1748 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1750 a_offset
= addr
& (s1
->section_align
- 1);
1751 p_offset
= file_offset
& (s1
->section_align
- 1);
1752 if (a_offset
< p_offset
)
1753 a_offset
+= s1
->section_align
;
1754 file_offset
+= (a_offset
- p_offset
);
1756 if (file_type
== TCC_OUTPUT_DLL
)
1759 addr
= ELF_START_ADDR
;
1760 /* compute address after headers */
1761 addr
+= (file_offset
& (s1
->section_align
- 1));
1764 /* dynamic relocation table information, for .dynamic section */
1768 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1769 bss_addr
= bss_size
= 0;
1771 /* leave one program header for the program interpreter */
1774 ph
+= 1 + HAVE_PHDR
;
1776 for(j
= 0; j
< 2; j
++) {
1777 ph
->p_type
= PT_LOAD
;
1779 ph
->p_flags
= PF_R
| PF_X
;
1781 ph
->p_flags
= PF_R
| PF_W
;
1782 ph
->p_align
= s1
->section_align
;
1784 /* we do the following ordering: interp, symbol tables,
1785 relocations, progbits, nobits */
1786 /* XXX: do faster and simpler sorting */
1787 for(k
= 0; k
< 5; k
++) {
1788 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1789 s
= s1
->sections
[i
];
1790 /* compute if section should be included */
1792 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1796 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1797 (SHF_ALLOC
| SHF_WRITE
))
1803 } else if (s
->sh_type
== SHT_DYNSYM
||
1804 s
->sh_type
== SHT_STRTAB
||
1805 s
->sh_type
== SHT_HASH
) {
1808 } else if (s
->sh_type
== SHT_RELX
) {
1811 } else if (s
->sh_type
== SHT_NOBITS
) {
1818 section_order
[sh_order_index
++] = i
;
1820 /* section matches: we align it and add its size */
1822 addr
= (addr
+ s
->sh_addralign
- 1) &
1823 ~(s
->sh_addralign
- 1);
1824 file_offset
+= addr
- tmp
;
1825 s
->sh_offset
= file_offset
;
1828 /* update program header infos */
1829 if (ph
->p_offset
== 0) {
1830 ph
->p_offset
= file_offset
;
1832 ph
->p_paddr
= ph
->p_vaddr
;
1834 /* update dynamic relocation infos */
1835 if (s
->sh_type
== SHT_RELX
) {
1836 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1837 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.got")) { // rel_size == 0) {
1839 rel_size
+= s
->sh_size
; // XXX only first rel.
1841 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.bss")) { // rel_size == 0) {
1843 bss_size
= s
->sh_size
; // XXX only first rel.
1848 rel_size
+= s
->sh_size
;
1852 if (s
->sh_type
!= SHT_NOBITS
)
1853 file_offset
+= s
->sh_size
;
1856 ph
->p_filesz
= file_offset
- ph
->p_offset
;
1857 ph
->p_memsz
= addr
- ph
->p_vaddr
;
1860 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1861 /* if in the middle of a page, we duplicate the page in
1862 memory so that one copy is RX and the other is RW */
1863 if ((addr
& (s1
->section_align
- 1)) != 0)
1864 addr
+= s1
->section_align
;
1866 addr
= (addr
+ s1
->section_align
- 1) & ~(s1
->section_align
- 1);
1867 file_offset
= (file_offset
+ s1
->section_align
- 1) &
1868 ~(s1
->section_align
- 1);
1873 /* if interpreter, then add corresponing program header */
1877 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1879 int len
= phnum
* sizeof(ElfW(Phdr
));
1881 ph
->p_type
= PT_PHDR
;
1882 ph
->p_offset
= sizeof(ElfW(Ehdr
));
1883 ph
->p_vaddr
= interp
->sh_addr
- len
;
1884 ph
->p_paddr
= ph
->p_vaddr
;
1885 ph
->p_filesz
= ph
->p_memsz
= len
;
1886 ph
->p_flags
= PF_R
| PF_X
;
1887 ph
->p_align
= 4; // interp->sh_addralign;
1892 ph
->p_type
= PT_INTERP
;
1893 ph
->p_offset
= interp
->sh_offset
;
1894 ph
->p_vaddr
= interp
->sh_addr
;
1895 ph
->p_paddr
= ph
->p_vaddr
;
1896 ph
->p_filesz
= interp
->sh_size
;
1897 ph
->p_memsz
= interp
->sh_size
;
1899 ph
->p_align
= interp
->sh_addralign
;
1902 /* if dynamic section, then add corresponing program header */
1906 ph
= &phdr
[phnum
- 1];
1908 ph
->p_type
= PT_DYNAMIC
;
1909 ph
->p_offset
= dynamic
->sh_offset
;
1910 ph
->p_vaddr
= dynamic
->sh_addr
;
1911 ph
->p_paddr
= ph
->p_vaddr
;
1912 ph
->p_filesz
= dynamic
->sh_size
;
1913 ph
->p_memsz
= dynamic
->sh_size
;
1914 ph
->p_flags
= PF_R
| PF_W
;
1915 ph
->p_align
= dynamic
->sh_addralign
;
1917 /* put GOT dynamic section address */
1918 put32(s1
->got
->data
, dynamic
->sh_addr
);
1920 /* relocate the PLT */
1921 if (file_type
== TCC_OUTPUT_EXE
1922 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1923 || file_type
== TCC_OUTPUT_DLL
1929 p_end
= p
+ s1
->plt
->data_offset
;
1931 #if defined(TCC_TARGET_I386)
1932 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
1933 put32(p
+ 8, get32(p
+ 8) + s1
->got
->sh_addr
);
1936 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
1939 #elif defined(TCC_TARGET_X86_64)
1940 int x
= s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 6;
1941 put32(p
+ 2, get32(p
+ 2) + x
);
1942 put32(p
+ 8, get32(p
+ 8) + x
- 6);
1945 put32(p
+ 2, get32(p
+ 2) + x
+ s1
->plt
->data
- p
);
1948 #elif defined(TCC_TARGET_ARM)
1950 x
=s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 12;
1953 put32(p
+ 12, x
+ get32(p
+ 12) + s1
->plt
->data
- p
);
1956 #elif defined(TCC_TARGET_C67)
1959 #error unsupported CPU
1964 /* relocate symbols in .dynsym */
1965 sym_end
= (ElfW(Sym
) *)(s1
->dynsym
->data
+ s1
->dynsym
->data_offset
);
1966 for(sym
= (ElfW(Sym
) *)s1
->dynsym
->data
+ 1;
1969 if (sym
->st_shndx
== SHN_UNDEF
) {
1970 /* relocate to the PLT if the symbol corresponds
1973 sym
->st_value
+= s1
->plt
->sh_addr
;
1974 } else if (sym
->st_shndx
< SHN_LORESERVE
) {
1975 /* do symbol relocation */
1976 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
1980 /* put dynamic section entries */
1981 dynamic
->data_offset
= saved_dynamic_data_offset
;
1982 put_dt(dynamic
, DT_HASH
, s1
->dynsym
->hash
->sh_addr
);
1983 put_dt(dynamic
, DT_STRTAB
, dynstr
->sh_addr
);
1984 put_dt(dynamic
, DT_SYMTAB
, s1
->dynsym
->sh_addr
);
1985 put_dt(dynamic
, DT_STRSZ
, dynstr
->data_offset
);
1986 put_dt(dynamic
, DT_SYMENT
, sizeof(ElfW(Sym
)));
1987 #ifdef TCC_TARGET_X86_64
1988 put_dt(dynamic
, DT_RELA
, rel_addr
);
1989 put_dt(dynamic
, DT_RELASZ
, rel_size
);
1990 put_dt(dynamic
, DT_RELAENT
, sizeof(ElfW_Rel
));
1992 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1993 put_dt(dynamic
, DT_PLTGOT
, s1
->got
->sh_addr
);
1994 put_dt(dynamic
, DT_PLTRELSZ
, rel_size
);
1995 put_dt(dynamic
, DT_JMPREL
, rel_addr
);
1996 put_dt(dynamic
, DT_PLTREL
, DT_REL
);
1997 put_dt(dynamic
, DT_REL
, bss_addr
);
1998 put_dt(dynamic
, DT_RELSZ
, bss_size
);
2000 put_dt(dynamic
, DT_REL
, rel_addr
);
2001 put_dt(dynamic
, DT_RELSZ
, rel_size
);
2002 put_dt(dynamic
, DT_RELENT
, sizeof(ElfW_Rel
));
2006 put_dt(dynamic
, DT_DEBUG
, 0);
2007 put_dt(dynamic
, DT_NULL
, 0);
2010 ehdr
.e_phentsize
= sizeof(ElfW(Phdr
));
2011 ehdr
.e_phnum
= phnum
;
2012 ehdr
.e_phoff
= sizeof(ElfW(Ehdr
));
2015 /* all other sections come after */
2016 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2017 s
= s1
->sections
[i
];
2018 if (phnum
> 0 && (s
->sh_flags
& SHF_ALLOC
))
2020 section_order
[sh_order_index
++] = i
;
2022 file_offset
= (file_offset
+ s
->sh_addralign
- 1) &
2023 ~(s
->sh_addralign
- 1);
2024 s
->sh_offset
= file_offset
;
2025 if (s
->sh_type
!= SHT_NOBITS
)
2026 file_offset
+= s
->sh_size
;
2029 /* if building executable or DLL, then relocate each section
2030 except the GOT which is already relocated */
2031 if (file_type
!= TCC_OUTPUT_OBJ
) {
2032 relocate_syms(s1
, 0);
2034 if (s1
->nb_errors
!= 0) {
2040 /* relocate sections */
2041 /* XXX: ignore sections with allocated relocations ? */
2042 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2043 s
= s1
->sections
[i
];
2044 if (s
->reloc
&& s
!= s1
->got
&& (s
->sh_flags
& SHF_ALLOC
)) //gr
2045 relocate_section(s1
, s
);
2048 /* relocate relocation entries if the relocation tables are
2049 allocated in the executable */
2050 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2051 s
= s1
->sections
[i
];
2052 if ((s
->sh_flags
& SHF_ALLOC
) &&
2053 s
->sh_type
== SHT_RELX
) {
2054 relocate_rel(s1
, s
);
2058 /* get entry point address */
2059 if (file_type
== TCC_OUTPUT_EXE
)
2060 ehdr
.e_entry
= (uplong
)tcc_get_symbol_err(s1
, "_start");
2062 ehdr
.e_entry
= text_section
->sh_addr
; /* XXX: is it correct ? */
2064 if (file_type
== TCC_OUTPUT_EXE
&& s1
->static_link
)
2067 /* write elf file */
2068 if (file_type
== TCC_OUTPUT_OBJ
)
2073 fd
= open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
, mode
);
2075 tcc_error_noabort("could not write '%s'", filename
);
2078 f
= fdopen(fd
, "wb");
2080 printf("<- %s\n", filename
);
2082 #ifdef TCC_TARGET_COFF
2083 if (s1
->output_format
== TCC_OUTPUT_FORMAT_COFF
) {
2084 tcc_output_coff(s1
, f
);
2087 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
2088 sort_syms(s1
, symtab_section
);
2091 file_offset
= (file_offset
+ 3) & -4;
2094 ehdr
.e_ident
[0] = ELFMAG0
;
2095 ehdr
.e_ident
[1] = ELFMAG1
;
2096 ehdr
.e_ident
[2] = ELFMAG2
;
2097 ehdr
.e_ident
[3] = ELFMAG3
;
2098 ehdr
.e_ident
[4] = ELFCLASSW
;
2099 ehdr
.e_ident
[5] = ELFDATA2LSB
;
2100 ehdr
.e_ident
[6] = EV_CURRENT
;
2101 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2102 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_FREEBSD
;
2104 #ifdef TCC_TARGET_ARM
2106 ehdr
.e_ident
[EI_OSABI
] = 0;
2107 ehdr
.e_flags
= 4 << 24;
2109 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_ARM
;
2114 case TCC_OUTPUT_EXE
:
2115 ehdr
.e_type
= ET_EXEC
;
2117 case TCC_OUTPUT_DLL
:
2118 ehdr
.e_type
= ET_DYN
;
2120 case TCC_OUTPUT_OBJ
:
2121 ehdr
.e_type
= ET_REL
;
2124 ehdr
.e_machine
= EM_TCC_TARGET
;
2125 ehdr
.e_version
= EV_CURRENT
;
2126 ehdr
.e_shoff
= file_offset
;
2127 ehdr
.e_ehsize
= sizeof(ElfW(Ehdr
));
2128 ehdr
.e_shentsize
= sizeof(ElfW(Shdr
));
2129 ehdr
.e_shnum
= shnum
;
2130 ehdr
.e_shstrndx
= shnum
- 1;
2132 fwrite(&ehdr
, 1, sizeof(ElfW(Ehdr
)), f
);
2133 fwrite(phdr
, 1, phnum
* sizeof(ElfW(Phdr
)), f
);
2134 offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
2136 for(i
=1;i
<s1
->nb_sections
;i
++) {
2137 s
= s1
->sections
[section_order
[i
]];
2138 if (s
->sh_type
!= SHT_NOBITS
) {
2139 if (s
->sh_type
== SHT_DYNSYM
)
2140 patch_dynsym_undef(s1
, s
);
2141 while (offset
< s
->sh_offset
) {
2146 fwrite(s
->data
, 1, size
, f
);
2151 /* output section headers */
2152 while (offset
< ehdr
.e_shoff
) {
2157 for(i
=0;i
<s1
->nb_sections
;i
++) {
2159 memset(sh
, 0, sizeof(ElfW(Shdr
)));
2160 s
= s1
->sections
[i
];
2162 sh
->sh_name
= s
->sh_name
;
2163 sh
->sh_type
= s
->sh_type
;
2164 sh
->sh_flags
= s
->sh_flags
;
2165 sh
->sh_entsize
= s
->sh_entsize
;
2166 sh
->sh_info
= s
->sh_info
;
2168 sh
->sh_link
= s
->link
->sh_num
;
2169 sh
->sh_addralign
= s
->sh_addralign
;
2170 sh
->sh_addr
= s
->sh_addr
;
2171 sh
->sh_offset
= s
->sh_offset
;
2172 sh
->sh_size
= s
->sh_size
;
2174 fwrite(sh
, 1, sizeof(ElfW(Shdr
)), f
);
2177 tcc_output_binary(s1
, f
, section_order
);
2183 tcc_free(s1
->symtab_to_dynsym
);
2184 tcc_free(section_order
);
2186 tcc_free(s1
->got_offsets
);
2190 LIBTCCAPI
int tcc_output_file(TCCState
*s
, const char *filename
)
2193 #ifdef TCC_TARGET_PE
2194 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
2195 ret
= pe_output_file(s
, filename
);
2199 ret
= elf_output_file(s
, filename
);
2204 static void *load_data(int fd
, unsigned long file_offset
, unsigned long size
)
2208 data
= tcc_malloc(size
);
2209 lseek(fd
, file_offset
, SEEK_SET
);
2210 read(fd
, data
, size
);
2214 typedef struct SectionMergeInfo
{
2215 Section
*s
; /* corresponding existing section */
2216 unsigned long offset
; /* offset of the new section in the existing section */
2217 uint8_t new_section
; /* true if section 's' was added */
2218 uint8_t link_once
; /* true if link once section */
2221 /* load an object file and merge it with current files */
2222 /* XXX: handle correctly stab (debug) info */
2223 ST_FUNC
int tcc_load_object_file(TCCState
*s1
,
2224 int fd
, unsigned long file_offset
)
2227 ElfW(Shdr
) *shdr
, *sh
;
2228 int size
, i
, j
, offset
, offseti
, nb_syms
, sym_index
, ret
;
2229 unsigned char *strsec
, *strtab
;
2230 int *old_to_new_syms
;
2231 char *sh_name
, *name
;
2232 SectionMergeInfo
*sm_table
, *sm
;
2233 ElfW(Sym
) *sym
, *symtab
;
2234 ElfW_Rel
*rel
, *rel_end
;
2240 stab_index
= stabstr_index
= 0;
2242 if (read(fd
, &ehdr
, sizeof(ehdr
)) != sizeof(ehdr
))
2244 if (ehdr
.e_ident
[0] != ELFMAG0
||
2245 ehdr
.e_ident
[1] != ELFMAG1
||
2246 ehdr
.e_ident
[2] != ELFMAG2
||
2247 ehdr
.e_ident
[3] != ELFMAG3
)
2249 /* test if object file */
2250 if (ehdr
.e_type
!= ET_REL
)
2252 /* test CPU specific stuff */
2253 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2254 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2256 tcc_error_noabort("invalid object file");
2260 shdr
= load_data(fd
, file_offset
+ ehdr
.e_shoff
,
2261 sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2262 sm_table
= tcc_mallocz(sizeof(SectionMergeInfo
) * ehdr
.e_shnum
);
2264 /* load section names */
2265 sh
= &shdr
[ehdr
.e_shstrndx
];
2266 strsec
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2268 /* load symtab and strtab */
2269 old_to_new_syms
= NULL
;
2273 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2275 if (sh
->sh_type
== SHT_SYMTAB
) {
2277 tcc_error_noabort("object must contain only one symtab");
2282 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2283 symtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2284 sm_table
[i
].s
= symtab_section
;
2286 /* now load strtab */
2287 sh
= &shdr
[sh
->sh_link
];
2288 strtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2292 /* now examine each section and try to merge its content with the
2294 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2295 /* no need to examine section name strtab */
2296 if (i
== ehdr
.e_shstrndx
)
2299 sh_name
= strsec
+ sh
->sh_name
;
2300 /* ignore sections types we do not handle */
2301 if (sh
->sh_type
!= SHT_PROGBITS
&&
2302 sh
->sh_type
!= SHT_RELX
&&
2304 sh
->sh_type
!= SHT_ARM_EXIDX
&&
2306 sh
->sh_type
!= SHT_NOBITS
&&
2307 sh
->sh_type
!= SHT_PREINIT_ARRAY
&&
2308 sh
->sh_type
!= SHT_INIT_ARRAY
&&
2309 sh
->sh_type
!= SHT_FINI_ARRAY
&&
2310 strcmp(sh_name
, ".stabstr")
2313 if (sh
->sh_addralign
< 1)
2314 sh
->sh_addralign
= 1;
2315 /* find corresponding section, if any */
2316 for(j
= 1; j
< s1
->nb_sections
;j
++) {
2317 s
= s1
->sections
[j
];
2318 if (!strcmp(s
->name
, sh_name
)) {
2319 if (!strncmp(sh_name
, ".gnu.linkonce",
2320 sizeof(".gnu.linkonce") - 1)) {
2321 /* if a 'linkonce' section is already present, we
2322 do not add it again. It is a little tricky as
2323 symbols can still be defined in
2325 sm_table
[i
].link_once
= 1;
2332 /* not found: create new section */
2333 s
= new_section(s1
, sh_name
, sh
->sh_type
, sh
->sh_flags
);
2334 /* take as much info as possible from the section. sh_link and
2335 sh_info will be updated later */
2336 s
->sh_addralign
= sh
->sh_addralign
;
2337 s
->sh_entsize
= sh
->sh_entsize
;
2338 sm_table
[i
].new_section
= 1;
2340 if (sh
->sh_type
!= s
->sh_type
) {
2341 tcc_error_noabort("invalid section type");
2345 /* align start of section */
2346 offset
= s
->data_offset
;
2348 if (0 == strcmp(sh_name
, ".stab")) {
2352 if (0 == strcmp(sh_name
, ".stabstr")) {
2357 size
= sh
->sh_addralign
- 1;
2358 offset
= (offset
+ size
) & ~size
;
2359 if (sh
->sh_addralign
> s
->sh_addralign
)
2360 s
->sh_addralign
= sh
->sh_addralign
;
2361 s
->data_offset
= offset
;
2363 sm_table
[i
].offset
= offset
;
2365 /* concatenate sections */
2367 if (sh
->sh_type
!= SHT_NOBITS
) {
2369 lseek(fd
, file_offset
+ sh
->sh_offset
, SEEK_SET
);
2370 ptr
= section_ptr_add(s
, size
);
2371 read(fd
, ptr
, size
);
2373 s
->data_offset
+= size
;
2378 /* //gr relocate stab strings */
2379 if (stab_index
&& stabstr_index
) {
2382 s
= sm_table
[stab_index
].s
;
2383 a
= (Stab_Sym
*)(s
->data
+ sm_table
[stab_index
].offset
);
2384 b
= (Stab_Sym
*)(s
->data
+ s
->data_offset
);
2385 o
= sm_table
[stabstr_index
].offset
;
2387 a
->n_strx
+= o
, a
++;
2390 /* second short pass to update sh_link and sh_info fields of new
2392 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2394 if (!s
|| !sm_table
[i
].new_section
)
2397 if (sh
->sh_link
> 0)
2398 s
->link
= sm_table
[sh
->sh_link
].s
;
2399 if (sh
->sh_type
== SHT_RELX
) {
2400 s
->sh_info
= sm_table
[sh
->sh_info
].s
->sh_num
;
2401 /* update backward link */
2402 s1
->sections
[s
->sh_info
]->reloc
= s
;
2407 /* resolve symbols */
2408 old_to_new_syms
= tcc_mallocz(nb_syms
* sizeof(int));
2411 for(i
= 1; i
< nb_syms
; i
++, sym
++) {
2412 if (sym
->st_shndx
!= SHN_UNDEF
&&
2413 sym
->st_shndx
< SHN_LORESERVE
) {
2414 sm
= &sm_table
[sym
->st_shndx
];
2415 if (sm
->link_once
) {
2416 /* if a symbol is in a link once section, we use the
2417 already defined symbol. It is very important to get
2418 correct relocations */
2419 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
2420 name
= strtab
+ sym
->st_name
;
2421 sym_index
= find_elf_sym(symtab_section
, name
);
2423 old_to_new_syms
[i
] = sym_index
;
2427 /* if no corresponding section added, no need to add symbol */
2430 /* convert section number */
2431 sym
->st_shndx
= sm
->s
->sh_num
;
2433 sym
->st_value
+= sm
->offset
;
2436 name
= strtab
+ sym
->st_name
;
2437 sym_index
= add_elf_sym(symtab_section
, sym
->st_value
, sym
->st_size
,
2438 sym
->st_info
, sym
->st_other
,
2439 sym
->st_shndx
, name
);
2440 old_to_new_syms
[i
] = sym_index
;
2443 /* third pass to patch relocation entries */
2444 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2449 offset
= sm_table
[i
].offset
;
2450 switch(s
->sh_type
) {
2452 /* take relocation offset information */
2453 offseti
= sm_table
[sh
->sh_info
].offset
;
2454 rel_end
= (ElfW_Rel
*)(s
->data
+ s
->data_offset
);
2455 for(rel
= (ElfW_Rel
*)(s
->data
+ offset
);
2460 /* convert symbol index */
2461 type
= ELFW(R_TYPE
)(rel
->r_info
);
2462 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
2463 /* NOTE: only one symtab assumed */
2464 if (sym_index
>= nb_syms
)
2466 sym_index
= old_to_new_syms
[sym_index
];
2467 /* ignore link_once in rel section. */
2468 if (!sym_index
&& !sm
->link_once
2469 #ifdef TCC_TARGET_ARM
2470 && type
!= R_ARM_V4BX
2474 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2475 i
, strsec
+ sh
->sh_name
, rel
->r_offset
);
2478 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
2479 /* offset the relocation offset */
2480 rel
->r_offset
+= offseti
;
2492 tcc_free(old_to_new_syms
);
2499 typedef struct ArchiveHeader
{
2500 char ar_name
[16]; /* name of this member */
2501 char ar_date
[12]; /* file mtime */
2502 char ar_uid
[6]; /* owner uid; printed as decimal */
2503 char ar_gid
[6]; /* owner gid; printed as decimal */
2504 char ar_mode
[8]; /* file mode, printed as octal */
2505 char ar_size
[10]; /* file size, printed as decimal */
2506 char ar_fmag
[2]; /* should contain ARFMAG */
2509 static int get_be32(const uint8_t *b
)
2511 return b
[3] | (b
[2] << 8) | (b
[1] << 16) | (b
[0] << 24);
2514 /* load only the objects which resolve undefined symbols */
2515 static int tcc_load_alacarte(TCCState
*s1
, int fd
, int size
)
2517 int i
, bound
, nsyms
, sym_index
, off
, ret
;
2519 const char *ar_names
, *p
;
2520 const uint8_t *ar_index
;
2523 data
= tcc_malloc(size
);
2524 if (read(fd
, data
, size
) != size
)
2526 nsyms
= get_be32(data
);
2527 ar_index
= data
+ 4;
2528 ar_names
= ar_index
+ nsyms
* 4;
2532 for(p
= ar_names
, i
= 0; i
< nsyms
; i
++, p
+= strlen(p
)+1) {
2533 sym_index
= find_elf_sym(symtab_section
, p
);
2535 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
2536 if(sym
->st_shndx
== SHN_UNDEF
) {
2537 off
= get_be32(ar_index
+ i
* 4) + sizeof(ArchiveHeader
);
2539 printf("%5d\t%s\t%08x\n", i
, p
, sym
->st_shndx
);
2542 lseek(fd
, off
, SEEK_SET
);
2543 if(tcc_load_object_file(s1
, fd
, off
) < 0) {
2558 /* load a '.a' file */
2559 ST_FUNC
int tcc_load_archive(TCCState
*s1
, int fd
)
2566 unsigned long file_offset
;
2568 /* skip magic which was already checked */
2569 read(fd
, magic
, sizeof(magic
));
2572 len
= read(fd
, &hdr
, sizeof(hdr
));
2575 if (len
!= sizeof(hdr
)) {
2576 tcc_error_noabort("invalid archive");
2579 memcpy(ar_size
, hdr
.ar_size
, sizeof(hdr
.ar_size
));
2580 ar_size
[sizeof(hdr
.ar_size
)] = '\0';
2581 size
= strtol(ar_size
, NULL
, 0);
2582 memcpy(ar_name
, hdr
.ar_name
, sizeof(hdr
.ar_name
));
2583 for(i
= sizeof(hdr
.ar_name
) - 1; i
>= 0; i
--) {
2584 if (ar_name
[i
] != ' ')
2587 ar_name
[i
+ 1] = '\0';
2588 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2589 file_offset
= lseek(fd
, 0, SEEK_CUR
);
2591 size
= (size
+ 1) & ~1;
2592 if (!strcmp(ar_name
, "/")) {
2593 /* coff symbol table : we handle it */
2594 if(s1
->alacarte_link
)
2595 return tcc_load_alacarte(s1
, fd
, size
);
2596 } else if (!strcmp(ar_name
, "//") ||
2597 !strcmp(ar_name
, "__.SYMDEF") ||
2598 !strcmp(ar_name
, "__.SYMDEF/") ||
2599 !strcmp(ar_name
, "ARFILENAMES/")) {
2600 /* skip symbol table or archive names */
2602 if (tcc_load_object_file(s1
, fd
, file_offset
) < 0)
2605 lseek(fd
, file_offset
+ size
, SEEK_SET
);
2610 #ifndef TCC_TARGET_PE
2611 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2612 is referenced by the user (so it should be added as DT_NEEDED in
2613 the generated ELF file) */
2614 ST_FUNC
int tcc_load_dll(TCCState
*s1
, int fd
, const char *filename
, int level
)
2617 ElfW(Shdr
) *shdr
, *sh
, *sh1
;
2618 int i
, j
, nb_syms
, nb_dts
, sym_bind
, ret
;
2619 ElfW(Sym
) *sym
, *dynsym
;
2620 ElfW(Dyn
) *dt
, *dynamic
;
2621 unsigned char *dynstr
;
2622 const char *name
, *soname
;
2623 DLLReference
*dllref
;
2625 read(fd
, &ehdr
, sizeof(ehdr
));
2627 /* test CPU specific stuff */
2628 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2629 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2630 tcc_error_noabort("bad architecture");
2635 shdr
= load_data(fd
, ehdr
.e_shoff
, sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2637 /* load dynamic section and dynamic symbols */
2641 dynsym
= NULL
; /* avoid warning */
2642 dynstr
= NULL
; /* avoid warning */
2643 for(i
= 0, sh
= shdr
; i
< ehdr
.e_shnum
; i
++, sh
++) {
2644 switch(sh
->sh_type
) {
2646 nb_dts
= sh
->sh_size
/ sizeof(ElfW(Dyn
));
2647 dynamic
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2650 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2651 dynsym
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2652 sh1
= &shdr
[sh
->sh_link
];
2653 dynstr
= load_data(fd
, sh1
->sh_offset
, sh1
->sh_size
);
2660 /* compute the real library name */
2661 soname
= tcc_basename(filename
);
2663 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2664 if (dt
->d_tag
== DT_SONAME
) {
2665 soname
= dynstr
+ dt
->d_un
.d_val
;
2669 /* if the dll is already loaded, do not load it */
2670 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
2671 dllref
= s1
->loaded_dlls
[i
];
2672 if (!strcmp(soname
, dllref
->name
)) {
2673 /* but update level if needed */
2674 if (level
< dllref
->level
)
2675 dllref
->level
= level
;
2681 // printf("loading dll '%s'\n", soname);
2683 /* add the dll and its level */
2684 dllref
= tcc_mallocz(sizeof(DLLReference
) + strlen(soname
));
2685 dllref
->level
= level
;
2686 strcpy(dllref
->name
, soname
);
2687 dynarray_add((void ***)&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
, dllref
);
2689 /* add dynamic symbols in dynsym_section */
2690 for(i
= 1, sym
= dynsym
+ 1; i
< nb_syms
; i
++, sym
++) {
2691 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
2692 if (sym_bind
== STB_LOCAL
)
2694 name
= dynstr
+ sym
->st_name
;
2695 add_elf_sym(s1
->dynsymtab_section
, sym
->st_value
, sym
->st_size
,
2696 sym
->st_info
, sym
->st_other
, sym
->st_shndx
, name
);
2699 /* load all referenced DLLs */
2700 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2703 name
= dynstr
+ dt
->d_un
.d_val
;
2704 for(j
= 0; j
< s1
->nb_loaded_dlls
; j
++) {
2705 dllref
= s1
->loaded_dlls
[j
];
2706 if (!strcmp(name
, dllref
->name
))
2707 goto already_loaded
;
2709 if (tcc_add_dll(s1
, name
, AFF_REFERENCED_DLL
) < 0) {
2710 tcc_error_noabort("referenced dll '%s' not found", name
);
2727 #define LD_TOK_NAME 256
2728 #define LD_TOK_EOF (-1)
2730 /* return next ld script token */
2731 static int ld_next(TCCState
*s1
, char *name
, int name_size
)
2749 file
->buf_ptr
= parse_comment(file
->buf_ptr
);
2750 ch
= file
->buf_ptr
[0];
2758 /* case 'a' ... 'z': */
2785 /* case 'A' ... 'z': */
2820 if (!((ch
>= 'a' && ch
<= 'z') ||
2821 (ch
>= 'A' && ch
<= 'Z') ||
2822 (ch
>= '0' && ch
<= '9') ||
2823 strchr("/.-_+=$:\\,~", ch
)))
2825 if ((q
- name
) < name_size
- 1) {
2842 printf("tok=%c %d\n", c
, c
);
2843 if (c
== LD_TOK_NAME
)
2844 printf(" name=%s\n", name
);
2850 * Extract the file name from the library name
2852 * /!\ No test on filename capacity, be careful
2854 static void libname_to_filename(TCCState
*s1
, const char libname
[], char filename
[])
2856 if (!s1
->static_link
) {
2857 sprintf(filename
, "lib%s.so", libname
);
2859 sprintf(filename
, "lib%s.a", libname
);
2863 static int ld_add_file(TCCState
*s1
, const char filename
[])
2867 ret
= tcc_add_file_internal(s1
, filename
, 0);
2869 ret
= tcc_add_dll(s1
, filename
, 0);
2873 static inline int new_undef_syms(void)
2876 ret
= new_undef_sym
;
2881 static int ld_add_file_list(TCCState
*s1
, const char *cmd
, int as_needed
)
2883 char filename
[1024], libname
[1024];
2884 int t
, group
, nblibs
= 0, ret
= 0;
2887 group
= !strcmp(cmd
, "GROUP");
2890 t
= ld_next(s1
, filename
, sizeof(filename
));
2893 t
= ld_next(s1
, filename
, sizeof(filename
));
2896 if (t
== LD_TOK_EOF
) {
2897 tcc_error_noabort("unexpected end of file");
2899 goto lib_parse_error
;
2900 } else if (t
== ')') {
2902 } else if (t
== '-') {
2903 t
= ld_next(s1
, filename
, sizeof(filename
));
2904 if ((t
!= LD_TOK_NAME
) || (filename
[0] != 'l')) {
2905 tcc_error_noabort("library name expected");
2907 goto lib_parse_error
;
2909 strcpy(libname
, &filename
[1]);
2910 libname_to_filename(s1
, libname
, filename
);
2911 } else if (t
!= LD_TOK_NAME
) {
2912 tcc_error_noabort("filename expected");
2914 goto lib_parse_error
;
2916 if (!strcmp(filename
, "AS_NEEDED")) {
2917 ret
= ld_add_file_list(s1
, cmd
, 1);
2919 goto lib_parse_error
;
2921 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2923 ret
= ld_add_file(s1
, filename
);
2925 goto lib_parse_error
;
2927 /* Add the filename *and* the libname to avoid future conversions */
2928 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(filename
));
2929 if (libname
[0] != '\0')
2930 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(libname
));
2934 t
= ld_next(s1
, filename
, sizeof(filename
));
2936 t
= ld_next(s1
, filename
, sizeof(filename
));
2939 if (group
&& !as_needed
) {
2940 while (new_undef_syms()) {
2943 for (i
= 0; i
< nblibs
; i
++)
2944 ld_add_file(s1
, libs
[i
]);
2948 dynarray_reset(&libs
, &nblibs
);
2952 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
2954 ST_FUNC
int tcc_load_ldscript(TCCState
*s1
)
2957 char filename
[1024];
2960 ch
= file
->buf_ptr
[0];
2963 t
= ld_next(s1
, cmd
, sizeof(cmd
));
2964 if (t
== LD_TOK_EOF
)
2966 else if (t
!= LD_TOK_NAME
)
2968 if (!strcmp(cmd
, "INPUT") ||
2969 !strcmp(cmd
, "GROUP")) {
2970 ret
= ld_add_file_list(s1
, cmd
, 0);
2973 } else if (!strcmp(cmd
, "OUTPUT_FORMAT") ||
2974 !strcmp(cmd
, "TARGET")) {
2975 /* ignore some commands */
2976 t
= ld_next(s1
, cmd
, sizeof(cmd
));
2980 t
= ld_next(s1
, filename
, sizeof(filename
));
2981 if (t
== LD_TOK_EOF
) {
2982 tcc_error_noabort("unexpected end of file");
2984 } else if (t
== ')') {
2994 #endif /* ndef TCC_TARGET_PE */