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 /* trade Thumb support for ARMv4 support */
665 if ((0x0ffffff0 & *(int*)ptr
) == 0x012FFF10)
666 *(int*)ptr
^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
669 fprintf(stderr
,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
670 type
,addr
,(unsigned int)(long)ptr
,val
);
672 #elif defined(TCC_TARGET_C67)
680 /* put the low 16 bits of the absolute address */
681 // add to what is already there
683 orig
= ((*(int *)(ptr
)) >> 7) & 0xffff;
684 orig
|= (((*(int *)(ptr
+4)) >> 7) & 0xffff) << 16;
686 //patch both at once - assumes always in pairs Low - High
688 *(int *) ptr
= (*(int *) ptr
& (~(0xffff << 7)) ) | (((val
+orig
) & 0xffff) << 7);
689 *(int *)(ptr
+4) = (*(int *)(ptr
+4) & (~(0xffff << 7)) ) | ((((val
+orig
)>>16) & 0xffff) << 7);
695 fprintf(stderr
,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
696 type
,addr
,(unsigned int)(long)ptr
, val
);
698 #elif defined(TCC_TARGET_X86_64)
700 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
701 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
702 qrel
->r_addend
= *(long long *)ptr
+ val
;
705 *(long long *)ptr
+= val
;
709 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
710 /* XXX: this logic may depend on TCC's codegen
711 now TCC uses R_X86_64_32 even for a 64bit pointer */
712 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
713 qrel
->r_addend
= *(int *)ptr
+ val
;
718 case R_X86_64_PC32
: {
720 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
722 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
724 qrel
->r_offset
= rel
->r_offset
;
725 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_X86_64_PC32
);
726 qrel
->r_addend
= *(int *)ptr
;
731 diff
= (long long)val
- addr
;
732 if (diff
<= -2147483647 || diff
> 2147483647) {
733 #ifndef TCC_TARGET_PE
734 /* XXX: naive support for over 32bit jump */
735 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
736 val
= add_jmp_table(s1
, val
);
740 if (diff
<= -2147483647 || diff
> 2147483647) {
741 error("internal error: relocation failed");
748 *(int *)ptr
+= val
- addr
;
750 case R_X86_64_GLOB_DAT
:
751 case R_X86_64_JUMP_SLOT
:
754 case R_X86_64_GOTPCREL
:
755 #ifndef TCC_TARGET_PE
756 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
757 val
= add_got_table(s1
, val
- rel
->r_addend
) + rel
->r_addend
;
758 *(int *)ptr
+= val
- addr
;
762 *(int *)ptr
+= (s1
->got
->sh_addr
- addr
+
763 s1
->got_offsets
[sym_index
] - 4);
765 case R_X86_64_GOTTPOFF
:
766 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
769 /* we load the got offset */
770 *(int *)ptr
+= s1
->got_offsets
[sym_index
];
773 #error unsupported processor
777 /* if the relocation is allocated, we change its symbol table */
778 if (sr
->sh_flags
& SHF_ALLOC
)
779 sr
->link
= s1
->dynsym
;
782 /* relocate relocation table in 'sr' */
783 static void relocate_rel(TCCState
*s1
, Section
*sr
)
786 ElfW_Rel
*rel
, *rel_end
;
788 s
= s1
->sections
[sr
->sh_info
];
789 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
790 for(rel
= (ElfW_Rel
*)sr
->data
;
793 rel
->r_offset
+= s
->sh_addr
;
797 /* count the number of dynamic relocations so that we can reserve
799 static int prepare_dynamic_rel(TCCState
*s1
, Section
*sr
)
801 ElfW_Rel
*rel
, *rel_end
;
802 int sym_index
, esym_index
, type
, count
;
805 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
806 for(rel
= (ElfW_Rel
*)sr
->data
; rel
< rel_end
; rel
++) {
807 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
808 type
= ELFW(R_TYPE
)(rel
->r_info
);
810 #if defined(TCC_TARGET_I386)
812 #elif defined(TCC_TARGET_X86_64)
819 #if defined(TCC_TARGET_I386)
821 #elif defined(TCC_TARGET_X86_64)
824 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
833 /* allocate the section */
834 sr
->sh_flags
|= SHF_ALLOC
;
835 sr
->sh_size
= count
* sizeof(ElfW_Rel
);
840 static void put_got_offset(TCCState
*s1
, int index
, unsigned long val
)
845 if (index
>= s1
->nb_got_offsets
) {
846 /* find immediately bigger power of 2 and reallocate array */
850 tab
= tcc_realloc(s1
->got_offsets
, n
* sizeof(unsigned long));
852 error("memory full");
853 s1
->got_offsets
= tab
;
854 memset(s1
->got_offsets
+ s1
->nb_got_offsets
, 0,
855 (n
- s1
->nb_got_offsets
) * sizeof(unsigned long));
856 s1
->nb_got_offsets
= n
;
858 s1
->got_offsets
[index
] = val
;
861 /* XXX: suppress that */
862 static void put32(unsigned char *p
, uint32_t val
)
870 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
871 defined(TCC_TARGET_X86_64)
872 static uint32_t get32(unsigned char *p
)
874 return p
[0] | (p
[1] << 8) | (p
[2] << 16) | (p
[3] << 24);
878 static void build_got(TCCState
*s1
)
882 /* if no got, then create it */
883 s1
->got
= new_section(s1
, ".got", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
884 s1
->got
->sh_entsize
= 4;
885 add_elf_sym(symtab_section
, 0, 4, ELFW(ST_INFO
)(STB_GLOBAL
, STT_OBJECT
),
886 0, s1
->got
->sh_num
, "_GLOBAL_OFFSET_TABLE_");
887 ptr
= section_ptr_add(s1
->got
, 3 * PTR_SIZE
);
889 /* keep space for _DYNAMIC pointer, if present */
891 /* two dummy got entries */
895 /* keep space for _DYNAMIC pointer, if present */
898 /* two dummy got entries */
906 /* put a got entry corresponding to a symbol in symtab_section. 'size'
907 and 'info' can be modifed if more precise info comes from the DLL */
908 static void put_got_entry(TCCState
*s1
,
909 int reloc_type
, unsigned long size
, int info
,
915 unsigned long offset
;
921 /* if a got entry already exists for that symbol, no need to add one */
922 if (sym_index
< s1
->nb_got_offsets
&&
923 s1
->got_offsets
[sym_index
] != 0)
926 put_got_offset(s1
, sym_index
, s1
->got
->data_offset
);
929 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
930 name
= symtab_section
->link
->data
+ sym
->st_name
;
931 offset
= sym
->st_value
;
932 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
934 #ifdef TCC_TARGET_X86_64
944 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
947 /* if we build a DLL, we add a %ebx offset */
948 if (s1
->output_type
== TCC_OUTPUT_DLL
)
954 /* add a PLT entry */
956 if (plt
->data_offset
== 0) {
957 /* first plt entry */
958 p
= section_ptr_add(plt
, 16);
959 p
[0] = 0xff; /* pushl got + PTR_SIZE */
961 put32(p
+ 2, PTR_SIZE
);
962 p
[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
964 put32(p
+ 8, PTR_SIZE
* 2);
967 p
= section_ptr_add(plt
, 16);
968 p
[0] = 0xff; /* jmp *(got + x) */
970 put32(p
+ 2, s1
->got
->data_offset
);
971 p
[6] = 0x68; /* push $xxx */
972 put32(p
+ 7, (plt
->data_offset
- 32) >> 1);
973 p
[11] = 0xe9; /* jmp plt_start */
974 put32(p
+ 12, -(plt
->data_offset
));
976 /* the symbol is modified so that it will be relocated to
978 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
979 if (s1
->output_type
== TCC_OUTPUT_EXE
)
981 offset
= plt
->data_offset
- 16;
983 #elif defined(TCC_TARGET_ARM)
984 if (reloc_type
== R_ARM_JUMP_SLOT
) {
988 /* if we build a DLL, we add a %ebx offset */
989 if (s1
->output_type
== TCC_OUTPUT_DLL
)
990 error("DLLs unimplemented!");
992 /* add a PLT entry */
994 if (plt
->data_offset
== 0) {
995 /* first plt entry */
996 p
= section_ptr_add(plt
, 16);
997 put32(p
, 0xe52de004);
998 put32(p
+ 4, 0xe59fe010);
999 put32(p
+ 8, 0xe08fe00e);
1000 put32(p
+ 12, 0xe5bef008);
1003 p
= section_ptr_add(plt
, 16);
1004 put32(p
, 0xe59fc004);
1005 put32(p
+4, 0xe08fc00c);
1006 put32(p
+8, 0xe59cf000);
1007 put32(p
+12, s1
->got
->data_offset
);
1009 /* the symbol is modified so that it will be relocated to
1011 if (s1
->output_type
== TCC_OUTPUT_EXE
)
1012 offset
= plt
->data_offset
- 16;
1014 #elif defined(TCC_TARGET_C67)
1015 error("C67 got not implemented");
1017 #error unsupported CPU
1019 index
= put_elf_sym(s1
->dynsym
, offset
,
1020 size
, info
, 0, sym
->st_shndx
, name
);
1021 /* put a got entry */
1022 put_elf_reloc(s1
->dynsym
, s1
->got
,
1023 s1
->got
->data_offset
,
1026 ptr
= section_ptr_add(s1
->got
, PTR_SIZE
);
1030 /* build GOT and PLT entries */
1031 ST_FUNC
void build_got_entries(TCCState
*s1
)
1033 Section
*s
, *symtab
;
1034 ElfW_Rel
*rel
, *rel_end
;
1036 int i
, type
, reloc_type
, sym_index
;
1038 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1039 s
= s1
->sections
[i
];
1040 if (s
->sh_type
!= SHT_RELX
)
1042 /* no need to handle got relocations */
1043 if (s
->link
!= symtab_section
)
1046 rel_end
= (ElfW_Rel
*)(s
->data
+ s
->data_offset
);
1047 for(rel
= (ElfW_Rel
*)s
->data
;
1050 type
= ELFW(R_TYPE
)(rel
->r_info
);
1052 #if defined(TCC_TARGET_I386)
1059 if (type
== R_386_GOT32
|| type
== R_386_PLT32
) {
1060 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1061 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1062 /* look at the symbol got offset. If none, then add one */
1063 if (type
== R_386_GOT32
)
1064 reloc_type
= R_386_GLOB_DAT
;
1066 reloc_type
= R_386_JMP_SLOT
;
1067 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1071 #elif defined(TCC_TARGET_ARM)
1072 case R_ARM_GOT_BREL
:
1073 case R_ARM_GOTOFF32
:
1074 case R_ARM_BASE_PREL
:
1078 if (type
== R_ARM_GOT_BREL
|| type
== R_ARM_PLT32
) {
1079 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1080 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1081 /* look at the symbol got offset. If none, then add one */
1082 if (type
== R_ARM_GOT_BREL
)
1083 reloc_type
= R_ARM_GLOB_DAT
;
1085 reloc_type
= R_ARM_JUMP_SLOT
;
1086 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1090 #elif defined(TCC_TARGET_C67)
1097 if (type
== R_C60_GOT32
|| type
== R_C60_PLT32
) {
1098 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1099 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1100 /* look at the symbol got offset. If none, then add one */
1101 if (type
== R_C60_GOT32
)
1102 reloc_type
= R_C60_GLOB_DAT
;
1104 reloc_type
= R_C60_JMP_SLOT
;
1105 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1109 #elif defined(TCC_TARGET_X86_64)
1110 case R_X86_64_GOT32
:
1111 case R_X86_64_GOTTPOFF
:
1112 case R_X86_64_GOTPCREL
:
1113 case R_X86_64_PLT32
:
1116 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
||
1117 type
== R_X86_64_PLT32
) {
1118 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1119 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1120 /* look at the symbol got offset. If none, then add one */
1121 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
)
1122 reloc_type
= R_X86_64_GLOB_DAT
;
1124 reloc_type
= R_X86_64_JUMP_SLOT
;
1125 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1130 #error unsupported CPU
1139 ST_FUNC Section
*new_symtab(TCCState
*s1
,
1140 const char *symtab_name
, int sh_type
, int sh_flags
,
1141 const char *strtab_name
,
1142 const char *hash_name
, int hash_sh_flags
)
1144 Section
*symtab
, *strtab
, *hash
;
1145 int *ptr
, nb_buckets
;
1147 symtab
= new_section(s1
, symtab_name
, sh_type
, sh_flags
);
1148 symtab
->sh_entsize
= sizeof(ElfW(Sym
));
1149 strtab
= new_section(s1
, strtab_name
, SHT_STRTAB
, sh_flags
);
1150 put_elf_str(strtab
, "");
1151 symtab
->link
= strtab
;
1152 put_elf_sym(symtab
, 0, 0, 0, 0, 0, NULL
);
1156 hash
= new_section(s1
, hash_name
, SHT_HASH
, hash_sh_flags
);
1157 hash
->sh_entsize
= sizeof(int);
1158 symtab
->hash
= hash
;
1159 hash
->link
= symtab
;
1161 ptr
= section_ptr_add(hash
, (2 + nb_buckets
+ 1) * sizeof(int));
1162 ptr
[0] = nb_buckets
;
1164 memset(ptr
+ 2, 0, (nb_buckets
+ 1) * sizeof(int));
1168 /* put dynamic tag */
1169 static void put_dt(Section
*dynamic
, int dt
, unsigned long val
)
1172 dyn
= section_ptr_add(dynamic
, sizeof(ElfW(Dyn
)));
1174 dyn
->d_un
.d_val
= val
;
1177 static void add_init_array_defines(TCCState
*s1
, const char *section_name
)
1181 char sym_start
[1024];
1184 snprintf(sym_start
, sizeof(sym_start
), "__%s_start", section_name
+ 1);
1185 snprintf(sym_end
, sizeof(sym_end
), "__%s_end", section_name
+ 1);
1187 s
= find_section(s1
, section_name
);
1192 end_offset
= s
->data_offset
;
1195 add_elf_sym(symtab_section
,
1197 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1198 s
->sh_num
, sym_start
);
1199 add_elf_sym(symtab_section
,
1201 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1202 s
->sh_num
, sym_end
);
1205 ST_FUNC
void tcc_add_bcheck(TCCState
*s1
)
1207 #ifdef CONFIG_TCC_BCHECK
1209 Section
*init_section
;
1210 unsigned char *pinit
;
1213 if (0 == s1
->do_bounds_check
)
1216 /* XXX: add an object file to do that */
1217 ptr
= section_ptr_add(bounds_section
, sizeof(unsigned long));
1219 add_elf_sym(symtab_section
, 0, 0,
1220 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1221 bounds_section
->sh_num
, "__bounds_start");
1222 /* add bound check code */
1223 #ifndef TCC_TARGET_PE
1226 snprintf(buf
, sizeof(buf
), "%s/%s", s1
->tcc_lib_path
, "bcheck.o");
1227 tcc_add_file(s1
, buf
);
1230 #ifdef TCC_TARGET_I386
1231 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
) {
1232 /* add 'call __bound_init()' in .init section */
1233 init_section
= find_section(s1
, ".init");
1234 pinit
= section_ptr_add(init_section
, 5);
1236 put32(pinit
+ 1, -4);
1237 sym_index
= find_elf_sym(symtab_section
, "__bound_init");
1238 put_elf_reloc(symtab_section
, init_section
,
1239 init_section
->data_offset
- 4, R_386_PC32
, sym_index
);
1245 /* add tcc runtime libraries */
1246 ST_FUNC
void tcc_add_runtime(TCCState
*s1
)
1251 if (!s1
->nostdlib
) {
1252 #ifdef CONFIG_USE_LIBGCC
1253 tcc_add_library(s1
, "c");
1254 tcc_add_file(s1
, CONFIG_SYSROOT
"/lib/libgcc_s.so.1");
1256 tcc_add_library(s1
, "c");
1257 #ifndef WITHOUT_LIBTCC
1260 snprintf(buf
, sizeof(buf
), "%s/%s", s1
->tcc_lib_path
, "libtcc1.a");
1261 tcc_add_file(s1
, buf
);
1266 /* add crt end if not memory output */
1267 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
&& !s1
->nostdlib
) {
1268 tcc_add_file(s1
, CONFIG_TCC_CRT_PREFIX
"/crtn.o");
1272 /* add various standard linker symbols (must be done after the
1273 sections are filled (for example after allocating common
1275 ST_FUNC
void tcc_add_linker_symbols(TCCState
*s1
)
1281 add_elf_sym(symtab_section
,
1282 text_section
->data_offset
, 0,
1283 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1284 text_section
->sh_num
, "_etext");
1285 add_elf_sym(symtab_section
,
1286 data_section
->data_offset
, 0,
1287 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1288 data_section
->sh_num
, "_edata");
1289 add_elf_sym(symtab_section
,
1290 bss_section
->data_offset
, 0,
1291 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1292 bss_section
->sh_num
, "_end");
1293 /* horrible new standard ldscript defines */
1294 add_init_array_defines(s1
, ".preinit_array");
1295 add_init_array_defines(s1
, ".init_array");
1296 add_init_array_defines(s1
, ".fini_array");
1298 /* add start and stop symbols for sections whose name can be
1300 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1301 s
= s1
->sections
[i
];
1302 if (s
->sh_type
== SHT_PROGBITS
&&
1303 (s
->sh_flags
& SHF_ALLOC
)) {
1307 /* check if section name can be expressed in C */
1313 if (!isid(ch
) && !isnum(ch
))
1317 snprintf(buf
, sizeof(buf
), "__start_%s", s
->name
);
1318 add_elf_sym(symtab_section
,
1320 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1322 snprintf(buf
, sizeof(buf
), "__stop_%s", s
->name
);
1323 add_elf_sym(symtab_section
,
1325 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1332 /* name of ELF interpreter */
1333 #if defined __FreeBSD__
1334 static const char elf_interp
[] = "/libexec/ld-elf.so.1";
1335 #elif defined TCC_ARM_EABI
1336 static const char elf_interp
[] = "/lib/ld-linux.so.3";
1337 #elif defined(TCC_TARGET_X86_64)
1338 # if defined(TCC_TARGET_X86_64_CENTOS)
1339 static const char elf_interp
[] = "/lib64/ld-linux-x86-64.so.2";
1341 static const char elf_interp
[] = "/lib/ld-linux-x86-64.so.2";
1342 # endif /* TCC_TARGET_X86_64_CENTOS */
1343 #elif defined(TCC_UCLIBC)
1344 static const char elf_interp
[] = "/lib/ld-uClibc.so.0";
1346 static const char elf_interp
[] = "/lib/ld-linux.so.2";
1349 static void tcc_output_binary(TCCState
*s1
, FILE *f
,
1350 const int *section_order
)
1353 int i
, offset
, size
;
1356 for(i
=1;i
<s1
->nb_sections
;i
++) {
1357 s
= s1
->sections
[section_order
[i
]];
1358 if (s
->sh_type
!= SHT_NOBITS
&&
1359 (s
->sh_flags
& SHF_ALLOC
)) {
1360 while (offset
< s
->sh_offset
) {
1365 fwrite(s
->data
, 1, size
, f
);
1371 #if defined(__FreeBSD__)
1373 #define EXTRA_RELITEMS 14
1375 /* move the relocation value from .dynsym to .got */
1376 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1378 uint32_t *gotd
= (void *)s1
->got
->data
;
1379 ElfW(Sym
) *sym
, *sym_end
;
1381 gotd
+= 3; // dummy entries in .got
1382 /* relocate symbols in .dynsym */
1383 sym_end
= (ElfW(Sym
) *)(s
->data
+ s
->data_offset
);
1384 for (sym
= (ElfW(Sym
) *)s
->data
+ 1; sym
< sym_end
; sym
++) {
1385 if (sym
->st_shndx
== SHN_UNDEF
) {
1386 *gotd
++ = sym
->st_value
+ 6; // XXX 6 is magic ?
1393 #define EXTRA_RELITEMS 9
1396 ST_FUNC
void fill_got_entry(TCCState
*s1
, ElfW_Rel
*rel
)
1398 int sym_index
= ELFW(R_SYM
) (rel
->r_info
);
1399 ElfW(Sym
) *sym
= &((ElfW(Sym
) *) symtab_section
->data
)[sym_index
];
1400 unsigned long offset
;
1402 if (sym_index
>= s1
->nb_got_offsets
)
1404 offset
= s1
->got_offsets
[sym_index
];
1405 section_reserve(s1
->got
, offset
+ PTR_SIZE
);
1406 #ifdef TCC_TARGET_X86_64
1407 /* only works for x86-64 */
1408 put32(s1
->got
->data
+ offset
, sym
->st_value
>> 32);
1410 put32(s1
->got
->data
+ offset
, sym
->st_value
& 0xffffffff);
1413 ST_FUNC
void fill_got(TCCState
*s1
)
1416 ElfW_Rel
*rel
, *rel_end
;
1419 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1420 s
= s1
->sections
[i
];
1421 if (s
->sh_type
!= SHT_RELX
)
1423 /* no need to handle got relocations */
1424 if (s
->link
!= symtab_section
)
1426 rel_end
= (ElfW_Rel
*) (s
->data
+ s
->data_offset
);
1427 for(rel
= (ElfW_Rel
*) s
->data
; rel
< rel_end
; rel
++) {
1428 switch (ELFW(R_TYPE
) (rel
->r_info
)) {
1429 case R_X86_64_GOT32
:
1430 case R_X86_64_GOTPCREL
:
1431 case R_X86_64_PLT32
:
1432 fill_got_entry(s1
, rel
);
1440 /* output an ELF file */
1441 /* XXX: suppress unneeded sections */
1442 static int elf_output_file(TCCState
*s1
, const char *filename
)
1448 int shnum
, i
, phnum
, file_offset
, offset
, size
, j
, tmp
, sh_order_index
, k
;
1450 Section
*strsec
, *s
;
1451 ElfW(Shdr
) shdr
, *sh
;
1452 ElfW(Phdr
) *phdr
, *ph
;
1453 Section
*interp
, *dynamic
, *dynstr
;
1454 unsigned long saved_dynamic_data_offset
;
1456 int type
, file_type
;
1457 unsigned long rel_addr
, rel_size
;
1458 unsigned long bss_addr
, bss_size
;
1460 file_type
= s1
->output_type
;
1463 if (file_type
!= TCC_OUTPUT_OBJ
) {
1464 tcc_add_runtime(s1
);
1468 section_order
= NULL
;
1471 dynstr
= NULL
; /* avoid warning */
1472 saved_dynamic_data_offset
= 0; /* avoid warning */
1474 if (file_type
!= TCC_OUTPUT_OBJ
) {
1475 relocate_common_syms();
1477 tcc_add_linker_symbols(s1
);
1479 if (!s1
->static_link
) {
1481 int sym_index
, index
;
1482 ElfW(Sym
) *esym
, *sym_end
;
1484 if (file_type
== TCC_OUTPUT_EXE
) {
1486 /* allow override the dynamic loader */
1487 const char *elfint
= getenv("LD_SO");
1489 elfint
= elf_interp
;
1490 /* add interpreter section only if executable */
1491 interp
= new_section(s1
, ".interp", SHT_PROGBITS
, SHF_ALLOC
);
1492 interp
->sh_addralign
= 1;
1493 ptr
= section_ptr_add(interp
, 1+strlen(elfint
));
1494 strcpy(ptr
, elfint
);
1497 /* add dynamic symbol table */
1498 s1
->dynsym
= new_symtab(s1
, ".dynsym", SHT_DYNSYM
, SHF_ALLOC
,
1500 ".hash", SHF_ALLOC
);
1501 dynstr
= s1
->dynsym
->link
;
1503 /* add dynamic section */
1504 dynamic
= new_section(s1
, ".dynamic", SHT_DYNAMIC
,
1505 SHF_ALLOC
| SHF_WRITE
);
1506 dynamic
->link
= dynstr
;
1507 dynamic
->sh_entsize
= sizeof(ElfW(Dyn
));
1510 s1
->plt
= new_section(s1
, ".plt", SHT_PROGBITS
,
1511 SHF_ALLOC
| SHF_EXECINSTR
);
1512 s1
->plt
->sh_entsize
= 4;
1516 /* scan for undefined symbols and see if they are in the
1517 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1518 is found, then we add it in the PLT. If a symbol
1519 STT_OBJECT is found, we add it in the .bss section with
1520 a suitable relocation */
1521 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+
1522 symtab_section
->data_offset
);
1523 if (file_type
== TCC_OUTPUT_EXE
) {
1524 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
1527 if (sym
->st_shndx
== SHN_UNDEF
) {
1528 name
= symtab_section
->link
->data
+ sym
->st_name
;
1529 sym_index
= find_elf_sym(s1
->dynsymtab_section
, name
);
1531 esym
= &((ElfW(Sym
) *)s1
->dynsymtab_section
->data
)[sym_index
];
1532 type
= ELFW(ST_TYPE
)(esym
->st_info
);
1533 if ((type
== STT_FUNC
) || (type
== STT_GNU_IFUNC
)) {
1534 put_got_entry(s1
, R_JMP_SLOT
, esym
->st_size
,
1536 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1537 } else if (type
== STT_OBJECT
) {
1538 unsigned long offset
;
1539 ElfW(Sym
) *dynsym
, *dynsym_end
;
1540 offset
= bss_section
->data_offset
;
1541 /* XXX: which alignment ? */
1542 offset
= (offset
+ 16 - 1) & -16;
1543 index
= put_elf_sym(s1
->dynsym
, offset
, esym
->st_size
,
1545 bss_section
->sh_num
, name
);
1546 /* Ensure symbol aliases (that is, symbols with
1547 the same st_value) resolve to the same
1548 address in program .bss or .data section. */
1549 dynsym_end
= (ElfW(Sym
) *)
1550 (s1
->dynsymtab_section
->data
+
1551 s1
->dynsymtab_section
->data_offset
);
1552 for(dynsym
= (ElfW(Sym
) *)s1
->dynsymtab_section
->data
+ 1;
1553 dynsym
< dynsym_end
; dynsym
++) {
1554 if (dynsym
->st_value
== esym
->st_value
) {
1556 dynname
= s1
->dynsymtab_section
->link
->data
1558 put_elf_sym(s1
->dynsym
, offset
,
1561 bss_section
->sh_num
,
1565 put_elf_reloc(s1
->dynsym
, bss_section
,
1566 offset
, R_COPY
, index
);
1567 offset
+= esym
->st_size
;
1568 bss_section
->data_offset
= offset
;
1571 /* STB_WEAK undefined symbols are accepted */
1572 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1574 if (ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
||
1575 !strcmp(name
, "_fp_hw")) {
1577 error_noabort("undefined symbol '%s'", name
);
1580 } else if (s1
->rdynamic
&&
1581 ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1582 /* if -rdynamic option, then export all non
1584 name
= symtab_section
->link
->data
+ sym
->st_name
;
1585 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1587 sym
->st_shndx
, name
);
1594 /* now look at unresolved dynamic symbols and export
1595 corresponding symbol */
1596 sym_end
= (ElfW(Sym
) *)(s1
->dynsymtab_section
->data
+
1597 s1
->dynsymtab_section
->data_offset
);
1598 for(esym
= (ElfW(Sym
) *)s1
->dynsymtab_section
->data
+ 1;
1601 if (esym
->st_shndx
== SHN_UNDEF
) {
1602 name
= s1
->dynsymtab_section
->link
->data
+ esym
->st_name
;
1603 sym_index
= find_elf_sym(symtab_section
, name
);
1605 /* XXX: avoid adding a symbol if already
1606 present because of -rdynamic ? */
1607 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1608 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1610 sym
->st_shndx
, name
);
1612 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1613 /* weak symbols can stay undefined */
1615 warning("undefined dynamic symbol '%s'", name
);
1622 /* shared library case : we simply export all the global symbols */
1623 nb_syms
= symtab_section
->data_offset
/ sizeof(ElfW(Sym
));
1624 s1
->symtab_to_dynsym
= tcc_mallocz(sizeof(int) * nb_syms
);
1625 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
1628 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1629 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1630 if ((ELFW(ST_TYPE
)(sym
->st_info
) == STT_FUNC
||
1631 ELFW(ST_TYPE
)(sym
->st_info
) == STT_GNU_IFUNC
)
1632 && sym
->st_shndx
== SHN_UNDEF
) {
1633 put_got_entry(s1
, R_JMP_SLOT
, sym
->st_size
,
1635 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1637 else if (ELFW(ST_TYPE
)(sym
->st_info
) == STT_OBJECT
) {
1638 put_got_entry(s1
, R_X86_64_GLOB_DAT
, sym
->st_size
,
1640 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1645 name
= symtab_section
->link
->data
+ sym
->st_name
;
1646 index
= put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1648 sym
->st_shndx
, name
);
1649 s1
->symtab_to_dynsym
[sym
-
1650 (ElfW(Sym
) *)symtab_section
->data
] =
1657 build_got_entries(s1
);
1659 /* add a list of needed dlls */
1660 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
1661 DLLReference
*dllref
= s1
->loaded_dlls
[i
];
1662 if (dllref
->level
== 0)
1663 put_dt(dynamic
, DT_NEEDED
, put_elf_str(dynstr
, dllref
->name
));
1667 put_dt(dynamic
, DT_RPATH
, put_elf_str(dynstr
, s1
->rpath
));
1669 /* XXX: currently, since we do not handle PIC code, we
1670 must relocate the readonly segments */
1671 if (file_type
== TCC_OUTPUT_DLL
) {
1673 put_dt(dynamic
, DT_SONAME
, put_elf_str(dynstr
, s1
->soname
));
1674 put_dt(dynamic
, DT_TEXTREL
, 0);
1678 put_dt(dynamic
, DT_SYMBOLIC
, 0);
1680 /* add necessary space for other entries */
1681 saved_dynamic_data_offset
= dynamic
->data_offset
;
1682 dynamic
->data_offset
+= sizeof(ElfW(Dyn
)) * EXTRA_RELITEMS
;
1684 /* still need to build got entries in case of static link */
1685 build_got_entries(s1
);
1689 memset(&ehdr
, 0, sizeof(ehdr
));
1691 /* we add a section for symbols */
1692 strsec
= new_section(s1
, ".shstrtab", SHT_STRTAB
, 0);
1693 put_elf_str(strsec
, "");
1695 /* compute number of sections */
1696 shnum
= s1
->nb_sections
;
1698 /* this array is used to reorder sections in the output file */
1699 section_order
= tcc_malloc(sizeof(int) * shnum
);
1700 section_order
[0] = 0;
1703 /* compute number of program headers */
1706 case TCC_OUTPUT_OBJ
:
1709 case TCC_OUTPUT_EXE
:
1710 if (!s1
->static_link
)
1711 phnum
= 4 + HAVE_PHDR
;
1715 case TCC_OUTPUT_DLL
:
1720 /* allocate strings for section names and decide if an unallocated
1721 section should be output */
1722 /* NOTE: the strsec section comes last, so its size is also
1724 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1725 s
= s1
->sections
[i
];
1726 s
->sh_name
= put_elf_str(strsec
, s
->name
);
1728 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1733 s
->reloc
? s
->reloc
->name
: "n"
1736 /* when generating a DLL, we include relocations but we may
1738 if (file_type
== TCC_OUTPUT_DLL
&&
1739 s
->sh_type
== SHT_RELX
&&
1740 !(s
->sh_flags
& SHF_ALLOC
)) {
1741 /* //gr: avoid bogus relocs for empty (debug) sections */
1742 if (s1
->sections
[s
->sh_info
]->sh_flags
& SHF_ALLOC
)
1743 prepare_dynamic_rel(s1
, s
);
1744 else if (s1
->do_debug
)
1745 s
->sh_size
= s
->data_offset
;
1746 } else if (s1
->do_debug
||
1747 file_type
== TCC_OUTPUT_OBJ
||
1748 (s
->sh_flags
& SHF_ALLOC
) ||
1749 i
== (s1
->nb_sections
- 1)) {
1750 /* we output all sections if debug or object file */
1751 s
->sh_size
= s
->data_offset
;
1755 /* allocate program segment headers */
1756 phdr
= tcc_mallocz(phnum
* sizeof(ElfW(Phdr
)));
1758 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1759 file_offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
1764 /* compute section to program header mapping */
1765 if (s1
->has_text_addr
) {
1766 int a_offset
, p_offset
;
1767 addr
= s1
->text_addr
;
1768 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1770 a_offset
= addr
& (s1
->section_align
- 1);
1771 p_offset
= file_offset
& (s1
->section_align
- 1);
1772 if (a_offset
< p_offset
)
1773 a_offset
+= s1
->section_align
;
1774 file_offset
+= (a_offset
- p_offset
);
1776 if (file_type
== TCC_OUTPUT_DLL
)
1779 addr
= ELF_START_ADDR
;
1780 /* compute address after headers */
1781 addr
+= (file_offset
& (s1
->section_align
- 1));
1784 /* dynamic relocation table information, for .dynamic section */
1788 bss_addr
= bss_size
= 0;
1789 /* leave one program header for the program interpreter */
1792 ph
+= 1 + HAVE_PHDR
;
1794 for(j
= 0; j
< 2; j
++) {
1795 ph
->p_type
= PT_LOAD
;
1797 ph
->p_flags
= PF_R
| PF_X
;
1799 ph
->p_flags
= PF_R
| PF_W
;
1800 ph
->p_align
= s1
->section_align
;
1802 /* we do the following ordering: interp, symbol tables,
1803 relocations, progbits, nobits */
1804 /* XXX: do faster and simpler sorting */
1805 for(k
= 0; k
< 5; k
++) {
1806 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1807 s
= s1
->sections
[i
];
1808 /* compute if section should be included */
1810 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1814 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1815 (SHF_ALLOC
| SHF_WRITE
))
1821 } else if (s
->sh_type
== SHT_DYNSYM
||
1822 s
->sh_type
== SHT_STRTAB
||
1823 s
->sh_type
== SHT_HASH
) {
1826 } else if (s
->sh_type
== SHT_RELX
) {
1829 } else if (s
->sh_type
== SHT_NOBITS
) {
1836 section_order
[sh_order_index
++] = i
;
1838 /* section matches: we align it and add its size */
1840 addr
= (addr
+ s
->sh_addralign
- 1) &
1841 ~(s
->sh_addralign
- 1);
1842 file_offset
+= addr
- tmp
;
1843 s
->sh_offset
= file_offset
;
1846 /* update program header infos */
1847 if (ph
->p_offset
== 0) {
1848 ph
->p_offset
= file_offset
;
1850 ph
->p_paddr
= ph
->p_vaddr
;
1852 /* update dynamic relocation infos */
1853 if (s
->sh_type
== SHT_RELX
) {
1854 #if defined(__FreeBSD__)
1855 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.got")) { // rel_size == 0) {
1857 rel_size
+= s
->sh_size
; // XXX only first rel.
1859 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.bss")) { // rel_size == 0) {
1861 bss_size
= s
->sh_size
; // XXX only first rel.
1866 rel_size
+= s
->sh_size
;
1870 if (s
->sh_type
!= SHT_NOBITS
)
1871 file_offset
+= s
->sh_size
;
1874 ph
->p_filesz
= file_offset
- ph
->p_offset
;
1875 ph
->p_memsz
= addr
- ph
->p_vaddr
;
1878 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1879 /* if in the middle of a page, we duplicate the page in
1880 memory so that one copy is RX and the other is RW */
1881 if ((addr
& (s1
->section_align
- 1)) != 0)
1882 addr
+= s1
->section_align
;
1884 addr
= (addr
+ s1
->section_align
- 1) & ~(s1
->section_align
- 1);
1885 file_offset
= (file_offset
+ s1
->section_align
- 1) &
1886 ~(s1
->section_align
- 1);
1891 /* if interpreter, then add corresponing program header */
1895 #if defined(__FreeBSD__)
1897 int len
= phnum
* sizeof(ElfW(Phdr
));
1899 ph
->p_type
= PT_PHDR
;
1900 ph
->p_offset
= sizeof(ElfW(Ehdr
));
1901 ph
->p_vaddr
= interp
->sh_addr
- len
;
1902 ph
->p_paddr
= ph
->p_vaddr
;
1903 ph
->p_filesz
= ph
->p_memsz
= len
;
1904 ph
->p_flags
= PF_R
| PF_X
;
1905 ph
->p_align
= 4; // interp->sh_addralign;
1910 ph
->p_type
= PT_INTERP
;
1911 ph
->p_offset
= interp
->sh_offset
;
1912 ph
->p_vaddr
= interp
->sh_addr
;
1913 ph
->p_paddr
= ph
->p_vaddr
;
1914 ph
->p_filesz
= interp
->sh_size
;
1915 ph
->p_memsz
= interp
->sh_size
;
1917 ph
->p_align
= interp
->sh_addralign
;
1920 /* if dynamic section, then add corresponing program header */
1924 ph
= &phdr
[phnum
- 1];
1926 ph
->p_type
= PT_DYNAMIC
;
1927 ph
->p_offset
= dynamic
->sh_offset
;
1928 ph
->p_vaddr
= dynamic
->sh_addr
;
1929 ph
->p_paddr
= ph
->p_vaddr
;
1930 ph
->p_filesz
= dynamic
->sh_size
;
1931 ph
->p_memsz
= dynamic
->sh_size
;
1932 ph
->p_flags
= PF_R
| PF_W
;
1933 ph
->p_align
= dynamic
->sh_addralign
;
1935 /* put GOT dynamic section address */
1936 put32(s1
->got
->data
, dynamic
->sh_addr
);
1938 /* relocate the PLT */
1939 if (file_type
== TCC_OUTPUT_EXE
1940 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1941 || file_type
== TCC_OUTPUT_DLL
1947 p_end
= p
+ s1
->plt
->data_offset
;
1949 #if defined(TCC_TARGET_I386)
1950 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
1951 put32(p
+ 8, get32(p
+ 8) + s1
->got
->sh_addr
);
1954 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
1957 #elif defined(TCC_TARGET_X86_64)
1958 int x
= s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 6;
1959 put32(p
+ 2, get32(p
+ 2) + x
);
1960 put32(p
+ 8, get32(p
+ 8) + x
- 6);
1963 put32(p
+ 2, get32(p
+ 2) + x
+ s1
->plt
->data
- p
);
1966 #elif defined(TCC_TARGET_ARM)
1968 x
=s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 12;
1971 put32(p
+ 12, x
+ get32(p
+ 12) + s1
->plt
->data
- p
);
1974 #elif defined(TCC_TARGET_C67)
1977 #error unsupported CPU
1982 /* relocate symbols in .dynsym */
1983 sym_end
= (ElfW(Sym
) *)(s1
->dynsym
->data
+ s1
->dynsym
->data_offset
);
1984 for(sym
= (ElfW(Sym
) *)s1
->dynsym
->data
+ 1;
1987 if (sym
->st_shndx
== SHN_UNDEF
) {
1988 /* relocate to the PLT if the symbol corresponds
1991 sym
->st_value
+= s1
->plt
->sh_addr
;
1992 } else if (sym
->st_shndx
< SHN_LORESERVE
) {
1993 /* do symbol relocation */
1994 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
1998 /* put dynamic section entries */
1999 dynamic
->data_offset
= saved_dynamic_data_offset
;
2000 put_dt(dynamic
, DT_HASH
, s1
->dynsym
->hash
->sh_addr
);
2001 put_dt(dynamic
, DT_STRTAB
, dynstr
->sh_addr
);
2002 put_dt(dynamic
, DT_SYMTAB
, s1
->dynsym
->sh_addr
);
2003 put_dt(dynamic
, DT_STRSZ
, dynstr
->data_offset
);
2004 put_dt(dynamic
, DT_SYMENT
, sizeof(ElfW(Sym
)));
2005 #ifdef TCC_TARGET_X86_64
2006 put_dt(dynamic
, DT_RELA
, rel_addr
);
2007 put_dt(dynamic
, DT_RELASZ
, rel_size
);
2008 put_dt(dynamic
, DT_RELAENT
, sizeof(ElfW_Rel
));
2010 #if defined(__FreeBSD__)
2011 put_dt(dynamic
, DT_PLTGOT
, s1
->got
->sh_addr
);
2012 put_dt(dynamic
, DT_PLTRELSZ
, rel_size
);
2013 put_dt(dynamic
, DT_JMPREL
, rel_addr
);
2014 put_dt(dynamic
, DT_PLTREL
, DT_REL
);
2015 put_dt(dynamic
, DT_REL
, bss_addr
);
2016 put_dt(dynamic
, DT_RELSZ
, bss_size
);
2018 put_dt(dynamic
, DT_REL
, rel_addr
);
2019 put_dt(dynamic
, DT_RELSZ
, rel_size
);
2020 put_dt(dynamic
, DT_RELENT
, sizeof(ElfW_Rel
));
2024 put_dt(dynamic
, DT_DEBUG
, 0);
2025 put_dt(dynamic
, DT_NULL
, 0);
2028 ehdr
.e_phentsize
= sizeof(ElfW(Phdr
));
2029 ehdr
.e_phnum
= phnum
;
2030 ehdr
.e_phoff
= sizeof(ElfW(Ehdr
));
2033 /* all other sections come after */
2034 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2035 s
= s1
->sections
[i
];
2036 if (phnum
> 0 && (s
->sh_flags
& SHF_ALLOC
))
2038 section_order
[sh_order_index
++] = i
;
2040 file_offset
= (file_offset
+ s
->sh_addralign
- 1) &
2041 ~(s
->sh_addralign
- 1);
2042 s
->sh_offset
= file_offset
;
2043 if (s
->sh_type
!= SHT_NOBITS
)
2044 file_offset
+= s
->sh_size
;
2047 /* if building executable or DLL, then relocate each section
2048 except the GOT which is already relocated */
2049 if (file_type
!= TCC_OUTPUT_OBJ
) {
2050 relocate_syms(s1
, 0);
2052 if (s1
->nb_errors
!= 0) {
2058 /* relocate sections */
2059 /* XXX: ignore sections with allocated relocations ? */
2060 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2061 s
= s1
->sections
[i
];
2062 if (s
->reloc
&& s
!= s1
->got
&& (s
->sh_flags
& SHF_ALLOC
)) //gr
2063 relocate_section(s1
, s
);
2066 /* relocate relocation entries if the relocation tables are
2067 allocated in the executable */
2068 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2069 s
= s1
->sections
[i
];
2070 if ((s
->sh_flags
& SHF_ALLOC
) &&
2071 s
->sh_type
== SHT_RELX
) {
2072 relocate_rel(s1
, s
);
2076 /* get entry point address */
2077 if (file_type
== TCC_OUTPUT_EXE
)
2078 ehdr
.e_entry
= (uplong
)tcc_get_symbol_err(s1
, "_start");
2080 ehdr
.e_entry
= text_section
->sh_addr
; /* XXX: is it correct ? */
2082 if (file_type
== TCC_OUTPUT_EXE
&& s1
->static_link
)
2085 /* write elf file */
2086 if (file_type
== TCC_OUTPUT_OBJ
)
2090 fd
= open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
, mode
);
2092 error_noabort("could not write '%s'", filename
);
2095 f
= fdopen(fd
, "wb");
2097 printf("<- %s\n", filename
);
2099 #ifdef TCC_TARGET_COFF
2100 if (s1
->output_format
== TCC_OUTPUT_FORMAT_COFF
) {
2101 tcc_output_coff(s1
, f
);
2104 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
2105 sort_syms(s1
, symtab_section
);
2108 file_offset
= (file_offset
+ 3) & -4;
2111 ehdr
.e_ident
[0] = ELFMAG0
;
2112 ehdr
.e_ident
[1] = ELFMAG1
;
2113 ehdr
.e_ident
[2] = ELFMAG2
;
2114 ehdr
.e_ident
[3] = ELFMAG3
;
2115 ehdr
.e_ident
[4] = TCC_ELFCLASS
;
2116 ehdr
.e_ident
[5] = ELFDATA2LSB
;
2117 ehdr
.e_ident
[6] = EV_CURRENT
;
2119 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_FREEBSD
;
2121 #ifdef TCC_TARGET_ARM
2123 ehdr
.e_ident
[EI_OSABI
] = 0;
2124 ehdr
.e_flags
= 4 << 24;
2126 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_ARM
;
2131 case TCC_OUTPUT_EXE
:
2132 ehdr
.e_type
= ET_EXEC
;
2134 case TCC_OUTPUT_DLL
:
2135 ehdr
.e_type
= ET_DYN
;
2137 case TCC_OUTPUT_OBJ
:
2138 ehdr
.e_type
= ET_REL
;
2141 ehdr
.e_machine
= EM_TCC_TARGET
;
2142 ehdr
.e_version
= EV_CURRENT
;
2143 ehdr
.e_shoff
= file_offset
;
2144 ehdr
.e_ehsize
= sizeof(ElfW(Ehdr
));
2145 ehdr
.e_shentsize
= sizeof(ElfW(Shdr
));
2146 ehdr
.e_shnum
= shnum
;
2147 ehdr
.e_shstrndx
= shnum
- 1;
2149 fwrite(&ehdr
, 1, sizeof(ElfW(Ehdr
)), f
);
2150 fwrite(phdr
, 1, phnum
* sizeof(ElfW(Phdr
)), f
);
2151 offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
2153 for(i
=1;i
<s1
->nb_sections
;i
++) {
2154 s
= s1
->sections
[section_order
[i
]];
2155 if (s
->sh_type
!= SHT_NOBITS
) {
2156 #if defined(__FreeBSD__)
2157 if (s
->sh_type
== SHT_DYNSYM
)
2158 patch_dynsym_undef(s1
, s
);
2160 while (offset
< s
->sh_offset
) {
2165 fwrite(s
->data
, 1, size
, f
);
2170 /* output section headers */
2171 while (offset
< ehdr
.e_shoff
) {
2176 for(i
=0;i
<s1
->nb_sections
;i
++) {
2178 memset(sh
, 0, sizeof(ElfW(Shdr
)));
2179 s
= s1
->sections
[i
];
2181 sh
->sh_name
= s
->sh_name
;
2182 sh
->sh_type
= s
->sh_type
;
2183 sh
->sh_flags
= s
->sh_flags
;
2184 sh
->sh_entsize
= s
->sh_entsize
;
2185 sh
->sh_info
= s
->sh_info
;
2187 sh
->sh_link
= s
->link
->sh_num
;
2188 sh
->sh_addralign
= s
->sh_addralign
;
2189 sh
->sh_addr
= s
->sh_addr
;
2190 sh
->sh_offset
= s
->sh_offset
;
2191 sh
->sh_size
= s
->sh_size
;
2193 fwrite(sh
, 1, sizeof(ElfW(Shdr
)), f
);
2196 tcc_output_binary(s1
, f
, section_order
);
2202 tcc_free(s1
->symtab_to_dynsym
);
2203 tcc_free(section_order
);
2205 tcc_free(s1
->got_offsets
);
2209 LIBTCCAPI
int tcc_output_file(TCCState
*s
, const char *filename
)
2212 #ifdef TCC_TARGET_PE
2213 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
2214 ret
= pe_output_file(s
, filename
);
2218 ret
= elf_output_file(s
, filename
);
2223 static void *load_data(int fd
, unsigned long file_offset
, unsigned long size
)
2227 data
= tcc_malloc(size
);
2228 lseek(fd
, file_offset
, SEEK_SET
);
2229 read(fd
, data
, size
);
2233 typedef struct SectionMergeInfo
{
2234 Section
*s
; /* corresponding existing section */
2235 unsigned long offset
; /* offset of the new section in the existing section */
2236 uint8_t new_section
; /* true if section 's' was added */
2237 uint8_t link_once
; /* true if link once section */
2240 /* load an object file and merge it with current files */
2241 /* XXX: handle correctly stab (debug) info */
2242 ST_FUNC
int tcc_load_object_file(TCCState
*s1
,
2243 int fd
, unsigned long file_offset
)
2246 ElfW(Shdr
) *shdr
, *sh
;
2247 int size
, i
, j
, offset
, offseti
, nb_syms
, sym_index
, ret
;
2248 unsigned char *strsec
, *strtab
;
2249 int *old_to_new_syms
;
2250 char *sh_name
, *name
;
2251 SectionMergeInfo
*sm_table
, *sm
;
2252 ElfW(Sym
) *sym
, *symtab
;
2253 ElfW_Rel
*rel
, *rel_end
;
2259 stab_index
= stabstr_index
= 0;
2261 if (read(fd
, &ehdr
, sizeof(ehdr
)) != sizeof(ehdr
))
2263 if (ehdr
.e_ident
[0] != ELFMAG0
||
2264 ehdr
.e_ident
[1] != ELFMAG1
||
2265 ehdr
.e_ident
[2] != ELFMAG2
||
2266 ehdr
.e_ident
[3] != ELFMAG3
)
2268 /* test if object file */
2269 if (ehdr
.e_type
!= ET_REL
)
2271 /* test CPU specific stuff */
2272 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2273 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2275 error_noabort("invalid object file");
2279 shdr
= load_data(fd
, file_offset
+ ehdr
.e_shoff
,
2280 sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2281 sm_table
= tcc_mallocz(sizeof(SectionMergeInfo
) * ehdr
.e_shnum
);
2283 /* load section names */
2284 sh
= &shdr
[ehdr
.e_shstrndx
];
2285 strsec
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2287 /* load symtab and strtab */
2288 old_to_new_syms
= NULL
;
2292 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2294 if (sh
->sh_type
== SHT_SYMTAB
) {
2296 error_noabort("object must contain only one symtab");
2301 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2302 symtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2303 sm_table
[i
].s
= symtab_section
;
2305 /* now load strtab */
2306 sh
= &shdr
[sh
->sh_link
];
2307 strtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2311 /* now examine each section and try to merge its content with the
2313 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2314 /* no need to examine section name strtab */
2315 if (i
== ehdr
.e_shstrndx
)
2318 sh_name
= strsec
+ sh
->sh_name
;
2319 /* ignore sections types we do not handle */
2320 if (sh
->sh_type
!= SHT_PROGBITS
&&
2321 sh
->sh_type
!= SHT_RELX
&&
2323 sh
->sh_type
!= SHT_ARM_EXIDX
&&
2325 sh
->sh_type
!= SHT_NOBITS
&&
2326 sh
->sh_type
!= SHT_PREINIT_ARRAY
&&
2327 sh
->sh_type
!= SHT_INIT_ARRAY
&&
2328 sh
->sh_type
!= SHT_FINI_ARRAY
&&
2329 strcmp(sh_name
, ".stabstr")
2332 if (sh
->sh_addralign
< 1)
2333 sh
->sh_addralign
= 1;
2334 /* find corresponding section, if any */
2335 for(j
= 1; j
< s1
->nb_sections
;j
++) {
2336 s
= s1
->sections
[j
];
2337 if (!strcmp(s
->name
, sh_name
)) {
2338 if (!strncmp(sh_name
, ".gnu.linkonce",
2339 sizeof(".gnu.linkonce") - 1)) {
2340 /* if a 'linkonce' section is already present, we
2341 do not add it again. It is a little tricky as
2342 symbols can still be defined in
2344 sm_table
[i
].link_once
= 1;
2351 /* not found: create new section */
2352 s
= new_section(s1
, sh_name
, sh
->sh_type
, sh
->sh_flags
);
2353 /* take as much info as possible from the section. sh_link and
2354 sh_info will be updated later */
2355 s
->sh_addralign
= sh
->sh_addralign
;
2356 s
->sh_entsize
= sh
->sh_entsize
;
2357 sm_table
[i
].new_section
= 1;
2359 if (sh
->sh_type
!= s
->sh_type
) {
2360 error_noabort("invalid section type");
2364 /* align start of section */
2365 offset
= s
->data_offset
;
2367 if (0 == strcmp(sh_name
, ".stab")) {
2371 if (0 == strcmp(sh_name
, ".stabstr")) {
2376 size
= sh
->sh_addralign
- 1;
2377 offset
= (offset
+ size
) & ~size
;
2378 if (sh
->sh_addralign
> s
->sh_addralign
)
2379 s
->sh_addralign
= sh
->sh_addralign
;
2380 s
->data_offset
= offset
;
2382 sm_table
[i
].offset
= offset
;
2384 /* concatenate sections */
2386 if (sh
->sh_type
!= SHT_NOBITS
) {
2388 lseek(fd
, file_offset
+ sh
->sh_offset
, SEEK_SET
);
2389 ptr
= section_ptr_add(s
, size
);
2390 read(fd
, ptr
, size
);
2392 s
->data_offset
+= size
;
2397 /* //gr relocate stab strings */
2398 if (stab_index
&& stabstr_index
) {
2401 s
= sm_table
[stab_index
].s
;
2402 a
= (Stab_Sym
*)(s
->data
+ sm_table
[stab_index
].offset
);
2403 b
= (Stab_Sym
*)(s
->data
+ s
->data_offset
);
2404 o
= sm_table
[stabstr_index
].offset
;
2406 a
->n_strx
+= o
, a
++;
2409 /* second short pass to update sh_link and sh_info fields of new
2411 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2413 if (!s
|| !sm_table
[i
].new_section
)
2416 if (sh
->sh_link
> 0)
2417 s
->link
= sm_table
[sh
->sh_link
].s
;
2418 if (sh
->sh_type
== SHT_RELX
) {
2419 s
->sh_info
= sm_table
[sh
->sh_info
].s
->sh_num
;
2420 /* update backward link */
2421 s1
->sections
[s
->sh_info
]->reloc
= s
;
2426 /* resolve symbols */
2427 old_to_new_syms
= tcc_mallocz(nb_syms
* sizeof(int));
2430 for(i
= 1; i
< nb_syms
; i
++, sym
++) {
2431 if (sym
->st_shndx
!= SHN_UNDEF
&&
2432 sym
->st_shndx
< SHN_LORESERVE
) {
2433 sm
= &sm_table
[sym
->st_shndx
];
2434 if (sm
->link_once
) {
2435 /* if a symbol is in a link once section, we use the
2436 already defined symbol. It is very important to get
2437 correct relocations */
2438 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
2439 name
= strtab
+ sym
->st_name
;
2440 sym_index
= find_elf_sym(symtab_section
, name
);
2442 old_to_new_syms
[i
] = sym_index
;
2446 /* if no corresponding section added, no need to add symbol */
2449 /* convert section number */
2450 sym
->st_shndx
= sm
->s
->sh_num
;
2452 sym
->st_value
+= sm
->offset
;
2455 name
= strtab
+ sym
->st_name
;
2456 sym_index
= add_elf_sym(symtab_section
, sym
->st_value
, sym
->st_size
,
2457 sym
->st_info
, sym
->st_other
,
2458 sym
->st_shndx
, name
);
2459 old_to_new_syms
[i
] = sym_index
;
2462 /* third pass to patch relocation entries */
2463 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2468 offset
= sm_table
[i
].offset
;
2469 switch(s
->sh_type
) {
2471 /* take relocation offset information */
2472 offseti
= sm_table
[sh
->sh_info
].offset
;
2473 rel_end
= (ElfW_Rel
*)(s
->data
+ s
->data_offset
);
2474 for(rel
= (ElfW_Rel
*)(s
->data
+ offset
);
2479 /* convert symbol index */
2480 type
= ELFW(R_TYPE
)(rel
->r_info
);
2481 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
2482 /* NOTE: only one symtab assumed */
2483 if (sym_index
>= nb_syms
)
2485 sym_index
= old_to_new_syms
[sym_index
];
2486 /* ignore link_once in rel section. */
2487 if (!sym_index
&& !sm
->link_once
2488 #ifdef TCC_TARGET_ARM
2489 && type
!= R_ARM_V4BX
2493 error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2494 i
, strsec
+ sh
->sh_name
, rel
->r_offset
);
2497 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
2498 /* offset the relocation offset */
2499 rel
->r_offset
+= offseti
;
2511 tcc_free(old_to_new_syms
);
2518 typedef struct ArchiveHeader
{
2519 char ar_name
[16]; /* name of this member */
2520 char ar_date
[12]; /* file mtime */
2521 char ar_uid
[6]; /* owner uid; printed as decimal */
2522 char ar_gid
[6]; /* owner gid; printed as decimal */
2523 char ar_mode
[8]; /* file mode, printed as octal */
2524 char ar_size
[10]; /* file size, printed as decimal */
2525 char ar_fmag
[2]; /* should contain ARFMAG */
2528 static int get_be32(const uint8_t *b
)
2530 return b
[3] | (b
[2] << 8) | (b
[1] << 16) | (b
[0] << 24);
2533 /* load only the objects which resolve undefined symbols */
2534 static int tcc_load_alacarte(TCCState
*s1
, int fd
, int size
)
2536 int i
, bound
, nsyms
, sym_index
, off
, ret
;
2538 const char *ar_names
, *p
;
2539 const uint8_t *ar_index
;
2542 data
= tcc_malloc(size
);
2543 if (read(fd
, data
, size
) != size
)
2545 nsyms
= get_be32(data
);
2546 ar_index
= data
+ 4;
2547 ar_names
= ar_index
+ nsyms
* 4;
2551 for(p
= ar_names
, i
= 0; i
< nsyms
; i
++, p
+= strlen(p
)+1) {
2552 sym_index
= find_elf_sym(symtab_section
, p
);
2554 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
2555 if(sym
->st_shndx
== SHN_UNDEF
) {
2556 off
= get_be32(ar_index
+ i
* 4) + sizeof(ArchiveHeader
);
2558 printf("%5d\t%s\t%08x\n", i
, p
, sym
->st_shndx
);
2561 lseek(fd
, off
, SEEK_SET
);
2562 if(tcc_load_object_file(s1
, fd
, off
) < 0) {
2577 /* load a '.a' file */
2578 ST_FUNC
int tcc_load_archive(TCCState
*s1
, int fd
)
2585 unsigned long file_offset
;
2587 /* skip magic which was already checked */
2588 read(fd
, magic
, sizeof(magic
));
2591 len
= read(fd
, &hdr
, sizeof(hdr
));
2594 if (len
!= sizeof(hdr
)) {
2595 error_noabort("invalid archive");
2598 memcpy(ar_size
, hdr
.ar_size
, sizeof(hdr
.ar_size
));
2599 ar_size
[sizeof(hdr
.ar_size
)] = '\0';
2600 size
= strtol(ar_size
, NULL
, 0);
2601 memcpy(ar_name
, hdr
.ar_name
, sizeof(hdr
.ar_name
));
2602 for(i
= sizeof(hdr
.ar_name
) - 1; i
>= 0; i
--) {
2603 if (ar_name
[i
] != ' ')
2606 ar_name
[i
+ 1] = '\0';
2607 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2608 file_offset
= lseek(fd
, 0, SEEK_CUR
);
2610 size
= (size
+ 1) & ~1;
2611 if (!strcmp(ar_name
, "/")) {
2612 /* coff symbol table : we handle it */
2613 if(s1
->alacarte_link
)
2614 return tcc_load_alacarte(s1
, fd
, size
);
2615 } else if (!strcmp(ar_name
, "//") ||
2616 !strcmp(ar_name
, "__.SYMDEF") ||
2617 !strcmp(ar_name
, "__.SYMDEF/") ||
2618 !strcmp(ar_name
, "ARFILENAMES/")) {
2619 /* skip symbol table or archive names */
2621 if (tcc_load_object_file(s1
, fd
, file_offset
) < 0)
2624 lseek(fd
, file_offset
+ size
, SEEK_SET
);
2629 #ifndef TCC_TARGET_PE
2630 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2631 is referenced by the user (so it should be added as DT_NEEDED in
2632 the generated ELF file) */
2633 ST_FUNC
int tcc_load_dll(TCCState
*s1
, int fd
, const char *filename
, int level
)
2636 ElfW(Shdr
) *shdr
, *sh
, *sh1
;
2637 int i
, j
, nb_syms
, nb_dts
, sym_bind
, ret
;
2638 ElfW(Sym
) *sym
, *dynsym
;
2639 ElfW(Dyn
) *dt
, *dynamic
;
2640 unsigned char *dynstr
;
2641 const char *name
, *soname
;
2642 DLLReference
*dllref
;
2644 read(fd
, &ehdr
, sizeof(ehdr
));
2646 /* test CPU specific stuff */
2647 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2648 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2649 error_noabort("bad architecture");
2654 shdr
= load_data(fd
, ehdr
.e_shoff
, sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2656 /* load dynamic section and dynamic symbols */
2660 dynsym
= NULL
; /* avoid warning */
2661 dynstr
= NULL
; /* avoid warning */
2662 for(i
= 0, sh
= shdr
; i
< ehdr
.e_shnum
; i
++, sh
++) {
2663 switch(sh
->sh_type
) {
2665 nb_dts
= sh
->sh_size
/ sizeof(ElfW(Dyn
));
2666 dynamic
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2669 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2670 dynsym
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2671 sh1
= &shdr
[sh
->sh_link
];
2672 dynstr
= load_data(fd
, sh1
->sh_offset
, sh1
->sh_size
);
2679 /* compute the real library name */
2680 soname
= tcc_basename(filename
);
2682 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2683 if (dt
->d_tag
== DT_SONAME
) {
2684 soname
= dynstr
+ dt
->d_un
.d_val
;
2688 /* if the dll is already loaded, do not load it */
2689 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
2690 dllref
= s1
->loaded_dlls
[i
];
2691 if (!strcmp(soname
, dllref
->name
)) {
2692 /* but update level if needed */
2693 if (level
< dllref
->level
)
2694 dllref
->level
= level
;
2700 // printf("loading dll '%s'\n", soname);
2702 /* add the dll and its level */
2703 dllref
= tcc_mallocz(sizeof(DLLReference
) + strlen(soname
));
2704 dllref
->level
= level
;
2705 strcpy(dllref
->name
, soname
);
2706 dynarray_add((void ***)&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
, dllref
);
2708 /* add dynamic symbols in dynsym_section */
2709 for(i
= 1, sym
= dynsym
+ 1; i
< nb_syms
; i
++, sym
++) {
2710 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
2711 if (sym_bind
== STB_LOCAL
)
2713 name
= dynstr
+ sym
->st_name
;
2714 add_elf_sym(s1
->dynsymtab_section
, sym
->st_value
, sym
->st_size
,
2715 sym
->st_info
, sym
->st_other
, sym
->st_shndx
, name
);
2718 /* load all referenced DLLs */
2719 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2722 name
= dynstr
+ dt
->d_un
.d_val
;
2723 for(j
= 0; j
< s1
->nb_loaded_dlls
; j
++) {
2724 dllref
= s1
->loaded_dlls
[j
];
2725 if (!strcmp(name
, dllref
->name
))
2726 goto already_loaded
;
2728 if (tcc_add_dll(s1
, name
, AFF_REFERENCED_DLL
) < 0) {
2729 error_noabort("referenced dll '%s' not found", name
);
2746 #define LD_TOK_NAME 256
2747 #define LD_TOK_EOF (-1)
2749 /* return next ld script token */
2750 static int ld_next(TCCState
*s1
, char *name
, int name_size
)
2768 file
->buf_ptr
= parse_comment(file
->buf_ptr
);
2769 ch
= file
->buf_ptr
[0];
2777 /* case 'a' ... 'z': */
2804 /* case 'A' ... 'z': */
2839 if (!((ch
>= 'a' && ch
<= 'z') ||
2840 (ch
>= 'A' && ch
<= 'Z') ||
2841 (ch
>= '0' && ch
<= '9') ||
2842 strchr("/.-_+=$:\\,~", ch
)))
2844 if ((q
- name
) < name_size
- 1) {
2861 printf("tok=%c %d\n", c
, c
);
2862 if (c
== LD_TOK_NAME
)
2863 printf(" name=%s\n", name
);
2868 char *tcc_strcpy_part(char *out
, const char *in
, size_t num
)
2870 memcpy(out
, in
, num
);
2876 * Extract the library name from the file name
2877 * Return 0 if the file isn't a library
2879 * /!\ No test on filename capacity, be careful
2881 static int filename_to_libname(TCCState
*s1
, const char filename
[], char libname
[])
2886 /* already converted to library name */
2887 if (libname
[0] != '\0')
2889 ext
= tcc_fileextension(filename
);
2892 libprefix
= !strncmp(filename
, "lib", 3);
2893 if (!s1
->static_link
) {
2894 #ifdef TCC_TARGET_PE
2895 if (!strcmp(ext
, ".def")) {
2896 size_t len
= ext
- filename
;
2897 tcc_strcpy_part(libname
, filename
, len
);
2901 if (libprefix
&& (!strcmp(ext
, ".so"))) {
2902 size_t len
= ext
- filename
- 3;
2903 tcc_strcpy_part(libname
, filename
+ 3, len
);
2908 if (libprefix
&& (!strcmp(ext
, ".a"))) {
2909 size_t len
= ext
- filename
- 3;
2910 tcc_strcpy_part(libname
, filename
+ 3, len
);
2918 * Extract the file name from the library name
2920 * /!\ No test on filename capacity, be careful
2922 static void libname_to_filename(TCCState
*s1
, const char libname
[], char filename
[])
2924 if (!s1
->static_link
) {
2925 #ifdef TCC_TARGET_PE
2926 sprintf(filename
, "%s.def", libname
);
2928 sprintf(filename
, "lib%s.so", libname
);
2931 sprintf(filename
, "lib%s.a", libname
);
2935 static int ld_add_file(TCCState
*s1
, const char filename
[], char libname
[])
2939 ret
= tcc_add_file_internal(s1
, filename
, 0);
2941 if (filename_to_libname(s1
, filename
, libname
))
2942 ret
= tcc_add_library(s1
, libname
);
2947 static inline int new_undef_syms(void)
2950 ret
= new_undef_sym
;
2955 static int ld_add_file_list(TCCState
*s1
, const char *cmd
, int as_needed
)
2957 char filename
[1024], libname
[1024];
2958 int t
, group
, nblibs
= 0, ret
= 0;
2961 group
= !strcmp(cmd
, "GROUP");
2964 t
= ld_next(s1
, filename
, sizeof(filename
));
2967 t
= ld_next(s1
, filename
, sizeof(filename
));
2970 if (t
== LD_TOK_EOF
) {
2971 error_noabort("unexpected end of file");
2973 goto lib_parse_error
;
2974 } else if (t
== ')') {
2976 } else if (t
== '-') {
2977 t
= ld_next(s1
, filename
, sizeof(filename
));
2978 if ((t
!= LD_TOK_NAME
) || (filename
[0] != 'l')) {
2979 error_noabort("library name expected");
2981 goto lib_parse_error
;
2983 strcpy(libname
, &filename
[1]);
2984 libname_to_filename(s1
, libname
, filename
);
2985 } else if (t
!= LD_TOK_NAME
) {
2986 error_noabort("filename expected");
2988 goto lib_parse_error
;
2990 if (!strcmp(filename
, "AS_NEEDED")) {
2991 ret
= ld_add_file_list(s1
, cmd
, 1);
2993 goto lib_parse_error
;
2995 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2997 ret
= ld_add_file(s1
, filename
, libname
);
2999 goto lib_parse_error
;
3001 /* Add the filename *and* the libname to avoid future conversions */
3002 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(filename
));
3003 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(libname
));
3007 t
= ld_next(s1
, filename
, sizeof(filename
));
3009 t
= ld_next(s1
, filename
, sizeof(filename
));
3012 if (group
&& !as_needed
) {
3013 while (new_undef_syms()) {
3016 for (i
= 0; i
< nblibs
; i
+= 2)
3017 ld_add_file(s1
, libs
[i
], libs
[i
+1]);
3021 dynarray_reset(&libs
, &nblibs
);
3025 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3027 ST_FUNC
int tcc_load_ldscript(TCCState
*s1
)
3030 char filename
[1024];
3033 ch
= file
->buf_ptr
[0];
3036 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3037 if (t
== LD_TOK_EOF
)
3039 else if (t
!= LD_TOK_NAME
)
3041 if (!strcmp(cmd
, "INPUT") ||
3042 !strcmp(cmd
, "GROUP")) {
3043 ret
= ld_add_file_list(s1
, cmd
, 0);
3046 } else if (!strcmp(cmd
, "OUTPUT_FORMAT") ||
3047 !strcmp(cmd
, "TARGET")) {
3048 /* ignore some commands */
3049 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3053 t
= ld_next(s1
, filename
, sizeof(filename
));
3054 if (t
== LD_TOK_EOF
) {
3055 error_noabort("unexpected end of file");
3057 } else if (t
== ')') {