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 #ifdef TCC_TARGET_X86_64
24 #define ElfW_Rel ElfW(Rela)
25 #define SHT_RELX SHT_RELA
26 #define REL_SECTION_FMT ".rela%s"
27 /* x86-64 requires PLT for DLLs */
28 #define TCC_OUTPUT_DLL_WITH_PLT
30 #define ElfW_Rel ElfW(Rel)
31 #define SHT_RELX SHT_REL
32 #define REL_SECTION_FMT ".rel%s"
35 static int new_undef_sym
= 0; /* Is there a new undefined sym since last new_undef_sym() */
37 /* XXX: DLL with PLT would only work with x86-64 for now */
38 //#define TCC_OUTPUT_DLL_WITH_PLT
40 ST_FUNC
int put_elf_str(Section
*s
, const char *sym
)
45 len
= strlen(sym
) + 1;
46 offset
= s
->data_offset
;
47 ptr
= section_ptr_add(s
, len
);
48 memcpy(ptr
, sym
, len
);
52 /* elf symbol hashing function */
53 static unsigned long elf_hash(const unsigned char *name
)
55 unsigned long h
= 0, g
;
58 h
= (h
<< 4) + *name
++;
67 /* rebuild hash table of section s */
68 /* NOTE: we do factorize the hash table code to go faster */
69 static void rebuild_hash(Section
*s
, unsigned int nb_buckets
)
72 int *ptr
, *hash
, nb_syms
, sym_index
, h
;
75 strtab
= s
->link
->data
;
76 nb_syms
= s
->data_offset
/ sizeof(ElfW(Sym
));
78 s
->hash
->data_offset
= 0;
79 ptr
= section_ptr_add(s
->hash
, (2 + nb_buckets
+ nb_syms
) * sizeof(int));
84 memset(hash
, 0, (nb_buckets
+ 1) * sizeof(int));
85 ptr
+= nb_buckets
+ 1;
87 sym
= (ElfW(Sym
) *)s
->data
+ 1;
88 for(sym_index
= 1; sym_index
< nb_syms
; sym_index
++) {
89 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
90 h
= elf_hash(strtab
+ sym
->st_name
) % nb_buckets
;
101 /* return the symbol number */
102 ST_FUNC
int put_elf_sym(Section
*s
, uplong value
, unsigned long size
,
103 int info
, int other
, int shndx
, const char *name
)
105 int name_offset
, sym_index
;
110 sym
= section_ptr_add(s
, sizeof(ElfW(Sym
)));
112 name_offset
= put_elf_str(s
->link
, name
);
115 /* XXX: endianness */
116 sym
->st_name
= name_offset
;
117 sym
->st_value
= value
;
120 sym
->st_other
= other
;
121 sym
->st_shndx
= shndx
;
122 sym_index
= sym
- (ElfW(Sym
) *)s
->data
;
126 ptr
= section_ptr_add(hs
, sizeof(int));
127 base
= (int *)hs
->data
;
128 /* only add global or weak symbols */
129 if (ELFW(ST_BIND
)(info
) != STB_LOCAL
) {
130 /* add another hashing entry */
132 h
= elf_hash(name
) % nbuckets
;
134 base
[2 + h
] = sym_index
;
136 /* we resize the hash table */
137 hs
->nb_hashed_syms
++;
138 if (hs
->nb_hashed_syms
> 2 * nbuckets
) {
139 rebuild_hash(s
, 2 * nbuckets
);
149 /* find global ELF symbol 'name' and return its index. Return 0 if not
151 ST_FUNC
int find_elf_sym(Section
*s
, const char *name
)
155 int nbuckets
, sym_index
, h
;
161 nbuckets
= ((int *)hs
->data
)[0];
162 h
= elf_hash(name
) % nbuckets
;
163 sym_index
= ((int *)hs
->data
)[2 + h
];
164 while (sym_index
!= 0) {
165 sym
= &((ElfW(Sym
) *)s
->data
)[sym_index
];
166 name1
= s
->link
->data
+ sym
->st_name
;
167 if (!strcmp(name
, name1
))
169 sym_index
= ((int *)hs
->data
)[2 + nbuckets
+ sym_index
];
174 /* return elf symbol value, signal error if 'err' is nonzero */
175 static void *get_elf_sym_addr(TCCState
*s
, const char *name
, int err
)
180 sym_index
= find_elf_sym(symtab_section
, name
);
181 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
182 if (!sym_index
|| sym
->st_shndx
== SHN_UNDEF
) {
184 error("%s not defined", name
);
187 return (void*)(uplong
)sym
->st_value
;
190 /* return elf symbol value */
191 LIBTCCAPI
void *tcc_get_symbol(TCCState
*s
, const char *name
)
193 return get_elf_sym_addr(s
, name
, 0);
196 /* return elf symbol value or error */
197 ST_FUNC
void *tcc_get_symbol_err(TCCState
*s
, const char *name
)
199 return get_elf_sym_addr(s
, name
, 1);
202 /* add an elf symbol : check if it is already defined and patch
203 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
204 ST_FUNC
int add_elf_sym(Section
*s
, uplong value
, unsigned long size
,
205 int info
, int other
, int sh_num
, const char *name
)
208 int sym_bind
, sym_index
, sym_type
, esym_bind
;
209 unsigned char sym_vis
, esym_vis
, new_vis
;
211 sym_bind
= ELFW(ST_BIND
)(info
);
212 sym_type
= ELFW(ST_TYPE
)(info
);
213 sym_vis
= ELFW(ST_VISIBILITY
)(other
);
215 if (sym_bind
!= STB_LOCAL
) {
216 /* we search global or weak symbols */
217 sym_index
= find_elf_sym(s
, name
);
220 esym
= &((ElfW(Sym
) *)s
->data
)[sym_index
];
221 if (esym
->st_shndx
!= SHN_UNDEF
) {
222 esym_bind
= ELFW(ST_BIND
)(esym
->st_info
);
223 /* propagate the most constraining visibility */
224 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
225 esym_vis
= ELFW(ST_VISIBILITY
)(esym
->st_other
);
226 if (esym_vis
== STV_DEFAULT
) {
228 } else if (sym_vis
== STV_DEFAULT
) {
231 new_vis
= (esym_vis
< sym_vis
) ? esym_vis
: sym_vis
;
233 esym
->st_other
= (esym
->st_other
& ~ELFW(ST_VISIBILITY
)(-1))
235 other
= esym
->st_other
; /* in case we have to patch esym */
236 if (sh_num
== SHN_UNDEF
) {
237 /* ignore adding of undefined symbol if the
238 corresponding symbol is already defined */
239 } else if (sym_bind
== STB_GLOBAL
&& esym_bind
== STB_WEAK
) {
240 /* global overrides weak, so patch */
242 } else if (sym_bind
== STB_WEAK
&& esym_bind
== STB_GLOBAL
) {
243 /* weak is ignored if already global */
244 } else if (sym_vis
== STV_HIDDEN
|| sym_vis
== STV_INTERNAL
) {
245 /* ignore hidden symbols after */
246 } else if (esym
->st_shndx
== SHN_COMMON
247 && (sh_num
< SHN_LORESERVE
|| sh_num
== SHN_COMMON
)) {
248 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
249 No idea if this is the correct solution ... */
251 } else if (s
== tcc_state
->dynsymtab_section
) {
252 /* we accept that two DLL define the same symbol */
255 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
256 sym_bind
, sh_num
, new_vis
, esym_bind
, esym
->st_shndx
, esym_vis
);
258 error_noabort("'%s' defined twice", name
);
262 esym
->st_info
= ELFW(ST_INFO
)(sym_bind
, sym_type
);
263 esym
->st_shndx
= sh_num
;
265 esym
->st_value
= value
;
266 esym
->st_size
= size
;
267 esym
->st_other
= other
;
271 sym_index
= put_elf_sym(s
, value
, size
,
272 ELFW(ST_INFO
)(sym_bind
, sym_type
), other
,
279 ST_FUNC
void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
280 int type
, int symbol
)
288 /* if no relocation section, create it */
289 snprintf(buf
, sizeof(buf
), REL_SECTION_FMT
, s
->name
);
290 /* if the symtab is allocated, then we consider the relocation
292 sr
= new_section(tcc_state
, buf
, SHT_RELX
, symtab
->sh_flags
);
293 sr
->sh_entsize
= sizeof(ElfW_Rel
);
295 sr
->sh_info
= s
->sh_num
;
298 rel
= section_ptr_add(sr
, sizeof(ElfW_Rel
));
299 rel
->r_offset
= offset
;
300 rel
->r_info
= ELFW(R_INFO
)(symbol
, type
);
301 #ifdef TCC_TARGET_X86_64
306 /* put stab debug information */
308 ST_FUNC
void put_stabs(const char *str
, int type
, int other
, int desc
,
313 sym
= section_ptr_add(stab_section
, sizeof(Stab_Sym
));
315 sym
->n_strx
= put_elf_str(stabstr_section
, str
);
320 sym
->n_other
= other
;
322 sym
->n_value
= value
;
325 ST_FUNC
void put_stabs_r(const char *str
, int type
, int other
, int desc
,
326 unsigned long value
, Section
*sec
, int sym_index
)
328 put_stabs(str
, type
, other
, desc
, value
);
329 put_elf_reloc(symtab_section
, stab_section
,
330 stab_section
->data_offset
- sizeof(unsigned int),
331 R_DATA_32
, sym_index
);
334 ST_FUNC
void put_stabn(int type
, int other
, int desc
, int value
)
336 put_stabs(NULL
, type
, other
, desc
, value
);
339 ST_FUNC
void put_stabd(int type
, int other
, int desc
)
341 put_stabs(NULL
, type
, other
, desc
, 0);
344 /* In an ELF file symbol table, the local symbols must appear below
345 the global and weak ones. Since TCC cannot sort it while generating
346 the code, we must do it after. All the relocation tables are also
347 modified to take into account the symbol table sorting */
348 static void sort_syms(TCCState
*s1
, Section
*s
)
350 int *old_to_new_syms
;
354 ElfW_Rel
*rel
, *rel_end
;
358 nb_syms
= s
->data_offset
/ sizeof(ElfW(Sym
));
359 new_syms
= tcc_malloc(nb_syms
* sizeof(ElfW(Sym
)));
360 old_to_new_syms
= tcc_malloc(nb_syms
* sizeof(int));
362 /* first pass for local symbols */
363 p
= (ElfW(Sym
) *)s
->data
;
365 for(i
= 0; i
< nb_syms
; i
++) {
366 if (ELFW(ST_BIND
)(p
->st_info
) == STB_LOCAL
) {
367 old_to_new_syms
[i
] = q
- new_syms
;
372 /* save the number of local symbols in section header */
373 s
->sh_info
= q
- new_syms
;
375 /* then second pass for non local symbols */
376 p
= (ElfW(Sym
) *)s
->data
;
377 for(i
= 0; i
< nb_syms
; i
++) {
378 if (ELFW(ST_BIND
)(p
->st_info
) != STB_LOCAL
) {
379 old_to_new_syms
[i
] = q
- new_syms
;
385 /* we copy the new symbols to the old */
386 memcpy(s
->data
, new_syms
, nb_syms
* sizeof(ElfW(Sym
)));
389 /* now we modify all the relocations */
390 for(i
= 1; i
< s1
->nb_sections
; i
++) {
391 sr
= s1
->sections
[i
];
392 if (sr
->sh_type
== SHT_RELX
&& sr
->link
== s
) {
393 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
394 for(rel
= (ElfW_Rel
*)sr
->data
;
397 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
398 type
= ELFW(R_TYPE
)(rel
->r_info
);
399 sym_index
= old_to_new_syms
[sym_index
];
400 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
405 tcc_free(old_to_new_syms
);
408 /* relocate common symbols in the .bss section */
409 ST_FUNC
void relocate_common_syms(void)
411 ElfW(Sym
) *sym
, *sym_end
;
412 unsigned long offset
, align
;
414 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+ symtab_section
->data_offset
);
415 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
418 if (sym
->st_shndx
== SHN_COMMON
) {
420 align
= sym
->st_value
;
421 offset
= bss_section
->data_offset
;
422 offset
= (offset
+ align
- 1) & -align
;
423 sym
->st_value
= offset
;
424 sym
->st_shndx
= bss_section
->sh_num
;
425 offset
+= sym
->st_size
;
426 bss_section
->data_offset
= offset
;
431 /* relocate symbol table, resolve undefined symbols if do_resolve is
432 true and output error if undefined symbol. */
433 ST_FUNC
void relocate_syms(TCCState
*s1
, int do_resolve
)
435 ElfW(Sym
) *sym
, *esym
, *sym_end
;
436 int sym_bind
, sh_num
, sym_index
;
439 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+ symtab_section
->data_offset
);
440 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
443 sh_num
= sym
->st_shndx
;
444 if (sh_num
== SHN_UNDEF
) {
445 name
= strtab_section
->data
+ sym
->st_name
;
447 #if !defined TCC_TARGET_PE || !defined _WIN32
449 name
= symtab_section
->link
->data
+ sym
->st_name
;
450 addr
= resolve_sym(s1
, name
);
452 sym
->st_value
= (uplong
)addr
;
456 } else if (s1
->dynsym
) {
457 /* if dynamic symbol exist, then use it */
458 sym_index
= find_elf_sym(s1
->dynsym
, name
);
460 esym
= &((ElfW(Sym
) *)s1
->dynsym
->data
)[sym_index
];
461 sym
->st_value
= esym
->st_value
;
465 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
467 if (!strcmp(name
, "_fp_hw"))
469 /* only weak symbols are accepted to be undefined. Their
471 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
472 if (sym_bind
== STB_WEAK
) {
475 error_noabort("undefined symbol '%s'", name
);
477 } else if (sh_num
< SHN_LORESERVE
) {
478 /* add section base */
479 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
485 #ifndef TCC_TARGET_PE
486 #ifdef TCC_TARGET_X86_64
487 #define JMP_TABLE_ENTRY_SIZE 14
488 static uplong
add_jmp_table(TCCState
*s1
, uplong val
)
490 char *p
= s1
->runtime_plt_and_got
+ s1
->runtime_plt_and_got_offset
;
491 s1
->runtime_plt_and_got_offset
+= JMP_TABLE_ENTRY_SIZE
;
496 *(uplong
*)(p
+ 6) = val
;
500 static uplong
add_got_table(TCCState
*s1
, uplong val
)
502 uplong
*p
= (uplong
*)(s1
->runtime_plt_and_got
+ s1
->runtime_plt_and_got_offset
);
503 s1
->runtime_plt_and_got_offset
+= sizeof(uplong
);
507 #elif defined TCC_TARGET_ARM
508 #define JMP_TABLE_ENTRY_SIZE 8
509 static int add_jmp_table(TCCState
*s1
, int val
)
511 uint32_t *p
= (uint32_t *)(s1
->runtime_plt_and_got
+ s1
->runtime_plt_and_got_offset
);
512 s1
->runtime_plt_and_got_offset
+= JMP_TABLE_ENTRY_SIZE
;
513 /* ldr pc, [pc, #-4] */
521 /* relocate a given section (CPU dependent) */
522 ST_FUNC
void relocate_section(TCCState
*s1
, Section
*s
)
525 ElfW_Rel
*rel
, *rel_end
, *qrel
;
530 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
535 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
536 qrel
= (ElfW_Rel
*)sr
->data
;
540 ptr
= s
->data
+ rel
->r_offset
;
542 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
543 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
545 #ifdef TCC_TARGET_X86_64
546 /* XXX: not tested */
547 val
+= rel
->r_addend
;
549 type
= ELFW(R_TYPE
)(rel
->r_info
);
550 addr
= s
->sh_addr
+ rel
->r_offset
;
554 #if defined(TCC_TARGET_I386)
556 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
557 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
558 qrel
->r_offset
= rel
->r_offset
;
560 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_386_32
);
564 qrel
->r_info
= ELFW(R_INFO
)(0, R_386_RELATIVE
);
571 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
573 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
575 qrel
->r_offset
= rel
->r_offset
;
576 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_386_PC32
);
581 *(int *)ptr
+= val
- addr
;
584 *(int *)ptr
+= val
- addr
;
591 *(int *)ptr
+= s1
->got
->sh_addr
- addr
;
594 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
597 /* we load the got offset */
598 *(int *)ptr
+= s1
->got_offsets
[sym_index
];
601 if (s1
->output_format
!= TCC_OUTPUT_FORMAT_BINARY
) {
603 error("can only produce 16-bit binary files");
605 *(short *)ptr
+= val
;
608 if (s1
->output_format
!= TCC_OUTPUT_FORMAT_BINARY
)
610 *(short *)ptr
+= val
- addr
;
612 #elif defined(TCC_TARGET_ARM)
619 x
= (*(int *)ptr
)&0xffffff;
620 (*(int *)ptr
) &= 0xff000000;
625 #ifndef TCC_TARGET_PE
626 if((x
& 3) != 0 || x
>= 0x4000000 || x
< -0x4000000)
627 if (s1
->output_type
== TCC_OUTPUT_MEMORY
)
628 x
+= add_jmp_table(s1
, val
) - val
; /* add veneer */
630 if((x
& 3) != 0 || x
>= 0x4000000 || x
< -0x4000000)
631 error("can't relocate value at %x",addr
);
640 x
= (*(int *)ptr
) & 0x7fffffff;
641 (*(int *)ptr
) &= 0x80000000;
644 if((x
^(x
>>1))&0x40000000)
645 error("can't relocate value at %x",addr
);
646 (*(int *)ptr
) |= x
& 0x7fffffff;
651 case R_ARM_BASE_PREL
:
652 *(int *)ptr
+= s1
->got
->sh_addr
- addr
;
655 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
658 /* we load the got offset */
659 *(int *)ptr
+= s1
->got_offsets
[sym_index
];
664 fprintf(stderr
,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
665 type
,addr
,(unsigned int)(long)ptr
,val
);
667 #elif defined(TCC_TARGET_C67)
675 /* put the low 16 bits of the absolute address */
676 // add to what is already there
678 orig
= ((*(int *)(ptr
)) >> 7) & 0xffff;
679 orig
|= (((*(int *)(ptr
+4)) >> 7) & 0xffff) << 16;
681 //patch both at once - assumes always in pairs Low - High
683 *(int *) ptr
= (*(int *) ptr
& (~(0xffff << 7)) ) | (((val
+orig
) & 0xffff) << 7);
684 *(int *)(ptr
+4) = (*(int *)(ptr
+4) & (~(0xffff << 7)) ) | ((((val
+orig
)>>16) & 0xffff) << 7);
690 fprintf(stderr
,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
691 type
,addr
,(unsigned int)(long)ptr
, val
);
693 #elif defined(TCC_TARGET_X86_64)
695 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
696 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
697 qrel
->r_addend
= *(long long *)ptr
+ val
;
700 *(long long *)ptr
+= val
;
704 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
705 /* XXX: this logic may depend on TCC's codegen
706 now TCC uses R_X86_64_32 even for a 64bit pointer */
707 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
708 qrel
->r_addend
= *(int *)ptr
+ val
;
713 case R_X86_64_PC32
: {
715 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
717 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
719 qrel
->r_offset
= rel
->r_offset
;
720 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_X86_64_PC32
);
721 qrel
->r_addend
= *(int *)ptr
;
726 diff
= (long long)val
- addr
;
727 if (diff
<= -2147483647 || diff
> 2147483647) {
728 #ifndef TCC_TARGET_PE
729 /* XXX: naive support for over 32bit jump */
730 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
731 val
= add_jmp_table(s1
, val
);
735 if (diff
<= -2147483647 || diff
> 2147483647) {
736 error("internal error: relocation failed");
743 *(int *)ptr
+= val
- addr
;
745 case R_X86_64_GLOB_DAT
:
746 case R_X86_64_JUMP_SLOT
:
749 case R_X86_64_GOTPCREL
:
750 #ifndef TCC_TARGET_PE
751 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
752 val
= add_got_table(s1
, val
- rel
->r_addend
) + rel
->r_addend
;
753 *(int *)ptr
+= val
- addr
;
757 *(int *)ptr
+= (s1
->got
->sh_addr
- addr
+
758 s1
->got_offsets
[sym_index
] - 4);
760 case R_X86_64_GOTTPOFF
:
761 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
764 /* we load the got offset */
765 *(int *)ptr
+= s1
->got_offsets
[sym_index
];
768 #error unsupported processor
772 /* if the relocation is allocated, we change its symbol table */
773 if (sr
->sh_flags
& SHF_ALLOC
)
774 sr
->link
= s1
->dynsym
;
777 /* relocate relocation table in 'sr' */
778 static void relocate_rel(TCCState
*s1
, Section
*sr
)
781 ElfW_Rel
*rel
, *rel_end
;
783 s
= s1
->sections
[sr
->sh_info
];
784 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
785 for(rel
= (ElfW_Rel
*)sr
->data
;
788 rel
->r_offset
+= s
->sh_addr
;
792 /* count the number of dynamic relocations so that we can reserve
794 static int prepare_dynamic_rel(TCCState
*s1
, Section
*sr
)
796 ElfW_Rel
*rel
, *rel_end
;
797 int sym_index
, esym_index
, type
, count
;
800 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
801 for(rel
= (ElfW_Rel
*)sr
->data
; rel
< rel_end
; rel
++) {
802 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
803 type
= ELFW(R_TYPE
)(rel
->r_info
);
805 #if defined(TCC_TARGET_I386)
807 #elif defined(TCC_TARGET_X86_64)
814 #if defined(TCC_TARGET_I386)
816 #elif defined(TCC_TARGET_X86_64)
819 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
828 /* allocate the section */
829 sr
->sh_flags
|= SHF_ALLOC
;
830 sr
->sh_size
= count
* sizeof(ElfW_Rel
);
835 static void put_got_offset(TCCState
*s1
, int index
, unsigned long val
)
840 if (index
>= s1
->nb_got_offsets
) {
841 /* find immediately bigger power of 2 and reallocate array */
845 tab
= tcc_realloc(s1
->got_offsets
, n
* sizeof(unsigned long));
847 error("memory full");
848 s1
->got_offsets
= tab
;
849 memset(s1
->got_offsets
+ s1
->nb_got_offsets
, 0,
850 (n
- s1
->nb_got_offsets
) * sizeof(unsigned long));
851 s1
->nb_got_offsets
= n
;
853 s1
->got_offsets
[index
] = val
;
856 /* XXX: suppress that */
857 static void put32(unsigned char *p
, uint32_t val
)
865 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
866 defined(TCC_TARGET_X86_64)
867 static uint32_t get32(unsigned char *p
)
869 return p
[0] | (p
[1] << 8) | (p
[2] << 16) | (p
[3] << 24);
873 static void build_got(TCCState
*s1
)
877 /* if no got, then create it */
878 s1
->got
= new_section(s1
, ".got", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
879 s1
->got
->sh_entsize
= 4;
880 add_elf_sym(symtab_section
, 0, 4, ELFW(ST_INFO
)(STB_GLOBAL
, STT_OBJECT
),
881 0, s1
->got
->sh_num
, "_GLOBAL_OFFSET_TABLE_");
882 ptr
= section_ptr_add(s1
->got
, 3 * PTR_SIZE
);
884 /* keep space for _DYNAMIC pointer, if present */
886 /* two dummy got entries */
890 /* keep space for _DYNAMIC pointer, if present */
893 /* two dummy got entries */
901 /* put a got entry corresponding to a symbol in symtab_section. 'size'
902 and 'info' can be modifed if more precise info comes from the DLL */
903 static void put_got_entry(TCCState
*s1
,
904 int reloc_type
, unsigned long size
, int info
,
910 unsigned long offset
;
916 /* if a got entry already exists for that symbol, no need to add one */
917 if (sym_index
< s1
->nb_got_offsets
&&
918 s1
->got_offsets
[sym_index
] != 0)
921 put_got_offset(s1
, sym_index
, s1
->got
->data_offset
);
924 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
925 name
= symtab_section
->link
->data
+ sym
->st_name
;
926 offset
= sym
->st_value
;
927 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
929 #ifdef TCC_TARGET_X86_64
939 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
942 /* if we build a DLL, we add a %ebx offset */
943 if (s1
->output_type
== TCC_OUTPUT_DLL
)
949 /* add a PLT entry */
951 if (plt
->data_offset
== 0) {
952 /* first plt entry */
953 p
= section_ptr_add(plt
, 16);
954 p
[0] = 0xff; /* pushl got + PTR_SIZE */
956 put32(p
+ 2, PTR_SIZE
);
957 p
[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
959 put32(p
+ 8, PTR_SIZE
* 2);
962 p
= section_ptr_add(plt
, 16);
963 p
[0] = 0xff; /* jmp *(got + x) */
965 put32(p
+ 2, s1
->got
->data_offset
);
966 p
[6] = 0x68; /* push $xxx */
967 put32(p
+ 7, (plt
->data_offset
- 32) >> 1);
968 p
[11] = 0xe9; /* jmp plt_start */
969 put32(p
+ 12, -(plt
->data_offset
));
971 /* the symbol is modified so that it will be relocated to
973 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
974 if (s1
->output_type
== TCC_OUTPUT_EXE
)
976 offset
= plt
->data_offset
- 16;
978 #elif defined(TCC_TARGET_ARM)
979 if (reloc_type
== R_ARM_JUMP_SLOT
) {
983 /* if we build a DLL, we add a %ebx offset */
984 if (s1
->output_type
== TCC_OUTPUT_DLL
)
985 error("DLLs unimplemented!");
987 /* add a PLT entry */
989 if (plt
->data_offset
== 0) {
990 /* first plt entry */
991 p
= section_ptr_add(plt
, 16);
992 put32(p
, 0xe52de004);
993 put32(p
+ 4, 0xe59fe010);
994 put32(p
+ 8, 0xe08fe00e);
995 put32(p
+ 12, 0xe5bef008);
998 p
= section_ptr_add(plt
, 16);
999 put32(p
, 0xe59fc004);
1000 put32(p
+4, 0xe08fc00c);
1001 put32(p
+8, 0xe59cf000);
1002 put32(p
+12, s1
->got
->data_offset
);
1004 /* the symbol is modified so that it will be relocated to
1006 if (s1
->output_type
== TCC_OUTPUT_EXE
)
1007 offset
= plt
->data_offset
- 16;
1009 #elif defined(TCC_TARGET_C67)
1010 error("C67 got not implemented");
1012 #error unsupported CPU
1014 index
= put_elf_sym(s1
->dynsym
, offset
,
1015 size
, info
, 0, sym
->st_shndx
, name
);
1016 /* put a got entry */
1017 put_elf_reloc(s1
->dynsym
, s1
->got
,
1018 s1
->got
->data_offset
,
1021 ptr
= section_ptr_add(s1
->got
, PTR_SIZE
);
1025 /* build GOT and PLT entries */
1026 ST_FUNC
void build_got_entries(TCCState
*s1
)
1028 Section
*s
, *symtab
;
1029 ElfW_Rel
*rel
, *rel_end
;
1031 int i
, type
, reloc_type
, sym_index
;
1033 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1034 s
= s1
->sections
[i
];
1035 if (s
->sh_type
!= SHT_RELX
)
1037 /* no need to handle got relocations */
1038 if (s
->link
!= symtab_section
)
1041 rel_end
= (ElfW_Rel
*)(s
->data
+ s
->data_offset
);
1042 for(rel
= (ElfW_Rel
*)s
->data
;
1045 type
= ELFW(R_TYPE
)(rel
->r_info
);
1047 #if defined(TCC_TARGET_I386)
1054 if (type
== R_386_GOT32
|| type
== R_386_PLT32
) {
1055 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1056 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1057 /* look at the symbol got offset. If none, then add one */
1058 if (type
== R_386_GOT32
)
1059 reloc_type
= R_386_GLOB_DAT
;
1061 reloc_type
= R_386_JMP_SLOT
;
1062 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1066 #elif defined(TCC_TARGET_ARM)
1067 case R_ARM_GOT_BREL
:
1068 case R_ARM_GOTOFF32
:
1069 case R_ARM_BASE_PREL
:
1073 if (type
== R_ARM_GOT_BREL
|| type
== R_ARM_PLT32
) {
1074 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1075 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1076 /* look at the symbol got offset. If none, then add one */
1077 if (type
== R_ARM_GOT_BREL
)
1078 reloc_type
= R_ARM_GLOB_DAT
;
1080 reloc_type
= R_ARM_JUMP_SLOT
;
1081 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1085 #elif defined(TCC_TARGET_C67)
1092 if (type
== R_C60_GOT32
|| type
== R_C60_PLT32
) {
1093 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1094 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1095 /* look at the symbol got offset. If none, then add one */
1096 if (type
== R_C60_GOT32
)
1097 reloc_type
= R_C60_GLOB_DAT
;
1099 reloc_type
= R_C60_JMP_SLOT
;
1100 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1104 #elif defined(TCC_TARGET_X86_64)
1105 case R_X86_64_GOT32
:
1106 case R_X86_64_GOTTPOFF
:
1107 case R_X86_64_GOTPCREL
:
1108 case R_X86_64_PLT32
:
1111 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
||
1112 type
== R_X86_64_PLT32
) {
1113 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1114 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1115 /* look at the symbol got offset. If none, then add one */
1116 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
)
1117 reloc_type
= R_X86_64_GLOB_DAT
;
1119 reloc_type
= R_X86_64_JUMP_SLOT
;
1120 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1125 #error unsupported CPU
1134 ST_FUNC Section
*new_symtab(TCCState
*s1
,
1135 const char *symtab_name
, int sh_type
, int sh_flags
,
1136 const char *strtab_name
,
1137 const char *hash_name
, int hash_sh_flags
)
1139 Section
*symtab
, *strtab
, *hash
;
1140 int *ptr
, nb_buckets
;
1142 symtab
= new_section(s1
, symtab_name
, sh_type
, sh_flags
);
1143 symtab
->sh_entsize
= sizeof(ElfW(Sym
));
1144 strtab
= new_section(s1
, strtab_name
, SHT_STRTAB
, sh_flags
);
1145 put_elf_str(strtab
, "");
1146 symtab
->link
= strtab
;
1147 put_elf_sym(symtab
, 0, 0, 0, 0, 0, NULL
);
1151 hash
= new_section(s1
, hash_name
, SHT_HASH
, hash_sh_flags
);
1152 hash
->sh_entsize
= sizeof(int);
1153 symtab
->hash
= hash
;
1154 hash
->link
= symtab
;
1156 ptr
= section_ptr_add(hash
, (2 + nb_buckets
+ 1) * sizeof(int));
1157 ptr
[0] = nb_buckets
;
1159 memset(ptr
+ 2, 0, (nb_buckets
+ 1) * sizeof(int));
1163 /* put dynamic tag */
1164 static void put_dt(Section
*dynamic
, int dt
, unsigned long val
)
1167 dyn
= section_ptr_add(dynamic
, sizeof(ElfW(Dyn
)));
1169 dyn
->d_un
.d_val
= val
;
1172 static void add_init_array_defines(TCCState
*s1
, const char *section_name
)
1176 char sym_start
[1024];
1179 snprintf(sym_start
, sizeof(sym_start
), "__%s_start", section_name
+ 1);
1180 snprintf(sym_end
, sizeof(sym_end
), "__%s_end", section_name
+ 1);
1182 s
= find_section(s1
, section_name
);
1187 end_offset
= s
->data_offset
;
1190 add_elf_sym(symtab_section
,
1192 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1193 s
->sh_num
, sym_start
);
1194 add_elf_sym(symtab_section
,
1196 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1197 s
->sh_num
, sym_end
);
1200 ST_FUNC
void tcc_add_bcheck(TCCState
*s1
)
1202 #ifdef CONFIG_TCC_BCHECK
1204 Section
*init_section
;
1205 unsigned char *pinit
;
1208 if (0 == s1
->do_bounds_check
)
1211 /* XXX: add an object file to do that */
1212 ptr
= section_ptr_add(bounds_section
, sizeof(unsigned long));
1214 add_elf_sym(symtab_section
, 0, 0,
1215 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1216 bounds_section
->sh_num
, "__bounds_start");
1217 /* add bound check code */
1218 #ifndef TCC_TARGET_PE
1221 snprintf(buf
, sizeof(buf
), "%s/%s", s1
->tcc_lib_path
, "bcheck.o");
1222 tcc_add_file(s1
, buf
);
1225 #ifdef TCC_TARGET_I386
1226 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
) {
1227 /* add 'call __bound_init()' in .init section */
1228 init_section
= find_section(s1
, ".init");
1229 pinit
= section_ptr_add(init_section
, 5);
1231 put32(pinit
+ 1, -4);
1232 sym_index
= find_elf_sym(symtab_section
, "__bound_init");
1233 put_elf_reloc(symtab_section
, init_section
,
1234 init_section
->data_offset
- 4, R_386_PC32
, sym_index
);
1240 /* add tcc runtime libraries */
1241 ST_FUNC
void tcc_add_runtime(TCCState
*s1
)
1246 if (!s1
->nostdlib
) {
1247 #ifdef CONFIG_USE_LIBGCC
1248 tcc_add_library(s1
, "c");
1249 tcc_add_file(s1
, CONFIG_SYSROOT
"/lib/libgcc_s.so.1");
1251 tcc_add_library(s1
, "c");
1252 #ifndef WITHOUT_LIBTCC
1255 snprintf(buf
, sizeof(buf
), "%s/%s", s1
->tcc_lib_path
, "libtcc1.a");
1256 tcc_add_file(s1
, buf
);
1261 /* add crt end if not memory output */
1262 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
&& !s1
->nostdlib
) {
1263 tcc_add_file(s1
, CONFIG_TCC_CRT_PREFIX
"/crtn.o");
1267 /* add various standard linker symbols (must be done after the
1268 sections are filled (for example after allocating common
1270 ST_FUNC
void tcc_add_linker_symbols(TCCState
*s1
)
1276 add_elf_sym(symtab_section
,
1277 text_section
->data_offset
, 0,
1278 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1279 text_section
->sh_num
, "_etext");
1280 add_elf_sym(symtab_section
,
1281 data_section
->data_offset
, 0,
1282 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1283 data_section
->sh_num
, "_edata");
1284 add_elf_sym(symtab_section
,
1285 bss_section
->data_offset
, 0,
1286 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1287 bss_section
->sh_num
, "_end");
1288 /* horrible new standard ldscript defines */
1289 add_init_array_defines(s1
, ".preinit_array");
1290 add_init_array_defines(s1
, ".init_array");
1291 add_init_array_defines(s1
, ".fini_array");
1293 /* add start and stop symbols for sections whose name can be
1295 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1296 s
= s1
->sections
[i
];
1297 if (s
->sh_type
== SHT_PROGBITS
&&
1298 (s
->sh_flags
& SHF_ALLOC
)) {
1302 /* check if section name can be expressed in C */
1308 if (!isid(ch
) && !isnum(ch
))
1312 snprintf(buf
, sizeof(buf
), "__start_%s", s
->name
);
1313 add_elf_sym(symtab_section
,
1315 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1317 snprintf(buf
, sizeof(buf
), "__stop_%s", s
->name
);
1318 add_elf_sym(symtab_section
,
1320 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1327 /* name of ELF interpreter */
1328 #if defined __FreeBSD__
1329 static const char elf_interp
[] = "/libexec/ld-elf.so.1";
1330 #elif defined TCC_ARM_EABI
1331 static const char elf_interp
[] = "/lib/ld-linux.so.3";
1332 #elif defined(TCC_TARGET_X86_64)
1333 # if defined(TCC_TARGET_X86_64_CENTOS)
1334 static const char elf_interp
[] = "/lib64/ld-linux-x86-64.so.2";
1336 static const char elf_interp
[] = "/lib/ld-linux-x86-64.so.2";
1337 # endif /* TCC_TARGET_X86_64_CENTOS */
1338 #elif defined(TCC_UCLIBC)
1339 static const char elf_interp
[] = "/lib/ld-uClibc.so.0";
1341 static const char elf_interp
[] = "/lib/ld-linux.so.2";
1344 static void tcc_output_binary(TCCState
*s1
, FILE *f
,
1345 const int *section_order
)
1348 int i
, offset
, size
;
1351 for(i
=1;i
<s1
->nb_sections
;i
++) {
1352 s
= s1
->sections
[section_order
[i
]];
1353 if (s
->sh_type
!= SHT_NOBITS
&&
1354 (s
->sh_flags
& SHF_ALLOC
)) {
1355 while (offset
< s
->sh_offset
) {
1360 fwrite(s
->data
, 1, size
, f
);
1366 #if defined(__FreeBSD__)
1368 #define EXTRA_RELITEMS 14
1370 /* move the relocation value from .dynsym to .got */
1371 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1373 uint32_t *gotd
= (void *)s1
->got
->data
;
1374 ElfW(Sym
) *sym
, *sym_end
;
1376 gotd
+= 3; // dummy entries in .got
1377 /* relocate symbols in .dynsym */
1378 sym_end
= (ElfW(Sym
) *)(s
->data
+ s
->data_offset
);
1379 for (sym
= (ElfW(Sym
) *)s
->data
+ 1; sym
< sym_end
; sym
++) {
1380 if (sym
->st_shndx
== SHN_UNDEF
) {
1381 *gotd
++ = sym
->st_value
+ 6; // XXX 6 is magic ?
1388 #define EXTRA_RELITEMS 9
1391 ST_FUNC
void fill_got_entry(TCCState
*s1
, ElfW_Rel
*rel
)
1393 int sym_index
= ELFW(R_SYM
) (rel
->r_info
);
1394 ElfW(Sym
) *sym
= &((ElfW(Sym
) *) symtab_section
->data
)[sym_index
];
1395 unsigned long offset
;
1397 if (sym_index
>= s1
->nb_got_offsets
)
1399 offset
= s1
->got_offsets
[sym_index
];
1400 section_reserve(s1
->got
, offset
+ PTR_SIZE
);
1401 #ifdef TCC_TARGET_X86_64
1402 /* only works for x86-64 */
1403 put32(s1
->got
->data
+ offset
, sym
->st_value
>> 32);
1405 put32(s1
->got
->data
+ offset
, sym
->st_value
& 0xffffffff);
1408 ST_FUNC
void fill_got(TCCState
*s1
)
1411 ElfW_Rel
*rel
, *rel_end
;
1414 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1415 s
= s1
->sections
[i
];
1416 if (s
->sh_type
!= SHT_RELX
)
1418 /* no need to handle got relocations */
1419 if (s
->link
!= symtab_section
)
1421 rel_end
= (ElfW_Rel
*) (s
->data
+ s
->data_offset
);
1422 for(rel
= (ElfW_Rel
*) s
->data
; rel
< rel_end
; rel
++) {
1423 switch (ELFW(R_TYPE
) (rel
->r_info
)) {
1424 case R_X86_64_GOT32
:
1425 case R_X86_64_GOTPCREL
:
1426 case R_X86_64_PLT32
:
1427 fill_got_entry(s1
, rel
);
1435 /* output an ELF file */
1436 /* XXX: suppress unneeded sections */
1437 static int elf_output_file(TCCState
*s1
, const char *filename
)
1443 int shnum
, i
, phnum
, file_offset
, offset
, size
, j
, tmp
, sh_order_index
, k
;
1445 Section
*strsec
, *s
;
1446 ElfW(Shdr
) shdr
, *sh
;
1447 ElfW(Phdr
) *phdr
, *ph
;
1448 Section
*interp
, *dynamic
, *dynstr
;
1449 unsigned long saved_dynamic_data_offset
;
1451 int type
, file_type
;
1452 unsigned long rel_addr
, rel_size
;
1453 unsigned long bss_addr
, bss_size
;
1455 file_type
= s1
->output_type
;
1458 if (file_type
!= TCC_OUTPUT_OBJ
) {
1459 tcc_add_runtime(s1
);
1463 section_order
= NULL
;
1466 dynstr
= NULL
; /* avoid warning */
1467 saved_dynamic_data_offset
= 0; /* avoid warning */
1469 if (file_type
!= TCC_OUTPUT_OBJ
) {
1470 relocate_common_syms();
1472 tcc_add_linker_symbols(s1
);
1474 if (!s1
->static_link
) {
1476 int sym_index
, index
;
1477 ElfW(Sym
) *esym
, *sym_end
;
1479 if (file_type
== TCC_OUTPUT_EXE
) {
1481 /* allow override the dynamic loader */
1482 const char *elfint
= getenv("LD_SO");
1484 elfint
= elf_interp
;
1485 /* add interpreter section only if executable */
1486 interp
= new_section(s1
, ".interp", SHT_PROGBITS
, SHF_ALLOC
);
1487 interp
->sh_addralign
= 1;
1488 ptr
= section_ptr_add(interp
, 1+strlen(elfint
));
1489 strcpy(ptr
, elfint
);
1492 /* add dynamic symbol table */
1493 s1
->dynsym
= new_symtab(s1
, ".dynsym", SHT_DYNSYM
, SHF_ALLOC
,
1495 ".hash", SHF_ALLOC
);
1496 dynstr
= s1
->dynsym
->link
;
1498 /* add dynamic section */
1499 dynamic
= new_section(s1
, ".dynamic", SHT_DYNAMIC
,
1500 SHF_ALLOC
| SHF_WRITE
);
1501 dynamic
->link
= dynstr
;
1502 dynamic
->sh_entsize
= sizeof(ElfW(Dyn
));
1505 s1
->plt
= new_section(s1
, ".plt", SHT_PROGBITS
,
1506 SHF_ALLOC
| SHF_EXECINSTR
);
1507 s1
->plt
->sh_entsize
= 4;
1511 /* scan for undefined symbols and see if they are in the
1512 dynamic symbols. If a symbol STT_FUNC is found, then we
1513 add it in the PLT. If a symbol STT_OBJECT is found, we
1514 add it in the .bss section with a suitable relocation */
1515 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+
1516 symtab_section
->data_offset
);
1517 if (file_type
== TCC_OUTPUT_EXE
) {
1518 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
1521 if (sym
->st_shndx
== SHN_UNDEF
) {
1522 name
= symtab_section
->link
->data
+ sym
->st_name
;
1523 sym_index
= find_elf_sym(s1
->dynsymtab_section
, name
);
1525 esym
= &((ElfW(Sym
) *)s1
->dynsymtab_section
->data
)[sym_index
];
1526 type
= ELFW(ST_TYPE
)(esym
->st_info
);
1527 if (type
== STT_FUNC
) {
1528 put_got_entry(s1
, R_JMP_SLOT
, esym
->st_size
,
1530 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1531 } else if (type
== STT_OBJECT
) {
1532 unsigned long offset
;
1533 ElfW(Sym
) *dynsym
, *dynsym_end
;
1534 offset
= bss_section
->data_offset
;
1535 /* XXX: which alignment ? */
1536 offset
= (offset
+ 16 - 1) & -16;
1537 index
= put_elf_sym(s1
->dynsym
, offset
, esym
->st_size
,
1539 bss_section
->sh_num
, name
);
1540 /* Ensure symbol aliases (that is, symbols with
1541 the same st_value) resolve to the same
1542 address in program .bss or .data section. */
1543 dynsym_end
= (ElfW(Sym
) *)
1544 (s1
->dynsymtab_section
->data
+
1545 s1
->dynsymtab_section
->data_offset
);
1546 for(dynsym
= (ElfW(Sym
) *)s1
->dynsymtab_section
->data
+ 1;
1547 dynsym
< dynsym_end
; dynsym
++) {
1548 if (dynsym
->st_value
== esym
->st_value
) {
1550 dynname
= s1
->dynsymtab_section
->link
->data
1552 put_elf_sym(s1
->dynsym
, offset
,
1555 bss_section
->sh_num
,
1559 put_elf_reloc(s1
->dynsym
, bss_section
,
1560 offset
, R_COPY
, index
);
1561 offset
+= esym
->st_size
;
1562 bss_section
->data_offset
= offset
;
1565 /* STB_WEAK undefined symbols are accepted */
1566 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1568 if (ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
||
1569 !strcmp(name
, "_fp_hw")) {
1571 error_noabort("undefined symbol '%s'", name
);
1574 } else if (s1
->rdynamic
&&
1575 ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1576 /* if -rdynamic option, then export all non
1578 name
= symtab_section
->link
->data
+ sym
->st_name
;
1579 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1581 sym
->st_shndx
, name
);
1588 /* now look at unresolved dynamic symbols and export
1589 corresponding symbol */
1590 sym_end
= (ElfW(Sym
) *)(s1
->dynsymtab_section
->data
+
1591 s1
->dynsymtab_section
->data_offset
);
1592 for(esym
= (ElfW(Sym
) *)s1
->dynsymtab_section
->data
+ 1;
1595 if (esym
->st_shndx
== SHN_UNDEF
) {
1596 name
= s1
->dynsymtab_section
->link
->data
+ esym
->st_name
;
1597 sym_index
= find_elf_sym(symtab_section
, name
);
1599 /* XXX: avoid adding a symbol if already
1600 present because of -rdynamic ? */
1601 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1602 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1604 sym
->st_shndx
, name
);
1606 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1607 /* weak symbols can stay undefined */
1609 warning("undefined dynamic symbol '%s'", name
);
1616 /* shared library case : we simply export all the global symbols */
1617 nb_syms
= symtab_section
->data_offset
/ sizeof(ElfW(Sym
));
1618 s1
->symtab_to_dynsym
= tcc_mallocz(sizeof(int) * nb_syms
);
1619 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
1622 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1623 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1624 if (ELFW(ST_TYPE
)(sym
->st_info
) == STT_FUNC
&&
1625 sym
->st_shndx
== SHN_UNDEF
) {
1626 put_got_entry(s1
, R_JMP_SLOT
, sym
->st_size
,
1628 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1630 else if (ELFW(ST_TYPE
)(sym
->st_info
) == STT_OBJECT
) {
1631 put_got_entry(s1
, R_X86_64_GLOB_DAT
, sym
->st_size
,
1633 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1638 name
= symtab_section
->link
->data
+ sym
->st_name
;
1639 index
= put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1641 sym
->st_shndx
, name
);
1642 s1
->symtab_to_dynsym
[sym
-
1643 (ElfW(Sym
) *)symtab_section
->data
] =
1650 build_got_entries(s1
);
1652 /* add a list of needed dlls */
1653 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
1654 DLLReference
*dllref
= s1
->loaded_dlls
[i
];
1655 if (dllref
->level
== 0)
1656 put_dt(dynamic
, DT_NEEDED
, put_elf_str(dynstr
, dllref
->name
));
1660 put_dt(dynamic
, DT_RPATH
, put_elf_str(dynstr
, s1
->rpath
));
1662 /* XXX: currently, since we do not handle PIC code, we
1663 must relocate the readonly segments */
1664 if (file_type
== TCC_OUTPUT_DLL
) {
1666 put_dt(dynamic
, DT_SONAME
, put_elf_str(dynstr
, s1
->soname
));
1667 put_dt(dynamic
, DT_TEXTREL
, 0);
1671 put_dt(dynamic
, DT_SYMBOLIC
, 0);
1673 /* add necessary space for other entries */
1674 saved_dynamic_data_offset
= dynamic
->data_offset
;
1675 dynamic
->data_offset
+= sizeof(ElfW(Dyn
)) * EXTRA_RELITEMS
;
1677 /* still need to build got entries in case of static link */
1678 build_got_entries(s1
);
1682 memset(&ehdr
, 0, sizeof(ehdr
));
1684 /* we add a section for symbols */
1685 strsec
= new_section(s1
, ".shstrtab", SHT_STRTAB
, 0);
1686 put_elf_str(strsec
, "");
1688 /* compute number of sections */
1689 shnum
= s1
->nb_sections
;
1691 /* this array is used to reorder sections in the output file */
1692 section_order
= tcc_malloc(sizeof(int) * shnum
);
1693 section_order
[0] = 0;
1696 /* compute number of program headers */
1699 case TCC_OUTPUT_OBJ
:
1702 case TCC_OUTPUT_EXE
:
1703 if (!s1
->static_link
)
1704 phnum
= 4 + HAVE_PHDR
;
1708 case TCC_OUTPUT_DLL
:
1713 /* allocate strings for section names and decide if an unallocated
1714 section should be output */
1715 /* NOTE: the strsec section comes last, so its size is also
1717 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1718 s
= s1
->sections
[i
];
1719 s
->sh_name
= put_elf_str(strsec
, s
->name
);
1721 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1726 s
->reloc
? s
->reloc
->name
: "n"
1729 /* when generating a DLL, we include relocations but we may
1731 if (file_type
== TCC_OUTPUT_DLL
&&
1732 s
->sh_type
== SHT_RELX
&&
1733 !(s
->sh_flags
& SHF_ALLOC
)) {
1734 /* //gr: avoid bogus relocs for empty (debug) sections */
1735 if (s1
->sections
[s
->sh_info
]->sh_flags
& SHF_ALLOC
)
1736 prepare_dynamic_rel(s1
, s
);
1737 else if (s1
->do_debug
)
1738 s
->sh_size
= s
->data_offset
;
1739 } else if (s1
->do_debug
||
1740 file_type
== TCC_OUTPUT_OBJ
||
1741 (s
->sh_flags
& SHF_ALLOC
) ||
1742 i
== (s1
->nb_sections
- 1)) {
1743 /* we output all sections if debug or object file */
1744 s
->sh_size
= s
->data_offset
;
1748 /* allocate program segment headers */
1749 phdr
= tcc_mallocz(phnum
* sizeof(ElfW(Phdr
)));
1751 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1752 file_offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
1757 /* compute section to program header mapping */
1758 if (s1
->has_text_addr
) {
1759 int a_offset
, p_offset
;
1760 addr
= s1
->text_addr
;
1761 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1763 a_offset
= addr
& (s1
->section_align
- 1);
1764 p_offset
= file_offset
& (s1
->section_align
- 1);
1765 if (a_offset
< p_offset
)
1766 a_offset
+= s1
->section_align
;
1767 file_offset
+= (a_offset
- p_offset
);
1769 if (file_type
== TCC_OUTPUT_DLL
)
1772 addr
= ELF_START_ADDR
;
1773 /* compute address after headers */
1774 addr
+= (file_offset
& (s1
->section_align
- 1));
1777 /* dynamic relocation table information, for .dynamic section */
1781 bss_addr
= bss_size
= 0;
1782 /* leave one program header for the program interpreter */
1785 ph
+= 1 + HAVE_PHDR
;
1787 for(j
= 0; j
< 2; j
++) {
1788 ph
->p_type
= PT_LOAD
;
1790 ph
->p_flags
= PF_R
| PF_X
;
1792 ph
->p_flags
= PF_R
| PF_W
;
1793 ph
->p_align
= s1
->section_align
;
1795 /* we do the following ordering: interp, symbol tables,
1796 relocations, progbits, nobits */
1797 /* XXX: do faster and simpler sorting */
1798 for(k
= 0; k
< 5; k
++) {
1799 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1800 s
= s1
->sections
[i
];
1801 /* compute if section should be included */
1803 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1807 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1808 (SHF_ALLOC
| SHF_WRITE
))
1814 } else if (s
->sh_type
== SHT_DYNSYM
||
1815 s
->sh_type
== SHT_STRTAB
||
1816 s
->sh_type
== SHT_HASH
) {
1819 } else if (s
->sh_type
== SHT_RELX
) {
1822 } else if (s
->sh_type
== SHT_NOBITS
) {
1829 section_order
[sh_order_index
++] = i
;
1831 /* section matches: we align it and add its size */
1833 addr
= (addr
+ s
->sh_addralign
- 1) &
1834 ~(s
->sh_addralign
- 1);
1835 file_offset
+= addr
- tmp
;
1836 s
->sh_offset
= file_offset
;
1839 /* update program header infos */
1840 if (ph
->p_offset
== 0) {
1841 ph
->p_offset
= file_offset
;
1843 ph
->p_paddr
= ph
->p_vaddr
;
1845 /* update dynamic relocation infos */
1846 if (s
->sh_type
== SHT_RELX
) {
1847 #if defined(__FreeBSD__)
1848 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.got")) { // rel_size == 0) {
1850 rel_size
+= s
->sh_size
; // XXX only first rel.
1852 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.bss")) { // rel_size == 0) {
1854 bss_size
= s
->sh_size
; // XXX only first rel.
1859 rel_size
+= s
->sh_size
;
1863 if (s
->sh_type
!= SHT_NOBITS
)
1864 file_offset
+= s
->sh_size
;
1867 ph
->p_filesz
= file_offset
- ph
->p_offset
;
1868 ph
->p_memsz
= addr
- ph
->p_vaddr
;
1871 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1872 /* if in the middle of a page, we duplicate the page in
1873 memory so that one copy is RX and the other is RW */
1874 if ((addr
& (s1
->section_align
- 1)) != 0)
1875 addr
+= s1
->section_align
;
1877 addr
= (addr
+ s1
->section_align
- 1) & ~(s1
->section_align
- 1);
1878 file_offset
= (file_offset
+ s1
->section_align
- 1) &
1879 ~(s1
->section_align
- 1);
1884 /* if interpreter, then add corresponing program header */
1888 #if defined(__FreeBSD__)
1890 int len
= phnum
* sizeof(ElfW(Phdr
));
1892 ph
->p_type
= PT_PHDR
;
1893 ph
->p_offset
= sizeof(ElfW(Ehdr
));
1894 ph
->p_vaddr
= interp
->sh_addr
- len
;
1895 ph
->p_paddr
= ph
->p_vaddr
;
1896 ph
->p_filesz
= ph
->p_memsz
= len
;
1897 ph
->p_flags
= PF_R
| PF_X
;
1898 ph
->p_align
= 4; // interp->sh_addralign;
1903 ph
->p_type
= PT_INTERP
;
1904 ph
->p_offset
= interp
->sh_offset
;
1905 ph
->p_vaddr
= interp
->sh_addr
;
1906 ph
->p_paddr
= ph
->p_vaddr
;
1907 ph
->p_filesz
= interp
->sh_size
;
1908 ph
->p_memsz
= interp
->sh_size
;
1910 ph
->p_align
= interp
->sh_addralign
;
1913 /* if dynamic section, then add corresponing program header */
1917 ph
= &phdr
[phnum
- 1];
1919 ph
->p_type
= PT_DYNAMIC
;
1920 ph
->p_offset
= dynamic
->sh_offset
;
1921 ph
->p_vaddr
= dynamic
->sh_addr
;
1922 ph
->p_paddr
= ph
->p_vaddr
;
1923 ph
->p_filesz
= dynamic
->sh_size
;
1924 ph
->p_memsz
= dynamic
->sh_size
;
1925 ph
->p_flags
= PF_R
| PF_W
;
1926 ph
->p_align
= dynamic
->sh_addralign
;
1928 /* put GOT dynamic section address */
1929 put32(s1
->got
->data
, dynamic
->sh_addr
);
1931 /* relocate the PLT */
1932 if (file_type
== TCC_OUTPUT_EXE
1933 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1934 || file_type
== TCC_OUTPUT_DLL
1940 p_end
= p
+ s1
->plt
->data_offset
;
1942 #if defined(TCC_TARGET_I386)
1943 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
1944 put32(p
+ 8, get32(p
+ 8) + s1
->got
->sh_addr
);
1947 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
1950 #elif defined(TCC_TARGET_X86_64)
1951 int x
= s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 6;
1952 put32(p
+ 2, get32(p
+ 2) + x
);
1953 put32(p
+ 8, get32(p
+ 8) + x
- 6);
1956 put32(p
+ 2, get32(p
+ 2) + x
+ s1
->plt
->data
- p
);
1959 #elif defined(TCC_TARGET_ARM)
1961 x
=s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 12;
1964 put32(p
+ 12, x
+ get32(p
+ 12) + s1
->plt
->data
- p
);
1967 #elif defined(TCC_TARGET_C67)
1970 #error unsupported CPU
1975 /* relocate symbols in .dynsym */
1976 sym_end
= (ElfW(Sym
) *)(s1
->dynsym
->data
+ s1
->dynsym
->data_offset
);
1977 for(sym
= (ElfW(Sym
) *)s1
->dynsym
->data
+ 1;
1980 if (sym
->st_shndx
== SHN_UNDEF
) {
1981 /* relocate to the PLT if the symbol corresponds
1984 sym
->st_value
+= s1
->plt
->sh_addr
;
1985 } else if (sym
->st_shndx
< SHN_LORESERVE
) {
1986 /* do symbol relocation */
1987 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
1991 /* put dynamic section entries */
1992 dynamic
->data_offset
= saved_dynamic_data_offset
;
1993 put_dt(dynamic
, DT_HASH
, s1
->dynsym
->hash
->sh_addr
);
1994 put_dt(dynamic
, DT_STRTAB
, dynstr
->sh_addr
);
1995 put_dt(dynamic
, DT_SYMTAB
, s1
->dynsym
->sh_addr
);
1996 put_dt(dynamic
, DT_STRSZ
, dynstr
->data_offset
);
1997 put_dt(dynamic
, DT_SYMENT
, sizeof(ElfW(Sym
)));
1998 #ifdef TCC_TARGET_X86_64
1999 put_dt(dynamic
, DT_RELA
, rel_addr
);
2000 put_dt(dynamic
, DT_RELASZ
, rel_size
);
2001 put_dt(dynamic
, DT_RELAENT
, sizeof(ElfW_Rel
));
2003 #if defined(__FreeBSD__)
2004 put_dt(dynamic
, DT_PLTGOT
, s1
->got
->sh_addr
);
2005 put_dt(dynamic
, DT_PLTRELSZ
, rel_size
);
2006 put_dt(dynamic
, DT_JMPREL
, rel_addr
);
2007 put_dt(dynamic
, DT_PLTREL
, DT_REL
);
2008 put_dt(dynamic
, DT_REL
, bss_addr
);
2009 put_dt(dynamic
, DT_RELSZ
, bss_size
);
2011 put_dt(dynamic
, DT_REL
, rel_addr
);
2012 put_dt(dynamic
, DT_RELSZ
, rel_size
);
2013 put_dt(dynamic
, DT_RELENT
, sizeof(ElfW_Rel
));
2017 put_dt(dynamic
, DT_DEBUG
, 0);
2018 put_dt(dynamic
, DT_NULL
, 0);
2021 ehdr
.e_phentsize
= sizeof(ElfW(Phdr
));
2022 ehdr
.e_phnum
= phnum
;
2023 ehdr
.e_phoff
= sizeof(ElfW(Ehdr
));
2026 /* all other sections come after */
2027 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2028 s
= s1
->sections
[i
];
2029 if (phnum
> 0 && (s
->sh_flags
& SHF_ALLOC
))
2031 section_order
[sh_order_index
++] = i
;
2033 file_offset
= (file_offset
+ s
->sh_addralign
- 1) &
2034 ~(s
->sh_addralign
- 1);
2035 s
->sh_offset
= file_offset
;
2036 if (s
->sh_type
!= SHT_NOBITS
)
2037 file_offset
+= s
->sh_size
;
2040 /* if building executable or DLL, then relocate each section
2041 except the GOT which is already relocated */
2042 if (file_type
!= TCC_OUTPUT_OBJ
) {
2043 relocate_syms(s1
, 0);
2045 if (s1
->nb_errors
!= 0) {
2051 /* relocate sections */
2052 /* XXX: ignore sections with allocated relocations ? */
2053 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2054 s
= s1
->sections
[i
];
2055 if (s
->reloc
&& s
!= s1
->got
&& (s
->sh_flags
& SHF_ALLOC
)) //gr
2056 relocate_section(s1
, s
);
2059 /* relocate relocation entries if the relocation tables are
2060 allocated in the executable */
2061 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2062 s
= s1
->sections
[i
];
2063 if ((s
->sh_flags
& SHF_ALLOC
) &&
2064 s
->sh_type
== SHT_RELX
) {
2065 relocate_rel(s1
, s
);
2069 /* get entry point address */
2070 if (file_type
== TCC_OUTPUT_EXE
)
2071 ehdr
.e_entry
= (uplong
)tcc_get_symbol_err(s1
, "_start");
2073 ehdr
.e_entry
= text_section
->sh_addr
; /* XXX: is it correct ? */
2075 if (file_type
== TCC_OUTPUT_EXE
&& s1
->static_link
)
2078 /* write elf file */
2079 if (file_type
== TCC_OUTPUT_OBJ
)
2083 fd
= open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
, mode
);
2085 error_noabort("could not write '%s'", filename
);
2088 f
= fdopen(fd
, "wb");
2090 printf("<- %s\n", filename
);
2092 #ifdef TCC_TARGET_COFF
2093 if (s1
->output_format
== TCC_OUTPUT_FORMAT_COFF
) {
2094 tcc_output_coff(s1
, f
);
2097 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
2098 sort_syms(s1
, symtab_section
);
2101 file_offset
= (file_offset
+ 3) & -4;
2104 ehdr
.e_ident
[0] = ELFMAG0
;
2105 ehdr
.e_ident
[1] = ELFMAG1
;
2106 ehdr
.e_ident
[2] = ELFMAG2
;
2107 ehdr
.e_ident
[3] = ELFMAG3
;
2108 ehdr
.e_ident
[4] = TCC_ELFCLASS
;
2109 ehdr
.e_ident
[5] = ELFDATA2LSB
;
2110 ehdr
.e_ident
[6] = EV_CURRENT
;
2112 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_FREEBSD
;
2114 #ifdef TCC_TARGET_ARM
2116 ehdr
.e_ident
[EI_OSABI
] = 0;
2117 ehdr
.e_flags
= 4 << 24;
2119 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_ARM
;
2124 case TCC_OUTPUT_EXE
:
2125 ehdr
.e_type
= ET_EXEC
;
2127 case TCC_OUTPUT_DLL
:
2128 ehdr
.e_type
= ET_DYN
;
2130 case TCC_OUTPUT_OBJ
:
2131 ehdr
.e_type
= ET_REL
;
2134 ehdr
.e_machine
= EM_TCC_TARGET
;
2135 ehdr
.e_version
= EV_CURRENT
;
2136 ehdr
.e_shoff
= file_offset
;
2137 ehdr
.e_ehsize
= sizeof(ElfW(Ehdr
));
2138 ehdr
.e_shentsize
= sizeof(ElfW(Shdr
));
2139 ehdr
.e_shnum
= shnum
;
2140 ehdr
.e_shstrndx
= shnum
- 1;
2142 fwrite(&ehdr
, 1, sizeof(ElfW(Ehdr
)), f
);
2143 fwrite(phdr
, 1, phnum
* sizeof(ElfW(Phdr
)), f
);
2144 offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
2146 for(i
=1;i
<s1
->nb_sections
;i
++) {
2147 s
= s1
->sections
[section_order
[i
]];
2148 if (s
->sh_type
!= SHT_NOBITS
) {
2149 #if defined(__FreeBSD__)
2150 if (s
->sh_type
== SHT_DYNSYM
)
2151 patch_dynsym_undef(s1
, s
);
2153 while (offset
< s
->sh_offset
) {
2158 fwrite(s
->data
, 1, size
, f
);
2163 /* output section headers */
2164 while (offset
< ehdr
.e_shoff
) {
2169 for(i
=0;i
<s1
->nb_sections
;i
++) {
2171 memset(sh
, 0, sizeof(ElfW(Shdr
)));
2172 s
= s1
->sections
[i
];
2174 sh
->sh_name
= s
->sh_name
;
2175 sh
->sh_type
= s
->sh_type
;
2176 sh
->sh_flags
= s
->sh_flags
;
2177 sh
->sh_entsize
= s
->sh_entsize
;
2178 sh
->sh_info
= s
->sh_info
;
2180 sh
->sh_link
= s
->link
->sh_num
;
2181 sh
->sh_addralign
= s
->sh_addralign
;
2182 sh
->sh_addr
= s
->sh_addr
;
2183 sh
->sh_offset
= s
->sh_offset
;
2184 sh
->sh_size
= s
->sh_size
;
2186 fwrite(sh
, 1, sizeof(ElfW(Shdr
)), f
);
2189 tcc_output_binary(s1
, f
, section_order
);
2195 tcc_free(s1
->symtab_to_dynsym
);
2196 tcc_free(section_order
);
2198 tcc_free(s1
->got_offsets
);
2202 LIBTCCAPI
int tcc_output_file(TCCState
*s
, const char *filename
)
2205 #ifdef TCC_TARGET_PE
2206 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
2207 ret
= pe_output_file(s
, filename
);
2211 ret
= elf_output_file(s
, filename
);
2216 static void *load_data(int fd
, unsigned long file_offset
, unsigned long size
)
2220 data
= tcc_malloc(size
);
2221 lseek(fd
, file_offset
, SEEK_SET
);
2222 read(fd
, data
, size
);
2226 typedef struct SectionMergeInfo
{
2227 Section
*s
; /* corresponding existing section */
2228 unsigned long offset
; /* offset of the new section in the existing section */
2229 uint8_t new_section
; /* true if section 's' was added */
2230 uint8_t link_once
; /* true if link once section */
2233 /* load an object file and merge it with current files */
2234 /* XXX: handle correctly stab (debug) info */
2235 ST_FUNC
int tcc_load_object_file(TCCState
*s1
,
2236 int fd
, unsigned long file_offset
)
2239 ElfW(Shdr
) *shdr
, *sh
;
2240 int size
, i
, j
, offset
, offseti
, nb_syms
, sym_index
, ret
;
2241 unsigned char *strsec
, *strtab
;
2242 int *old_to_new_syms
;
2243 char *sh_name
, *name
;
2244 SectionMergeInfo
*sm_table
, *sm
;
2245 ElfW(Sym
) *sym
, *symtab
;
2246 ElfW_Rel
*rel
, *rel_end
;
2252 stab_index
= stabstr_index
= 0;
2254 if (read(fd
, &ehdr
, sizeof(ehdr
)) != sizeof(ehdr
))
2256 if (ehdr
.e_ident
[0] != ELFMAG0
||
2257 ehdr
.e_ident
[1] != ELFMAG1
||
2258 ehdr
.e_ident
[2] != ELFMAG2
||
2259 ehdr
.e_ident
[3] != ELFMAG3
)
2261 /* test if object file */
2262 if (ehdr
.e_type
!= ET_REL
)
2264 /* test CPU specific stuff */
2265 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2266 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2268 error_noabort("invalid object file");
2272 shdr
= load_data(fd
, file_offset
+ ehdr
.e_shoff
,
2273 sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2274 sm_table
= tcc_mallocz(sizeof(SectionMergeInfo
) * ehdr
.e_shnum
);
2276 /* load section names */
2277 sh
= &shdr
[ehdr
.e_shstrndx
];
2278 strsec
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2280 /* load symtab and strtab */
2281 old_to_new_syms
= NULL
;
2285 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2287 if (sh
->sh_type
== SHT_SYMTAB
) {
2289 error_noabort("object must contain only one symtab");
2294 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2295 symtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2296 sm_table
[i
].s
= symtab_section
;
2298 /* now load strtab */
2299 sh
= &shdr
[sh
->sh_link
];
2300 strtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2304 /* now examine each section and try to merge its content with the
2306 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2307 /* no need to examine section name strtab */
2308 if (i
== ehdr
.e_shstrndx
)
2311 sh_name
= strsec
+ sh
->sh_name
;
2312 /* ignore sections types we do not handle */
2313 if (sh
->sh_type
!= SHT_PROGBITS
&&
2314 sh
->sh_type
!= SHT_RELX
&&
2316 sh
->sh_type
!= SHT_ARM_EXIDX
&&
2318 sh
->sh_type
!= SHT_NOBITS
&&
2319 strcmp(sh_name
, ".stabstr")
2322 if (sh
->sh_addralign
< 1)
2323 sh
->sh_addralign
= 1;
2324 /* find corresponding section, if any */
2325 for(j
= 1; j
< s1
->nb_sections
;j
++) {
2326 s
= s1
->sections
[j
];
2327 if (!strcmp(s
->name
, sh_name
)) {
2328 if (!strncmp(sh_name
, ".gnu.linkonce",
2329 sizeof(".gnu.linkonce") - 1)) {
2330 /* if a 'linkonce' section is already present, we
2331 do not add it again. It is a little tricky as
2332 symbols can still be defined in
2334 sm_table
[i
].link_once
= 1;
2341 /* not found: create new section */
2342 s
= new_section(s1
, sh_name
, sh
->sh_type
, sh
->sh_flags
);
2343 /* take as much info as possible from the section. sh_link and
2344 sh_info will be updated later */
2345 s
->sh_addralign
= sh
->sh_addralign
;
2346 s
->sh_entsize
= sh
->sh_entsize
;
2347 sm_table
[i
].new_section
= 1;
2349 if (sh
->sh_type
!= s
->sh_type
) {
2350 error_noabort("invalid section type");
2354 /* align start of section */
2355 offset
= s
->data_offset
;
2357 if (0 == strcmp(sh_name
, ".stab")) {
2361 if (0 == strcmp(sh_name
, ".stabstr")) {
2366 size
= sh
->sh_addralign
- 1;
2367 offset
= (offset
+ size
) & ~size
;
2368 if (sh
->sh_addralign
> s
->sh_addralign
)
2369 s
->sh_addralign
= sh
->sh_addralign
;
2370 s
->data_offset
= offset
;
2372 sm_table
[i
].offset
= offset
;
2374 /* concatenate sections */
2376 if (sh
->sh_type
!= SHT_NOBITS
) {
2378 lseek(fd
, file_offset
+ sh
->sh_offset
, SEEK_SET
);
2379 ptr
= section_ptr_add(s
, size
);
2380 read(fd
, ptr
, size
);
2382 s
->data_offset
+= size
;
2387 /* //gr relocate stab strings */
2388 if (stab_index
&& stabstr_index
) {
2391 s
= sm_table
[stab_index
].s
;
2392 a
= (Stab_Sym
*)(s
->data
+ sm_table
[stab_index
].offset
);
2393 b
= (Stab_Sym
*)(s
->data
+ s
->data_offset
);
2394 o
= sm_table
[stabstr_index
].offset
;
2396 a
->n_strx
+= o
, a
++;
2399 /* second short pass to update sh_link and sh_info fields of new
2401 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2403 if (!s
|| !sm_table
[i
].new_section
)
2406 if (sh
->sh_link
> 0)
2407 s
->link
= sm_table
[sh
->sh_link
].s
;
2408 if (sh
->sh_type
== SHT_RELX
) {
2409 s
->sh_info
= sm_table
[sh
->sh_info
].s
->sh_num
;
2410 /* update backward link */
2411 s1
->sections
[s
->sh_info
]->reloc
= s
;
2416 /* resolve symbols */
2417 old_to_new_syms
= tcc_mallocz(nb_syms
* sizeof(int));
2420 for(i
= 1; i
< nb_syms
; i
++, sym
++) {
2421 if (sym
->st_shndx
!= SHN_UNDEF
&&
2422 sym
->st_shndx
< SHN_LORESERVE
) {
2423 sm
= &sm_table
[sym
->st_shndx
];
2424 if (sm
->link_once
) {
2425 /* if a symbol is in a link once section, we use the
2426 already defined symbol. It is very important to get
2427 correct relocations */
2428 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
2429 name
= strtab
+ sym
->st_name
;
2430 sym_index
= find_elf_sym(symtab_section
, name
);
2432 old_to_new_syms
[i
] = sym_index
;
2436 /* if no corresponding section added, no need to add symbol */
2439 /* convert section number */
2440 sym
->st_shndx
= sm
->s
->sh_num
;
2442 sym
->st_value
+= sm
->offset
;
2445 name
= strtab
+ sym
->st_name
;
2446 sym_index
= add_elf_sym(symtab_section
, sym
->st_value
, sym
->st_size
,
2447 sym
->st_info
, sym
->st_other
,
2448 sym
->st_shndx
, name
);
2449 old_to_new_syms
[i
] = sym_index
;
2452 /* third pass to patch relocation entries */
2453 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2458 offset
= sm_table
[i
].offset
;
2459 switch(s
->sh_type
) {
2461 /* take relocation offset information */
2462 offseti
= sm_table
[sh
->sh_info
].offset
;
2463 rel_end
= (ElfW_Rel
*)(s
->data
+ s
->data_offset
);
2464 for(rel
= (ElfW_Rel
*)(s
->data
+ offset
);
2469 /* convert symbol index */
2470 type
= ELFW(R_TYPE
)(rel
->r_info
);
2471 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
2472 /* NOTE: only one symtab assumed */
2473 if (sym_index
>= nb_syms
)
2475 sym_index
= old_to_new_syms
[sym_index
];
2476 /* ignore link_once in rel section. */
2477 if (!sym_index
&& !sm
->link_once
) {
2479 error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2480 i
, strsec
+ sh
->sh_name
, rel
->r_offset
);
2483 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
2484 /* offset the relocation offset */
2485 rel
->r_offset
+= offseti
;
2497 tcc_free(old_to_new_syms
);
2504 typedef struct ArchiveHeader
{
2505 char ar_name
[16]; /* name of this member */
2506 char ar_date
[12]; /* file mtime */
2507 char ar_uid
[6]; /* owner uid; printed as decimal */
2508 char ar_gid
[6]; /* owner gid; printed as decimal */
2509 char ar_mode
[8]; /* file mode, printed as octal */
2510 char ar_size
[10]; /* file size, printed as decimal */
2511 char ar_fmag
[2]; /* should contain ARFMAG */
2514 static int get_be32(const uint8_t *b
)
2516 return b
[3] | (b
[2] << 8) | (b
[1] << 16) | (b
[0] << 24);
2519 /* load only the objects which resolve undefined symbols */
2520 static int tcc_load_alacarte(TCCState
*s1
, int fd
, int size
)
2522 int i
, bound
, nsyms
, sym_index
, off
, ret
;
2524 const char *ar_names
, *p
;
2525 const uint8_t *ar_index
;
2528 data
= tcc_malloc(size
);
2529 if (read(fd
, data
, size
) != size
)
2531 nsyms
= get_be32(data
);
2532 ar_index
= data
+ 4;
2533 ar_names
= ar_index
+ nsyms
* 4;
2537 for(p
= ar_names
, i
= 0; i
< nsyms
; i
++, p
+= strlen(p
)+1) {
2538 sym_index
= find_elf_sym(symtab_section
, p
);
2540 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
2541 if(sym
->st_shndx
== SHN_UNDEF
) {
2542 off
= get_be32(ar_index
+ i
* 4) + sizeof(ArchiveHeader
);
2544 printf("%5d\t%s\t%08x\n", i
, p
, sym
->st_shndx
);
2547 lseek(fd
, off
, SEEK_SET
);
2548 if(tcc_load_object_file(s1
, fd
, off
) < 0) {
2563 /* load a '.a' file */
2564 ST_FUNC
int tcc_load_archive(TCCState
*s1
, int fd
)
2571 unsigned long file_offset
;
2573 /* skip magic which was already checked */
2574 read(fd
, magic
, sizeof(magic
));
2577 len
= read(fd
, &hdr
, sizeof(hdr
));
2580 if (len
!= sizeof(hdr
)) {
2581 error_noabort("invalid archive");
2584 memcpy(ar_size
, hdr
.ar_size
, sizeof(hdr
.ar_size
));
2585 ar_size
[sizeof(hdr
.ar_size
)] = '\0';
2586 size
= strtol(ar_size
, NULL
, 0);
2587 memcpy(ar_name
, hdr
.ar_name
, sizeof(hdr
.ar_name
));
2588 for(i
= sizeof(hdr
.ar_name
) - 1; i
>= 0; i
--) {
2589 if (ar_name
[i
] != ' ')
2592 ar_name
[i
+ 1] = '\0';
2593 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2594 file_offset
= lseek(fd
, 0, SEEK_CUR
);
2596 size
= (size
+ 1) & ~1;
2597 if (!strcmp(ar_name
, "/")) {
2598 /* coff symbol table : we handle it */
2599 if(s1
->alacarte_link
)
2600 return tcc_load_alacarte(s1
, fd
, size
);
2601 } else if (!strcmp(ar_name
, "//") ||
2602 !strcmp(ar_name
, "__.SYMDEF") ||
2603 !strcmp(ar_name
, "__.SYMDEF/") ||
2604 !strcmp(ar_name
, "ARFILENAMES/")) {
2605 /* skip symbol table or archive names */
2607 if (tcc_load_object_file(s1
, fd
, file_offset
) < 0)
2610 lseek(fd
, file_offset
+ size
, SEEK_SET
);
2615 #ifndef TCC_TARGET_PE
2616 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2617 is referenced by the user (so it should be added as DT_NEEDED in
2618 the generated ELF file) */
2619 ST_FUNC
int tcc_load_dll(TCCState
*s1
, int fd
, const char *filename
, int level
)
2622 ElfW(Shdr
) *shdr
, *sh
, *sh1
;
2623 int i
, j
, nb_syms
, nb_dts
, sym_bind
, ret
;
2624 ElfW(Sym
) *sym
, *dynsym
;
2625 ElfW(Dyn
) *dt
, *dynamic
;
2626 unsigned char *dynstr
;
2627 const char *name
, *soname
;
2628 DLLReference
*dllref
;
2630 read(fd
, &ehdr
, sizeof(ehdr
));
2632 /* test CPU specific stuff */
2633 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2634 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2635 error_noabort("bad architecture");
2640 shdr
= load_data(fd
, ehdr
.e_shoff
, sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2642 /* load dynamic section and dynamic symbols */
2646 dynsym
= NULL
; /* avoid warning */
2647 dynstr
= NULL
; /* avoid warning */
2648 for(i
= 0, sh
= shdr
; i
< ehdr
.e_shnum
; i
++, sh
++) {
2649 switch(sh
->sh_type
) {
2651 nb_dts
= sh
->sh_size
/ sizeof(ElfW(Dyn
));
2652 dynamic
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2655 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2656 dynsym
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2657 sh1
= &shdr
[sh
->sh_link
];
2658 dynstr
= load_data(fd
, sh1
->sh_offset
, sh1
->sh_size
);
2665 /* compute the real library name */
2666 soname
= tcc_basename(filename
);
2668 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2669 if (dt
->d_tag
== DT_SONAME
) {
2670 soname
= dynstr
+ dt
->d_un
.d_val
;
2674 /* if the dll is already loaded, do not load it */
2675 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
2676 dllref
= s1
->loaded_dlls
[i
];
2677 if (!strcmp(soname
, dllref
->name
)) {
2678 /* but update level if needed */
2679 if (level
< dllref
->level
)
2680 dllref
->level
= level
;
2686 // printf("loading dll '%s'\n", soname);
2688 /* add the dll and its level */
2689 dllref
= tcc_mallocz(sizeof(DLLReference
) + strlen(soname
));
2690 dllref
->level
= level
;
2691 strcpy(dllref
->name
, soname
);
2692 dynarray_add((void ***)&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
, dllref
);
2694 /* add dynamic symbols in dynsym_section */
2695 for(i
= 1, sym
= dynsym
+ 1; i
< nb_syms
; i
++, sym
++) {
2696 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
2697 if (sym_bind
== STB_LOCAL
)
2699 name
= dynstr
+ sym
->st_name
;
2700 add_elf_sym(s1
->dynsymtab_section
, sym
->st_value
, sym
->st_size
,
2701 sym
->st_info
, sym
->st_other
, sym
->st_shndx
, name
);
2704 /* load all referenced DLLs */
2705 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2708 name
= dynstr
+ dt
->d_un
.d_val
;
2709 for(j
= 0; j
< s1
->nb_loaded_dlls
; j
++) {
2710 dllref
= s1
->loaded_dlls
[j
];
2711 if (!strcmp(name
, dllref
->name
))
2712 goto already_loaded
;
2714 if (tcc_add_dll(s1
, name
, AFF_REFERENCED_DLL
) < 0) {
2715 error_noabort("referenced dll '%s' not found", name
);
2732 #define LD_TOK_NAME 256
2733 #define LD_TOK_EOF (-1)
2735 /* return next ld script token */
2736 static int ld_next(TCCState
*s1
, char *name
, int name_size
)
2754 file
->buf_ptr
= parse_comment(file
->buf_ptr
);
2755 ch
= file
->buf_ptr
[0];
2763 /* case 'a' ... 'z': */
2790 /* case 'A' ... 'z': */
2825 if (!((ch
>= 'a' && ch
<= 'z') ||
2826 (ch
>= 'A' && ch
<= 'Z') ||
2827 (ch
>= '0' && ch
<= '9') ||
2828 strchr("/.-_+=$:\\,~", ch
)))
2830 if ((q
- name
) < name_size
- 1) {
2847 printf("tok=%c %d\n", c
, c
);
2848 if (c
== LD_TOK_NAME
)
2849 printf(" name=%s\n", name
);
2854 char *tcc_strcpy_part(char *out
, const char *in
, size_t num
)
2856 memcpy(out
, in
, num
);
2862 * Extract the library name from the file name
2863 * Return 0 if the file isn't a library
2865 * /!\ No test on filename capacity, be careful
2867 static int filename_to_libname(TCCState
*s1
, const char filename
[], char libname
[])
2872 /* already converted to library name */
2873 if (libname
[0] != '\0')
2875 ext
= tcc_fileextension(filename
);
2878 libprefix
= !strncmp(filename
, "lib", 3);
2879 if (!s1
->static_link
) {
2880 #ifdef TCC_TARGET_PE
2881 if (!strcmp(ext
, ".def")) {
2882 size_t len
= ext
- filename
;
2883 tcc_strcpy_part(libname
, filename
, len
);
2887 if (libprefix
&& (!strcmp(ext
, ".so"))) {
2888 size_t len
= ext
- filename
- 3;
2889 tcc_strcpy_part(libname
, filename
+ 3, len
);
2894 if (libprefix
&& (!strcmp(ext
, ".a"))) {
2895 size_t len
= ext
- filename
- 3;
2896 tcc_strcpy_part(libname
, filename
+ 3, len
);
2904 * Extract the file name from the library name
2906 * /!\ No test on filename capacity, be careful
2908 static void libname_to_filename(TCCState
*s1
, const char libname
[], char filename
[])
2910 if (!s1
->static_link
) {
2911 #ifdef TCC_TARGET_PE
2912 sprintf(filename
, "%s.def", libname
);
2914 sprintf(filename
, "lib%s.so", libname
);
2917 sprintf(filename
, "lib%s.a", libname
);
2921 static int ld_add_file(TCCState
*s1
, const char filename
[], char libname
[])
2925 ret
= tcc_add_file_internal(s1
, filename
, 0);
2927 if (filename_to_libname(s1
, filename
, libname
))
2928 ret
= tcc_add_library(s1
, libname
);
2933 static inline int new_undef_syms(void)
2936 ret
= new_undef_sym
;
2941 static int ld_add_file_list(TCCState
*s1
, const char *cmd
, int as_needed
)
2943 char filename
[1024], libname
[1024];
2944 int t
, group
, nblibs
= 0, ret
= 0;
2947 group
= !strcmp(cmd
, "GROUP");
2950 t
= ld_next(s1
, filename
, sizeof(filename
));
2953 t
= ld_next(s1
, filename
, sizeof(filename
));
2956 if (t
== LD_TOK_EOF
) {
2957 error_noabort("unexpected end of file");
2959 goto lib_parse_error
;
2960 } else if (t
== ')') {
2962 } else if (t
== '-') {
2963 t
= ld_next(s1
, filename
, sizeof(filename
));
2964 if ((t
!= LD_TOK_NAME
) || (filename
[0] != 'l')) {
2965 error_noabort("library name expected");
2967 goto lib_parse_error
;
2969 strcpy(libname
, &filename
[1]);
2970 libname_to_filename(s1
, libname
, filename
);
2971 } else if (t
!= LD_TOK_NAME
) {
2972 error_noabort("filename expected");
2974 goto lib_parse_error
;
2976 if (!strcmp(filename
, "AS_NEEDED")) {
2977 ret
= ld_add_file_list(s1
, cmd
, 1);
2979 goto lib_parse_error
;
2981 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2983 ret
= ld_add_file(s1
, filename
, libname
);
2985 goto lib_parse_error
;
2987 /* Add the filename *and* the libname to avoid future conversions */
2988 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(filename
));
2989 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(libname
));
2993 t
= ld_next(s1
, filename
, sizeof(filename
));
2995 t
= ld_next(s1
, filename
, sizeof(filename
));
2998 if (group
&& !as_needed
) {
2999 while (new_undef_syms()) {
3002 for (i
= 0; i
< nblibs
; i
+= 2)
3003 ld_add_file(s1
, libs
[i
], libs
[i
+1]);
3007 dynarray_reset(&libs
, &nblibs
);
3011 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3013 ST_FUNC
int tcc_load_ldscript(TCCState
*s1
)
3016 char filename
[1024];
3019 ch
= file
->buf_ptr
[0];
3022 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3023 if (t
== LD_TOK_EOF
)
3025 else if (t
!= LD_TOK_NAME
)
3027 if (!strcmp(cmd
, "INPUT") ||
3028 !strcmp(cmd
, "GROUP")) {
3029 ret
= ld_add_file_list(s1
, cmd
, 0);
3032 } else if (!strcmp(cmd
, "OUTPUT_FORMAT") ||
3033 !strcmp(cmd
, "TARGET")) {
3034 /* ignore some commands */
3035 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3039 t
= ld_next(s1
, filename
, sizeof(filename
));
3040 if (t
== LD_TOK_EOF
) {
3041 error_noabort("unexpected end of file");
3043 } else if (t
== ')') {