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(s
->symtab
, name
);
166 sym
= &((ElfW(Sym
) *)s
->symtab
->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));
839 s1
->got_offsets
= tab
;
840 memset(s1
->got_offsets
+ s1
->nb_got_offsets
, 0,
841 (n
- s1
->nb_got_offsets
) * sizeof(unsigned long));
842 s1
->nb_got_offsets
= n
;
844 s1
->got_offsets
[index
] = val
;
847 /* XXX: suppress that */
848 static void put32(unsigned char *p
, uint32_t val
)
856 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
857 defined(TCC_TARGET_X86_64)
858 static uint32_t get32(unsigned char *p
)
860 return p
[0] | (p
[1] << 8) | (p
[2] << 16) | (p
[3] << 24);
864 static void build_got(TCCState
*s1
)
868 /* if no got, then create it */
869 s1
->got
= new_section(s1
, ".got", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
870 s1
->got
->sh_entsize
= 4;
871 add_elf_sym(symtab_section
, 0, 4, ELFW(ST_INFO
)(STB_GLOBAL
, STT_OBJECT
),
872 0, s1
->got
->sh_num
, "_GLOBAL_OFFSET_TABLE_");
873 ptr
= section_ptr_add(s1
->got
, 3 * PTR_SIZE
);
875 /* keep space for _DYNAMIC pointer, if present */
877 /* two dummy got entries */
881 /* keep space for _DYNAMIC pointer, if present */
884 /* two dummy got entries */
892 /* put a got entry corresponding to a symbol in symtab_section. 'size'
893 and 'info' can be modifed if more precise info comes from the DLL */
894 static void put_got_entry(TCCState
*s1
,
895 int reloc_type
, unsigned long size
, int info
,
901 unsigned long offset
;
907 /* if a got entry already exists for that symbol, no need to add one */
908 if (sym_index
< s1
->nb_got_offsets
&&
909 s1
->got_offsets
[sym_index
] != 0)
912 put_got_offset(s1
, sym_index
, s1
->got
->data_offset
);
915 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
916 name
= symtab_section
->link
->data
+ sym
->st_name
;
917 offset
= sym
->st_value
;
918 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
920 #ifdef TCC_TARGET_X86_64
930 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
933 /* if we build a DLL, we add a %ebx offset */
934 if (s1
->output_type
== TCC_OUTPUT_DLL
)
940 /* add a PLT entry */
942 if (plt
->data_offset
== 0) {
943 /* first plt entry */
944 p
= section_ptr_add(plt
, 16);
945 p
[0] = 0xff; /* pushl got + PTR_SIZE */
947 put32(p
+ 2, PTR_SIZE
);
948 p
[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
950 put32(p
+ 8, PTR_SIZE
* 2);
953 p
= section_ptr_add(plt
, 16);
954 p
[0] = 0xff; /* jmp *(got + x) */
956 put32(p
+ 2, s1
->got
->data_offset
);
957 p
[6] = 0x68; /* push $xxx */
958 put32(p
+ 7, (plt
->data_offset
- 32) >> 1);
959 p
[11] = 0xe9; /* jmp plt_start */
960 put32(p
+ 12, -(plt
->data_offset
));
962 /* the symbol is modified so that it will be relocated to
964 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
965 if (s1
->output_type
== TCC_OUTPUT_EXE
)
967 offset
= plt
->data_offset
- 16;
969 #elif defined(TCC_TARGET_ARM)
970 if (reloc_type
== R_ARM_JUMP_SLOT
) {
974 /* if we build a DLL, we add a %ebx offset */
975 if (s1
->output_type
== TCC_OUTPUT_DLL
)
976 tcc_error("DLLs unimplemented!");
978 /* add a PLT entry */
980 if (plt
->data_offset
== 0) {
981 /* first plt entry */
982 p
= section_ptr_add(plt
, 16);
983 put32(p
, 0xe52de004);
984 put32(p
+ 4, 0xe59fe010);
985 put32(p
+ 8, 0xe08fe00e);
986 put32(p
+ 12, 0xe5bef008);
989 p
= section_ptr_add(plt
, 16);
990 put32(p
, 0xe59fc004);
991 put32(p
+4, 0xe08fc00c);
992 put32(p
+8, 0xe59cf000);
993 put32(p
+12, s1
->got
->data_offset
);
995 /* the symbol is modified so that it will be relocated to
997 if (s1
->output_type
== TCC_OUTPUT_EXE
)
998 offset
= plt
->data_offset
- 16;
1000 #elif defined(TCC_TARGET_C67)
1001 tcc_error("C67 got not implemented");
1003 #error unsupported CPU
1005 index
= put_elf_sym(s1
->dynsym
, offset
,
1006 size
, info
, 0, sym
->st_shndx
, name
);
1007 /* put a got entry */
1008 put_elf_reloc(s1
->dynsym
, s1
->got
,
1009 s1
->got
->data_offset
,
1012 ptr
= section_ptr_add(s1
->got
, PTR_SIZE
);
1016 /* build GOT and PLT entries */
1017 ST_FUNC
void build_got_entries(TCCState
*s1
)
1020 ElfW_Rel
*rel
, *rel_end
;
1022 int i
, type
, reloc_type
, sym_index
;
1024 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1025 s
= s1
->sections
[i
];
1026 if (s
->sh_type
!= SHT_RELX
)
1028 /* no need to handle got relocations */
1029 if (s
->link
!= symtab_section
)
1031 rel_end
= (ElfW_Rel
*)(s
->data
+ s
->data_offset
);
1032 for(rel
= (ElfW_Rel
*)s
->data
;
1035 type
= ELFW(R_TYPE
)(rel
->r_info
);
1037 #if defined(TCC_TARGET_I386)
1044 if (type
== R_386_GOT32
|| type
== R_386_PLT32
) {
1045 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1046 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1047 /* look at the symbol got offset. If none, then add one */
1048 if (type
== R_386_GOT32
)
1049 reloc_type
= R_386_GLOB_DAT
;
1051 reloc_type
= R_386_JMP_SLOT
;
1052 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1056 #elif defined(TCC_TARGET_ARM)
1057 case R_ARM_GOT_BREL
:
1058 case R_ARM_GOTOFF32
:
1059 case R_ARM_BASE_PREL
:
1063 if (type
== R_ARM_GOT_BREL
|| type
== R_ARM_PLT32
) {
1064 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1065 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1066 /* look at the symbol got offset. If none, then add one */
1067 if (type
== R_ARM_GOT_BREL
)
1068 reloc_type
= R_ARM_GLOB_DAT
;
1070 reloc_type
= R_ARM_JUMP_SLOT
;
1071 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1075 #elif defined(TCC_TARGET_C67)
1082 if (type
== R_C60_GOT32
|| type
== R_C60_PLT32
) {
1083 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1084 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1085 /* look at the symbol got offset. If none, then add one */
1086 if (type
== R_C60_GOT32
)
1087 reloc_type
= R_C60_GLOB_DAT
;
1089 reloc_type
= R_C60_JMP_SLOT
;
1090 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1094 #elif defined(TCC_TARGET_X86_64)
1095 case R_X86_64_GOT32
:
1096 case R_X86_64_GOTTPOFF
:
1097 case R_X86_64_GOTPCREL
:
1098 case R_X86_64_PLT32
:
1101 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
||
1102 type
== R_X86_64_PLT32
) {
1103 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1104 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1105 /* look at the symbol got offset. If none, then add one */
1106 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
)
1107 reloc_type
= R_X86_64_GLOB_DAT
;
1109 reloc_type
= R_X86_64_JUMP_SLOT
;
1110 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1115 #error unsupported CPU
1124 ST_FUNC Section
*new_symtab(TCCState
*s1
,
1125 const char *symtab_name
, int sh_type
, int sh_flags
,
1126 const char *strtab_name
,
1127 const char *hash_name
, int hash_sh_flags
)
1129 Section
*symtab
, *strtab
, *hash
;
1130 int *ptr
, nb_buckets
;
1132 symtab
= new_section(s1
, symtab_name
, sh_type
, sh_flags
);
1133 symtab
->sh_entsize
= sizeof(ElfW(Sym
));
1134 strtab
= new_section(s1
, strtab_name
, SHT_STRTAB
, sh_flags
);
1135 put_elf_str(strtab
, "");
1136 symtab
->link
= strtab
;
1137 put_elf_sym(symtab
, 0, 0, 0, 0, 0, NULL
);
1141 hash
= new_section(s1
, hash_name
, SHT_HASH
, hash_sh_flags
);
1142 hash
->sh_entsize
= sizeof(int);
1143 symtab
->hash
= hash
;
1144 hash
->link
= symtab
;
1146 ptr
= section_ptr_add(hash
, (2 + nb_buckets
+ 1) * sizeof(int));
1147 ptr
[0] = nb_buckets
;
1149 memset(ptr
+ 2, 0, (nb_buckets
+ 1) * sizeof(int));
1153 /* put dynamic tag */
1154 static void put_dt(Section
*dynamic
, int dt
, uplong val
)
1157 dyn
= section_ptr_add(dynamic
, sizeof(ElfW(Dyn
)));
1159 dyn
->d_un
.d_val
= val
;
1162 static void add_init_array_defines(TCCState
*s1
, const char *section_name
)
1166 char sym_start
[1024];
1169 snprintf(sym_start
, sizeof(sym_start
), "__%s_start", section_name
+ 1);
1170 snprintf(sym_end
, sizeof(sym_end
), "__%s_end", section_name
+ 1);
1172 s
= find_section(s1
, section_name
);
1177 end_offset
= s
->data_offset
;
1180 add_elf_sym(symtab_section
,
1182 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1183 s
->sh_num
, sym_start
);
1184 add_elf_sym(symtab_section
,
1186 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1187 s
->sh_num
, sym_end
);
1190 static int tcc_add_support(TCCState
*s1
, const char *filename
)
1193 snprintf(buf
, sizeof(buf
), "%s/%s", s1
->tcc_lib_path
, filename
);
1194 return tcc_add_file(s1
, buf
);
1197 ST_FUNC
void tcc_add_bcheck(TCCState
*s1
)
1199 #ifdef CONFIG_TCC_BCHECK
1201 Section
*init_section
;
1202 unsigned char *pinit
;
1205 if (0 == s1
->do_bounds_check
)
1208 /* XXX: add an object file to do that */
1209 ptr
= section_ptr_add(bounds_section
, sizeof(unsigned long));
1211 add_elf_sym(symtab_section
, 0, 0,
1212 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1213 bounds_section
->sh_num
, "__bounds_start");
1214 /* add bound check code */
1215 #ifndef TCC_TARGET_PE
1216 tcc_add_support(s1
, "bcheck.o");
1218 #ifdef TCC_TARGET_I386
1219 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
) {
1220 /* add 'call __bound_init()' in .init section */
1221 init_section
= find_section(s1
, ".init");
1222 pinit
= section_ptr_add(init_section
, 5);
1224 put32(pinit
+ 1, -4);
1225 sym_index
= find_elf_sym(symtab_section
, "__bound_init");
1226 put_elf_reloc(symtab_section
, init_section
,
1227 init_section
->data_offset
- 4, R_386_PC32
, sym_index
);
1233 /* add tcc runtime libraries */
1234 ST_FUNC
void tcc_add_runtime(TCCState
*s1
)
1239 if (!s1
->nostdlib
) {
1240 tcc_add_library(s1
, "c");
1241 #ifdef CONFIG_USE_LIBGCC
1242 tcc_add_file(s1
, TCC_LIBGCC
);
1243 #elif !defined WITHOUT_LIBTCC
1244 tcc_add_support(s1
, "libtcc1.a");
1246 /* add crt end if not memory output */
1247 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
)
1248 tcc_add_crt(s1
, "crtn.o");
1252 /* add various standard linker symbols (must be done after the
1253 sections are filled (for example after allocating common
1255 ST_FUNC
void tcc_add_linker_symbols(TCCState
*s1
)
1261 add_elf_sym(symtab_section
,
1262 text_section
->data_offset
, 0,
1263 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1264 text_section
->sh_num
, "_etext");
1265 add_elf_sym(symtab_section
,
1266 data_section
->data_offset
, 0,
1267 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1268 data_section
->sh_num
, "_edata");
1269 add_elf_sym(symtab_section
,
1270 bss_section
->data_offset
, 0,
1271 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1272 bss_section
->sh_num
, "_end");
1273 /* horrible new standard ldscript defines */
1274 add_init_array_defines(s1
, ".preinit_array");
1275 add_init_array_defines(s1
, ".init_array");
1276 add_init_array_defines(s1
, ".fini_array");
1278 /* add start and stop symbols for sections whose name can be
1280 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1281 s
= s1
->sections
[i
];
1282 if (s
->sh_type
== SHT_PROGBITS
&&
1283 (s
->sh_flags
& SHF_ALLOC
)) {
1287 /* check if section name can be expressed in C */
1293 if (!isid(ch
) && !isnum(ch
))
1297 snprintf(buf
, sizeof(buf
), "__start_%s", s
->name
);
1298 add_elf_sym(symtab_section
,
1300 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1302 snprintf(buf
, sizeof(buf
), "__stop_%s", s
->name
);
1303 add_elf_sym(symtab_section
,
1305 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1312 static void tcc_output_binary(TCCState
*s1
, FILE *f
,
1313 const int *section_order
)
1316 int i
, offset
, size
;
1319 for(i
=1;i
<s1
->nb_sections
;i
++) {
1320 s
= s1
->sections
[section_order
[i
]];
1321 if (s
->sh_type
!= SHT_NOBITS
&&
1322 (s
->sh_flags
& SHF_ALLOC
)) {
1323 while (offset
< s
->sh_offset
) {
1328 fwrite(s
->data
, 1, size
, f
);
1334 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1336 #define EXTRA_RELITEMS 14
1338 /* move the relocation value from .dynsym to .got */
1339 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1341 uint32_t *gotd
= (void *)s1
->got
->data
;
1342 ElfW(Sym
) *sym
, *sym_end
;
1344 gotd
+= 3; // dummy entries in .got
1345 /* relocate symbols in .dynsym */
1346 sym_end
= (ElfW(Sym
) *)(s
->data
+ s
->data_offset
);
1347 for (sym
= (ElfW(Sym
) *)s
->data
+ 1; sym
< sym_end
; sym
++) {
1348 if (sym
->st_shndx
== SHN_UNDEF
) {
1349 *gotd
++ = sym
->st_value
+ 6; // XXX 6 is magic ?
1356 #define EXTRA_RELITEMS 9
1358 /* zero plt offsets of weak symbols in .dynsym */
1359 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1361 ElfW(Sym
) *sym
, *sym_end
;
1363 sym_end
= (ElfW(Sym
) *)(s
->data
+ s
->data_offset
);
1364 for (sym
= (ElfW(Sym
) *)s
->data
+ 1; sym
< sym_end
; sym
++)
1365 if (sym
->st_shndx
== SHN_UNDEF
&& ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
1370 ST_FUNC
void fill_got_entry(TCCState
*s1
, ElfW_Rel
*rel
)
1372 int sym_index
= ELFW(R_SYM
) (rel
->r_info
);
1373 ElfW(Sym
) *sym
= &((ElfW(Sym
) *) symtab_section
->data
)[sym_index
];
1374 unsigned long offset
;
1376 if (sym_index
>= s1
->nb_got_offsets
)
1378 offset
= s1
->got_offsets
[sym_index
];
1379 section_reserve(s1
->got
, offset
+ PTR_SIZE
);
1380 #ifdef TCC_TARGET_X86_64
1381 /* only works for x86-64 */
1382 put32(s1
->got
->data
+ offset
+ 4, sym
->st_value
>> 32);
1384 put32(s1
->got
->data
+ offset
, sym
->st_value
& 0xffffffff);
1387 ST_FUNC
void fill_got(TCCState
*s1
)
1390 ElfW_Rel
*rel
, *rel_end
;
1393 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1394 s
= s1
->sections
[i
];
1395 if (s
->sh_type
!= SHT_RELX
)
1397 /* no need to handle got relocations */
1398 if (s
->link
!= symtab_section
)
1400 rel_end
= (ElfW_Rel
*) (s
->data
+ s
->data_offset
);
1401 for(rel
= (ElfW_Rel
*) s
->data
; rel
< rel_end
; rel
++) {
1402 switch (ELFW(R_TYPE
) (rel
->r_info
)) {
1403 case R_X86_64_GOT32
:
1404 case R_X86_64_GOTPCREL
:
1405 case R_X86_64_PLT32
:
1406 fill_got_entry(s1
, rel
);
1414 /* output an ELF file */
1415 /* XXX: suppress unneeded sections */
1416 static int elf_output_file(TCCState
*s1
, const char *filename
)
1422 int shnum
, i
, phnum
, file_offset
, offset
, size
, j
, sh_order_index
, k
;
1425 Section
*strsec
, *s
;
1426 ElfW(Shdr
) shdr
, *sh
;
1427 ElfW(Phdr
) *phdr
, *ph
;
1428 Section
*interp
, *dynamic
, *dynstr
;
1429 unsigned long saved_dynamic_data_offset
;
1431 int type
, file_type
;
1432 uplong rel_addr
, rel_size
;
1433 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1434 uplong bss_addr
, bss_size
;
1437 file_type
= s1
->output_type
;
1440 if (file_type
!= TCC_OUTPUT_OBJ
) {
1441 tcc_add_runtime(s1
);
1445 section_order
= NULL
;
1448 dynstr
= NULL
; /* avoid warning */
1449 saved_dynamic_data_offset
= 0; /* avoid warning */
1451 if (file_type
!= TCC_OUTPUT_OBJ
) {
1452 relocate_common_syms();
1454 tcc_add_linker_symbols(s1
);
1456 if (!s1
->static_link
) {
1458 int sym_index
, index
;
1459 ElfW(Sym
) *esym
, *sym_end
;
1461 if (file_type
== TCC_OUTPUT_EXE
) {
1463 /* allow override the dynamic loader */
1464 const char *elfint
= getenv("LD_SO");
1466 elfint
= CONFIG_TCC_ELFINTERP
;
1467 /* add interpreter section only if executable */
1468 interp
= new_section(s1
, ".interp", SHT_PROGBITS
, SHF_ALLOC
);
1469 interp
->sh_addralign
= 1;
1470 ptr
= section_ptr_add(interp
, 1+strlen(elfint
));
1471 strcpy(ptr
, elfint
);
1474 /* add dynamic symbol table */
1475 s1
->dynsym
= new_symtab(s1
, ".dynsym", SHT_DYNSYM
, SHF_ALLOC
,
1477 ".hash", SHF_ALLOC
);
1478 dynstr
= s1
->dynsym
->link
;
1480 /* add dynamic section */
1481 dynamic
= new_section(s1
, ".dynamic", SHT_DYNAMIC
,
1482 SHF_ALLOC
| SHF_WRITE
);
1483 dynamic
->link
= dynstr
;
1484 dynamic
->sh_entsize
= sizeof(ElfW(Dyn
));
1487 s1
->plt
= new_section(s1
, ".plt", SHT_PROGBITS
,
1488 SHF_ALLOC
| SHF_EXECINSTR
);
1489 s1
->plt
->sh_entsize
= 4;
1493 /* scan for undefined symbols and see if they are in the
1494 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1495 is found, then we add it in the PLT. If a symbol
1496 STT_OBJECT is found, we add it in the .bss section with
1497 a suitable relocation */
1498 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+
1499 symtab_section
->data_offset
);
1500 if (file_type
== TCC_OUTPUT_EXE
) {
1501 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
1504 if (sym
->st_shndx
== SHN_UNDEF
) {
1505 name
= symtab_section
->link
->data
+ sym
->st_name
;
1506 sym_index
= find_elf_sym(s1
->dynsymtab_section
, name
);
1508 esym
= &((ElfW(Sym
) *)s1
->dynsymtab_section
->data
)[sym_index
];
1509 type
= ELFW(ST_TYPE
)(esym
->st_info
);
1510 if ((type
== STT_FUNC
) || (type
== STT_GNU_IFUNC
)) {
1511 put_got_entry(s1
, R_JMP_SLOT
, esym
->st_size
,
1512 ELFW(ST_INFO
)(STB_GLOBAL
,type
),
1513 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1514 } else if (type
== STT_OBJECT
) {
1515 unsigned long offset
;
1516 ElfW(Sym
) *dynsym
, *dynsym_end
;
1517 offset
= bss_section
->data_offset
;
1518 /* XXX: which alignment ? */
1519 offset
= (offset
+ 16 - 1) & -16;
1520 index
= put_elf_sym(s1
->dynsym
, offset
, esym
->st_size
,
1522 bss_section
->sh_num
, name
);
1523 // Ensure R_COPY works for weak symbol aliases
1524 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1525 dynsym_end
= (ElfW(Sym
) *)
1526 (s1
->dynsymtab_section
->data
+
1527 s1
->dynsymtab_section
->data_offset
);
1528 for(dynsym
= (ElfW(Sym
) *)s1
->dynsymtab_section
->data
+ 1;
1529 dynsym
< dynsym_end
; dynsym
++) {
1530 if ((dynsym
->st_value
== esym
->st_value
)
1531 && (ELFW(ST_BIND
)(dynsym
->st_info
) == STB_GLOBAL
)) {
1533 dynname
= s1
->dynsymtab_section
->link
->data
1535 put_elf_sym(s1
->dynsym
, offset
,
1538 bss_section
->sh_num
,
1544 put_elf_reloc(s1
->dynsym
, bss_section
,
1545 offset
, R_COPY
, index
);
1546 offset
+= esym
->st_size
;
1547 bss_section
->data_offset
= offset
;
1550 /* STB_WEAK undefined symbols are accepted */
1551 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1553 if (ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
||
1554 !strcmp(name
, "_fp_hw")) {
1556 tcc_error_noabort("undefined symbol '%s'", name
);
1559 } else if (s1
->rdynamic
&&
1560 ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1561 /* if -rdynamic option, then export all non
1563 name
= symtab_section
->link
->data
+ sym
->st_name
;
1564 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1566 sym
->st_shndx
, name
);
1573 /* now look at unresolved dynamic symbols and export
1574 corresponding symbol */
1575 sym_end
= (ElfW(Sym
) *)(s1
->dynsymtab_section
->data
+
1576 s1
->dynsymtab_section
->data_offset
);
1577 for(esym
= (ElfW(Sym
) *)s1
->dynsymtab_section
->data
+ 1;
1580 if (esym
->st_shndx
== SHN_UNDEF
) {
1581 name
= s1
->dynsymtab_section
->link
->data
+ esym
->st_name
;
1582 sym_index
= find_elf_sym(symtab_section
, name
);
1584 /* XXX: avoid adding a symbol if already
1585 present because of -rdynamic ? */
1586 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1587 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1589 sym
->st_shndx
, name
);
1591 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1592 /* weak symbols can stay undefined */
1594 tcc_warning("undefined dynamic symbol '%s'", name
);
1601 /* shared library case : we simply export all the global symbols */
1602 nb_syms
= symtab_section
->data_offset
/ sizeof(ElfW(Sym
));
1603 s1
->symtab_to_dynsym
= tcc_mallocz(sizeof(int) * nb_syms
);
1604 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
1607 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1608 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1609 if ((ELFW(ST_TYPE
)(sym
->st_info
) == STT_FUNC
||
1610 ELFW(ST_TYPE
)(sym
->st_info
) == STT_GNU_IFUNC
)
1611 && sym
->st_shndx
== SHN_UNDEF
) {
1612 put_got_entry(s1
, R_JMP_SLOT
, sym
->st_size
,
1614 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1616 else if (ELFW(ST_TYPE
)(sym
->st_info
) == STT_OBJECT
) {
1617 put_got_entry(s1
, R_X86_64_GLOB_DAT
, sym
->st_size
,
1619 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1624 name
= symtab_section
->link
->data
+ sym
->st_name
;
1625 index
= put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1627 sym
->st_shndx
, name
);
1628 s1
->symtab_to_dynsym
[sym
-
1629 (ElfW(Sym
) *)symtab_section
->data
] =
1636 build_got_entries(s1
);
1638 /* add a list of needed dlls */
1639 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
1640 DLLReference
*dllref
= s1
->loaded_dlls
[i
];
1641 if (dllref
->level
== 0)
1642 put_dt(dynamic
, DT_NEEDED
, put_elf_str(dynstr
, dllref
->name
));
1646 put_dt(dynamic
, DT_RPATH
, put_elf_str(dynstr
, s1
->rpath
));
1648 /* XXX: currently, since we do not handle PIC code, we
1649 must relocate the readonly segments */
1650 if (file_type
== TCC_OUTPUT_DLL
) {
1652 put_dt(dynamic
, DT_SONAME
, put_elf_str(dynstr
, s1
->soname
));
1653 put_dt(dynamic
, DT_TEXTREL
, 0);
1657 put_dt(dynamic
, DT_SYMBOLIC
, 0);
1659 /* add necessary space for other entries */
1660 saved_dynamic_data_offset
= dynamic
->data_offset
;
1661 dynamic
->data_offset
+= sizeof(ElfW(Dyn
)) * EXTRA_RELITEMS
;
1663 /* still need to build got entries in case of static link */
1664 build_got_entries(s1
);
1668 memset(&ehdr
, 0, sizeof(ehdr
));
1670 /* we add a section for symbols */
1671 strsec
= new_section(s1
, ".shstrtab", SHT_STRTAB
, 0);
1672 put_elf_str(strsec
, "");
1674 /* compute number of sections */
1675 shnum
= s1
->nb_sections
;
1677 /* this array is used to reorder sections in the output file */
1678 section_order
= tcc_malloc(sizeof(int) * shnum
);
1679 section_order
[0] = 0;
1682 /* compute number of program headers */
1685 case TCC_OUTPUT_OBJ
:
1688 case TCC_OUTPUT_EXE
:
1689 if (!s1
->static_link
)
1690 phnum
= 4 + HAVE_PHDR
;
1694 case TCC_OUTPUT_DLL
:
1699 /* allocate strings for section names and decide if an unallocated
1700 section should be output */
1701 /* NOTE: the strsec section comes last, so its size is also
1703 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1704 s
= s1
->sections
[i
];
1705 s
->sh_name
= put_elf_str(strsec
, s
->name
);
1707 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1712 s
->reloc
? s
->reloc
->name
: "n"
1715 /* when generating a DLL, we include relocations but we may
1717 if (file_type
== TCC_OUTPUT_DLL
&&
1718 s
->sh_type
== SHT_RELX
&&
1719 !(s
->sh_flags
& SHF_ALLOC
)) {
1720 /* //gr: avoid bogus relocs for empty (debug) sections */
1721 if (s1
->sections
[s
->sh_info
]->sh_flags
& SHF_ALLOC
)
1722 prepare_dynamic_rel(s1
, s
);
1723 else if (s1
->do_debug
)
1724 s
->sh_size
= s
->data_offset
;
1725 } else if (s1
->do_debug
||
1726 file_type
== TCC_OUTPUT_OBJ
||
1727 (s
->sh_flags
& SHF_ALLOC
) ||
1728 i
== (s1
->nb_sections
- 1)) {
1729 /* we output all sections if debug or object file */
1730 s
->sh_size
= s
->data_offset
;
1734 /* allocate program segment headers */
1735 phdr
= tcc_mallocz(phnum
* sizeof(ElfW(Phdr
)));
1737 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1738 file_offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
1743 /* compute section to program header mapping */
1744 if (s1
->has_text_addr
) {
1745 int a_offset
, p_offset
;
1746 addr
= s1
->text_addr
;
1747 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1749 a_offset
= (int) (addr
& (s1
->section_align
- 1));
1750 p_offset
= file_offset
& (s1
->section_align
- 1);
1751 if (a_offset
< p_offset
)
1752 a_offset
+= s1
->section_align
;
1753 file_offset
+= (a_offset
- p_offset
);
1755 if (file_type
== TCC_OUTPUT_DLL
)
1758 addr
= ELF_START_ADDR
;
1759 /* compute address after headers */
1760 addr
+= (file_offset
& (s1
->section_align
- 1));
1763 /* dynamic relocation table information, for .dynamic section */
1767 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1768 bss_addr
= bss_size
= 0;
1770 /* leave one program header for the program interpreter */
1773 ph
+= 1 + HAVE_PHDR
;
1775 for(j
= 0; j
< 2; j
++) {
1776 ph
->p_type
= PT_LOAD
;
1778 ph
->p_flags
= PF_R
| PF_X
;
1780 ph
->p_flags
= PF_R
| PF_W
;
1781 ph
->p_align
= s1
->section_align
;
1783 /* we do the following ordering: interp, symbol tables,
1784 relocations, progbits, nobits */
1785 /* XXX: do faster and simpler sorting */
1786 for(k
= 0; k
< 5; k
++) {
1787 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1788 s
= s1
->sections
[i
];
1789 /* compute if section should be included */
1791 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1795 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1796 (SHF_ALLOC
| SHF_WRITE
))
1802 } else if (s
->sh_type
== SHT_DYNSYM
||
1803 s
->sh_type
== SHT_STRTAB
||
1804 s
->sh_type
== SHT_HASH
) {
1807 } else if (s
->sh_type
== SHT_RELX
) {
1810 } else if (s
->sh_type
== SHT_NOBITS
) {
1817 section_order
[sh_order_index
++] = i
;
1819 /* section matches: we align it and add its size */
1821 addr
= (addr
+ s
->sh_addralign
- 1) &
1822 ~(s
->sh_addralign
- 1);
1823 file_offset
+= (int) ( addr
- tmp
);
1824 s
->sh_offset
= file_offset
;
1827 /* update program header infos */
1828 if (ph
->p_offset
== 0) {
1829 ph
->p_offset
= file_offset
;
1831 ph
->p_paddr
= ph
->p_vaddr
;
1833 /* update dynamic relocation infos */
1834 if (s
->sh_type
== SHT_RELX
) {
1835 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1836 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.got")) { // rel_size == 0) {
1838 rel_size
+= s
->sh_size
; // XXX only first rel.
1840 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.bss")) { // rel_size == 0) {
1842 bss_size
= s
->sh_size
; // XXX only first rel.
1847 rel_size
+= s
->sh_size
;
1851 if (s
->sh_type
!= SHT_NOBITS
)
1852 file_offset
+= s
->sh_size
;
1855 ph
->p_filesz
= file_offset
- ph
->p_offset
;
1856 ph
->p_memsz
= addr
- ph
->p_vaddr
;
1859 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1860 /* if in the middle of a page, we duplicate the page in
1861 memory so that one copy is RX and the other is RW */
1862 if ((addr
& (s1
->section_align
- 1)) != 0)
1863 addr
+= s1
->section_align
;
1865 addr
= (addr
+ s1
->section_align
- 1) & ~(s1
->section_align
- 1);
1866 file_offset
= (file_offset
+ s1
->section_align
- 1) &
1867 ~(s1
->section_align
- 1);
1872 /* if interpreter, then add corresponing program header */
1876 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1878 int len
= phnum
* sizeof(ElfW(Phdr
));
1880 ph
->p_type
= PT_PHDR
;
1881 ph
->p_offset
= sizeof(ElfW(Ehdr
));
1882 ph
->p_vaddr
= interp
->sh_addr
- len
;
1883 ph
->p_paddr
= ph
->p_vaddr
;
1884 ph
->p_filesz
= ph
->p_memsz
= len
;
1885 ph
->p_flags
= PF_R
| PF_X
;
1886 ph
->p_align
= 4; // interp->sh_addralign;
1891 ph
->p_type
= PT_INTERP
;
1892 ph
->p_offset
= interp
->sh_offset
;
1893 ph
->p_vaddr
= interp
->sh_addr
;
1894 ph
->p_paddr
= ph
->p_vaddr
;
1895 ph
->p_filesz
= interp
->sh_size
;
1896 ph
->p_memsz
= interp
->sh_size
;
1898 ph
->p_align
= interp
->sh_addralign
;
1901 /* if dynamic section, then add corresponing program header */
1905 ph
= &phdr
[phnum
- 1];
1907 ph
->p_type
= PT_DYNAMIC
;
1908 ph
->p_offset
= dynamic
->sh_offset
;
1909 ph
->p_vaddr
= dynamic
->sh_addr
;
1910 ph
->p_paddr
= ph
->p_vaddr
;
1911 ph
->p_filesz
= dynamic
->sh_size
;
1912 ph
->p_memsz
= dynamic
->sh_size
;
1913 ph
->p_flags
= PF_R
| PF_W
;
1914 ph
->p_align
= dynamic
->sh_addralign
;
1916 /* put GOT dynamic section address */
1917 put32(s1
->got
->data
, dynamic
->sh_addr
);
1919 /* relocate the PLT */
1920 if (file_type
== TCC_OUTPUT_EXE
1921 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1922 || file_type
== TCC_OUTPUT_DLL
1928 p_end
= p
+ s1
->plt
->data_offset
;
1930 #if defined(TCC_TARGET_I386)
1931 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
1932 put32(p
+ 8, get32(p
+ 8) + s1
->got
->sh_addr
);
1935 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
1938 #elif defined(TCC_TARGET_X86_64)
1939 int x
= s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 6;
1940 put32(p
+ 2, get32(p
+ 2) + x
);
1941 put32(p
+ 8, get32(p
+ 8) + x
- 6);
1944 put32(p
+ 2, get32(p
+ 2) + x
+ s1
->plt
->data
- p
);
1947 #elif defined(TCC_TARGET_ARM)
1949 x
=s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 12;
1952 put32(p
+ 12, x
+ get32(p
+ 12) + s1
->plt
->data
- p
);
1955 #elif defined(TCC_TARGET_C67)
1958 #error unsupported CPU
1963 /* relocate symbols in .dynsym */
1964 sym_end
= (ElfW(Sym
) *)(s1
->dynsym
->data
+ s1
->dynsym
->data_offset
);
1965 for(sym
= (ElfW(Sym
) *)s1
->dynsym
->data
+ 1;
1968 if (sym
->st_shndx
== SHN_UNDEF
) {
1969 /* relocate to the PLT if the symbol corresponds
1972 sym
->st_value
+= s1
->plt
->sh_addr
;
1973 } else if (sym
->st_shndx
< SHN_LORESERVE
) {
1974 /* do symbol relocation */
1975 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
1979 /* put dynamic section entries */
1980 dynamic
->data_offset
= saved_dynamic_data_offset
;
1981 put_dt(dynamic
, DT_HASH
, s1
->dynsym
->hash
->sh_addr
);
1982 put_dt(dynamic
, DT_STRTAB
, dynstr
->sh_addr
);
1983 put_dt(dynamic
, DT_SYMTAB
, s1
->dynsym
->sh_addr
);
1984 put_dt(dynamic
, DT_STRSZ
, dynstr
->data_offset
);
1985 put_dt(dynamic
, DT_SYMENT
, sizeof(ElfW(Sym
)));
1986 #ifdef TCC_TARGET_X86_64
1987 put_dt(dynamic
, DT_RELA
, rel_addr
);
1988 put_dt(dynamic
, DT_RELASZ
, rel_size
);
1989 put_dt(dynamic
, DT_RELAENT
, sizeof(ElfW_Rel
));
1991 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1992 put_dt(dynamic
, DT_PLTGOT
, s1
->got
->sh_addr
);
1993 put_dt(dynamic
, DT_PLTRELSZ
, rel_size
);
1994 put_dt(dynamic
, DT_JMPREL
, rel_addr
);
1995 put_dt(dynamic
, DT_PLTREL
, DT_REL
);
1996 put_dt(dynamic
, DT_REL
, bss_addr
);
1997 put_dt(dynamic
, DT_RELSZ
, bss_size
);
1999 put_dt(dynamic
, DT_REL
, rel_addr
);
2000 put_dt(dynamic
, DT_RELSZ
, rel_size
);
2001 put_dt(dynamic
, DT_RELENT
, sizeof(ElfW_Rel
));
2005 put_dt(dynamic
, DT_DEBUG
, 0);
2006 put_dt(dynamic
, DT_NULL
, 0);
2009 ehdr
.e_phentsize
= sizeof(ElfW(Phdr
));
2010 ehdr
.e_phnum
= phnum
;
2011 ehdr
.e_phoff
= sizeof(ElfW(Ehdr
));
2014 /* all other sections come after */
2015 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2016 s
= s1
->sections
[i
];
2017 if (phnum
> 0 && (s
->sh_flags
& SHF_ALLOC
))
2019 section_order
[sh_order_index
++] = i
;
2021 file_offset
= (file_offset
+ s
->sh_addralign
- 1) &
2022 ~(s
->sh_addralign
- 1);
2023 s
->sh_offset
= file_offset
;
2024 if (s
->sh_type
!= SHT_NOBITS
)
2025 file_offset
+= s
->sh_size
;
2028 /* if building executable or DLL, then relocate each section
2029 except the GOT which is already relocated */
2030 if (file_type
!= TCC_OUTPUT_OBJ
) {
2031 relocate_syms(s1
, 0);
2033 if (s1
->nb_errors
!= 0) {
2039 /* relocate sections */
2040 /* XXX: ignore sections with allocated relocations ? */
2041 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2042 s
= s1
->sections
[i
];
2043 if (s
->reloc
&& s
!= s1
->got
&& (s
->sh_flags
& SHF_ALLOC
)) //gr
2044 relocate_section(s1
, s
);
2047 /* relocate relocation entries if the relocation tables are
2048 allocated in the executable */
2049 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2050 s
= s1
->sections
[i
];
2051 if ((s
->sh_flags
& SHF_ALLOC
) &&
2052 s
->sh_type
== SHT_RELX
) {
2053 relocate_rel(s1
, s
);
2057 /* get entry point address */
2058 if (file_type
== TCC_OUTPUT_EXE
)
2059 ehdr
.e_entry
= (uplong
)tcc_get_symbol_err(s1
, "_start");
2061 ehdr
.e_entry
= text_section
->sh_addr
; /* XXX: is it correct ? */
2063 if (file_type
== TCC_OUTPUT_EXE
&& s1
->static_link
)
2066 /* write elf file */
2067 if (file_type
== TCC_OUTPUT_OBJ
)
2072 fd
= open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
, mode
);
2074 tcc_error_noabort("could not write '%s'", filename
);
2077 f
= fdopen(fd
, "wb");
2079 printf("<- %s\n", filename
);
2081 #ifdef TCC_TARGET_COFF
2082 if (s1
->output_format
== TCC_OUTPUT_FORMAT_COFF
) {
2083 tcc_output_coff(s1
, f
);
2086 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
2087 sort_syms(s1
, symtab_section
);
2090 file_offset
= (file_offset
+ 3) & -4;
2093 ehdr
.e_ident
[0] = ELFMAG0
;
2094 ehdr
.e_ident
[1] = ELFMAG1
;
2095 ehdr
.e_ident
[2] = ELFMAG2
;
2096 ehdr
.e_ident
[3] = ELFMAG3
;
2097 ehdr
.e_ident
[4] = ELFCLASSW
;
2098 ehdr
.e_ident
[5] = ELFDATA2LSB
;
2099 ehdr
.e_ident
[6] = EV_CURRENT
;
2100 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2101 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_FREEBSD
;
2103 #ifdef TCC_TARGET_ARM
2105 ehdr
.e_ident
[EI_OSABI
] = 0;
2106 ehdr
.e_flags
= 4 << 24;
2108 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_ARM
;
2113 case TCC_OUTPUT_EXE
:
2114 ehdr
.e_type
= ET_EXEC
;
2116 case TCC_OUTPUT_DLL
:
2117 ehdr
.e_type
= ET_DYN
;
2119 case TCC_OUTPUT_OBJ
:
2120 ehdr
.e_type
= ET_REL
;
2123 ehdr
.e_machine
= EM_TCC_TARGET
;
2124 ehdr
.e_version
= EV_CURRENT
;
2125 ehdr
.e_shoff
= file_offset
;
2126 ehdr
.e_ehsize
= sizeof(ElfW(Ehdr
));
2127 ehdr
.e_shentsize
= sizeof(ElfW(Shdr
));
2128 ehdr
.e_shnum
= shnum
;
2129 ehdr
.e_shstrndx
= shnum
- 1;
2131 fwrite(&ehdr
, 1, sizeof(ElfW(Ehdr
)), f
);
2132 fwrite(phdr
, 1, phnum
* sizeof(ElfW(Phdr
)), f
);
2133 offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
2135 for(i
=1;i
<s1
->nb_sections
;i
++) {
2136 s
= s1
->sections
[section_order
[i
]];
2137 if (s
->sh_type
!= SHT_NOBITS
) {
2138 if (s
->sh_type
== SHT_DYNSYM
)
2139 patch_dynsym_undef(s1
, s
);
2140 while (offset
< s
->sh_offset
) {
2145 fwrite(s
->data
, 1, size
, f
);
2150 /* output section headers */
2151 while (offset
< ehdr
.e_shoff
) {
2156 for(i
=0;i
<s1
->nb_sections
;i
++) {
2158 memset(sh
, 0, sizeof(ElfW(Shdr
)));
2159 s
= s1
->sections
[i
];
2161 sh
->sh_name
= s
->sh_name
;
2162 sh
->sh_type
= s
->sh_type
;
2163 sh
->sh_flags
= s
->sh_flags
;
2164 sh
->sh_entsize
= s
->sh_entsize
;
2165 sh
->sh_info
= s
->sh_info
;
2167 sh
->sh_link
= s
->link
->sh_num
;
2168 sh
->sh_addralign
= s
->sh_addralign
;
2169 sh
->sh_addr
= s
->sh_addr
;
2170 sh
->sh_offset
= s
->sh_offset
;
2171 sh
->sh_size
= s
->sh_size
;
2173 fwrite(sh
, 1, sizeof(ElfW(Shdr
)), f
);
2176 tcc_output_binary(s1
, f
, section_order
);
2182 tcc_free(s1
->symtab_to_dynsym
);
2183 tcc_free(section_order
);
2185 tcc_free(s1
->got_offsets
);
2189 LIBTCCAPI
int tcc_output_file(TCCState
*s
, const char *filename
)
2192 #ifdef TCC_TARGET_PE
2193 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
2194 ret
= pe_output_file(s
, filename
);
2198 ret
= elf_output_file(s
, filename
);
2203 static void *load_data(int fd
, unsigned long file_offset
, unsigned long size
)
2207 data
= tcc_malloc(size
);
2208 lseek(fd
, file_offset
, SEEK_SET
);
2209 read(fd
, data
, size
);
2213 typedef struct SectionMergeInfo
{
2214 Section
*s
; /* corresponding existing section */
2215 unsigned long offset
; /* offset of the new section in the existing section */
2216 uint8_t new_section
; /* true if section 's' was added */
2217 uint8_t link_once
; /* true if link once section */
2220 /* load an object file and merge it with current files */
2221 /* XXX: handle correctly stab (debug) info */
2222 ST_FUNC
int tcc_load_object_file(TCCState
*s1
,
2223 int fd
, unsigned long file_offset
)
2226 ElfW(Shdr
) *shdr
, *sh
;
2227 int size
, i
, j
, offset
, offseti
, nb_syms
, sym_index
, ret
;
2228 unsigned char *strsec
, *strtab
;
2229 int *old_to_new_syms
;
2230 char *sh_name
, *name
;
2231 SectionMergeInfo
*sm_table
, *sm
;
2232 ElfW(Sym
) *sym
, *symtab
;
2233 ElfW_Rel
*rel
, *rel_end
;
2239 stab_index
= stabstr_index
= 0;
2241 if (read(fd
, &ehdr
, sizeof(ehdr
)) != sizeof(ehdr
))
2243 if (ehdr
.e_ident
[0] != ELFMAG0
||
2244 ehdr
.e_ident
[1] != ELFMAG1
||
2245 ehdr
.e_ident
[2] != ELFMAG2
||
2246 ehdr
.e_ident
[3] != ELFMAG3
)
2248 /* test if object file */
2249 if (ehdr
.e_type
!= ET_REL
)
2251 /* test CPU specific stuff */
2252 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2253 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2255 tcc_error_noabort("invalid object file");
2259 shdr
= load_data(fd
, file_offset
+ ehdr
.e_shoff
,
2260 sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2261 sm_table
= tcc_mallocz(sizeof(SectionMergeInfo
) * ehdr
.e_shnum
);
2263 /* load section names */
2264 sh
= &shdr
[ehdr
.e_shstrndx
];
2265 strsec
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2267 /* load symtab and strtab */
2268 old_to_new_syms
= NULL
;
2272 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2274 if (sh
->sh_type
== SHT_SYMTAB
) {
2276 tcc_error_noabort("object must contain only one symtab");
2281 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2282 symtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2283 sm_table
[i
].s
= symtab_section
;
2285 /* now load strtab */
2286 sh
= &shdr
[sh
->sh_link
];
2287 strtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2291 /* now examine each section and try to merge its content with the
2293 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2294 /* no need to examine section name strtab */
2295 if (i
== ehdr
.e_shstrndx
)
2298 sh_name
= strsec
+ sh
->sh_name
;
2299 /* ignore sections types we do not handle */
2300 if (sh
->sh_type
!= SHT_PROGBITS
&&
2301 sh
->sh_type
!= SHT_RELX
&&
2303 sh
->sh_type
!= SHT_ARM_EXIDX
&&
2305 sh
->sh_type
!= SHT_NOBITS
&&
2306 sh
->sh_type
!= SHT_PREINIT_ARRAY
&&
2307 sh
->sh_type
!= SHT_INIT_ARRAY
&&
2308 sh
->sh_type
!= SHT_FINI_ARRAY
&&
2309 strcmp(sh_name
, ".stabstr")
2312 if (sh
->sh_addralign
< 1)
2313 sh
->sh_addralign
= 1;
2314 /* find corresponding section, if any */
2315 for(j
= 1; j
< s1
->nb_sections
;j
++) {
2316 s
= s1
->sections
[j
];
2317 if (!strcmp(s
->name
, sh_name
)) {
2318 if (!strncmp(sh_name
, ".gnu.linkonce",
2319 sizeof(".gnu.linkonce") - 1)) {
2320 /* if a 'linkonce' section is already present, we
2321 do not add it again. It is a little tricky as
2322 symbols can still be defined in
2324 sm_table
[i
].link_once
= 1;
2331 /* not found: create new section */
2332 s
= new_section(s1
, sh_name
, sh
->sh_type
, sh
->sh_flags
);
2333 /* take as much info as possible from the section. sh_link and
2334 sh_info will be updated later */
2335 s
->sh_addralign
= sh
->sh_addralign
;
2336 s
->sh_entsize
= sh
->sh_entsize
;
2337 sm_table
[i
].new_section
= 1;
2339 if (sh
->sh_type
!= s
->sh_type
) {
2340 tcc_error_noabort("invalid section type");
2344 /* align start of section */
2345 offset
= s
->data_offset
;
2347 if (0 == strcmp(sh_name
, ".stab")) {
2351 if (0 == strcmp(sh_name
, ".stabstr")) {
2356 size
= sh
->sh_addralign
- 1;
2357 offset
= (offset
+ size
) & ~size
;
2358 if (sh
->sh_addralign
> s
->sh_addralign
)
2359 s
->sh_addralign
= sh
->sh_addralign
;
2360 s
->data_offset
= offset
;
2362 sm_table
[i
].offset
= offset
;
2364 /* concatenate sections */
2366 if (sh
->sh_type
!= SHT_NOBITS
) {
2368 lseek(fd
, file_offset
+ sh
->sh_offset
, SEEK_SET
);
2369 ptr
= section_ptr_add(s
, size
);
2370 read(fd
, ptr
, size
);
2372 s
->data_offset
+= size
;
2377 /* //gr relocate stab strings */
2378 if (stab_index
&& stabstr_index
) {
2381 s
= sm_table
[stab_index
].s
;
2382 a
= (Stab_Sym
*)(s
->data
+ sm_table
[stab_index
].offset
);
2383 b
= (Stab_Sym
*)(s
->data
+ s
->data_offset
);
2384 o
= sm_table
[stabstr_index
].offset
;
2386 a
->n_strx
+= o
, a
++;
2389 /* second short pass to update sh_link and sh_info fields of new
2391 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2393 if (!s
|| !sm_table
[i
].new_section
)
2396 if (sh
->sh_link
> 0)
2397 s
->link
= sm_table
[sh
->sh_link
].s
;
2398 if (sh
->sh_type
== SHT_RELX
) {
2399 s
->sh_info
= sm_table
[sh
->sh_info
].s
->sh_num
;
2400 /* update backward link */
2401 s1
->sections
[s
->sh_info
]->reloc
= s
;
2406 /* resolve symbols */
2407 old_to_new_syms
= tcc_mallocz(nb_syms
* sizeof(int));
2410 for(i
= 1; i
< nb_syms
; i
++, sym
++) {
2411 if (sym
->st_shndx
!= SHN_UNDEF
&&
2412 sym
->st_shndx
< SHN_LORESERVE
) {
2413 sm
= &sm_table
[sym
->st_shndx
];
2414 if (sm
->link_once
) {
2415 /* if a symbol is in a link once section, we use the
2416 already defined symbol. It is very important to get
2417 correct relocations */
2418 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
2419 name
= strtab
+ sym
->st_name
;
2420 sym_index
= find_elf_sym(symtab_section
, name
);
2422 old_to_new_syms
[i
] = sym_index
;
2426 /* if no corresponding section added, no need to add symbol */
2429 /* convert section number */
2430 sym
->st_shndx
= sm
->s
->sh_num
;
2432 sym
->st_value
+= sm
->offset
;
2435 name
= strtab
+ sym
->st_name
;
2436 sym_index
= add_elf_sym(symtab_section
, sym
->st_value
, sym
->st_size
,
2437 sym
->st_info
, sym
->st_other
,
2438 sym
->st_shndx
, name
);
2439 old_to_new_syms
[i
] = sym_index
;
2442 /* third pass to patch relocation entries */
2443 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2448 offset
= sm_table
[i
].offset
;
2449 switch(s
->sh_type
) {
2451 /* take relocation offset information */
2452 offseti
= sm_table
[sh
->sh_info
].offset
;
2453 rel_end
= (ElfW_Rel
*)(s
->data
+ s
->data_offset
);
2454 for(rel
= (ElfW_Rel
*)(s
->data
+ offset
);
2459 /* convert symbol index */
2460 type
= ELFW(R_TYPE
)(rel
->r_info
);
2461 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
2462 /* NOTE: only one symtab assumed */
2463 if (sym_index
>= nb_syms
)
2465 sym_index
= old_to_new_syms
[sym_index
];
2466 /* ignore link_once in rel section. */
2467 if (!sym_index
&& !sm
->link_once
2468 #ifdef TCC_TARGET_ARM
2469 && type
!= R_ARM_V4BX
2473 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2474 i
, strsec
+ sh
->sh_name
, rel
->r_offset
);
2477 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
2478 /* offset the relocation offset */
2479 rel
->r_offset
+= offseti
;
2491 tcc_free(old_to_new_syms
);
2498 typedef struct ArchiveHeader
{
2499 char ar_name
[16]; /* name of this member */
2500 char ar_date
[12]; /* file mtime */
2501 char ar_uid
[6]; /* owner uid; printed as decimal */
2502 char ar_gid
[6]; /* owner gid; printed as decimal */
2503 char ar_mode
[8]; /* file mode, printed as octal */
2504 char ar_size
[10]; /* file size, printed as decimal */
2505 char ar_fmag
[2]; /* should contain ARFMAG */
2508 static int get_be32(const uint8_t *b
)
2510 return b
[3] | (b
[2] << 8) | (b
[1] << 16) | (b
[0] << 24);
2513 /* load only the objects which resolve undefined symbols */
2514 static int tcc_load_alacarte(TCCState
*s1
, int fd
, int size
)
2516 int i
, bound
, nsyms
, sym_index
, off
, ret
;
2518 const char *ar_names
, *p
;
2519 const uint8_t *ar_index
;
2522 data
= tcc_malloc(size
);
2523 if (read(fd
, data
, size
) != size
)
2525 nsyms
= get_be32(data
);
2526 ar_index
= data
+ 4;
2527 ar_names
= ar_index
+ nsyms
* 4;
2531 for(p
= ar_names
, i
= 0; i
< nsyms
; i
++, p
+= strlen(p
)+1) {
2532 sym_index
= find_elf_sym(symtab_section
, p
);
2534 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
2535 if(sym
->st_shndx
== SHN_UNDEF
) {
2536 off
= get_be32(ar_index
+ i
* 4) + sizeof(ArchiveHeader
);
2538 printf("%5d\t%s\t%08x\n", i
, p
, sym
->st_shndx
);
2541 lseek(fd
, off
, SEEK_SET
);
2542 if(tcc_load_object_file(s1
, fd
, off
) < 0) {
2557 /* load a '.a' file */
2558 ST_FUNC
int tcc_load_archive(TCCState
*s1
, int fd
)
2565 unsigned long file_offset
;
2567 /* skip magic which was already checked */
2568 read(fd
, magic
, sizeof(magic
));
2571 len
= read(fd
, &hdr
, sizeof(hdr
));
2574 if (len
!= sizeof(hdr
)) {
2575 tcc_error_noabort("invalid archive");
2578 memcpy(ar_size
, hdr
.ar_size
, sizeof(hdr
.ar_size
));
2579 ar_size
[sizeof(hdr
.ar_size
)] = '\0';
2580 size
= strtol(ar_size
, NULL
, 0);
2581 memcpy(ar_name
, hdr
.ar_name
, sizeof(hdr
.ar_name
));
2582 for(i
= sizeof(hdr
.ar_name
) - 1; i
>= 0; i
--) {
2583 if (ar_name
[i
] != ' ')
2586 ar_name
[i
+ 1] = '\0';
2587 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2588 file_offset
= lseek(fd
, 0, SEEK_CUR
);
2590 size
= (size
+ 1) & ~1;
2591 if (!strcmp(ar_name
, "/")) {
2592 /* coff symbol table : we handle it */
2593 if(s1
->alacarte_link
)
2594 return tcc_load_alacarte(s1
, fd
, size
);
2595 } else if (!strcmp(ar_name
, "//") ||
2596 !strcmp(ar_name
, "__.SYMDEF") ||
2597 !strcmp(ar_name
, "__.SYMDEF/") ||
2598 !strcmp(ar_name
, "ARFILENAMES/")) {
2599 /* skip symbol table or archive names */
2601 if (tcc_load_object_file(s1
, fd
, file_offset
) < 0)
2604 lseek(fd
, file_offset
+ size
, SEEK_SET
);
2609 #ifndef TCC_TARGET_PE
2610 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2611 is referenced by the user (so it should be added as DT_NEEDED in
2612 the generated ELF file) */
2613 ST_FUNC
int tcc_load_dll(TCCState
*s1
, int fd
, const char *filename
, int level
)
2616 ElfW(Shdr
) *shdr
, *sh
, *sh1
;
2617 int i
, j
, nb_syms
, nb_dts
, sym_bind
, ret
;
2618 ElfW(Sym
) *sym
, *dynsym
;
2619 ElfW(Dyn
) *dt
, *dynamic
;
2620 unsigned char *dynstr
;
2621 const char *name
, *soname
;
2622 DLLReference
*dllref
;
2624 read(fd
, &ehdr
, sizeof(ehdr
));
2626 /* test CPU specific stuff */
2627 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2628 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2629 tcc_error_noabort("bad architecture");
2634 shdr
= load_data(fd
, ehdr
.e_shoff
, sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2636 /* load dynamic section and dynamic symbols */
2640 dynsym
= NULL
; /* avoid warning */
2641 dynstr
= NULL
; /* avoid warning */
2642 for(i
= 0, sh
= shdr
; i
< ehdr
.e_shnum
; i
++, sh
++) {
2643 switch(sh
->sh_type
) {
2645 nb_dts
= sh
->sh_size
/ sizeof(ElfW(Dyn
));
2646 dynamic
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2649 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2650 dynsym
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2651 sh1
= &shdr
[sh
->sh_link
];
2652 dynstr
= load_data(fd
, sh1
->sh_offset
, sh1
->sh_size
);
2659 /* compute the real library name */
2660 soname
= tcc_basename(filename
);
2662 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2663 if (dt
->d_tag
== DT_SONAME
) {
2664 soname
= dynstr
+ dt
->d_un
.d_val
;
2668 /* if the dll is already loaded, do not load it */
2669 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
2670 dllref
= s1
->loaded_dlls
[i
];
2671 if (!strcmp(soname
, dllref
->name
)) {
2672 /* but update level if needed */
2673 if (level
< dllref
->level
)
2674 dllref
->level
= level
;
2680 // printf("loading dll '%s'\n", soname);
2682 /* add the dll and its level */
2683 dllref
= tcc_mallocz(sizeof(DLLReference
) + strlen(soname
));
2684 dllref
->level
= level
;
2685 strcpy(dllref
->name
, soname
);
2686 dynarray_add((void ***)&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
, dllref
);
2688 /* add dynamic symbols in dynsym_section */
2689 for(i
= 1, sym
= dynsym
+ 1; i
< nb_syms
; i
++, sym
++) {
2690 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
2691 if (sym_bind
== STB_LOCAL
)
2693 name
= dynstr
+ sym
->st_name
;
2694 add_elf_sym(s1
->dynsymtab_section
, sym
->st_value
, sym
->st_size
,
2695 sym
->st_info
, sym
->st_other
, sym
->st_shndx
, name
);
2698 /* load all referenced DLLs */
2699 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2702 name
= dynstr
+ dt
->d_un
.d_val
;
2703 for(j
= 0; j
< s1
->nb_loaded_dlls
; j
++) {
2704 dllref
= s1
->loaded_dlls
[j
];
2705 if (!strcmp(name
, dllref
->name
))
2706 goto already_loaded
;
2708 if (tcc_add_dll(s1
, name
, AFF_REFERENCED_DLL
) < 0) {
2709 tcc_error_noabort("referenced dll '%s' not found", name
);
2726 #define LD_TOK_NAME 256
2727 #define LD_TOK_EOF (-1)
2729 /* return next ld script token */
2730 static int ld_next(TCCState
*s1
, char *name
, int name_size
)
2748 file
->buf_ptr
= parse_comment(file
->buf_ptr
);
2749 ch
= file
->buf_ptr
[0];
2757 /* case 'a' ... 'z': */
2784 /* case 'A' ... 'z': */
2819 if (!((ch
>= 'a' && ch
<= 'z') ||
2820 (ch
>= 'A' && ch
<= 'Z') ||
2821 (ch
>= '0' && ch
<= '9') ||
2822 strchr("/.-_+=$:\\,~", ch
)))
2824 if ((q
- name
) < name_size
- 1) {
2841 printf("tok=%c %d\n", c
, c
);
2842 if (c
== LD_TOK_NAME
)
2843 printf(" name=%s\n", name
);
2849 * Extract the file name from the library name
2851 * /!\ No test on filename capacity, be careful
2853 static void libname_to_filename(TCCState
*s1
, const char libname
[], char filename
[])
2855 if (!s1
->static_link
) {
2856 sprintf(filename
, "lib%s.so", libname
);
2858 sprintf(filename
, "lib%s.a", libname
);
2862 static int ld_add_file(TCCState
*s1
, const char filename
[])
2866 ret
= tcc_add_file_internal(s1
, filename
, 0);
2868 ret
= tcc_add_dll(s1
, filename
, 0);
2872 static inline int new_undef_syms(void)
2875 ret
= new_undef_sym
;
2880 static int ld_add_file_list(TCCState
*s1
, const char *cmd
, int as_needed
)
2882 char filename
[1024], libname
[1024];
2883 int t
, group
, nblibs
= 0, ret
= 0;
2886 group
= !strcmp(cmd
, "GROUP");
2889 t
= ld_next(s1
, filename
, sizeof(filename
));
2892 t
= ld_next(s1
, filename
, sizeof(filename
));
2895 if (t
== LD_TOK_EOF
) {
2896 tcc_error_noabort("unexpected end of file");
2898 goto lib_parse_error
;
2899 } else if (t
== ')') {
2901 } else if (t
== '-') {
2902 t
= ld_next(s1
, filename
, sizeof(filename
));
2903 if ((t
!= LD_TOK_NAME
) || (filename
[0] != 'l')) {
2904 tcc_error_noabort("library name expected");
2906 goto lib_parse_error
;
2908 strcpy(libname
, &filename
[1]);
2909 libname_to_filename(s1
, libname
, filename
);
2910 } else if (t
!= LD_TOK_NAME
) {
2911 tcc_error_noabort("filename expected");
2913 goto lib_parse_error
;
2915 if (!strcmp(filename
, "AS_NEEDED")) {
2916 ret
= ld_add_file_list(s1
, cmd
, 1);
2918 goto lib_parse_error
;
2920 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2922 ret
= ld_add_file(s1
, filename
);
2924 goto lib_parse_error
;
2926 /* Add the filename *and* the libname to avoid future conversions */
2927 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(filename
));
2928 if (libname
[0] != '\0')
2929 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(libname
));
2933 t
= ld_next(s1
, filename
, sizeof(filename
));
2935 t
= ld_next(s1
, filename
, sizeof(filename
));
2938 if (group
&& !as_needed
) {
2939 while (new_undef_syms()) {
2942 for (i
= 0; i
< nblibs
; i
++)
2943 ld_add_file(s1
, libs
[i
]);
2947 dynarray_reset(&libs
, &nblibs
);
2951 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
2953 ST_FUNC
int tcc_load_ldscript(TCCState
*s1
)
2956 char filename
[1024];
2959 ch
= file
->buf_ptr
[0];
2962 t
= ld_next(s1
, cmd
, sizeof(cmd
));
2963 if (t
== LD_TOK_EOF
)
2965 else if (t
!= LD_TOK_NAME
)
2967 if (!strcmp(cmd
, "INPUT") ||
2968 !strcmp(cmd
, "GROUP")) {
2969 ret
= ld_add_file_list(s1
, cmd
, 0);
2972 } else if (!strcmp(cmd
, "OUTPUT_FORMAT") ||
2973 !strcmp(cmd
, "TARGET")) {
2974 /* ignore some commands */
2975 t
= ld_next(s1
, cmd
, sizeof(cmd
));
2979 t
= ld_next(s1
, filename
, sizeof(filename
));
2980 if (t
== LD_TOK_EOF
) {
2981 tcc_error_noabort("unexpected end of file");
2983 } else if (t
== ')') {
2993 #endif /* ndef TCC_TARGET_PE */