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
, uplong 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
+ 4, 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
, sh_order_index
, k
;
1427 Section
*strsec
, *s
;
1428 ElfW(Shdr
) shdr
, *sh
;
1429 ElfW(Phdr
) *phdr
, *ph
;
1430 Section
*interp
, *dynamic
, *dynstr
;
1431 unsigned long saved_dynamic_data_offset
;
1433 int type
, file_type
;
1434 uplong rel_addr
, rel_size
;
1435 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1436 uplong bss_addr
, bss_size
;
1439 file_type
= s1
->output_type
;
1442 if (file_type
!= TCC_OUTPUT_OBJ
) {
1443 tcc_add_runtime(s1
);
1447 section_order
= NULL
;
1450 dynstr
= NULL
; /* avoid warning */
1451 saved_dynamic_data_offset
= 0; /* avoid warning */
1453 if (file_type
!= TCC_OUTPUT_OBJ
) {
1454 relocate_common_syms();
1456 tcc_add_linker_symbols(s1
);
1458 if (!s1
->static_link
) {
1460 int sym_index
, index
;
1461 ElfW(Sym
) *esym
, *sym_end
;
1463 if (file_type
== TCC_OUTPUT_EXE
) {
1465 /* allow override the dynamic loader */
1466 const char *elfint
= getenv("LD_SO");
1468 elfint
= CONFIG_TCC_ELFINTERP
;
1469 /* add interpreter section only if executable */
1470 interp
= new_section(s1
, ".interp", SHT_PROGBITS
, SHF_ALLOC
);
1471 interp
->sh_addralign
= 1;
1472 ptr
= section_ptr_add(interp
, 1+strlen(elfint
));
1473 strcpy(ptr
, elfint
);
1476 /* add dynamic symbol table */
1477 s1
->dynsym
= new_symtab(s1
, ".dynsym", SHT_DYNSYM
, SHF_ALLOC
,
1479 ".hash", SHF_ALLOC
);
1480 dynstr
= s1
->dynsym
->link
;
1482 /* add dynamic section */
1483 dynamic
= new_section(s1
, ".dynamic", SHT_DYNAMIC
,
1484 SHF_ALLOC
| SHF_WRITE
);
1485 dynamic
->link
= dynstr
;
1486 dynamic
->sh_entsize
= sizeof(ElfW(Dyn
));
1489 s1
->plt
= new_section(s1
, ".plt", SHT_PROGBITS
,
1490 SHF_ALLOC
| SHF_EXECINSTR
);
1491 s1
->plt
->sh_entsize
= 4;
1495 /* scan for undefined symbols and see if they are in the
1496 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1497 is found, then we add it in the PLT. If a symbol
1498 STT_OBJECT is found, we add it in the .bss section with
1499 a suitable relocation */
1500 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+
1501 symtab_section
->data_offset
);
1502 if (file_type
== TCC_OUTPUT_EXE
) {
1503 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
1506 if (sym
->st_shndx
== SHN_UNDEF
) {
1507 name
= symtab_section
->link
->data
+ sym
->st_name
;
1508 sym_index
= find_elf_sym(s1
->dynsymtab_section
, name
);
1510 esym
= &((ElfW(Sym
) *)s1
->dynsymtab_section
->data
)[sym_index
];
1511 type
= ELFW(ST_TYPE
)(esym
->st_info
);
1512 if ((type
== STT_FUNC
) || (type
== STT_GNU_IFUNC
)) {
1513 put_got_entry(s1
, R_JMP_SLOT
, esym
->st_size
,
1514 ELFW(ST_INFO
)(STB_GLOBAL
,type
),
1515 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1516 } else if (type
== STT_OBJECT
) {
1517 unsigned long offset
;
1518 ElfW(Sym
) *dynsym
, *dynsym_end
;
1519 offset
= bss_section
->data_offset
;
1520 /* XXX: which alignment ? */
1521 offset
= (offset
+ 16 - 1) & -16;
1522 index
= put_elf_sym(s1
->dynsym
, offset
, esym
->st_size
,
1524 bss_section
->sh_num
, name
);
1525 // Ensure R_COPY works for weak symbol aliases
1526 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1527 dynsym_end
= (ElfW(Sym
) *)
1528 (s1
->dynsymtab_section
->data
+
1529 s1
->dynsymtab_section
->data_offset
);
1530 for(dynsym
= (ElfW(Sym
) *)s1
->dynsymtab_section
->data
+ 1;
1531 dynsym
< dynsym_end
; dynsym
++) {
1532 if ((dynsym
->st_value
== esym
->st_value
)
1533 && (ELFW(ST_BIND
)(dynsym
->st_info
) == STB_GLOBAL
)) {
1535 dynname
= s1
->dynsymtab_section
->link
->data
1537 put_elf_sym(s1
->dynsym
, offset
,
1540 bss_section
->sh_num
,
1546 put_elf_reloc(s1
->dynsym
, bss_section
,
1547 offset
, R_COPY
, index
);
1548 offset
+= esym
->st_size
;
1549 bss_section
->data_offset
= offset
;
1552 /* STB_WEAK undefined symbols are accepted */
1553 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1555 if (ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
||
1556 !strcmp(name
, "_fp_hw")) {
1558 tcc_error_noabort("undefined symbol '%s'", name
);
1561 } else if (s1
->rdynamic
&&
1562 ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1563 /* if -rdynamic option, then export all non
1565 name
= symtab_section
->link
->data
+ sym
->st_name
;
1566 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1568 sym
->st_shndx
, name
);
1575 /* now look at unresolved dynamic symbols and export
1576 corresponding symbol */
1577 sym_end
= (ElfW(Sym
) *)(s1
->dynsymtab_section
->data
+
1578 s1
->dynsymtab_section
->data_offset
);
1579 for(esym
= (ElfW(Sym
) *)s1
->dynsymtab_section
->data
+ 1;
1582 if (esym
->st_shndx
== SHN_UNDEF
) {
1583 name
= s1
->dynsymtab_section
->link
->data
+ esym
->st_name
;
1584 sym_index
= find_elf_sym(symtab_section
, name
);
1586 /* XXX: avoid adding a symbol if already
1587 present because of -rdynamic ? */
1588 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1589 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1591 sym
->st_shndx
, name
);
1593 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1594 /* weak symbols can stay undefined */
1596 tcc_warning("undefined dynamic symbol '%s'", name
);
1603 /* shared library case : we simply export all the global symbols */
1604 nb_syms
= symtab_section
->data_offset
/ sizeof(ElfW(Sym
));
1605 s1
->symtab_to_dynsym
= tcc_mallocz(sizeof(int) * nb_syms
);
1606 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
1609 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1610 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1611 if ((ELFW(ST_TYPE
)(sym
->st_info
) == STT_FUNC
||
1612 ELFW(ST_TYPE
)(sym
->st_info
) == STT_GNU_IFUNC
)
1613 && sym
->st_shndx
== SHN_UNDEF
) {
1614 put_got_entry(s1
, R_JMP_SLOT
, sym
->st_size
,
1616 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1618 else if (ELFW(ST_TYPE
)(sym
->st_info
) == STT_OBJECT
) {
1619 put_got_entry(s1
, R_X86_64_GLOB_DAT
, sym
->st_size
,
1621 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1626 name
= symtab_section
->link
->data
+ sym
->st_name
;
1627 index
= put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1629 sym
->st_shndx
, name
);
1630 s1
->symtab_to_dynsym
[sym
-
1631 (ElfW(Sym
) *)symtab_section
->data
] =
1638 build_got_entries(s1
);
1640 /* add a list of needed dlls */
1641 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
1642 DLLReference
*dllref
= s1
->loaded_dlls
[i
];
1643 if (dllref
->level
== 0)
1644 put_dt(dynamic
, DT_NEEDED
, put_elf_str(dynstr
, dllref
->name
));
1648 put_dt(dynamic
, DT_RPATH
, put_elf_str(dynstr
, s1
->rpath
));
1650 /* XXX: currently, since we do not handle PIC code, we
1651 must relocate the readonly segments */
1652 if (file_type
== TCC_OUTPUT_DLL
) {
1654 put_dt(dynamic
, DT_SONAME
, put_elf_str(dynstr
, s1
->soname
));
1655 put_dt(dynamic
, DT_TEXTREL
, 0);
1659 put_dt(dynamic
, DT_SYMBOLIC
, 0);
1661 /* add necessary space for other entries */
1662 saved_dynamic_data_offset
= dynamic
->data_offset
;
1663 dynamic
->data_offset
+= sizeof(ElfW(Dyn
)) * EXTRA_RELITEMS
;
1665 /* still need to build got entries in case of static link */
1666 build_got_entries(s1
);
1670 memset(&ehdr
, 0, sizeof(ehdr
));
1672 /* we add a section for symbols */
1673 strsec
= new_section(s1
, ".shstrtab", SHT_STRTAB
, 0);
1674 put_elf_str(strsec
, "");
1676 /* compute number of sections */
1677 shnum
= s1
->nb_sections
;
1679 /* this array is used to reorder sections in the output file */
1680 section_order
= tcc_malloc(sizeof(int) * shnum
);
1681 section_order
[0] = 0;
1684 /* compute number of program headers */
1687 case TCC_OUTPUT_OBJ
:
1690 case TCC_OUTPUT_EXE
:
1691 if (!s1
->static_link
)
1692 phnum
= 4 + HAVE_PHDR
;
1696 case TCC_OUTPUT_DLL
:
1701 /* allocate strings for section names and decide if an unallocated
1702 section should be output */
1703 /* NOTE: the strsec section comes last, so its size is also
1705 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1706 s
= s1
->sections
[i
];
1707 s
->sh_name
= put_elf_str(strsec
, s
->name
);
1709 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1714 s
->reloc
? s
->reloc
->name
: "n"
1717 /* when generating a DLL, we include relocations but we may
1719 if (file_type
== TCC_OUTPUT_DLL
&&
1720 s
->sh_type
== SHT_RELX
&&
1721 !(s
->sh_flags
& SHF_ALLOC
)) {
1722 /* //gr: avoid bogus relocs for empty (debug) sections */
1723 if (s1
->sections
[s
->sh_info
]->sh_flags
& SHF_ALLOC
)
1724 prepare_dynamic_rel(s1
, s
);
1725 else if (s1
->do_debug
)
1726 s
->sh_size
= s
->data_offset
;
1727 } else if (s1
->do_debug
||
1728 file_type
== TCC_OUTPUT_OBJ
||
1729 (s
->sh_flags
& SHF_ALLOC
) ||
1730 i
== (s1
->nb_sections
- 1)) {
1731 /* we output all sections if debug or object file */
1732 s
->sh_size
= s
->data_offset
;
1736 /* allocate program segment headers */
1737 phdr
= tcc_mallocz(phnum
* sizeof(ElfW(Phdr
)));
1739 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1740 file_offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
1745 /* compute section to program header mapping */
1746 if (s1
->has_text_addr
) {
1747 int a_offset
, p_offset
;
1748 addr
= s1
->text_addr
;
1749 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1751 a_offset
= (int) (addr
& (s1
->section_align
- 1));
1752 p_offset
= file_offset
& (s1
->section_align
- 1);
1753 if (a_offset
< p_offset
)
1754 a_offset
+= s1
->section_align
;
1755 file_offset
+= (a_offset
- p_offset
);
1757 if (file_type
== TCC_OUTPUT_DLL
)
1760 addr
= ELF_START_ADDR
;
1761 /* compute address after headers */
1762 addr
+= (file_offset
& (s1
->section_align
- 1));
1765 /* dynamic relocation table information, for .dynamic section */
1769 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1770 bss_addr
= bss_size
= 0;
1772 /* leave one program header for the program interpreter */
1775 ph
+= 1 + HAVE_PHDR
;
1777 for(j
= 0; j
< 2; j
++) {
1778 ph
->p_type
= PT_LOAD
;
1780 ph
->p_flags
= PF_R
| PF_X
;
1782 ph
->p_flags
= PF_R
| PF_W
;
1783 ph
->p_align
= s1
->section_align
;
1785 /* we do the following ordering: interp, symbol tables,
1786 relocations, progbits, nobits */
1787 /* XXX: do faster and simpler sorting */
1788 for(k
= 0; k
< 5; k
++) {
1789 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1790 s
= s1
->sections
[i
];
1791 /* compute if section should be included */
1793 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1797 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1798 (SHF_ALLOC
| SHF_WRITE
))
1804 } else if (s
->sh_type
== SHT_DYNSYM
||
1805 s
->sh_type
== SHT_STRTAB
||
1806 s
->sh_type
== SHT_HASH
) {
1809 } else if (s
->sh_type
== SHT_RELX
) {
1812 } else if (s
->sh_type
== SHT_NOBITS
) {
1819 section_order
[sh_order_index
++] = i
;
1821 /* section matches: we align it and add its size */
1823 addr
= (addr
+ s
->sh_addralign
- 1) &
1824 ~(s
->sh_addralign
- 1);
1825 file_offset
+= (int) ( addr
- tmp
);
1826 s
->sh_offset
= file_offset
;
1829 /* update program header infos */
1830 if (ph
->p_offset
== 0) {
1831 ph
->p_offset
= file_offset
;
1833 ph
->p_paddr
= ph
->p_vaddr
;
1835 /* update dynamic relocation infos */
1836 if (s
->sh_type
== SHT_RELX
) {
1837 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1838 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.got")) { // rel_size == 0) {
1840 rel_size
+= s
->sh_size
; // XXX only first rel.
1842 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.bss")) { // rel_size == 0) {
1844 bss_size
= s
->sh_size
; // XXX only first rel.
1849 rel_size
+= s
->sh_size
;
1853 if (s
->sh_type
!= SHT_NOBITS
)
1854 file_offset
+= s
->sh_size
;
1857 ph
->p_filesz
= file_offset
- ph
->p_offset
;
1858 ph
->p_memsz
= addr
- ph
->p_vaddr
;
1861 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1862 /* if in the middle of a page, we duplicate the page in
1863 memory so that one copy is RX and the other is RW */
1864 if ((addr
& (s1
->section_align
- 1)) != 0)
1865 addr
+= s1
->section_align
;
1867 addr
= (addr
+ s1
->section_align
- 1) & ~(s1
->section_align
- 1);
1868 file_offset
= (file_offset
+ s1
->section_align
- 1) &
1869 ~(s1
->section_align
- 1);
1874 /* if interpreter, then add corresponing program header */
1878 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1880 int len
= phnum
* sizeof(ElfW(Phdr
));
1882 ph
->p_type
= PT_PHDR
;
1883 ph
->p_offset
= sizeof(ElfW(Ehdr
));
1884 ph
->p_vaddr
= interp
->sh_addr
- len
;
1885 ph
->p_paddr
= ph
->p_vaddr
;
1886 ph
->p_filesz
= ph
->p_memsz
= len
;
1887 ph
->p_flags
= PF_R
| PF_X
;
1888 ph
->p_align
= 4; // interp->sh_addralign;
1893 ph
->p_type
= PT_INTERP
;
1894 ph
->p_offset
= interp
->sh_offset
;
1895 ph
->p_vaddr
= interp
->sh_addr
;
1896 ph
->p_paddr
= ph
->p_vaddr
;
1897 ph
->p_filesz
= interp
->sh_size
;
1898 ph
->p_memsz
= interp
->sh_size
;
1900 ph
->p_align
= interp
->sh_addralign
;
1903 /* if dynamic section, then add corresponing program header */
1907 ph
= &phdr
[phnum
- 1];
1909 ph
->p_type
= PT_DYNAMIC
;
1910 ph
->p_offset
= dynamic
->sh_offset
;
1911 ph
->p_vaddr
= dynamic
->sh_addr
;
1912 ph
->p_paddr
= ph
->p_vaddr
;
1913 ph
->p_filesz
= dynamic
->sh_size
;
1914 ph
->p_memsz
= dynamic
->sh_size
;
1915 ph
->p_flags
= PF_R
| PF_W
;
1916 ph
->p_align
= dynamic
->sh_addralign
;
1918 /* put GOT dynamic section address */
1919 put32(s1
->got
->data
, dynamic
->sh_addr
);
1921 /* relocate the PLT */
1922 if (file_type
== TCC_OUTPUT_EXE
1923 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1924 || file_type
== TCC_OUTPUT_DLL
1930 p_end
= p
+ s1
->plt
->data_offset
;
1932 #if defined(TCC_TARGET_I386)
1933 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
1934 put32(p
+ 8, get32(p
+ 8) + s1
->got
->sh_addr
);
1937 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
1940 #elif defined(TCC_TARGET_X86_64)
1941 int x
= s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 6;
1942 put32(p
+ 2, get32(p
+ 2) + x
);
1943 put32(p
+ 8, get32(p
+ 8) + x
- 6);
1946 put32(p
+ 2, get32(p
+ 2) + x
+ s1
->plt
->data
- p
);
1949 #elif defined(TCC_TARGET_ARM)
1951 x
=s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 12;
1954 put32(p
+ 12, x
+ get32(p
+ 12) + s1
->plt
->data
- p
);
1957 #elif defined(TCC_TARGET_C67)
1960 #error unsupported CPU
1965 /* relocate symbols in .dynsym */
1966 sym_end
= (ElfW(Sym
) *)(s1
->dynsym
->data
+ s1
->dynsym
->data_offset
);
1967 for(sym
= (ElfW(Sym
) *)s1
->dynsym
->data
+ 1;
1970 if (sym
->st_shndx
== SHN_UNDEF
) {
1971 /* relocate to the PLT if the symbol corresponds
1974 sym
->st_value
+= s1
->plt
->sh_addr
;
1975 } else if (sym
->st_shndx
< SHN_LORESERVE
) {
1976 /* do symbol relocation */
1977 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
1981 /* put dynamic section entries */
1982 dynamic
->data_offset
= saved_dynamic_data_offset
;
1983 put_dt(dynamic
, DT_HASH
, s1
->dynsym
->hash
->sh_addr
);
1984 put_dt(dynamic
, DT_STRTAB
, dynstr
->sh_addr
);
1985 put_dt(dynamic
, DT_SYMTAB
, s1
->dynsym
->sh_addr
);
1986 put_dt(dynamic
, DT_STRSZ
, dynstr
->data_offset
);
1987 put_dt(dynamic
, DT_SYMENT
, sizeof(ElfW(Sym
)));
1988 #ifdef TCC_TARGET_X86_64
1989 put_dt(dynamic
, DT_RELA
, rel_addr
);
1990 put_dt(dynamic
, DT_RELASZ
, rel_size
);
1991 put_dt(dynamic
, DT_RELAENT
, sizeof(ElfW_Rel
));
1993 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1994 put_dt(dynamic
, DT_PLTGOT
, s1
->got
->sh_addr
);
1995 put_dt(dynamic
, DT_PLTRELSZ
, rel_size
);
1996 put_dt(dynamic
, DT_JMPREL
, rel_addr
);
1997 put_dt(dynamic
, DT_PLTREL
, DT_REL
);
1998 put_dt(dynamic
, DT_REL
, bss_addr
);
1999 put_dt(dynamic
, DT_RELSZ
, bss_size
);
2001 put_dt(dynamic
, DT_REL
, rel_addr
);
2002 put_dt(dynamic
, DT_RELSZ
, rel_size
);
2003 put_dt(dynamic
, DT_RELENT
, sizeof(ElfW_Rel
));
2007 put_dt(dynamic
, DT_DEBUG
, 0);
2008 put_dt(dynamic
, DT_NULL
, 0);
2011 ehdr
.e_phentsize
= sizeof(ElfW(Phdr
));
2012 ehdr
.e_phnum
= phnum
;
2013 ehdr
.e_phoff
= sizeof(ElfW(Ehdr
));
2016 /* all other sections come after */
2017 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2018 s
= s1
->sections
[i
];
2019 if (phnum
> 0 && (s
->sh_flags
& SHF_ALLOC
))
2021 section_order
[sh_order_index
++] = i
;
2023 file_offset
= (file_offset
+ s
->sh_addralign
- 1) &
2024 ~(s
->sh_addralign
- 1);
2025 s
->sh_offset
= file_offset
;
2026 if (s
->sh_type
!= SHT_NOBITS
)
2027 file_offset
+= s
->sh_size
;
2030 /* if building executable or DLL, then relocate each section
2031 except the GOT which is already relocated */
2032 if (file_type
!= TCC_OUTPUT_OBJ
) {
2033 relocate_syms(s1
, 0);
2035 if (s1
->nb_errors
!= 0) {
2041 /* relocate sections */
2042 /* XXX: ignore sections with allocated relocations ? */
2043 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2044 s
= s1
->sections
[i
];
2045 if (s
->reloc
&& s
!= s1
->got
&& (s
->sh_flags
& SHF_ALLOC
)) //gr
2046 relocate_section(s1
, s
);
2049 /* relocate relocation entries if the relocation tables are
2050 allocated in the executable */
2051 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2052 s
= s1
->sections
[i
];
2053 if ((s
->sh_flags
& SHF_ALLOC
) &&
2054 s
->sh_type
== SHT_RELX
) {
2055 relocate_rel(s1
, s
);
2059 /* get entry point address */
2060 if (file_type
== TCC_OUTPUT_EXE
)
2061 ehdr
.e_entry
= (uplong
)tcc_get_symbol_err(s1
, "_start");
2063 ehdr
.e_entry
= text_section
->sh_addr
; /* XXX: is it correct ? */
2065 if (file_type
== TCC_OUTPUT_EXE
&& s1
->static_link
)
2068 /* write elf file */
2069 if (file_type
== TCC_OUTPUT_OBJ
)
2074 fd
= open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
, mode
);
2076 tcc_error_noabort("could not write '%s'", filename
);
2079 f
= fdopen(fd
, "wb");
2081 printf("<- %s\n", filename
);
2083 #ifdef TCC_TARGET_COFF
2084 if (s1
->output_format
== TCC_OUTPUT_FORMAT_COFF
) {
2085 tcc_output_coff(s1
, f
);
2088 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
2089 sort_syms(s1
, symtab_section
);
2092 file_offset
= (file_offset
+ 3) & -4;
2095 ehdr
.e_ident
[0] = ELFMAG0
;
2096 ehdr
.e_ident
[1] = ELFMAG1
;
2097 ehdr
.e_ident
[2] = ELFMAG2
;
2098 ehdr
.e_ident
[3] = ELFMAG3
;
2099 ehdr
.e_ident
[4] = ELFCLASSW
;
2100 ehdr
.e_ident
[5] = ELFDATA2LSB
;
2101 ehdr
.e_ident
[6] = EV_CURRENT
;
2102 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2103 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_FREEBSD
;
2105 #ifdef TCC_TARGET_ARM
2107 ehdr
.e_ident
[EI_OSABI
] = 0;
2108 ehdr
.e_flags
= 4 << 24;
2110 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_ARM
;
2115 case TCC_OUTPUT_EXE
:
2116 ehdr
.e_type
= ET_EXEC
;
2118 case TCC_OUTPUT_DLL
:
2119 ehdr
.e_type
= ET_DYN
;
2121 case TCC_OUTPUT_OBJ
:
2122 ehdr
.e_type
= ET_REL
;
2125 ehdr
.e_machine
= EM_TCC_TARGET
;
2126 ehdr
.e_version
= EV_CURRENT
;
2127 ehdr
.e_shoff
= file_offset
;
2128 ehdr
.e_ehsize
= sizeof(ElfW(Ehdr
));
2129 ehdr
.e_shentsize
= sizeof(ElfW(Shdr
));
2130 ehdr
.e_shnum
= shnum
;
2131 ehdr
.e_shstrndx
= shnum
- 1;
2133 fwrite(&ehdr
, 1, sizeof(ElfW(Ehdr
)), f
);
2134 fwrite(phdr
, 1, phnum
* sizeof(ElfW(Phdr
)), f
);
2135 offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
2137 for(i
=1;i
<s1
->nb_sections
;i
++) {
2138 s
= s1
->sections
[section_order
[i
]];
2139 if (s
->sh_type
!= SHT_NOBITS
) {
2140 if (s
->sh_type
== SHT_DYNSYM
)
2141 patch_dynsym_undef(s1
, s
);
2142 while (offset
< s
->sh_offset
) {
2147 fwrite(s
->data
, 1, size
, f
);
2152 /* output section headers */
2153 while (offset
< ehdr
.e_shoff
) {
2158 for(i
=0;i
<s1
->nb_sections
;i
++) {
2160 memset(sh
, 0, sizeof(ElfW(Shdr
)));
2161 s
= s1
->sections
[i
];
2163 sh
->sh_name
= s
->sh_name
;
2164 sh
->sh_type
= s
->sh_type
;
2165 sh
->sh_flags
= s
->sh_flags
;
2166 sh
->sh_entsize
= s
->sh_entsize
;
2167 sh
->sh_info
= s
->sh_info
;
2169 sh
->sh_link
= s
->link
->sh_num
;
2170 sh
->sh_addralign
= s
->sh_addralign
;
2171 sh
->sh_addr
= s
->sh_addr
;
2172 sh
->sh_offset
= s
->sh_offset
;
2173 sh
->sh_size
= s
->sh_size
;
2175 fwrite(sh
, 1, sizeof(ElfW(Shdr
)), f
);
2178 tcc_output_binary(s1
, f
, section_order
);
2184 tcc_free(s1
->symtab_to_dynsym
);
2185 tcc_free(section_order
);
2187 tcc_free(s1
->got_offsets
);
2191 LIBTCCAPI
int tcc_output_file(TCCState
*s
, const char *filename
)
2194 #ifdef TCC_TARGET_PE
2195 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
2196 ret
= pe_output_file(s
, filename
);
2200 ret
= elf_output_file(s
, filename
);
2205 static void *load_data(int fd
, unsigned long file_offset
, unsigned long size
)
2209 data
= tcc_malloc(size
);
2210 lseek(fd
, file_offset
, SEEK_SET
);
2211 read(fd
, data
, size
);
2215 typedef struct SectionMergeInfo
{
2216 Section
*s
; /* corresponding existing section */
2217 unsigned long offset
; /* offset of the new section in the existing section */
2218 uint8_t new_section
; /* true if section 's' was added */
2219 uint8_t link_once
; /* true if link once section */
2222 /* load an object file and merge it with current files */
2223 /* XXX: handle correctly stab (debug) info */
2224 ST_FUNC
int tcc_load_object_file(TCCState
*s1
,
2225 int fd
, unsigned long file_offset
)
2228 ElfW(Shdr
) *shdr
, *sh
;
2229 int size
, i
, j
, offset
, offseti
, nb_syms
, sym_index
, ret
;
2230 unsigned char *strsec
, *strtab
;
2231 int *old_to_new_syms
;
2232 char *sh_name
, *name
;
2233 SectionMergeInfo
*sm_table
, *sm
;
2234 ElfW(Sym
) *sym
, *symtab
;
2235 ElfW_Rel
*rel
, *rel_end
;
2241 stab_index
= stabstr_index
= 0;
2243 if (read(fd
, &ehdr
, sizeof(ehdr
)) != sizeof(ehdr
))
2245 if (ehdr
.e_ident
[0] != ELFMAG0
||
2246 ehdr
.e_ident
[1] != ELFMAG1
||
2247 ehdr
.e_ident
[2] != ELFMAG2
||
2248 ehdr
.e_ident
[3] != ELFMAG3
)
2250 /* test if object file */
2251 if (ehdr
.e_type
!= ET_REL
)
2253 /* test CPU specific stuff */
2254 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2255 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2257 tcc_error_noabort("invalid object file");
2261 shdr
= load_data(fd
, file_offset
+ ehdr
.e_shoff
,
2262 sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2263 sm_table
= tcc_mallocz(sizeof(SectionMergeInfo
) * ehdr
.e_shnum
);
2265 /* load section names */
2266 sh
= &shdr
[ehdr
.e_shstrndx
];
2267 strsec
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2269 /* load symtab and strtab */
2270 old_to_new_syms
= NULL
;
2274 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2276 if (sh
->sh_type
== SHT_SYMTAB
) {
2278 tcc_error_noabort("object must contain only one symtab");
2283 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2284 symtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2285 sm_table
[i
].s
= symtab_section
;
2287 /* now load strtab */
2288 sh
= &shdr
[sh
->sh_link
];
2289 strtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2293 /* now examine each section and try to merge its content with the
2295 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2296 /* no need to examine section name strtab */
2297 if (i
== ehdr
.e_shstrndx
)
2300 sh_name
= strsec
+ sh
->sh_name
;
2301 /* ignore sections types we do not handle */
2302 if (sh
->sh_type
!= SHT_PROGBITS
&&
2303 sh
->sh_type
!= SHT_RELX
&&
2305 sh
->sh_type
!= SHT_ARM_EXIDX
&&
2307 sh
->sh_type
!= SHT_NOBITS
&&
2308 sh
->sh_type
!= SHT_PREINIT_ARRAY
&&
2309 sh
->sh_type
!= SHT_INIT_ARRAY
&&
2310 sh
->sh_type
!= SHT_FINI_ARRAY
&&
2311 strcmp(sh_name
, ".stabstr")
2314 if (sh
->sh_addralign
< 1)
2315 sh
->sh_addralign
= 1;
2316 /* find corresponding section, if any */
2317 for(j
= 1; j
< s1
->nb_sections
;j
++) {
2318 s
= s1
->sections
[j
];
2319 if (!strcmp(s
->name
, sh_name
)) {
2320 if (!strncmp(sh_name
, ".gnu.linkonce",
2321 sizeof(".gnu.linkonce") - 1)) {
2322 /* if a 'linkonce' section is already present, we
2323 do not add it again. It is a little tricky as
2324 symbols can still be defined in
2326 sm_table
[i
].link_once
= 1;
2333 /* not found: create new section */
2334 s
= new_section(s1
, sh_name
, sh
->sh_type
, sh
->sh_flags
);
2335 /* take as much info as possible from the section. sh_link and
2336 sh_info will be updated later */
2337 s
->sh_addralign
= sh
->sh_addralign
;
2338 s
->sh_entsize
= sh
->sh_entsize
;
2339 sm_table
[i
].new_section
= 1;
2341 if (sh
->sh_type
!= s
->sh_type
) {
2342 tcc_error_noabort("invalid section type");
2346 /* align start of section */
2347 offset
= s
->data_offset
;
2349 if (0 == strcmp(sh_name
, ".stab")) {
2353 if (0 == strcmp(sh_name
, ".stabstr")) {
2358 size
= sh
->sh_addralign
- 1;
2359 offset
= (offset
+ size
) & ~size
;
2360 if (sh
->sh_addralign
> s
->sh_addralign
)
2361 s
->sh_addralign
= sh
->sh_addralign
;
2362 s
->data_offset
= offset
;
2364 sm_table
[i
].offset
= offset
;
2366 /* concatenate sections */
2368 if (sh
->sh_type
!= SHT_NOBITS
) {
2370 lseek(fd
, file_offset
+ sh
->sh_offset
, SEEK_SET
);
2371 ptr
= section_ptr_add(s
, size
);
2372 read(fd
, ptr
, size
);
2374 s
->data_offset
+= size
;
2379 /* //gr relocate stab strings */
2380 if (stab_index
&& stabstr_index
) {
2383 s
= sm_table
[stab_index
].s
;
2384 a
= (Stab_Sym
*)(s
->data
+ sm_table
[stab_index
].offset
);
2385 b
= (Stab_Sym
*)(s
->data
+ s
->data_offset
);
2386 o
= sm_table
[stabstr_index
].offset
;
2388 a
->n_strx
+= o
, a
++;
2391 /* second short pass to update sh_link and sh_info fields of new
2393 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2395 if (!s
|| !sm_table
[i
].new_section
)
2398 if (sh
->sh_link
> 0)
2399 s
->link
= sm_table
[sh
->sh_link
].s
;
2400 if (sh
->sh_type
== SHT_RELX
) {
2401 s
->sh_info
= sm_table
[sh
->sh_info
].s
->sh_num
;
2402 /* update backward link */
2403 s1
->sections
[s
->sh_info
]->reloc
= s
;
2408 /* resolve symbols */
2409 old_to_new_syms
= tcc_mallocz(nb_syms
* sizeof(int));
2412 for(i
= 1; i
< nb_syms
; i
++, sym
++) {
2413 if (sym
->st_shndx
!= SHN_UNDEF
&&
2414 sym
->st_shndx
< SHN_LORESERVE
) {
2415 sm
= &sm_table
[sym
->st_shndx
];
2416 if (sm
->link_once
) {
2417 /* if a symbol is in a link once section, we use the
2418 already defined symbol. It is very important to get
2419 correct relocations */
2420 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
2421 name
= strtab
+ sym
->st_name
;
2422 sym_index
= find_elf_sym(symtab_section
, name
);
2424 old_to_new_syms
[i
] = sym_index
;
2428 /* if no corresponding section added, no need to add symbol */
2431 /* convert section number */
2432 sym
->st_shndx
= sm
->s
->sh_num
;
2434 sym
->st_value
+= sm
->offset
;
2437 name
= strtab
+ sym
->st_name
;
2438 sym_index
= add_elf_sym(symtab_section
, sym
->st_value
, sym
->st_size
,
2439 sym
->st_info
, sym
->st_other
,
2440 sym
->st_shndx
, name
);
2441 old_to_new_syms
[i
] = sym_index
;
2444 /* third pass to patch relocation entries */
2445 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2450 offset
= sm_table
[i
].offset
;
2451 switch(s
->sh_type
) {
2453 /* take relocation offset information */
2454 offseti
= sm_table
[sh
->sh_info
].offset
;
2455 rel_end
= (ElfW_Rel
*)(s
->data
+ s
->data_offset
);
2456 for(rel
= (ElfW_Rel
*)(s
->data
+ offset
);
2461 /* convert symbol index */
2462 type
= ELFW(R_TYPE
)(rel
->r_info
);
2463 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
2464 /* NOTE: only one symtab assumed */
2465 if (sym_index
>= nb_syms
)
2467 sym_index
= old_to_new_syms
[sym_index
];
2468 /* ignore link_once in rel section. */
2469 if (!sym_index
&& !sm
->link_once
2470 #ifdef TCC_TARGET_ARM
2471 && type
!= R_ARM_V4BX
2475 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2476 i
, strsec
+ sh
->sh_name
, rel
->r_offset
);
2479 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
2480 /* offset the relocation offset */
2481 rel
->r_offset
+= offseti
;
2493 tcc_free(old_to_new_syms
);
2500 typedef struct ArchiveHeader
{
2501 char ar_name
[16]; /* name of this member */
2502 char ar_date
[12]; /* file mtime */
2503 char ar_uid
[6]; /* owner uid; printed as decimal */
2504 char ar_gid
[6]; /* owner gid; printed as decimal */
2505 char ar_mode
[8]; /* file mode, printed as octal */
2506 char ar_size
[10]; /* file size, printed as decimal */
2507 char ar_fmag
[2]; /* should contain ARFMAG */
2510 static int get_be32(const uint8_t *b
)
2512 return b
[3] | (b
[2] << 8) | (b
[1] << 16) | (b
[0] << 24);
2515 /* load only the objects which resolve undefined symbols */
2516 static int tcc_load_alacarte(TCCState
*s1
, int fd
, int size
)
2518 int i
, bound
, nsyms
, sym_index
, off
, ret
;
2520 const char *ar_names
, *p
;
2521 const uint8_t *ar_index
;
2524 data
= tcc_malloc(size
);
2525 if (read(fd
, data
, size
) != size
)
2527 nsyms
= get_be32(data
);
2528 ar_index
= data
+ 4;
2529 ar_names
= ar_index
+ nsyms
* 4;
2533 for(p
= ar_names
, i
= 0; i
< nsyms
; i
++, p
+= strlen(p
)+1) {
2534 sym_index
= find_elf_sym(symtab_section
, p
);
2536 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
2537 if(sym
->st_shndx
== SHN_UNDEF
) {
2538 off
= get_be32(ar_index
+ i
* 4) + sizeof(ArchiveHeader
);
2540 printf("%5d\t%s\t%08x\n", i
, p
, sym
->st_shndx
);
2543 lseek(fd
, off
, SEEK_SET
);
2544 if(tcc_load_object_file(s1
, fd
, off
) < 0) {
2559 /* load a '.a' file */
2560 ST_FUNC
int tcc_load_archive(TCCState
*s1
, int fd
)
2567 unsigned long file_offset
;
2569 /* skip magic which was already checked */
2570 read(fd
, magic
, sizeof(magic
));
2573 len
= read(fd
, &hdr
, sizeof(hdr
));
2576 if (len
!= sizeof(hdr
)) {
2577 tcc_error_noabort("invalid archive");
2580 memcpy(ar_size
, hdr
.ar_size
, sizeof(hdr
.ar_size
));
2581 ar_size
[sizeof(hdr
.ar_size
)] = '\0';
2582 size
= strtol(ar_size
, NULL
, 0);
2583 memcpy(ar_name
, hdr
.ar_name
, sizeof(hdr
.ar_name
));
2584 for(i
= sizeof(hdr
.ar_name
) - 1; i
>= 0; i
--) {
2585 if (ar_name
[i
] != ' ')
2588 ar_name
[i
+ 1] = '\0';
2589 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2590 file_offset
= lseek(fd
, 0, SEEK_CUR
);
2592 size
= (size
+ 1) & ~1;
2593 if (!strcmp(ar_name
, "/")) {
2594 /* coff symbol table : we handle it */
2595 if(s1
->alacarte_link
)
2596 return tcc_load_alacarte(s1
, fd
, size
);
2597 } else if (!strcmp(ar_name
, "//") ||
2598 !strcmp(ar_name
, "__.SYMDEF") ||
2599 !strcmp(ar_name
, "__.SYMDEF/") ||
2600 !strcmp(ar_name
, "ARFILENAMES/")) {
2601 /* skip symbol table or archive names */
2603 if (tcc_load_object_file(s1
, fd
, file_offset
) < 0)
2606 lseek(fd
, file_offset
+ size
, SEEK_SET
);
2611 #ifndef TCC_TARGET_PE
2612 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2613 is referenced by the user (so it should be added as DT_NEEDED in
2614 the generated ELF file) */
2615 ST_FUNC
int tcc_load_dll(TCCState
*s1
, int fd
, const char *filename
, int level
)
2618 ElfW(Shdr
) *shdr
, *sh
, *sh1
;
2619 int i
, j
, nb_syms
, nb_dts
, sym_bind
, ret
;
2620 ElfW(Sym
) *sym
, *dynsym
;
2621 ElfW(Dyn
) *dt
, *dynamic
;
2622 unsigned char *dynstr
;
2623 const char *name
, *soname
;
2624 DLLReference
*dllref
;
2626 read(fd
, &ehdr
, sizeof(ehdr
));
2628 /* test CPU specific stuff */
2629 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2630 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2631 tcc_error_noabort("bad architecture");
2636 shdr
= load_data(fd
, ehdr
.e_shoff
, sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2638 /* load dynamic section and dynamic symbols */
2642 dynsym
= NULL
; /* avoid warning */
2643 dynstr
= NULL
; /* avoid warning */
2644 for(i
= 0, sh
= shdr
; i
< ehdr
.e_shnum
; i
++, sh
++) {
2645 switch(sh
->sh_type
) {
2647 nb_dts
= sh
->sh_size
/ sizeof(ElfW(Dyn
));
2648 dynamic
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2651 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2652 dynsym
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2653 sh1
= &shdr
[sh
->sh_link
];
2654 dynstr
= load_data(fd
, sh1
->sh_offset
, sh1
->sh_size
);
2661 /* compute the real library name */
2662 soname
= tcc_basename(filename
);
2664 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2665 if (dt
->d_tag
== DT_SONAME
) {
2666 soname
= dynstr
+ dt
->d_un
.d_val
;
2670 /* if the dll is already loaded, do not load it */
2671 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
2672 dllref
= s1
->loaded_dlls
[i
];
2673 if (!strcmp(soname
, dllref
->name
)) {
2674 /* but update level if needed */
2675 if (level
< dllref
->level
)
2676 dllref
->level
= level
;
2682 // printf("loading dll '%s'\n", soname);
2684 /* add the dll and its level */
2685 dllref
= tcc_mallocz(sizeof(DLLReference
) + strlen(soname
));
2686 dllref
->level
= level
;
2687 strcpy(dllref
->name
, soname
);
2688 dynarray_add((void ***)&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
, dllref
);
2690 /* add dynamic symbols in dynsym_section */
2691 for(i
= 1, sym
= dynsym
+ 1; i
< nb_syms
; i
++, sym
++) {
2692 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
2693 if (sym_bind
== STB_LOCAL
)
2695 name
= dynstr
+ sym
->st_name
;
2696 add_elf_sym(s1
->dynsymtab_section
, sym
->st_value
, sym
->st_size
,
2697 sym
->st_info
, sym
->st_other
, sym
->st_shndx
, name
);
2700 /* load all referenced DLLs */
2701 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2704 name
= dynstr
+ dt
->d_un
.d_val
;
2705 for(j
= 0; j
< s1
->nb_loaded_dlls
; j
++) {
2706 dllref
= s1
->loaded_dlls
[j
];
2707 if (!strcmp(name
, dllref
->name
))
2708 goto already_loaded
;
2710 if (tcc_add_dll(s1
, name
, AFF_REFERENCED_DLL
) < 0) {
2711 tcc_error_noabort("referenced dll '%s' not found", name
);
2728 #define LD_TOK_NAME 256
2729 #define LD_TOK_EOF (-1)
2731 /* return next ld script token */
2732 static int ld_next(TCCState
*s1
, char *name
, int name_size
)
2750 file
->buf_ptr
= parse_comment(file
->buf_ptr
);
2751 ch
= file
->buf_ptr
[0];
2759 /* case 'a' ... 'z': */
2786 /* case 'A' ... 'z': */
2821 if (!((ch
>= 'a' && ch
<= 'z') ||
2822 (ch
>= 'A' && ch
<= 'Z') ||
2823 (ch
>= '0' && ch
<= '9') ||
2824 strchr("/.-_+=$:\\,~", ch
)))
2826 if ((q
- name
) < name_size
- 1) {
2843 printf("tok=%c %d\n", c
, c
);
2844 if (c
== LD_TOK_NAME
)
2845 printf(" name=%s\n", name
);
2851 * Extract the file name from the library name
2853 * /!\ No test on filename capacity, be careful
2855 static void libname_to_filename(TCCState
*s1
, const char libname
[], char filename
[])
2857 if (!s1
->static_link
) {
2858 sprintf(filename
, "lib%s.so", libname
);
2860 sprintf(filename
, "lib%s.a", libname
);
2864 static int ld_add_file(TCCState
*s1
, const char filename
[])
2868 ret
= tcc_add_file_internal(s1
, filename
, 0);
2870 ret
= tcc_add_dll(s1
, filename
, 0);
2874 static inline int new_undef_syms(void)
2877 ret
= new_undef_sym
;
2882 static int ld_add_file_list(TCCState
*s1
, const char *cmd
, int as_needed
)
2884 char filename
[1024], libname
[1024];
2885 int t
, group
, nblibs
= 0, ret
= 0;
2888 group
= !strcmp(cmd
, "GROUP");
2891 t
= ld_next(s1
, filename
, sizeof(filename
));
2894 t
= ld_next(s1
, filename
, sizeof(filename
));
2897 if (t
== LD_TOK_EOF
) {
2898 tcc_error_noabort("unexpected end of file");
2900 goto lib_parse_error
;
2901 } else if (t
== ')') {
2903 } else if (t
== '-') {
2904 t
= ld_next(s1
, filename
, sizeof(filename
));
2905 if ((t
!= LD_TOK_NAME
) || (filename
[0] != 'l')) {
2906 tcc_error_noabort("library name expected");
2908 goto lib_parse_error
;
2910 strcpy(libname
, &filename
[1]);
2911 libname_to_filename(s1
, libname
, filename
);
2912 } else if (t
!= LD_TOK_NAME
) {
2913 tcc_error_noabort("filename expected");
2915 goto lib_parse_error
;
2917 if (!strcmp(filename
, "AS_NEEDED")) {
2918 ret
= ld_add_file_list(s1
, cmd
, 1);
2920 goto lib_parse_error
;
2922 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2924 ret
= ld_add_file(s1
, filename
);
2926 goto lib_parse_error
;
2928 /* Add the filename *and* the libname to avoid future conversions */
2929 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(filename
));
2930 if (libname
[0] != '\0')
2931 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(libname
));
2935 t
= ld_next(s1
, filename
, sizeof(filename
));
2937 t
= ld_next(s1
, filename
, sizeof(filename
));
2940 if (group
&& !as_needed
) {
2941 while (new_undef_syms()) {
2944 for (i
= 0; i
< nblibs
; i
++)
2945 ld_add_file(s1
, libs
[i
]);
2949 dynarray_reset(&libs
, &nblibs
);
2953 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
2955 ST_FUNC
int tcc_load_ldscript(TCCState
*s1
)
2958 char filename
[1024];
2961 ch
= file
->buf_ptr
[0];
2964 t
= ld_next(s1
, cmd
, sizeof(cmd
));
2965 if (t
== LD_TOK_EOF
)
2967 else if (t
!= LD_TOK_NAME
)
2969 if (!strcmp(cmd
, "INPUT") ||
2970 !strcmp(cmd
, "GROUP")) {
2971 ret
= ld_add_file_list(s1
, cmd
, 0);
2974 } else if (!strcmp(cmd
, "OUTPUT_FORMAT") ||
2975 !strcmp(cmd
, "TARGET")) {
2976 /* ignore some commands */
2977 t
= ld_next(s1
, cmd
, sizeof(cmd
));
2981 t
= ld_next(s1
, filename
, sizeof(filename
));
2982 if (t
== LD_TOK_EOF
) {
2983 tcc_error_noabort("unexpected end of file");
2985 } else if (t
== ')') {
2995 #endif /* ndef TCC_TARGET_PE */