2 * ELF file handling for TCC
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 static int new_undef_sym
= 0; /* Is there a new undefined sym since last new_undef_sym() */
25 ST_FUNC
int put_elf_str(Section
*s
, const char *sym
)
30 len
= strlen(sym
) + 1;
31 offset
= s
->data_offset
;
32 ptr
= section_ptr_add(s
, len
);
33 memcpy(ptr
, sym
, len
);
37 /* elf symbol hashing function */
38 static unsigned long elf_hash(const unsigned char *name
)
40 unsigned long h
= 0, g
;
43 h
= (h
<< 4) + *name
++;
52 /* rebuild hash table of section s */
53 /* NOTE: we do factorize the hash table code to go faster */
54 static void rebuild_hash(Section
*s
, unsigned int nb_buckets
)
57 int *ptr
, *hash
, nb_syms
, sym_index
, h
;
60 strtab
= s
->link
->data
;
61 nb_syms
= s
->data_offset
/ sizeof(ElfW(Sym
));
63 s
->hash
->data_offset
= 0;
64 ptr
= section_ptr_add(s
->hash
, (2 + nb_buckets
+ nb_syms
) * sizeof(int));
69 memset(hash
, 0, (nb_buckets
+ 1) * sizeof(int));
70 ptr
+= nb_buckets
+ 1;
72 sym
= (ElfW(Sym
) *)s
->data
+ 1;
73 for(sym_index
= 1; sym_index
< nb_syms
; sym_index
++) {
74 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
75 h
= elf_hash(strtab
+ sym
->st_name
) % nb_buckets
;
86 /* return the symbol number */
87 ST_FUNC
int put_elf_sym(Section
*s
, uplong value
, unsigned long size
,
88 int info
, int other
, int shndx
, const char *name
)
90 int name_offset
, sym_index
;
95 sym
= section_ptr_add(s
, sizeof(ElfW(Sym
)));
97 name_offset
= put_elf_str(s
->link
, name
);
100 /* XXX: endianness */
101 sym
->st_name
= name_offset
;
102 sym
->st_value
= value
;
105 sym
->st_other
= other
;
106 sym
->st_shndx
= shndx
;
107 sym_index
= sym
- (ElfW(Sym
) *)s
->data
;
111 ptr
= section_ptr_add(hs
, sizeof(int));
112 base
= (int *)hs
->data
;
113 /* only add global or weak symbols */
114 if (ELFW(ST_BIND
)(info
) != STB_LOCAL
) {
115 /* add another hashing entry */
117 h
= elf_hash(name
) % nbuckets
;
119 base
[2 + h
] = sym_index
;
121 /* we resize the hash table */
122 hs
->nb_hashed_syms
++;
123 if (hs
->nb_hashed_syms
> 2 * nbuckets
) {
124 rebuild_hash(s
, 2 * nbuckets
);
134 /* find global ELF symbol 'name' and return its index. Return 0 if not
136 ST_FUNC
int find_elf_sym(Section
*s
, const char *name
)
140 int nbuckets
, sym_index
, h
;
146 nbuckets
= ((int *)hs
->data
)[0];
147 h
= elf_hash(name
) % nbuckets
;
148 sym_index
= ((int *)hs
->data
)[2 + h
];
149 while (sym_index
!= 0) {
150 sym
= &((ElfW(Sym
) *)s
->data
)[sym_index
];
151 name1
= s
->link
->data
+ sym
->st_name
;
152 if (!strcmp(name
, name1
))
154 sym_index
= ((int *)hs
->data
)[2 + nbuckets
+ sym_index
];
159 /* return elf symbol value, signal error if 'err' is nonzero */
160 static void *get_elf_sym_addr(TCCState
*s
, const char *name
, int err
)
165 sym_index
= find_elf_sym(s
->symtab
, name
);
166 sym
= &((ElfW(Sym
) *)s
->symtab
->data
)[sym_index
];
167 if (!sym_index
|| sym
->st_shndx
== SHN_UNDEF
) {
169 tcc_error("%s not defined", name
);
172 return (void*)(uplong
)sym
->st_value
;
175 /* return elf symbol value */
176 LIBTCCAPI
void *tcc_get_symbol(TCCState
*s
, const char *name
)
178 return get_elf_sym_addr(s
, name
, 0);
181 /* return elf symbol value or error */
182 ST_FUNC
void *tcc_get_symbol_err(TCCState
*s
, const char *name
)
184 return get_elf_sym_addr(s
, name
, 1);
187 /* add an elf symbol : check if it is already defined and patch
188 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
189 ST_FUNC
int add_elf_sym(Section
*s
, uplong value
, unsigned long size
,
190 int info
, int other
, int sh_num
, const char *name
)
193 int sym_bind
, sym_index
, sym_type
, esym_bind
;
194 unsigned char sym_vis
, esym_vis
, new_vis
;
196 sym_bind
= ELFW(ST_BIND
)(info
);
197 sym_type
= ELFW(ST_TYPE
)(info
);
198 sym_vis
= ELFW(ST_VISIBILITY
)(other
);
200 if (sym_bind
!= STB_LOCAL
) {
201 /* we search global or weak symbols */
202 sym_index
= find_elf_sym(s
, name
);
205 esym
= &((ElfW(Sym
) *)s
->data
)[sym_index
];
206 if (esym
->st_shndx
!= SHN_UNDEF
) {
207 esym_bind
= ELFW(ST_BIND
)(esym
->st_info
);
208 /* propagate the most constraining visibility */
209 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
210 esym_vis
= ELFW(ST_VISIBILITY
)(esym
->st_other
);
211 if (esym_vis
== STV_DEFAULT
) {
213 } else if (sym_vis
== STV_DEFAULT
) {
216 new_vis
= (esym_vis
< sym_vis
) ? esym_vis
: sym_vis
;
218 esym
->st_other
= (esym
->st_other
& ~ELFW(ST_VISIBILITY
)(-1))
220 other
= esym
->st_other
; /* in case we have to patch esym */
221 if (sh_num
== SHN_UNDEF
) {
222 /* ignore adding of undefined symbol if the
223 corresponding symbol is already defined */
224 } else if (sym_bind
== STB_GLOBAL
&& esym_bind
== STB_WEAK
) {
225 /* global overrides weak, so patch */
227 } else if (sym_bind
== STB_WEAK
&& esym_bind
== STB_GLOBAL
) {
228 /* weak is ignored if already global */
229 } else if (sym_bind
== STB_WEAK
&& esym_bind
== STB_WEAK
) {
230 /* keep first-found weak definition, ignore subsequents */
231 } else if (sym_vis
== STV_HIDDEN
|| sym_vis
== STV_INTERNAL
) {
232 /* ignore hidden symbols after */
233 } else if (esym
->st_shndx
== SHN_COMMON
234 && (sh_num
< SHN_LORESERVE
|| sh_num
== SHN_COMMON
)) {
235 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
236 No idea if this is the correct solution ... */
238 } else if (s
== tcc_state
->dynsymtab_section
) {
239 /* we accept that two DLL define the same symbol */
242 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
243 sym_bind
, sh_num
, new_vis
, esym_bind
, esym
->st_shndx
, esym_vis
);
245 tcc_error_noabort("'%s' defined twice", name
);
249 esym
->st_info
= ELFW(ST_INFO
)(sym_bind
, sym_type
);
250 esym
->st_shndx
= sh_num
;
252 esym
->st_value
= value
;
253 esym
->st_size
= size
;
254 esym
->st_other
= other
;
258 sym_index
= put_elf_sym(s
, value
, size
,
259 ELFW(ST_INFO
)(sym_bind
, sym_type
), other
,
266 ST_FUNC
void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
267 int type
, int symbol
)
275 /* if no relocation section, create it */
276 snprintf(buf
, sizeof(buf
), REL_SECTION_FMT
, s
->name
);
277 /* if the symtab is allocated, then we consider the relocation
279 sr
= new_section(tcc_state
, buf
, SHT_RELX
, symtab
->sh_flags
);
280 sr
->sh_entsize
= sizeof(ElfW_Rel
);
282 sr
->sh_info
= s
->sh_num
;
285 rel
= section_ptr_add(sr
, sizeof(ElfW_Rel
));
286 rel
->r_offset
= offset
;
287 rel
->r_info
= ELFW(R_INFO
)(symbol
, type
);
288 #ifdef TCC_TARGET_X86_64
293 /* put stab debug information */
295 ST_FUNC
void put_stabs(const char *str
, int type
, int other
, int desc
,
300 sym
= section_ptr_add(stab_section
, sizeof(Stab_Sym
));
302 sym
->n_strx
= put_elf_str(stabstr_section
, str
);
307 sym
->n_other
= other
;
309 sym
->n_value
= value
;
312 ST_FUNC
void put_stabs_r(const char *str
, int type
, int other
, int desc
,
313 unsigned long value
, Section
*sec
, int sym_index
)
315 put_stabs(str
, type
, other
, desc
, value
);
316 put_elf_reloc(symtab_section
, stab_section
,
317 stab_section
->data_offset
- sizeof(unsigned int),
318 R_DATA_32
, sym_index
);
321 ST_FUNC
void put_stabn(int type
, int other
, int desc
, int value
)
323 put_stabs(NULL
, type
, other
, desc
, value
);
326 ST_FUNC
void put_stabd(int type
, int other
, int desc
)
328 put_stabs(NULL
, type
, other
, desc
, 0);
331 /* In an ELF file symbol table, the local symbols must appear below
332 the global and weak ones. Since TCC cannot sort it while generating
333 the code, we must do it after. All the relocation tables are also
334 modified to take into account the symbol table sorting */
335 static void sort_syms(TCCState
*s1
, Section
*s
)
337 int *old_to_new_syms
;
341 ElfW_Rel
*rel
, *rel_end
;
345 nb_syms
= s
->data_offset
/ sizeof(ElfW(Sym
));
346 new_syms
= tcc_malloc(nb_syms
* sizeof(ElfW(Sym
)));
347 old_to_new_syms
= tcc_malloc(nb_syms
* sizeof(int));
349 /* first pass for local symbols */
350 p
= (ElfW(Sym
) *)s
->data
;
352 for(i
= 0; i
< nb_syms
; i
++) {
353 if (ELFW(ST_BIND
)(p
->st_info
) == STB_LOCAL
) {
354 old_to_new_syms
[i
] = q
- new_syms
;
359 /* save the number of local symbols in section header */
360 s
->sh_info
= q
- new_syms
;
362 /* then second pass for non local symbols */
363 p
= (ElfW(Sym
) *)s
->data
;
364 for(i
= 0; i
< nb_syms
; i
++) {
365 if (ELFW(ST_BIND
)(p
->st_info
) != STB_LOCAL
) {
366 old_to_new_syms
[i
] = q
- new_syms
;
372 /* we copy the new symbols to the old */
373 memcpy(s
->data
, new_syms
, nb_syms
* sizeof(ElfW(Sym
)));
376 /* now we modify all the relocations */
377 for(i
= 1; i
< s1
->nb_sections
; i
++) {
378 sr
= s1
->sections
[i
];
379 if (sr
->sh_type
== SHT_RELX
&& sr
->link
== s
) {
380 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
381 for(rel
= (ElfW_Rel
*)sr
->data
;
384 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
385 type
= ELFW(R_TYPE
)(rel
->r_info
);
386 sym_index
= old_to_new_syms
[sym_index
];
387 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
392 tcc_free(old_to_new_syms
);
395 /* relocate common symbols in the .bss section */
396 ST_FUNC
void relocate_common_syms(void)
398 ElfW(Sym
) *sym
, *sym_end
;
399 unsigned long offset
, align
;
401 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+ symtab_section
->data_offset
);
402 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
405 if (sym
->st_shndx
== SHN_COMMON
) {
407 align
= sym
->st_value
;
408 offset
= bss_section
->data_offset
;
409 offset
= (offset
+ align
- 1) & -align
;
410 sym
->st_value
= offset
;
411 sym
->st_shndx
= bss_section
->sh_num
;
412 offset
+= sym
->st_size
;
413 bss_section
->data_offset
= offset
;
418 /* relocate symbol table, resolve undefined symbols if do_resolve is
419 true and output error if undefined symbol. */
420 ST_FUNC
void relocate_syms(TCCState
*s1
, int do_resolve
)
422 ElfW(Sym
) *sym
, *esym
, *sym_end
;
423 int sym_bind
, sh_num
, sym_index
;
426 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+ symtab_section
->data_offset
);
427 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
430 sh_num
= sym
->st_shndx
;
431 if (sh_num
== SHN_UNDEF
) {
432 name
= strtab_section
->data
+ sym
->st_name
;
434 #if !defined TCC_TARGET_PE || !defined _WIN32
436 name
= symtab_section
->link
->data
+ sym
->st_name
;
437 addr
= resolve_sym(s1
, name
);
439 sym
->st_value
= (uplong
)addr
;
443 } else if (s1
->dynsym
) {
444 /* if dynamic symbol exist, then use it */
445 sym_index
= find_elf_sym(s1
->dynsym
, name
);
447 esym
= &((ElfW(Sym
) *)s1
->dynsym
->data
)[sym_index
];
448 sym
->st_value
= esym
->st_value
;
452 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
454 if (!strcmp(name
, "_fp_hw"))
456 /* only weak symbols are accepted to be undefined. Their
458 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
459 if (sym_bind
== STB_WEAK
) {
462 tcc_error_noabort("undefined symbol '%s'", name
);
464 } else if (sh_num
< SHN_LORESERVE
) {
465 /* add section base */
466 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
472 #ifndef TCC_TARGET_PE
473 #ifdef TCC_TARGET_X86_64
474 #define JMP_TABLE_ENTRY_SIZE 14
475 static uplong
add_jmp_table(TCCState
*s1
, uplong val
)
477 char *p
= s1
->runtime_plt_and_got
+ s1
->runtime_plt_and_got_offset
;
478 s1
->runtime_plt_and_got_offset
+= JMP_TABLE_ENTRY_SIZE
;
483 *(uplong
*)(p
+ 6) = val
;
487 static uplong
add_got_table(TCCState
*s1
, uplong val
)
489 uplong
*p
= (uplong
*)(s1
->runtime_plt_and_got
+ s1
->runtime_plt_and_got_offset
);
490 s1
->runtime_plt_and_got_offset
+= sizeof(uplong
);
494 #elif defined TCC_TARGET_ARM
495 #define JMP_TABLE_ENTRY_SIZE 8
496 static uplong
add_jmp_table(TCCState
*s1
, int val
)
498 uint32_t *p
= (uint32_t *)(s1
->runtime_plt_and_got
+ s1
->runtime_plt_and_got_offset
);
499 s1
->runtime_plt_and_got_offset
+= JMP_TABLE_ENTRY_SIZE
;
500 /* ldr pc, [pc, #-4] */
508 /* relocate a given section (CPU dependent) */
509 ST_FUNC
void relocate_section(TCCState
*s1
, Section
*s
)
512 ElfW_Rel
*rel
, *rel_end
, *qrel
;
517 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
522 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
523 qrel
= (ElfW_Rel
*)sr
->data
;
527 ptr
= s
->data
+ rel
->r_offset
;
529 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
530 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
532 #ifdef TCC_TARGET_X86_64
533 val
+= rel
->r_addend
;
535 type
= ELFW(R_TYPE
)(rel
->r_info
);
536 addr
= s
->sh_addr
+ rel
->r_offset
;
540 #if defined(TCC_TARGET_I386)
542 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
543 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
544 qrel
->r_offset
= rel
->r_offset
;
546 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_386_32
);
550 qrel
->r_info
= ELFW(R_INFO
)(0, R_386_RELATIVE
);
557 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
559 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
561 qrel
->r_offset
= rel
->r_offset
;
562 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_386_PC32
);
567 *(int *)ptr
+= val
- addr
;
570 *(int *)ptr
+= val
- addr
;
577 *(int *)ptr
+= s1
->got
->sh_addr
- addr
;
580 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
583 /* we load the got offset */
584 *(int *)ptr
+= s1
->got_offsets
[sym_index
];
587 if (s1
->output_format
!= TCC_OUTPUT_FORMAT_BINARY
) {
589 tcc_error("can only produce 16-bit binary files");
591 *(short *)ptr
+= val
;
594 if (s1
->output_format
!= TCC_OUTPUT_FORMAT_BINARY
)
596 *(short *)ptr
+= val
- addr
;
598 #elif defined(TCC_TARGET_ARM)
604 int x
, is_thumb
, is_call
, h
;
605 x
= (*(int *)ptr
)&0xffffff;
606 (*(int *)ptr
) &= 0xff000000;
611 is_call
= (type
== R_ARM_CALL
);
612 x
+= (val
& -2) - addr
;
614 #ifndef TCC_TARGET_PE
615 if((x
& 3) != 0 || x
>= 0x4000000 || x
< -0x4000000)
616 if (s1
->output_type
== TCC_OUTPUT_MEMORY
)
617 x
+= add_jmp_table(s1
, val
) - val
; /* add veneer */
619 if((x
& 3) != 0 || x
>= 0x4000000 || x
< -0x4000000)
620 if (!(h
&& is_call
&& is_thumb
))
621 tcc_error("can't relocate value at %x",addr
);
624 if (is_call
&& is_thumb
) {
626 (*(int *)ptr
) = 0xfa << 24; /* bl -> blx */
632 case R_ARM_MOVW_ABS_NC
:
635 if (type
== R_ARM_MOVT_ABS
)
638 imm4
= (val
>> 12) & 0xf;
639 x
= (imm4
<< 16) | imm12
;
640 if (type
== R_ARM_THM_MOVT_ABS
)
646 case R_ARM_THM_MOVT_ABS
:
647 case R_ARM_THM_MOVW_ABS_NC
:
649 int x
, i
, imm4
, imm3
, imm8
;
650 if (type
== R_ARM_THM_MOVT_ABS
)
653 imm3
= (val
>> 8) & 0x7;
655 imm4
= (val
>> 12) & 0xf;
656 x
= (imm3
<< 28) | (imm8
<< 16) | (i
<< 10) | imm4
;
657 if (type
== R_ARM_THM_MOVT_ABS
)
666 x
= (*(int *)ptr
) & 0x7fffffff;
667 (*(int *)ptr
) &= 0x80000000;
670 if((x
^(x
>>1))&0x40000000)
671 tcc_error("can't relocate value at %x",addr
);
672 (*(int *)ptr
) |= x
& 0x7fffffff;
678 *(int *)ptr
+= val
- addr
;
680 case R_ARM_BASE_PREL
:
681 *(int *)ptr
+= s1
->got
->sh_addr
- addr
;
684 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
687 /* we load the got offset */
688 *(int *)ptr
+= s1
->got_offsets
[sym_index
];
693 /* trade Thumb support for ARMv4 support */
694 if ((0x0ffffff0 & *(int*)ptr
) == 0x012FFF10)
695 *(int*)ptr
^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
698 fprintf(stderr
,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
699 type
, (unsigned)addr
, (unsigned)(uplong
)ptr
, (unsigned)val
);
701 #elif defined(TCC_TARGET_C67)
709 /* put the low 16 bits of the absolute address */
710 // add to what is already there
712 orig
= ((*(int *)(ptr
)) >> 7) & 0xffff;
713 orig
|= (((*(int *)(ptr
+4)) >> 7) & 0xffff) << 16;
715 //patch both at once - assumes always in pairs Low - High
717 *(int *) ptr
= (*(int *) ptr
& (~(0xffff << 7)) ) | (((val
+orig
) & 0xffff) << 7);
718 *(int *)(ptr
+4) = (*(int *)(ptr
+4) & (~(0xffff << 7)) ) | ((((val
+orig
)>>16) & 0xffff) << 7);
724 fprintf(stderr
,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
725 type
, (unsigned)addr
, (unsigned)(uplong
)ptr
, (unsigned)val
);
727 #elif defined(TCC_TARGET_X86_64)
729 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
730 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
731 qrel
->r_addend
= *(long long *)ptr
+ val
;
734 *(long long *)ptr
+= val
;
738 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
739 /* XXX: this logic may depend on TCC's codegen
740 now TCC uses R_X86_64_32 even for a 64bit pointer */
741 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
742 qrel
->r_addend
= *(int *)ptr
+ val
;
749 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
751 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
753 qrel
->r_offset
= rel
->r_offset
;
754 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_X86_64_PC32
);
755 qrel
->r_addend
= *(int *)ptr
;
761 case R_X86_64_PLT32
: {
763 diff
= (long long)val
- addr
;
764 if (diff
<= -2147483647 || diff
> 2147483647) {
765 #ifndef TCC_TARGET_PE
766 /* XXX: naive support for over 32bit jump */
767 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
768 val
= (add_jmp_table(s1
, val
- rel
->r_addend
) +
773 if (diff
<= -2147483647 || diff
> 2147483647) {
774 tcc_error("internal error: relocation failed");
780 case R_X86_64_GLOB_DAT
:
781 case R_X86_64_JUMP_SLOT
:
782 /* They don't need addend */
783 *(int *)ptr
= val
- rel
->r_addend
;
785 case R_X86_64_GOTPCREL
:
786 #ifndef TCC_TARGET_PE
787 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
788 val
= add_got_table(s1
, val
- rel
->r_addend
) + rel
->r_addend
;
789 *(int *)ptr
+= val
- addr
;
793 *(int *)ptr
+= (s1
->got
->sh_addr
- addr
+
794 s1
->got_offsets
[sym_index
] - 4);
796 case R_X86_64_GOTTPOFF
:
797 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
800 /* we load the got offset */
801 *(int *)ptr
+= s1
->got_offsets
[sym_index
];
804 #error unsupported processor
808 /* if the relocation is allocated, we change its symbol table */
809 if (sr
->sh_flags
& SHF_ALLOC
)
810 sr
->link
= s1
->dynsym
;
813 /* relocate relocation table in 'sr' */
814 static void relocate_rel(TCCState
*s1
, Section
*sr
)
817 ElfW_Rel
*rel
, *rel_end
;
819 s
= s1
->sections
[sr
->sh_info
];
820 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
821 for(rel
= (ElfW_Rel
*)sr
->data
;
824 rel
->r_offset
+= s
->sh_addr
;
828 /* count the number of dynamic relocations so that we can reserve
830 static int prepare_dynamic_rel(TCCState
*s1
, Section
*sr
)
832 ElfW_Rel
*rel
, *rel_end
;
833 int sym_index
, esym_index
, type
, count
;
836 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
837 for(rel
= (ElfW_Rel
*)sr
->data
; rel
< rel_end
; rel
++) {
838 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
839 type
= ELFW(R_TYPE
)(rel
->r_info
);
841 #if defined(TCC_TARGET_I386)
843 #elif defined(TCC_TARGET_X86_64)
850 #if defined(TCC_TARGET_I386)
852 #elif defined(TCC_TARGET_X86_64)
855 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
864 /* allocate the section */
865 sr
->sh_flags
|= SHF_ALLOC
;
866 sr
->sh_size
= count
* sizeof(ElfW_Rel
);
871 static void put_got_offset(TCCState
*s1
, int index
, unsigned long val
)
876 if (index
>= s1
->nb_got_offsets
) {
877 /* find immediately bigger power of 2 and reallocate array */
881 tab
= tcc_realloc(s1
->got_offsets
, n
* sizeof(unsigned long));
882 s1
->got_offsets
= tab
;
883 memset(s1
->got_offsets
+ s1
->nb_got_offsets
, 0,
884 (n
- s1
->nb_got_offsets
) * sizeof(unsigned long));
885 s1
->nb_got_offsets
= n
;
887 s1
->got_offsets
[index
] = val
;
890 /* XXX: suppress that */
891 static void put32(unsigned char *p
, uint32_t val
)
899 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
900 defined(TCC_TARGET_X86_64)
901 static uint32_t get32(unsigned char *p
)
903 return p
[0] | (p
[1] << 8) | (p
[2] << 16) | (p
[3] << 24);
907 static void build_got(TCCState
*s1
)
911 /* if no got, then create it */
912 s1
->got
= new_section(s1
, ".got", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
913 s1
->got
->sh_entsize
= 4;
914 add_elf_sym(symtab_section
, 0, 4, ELFW(ST_INFO
)(STB_GLOBAL
, STT_OBJECT
),
915 0, s1
->got
->sh_num
, "_GLOBAL_OFFSET_TABLE_");
916 ptr
= section_ptr_add(s1
->got
, 3 * PTR_SIZE
);
918 /* keep space for _DYNAMIC pointer, if present */
920 /* two dummy got entries */
924 /* keep space for _DYNAMIC pointer, if present */
927 /* two dummy got entries */
935 /* put a got entry corresponding to a symbol in symtab_section. 'size'
936 and 'info' can be modifed if more precise info comes from the DLL */
937 static void put_got_entry(TCCState
*s1
,
938 int reloc_type
, unsigned long size
, int info
,
944 unsigned long offset
;
950 /* if a got entry already exists for that symbol, no need to add one */
951 if (sym_index
< s1
->nb_got_offsets
&&
952 s1
->got_offsets
[sym_index
] != 0)
955 put_got_offset(s1
, sym_index
, s1
->got
->data_offset
);
958 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
959 name
= symtab_section
->link
->data
+ sym
->st_name
;
960 offset
= sym
->st_value
;
961 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
963 #ifdef TCC_TARGET_X86_64
973 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
976 /* if we build a DLL, we add a %ebx offset */
977 if (s1
->output_type
== TCC_OUTPUT_DLL
)
983 /* add a PLT entry */
985 if (plt
->data_offset
== 0) {
986 /* first plt entry */
987 p
= section_ptr_add(plt
, 16);
988 p
[0] = 0xff; /* pushl got + PTR_SIZE */
990 put32(p
+ 2, PTR_SIZE
);
991 p
[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
993 put32(p
+ 8, PTR_SIZE
* 2);
996 p
= section_ptr_add(plt
, 16);
997 p
[0] = 0xff; /* jmp *(got + x) */
999 put32(p
+ 2, s1
->got
->data_offset
);
1000 p
[6] = 0x68; /* push $xxx */
1001 put32(p
+ 7, (plt
->data_offset
- 32) >> 1);
1002 p
[11] = 0xe9; /* jmp plt_start */
1003 put32(p
+ 12, -(plt
->data_offset
));
1005 /* the symbol is modified so that it will be relocated to
1007 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
1008 if (s1
->output_type
== TCC_OUTPUT_EXE
)
1010 offset
= plt
->data_offset
- 16;
1012 #elif defined(TCC_TARGET_ARM)
1013 if (reloc_type
== R_ARM_JUMP_SLOT
) {
1017 /* if we build a DLL, we add a %ebx offset */
1018 if (s1
->output_type
== TCC_OUTPUT_DLL
)
1019 tcc_error("DLLs unimplemented!");
1021 /* add a PLT entry */
1023 if (plt
->data_offset
== 0) {
1024 /* first plt entry */
1025 p
= section_ptr_add(plt
, 16);
1026 put32(p
, 0xe52de004);
1027 put32(p
+ 4, 0xe59fe010);
1028 put32(p
+ 8, 0xe08fe00e);
1029 put32(p
+ 12, 0xe5bef008);
1032 p
= section_ptr_add(plt
, 16);
1033 put32(p
, 0xe59fc004);
1034 put32(p
+4, 0xe08fc00c);
1035 put32(p
+8, 0xe59cf000);
1036 put32(p
+12, s1
->got
->data_offset
);
1038 /* the symbol is modified so that it will be relocated to
1040 if (s1
->output_type
== TCC_OUTPUT_EXE
)
1041 offset
= plt
->data_offset
- 16;
1043 #elif defined(TCC_TARGET_C67)
1044 tcc_error("C67 got not implemented");
1046 #error unsupported CPU
1048 index
= put_elf_sym(s1
->dynsym
, offset
,
1049 size
, info
, 0, sym
->st_shndx
, name
);
1050 /* put a got entry */
1051 put_elf_reloc(s1
->dynsym
, s1
->got
,
1052 s1
->got
->data_offset
,
1055 ptr
= section_ptr_add(s1
->got
, PTR_SIZE
);
1059 /* build GOT and PLT entries */
1060 ST_FUNC
void build_got_entries(TCCState
*s1
)
1063 ElfW_Rel
*rel
, *rel_end
;
1065 int i
, type
, reloc_type
, sym_index
;
1067 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1068 s
= s1
->sections
[i
];
1069 if (s
->sh_type
!= SHT_RELX
)
1071 /* no need to handle got relocations */
1072 if (s
->link
!= symtab_section
)
1074 rel_end
= (ElfW_Rel
*)(s
->data
+ s
->data_offset
);
1075 for(rel
= (ElfW_Rel
*)s
->data
;
1078 type
= ELFW(R_TYPE
)(rel
->r_info
);
1080 #if defined(TCC_TARGET_I386)
1087 if (type
== R_386_GOT32
|| type
== R_386_PLT32
) {
1088 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1089 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1090 /* look at the symbol got offset. If none, then add one */
1091 if (type
== R_386_GOT32
)
1092 reloc_type
= R_386_GLOB_DAT
;
1094 reloc_type
= R_386_JMP_SLOT
;
1095 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1099 #elif defined(TCC_TARGET_ARM)
1100 case R_ARM_GOT_BREL
:
1101 case R_ARM_GOTOFF32
:
1102 case R_ARM_BASE_PREL
:
1106 if (type
== R_ARM_GOT_BREL
|| type
== R_ARM_PLT32
) {
1107 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1108 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1109 /* look at the symbol got offset. If none, then add one */
1110 if (type
== R_ARM_GOT_BREL
)
1111 reloc_type
= R_ARM_GLOB_DAT
;
1113 reloc_type
= R_ARM_JUMP_SLOT
;
1114 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1118 #elif defined(TCC_TARGET_C67)
1125 if (type
== R_C60_GOT32
|| type
== R_C60_PLT32
) {
1126 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1127 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1128 /* look at the symbol got offset. If none, then add one */
1129 if (type
== R_C60_GOT32
)
1130 reloc_type
= R_C60_GLOB_DAT
;
1132 reloc_type
= R_C60_JMP_SLOT
;
1133 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1137 #elif defined(TCC_TARGET_X86_64)
1138 case R_X86_64_GOT32
:
1139 case R_X86_64_GOTTPOFF
:
1140 case R_X86_64_GOTPCREL
:
1141 case R_X86_64_PLT32
:
1144 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
||
1145 type
== R_X86_64_PLT32
) {
1146 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1147 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1148 /* look at the symbol got offset. If none, then add one */
1149 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
)
1150 reloc_type
= R_X86_64_GLOB_DAT
;
1152 reloc_type
= R_X86_64_JUMP_SLOT
;
1153 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1158 #error unsupported CPU
1167 ST_FUNC Section
*new_symtab(TCCState
*s1
,
1168 const char *symtab_name
, int sh_type
, int sh_flags
,
1169 const char *strtab_name
,
1170 const char *hash_name
, int hash_sh_flags
)
1172 Section
*symtab
, *strtab
, *hash
;
1173 int *ptr
, nb_buckets
;
1175 symtab
= new_section(s1
, symtab_name
, sh_type
, sh_flags
);
1176 symtab
->sh_entsize
= sizeof(ElfW(Sym
));
1177 strtab
= new_section(s1
, strtab_name
, SHT_STRTAB
, sh_flags
);
1178 put_elf_str(strtab
, "");
1179 symtab
->link
= strtab
;
1180 put_elf_sym(symtab
, 0, 0, 0, 0, 0, NULL
);
1184 hash
= new_section(s1
, hash_name
, SHT_HASH
, hash_sh_flags
);
1185 hash
->sh_entsize
= sizeof(int);
1186 symtab
->hash
= hash
;
1187 hash
->link
= symtab
;
1189 ptr
= section_ptr_add(hash
, (2 + nb_buckets
+ 1) * sizeof(int));
1190 ptr
[0] = nb_buckets
;
1192 memset(ptr
+ 2, 0, (nb_buckets
+ 1) * sizeof(int));
1196 /* put dynamic tag */
1197 static void put_dt(Section
*dynamic
, int dt
, uplong val
)
1200 dyn
= section_ptr_add(dynamic
, sizeof(ElfW(Dyn
)));
1202 dyn
->d_un
.d_val
= val
;
1205 static void add_init_array_defines(TCCState
*s1
, const char *section_name
)
1209 char sym_start
[1024];
1212 snprintf(sym_start
, sizeof(sym_start
), "__%s_start", section_name
+ 1);
1213 snprintf(sym_end
, sizeof(sym_end
), "__%s_end", section_name
+ 1);
1215 s
= find_section(s1
, section_name
);
1220 end_offset
= s
->data_offset
;
1223 add_elf_sym(symtab_section
,
1225 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1226 s
->sh_num
, sym_start
);
1227 add_elf_sym(symtab_section
,
1229 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1230 s
->sh_num
, sym_end
);
1233 static int tcc_add_support(TCCState
*s1
, const char *filename
)
1236 snprintf(buf
, sizeof(buf
), "%s/%s", s1
->tcc_lib_path
, filename
);
1237 return tcc_add_file(s1
, buf
);
1240 ST_FUNC
void tcc_add_bcheck(TCCState
*s1
)
1242 #ifdef CONFIG_TCC_BCHECK
1244 Section
*init_section
;
1245 unsigned char *pinit
;
1248 if (0 == s1
->do_bounds_check
)
1251 /* XXX: add an object file to do that */
1252 ptr
= section_ptr_add(bounds_section
, sizeof(unsigned long));
1254 add_elf_sym(symtab_section
, 0, 0,
1255 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1256 bounds_section
->sh_num
, "__bounds_start");
1257 /* add bound check code */
1258 #ifndef TCC_TARGET_PE
1259 tcc_add_support(s1
, "bcheck.o");
1261 #ifdef TCC_TARGET_I386
1262 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
) {
1263 /* add 'call __bound_init()' in .init section */
1264 init_section
= find_section(s1
, ".init");
1265 pinit
= section_ptr_add(init_section
, 5);
1267 put32(pinit
+ 1, -4);
1268 sym_index
= find_elf_sym(symtab_section
, "__bound_init");
1269 put_elf_reloc(symtab_section
, init_section
,
1270 init_section
->data_offset
- 4, R_386_PC32
, sym_index
);
1276 /* add tcc runtime libraries */
1277 ST_FUNC
void tcc_add_runtime(TCCState
*s1
)
1282 if (!s1
->nostdlib
) {
1283 tcc_add_library(s1
, "c");
1284 #ifdef CONFIG_USE_LIBGCC
1285 tcc_add_file(s1
, TCC_LIBGCC
);
1286 #elif !defined WITHOUT_LIBTCC
1287 tcc_add_support(s1
, "libtcc1.a");
1289 /* add crt end if not memory output */
1290 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
)
1291 tcc_add_crt(s1
, "crtn.o");
1295 /* add various standard linker symbols (must be done after the
1296 sections are filled (for example after allocating common
1298 ST_FUNC
void tcc_add_linker_symbols(TCCState
*s1
)
1304 add_elf_sym(symtab_section
,
1305 text_section
->data_offset
, 0,
1306 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1307 text_section
->sh_num
, "_etext");
1308 add_elf_sym(symtab_section
,
1309 data_section
->data_offset
, 0,
1310 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1311 data_section
->sh_num
, "_edata");
1312 add_elf_sym(symtab_section
,
1313 bss_section
->data_offset
, 0,
1314 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1315 bss_section
->sh_num
, "_end");
1316 /* horrible new standard ldscript defines */
1317 add_init_array_defines(s1
, ".preinit_array");
1318 add_init_array_defines(s1
, ".init_array");
1319 add_init_array_defines(s1
, ".fini_array");
1321 /* add start and stop symbols for sections whose name can be
1323 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1324 s
= s1
->sections
[i
];
1325 if (s
->sh_type
== SHT_PROGBITS
&&
1326 (s
->sh_flags
& SHF_ALLOC
)) {
1330 /* check if section name can be expressed in C */
1336 if (!isid(ch
) && !isnum(ch
))
1340 snprintf(buf
, sizeof(buf
), "__start_%s", s
->name
);
1341 add_elf_sym(symtab_section
,
1343 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1345 snprintf(buf
, sizeof(buf
), "__stop_%s", s
->name
);
1346 add_elf_sym(symtab_section
,
1348 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1355 static void tcc_output_binary(TCCState
*s1
, FILE *f
,
1356 const int *section_order
)
1359 int i
, offset
, size
;
1362 for(i
=1;i
<s1
->nb_sections
;i
++) {
1363 s
= s1
->sections
[section_order
[i
]];
1364 if (s
->sh_type
!= SHT_NOBITS
&&
1365 (s
->sh_flags
& SHF_ALLOC
)) {
1366 while (offset
< s
->sh_offset
) {
1371 fwrite(s
->data
, 1, size
, f
);
1377 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1379 #define EXTRA_RELITEMS 14
1381 /* move the relocation value from .dynsym to .got */
1382 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1384 uint32_t *gotd
= (void *)s1
->got
->data
;
1385 ElfW(Sym
) *sym
, *sym_end
;
1387 gotd
+= 3; // dummy entries in .got
1388 /* relocate symbols in .dynsym */
1389 sym_end
= (ElfW(Sym
) *)(s
->data
+ s
->data_offset
);
1390 for (sym
= (ElfW(Sym
) *)s
->data
+ 1; sym
< sym_end
; sym
++) {
1391 if (sym
->st_shndx
== SHN_UNDEF
) {
1392 *gotd
++ = sym
->st_value
+ 6; // XXX 6 is magic ?
1399 #define EXTRA_RELITEMS 9
1401 /* zero plt offsets of weak symbols in .dynsym */
1402 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1404 ElfW(Sym
) *sym
, *sym_end
;
1406 sym_end
= (ElfW(Sym
) *)(s
->data
+ s
->data_offset
);
1407 for (sym
= (ElfW(Sym
) *)s
->data
+ 1; sym
< sym_end
; sym
++)
1408 if (sym
->st_shndx
== SHN_UNDEF
&& ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
1413 ST_FUNC
void fill_got_entry(TCCState
*s1
, ElfW_Rel
*rel
)
1415 int sym_index
= ELFW(R_SYM
) (rel
->r_info
);
1416 ElfW(Sym
) *sym
= &((ElfW(Sym
) *) symtab_section
->data
)[sym_index
];
1417 unsigned long offset
;
1419 if (sym_index
>= s1
->nb_got_offsets
)
1421 offset
= s1
->got_offsets
[sym_index
];
1422 section_reserve(s1
->got
, offset
+ PTR_SIZE
);
1423 #ifdef TCC_TARGET_X86_64
1424 /* only works for x86-64 */
1425 put32(s1
->got
->data
+ offset
+ 4, sym
->st_value
>> 32);
1427 put32(s1
->got
->data
+ offset
, sym
->st_value
& 0xffffffff);
1430 ST_FUNC
void fill_got(TCCState
*s1
)
1433 ElfW_Rel
*rel
, *rel_end
;
1436 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1437 s
= s1
->sections
[i
];
1438 if (s
->sh_type
!= SHT_RELX
)
1440 /* no need to handle got relocations */
1441 if (s
->link
!= symtab_section
)
1443 rel_end
= (ElfW_Rel
*) (s
->data
+ s
->data_offset
);
1444 for(rel
= (ElfW_Rel
*) s
->data
; rel
< rel_end
; rel
++) {
1445 switch (ELFW(R_TYPE
) (rel
->r_info
)) {
1446 case R_X86_64_GOT32
:
1447 case R_X86_64_GOTPCREL
:
1448 case R_X86_64_PLT32
:
1449 fill_got_entry(s1
, rel
);
1457 /* output an ELF file */
1458 /* XXX: suppress unneeded sections */
1459 static int elf_output_file(TCCState
*s1
, const char *filename
)
1465 int shnum
, i
, phnum
, file_offset
, offset
, size
, j
, sh_order_index
, k
;
1468 Section
*strsec
, *s
;
1469 ElfW(Shdr
) shdr
, *sh
;
1470 ElfW(Phdr
) *phdr
, *ph
;
1471 Section
*interp
, *dynamic
, *dynstr
;
1472 unsigned long saved_dynamic_data_offset
;
1474 int type
, file_type
;
1475 uplong rel_addr
, rel_size
;
1476 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1477 uplong bss_addr
, bss_size
;
1480 file_type
= s1
->output_type
;
1483 if (file_type
!= TCC_OUTPUT_OBJ
) {
1484 tcc_add_runtime(s1
);
1488 section_order
= NULL
;
1491 dynstr
= NULL
; /* avoid warning */
1492 saved_dynamic_data_offset
= 0; /* avoid warning */
1494 if (file_type
!= TCC_OUTPUT_OBJ
) {
1495 relocate_common_syms();
1497 tcc_add_linker_symbols(s1
);
1499 if (!s1
->static_link
) {
1501 int sym_index
, index
;
1502 ElfW(Sym
) *esym
, *sym_end
;
1504 if (file_type
== TCC_OUTPUT_EXE
) {
1506 /* allow override the dynamic loader */
1507 const char *elfint
= getenv("LD_SO");
1509 elfint
= CONFIG_TCC_ELFINTERP
;
1510 /* add interpreter section only if executable */
1511 interp
= new_section(s1
, ".interp", SHT_PROGBITS
, SHF_ALLOC
);
1512 interp
->sh_addralign
= 1;
1513 ptr
= section_ptr_add(interp
, 1+strlen(elfint
));
1514 strcpy(ptr
, elfint
);
1517 /* add dynamic symbol table */
1518 s1
->dynsym
= new_symtab(s1
, ".dynsym", SHT_DYNSYM
, SHF_ALLOC
,
1520 ".hash", SHF_ALLOC
);
1521 dynstr
= s1
->dynsym
->link
;
1523 /* add dynamic section */
1524 dynamic
= new_section(s1
, ".dynamic", SHT_DYNAMIC
,
1525 SHF_ALLOC
| SHF_WRITE
);
1526 dynamic
->link
= dynstr
;
1527 dynamic
->sh_entsize
= sizeof(ElfW(Dyn
));
1530 s1
->plt
= new_section(s1
, ".plt", SHT_PROGBITS
,
1531 SHF_ALLOC
| SHF_EXECINSTR
);
1532 s1
->plt
->sh_entsize
= 4;
1536 /* scan for undefined symbols and see if they are in the
1537 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1538 is found, then we add it in the PLT. If a symbol
1539 STT_OBJECT is found, we add it in the .bss section with
1540 a suitable relocation */
1541 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+
1542 symtab_section
->data_offset
);
1543 if (file_type
== TCC_OUTPUT_EXE
) {
1544 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
1547 if (sym
->st_shndx
== SHN_UNDEF
) {
1548 name
= symtab_section
->link
->data
+ sym
->st_name
;
1549 sym_index
= find_elf_sym(s1
->dynsymtab_section
, name
);
1551 esym
= &((ElfW(Sym
) *)s1
->dynsymtab_section
->data
)[sym_index
];
1552 type
= ELFW(ST_TYPE
)(esym
->st_info
);
1553 if ((type
== STT_FUNC
) || (type
== STT_GNU_IFUNC
)) {
1554 put_got_entry(s1
, R_JMP_SLOT
, esym
->st_size
,
1555 ELFW(ST_INFO
)(STB_GLOBAL
,type
),
1556 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1557 } else if (type
== STT_OBJECT
) {
1558 unsigned long offset
;
1559 ElfW(Sym
) *dynsym
, *dynsym_end
;
1560 offset
= bss_section
->data_offset
;
1561 /* XXX: which alignment ? */
1562 offset
= (offset
+ 16 - 1) & -16;
1563 index
= put_elf_sym(s1
->dynsym
, offset
, esym
->st_size
,
1565 bss_section
->sh_num
, name
);
1566 // Ensure R_COPY works for weak symbol aliases
1567 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1568 dynsym_end
= (ElfW(Sym
) *)
1569 (s1
->dynsymtab_section
->data
+
1570 s1
->dynsymtab_section
->data_offset
);
1571 for(dynsym
= (ElfW(Sym
) *)s1
->dynsymtab_section
->data
+ 1;
1572 dynsym
< dynsym_end
; dynsym
++) {
1573 if ((dynsym
->st_value
== esym
->st_value
)
1574 && (ELFW(ST_BIND
)(dynsym
->st_info
) == STB_GLOBAL
)) {
1576 dynname
= s1
->dynsymtab_section
->link
->data
1578 put_elf_sym(s1
->dynsym
, offset
,
1581 bss_section
->sh_num
,
1587 put_elf_reloc(s1
->dynsym
, bss_section
,
1588 offset
, R_COPY
, index
);
1589 offset
+= esym
->st_size
;
1590 bss_section
->data_offset
= offset
;
1593 /* STB_WEAK undefined symbols are accepted */
1594 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1596 if (ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
||
1597 !strcmp(name
, "_fp_hw")) {
1599 tcc_error_noabort("undefined symbol '%s'", name
);
1602 } else if (s1
->rdynamic
&&
1603 ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1604 /* if -rdynamic option, then export all non
1606 name
= symtab_section
->link
->data
+ sym
->st_name
;
1607 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1609 sym
->st_shndx
, name
);
1616 /* now look at unresolved dynamic symbols and export
1617 corresponding symbol */
1618 sym_end
= (ElfW(Sym
) *)(s1
->dynsymtab_section
->data
+
1619 s1
->dynsymtab_section
->data_offset
);
1620 for(esym
= (ElfW(Sym
) *)s1
->dynsymtab_section
->data
+ 1;
1623 if (esym
->st_shndx
== SHN_UNDEF
) {
1624 name
= s1
->dynsymtab_section
->link
->data
+ esym
->st_name
;
1625 sym_index
= find_elf_sym(symtab_section
, name
);
1627 /* XXX: avoid adding a symbol if already
1628 present because of -rdynamic ? */
1629 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1630 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1632 sym
->st_shndx
, name
);
1634 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1635 /* weak symbols can stay undefined */
1637 tcc_warning("undefined dynamic symbol '%s'", name
);
1644 /* shared library case : we simply export all the global symbols */
1645 nb_syms
= symtab_section
->data_offset
/ sizeof(ElfW(Sym
));
1646 s1
->symtab_to_dynsym
= tcc_mallocz(sizeof(int) * nb_syms
);
1647 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
1650 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1651 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1652 if ((ELFW(ST_TYPE
)(sym
->st_info
) == STT_FUNC
||
1653 ELFW(ST_TYPE
)(sym
->st_info
) == STT_GNU_IFUNC
)
1654 && sym
->st_shndx
== SHN_UNDEF
) {
1655 put_got_entry(s1
, R_JMP_SLOT
, sym
->st_size
,
1657 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1659 else if (ELFW(ST_TYPE
)(sym
->st_info
) == STT_OBJECT
) {
1660 put_got_entry(s1
, R_X86_64_GLOB_DAT
, sym
->st_size
,
1662 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1667 name
= symtab_section
->link
->data
+ sym
->st_name
;
1668 index
= put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1670 sym
->st_shndx
, name
);
1671 s1
->symtab_to_dynsym
[sym
-
1672 (ElfW(Sym
) *)symtab_section
->data
] =
1679 build_got_entries(s1
);
1681 /* add a list of needed dlls */
1682 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
1683 DLLReference
*dllref
= s1
->loaded_dlls
[i
];
1684 if (dllref
->level
== 0)
1685 put_dt(dynamic
, DT_NEEDED
, put_elf_str(dynstr
, dllref
->name
));
1689 put_dt(dynamic
, DT_RPATH
, put_elf_str(dynstr
, s1
->rpath
));
1691 /* XXX: currently, since we do not handle PIC code, we
1692 must relocate the readonly segments */
1693 if (file_type
== TCC_OUTPUT_DLL
) {
1695 put_dt(dynamic
, DT_SONAME
, put_elf_str(dynstr
, s1
->soname
));
1696 put_dt(dynamic
, DT_TEXTREL
, 0);
1700 put_dt(dynamic
, DT_SYMBOLIC
, 0);
1702 /* add necessary space for other entries */
1703 saved_dynamic_data_offset
= dynamic
->data_offset
;
1704 dynamic
->data_offset
+= sizeof(ElfW(Dyn
)) * EXTRA_RELITEMS
;
1706 /* still need to build got entries in case of static link */
1707 build_got_entries(s1
);
1711 memset(&ehdr
, 0, sizeof(ehdr
));
1713 /* we add a section for symbols */
1714 strsec
= new_section(s1
, ".shstrtab", SHT_STRTAB
, 0);
1715 put_elf_str(strsec
, "");
1717 /* compute number of sections */
1718 shnum
= s1
->nb_sections
;
1720 /* this array is used to reorder sections in the output file */
1721 section_order
= tcc_malloc(sizeof(int) * shnum
);
1722 section_order
[0] = 0;
1725 /* compute number of program headers */
1728 case TCC_OUTPUT_OBJ
:
1731 case TCC_OUTPUT_EXE
:
1732 if (!s1
->static_link
)
1733 phnum
= 4 + HAVE_PHDR
;
1737 case TCC_OUTPUT_DLL
:
1742 /* allocate strings for section names and decide if an unallocated
1743 section should be output */
1744 /* NOTE: the strsec section comes last, so its size is also
1746 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1747 s
= s1
->sections
[i
];
1748 s
->sh_name
= put_elf_str(strsec
, s
->name
);
1750 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1755 s
->reloc
? s
->reloc
->name
: "n"
1758 /* when generating a DLL, we include relocations but we may
1760 if (file_type
== TCC_OUTPUT_DLL
&&
1761 s
->sh_type
== SHT_RELX
&&
1762 !(s
->sh_flags
& SHF_ALLOC
)) {
1763 /* //gr: avoid bogus relocs for empty (debug) sections */
1764 if (s1
->sections
[s
->sh_info
]->sh_flags
& SHF_ALLOC
)
1765 prepare_dynamic_rel(s1
, s
);
1766 else if (s1
->do_debug
)
1767 s
->sh_size
= s
->data_offset
;
1768 } else if (s1
->do_debug
||
1769 file_type
== TCC_OUTPUT_OBJ
||
1770 (s
->sh_flags
& SHF_ALLOC
) ||
1771 i
== (s1
->nb_sections
- 1)) {
1772 /* we output all sections if debug or object file */
1773 s
->sh_size
= s
->data_offset
;
1777 /* allocate program segment headers */
1778 phdr
= tcc_mallocz(phnum
* sizeof(ElfW(Phdr
)));
1780 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1781 file_offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
1786 /* compute section to program header mapping */
1787 if (s1
->has_text_addr
) {
1788 int a_offset
, p_offset
;
1789 addr
= s1
->text_addr
;
1790 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1792 a_offset
= (int) (addr
& (s1
->section_align
- 1));
1793 p_offset
= file_offset
& (s1
->section_align
- 1);
1794 if (a_offset
< p_offset
)
1795 a_offset
+= s1
->section_align
;
1796 file_offset
+= (a_offset
- p_offset
);
1798 if (file_type
== TCC_OUTPUT_DLL
)
1801 addr
= ELF_START_ADDR
;
1802 /* compute address after headers */
1803 addr
+= (file_offset
& (s1
->section_align
- 1));
1806 /* dynamic relocation table information, for .dynamic section */
1810 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1811 bss_addr
= bss_size
= 0;
1813 /* leave one program header for the program interpreter */
1816 ph
+= 1 + HAVE_PHDR
;
1818 for(j
= 0; j
< 2; j
++) {
1819 ph
->p_type
= PT_LOAD
;
1821 ph
->p_flags
= PF_R
| PF_X
;
1823 ph
->p_flags
= PF_R
| PF_W
;
1824 ph
->p_align
= s1
->section_align
;
1826 /* we do the following ordering: interp, symbol tables,
1827 relocations, progbits, nobits */
1828 /* XXX: do faster and simpler sorting */
1829 for(k
= 0; k
< 5; k
++) {
1830 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1831 s
= s1
->sections
[i
];
1832 /* compute if section should be included */
1834 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1838 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1839 (SHF_ALLOC
| SHF_WRITE
))
1845 } else if (s
->sh_type
== SHT_DYNSYM
||
1846 s
->sh_type
== SHT_STRTAB
||
1847 s
->sh_type
== SHT_HASH
) {
1850 } else if (s
->sh_type
== SHT_RELX
) {
1853 } else if (s
->sh_type
== SHT_NOBITS
) {
1860 section_order
[sh_order_index
++] = i
;
1862 /* section matches: we align it and add its size */
1864 addr
= (addr
+ s
->sh_addralign
- 1) &
1865 ~(s
->sh_addralign
- 1);
1866 file_offset
+= (int) ( addr
- tmp
);
1867 s
->sh_offset
= file_offset
;
1870 /* update program header infos */
1871 if (ph
->p_offset
== 0) {
1872 ph
->p_offset
= file_offset
;
1874 ph
->p_paddr
= ph
->p_vaddr
;
1876 /* update dynamic relocation infos */
1877 if (s
->sh_type
== SHT_RELX
) {
1878 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1879 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.got")) { // rel_size == 0) {
1881 rel_size
+= s
->sh_size
; // XXX only first rel.
1883 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.bss")) { // rel_size == 0) {
1885 bss_size
= s
->sh_size
; // XXX only first rel.
1890 rel_size
+= s
->sh_size
;
1894 if (s
->sh_type
!= SHT_NOBITS
)
1895 file_offset
+= s
->sh_size
;
1898 ph
->p_filesz
= file_offset
- ph
->p_offset
;
1899 ph
->p_memsz
= addr
- ph
->p_vaddr
;
1902 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1903 /* if in the middle of a page, we duplicate the page in
1904 memory so that one copy is RX and the other is RW */
1905 if ((addr
& (s1
->section_align
- 1)) != 0)
1906 addr
+= s1
->section_align
;
1908 addr
= (addr
+ s1
->section_align
- 1) & ~(s1
->section_align
- 1);
1909 file_offset
= (file_offset
+ s1
->section_align
- 1) &
1910 ~(s1
->section_align
- 1);
1915 /* if interpreter, then add corresponing program header */
1919 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1921 int len
= phnum
* sizeof(ElfW(Phdr
));
1923 ph
->p_type
= PT_PHDR
;
1924 ph
->p_offset
= sizeof(ElfW(Ehdr
));
1925 ph
->p_vaddr
= interp
->sh_addr
- len
;
1926 ph
->p_paddr
= ph
->p_vaddr
;
1927 ph
->p_filesz
= ph
->p_memsz
= len
;
1928 ph
->p_flags
= PF_R
| PF_X
;
1929 ph
->p_align
= 4; // interp->sh_addralign;
1934 ph
->p_type
= PT_INTERP
;
1935 ph
->p_offset
= interp
->sh_offset
;
1936 ph
->p_vaddr
= interp
->sh_addr
;
1937 ph
->p_paddr
= ph
->p_vaddr
;
1938 ph
->p_filesz
= interp
->sh_size
;
1939 ph
->p_memsz
= interp
->sh_size
;
1941 ph
->p_align
= interp
->sh_addralign
;
1944 /* if dynamic section, then add corresponing program header */
1948 ph
= &phdr
[phnum
- 1];
1950 ph
->p_type
= PT_DYNAMIC
;
1951 ph
->p_offset
= dynamic
->sh_offset
;
1952 ph
->p_vaddr
= dynamic
->sh_addr
;
1953 ph
->p_paddr
= ph
->p_vaddr
;
1954 ph
->p_filesz
= dynamic
->sh_size
;
1955 ph
->p_memsz
= dynamic
->sh_size
;
1956 ph
->p_flags
= PF_R
| PF_W
;
1957 ph
->p_align
= dynamic
->sh_addralign
;
1959 /* put GOT dynamic section address */
1960 put32(s1
->got
->data
, dynamic
->sh_addr
);
1962 /* relocate the PLT */
1963 if (file_type
== TCC_OUTPUT_EXE
1964 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1965 || file_type
== TCC_OUTPUT_DLL
1971 p_end
= p
+ s1
->plt
->data_offset
;
1973 #if defined(TCC_TARGET_I386)
1974 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
1975 put32(p
+ 8, get32(p
+ 8) + s1
->got
->sh_addr
);
1978 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
1981 #elif defined(TCC_TARGET_X86_64)
1982 int x
= s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 6;
1983 put32(p
+ 2, get32(p
+ 2) + x
);
1984 put32(p
+ 8, get32(p
+ 8) + x
- 6);
1987 put32(p
+ 2, get32(p
+ 2) + x
+ s1
->plt
->data
- p
);
1990 #elif defined(TCC_TARGET_ARM)
1992 x
=s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 12;
1995 put32(p
+ 12, x
+ get32(p
+ 12) + s1
->plt
->data
- p
);
1998 #elif defined(TCC_TARGET_C67)
2001 #error unsupported CPU
2006 /* relocate symbols in .dynsym */
2007 sym_end
= (ElfW(Sym
) *)(s1
->dynsym
->data
+ s1
->dynsym
->data_offset
);
2008 for(sym
= (ElfW(Sym
) *)s1
->dynsym
->data
+ 1;
2011 if (sym
->st_shndx
== SHN_UNDEF
) {
2012 /* relocate to the PLT if the symbol corresponds
2015 sym
->st_value
+= s1
->plt
->sh_addr
;
2016 } else if (sym
->st_shndx
< SHN_LORESERVE
) {
2017 /* do symbol relocation */
2018 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
2022 /* put dynamic section entries */
2023 dynamic
->data_offset
= saved_dynamic_data_offset
;
2024 put_dt(dynamic
, DT_HASH
, s1
->dynsym
->hash
->sh_addr
);
2025 put_dt(dynamic
, DT_STRTAB
, dynstr
->sh_addr
);
2026 put_dt(dynamic
, DT_SYMTAB
, s1
->dynsym
->sh_addr
);
2027 put_dt(dynamic
, DT_STRSZ
, dynstr
->data_offset
);
2028 put_dt(dynamic
, DT_SYMENT
, sizeof(ElfW(Sym
)));
2029 #ifdef TCC_TARGET_X86_64
2030 put_dt(dynamic
, DT_RELA
, rel_addr
);
2031 put_dt(dynamic
, DT_RELASZ
, rel_size
);
2032 put_dt(dynamic
, DT_RELAENT
, sizeof(ElfW_Rel
));
2034 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2035 put_dt(dynamic
, DT_PLTGOT
, s1
->got
->sh_addr
);
2036 put_dt(dynamic
, DT_PLTRELSZ
, rel_size
);
2037 put_dt(dynamic
, DT_JMPREL
, rel_addr
);
2038 put_dt(dynamic
, DT_PLTREL
, DT_REL
);
2039 put_dt(dynamic
, DT_REL
, bss_addr
);
2040 put_dt(dynamic
, DT_RELSZ
, bss_size
);
2042 put_dt(dynamic
, DT_REL
, rel_addr
);
2043 put_dt(dynamic
, DT_RELSZ
, rel_size
);
2044 put_dt(dynamic
, DT_RELENT
, sizeof(ElfW_Rel
));
2048 put_dt(dynamic
, DT_DEBUG
, 0);
2049 put_dt(dynamic
, DT_NULL
, 0);
2052 ehdr
.e_phentsize
= sizeof(ElfW(Phdr
));
2053 ehdr
.e_phnum
= phnum
;
2054 ehdr
.e_phoff
= sizeof(ElfW(Ehdr
));
2057 /* all other sections come after */
2058 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2059 s
= s1
->sections
[i
];
2060 if (phnum
> 0 && (s
->sh_flags
& SHF_ALLOC
))
2062 section_order
[sh_order_index
++] = i
;
2064 file_offset
= (file_offset
+ s
->sh_addralign
- 1) &
2065 ~(s
->sh_addralign
- 1);
2066 s
->sh_offset
= file_offset
;
2067 if (s
->sh_type
!= SHT_NOBITS
)
2068 file_offset
+= s
->sh_size
;
2071 /* if building executable or DLL, then relocate each section
2072 except the GOT which is already relocated */
2073 if (file_type
!= TCC_OUTPUT_OBJ
) {
2074 relocate_syms(s1
, 0);
2076 if (s1
->nb_errors
!= 0) {
2082 /* relocate sections */
2083 /* XXX: ignore sections with allocated relocations ? */
2084 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2085 s
= s1
->sections
[i
];
2086 if (s
->reloc
&& s
!= s1
->got
&& (s
->sh_flags
& SHF_ALLOC
)) //gr
2087 relocate_section(s1
, s
);
2090 /* relocate relocation entries if the relocation tables are
2091 allocated in the executable */
2092 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2093 s
= s1
->sections
[i
];
2094 if ((s
->sh_flags
& SHF_ALLOC
) &&
2095 s
->sh_type
== SHT_RELX
) {
2096 relocate_rel(s1
, s
);
2100 /* get entry point address */
2101 if (file_type
== TCC_OUTPUT_EXE
)
2102 ehdr
.e_entry
= (uplong
)tcc_get_symbol_err(s1
, "_start");
2104 ehdr
.e_entry
= text_section
->sh_addr
; /* XXX: is it correct ? */
2106 if (file_type
== TCC_OUTPUT_EXE
&& s1
->static_link
)
2109 /* write elf file */
2110 if (file_type
== TCC_OUTPUT_OBJ
)
2115 fd
= open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
, mode
);
2117 tcc_error_noabort("could not write '%s'", filename
);
2120 f
= fdopen(fd
, "wb");
2122 printf("<- %s\n", filename
);
2124 #ifdef TCC_TARGET_COFF
2125 if (s1
->output_format
== TCC_OUTPUT_FORMAT_COFF
) {
2126 tcc_output_coff(s1
, f
);
2129 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
2130 sort_syms(s1
, symtab_section
);
2133 file_offset
= (file_offset
+ 3) & -4;
2136 ehdr
.e_ident
[0] = ELFMAG0
;
2137 ehdr
.e_ident
[1] = ELFMAG1
;
2138 ehdr
.e_ident
[2] = ELFMAG2
;
2139 ehdr
.e_ident
[3] = ELFMAG3
;
2140 ehdr
.e_ident
[4] = ELFCLASSW
;
2141 ehdr
.e_ident
[5] = ELFDATA2LSB
;
2142 ehdr
.e_ident
[6] = EV_CURRENT
;
2143 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2144 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_FREEBSD
;
2146 #ifdef TCC_TARGET_ARM
2148 ehdr
.e_ident
[EI_OSABI
] = 0;
2149 ehdr
.e_flags
= 4 << 24;
2151 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_ARM
;
2156 case TCC_OUTPUT_EXE
:
2157 ehdr
.e_type
= ET_EXEC
;
2159 case TCC_OUTPUT_DLL
:
2160 ehdr
.e_type
= ET_DYN
;
2162 case TCC_OUTPUT_OBJ
:
2163 ehdr
.e_type
= ET_REL
;
2166 ehdr
.e_machine
= EM_TCC_TARGET
;
2167 ehdr
.e_version
= EV_CURRENT
;
2168 ehdr
.e_shoff
= file_offset
;
2169 ehdr
.e_ehsize
= sizeof(ElfW(Ehdr
));
2170 ehdr
.e_shentsize
= sizeof(ElfW(Shdr
));
2171 ehdr
.e_shnum
= shnum
;
2172 ehdr
.e_shstrndx
= shnum
- 1;
2174 fwrite(&ehdr
, 1, sizeof(ElfW(Ehdr
)), f
);
2175 fwrite(phdr
, 1, phnum
* sizeof(ElfW(Phdr
)), f
);
2176 offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
2178 for(i
=1;i
<s1
->nb_sections
;i
++) {
2179 s
= s1
->sections
[section_order
[i
]];
2180 if (s
->sh_type
!= SHT_NOBITS
) {
2181 if (s
->sh_type
== SHT_DYNSYM
)
2182 patch_dynsym_undef(s1
, s
);
2183 while (offset
< s
->sh_offset
) {
2188 fwrite(s
->data
, 1, size
, f
);
2193 /* output section headers */
2194 while (offset
< ehdr
.e_shoff
) {
2199 for(i
=0;i
<s1
->nb_sections
;i
++) {
2201 memset(sh
, 0, sizeof(ElfW(Shdr
)));
2202 s
= s1
->sections
[i
];
2204 sh
->sh_name
= s
->sh_name
;
2205 sh
->sh_type
= s
->sh_type
;
2206 sh
->sh_flags
= s
->sh_flags
;
2207 sh
->sh_entsize
= s
->sh_entsize
;
2208 sh
->sh_info
= s
->sh_info
;
2210 sh
->sh_link
= s
->link
->sh_num
;
2211 sh
->sh_addralign
= s
->sh_addralign
;
2212 sh
->sh_addr
= s
->sh_addr
;
2213 sh
->sh_offset
= s
->sh_offset
;
2214 sh
->sh_size
= s
->sh_size
;
2216 fwrite(sh
, 1, sizeof(ElfW(Shdr
)), f
);
2219 tcc_output_binary(s1
, f
, section_order
);
2225 tcc_free(s1
->symtab_to_dynsym
);
2226 tcc_free(section_order
);
2228 tcc_free(s1
->got_offsets
);
2232 LIBTCCAPI
int tcc_output_file(TCCState
*s
, const char *filename
)
2235 #ifdef TCC_TARGET_PE
2236 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
2237 ret
= pe_output_file(s
, filename
);
2241 ret
= elf_output_file(s
, filename
);
2246 static void *load_data(int fd
, unsigned long file_offset
, unsigned long size
)
2250 data
= tcc_malloc(size
);
2251 lseek(fd
, file_offset
, SEEK_SET
);
2252 read(fd
, data
, size
);
2256 typedef struct SectionMergeInfo
{
2257 Section
*s
; /* corresponding existing section */
2258 unsigned long offset
; /* offset of the new section in the existing section */
2259 uint8_t new_section
; /* true if section 's' was added */
2260 uint8_t link_once
; /* true if link once section */
2263 /* load an object file and merge it with current files */
2264 /* XXX: handle correctly stab (debug) info */
2265 ST_FUNC
int tcc_load_object_file(TCCState
*s1
,
2266 int fd
, unsigned long file_offset
)
2269 ElfW(Shdr
) *shdr
, *sh
;
2270 int size
, i
, j
, offset
, offseti
, nb_syms
, sym_index
, ret
;
2271 unsigned char *strsec
, *strtab
;
2272 int *old_to_new_syms
;
2273 char *sh_name
, *name
;
2274 SectionMergeInfo
*sm_table
, *sm
;
2275 ElfW(Sym
) *sym
, *symtab
;
2276 ElfW_Rel
*rel
, *rel_end
;
2282 stab_index
= stabstr_index
= 0;
2284 if (read(fd
, &ehdr
, sizeof(ehdr
)) != sizeof(ehdr
))
2286 if (ehdr
.e_ident
[0] != ELFMAG0
||
2287 ehdr
.e_ident
[1] != ELFMAG1
||
2288 ehdr
.e_ident
[2] != ELFMAG2
||
2289 ehdr
.e_ident
[3] != ELFMAG3
)
2291 /* test if object file */
2292 if (ehdr
.e_type
!= ET_REL
)
2294 /* test CPU specific stuff */
2295 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2296 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2298 tcc_error_noabort("invalid object file");
2302 shdr
= load_data(fd
, file_offset
+ ehdr
.e_shoff
,
2303 sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2304 sm_table
= tcc_mallocz(sizeof(SectionMergeInfo
) * ehdr
.e_shnum
);
2306 /* load section names */
2307 sh
= &shdr
[ehdr
.e_shstrndx
];
2308 strsec
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2310 /* load symtab and strtab */
2311 old_to_new_syms
= NULL
;
2315 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2317 if (sh
->sh_type
== SHT_SYMTAB
) {
2319 tcc_error_noabort("object must contain only one symtab");
2324 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2325 symtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2326 sm_table
[i
].s
= symtab_section
;
2328 /* now load strtab */
2329 sh
= &shdr
[sh
->sh_link
];
2330 strtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2334 /* now examine each section and try to merge its content with the
2336 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2337 /* no need to examine section name strtab */
2338 if (i
== ehdr
.e_shstrndx
)
2341 sh_name
= strsec
+ sh
->sh_name
;
2342 /* ignore sections types we do not handle */
2343 if (sh
->sh_type
!= SHT_PROGBITS
&&
2344 sh
->sh_type
!= SHT_RELX
&&
2346 sh
->sh_type
!= SHT_ARM_EXIDX
&&
2348 sh
->sh_type
!= SHT_NOBITS
&&
2349 sh
->sh_type
!= SHT_PREINIT_ARRAY
&&
2350 sh
->sh_type
!= SHT_INIT_ARRAY
&&
2351 sh
->sh_type
!= SHT_FINI_ARRAY
&&
2352 strcmp(sh_name
, ".stabstr")
2355 if (sh
->sh_addralign
< 1)
2356 sh
->sh_addralign
= 1;
2357 /* find corresponding section, if any */
2358 for(j
= 1; j
< s1
->nb_sections
;j
++) {
2359 s
= s1
->sections
[j
];
2360 if (!strcmp(s
->name
, sh_name
)) {
2361 if (!strncmp(sh_name
, ".gnu.linkonce",
2362 sizeof(".gnu.linkonce") - 1)) {
2363 /* if a 'linkonce' section is already present, we
2364 do not add it again. It is a little tricky as
2365 symbols can still be defined in
2367 sm_table
[i
].link_once
= 1;
2374 /* not found: create new section */
2375 s
= new_section(s1
, sh_name
, sh
->sh_type
, sh
->sh_flags
);
2376 /* take as much info as possible from the section. sh_link and
2377 sh_info will be updated later */
2378 s
->sh_addralign
= sh
->sh_addralign
;
2379 s
->sh_entsize
= sh
->sh_entsize
;
2380 sm_table
[i
].new_section
= 1;
2382 if (sh
->sh_type
!= s
->sh_type
) {
2383 tcc_error_noabort("invalid section type");
2387 /* align start of section */
2388 offset
= s
->data_offset
;
2390 if (0 == strcmp(sh_name
, ".stab")) {
2394 if (0 == strcmp(sh_name
, ".stabstr")) {
2399 size
= sh
->sh_addralign
- 1;
2400 offset
= (offset
+ size
) & ~size
;
2401 if (sh
->sh_addralign
> s
->sh_addralign
)
2402 s
->sh_addralign
= sh
->sh_addralign
;
2403 s
->data_offset
= offset
;
2405 sm_table
[i
].offset
= offset
;
2407 /* concatenate sections */
2409 if (sh
->sh_type
!= SHT_NOBITS
) {
2411 lseek(fd
, file_offset
+ sh
->sh_offset
, SEEK_SET
);
2412 ptr
= section_ptr_add(s
, size
);
2413 read(fd
, ptr
, size
);
2415 s
->data_offset
+= size
;
2420 /* //gr relocate stab strings */
2421 if (stab_index
&& stabstr_index
) {
2424 s
= sm_table
[stab_index
].s
;
2425 a
= (Stab_Sym
*)(s
->data
+ sm_table
[stab_index
].offset
);
2426 b
= (Stab_Sym
*)(s
->data
+ s
->data_offset
);
2427 o
= sm_table
[stabstr_index
].offset
;
2429 a
->n_strx
+= o
, a
++;
2432 /* second short pass to update sh_link and sh_info fields of new
2434 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2436 if (!s
|| !sm_table
[i
].new_section
)
2439 if (sh
->sh_link
> 0)
2440 s
->link
= sm_table
[sh
->sh_link
].s
;
2441 if (sh
->sh_type
== SHT_RELX
) {
2442 s
->sh_info
= sm_table
[sh
->sh_info
].s
->sh_num
;
2443 /* update backward link */
2444 s1
->sections
[s
->sh_info
]->reloc
= s
;
2449 /* resolve symbols */
2450 old_to_new_syms
= tcc_mallocz(nb_syms
* sizeof(int));
2453 for(i
= 1; i
< nb_syms
; i
++, sym
++) {
2454 if (sym
->st_shndx
!= SHN_UNDEF
&&
2455 sym
->st_shndx
< SHN_LORESERVE
) {
2456 sm
= &sm_table
[sym
->st_shndx
];
2457 if (sm
->link_once
) {
2458 /* if a symbol is in a link once section, we use the
2459 already defined symbol. It is very important to get
2460 correct relocations */
2461 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
2462 name
= strtab
+ sym
->st_name
;
2463 sym_index
= find_elf_sym(symtab_section
, name
);
2465 old_to_new_syms
[i
] = sym_index
;
2469 /* if no corresponding section added, no need to add symbol */
2472 /* convert section number */
2473 sym
->st_shndx
= sm
->s
->sh_num
;
2475 sym
->st_value
+= sm
->offset
;
2478 name
= strtab
+ sym
->st_name
;
2479 sym_index
= add_elf_sym(symtab_section
, sym
->st_value
, sym
->st_size
,
2480 sym
->st_info
, sym
->st_other
,
2481 sym
->st_shndx
, name
);
2482 old_to_new_syms
[i
] = sym_index
;
2485 /* third pass to patch relocation entries */
2486 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2491 offset
= sm_table
[i
].offset
;
2492 switch(s
->sh_type
) {
2494 /* take relocation offset information */
2495 offseti
= sm_table
[sh
->sh_info
].offset
;
2496 rel_end
= (ElfW_Rel
*)(s
->data
+ s
->data_offset
);
2497 for(rel
= (ElfW_Rel
*)(s
->data
+ offset
);
2502 /* convert symbol index */
2503 type
= ELFW(R_TYPE
)(rel
->r_info
);
2504 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
2505 /* NOTE: only one symtab assumed */
2506 if (sym_index
>= nb_syms
)
2508 sym_index
= old_to_new_syms
[sym_index
];
2509 /* ignore link_once in rel section. */
2510 if (!sym_index
&& !sm
->link_once
2511 #ifdef TCC_TARGET_ARM
2512 && type
!= R_ARM_V4BX
2516 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2517 i
, strsec
+ sh
->sh_name
, rel
->r_offset
);
2520 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
2521 /* offset the relocation offset */
2522 rel
->r_offset
+= offseti
;
2534 tcc_free(old_to_new_syms
);
2541 typedef struct ArchiveHeader
{
2542 char ar_name
[16]; /* name of this member */
2543 char ar_date
[12]; /* file mtime */
2544 char ar_uid
[6]; /* owner uid; printed as decimal */
2545 char ar_gid
[6]; /* owner gid; printed as decimal */
2546 char ar_mode
[8]; /* file mode, printed as octal */
2547 char ar_size
[10]; /* file size, printed as decimal */
2548 char ar_fmag
[2]; /* should contain ARFMAG */
2551 static int get_be32(const uint8_t *b
)
2553 return b
[3] | (b
[2] << 8) | (b
[1] << 16) | (b
[0] << 24);
2556 /* load only the objects which resolve undefined symbols */
2557 static int tcc_load_alacarte(TCCState
*s1
, int fd
, int size
)
2559 int i
, bound
, nsyms
, sym_index
, off
, ret
;
2561 const char *ar_names
, *p
;
2562 const uint8_t *ar_index
;
2565 data
= tcc_malloc(size
);
2566 if (read(fd
, data
, size
) != size
)
2568 nsyms
= get_be32(data
);
2569 ar_index
= data
+ 4;
2570 ar_names
= ar_index
+ nsyms
* 4;
2574 for(p
= ar_names
, i
= 0; i
< nsyms
; i
++, p
+= strlen(p
)+1) {
2575 sym_index
= find_elf_sym(symtab_section
, p
);
2577 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
2578 if(sym
->st_shndx
== SHN_UNDEF
) {
2579 off
= get_be32(ar_index
+ i
* 4) + sizeof(ArchiveHeader
);
2581 printf("%5d\t%s\t%08x\n", i
, p
, sym
->st_shndx
);
2584 lseek(fd
, off
, SEEK_SET
);
2585 if(tcc_load_object_file(s1
, fd
, off
) < 0) {
2600 /* load a '.a' file */
2601 ST_FUNC
int tcc_load_archive(TCCState
*s1
, int fd
)
2608 unsigned long file_offset
;
2610 /* skip magic which was already checked */
2611 read(fd
, magic
, sizeof(magic
));
2614 len
= read(fd
, &hdr
, sizeof(hdr
));
2617 if (len
!= sizeof(hdr
)) {
2618 tcc_error_noabort("invalid archive");
2621 memcpy(ar_size
, hdr
.ar_size
, sizeof(hdr
.ar_size
));
2622 ar_size
[sizeof(hdr
.ar_size
)] = '\0';
2623 size
= strtol(ar_size
, NULL
, 0);
2624 memcpy(ar_name
, hdr
.ar_name
, sizeof(hdr
.ar_name
));
2625 for(i
= sizeof(hdr
.ar_name
) - 1; i
>= 0; i
--) {
2626 if (ar_name
[i
] != ' ')
2629 ar_name
[i
+ 1] = '\0';
2630 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2631 file_offset
= lseek(fd
, 0, SEEK_CUR
);
2633 size
= (size
+ 1) & ~1;
2634 if (!strcmp(ar_name
, "/")) {
2635 /* coff symbol table : we handle it */
2636 if(s1
->alacarte_link
)
2637 return tcc_load_alacarte(s1
, fd
, size
);
2638 } else if (!strcmp(ar_name
, "//") ||
2639 !strcmp(ar_name
, "__.SYMDEF") ||
2640 !strcmp(ar_name
, "__.SYMDEF/") ||
2641 !strcmp(ar_name
, "ARFILENAMES/")) {
2642 /* skip symbol table or archive names */
2644 if (tcc_load_object_file(s1
, fd
, file_offset
) < 0)
2647 lseek(fd
, file_offset
+ size
, SEEK_SET
);
2652 #ifndef TCC_TARGET_PE
2653 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2654 is referenced by the user (so it should be added as DT_NEEDED in
2655 the generated ELF file) */
2656 ST_FUNC
int tcc_load_dll(TCCState
*s1
, int fd
, const char *filename
, int level
)
2659 ElfW(Shdr
) *shdr
, *sh
, *sh1
;
2660 int i
, j
, nb_syms
, nb_dts
, sym_bind
, ret
;
2661 ElfW(Sym
) *sym
, *dynsym
;
2662 ElfW(Dyn
) *dt
, *dynamic
;
2663 unsigned char *dynstr
;
2664 const char *name
, *soname
;
2665 DLLReference
*dllref
;
2667 read(fd
, &ehdr
, sizeof(ehdr
));
2669 /* test CPU specific stuff */
2670 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2671 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2672 tcc_error_noabort("bad architecture");
2677 shdr
= load_data(fd
, ehdr
.e_shoff
, sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2679 /* load dynamic section and dynamic symbols */
2683 dynsym
= NULL
; /* avoid warning */
2684 dynstr
= NULL
; /* avoid warning */
2685 for(i
= 0, sh
= shdr
; i
< ehdr
.e_shnum
; i
++, sh
++) {
2686 switch(sh
->sh_type
) {
2688 nb_dts
= sh
->sh_size
/ sizeof(ElfW(Dyn
));
2689 dynamic
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2692 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2693 dynsym
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2694 sh1
= &shdr
[sh
->sh_link
];
2695 dynstr
= load_data(fd
, sh1
->sh_offset
, sh1
->sh_size
);
2702 /* compute the real library name */
2703 soname
= tcc_basename(filename
);
2705 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2706 if (dt
->d_tag
== DT_SONAME
) {
2707 soname
= dynstr
+ dt
->d_un
.d_val
;
2711 /* if the dll is already loaded, do not load it */
2712 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
2713 dllref
= s1
->loaded_dlls
[i
];
2714 if (!strcmp(soname
, dllref
->name
)) {
2715 /* but update level if needed */
2716 if (level
< dllref
->level
)
2717 dllref
->level
= level
;
2723 // printf("loading dll '%s'\n", soname);
2725 /* add the dll and its level */
2726 dllref
= tcc_mallocz(sizeof(DLLReference
) + strlen(soname
));
2727 dllref
->level
= level
;
2728 strcpy(dllref
->name
, soname
);
2729 dynarray_add((void ***)&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
, dllref
);
2731 /* add dynamic symbols in dynsym_section */
2732 for(i
= 1, sym
= dynsym
+ 1; i
< nb_syms
; i
++, sym
++) {
2733 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
2734 if (sym_bind
== STB_LOCAL
)
2736 name
= dynstr
+ sym
->st_name
;
2737 add_elf_sym(s1
->dynsymtab_section
, sym
->st_value
, sym
->st_size
,
2738 sym
->st_info
, sym
->st_other
, sym
->st_shndx
, name
);
2741 /* load all referenced DLLs */
2742 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2745 name
= dynstr
+ dt
->d_un
.d_val
;
2746 for(j
= 0; j
< s1
->nb_loaded_dlls
; j
++) {
2747 dllref
= s1
->loaded_dlls
[j
];
2748 if (!strcmp(name
, dllref
->name
))
2749 goto already_loaded
;
2751 if (tcc_add_dll(s1
, name
, AFF_REFERENCED_DLL
) < 0) {
2752 tcc_error_noabort("referenced dll '%s' not found", name
);
2769 #define LD_TOK_NAME 256
2770 #define LD_TOK_EOF (-1)
2772 /* return next ld script token */
2773 static int ld_next(TCCState
*s1
, char *name
, int name_size
)
2791 file
->buf_ptr
= parse_comment(file
->buf_ptr
);
2792 ch
= file
->buf_ptr
[0];
2800 /* case 'a' ... 'z': */
2827 /* case 'A' ... 'z': */
2862 if (!((ch
>= 'a' && ch
<= 'z') ||
2863 (ch
>= 'A' && ch
<= 'Z') ||
2864 (ch
>= '0' && ch
<= '9') ||
2865 strchr("/.-_+=$:\\,~", ch
)))
2867 if ((q
- name
) < name_size
- 1) {
2884 printf("tok=%c %d\n", c
, c
);
2885 if (c
== LD_TOK_NAME
)
2886 printf(" name=%s\n", name
);
2892 * Extract the file name from the library name
2894 * /!\ No test on filename capacity, be careful
2896 static void libname_to_filename(TCCState
*s1
, const char libname
[], char filename
[])
2898 if (!s1
->static_link
) {
2899 sprintf(filename
, "lib%s.so", libname
);
2901 sprintf(filename
, "lib%s.a", libname
);
2905 static int ld_add_file(TCCState
*s1
, const char filename
[])
2909 ret
= tcc_add_file_internal(s1
, filename
, 0);
2911 ret
= tcc_add_dll(s1
, filename
, 0);
2915 static inline int new_undef_syms(void)
2918 ret
= new_undef_sym
;
2923 static int ld_add_file_list(TCCState
*s1
, const char *cmd
, int as_needed
)
2925 char filename
[1024], libname
[1024];
2926 int t
, group
, nblibs
= 0, ret
= 0;
2929 group
= !strcmp(cmd
, "GROUP");
2932 t
= ld_next(s1
, filename
, sizeof(filename
));
2935 t
= ld_next(s1
, filename
, sizeof(filename
));
2938 if (t
== LD_TOK_EOF
) {
2939 tcc_error_noabort("unexpected end of file");
2941 goto lib_parse_error
;
2942 } else if (t
== ')') {
2944 } else if (t
== '-') {
2945 t
= ld_next(s1
, filename
, sizeof(filename
));
2946 if ((t
!= LD_TOK_NAME
) || (filename
[0] != 'l')) {
2947 tcc_error_noabort("library name expected");
2949 goto lib_parse_error
;
2951 strcpy(libname
, &filename
[1]);
2952 libname_to_filename(s1
, libname
, filename
);
2953 } else if (t
!= LD_TOK_NAME
) {
2954 tcc_error_noabort("filename expected");
2956 goto lib_parse_error
;
2958 if (!strcmp(filename
, "AS_NEEDED")) {
2959 ret
= ld_add_file_list(s1
, cmd
, 1);
2961 goto lib_parse_error
;
2963 /* TODO: Implement AS_NEEDED support. Ignore it for now */
2965 ret
= ld_add_file(s1
, filename
);
2967 goto lib_parse_error
;
2969 /* Add the filename *and* the libname to avoid future conversions */
2970 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(filename
));
2971 if (libname
[0] != '\0')
2972 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(libname
));
2976 t
= ld_next(s1
, filename
, sizeof(filename
));
2978 t
= ld_next(s1
, filename
, sizeof(filename
));
2981 if (group
&& !as_needed
) {
2982 while (new_undef_syms()) {
2985 for (i
= 0; i
< nblibs
; i
++)
2986 ld_add_file(s1
, libs
[i
]);
2990 dynarray_reset(&libs
, &nblibs
);
2994 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
2996 ST_FUNC
int tcc_load_ldscript(TCCState
*s1
)
2999 char filename
[1024];
3002 ch
= file
->buf_ptr
[0];
3005 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3006 if (t
== LD_TOK_EOF
)
3008 else if (t
!= LD_TOK_NAME
)
3010 if (!strcmp(cmd
, "INPUT") ||
3011 !strcmp(cmd
, "GROUP")) {
3012 ret
= ld_add_file_list(s1
, cmd
, 0);
3015 } else if (!strcmp(cmd
, "OUTPUT_FORMAT") ||
3016 !strcmp(cmd
, "TARGET")) {
3017 /* ignore some commands */
3018 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3022 t
= ld_next(s1
, filename
, sizeof(filename
));
3023 if (t
== LD_TOK_EOF
) {
3024 tcc_error_noabort("unexpected end of file");
3026 } else if (t
== ')') {
3036 #endif /* ndef TCC_TARGET_PE */