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
->sym_infos
[sym_index
].got_offset
<< 1;
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
, blx_avail
;
605 x
= (*(int *)ptr
)&0xffffff;
606 (*(int *)ptr
) &= 0xff000000;
610 blx_avail
= (TCC_ARM_VERSION
>= 5);
612 is_call
= (type
== R_ARM_CALL
);
615 #ifndef TCC_TARGET_PE
616 if ((x
& 3) || x
>= 0x4000000 || x
< -0x4000000)
617 if (!(x
& 3) || !blx_avail
|| !is_call
)
618 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
619 x
+= add_jmp_table(s1
, val
) - val
; /* add veneer */
620 is_thumb
= 0; /* Veneer uses ARM instructions */
623 if ((x
& 3) || x
>= 0x4000000 || x
< -0x4000000)
624 if (!(x
& 3) || !blx_avail
|| !is_call
)
625 tcc_error("can't relocate value at %x",addr
);
628 /* Only reached if blx is avail and it is a call */
631 (*(int *)ptr
) = 0xfa << 24; /* bl -> blx */
636 /* Since these relocations only concern Thumb-2 and blx instruction was
637 introduced before Thumb-2, we can assume blx is available and not
640 case R_ARM_THM_JUMP24
:
642 int x
, hi
, lo
, s
, j1
, j2
, i1
, i2
, imm10
, imm11
;
643 int to_thumb
, is_call
, to_plt
, blx_bit
= 1 << 12;
647 if (sym
->st_shndx
== SHN_UNDEF
&&
648 ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
651 /* Get initial offset */
652 hi
= (*(uint16_t *)ptr
);
653 lo
= (*(uint16_t *)(ptr
+2));
661 x
= (s
<< 24) | (i1
<< 23) | (i2
<< 22) |
662 (imm10
<< 12) | (imm11
<< 1);
666 /* Relocation infos */
669 to_plt
= (val
>= plt
->sh_addr
) &&
670 (val
< plt
->sh_addr
+ plt
->data_offset
);
671 is_call
= (type
== R_ARM_THM_CALL
);
673 /* Compute final offset */
674 if (to_plt
&& !is_call
) /* Point to 1st instr of Thumb stub */
677 if (!to_thumb
&& is_call
) {
678 blx_bit
= 0; /* bl -> blx */
679 x
= (x
+ 3) & -4; /* Compute offset from aligned PC */
682 /* Check that relocation is possible
683 * offset must not be out of range
684 * if target is to be entered in arm mode:
686 - instruction must be a call (bl) or a jump to PLT */
687 if (!to_thumb
|| x
>= 0x1000000 || x
< -0x1000000)
688 if (to_thumb
|| (val
& 2) || (!is_call
&& !to_plt
))
689 tcc_error("can't relocate value at %x",addr
);
691 /* Compute and store final offset */
697 imm10
= (x
>> 12) & 0x3ff;
698 imm11
= (x
>> 1) & 0x7ff;
699 (*(uint16_t *)ptr
) = (uint16_t) ((hi
& 0xf800) |
701 (*(uint16_t *)(ptr
+2)) = (uint16_t) ((lo
& 0xc000) |
702 (j1
<< 13) | blx_bit
| (j2
<< 11) |
707 case R_ARM_MOVW_ABS_NC
:
710 if (type
== R_ARM_MOVT_ABS
)
713 imm4
= (val
>> 12) & 0xf;
714 x
= (imm4
<< 16) | imm12
;
715 if (type
== R_ARM_THM_MOVT_ABS
)
721 case R_ARM_THM_MOVT_ABS
:
722 case R_ARM_THM_MOVW_ABS_NC
:
724 int x
, i
, imm4
, imm3
, imm8
;
725 if (type
== R_ARM_THM_MOVT_ABS
)
728 imm3
= (val
>> 8) & 0x7;
730 imm4
= (val
>> 12) & 0xf;
731 x
= (imm3
<< 28) | (imm8
<< 16) | (i
<< 10) | imm4
;
732 if (type
== R_ARM_THM_MOVT_ABS
)
741 x
= (*(int *)ptr
) & 0x7fffffff;
742 (*(int *)ptr
) &= 0x80000000;
745 if((x
^(x
>>1))&0x40000000)
746 tcc_error("can't relocate value at %x",addr
);
747 (*(int *)ptr
) |= x
& 0x7fffffff;
753 *(int *)ptr
+= val
- addr
;
755 case R_ARM_BASE_PREL
:
756 *(int *)ptr
+= s1
->got
->sh_addr
- addr
;
759 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
762 /* we load the got offset */
763 *(int *)ptr
+= s1
->sym_infos
[sym_index
].got_offset
<< 1;
768 /* trade Thumb support for ARMv4 support */
769 if ((0x0ffffff0 & *(int*)ptr
) == 0x012FFF10)
770 *(int*)ptr
^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
773 fprintf(stderr
,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
774 type
, (unsigned)addr
, (unsigned)(uplong
)ptr
, (unsigned)val
);
776 #elif defined(TCC_TARGET_C67)
784 /* put the low 16 bits of the absolute address */
785 // add to what is already there
787 orig
= ((*(int *)(ptr
)) >> 7) & 0xffff;
788 orig
|= (((*(int *)(ptr
+4)) >> 7) & 0xffff) << 16;
790 //patch both at once - assumes always in pairs Low - High
792 *(int *) ptr
= (*(int *) ptr
& (~(0xffff << 7)) ) | (((val
+orig
) & 0xffff) << 7);
793 *(int *)(ptr
+4) = (*(int *)(ptr
+4) & (~(0xffff << 7)) ) | ((((val
+orig
)>>16) & 0xffff) << 7);
799 fprintf(stderr
,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
800 type
, (unsigned)addr
, (unsigned)(uplong
)ptr
, (unsigned)val
);
802 #elif defined(TCC_TARGET_X86_64)
804 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
805 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
806 qrel
->r_addend
= *(long long *)ptr
+ val
;
809 *(long long *)ptr
+= val
;
813 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
814 /* XXX: this logic may depend on TCC's codegen
815 now TCC uses R_X86_64_32 even for a 64bit pointer */
816 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
817 qrel
->r_addend
= *(int *)ptr
+ val
;
824 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
826 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
828 qrel
->r_offset
= rel
->r_offset
;
829 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_X86_64_PC32
);
830 qrel
->r_addend
= *(int *)ptr
;
836 case R_X86_64_PLT32
: {
838 diff
= (long long)val
- addr
;
839 if (diff
<= -2147483647 || diff
> 2147483647) {
840 #ifndef TCC_TARGET_PE
841 /* XXX: naive support for over 32bit jump */
842 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
843 val
= (add_jmp_table(s1
, val
- rel
->r_addend
) +
848 if (diff
<= -2147483647 || diff
> 2147483647) {
849 tcc_error("internal error: relocation failed");
855 case R_X86_64_GLOB_DAT
:
856 case R_X86_64_JUMP_SLOT
:
857 /* They don't need addend */
858 *(int *)ptr
= val
- rel
->r_addend
;
860 case R_X86_64_GOTPCREL
:
861 #ifndef TCC_TARGET_PE
862 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
863 val
= add_got_table(s1
, val
- rel
->r_addend
) + rel
->r_addend
;
864 *(int *)ptr
+= val
- addr
;
868 *(int *)ptr
+= (s1
->got
->sh_addr
- addr
+
869 (s1
->sym_infos
[sym_index
].got_offset
<< 1) - 4);
871 case R_X86_64_GOTTPOFF
:
872 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
875 /* we load the got offset */
876 *(int *)ptr
+= s1
->sym_infos
[sym_index
].got_offset
<< 1;
879 #error unsupported processor
883 /* if the relocation is allocated, we change its symbol table */
884 if (sr
->sh_flags
& SHF_ALLOC
)
885 sr
->link
= s1
->dynsym
;
888 /* relocate relocation table in 'sr' */
889 static void relocate_rel(TCCState
*s1
, Section
*sr
)
892 ElfW_Rel
*rel
, *rel_end
;
894 s
= s1
->sections
[sr
->sh_info
];
895 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
896 for(rel
= (ElfW_Rel
*)sr
->data
;
899 rel
->r_offset
+= s
->sh_addr
;
903 /* count the number of dynamic relocations so that we can reserve
905 static int prepare_dynamic_rel(TCCState
*s1
, Section
*sr
)
907 ElfW_Rel
*rel
, *rel_end
;
908 int sym_index
, esym_index
, type
, count
;
911 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
912 for(rel
= (ElfW_Rel
*)sr
->data
; rel
< rel_end
; rel
++) {
913 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
914 type
= ELFW(R_TYPE
)(rel
->r_info
);
916 #if defined(TCC_TARGET_I386)
918 #elif defined(TCC_TARGET_X86_64)
925 #if defined(TCC_TARGET_I386)
927 #elif defined(TCC_TARGET_X86_64)
930 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
939 /* allocate the section */
940 sr
->sh_flags
|= SHF_ALLOC
;
941 sr
->sh_size
= count
* sizeof(ElfW_Rel
);
946 static void put_sym_info(TCCState
*s1
, int index
)
949 typeof(s1
->sym_infos
) tab
;
951 if (index
>= s1
->nb_sym_infos
) {
952 /* find immediately bigger power of 2 and reallocate array */
956 tab
= tcc_realloc(s1
->sym_infos
, n
* sizeof(unsigned long));
958 memset(s1
->sym_infos
+ s1
->nb_sym_infos
, 0,
959 (n
- s1
->nb_sym_infos
) * sizeof(unsigned long));
960 s1
->nb_sym_infos
= n
;
964 #ifdef TCC_TARGET_ARM
965 static void put_plt_thumb_stub(TCCState
*s1
, int index
, unsigned char bit
)
967 put_sym_info(s1
, index
);
968 s1
->sym_infos
[index
].plt_thumb_stub
= bit
;
972 static void put_got_offset(TCCState
*s1
, int index
, unsigned long val
)
974 put_sym_info(s1
, index
);
975 s1
->sym_infos
[index
].got_offset
= val
>> 1;
978 /* XXX: suppress that */
979 static void put32(unsigned char *p
, uint32_t val
)
987 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
988 defined(TCC_TARGET_X86_64)
989 static uint32_t get32(unsigned char *p
)
991 return p
[0] | (p
[1] << 8) | (p
[2] << 16) | (p
[3] << 24);
995 static void build_got(TCCState
*s1
)
999 /* if no got, then create it */
1000 s1
->got
= new_section(s1
, ".got", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
1001 s1
->got
->sh_entsize
= 4;
1002 add_elf_sym(symtab_section
, 0, 4, ELFW(ST_INFO
)(STB_GLOBAL
, STT_OBJECT
),
1003 0, s1
->got
->sh_num
, "_GLOBAL_OFFSET_TABLE_");
1004 ptr
= section_ptr_add(s1
->got
, 3 * PTR_SIZE
);
1006 /* keep space for _DYNAMIC pointer, if present */
1008 /* two dummy got entries */
1012 /* keep space for _DYNAMIC pointer, if present */
1015 /* two dummy got entries */
1023 /* put a got entry corresponding to a symbol in symtab_section. 'size'
1024 and 'info' can be modifed if more precise info comes from the DLL */
1025 static void put_got_entry(TCCState
*s1
,
1026 int reloc_type
, unsigned long size
, int info
,
1032 unsigned long offset
;
1038 /* if a got entry already exists for that symbol, no need to add one */
1039 if (sym_index
< s1
->nb_sym_infos
&&
1040 s1
->sym_infos
[sym_index
].got_offset
<< 1)
1043 put_got_offset(s1
, sym_index
, s1
->got
->data_offset
);
1046 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1047 name
= symtab_section
->link
->data
+ sym
->st_name
;
1048 offset
= sym
->st_value
;
1049 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1051 #ifdef TCC_TARGET_X86_64
1061 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1064 /* if we build a DLL, we add a %ebx offset */
1065 if (s1
->output_type
== TCC_OUTPUT_DLL
)
1071 /* add a PLT entry */
1073 if (plt
->data_offset
== 0) {
1074 /* first plt entry */
1075 p
= section_ptr_add(plt
, 16);
1076 p
[0] = 0xff; /* pushl got + PTR_SIZE */
1077 p
[1] = modrm
+ 0x10;
1078 put32(p
+ 2, PTR_SIZE
);
1079 p
[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1081 put32(p
+ 8, PTR_SIZE
* 2);
1084 p
= section_ptr_add(plt
, 16);
1085 p
[0] = 0xff; /* jmp *(got + x) */
1087 put32(p
+ 2, s1
->got
->data_offset
);
1088 p
[6] = 0x68; /* push $xxx */
1089 put32(p
+ 7, (plt
->data_offset
- 32) >> 1);
1090 p
[11] = 0xe9; /* jmp plt_start */
1091 put32(p
+ 12, -(plt
->data_offset
));
1093 /* the symbol is modified so that it will be relocated to
1095 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
1096 if (s1
->output_type
== TCC_OUTPUT_EXE
)
1098 offset
= plt
->data_offset
- 16;
1100 #elif defined(TCC_TARGET_ARM)
1101 if (reloc_type
== R_ARM_JUMP_SLOT
) {
1105 /* if we build a DLL, we add a %ebx offset */
1106 if (s1
->output_type
== TCC_OUTPUT_DLL
)
1107 tcc_error("DLLs unimplemented!");
1109 /* add a PLT entry */
1111 if (plt
->data_offset
== 0) {
1112 /* first plt entry */
1113 p
= section_ptr_add(plt
, 16);
1114 put32(p
, 0xe52de004);
1115 put32(p
+ 4, 0xe59fe010);
1116 put32(p
+ 8, 0xe08fe00e);
1117 put32(p
+ 12, 0xe5bef008);
1120 if (s1
->sym_infos
[sym_index
].plt_thumb_stub
) {
1121 p
= section_ptr_add(plt
, 20);
1122 put32(p
, 0x4778); // bx pc
1123 put32(p
+2, 0x46c0); // nop
1126 p
= section_ptr_add(plt
, 16);
1127 put32(p
, 0xe59fc004); // ldr ip, [pc, #4] // offset in GOT
1128 put32(p
+4, 0xe08fc00c); // add ip, pc, ip // absolute address or offset
1129 put32(p
+8, 0xe59cf000); // ldr pc, [ip] // load absolute address or load offset
1130 put32(p
+12, s1
->got
->data_offset
);
1132 /* the symbol is modified so that it will be relocated to
1134 if (s1
->output_type
== TCC_OUTPUT_EXE
)
1135 offset
= plt
->data_offset
- 16;
1137 #elif defined(TCC_TARGET_C67)
1138 tcc_error("C67 got not implemented");
1140 #error unsupported CPU
1142 index
= put_elf_sym(s1
->dynsym
, offset
,
1143 size
, info
, 0, sym
->st_shndx
, name
);
1144 /* put a got entry */
1145 put_elf_reloc(s1
->dynsym
, s1
->got
,
1146 s1
->got
->data_offset
,
1149 ptr
= section_ptr_add(s1
->got
, PTR_SIZE
);
1153 /* build GOT and PLT entries */
1154 ST_FUNC
void build_got_entries(TCCState
*s1
)
1157 ElfW_Rel
*rel
, *rel_end
;
1159 int i
, type
, reloc_type
, sym_index
;
1161 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1162 s
= s1
->sections
[i
];
1163 if (s
->sh_type
!= SHT_RELX
)
1165 /* no need to handle got relocations */
1166 if (s
->link
!= symtab_section
)
1168 rel_end
= (ElfW_Rel
*)(s
->data
+ s
->data_offset
);
1169 for(rel
= (ElfW_Rel
*)s
->data
;
1172 type
= ELFW(R_TYPE
)(rel
->r_info
);
1174 #if defined(TCC_TARGET_I386)
1181 if (type
== R_386_GOT32
|| type
== R_386_PLT32
) {
1182 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1183 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1184 /* look at the symbol got offset. If none, then add one */
1185 if (type
== R_386_GOT32
)
1186 reloc_type
= R_386_GLOB_DAT
;
1188 reloc_type
= R_386_JMP_SLOT
;
1189 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1193 #elif defined(TCC_TARGET_ARM)
1194 case R_ARM_GOT_BREL
:
1195 case R_ARM_GOTOFF32
:
1196 case R_ARM_BASE_PREL
:
1200 if (type
== R_ARM_GOT_BREL
|| type
== R_ARM_PLT32
) {
1201 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1202 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1203 /* look at the symbol got offset. If none, then add one */
1204 if (type
== R_ARM_GOT_BREL
)
1205 reloc_type
= R_ARM_GLOB_DAT
;
1207 reloc_type
= R_ARM_JUMP_SLOT
;
1208 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1212 #elif defined(TCC_TARGET_C67)
1219 if (type
== R_C60_GOT32
|| type
== R_C60_PLT32
) {
1220 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1221 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1222 /* look at the symbol got offset. If none, then add one */
1223 if (type
== R_C60_GOT32
)
1224 reloc_type
= R_C60_GLOB_DAT
;
1226 reloc_type
= R_C60_JMP_SLOT
;
1227 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1231 #elif defined(TCC_TARGET_X86_64)
1232 case R_X86_64_GOT32
:
1233 case R_X86_64_GOTTPOFF
:
1234 case R_X86_64_GOTPCREL
:
1235 case R_X86_64_PLT32
:
1238 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
||
1239 type
== R_X86_64_PLT32
) {
1240 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1241 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1242 /* look at the symbol got offset. If none, then add one */
1243 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
)
1244 reloc_type
= R_X86_64_GLOB_DAT
;
1246 reloc_type
= R_X86_64_JUMP_SLOT
;
1247 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1252 #error unsupported CPU
1261 ST_FUNC Section
*new_symtab(TCCState
*s1
,
1262 const char *symtab_name
, int sh_type
, int sh_flags
,
1263 const char *strtab_name
,
1264 const char *hash_name
, int hash_sh_flags
)
1266 Section
*symtab
, *strtab
, *hash
;
1267 int *ptr
, nb_buckets
;
1269 symtab
= new_section(s1
, symtab_name
, sh_type
, sh_flags
);
1270 symtab
->sh_entsize
= sizeof(ElfW(Sym
));
1271 strtab
= new_section(s1
, strtab_name
, SHT_STRTAB
, sh_flags
);
1272 put_elf_str(strtab
, "");
1273 symtab
->link
= strtab
;
1274 put_elf_sym(symtab
, 0, 0, 0, 0, 0, NULL
);
1278 hash
= new_section(s1
, hash_name
, SHT_HASH
, hash_sh_flags
);
1279 hash
->sh_entsize
= sizeof(int);
1280 symtab
->hash
= hash
;
1281 hash
->link
= symtab
;
1283 ptr
= section_ptr_add(hash
, (2 + nb_buckets
+ 1) * sizeof(int));
1284 ptr
[0] = nb_buckets
;
1286 memset(ptr
+ 2, 0, (nb_buckets
+ 1) * sizeof(int));
1290 /* put dynamic tag */
1291 static void put_dt(Section
*dynamic
, int dt
, uplong val
)
1294 dyn
= section_ptr_add(dynamic
, sizeof(ElfW(Dyn
)));
1296 dyn
->d_un
.d_val
= val
;
1299 static void add_init_array_defines(TCCState
*s1
, const char *section_name
)
1303 char sym_start
[1024];
1306 snprintf(sym_start
, sizeof(sym_start
), "__%s_start", section_name
+ 1);
1307 snprintf(sym_end
, sizeof(sym_end
), "__%s_end", section_name
+ 1);
1309 s
= find_section(s1
, section_name
);
1314 end_offset
= s
->data_offset
;
1317 add_elf_sym(symtab_section
,
1319 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1320 s
->sh_num
, sym_start
);
1321 add_elf_sym(symtab_section
,
1323 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1324 s
->sh_num
, sym_end
);
1327 static int tcc_add_support(TCCState
*s1
, const char *filename
)
1330 snprintf(buf
, sizeof(buf
), "%s/%s", s1
->tcc_lib_path
, filename
);
1331 return tcc_add_file(s1
, buf
);
1334 ST_FUNC
void tcc_add_bcheck(TCCState
*s1
)
1336 #ifdef CONFIG_TCC_BCHECK
1338 Section
*init_section
;
1339 unsigned char *pinit
;
1342 if (0 == s1
->do_bounds_check
)
1345 /* XXX: add an object file to do that */
1346 ptr
= section_ptr_add(bounds_section
, sizeof(unsigned long));
1348 add_elf_sym(symtab_section
, 0, 0,
1349 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1350 bounds_section
->sh_num
, "__bounds_start");
1351 /* add bound check code */
1352 #ifndef TCC_TARGET_PE
1353 tcc_add_support(s1
, "bcheck.o");
1355 #ifdef TCC_TARGET_I386
1356 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
) {
1357 /* add 'call __bound_init()' in .init section */
1358 init_section
= find_section(s1
, ".init");
1359 pinit
= section_ptr_add(init_section
, 5);
1361 put32(pinit
+ 1, -4);
1362 sym_index
= find_elf_sym(symtab_section
, "__bound_init");
1363 put_elf_reloc(symtab_section
, init_section
,
1364 init_section
->data_offset
- 4, R_386_PC32
, sym_index
);
1370 /* add tcc runtime libraries */
1371 ST_FUNC
void tcc_add_runtime(TCCState
*s1
)
1376 if (!s1
->nostdlib
) {
1377 tcc_add_library(s1
, "c");
1378 #ifdef CONFIG_USE_LIBGCC
1379 tcc_add_file(s1
, TCC_LIBGCC
);
1380 #elif !defined WITHOUT_LIBTCC
1381 tcc_add_support(s1
, "libtcc1.a");
1383 /* add crt end if not memory output */
1384 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
)
1385 tcc_add_crt(s1
, "crtn.o");
1389 /* add various standard linker symbols (must be done after the
1390 sections are filled (for example after allocating common
1392 ST_FUNC
void tcc_add_linker_symbols(TCCState
*s1
)
1398 add_elf_sym(symtab_section
,
1399 text_section
->data_offset
, 0,
1400 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1401 text_section
->sh_num
, "_etext");
1402 add_elf_sym(symtab_section
,
1403 data_section
->data_offset
, 0,
1404 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1405 data_section
->sh_num
, "_edata");
1406 add_elf_sym(symtab_section
,
1407 bss_section
->data_offset
, 0,
1408 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1409 bss_section
->sh_num
, "_end");
1410 /* horrible new standard ldscript defines */
1411 add_init_array_defines(s1
, ".preinit_array");
1412 add_init_array_defines(s1
, ".init_array");
1413 add_init_array_defines(s1
, ".fini_array");
1415 /* add start and stop symbols for sections whose name can be
1417 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1418 s
= s1
->sections
[i
];
1419 if (s
->sh_type
== SHT_PROGBITS
&&
1420 (s
->sh_flags
& SHF_ALLOC
)) {
1424 /* check if section name can be expressed in C */
1430 if (!isid(ch
) && !isnum(ch
))
1434 snprintf(buf
, sizeof(buf
), "__start_%s", s
->name
);
1435 add_elf_sym(symtab_section
,
1437 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1439 snprintf(buf
, sizeof(buf
), "__stop_%s", s
->name
);
1440 add_elf_sym(symtab_section
,
1442 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1449 static void tcc_output_binary(TCCState
*s1
, FILE *f
,
1450 const int *section_order
)
1453 int i
, offset
, size
;
1456 for(i
=1;i
<s1
->nb_sections
;i
++) {
1457 s
= s1
->sections
[section_order
[i
]];
1458 if (s
->sh_type
!= SHT_NOBITS
&&
1459 (s
->sh_flags
& SHF_ALLOC
)) {
1460 while (offset
< s
->sh_offset
) {
1465 fwrite(s
->data
, 1, size
, f
);
1471 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1473 #define EXTRA_RELITEMS 14
1475 /* move the relocation value from .dynsym to .got */
1476 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1478 uint32_t *gotd
= (void *)s1
->got
->data
;
1479 ElfW(Sym
) *sym
, *sym_end
;
1481 gotd
+= 3; // dummy entries in .got
1482 /* relocate symbols in .dynsym */
1483 sym_end
= (ElfW(Sym
) *)(s
->data
+ s
->data_offset
);
1484 for (sym
= (ElfW(Sym
) *)s
->data
+ 1; sym
< sym_end
; sym
++) {
1485 if (sym
->st_shndx
== SHN_UNDEF
) {
1486 *gotd
++ = sym
->st_value
+ 6; // XXX 6 is magic ?
1493 #define EXTRA_RELITEMS 9
1495 /* zero plt offsets of weak symbols in .dynsym */
1496 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1498 ElfW(Sym
) *sym
, *sym_end
;
1500 sym_end
= (ElfW(Sym
) *)(s
->data
+ s
->data_offset
);
1501 for (sym
= (ElfW(Sym
) *)s
->data
+ 1; sym
< sym_end
; sym
++)
1502 if (sym
->st_shndx
== SHN_UNDEF
&& ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
1507 ST_FUNC
void fill_got_entry(TCCState
*s1
, ElfW_Rel
*rel
)
1509 int sym_index
= ELFW(R_SYM
) (rel
->r_info
);
1510 ElfW(Sym
) *sym
= &((ElfW(Sym
) *) symtab_section
->data
)[sym_index
];
1511 unsigned long offset
;
1513 if (sym_index
>= s1
->nb_sym_infos
)
1515 offset
= s1
->sym_infos
[sym_index
].got_offset
<< 1;
1516 section_reserve(s1
->got
, offset
+ PTR_SIZE
);
1517 #ifdef TCC_TARGET_X86_64
1518 /* only works for x86-64 */
1519 put32(s1
->got
->data
+ offset
+ 4, sym
->st_value
>> 32);
1521 put32(s1
->got
->data
+ offset
, sym
->st_value
& 0xffffffff);
1524 ST_FUNC
void fill_got(TCCState
*s1
)
1527 ElfW_Rel
*rel
, *rel_end
;
1530 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1531 s
= s1
->sections
[i
];
1532 if (s
->sh_type
!= SHT_RELX
)
1534 /* no need to handle got relocations */
1535 if (s
->link
!= symtab_section
)
1537 rel_end
= (ElfW_Rel
*) (s
->data
+ s
->data_offset
);
1538 for(rel
= (ElfW_Rel
*) s
->data
; rel
< rel_end
; rel
++) {
1539 switch (ELFW(R_TYPE
) (rel
->r_info
)) {
1540 case R_X86_64_GOT32
:
1541 case R_X86_64_GOTPCREL
:
1542 case R_X86_64_PLT32
:
1543 fill_got_entry(s1
, rel
);
1551 /* output an ELF file */
1552 /* XXX: suppress unneeded sections */
1553 static int elf_output_file(TCCState
*s1
, const char *filename
)
1559 int shnum
, i
, phnum
, file_offset
, offset
, size
, j
, sh_order_index
, k
;
1562 Section
*strsec
, *s
;
1563 ElfW(Shdr
) shdr
, *sh
;
1564 ElfW(Phdr
) *phdr
, *ph
;
1565 Section
*interp
, *dynamic
, *dynstr
;
1566 unsigned long saved_dynamic_data_offset
;
1568 int type
, file_type
;
1569 uplong rel_addr
, rel_size
;
1570 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1571 uplong bss_addr
, bss_size
;
1574 file_type
= s1
->output_type
;
1577 if (file_type
!= TCC_OUTPUT_OBJ
) {
1578 tcc_add_runtime(s1
);
1582 section_order
= NULL
;
1585 dynstr
= NULL
; /* avoid warning */
1586 saved_dynamic_data_offset
= 0; /* avoid warning */
1588 if (file_type
!= TCC_OUTPUT_OBJ
) {
1589 relocate_common_syms();
1591 tcc_add_linker_symbols(s1
);
1593 if (!s1
->static_link
) {
1595 int sym_index
, index
;
1596 ElfW(Sym
) *esym
, *sym_end
;
1598 if (file_type
== TCC_OUTPUT_EXE
) {
1600 /* allow override the dynamic loader */
1601 const char *elfint
= getenv("LD_SO");
1603 elfint
= CONFIG_TCC_ELFINTERP
;
1604 /* add interpreter section only if executable */
1605 interp
= new_section(s1
, ".interp", SHT_PROGBITS
, SHF_ALLOC
);
1606 interp
->sh_addralign
= 1;
1607 ptr
= section_ptr_add(interp
, 1+strlen(elfint
));
1608 strcpy(ptr
, elfint
);
1611 /* add dynamic symbol table */
1612 s1
->dynsym
= new_symtab(s1
, ".dynsym", SHT_DYNSYM
, SHF_ALLOC
,
1614 ".hash", SHF_ALLOC
);
1615 dynstr
= s1
->dynsym
->link
;
1617 /* add dynamic section */
1618 dynamic
= new_section(s1
, ".dynamic", SHT_DYNAMIC
,
1619 SHF_ALLOC
| SHF_WRITE
);
1620 dynamic
->link
= dynstr
;
1621 dynamic
->sh_entsize
= sizeof(ElfW(Dyn
));
1624 s1
->plt
= new_section(s1
, ".plt", SHT_PROGBITS
,
1625 SHF_ALLOC
| SHF_EXECINSTR
);
1626 s1
->plt
->sh_entsize
= 4;
1630 /* scan for undefined symbols and see if they are in the
1631 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1632 is found, then we add it in the PLT. If a symbol
1633 STT_OBJECT is found, we add it in the .bss section with
1634 a suitable relocation */
1635 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+
1636 symtab_section
->data_offset
);
1637 if (file_type
== TCC_OUTPUT_EXE
) {
1638 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
1641 if (sym
->st_shndx
== SHN_UNDEF
) {
1642 name
= symtab_section
->link
->data
+ sym
->st_name
;
1643 sym_index
= find_elf_sym(s1
->dynsymtab_section
, name
);
1645 esym
= &((ElfW(Sym
) *)s1
->dynsymtab_section
->data
)[sym_index
];
1646 type
= ELFW(ST_TYPE
)(esym
->st_info
);
1647 if ((type
== STT_FUNC
) || (type
== STT_GNU_IFUNC
)) {
1648 put_got_entry(s1
, R_JMP_SLOT
, esym
->st_size
,
1649 ELFW(ST_INFO
)(STB_GLOBAL
,type
),
1650 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1651 } else if (type
== STT_OBJECT
) {
1652 unsigned long offset
;
1653 ElfW(Sym
) *dynsym
, *dynsym_end
;
1654 offset
= bss_section
->data_offset
;
1655 /* XXX: which alignment ? */
1656 offset
= (offset
+ 16 - 1) & -16;
1657 index
= put_elf_sym(s1
->dynsym
, offset
, esym
->st_size
,
1659 bss_section
->sh_num
, name
);
1660 // Ensure R_COPY works for weak symbol aliases
1661 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1662 dynsym_end
= (ElfW(Sym
) *)
1663 (s1
->dynsymtab_section
->data
+
1664 s1
->dynsymtab_section
->data_offset
);
1665 for(dynsym
= (ElfW(Sym
) *)s1
->dynsymtab_section
->data
+ 1;
1666 dynsym
< dynsym_end
; dynsym
++) {
1667 if ((dynsym
->st_value
== esym
->st_value
)
1668 && (ELFW(ST_BIND
)(dynsym
->st_info
) == STB_GLOBAL
)) {
1670 dynname
= s1
->dynsymtab_section
->link
->data
1672 put_elf_sym(s1
->dynsym
, offset
,
1675 bss_section
->sh_num
,
1681 put_elf_reloc(s1
->dynsym
, bss_section
,
1682 offset
, R_COPY
, index
);
1683 offset
+= esym
->st_size
;
1684 bss_section
->data_offset
= offset
;
1687 /* STB_WEAK undefined symbols are accepted */
1688 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1690 if (ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
||
1691 !strcmp(name
, "_fp_hw")) {
1693 tcc_error_noabort("undefined symbol '%s'", name
);
1696 } else if (s1
->rdynamic
&&
1697 ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1698 /* if -rdynamic option, then export all non
1700 name
= symtab_section
->link
->data
+ sym
->st_name
;
1701 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1703 sym
->st_shndx
, name
);
1710 /* now look at unresolved dynamic symbols and export
1711 corresponding symbol */
1712 sym_end
= (ElfW(Sym
) *)(s1
->dynsymtab_section
->data
+
1713 s1
->dynsymtab_section
->data_offset
);
1714 for(esym
= (ElfW(Sym
) *)s1
->dynsymtab_section
->data
+ 1;
1717 if (esym
->st_shndx
== SHN_UNDEF
) {
1718 name
= s1
->dynsymtab_section
->link
->data
+ esym
->st_name
;
1719 sym_index
= find_elf_sym(symtab_section
, name
);
1721 /* XXX: avoid adding a symbol if already
1722 present because of -rdynamic ? */
1723 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1724 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1726 sym
->st_shndx
, name
);
1728 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1729 /* weak symbols can stay undefined */
1731 tcc_warning("undefined dynamic symbol '%s'", name
);
1738 /* shared library case : we simply export all the global symbols */
1739 nb_syms
= symtab_section
->data_offset
/ sizeof(ElfW(Sym
));
1740 s1
->symtab_to_dynsym
= tcc_mallocz(sizeof(int) * nb_syms
);
1741 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
1744 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1745 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1746 if ((ELFW(ST_TYPE
)(sym
->st_info
) == STT_FUNC
||
1747 ELFW(ST_TYPE
)(sym
->st_info
) == STT_GNU_IFUNC
)
1748 && sym
->st_shndx
== SHN_UNDEF
) {
1749 put_got_entry(s1
, R_JMP_SLOT
, sym
->st_size
,
1751 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1753 else if (ELFW(ST_TYPE
)(sym
->st_info
) == STT_OBJECT
) {
1754 put_got_entry(s1
, R_X86_64_GLOB_DAT
, sym
->st_size
,
1756 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1761 name
= symtab_section
->link
->data
+ sym
->st_name
;
1762 index
= put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1764 sym
->st_shndx
, name
);
1765 s1
->symtab_to_dynsym
[sym
-
1766 (ElfW(Sym
) *)symtab_section
->data
] =
1773 build_got_entries(s1
);
1775 /* add a list of needed dlls */
1776 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
1777 DLLReference
*dllref
= s1
->loaded_dlls
[i
];
1778 if (dllref
->level
== 0)
1779 put_dt(dynamic
, DT_NEEDED
, put_elf_str(dynstr
, dllref
->name
));
1783 put_dt(dynamic
, DT_RPATH
, put_elf_str(dynstr
, s1
->rpath
));
1785 /* XXX: currently, since we do not handle PIC code, we
1786 must relocate the readonly segments */
1787 if (file_type
== TCC_OUTPUT_DLL
) {
1789 put_dt(dynamic
, DT_SONAME
, put_elf_str(dynstr
, s1
->soname
));
1790 put_dt(dynamic
, DT_TEXTREL
, 0);
1794 put_dt(dynamic
, DT_SYMBOLIC
, 0);
1796 /* add necessary space for other entries */
1797 saved_dynamic_data_offset
= dynamic
->data_offset
;
1798 dynamic
->data_offset
+= sizeof(ElfW(Dyn
)) * EXTRA_RELITEMS
;
1800 /* still need to build got entries in case of static link */
1801 build_got_entries(s1
);
1805 memset(&ehdr
, 0, sizeof(ehdr
));
1807 /* we add a section for symbols */
1808 strsec
= new_section(s1
, ".shstrtab", SHT_STRTAB
, 0);
1809 put_elf_str(strsec
, "");
1811 /* compute number of sections */
1812 shnum
= s1
->nb_sections
;
1814 /* this array is used to reorder sections in the output file */
1815 section_order
= tcc_malloc(sizeof(int) * shnum
);
1816 section_order
[0] = 0;
1819 /* compute number of program headers */
1822 case TCC_OUTPUT_OBJ
:
1825 case TCC_OUTPUT_EXE
:
1826 if (!s1
->static_link
)
1827 phnum
= 4 + HAVE_PHDR
;
1831 case TCC_OUTPUT_DLL
:
1836 /* allocate strings for section names and decide if an unallocated
1837 section should be output */
1838 /* NOTE: the strsec section comes last, so its size is also
1840 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1841 s
= s1
->sections
[i
];
1842 s
->sh_name
= put_elf_str(strsec
, s
->name
);
1844 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1849 s
->reloc
? s
->reloc
->name
: "n"
1852 /* when generating a DLL, we include relocations but we may
1854 if (file_type
== TCC_OUTPUT_DLL
&&
1855 s
->sh_type
== SHT_RELX
&&
1856 !(s
->sh_flags
& SHF_ALLOC
)) {
1857 /* //gr: avoid bogus relocs for empty (debug) sections */
1858 if (s1
->sections
[s
->sh_info
]->sh_flags
& SHF_ALLOC
)
1859 prepare_dynamic_rel(s1
, s
);
1860 else if (s1
->do_debug
)
1861 s
->sh_size
= s
->data_offset
;
1862 } else if (s1
->do_debug
||
1863 file_type
== TCC_OUTPUT_OBJ
||
1864 (s
->sh_flags
& SHF_ALLOC
) ||
1865 i
== (s1
->nb_sections
- 1)) {
1866 /* we output all sections if debug or object file */
1867 s
->sh_size
= s
->data_offset
;
1871 /* allocate program segment headers */
1872 phdr
= tcc_mallocz(phnum
* sizeof(ElfW(Phdr
)));
1874 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1875 file_offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
1880 /* compute section to program header mapping */
1881 if (s1
->has_text_addr
) {
1882 int a_offset
, p_offset
;
1883 addr
= s1
->text_addr
;
1884 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1886 a_offset
= (int) (addr
& (s1
->section_align
- 1));
1887 p_offset
= file_offset
& (s1
->section_align
- 1);
1888 if (a_offset
< p_offset
)
1889 a_offset
+= s1
->section_align
;
1890 file_offset
+= (a_offset
- p_offset
);
1892 if (file_type
== TCC_OUTPUT_DLL
)
1895 addr
= ELF_START_ADDR
;
1896 /* compute address after headers */
1897 addr
+= (file_offset
& (s1
->section_align
- 1));
1900 /* dynamic relocation table information, for .dynamic section */
1904 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1905 bss_addr
= bss_size
= 0;
1907 /* leave one program header for the program interpreter */
1910 ph
+= 1 + HAVE_PHDR
;
1912 for(j
= 0; j
< 2; j
++) {
1913 ph
->p_type
= PT_LOAD
;
1915 ph
->p_flags
= PF_R
| PF_X
;
1917 ph
->p_flags
= PF_R
| PF_W
;
1918 ph
->p_align
= s1
->section_align
;
1920 /* we do the following ordering: interp, symbol tables,
1921 relocations, progbits, nobits */
1922 /* XXX: do faster and simpler sorting */
1923 for(k
= 0; k
< 5; k
++) {
1924 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1925 s
= s1
->sections
[i
];
1926 /* compute if section should be included */
1928 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1932 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1933 (SHF_ALLOC
| SHF_WRITE
))
1939 } else if (s
->sh_type
== SHT_DYNSYM
||
1940 s
->sh_type
== SHT_STRTAB
||
1941 s
->sh_type
== SHT_HASH
) {
1944 } else if (s
->sh_type
== SHT_RELX
) {
1947 } else if (s
->sh_type
== SHT_NOBITS
) {
1954 section_order
[sh_order_index
++] = i
;
1956 /* section matches: we align it and add its size */
1958 addr
= (addr
+ s
->sh_addralign
- 1) &
1959 ~(s
->sh_addralign
- 1);
1960 file_offset
+= (int) ( addr
- tmp
);
1961 s
->sh_offset
= file_offset
;
1964 /* update program header infos */
1965 if (ph
->p_offset
== 0) {
1966 ph
->p_offset
= file_offset
;
1968 ph
->p_paddr
= ph
->p_vaddr
;
1970 /* update dynamic relocation infos */
1971 if (s
->sh_type
== SHT_RELX
) {
1972 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1973 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.got")) { // rel_size == 0) {
1975 rel_size
+= s
->sh_size
; // XXX only first rel.
1977 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.bss")) { // rel_size == 0) {
1979 bss_size
= s
->sh_size
; // XXX only first rel.
1984 rel_size
+= s
->sh_size
;
1988 if (s
->sh_type
!= SHT_NOBITS
)
1989 file_offset
+= s
->sh_size
;
1992 ph
->p_filesz
= file_offset
- ph
->p_offset
;
1993 ph
->p_memsz
= addr
- ph
->p_vaddr
;
1996 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1997 /* if in the middle of a page, we duplicate the page in
1998 memory so that one copy is RX and the other is RW */
1999 if ((addr
& (s1
->section_align
- 1)) != 0)
2000 addr
+= s1
->section_align
;
2002 addr
= (addr
+ s1
->section_align
- 1) & ~(s1
->section_align
- 1);
2003 file_offset
= (file_offset
+ s1
->section_align
- 1) &
2004 ~(s1
->section_align
- 1);
2009 /* if interpreter, then add corresponing program header */
2013 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2015 int len
= phnum
* sizeof(ElfW(Phdr
));
2017 ph
->p_type
= PT_PHDR
;
2018 ph
->p_offset
= sizeof(ElfW(Ehdr
));
2019 ph
->p_vaddr
= interp
->sh_addr
- len
;
2020 ph
->p_paddr
= ph
->p_vaddr
;
2021 ph
->p_filesz
= ph
->p_memsz
= len
;
2022 ph
->p_flags
= PF_R
| PF_X
;
2023 ph
->p_align
= 4; // interp->sh_addralign;
2028 ph
->p_type
= PT_INTERP
;
2029 ph
->p_offset
= interp
->sh_offset
;
2030 ph
->p_vaddr
= interp
->sh_addr
;
2031 ph
->p_paddr
= ph
->p_vaddr
;
2032 ph
->p_filesz
= interp
->sh_size
;
2033 ph
->p_memsz
= interp
->sh_size
;
2035 ph
->p_align
= interp
->sh_addralign
;
2038 /* if dynamic section, then add corresponing program header */
2042 ph
= &phdr
[phnum
- 1];
2044 ph
->p_type
= PT_DYNAMIC
;
2045 ph
->p_offset
= dynamic
->sh_offset
;
2046 ph
->p_vaddr
= dynamic
->sh_addr
;
2047 ph
->p_paddr
= ph
->p_vaddr
;
2048 ph
->p_filesz
= dynamic
->sh_size
;
2049 ph
->p_memsz
= dynamic
->sh_size
;
2050 ph
->p_flags
= PF_R
| PF_W
;
2051 ph
->p_align
= dynamic
->sh_addralign
;
2053 /* put GOT dynamic section address */
2054 put32(s1
->got
->data
, dynamic
->sh_addr
);
2056 /* relocate the PLT */
2057 if (file_type
== TCC_OUTPUT_EXE
2058 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2059 || file_type
== TCC_OUTPUT_DLL
2065 p_end
= p
+ s1
->plt
->data_offset
;
2067 #if defined(TCC_TARGET_I386)
2068 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
2069 put32(p
+ 8, get32(p
+ 8) + s1
->got
->sh_addr
);
2072 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
2075 #elif defined(TCC_TARGET_X86_64)
2076 int x
= s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 6;
2077 put32(p
+ 2, get32(p
+ 2) + x
);
2078 put32(p
+ 8, get32(p
+ 8) + x
- 6);
2081 put32(p
+ 2, get32(p
+ 2) + x
+ s1
->plt
->data
- p
);
2084 #elif defined(TCC_TARGET_ARM)
2086 x
=s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 12;
2089 if (get32(p
) == 0x46c04778) /* PLT Thumb stub present */
2091 put32(p
+ 12, x
+ get32(p
+ 12) + s1
->plt
->data
- p
);
2094 #elif defined(TCC_TARGET_C67)
2097 #error unsupported CPU
2102 /* relocate symbols in .dynsym */
2103 sym_end
= (ElfW(Sym
) *)(s1
->dynsym
->data
+ s1
->dynsym
->data_offset
);
2104 for(sym
= (ElfW(Sym
) *)s1
->dynsym
->data
+ 1;
2107 if (sym
->st_shndx
== SHN_UNDEF
) {
2108 /* relocate to the PLT if the symbol corresponds
2111 sym
->st_value
+= s1
->plt
->sh_addr
;
2112 } else if (sym
->st_shndx
< SHN_LORESERVE
) {
2113 /* do symbol relocation */
2114 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
2118 /* put dynamic section entries */
2119 dynamic
->data_offset
= saved_dynamic_data_offset
;
2120 put_dt(dynamic
, DT_HASH
, s1
->dynsym
->hash
->sh_addr
);
2121 put_dt(dynamic
, DT_STRTAB
, dynstr
->sh_addr
);
2122 put_dt(dynamic
, DT_SYMTAB
, s1
->dynsym
->sh_addr
);
2123 put_dt(dynamic
, DT_STRSZ
, dynstr
->data_offset
);
2124 put_dt(dynamic
, DT_SYMENT
, sizeof(ElfW(Sym
)));
2125 #ifdef TCC_TARGET_X86_64
2126 put_dt(dynamic
, DT_RELA
, rel_addr
);
2127 put_dt(dynamic
, DT_RELASZ
, rel_size
);
2128 put_dt(dynamic
, DT_RELAENT
, sizeof(ElfW_Rel
));
2130 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2131 put_dt(dynamic
, DT_PLTGOT
, s1
->got
->sh_addr
);
2132 put_dt(dynamic
, DT_PLTRELSZ
, rel_size
);
2133 put_dt(dynamic
, DT_JMPREL
, rel_addr
);
2134 put_dt(dynamic
, DT_PLTREL
, DT_REL
);
2135 put_dt(dynamic
, DT_REL
, bss_addr
);
2136 put_dt(dynamic
, DT_RELSZ
, bss_size
);
2138 put_dt(dynamic
, DT_REL
, rel_addr
);
2139 put_dt(dynamic
, DT_RELSZ
, rel_size
);
2140 put_dt(dynamic
, DT_RELENT
, sizeof(ElfW_Rel
));
2144 put_dt(dynamic
, DT_DEBUG
, 0);
2145 put_dt(dynamic
, DT_NULL
, 0);
2148 ehdr
.e_phentsize
= sizeof(ElfW(Phdr
));
2149 ehdr
.e_phnum
= phnum
;
2150 ehdr
.e_phoff
= sizeof(ElfW(Ehdr
));
2153 /* all other sections come after */
2154 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2155 s
= s1
->sections
[i
];
2156 if (phnum
> 0 && (s
->sh_flags
& SHF_ALLOC
))
2158 section_order
[sh_order_index
++] = i
;
2160 file_offset
= (file_offset
+ s
->sh_addralign
- 1) &
2161 ~(s
->sh_addralign
- 1);
2162 s
->sh_offset
= file_offset
;
2163 if (s
->sh_type
!= SHT_NOBITS
)
2164 file_offset
+= s
->sh_size
;
2167 /* if building executable or DLL, then relocate each section
2168 except the GOT which is already relocated */
2169 if (file_type
!= TCC_OUTPUT_OBJ
) {
2170 relocate_syms(s1
, 0);
2172 if (s1
->nb_errors
!= 0) {
2178 /* relocate sections */
2179 /* XXX: ignore sections with allocated relocations ? */
2180 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2181 s
= s1
->sections
[i
];
2182 if (s
->reloc
&& s
!= s1
->got
&& (s
->sh_flags
& SHF_ALLOC
)) //gr
2183 relocate_section(s1
, s
);
2186 /* relocate relocation entries if the relocation tables are
2187 allocated in the executable */
2188 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2189 s
= s1
->sections
[i
];
2190 if ((s
->sh_flags
& SHF_ALLOC
) &&
2191 s
->sh_type
== SHT_RELX
) {
2192 relocate_rel(s1
, s
);
2196 /* get entry point address */
2197 if (file_type
== TCC_OUTPUT_EXE
)
2198 ehdr
.e_entry
= (uplong
)tcc_get_symbol_err(s1
, "_start");
2200 ehdr
.e_entry
= text_section
->sh_addr
; /* XXX: is it correct ? */
2202 if (file_type
== TCC_OUTPUT_EXE
&& s1
->static_link
)
2205 /* write elf file */
2206 if (file_type
== TCC_OUTPUT_OBJ
)
2211 fd
= open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
, mode
);
2213 tcc_error_noabort("could not write '%s'", filename
);
2216 f
= fdopen(fd
, "wb");
2218 printf("<- %s\n", filename
);
2220 #ifdef TCC_TARGET_COFF
2221 if (s1
->output_format
== TCC_OUTPUT_FORMAT_COFF
) {
2222 tcc_output_coff(s1
, f
);
2225 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
2226 sort_syms(s1
, symtab_section
);
2229 file_offset
= (file_offset
+ 3) & -4;
2232 ehdr
.e_ident
[0] = ELFMAG0
;
2233 ehdr
.e_ident
[1] = ELFMAG1
;
2234 ehdr
.e_ident
[2] = ELFMAG2
;
2235 ehdr
.e_ident
[3] = ELFMAG3
;
2236 ehdr
.e_ident
[4] = ELFCLASSW
;
2237 ehdr
.e_ident
[5] = ELFDATA2LSB
;
2238 ehdr
.e_ident
[6] = EV_CURRENT
;
2239 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2240 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_FREEBSD
;
2242 #ifdef TCC_TARGET_ARM
2244 ehdr
.e_ident
[EI_OSABI
] = 0;
2245 ehdr
.e_flags
= 4 << 24;
2247 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_ARM
;
2252 case TCC_OUTPUT_EXE
:
2253 ehdr
.e_type
= ET_EXEC
;
2255 case TCC_OUTPUT_DLL
:
2256 ehdr
.e_type
= ET_DYN
;
2258 case TCC_OUTPUT_OBJ
:
2259 ehdr
.e_type
= ET_REL
;
2262 ehdr
.e_machine
= EM_TCC_TARGET
;
2263 ehdr
.e_version
= EV_CURRENT
;
2264 ehdr
.e_shoff
= file_offset
;
2265 ehdr
.e_ehsize
= sizeof(ElfW(Ehdr
));
2266 ehdr
.e_shentsize
= sizeof(ElfW(Shdr
));
2267 ehdr
.e_shnum
= shnum
;
2268 ehdr
.e_shstrndx
= shnum
- 1;
2270 fwrite(&ehdr
, 1, sizeof(ElfW(Ehdr
)), f
);
2271 fwrite(phdr
, 1, phnum
* sizeof(ElfW(Phdr
)), f
);
2272 offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
2274 for(i
=1;i
<s1
->nb_sections
;i
++) {
2275 s
= s1
->sections
[section_order
[i
]];
2276 if (s
->sh_type
!= SHT_NOBITS
) {
2277 if (s
->sh_type
== SHT_DYNSYM
)
2278 patch_dynsym_undef(s1
, s
);
2279 while (offset
< s
->sh_offset
) {
2284 fwrite(s
->data
, 1, size
, f
);
2289 /* output section headers */
2290 while (offset
< ehdr
.e_shoff
) {
2295 for(i
=0;i
<s1
->nb_sections
;i
++) {
2297 memset(sh
, 0, sizeof(ElfW(Shdr
)));
2298 s
= s1
->sections
[i
];
2300 sh
->sh_name
= s
->sh_name
;
2301 sh
->sh_type
= s
->sh_type
;
2302 sh
->sh_flags
= s
->sh_flags
;
2303 sh
->sh_entsize
= s
->sh_entsize
;
2304 sh
->sh_info
= s
->sh_info
;
2306 sh
->sh_link
= s
->link
->sh_num
;
2307 sh
->sh_addralign
= s
->sh_addralign
;
2308 sh
->sh_addr
= s
->sh_addr
;
2309 sh
->sh_offset
= s
->sh_offset
;
2310 sh
->sh_size
= s
->sh_size
;
2312 fwrite(sh
, 1, sizeof(ElfW(Shdr
)), f
);
2315 tcc_output_binary(s1
, f
, section_order
);
2321 tcc_free(s1
->symtab_to_dynsym
);
2322 tcc_free(section_order
);
2324 tcc_free(s1
->sym_infos
);
2328 LIBTCCAPI
int tcc_output_file(TCCState
*s
, const char *filename
)
2331 #ifdef TCC_TARGET_PE
2332 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
2333 ret
= pe_output_file(s
, filename
);
2337 ret
= elf_output_file(s
, filename
);
2342 static void *load_data(int fd
, unsigned long file_offset
, unsigned long size
)
2346 data
= tcc_malloc(size
);
2347 lseek(fd
, file_offset
, SEEK_SET
);
2348 read(fd
, data
, size
);
2352 typedef struct SectionMergeInfo
{
2353 Section
*s
; /* corresponding existing section */
2354 unsigned long offset
; /* offset of the new section in the existing section */
2355 uint8_t new_section
; /* true if section 's' was added */
2356 uint8_t link_once
; /* true if link once section */
2359 /* load an object file and merge it with current files */
2360 /* XXX: handle correctly stab (debug) info */
2361 ST_FUNC
int tcc_load_object_file(TCCState
*s1
,
2362 int fd
, unsigned long file_offset
)
2365 ElfW(Shdr
) *shdr
, *sh
;
2366 int size
, i
, j
, offset
, offseti
, nb_syms
, sym_index
, ret
;
2367 unsigned char *strsec
, *strtab
;
2368 int *old_to_new_syms
;
2369 char *sh_name
, *name
;
2370 SectionMergeInfo
*sm_table
, *sm
;
2371 ElfW(Sym
) *sym
, *symtab
;
2372 ElfW_Rel
*rel
, *rel_end
;
2378 stab_index
= stabstr_index
= 0;
2380 if (read(fd
, &ehdr
, sizeof(ehdr
)) != sizeof(ehdr
))
2382 if (ehdr
.e_ident
[0] != ELFMAG0
||
2383 ehdr
.e_ident
[1] != ELFMAG1
||
2384 ehdr
.e_ident
[2] != ELFMAG2
||
2385 ehdr
.e_ident
[3] != ELFMAG3
)
2387 /* test if object file */
2388 if (ehdr
.e_type
!= ET_REL
)
2390 /* test CPU specific stuff */
2391 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2392 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2394 tcc_error_noabort("invalid object file");
2398 shdr
= load_data(fd
, file_offset
+ ehdr
.e_shoff
,
2399 sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2400 sm_table
= tcc_mallocz(sizeof(SectionMergeInfo
) * ehdr
.e_shnum
);
2402 /* load section names */
2403 sh
= &shdr
[ehdr
.e_shstrndx
];
2404 strsec
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2406 /* load symtab and strtab */
2407 old_to_new_syms
= NULL
;
2411 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2413 if (sh
->sh_type
== SHT_SYMTAB
) {
2415 tcc_error_noabort("object must contain only one symtab");
2420 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2421 symtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2422 sm_table
[i
].s
= symtab_section
;
2424 /* now load strtab */
2425 sh
= &shdr
[sh
->sh_link
];
2426 strtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2430 /* now examine each section and try to merge its content with the
2432 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2433 /* no need to examine section name strtab */
2434 if (i
== ehdr
.e_shstrndx
)
2437 sh_name
= strsec
+ sh
->sh_name
;
2438 /* ignore sections types we do not handle */
2439 if (sh
->sh_type
!= SHT_PROGBITS
&&
2440 sh
->sh_type
!= SHT_RELX
&&
2442 sh
->sh_type
!= SHT_ARM_EXIDX
&&
2444 sh
->sh_type
!= SHT_NOBITS
&&
2445 sh
->sh_type
!= SHT_PREINIT_ARRAY
&&
2446 sh
->sh_type
!= SHT_INIT_ARRAY
&&
2447 sh
->sh_type
!= SHT_FINI_ARRAY
&&
2448 strcmp(sh_name
, ".stabstr")
2451 if (sh
->sh_addralign
< 1)
2452 sh
->sh_addralign
= 1;
2453 /* find corresponding section, if any */
2454 for(j
= 1; j
< s1
->nb_sections
;j
++) {
2455 s
= s1
->sections
[j
];
2456 if (!strcmp(s
->name
, sh_name
)) {
2457 if (!strncmp(sh_name
, ".gnu.linkonce",
2458 sizeof(".gnu.linkonce") - 1)) {
2459 /* if a 'linkonce' section is already present, we
2460 do not add it again. It is a little tricky as
2461 symbols can still be defined in
2463 sm_table
[i
].link_once
= 1;
2470 /* not found: create new section */
2471 s
= new_section(s1
, sh_name
, sh
->sh_type
, sh
->sh_flags
);
2472 /* take as much info as possible from the section. sh_link and
2473 sh_info will be updated later */
2474 s
->sh_addralign
= sh
->sh_addralign
;
2475 s
->sh_entsize
= sh
->sh_entsize
;
2476 sm_table
[i
].new_section
= 1;
2478 if (sh
->sh_type
!= s
->sh_type
) {
2479 tcc_error_noabort("invalid section type");
2483 /* align start of section */
2484 offset
= s
->data_offset
;
2486 if (0 == strcmp(sh_name
, ".stab")) {
2490 if (0 == strcmp(sh_name
, ".stabstr")) {
2495 size
= sh
->sh_addralign
- 1;
2496 offset
= (offset
+ size
) & ~size
;
2497 if (sh
->sh_addralign
> s
->sh_addralign
)
2498 s
->sh_addralign
= sh
->sh_addralign
;
2499 s
->data_offset
= offset
;
2501 sm_table
[i
].offset
= offset
;
2503 /* concatenate sections */
2505 if (sh
->sh_type
!= SHT_NOBITS
) {
2507 lseek(fd
, file_offset
+ sh
->sh_offset
, SEEK_SET
);
2508 ptr
= section_ptr_add(s
, size
);
2509 read(fd
, ptr
, size
);
2511 s
->data_offset
+= size
;
2516 /* //gr relocate stab strings */
2517 if (stab_index
&& stabstr_index
) {
2520 s
= sm_table
[stab_index
].s
;
2521 a
= (Stab_Sym
*)(s
->data
+ sm_table
[stab_index
].offset
);
2522 b
= (Stab_Sym
*)(s
->data
+ s
->data_offset
);
2523 o
= sm_table
[stabstr_index
].offset
;
2525 a
->n_strx
+= o
, a
++;
2528 /* second short pass to update sh_link and sh_info fields of new
2530 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2532 if (!s
|| !sm_table
[i
].new_section
)
2535 if (sh
->sh_link
> 0)
2536 s
->link
= sm_table
[sh
->sh_link
].s
;
2537 if (sh
->sh_type
== SHT_RELX
) {
2538 s
->sh_info
= sm_table
[sh
->sh_info
].s
->sh_num
;
2539 /* update backward link */
2540 s1
->sections
[s
->sh_info
]->reloc
= s
;
2545 /* resolve symbols */
2546 old_to_new_syms
= tcc_mallocz(nb_syms
* sizeof(int));
2549 for(i
= 1; i
< nb_syms
; i
++, sym
++) {
2550 if (sym
->st_shndx
!= SHN_UNDEF
&&
2551 sym
->st_shndx
< SHN_LORESERVE
) {
2552 sm
= &sm_table
[sym
->st_shndx
];
2553 if (sm
->link_once
) {
2554 /* if a symbol is in a link once section, we use the
2555 already defined symbol. It is very important to get
2556 correct relocations */
2557 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
2558 name
= strtab
+ sym
->st_name
;
2559 sym_index
= find_elf_sym(symtab_section
, name
);
2561 old_to_new_syms
[i
] = sym_index
;
2565 /* if no corresponding section added, no need to add symbol */
2568 /* convert section number */
2569 sym
->st_shndx
= sm
->s
->sh_num
;
2571 sym
->st_value
+= sm
->offset
;
2574 name
= strtab
+ sym
->st_name
;
2575 sym_index
= add_elf_sym(symtab_section
, sym
->st_value
, sym
->st_size
,
2576 sym
->st_info
, sym
->st_other
,
2577 sym
->st_shndx
, name
);
2578 old_to_new_syms
[i
] = sym_index
;
2581 /* third pass to patch relocation entries */
2582 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2587 offset
= sm_table
[i
].offset
;
2588 switch(s
->sh_type
) {
2590 /* take relocation offset information */
2591 offseti
= sm_table
[sh
->sh_info
].offset
;
2592 rel_end
= (ElfW_Rel
*)(s
->data
+ s
->data_offset
);
2593 for(rel
= (ElfW_Rel
*)(s
->data
+ offset
);
2598 /* convert symbol index */
2599 type
= ELFW(R_TYPE
)(rel
->r_info
);
2600 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
2601 /* NOTE: only one symtab assumed */
2602 if (sym_index
>= nb_syms
)
2604 sym_index
= old_to_new_syms
[sym_index
];
2605 /* ignore link_once in rel section. */
2606 if (!sym_index
&& !sm
->link_once
2607 #ifdef TCC_TARGET_ARM
2608 && type
!= R_ARM_V4BX
2612 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2613 i
, strsec
+ sh
->sh_name
, rel
->r_offset
);
2616 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
2617 /* offset the relocation offset */
2618 rel
->r_offset
+= offseti
;
2619 #ifdef TCC_TARGET_ARM
2620 /* Jumps and branches from a Thumb code to a PLT entry need
2621 special handling since PLT entries are ARM code.
2622 Unconditional bl instructions referencing PLT entries are
2623 handled by converting these instructions into blx
2624 instructions. Other case of instructions referencing a PLT
2625 entry require to add a Thumb stub before the PLT entry to
2626 switch to ARM mode. We set bit 0 of the got offset of a
2627 symbol to indicate such a case. */
2628 if (type
== R_ARM_THM_JUMP24
) {
2629 put_plt_thumb_stub(s1
, sym_index
, 1);
2643 tcc_free(old_to_new_syms
);
2650 typedef struct ArchiveHeader
{
2651 char ar_name
[16]; /* name of this member */
2652 char ar_date
[12]; /* file mtime */
2653 char ar_uid
[6]; /* owner uid; printed as decimal */
2654 char ar_gid
[6]; /* owner gid; printed as decimal */
2655 char ar_mode
[8]; /* file mode, printed as octal */
2656 char ar_size
[10]; /* file size, printed as decimal */
2657 char ar_fmag
[2]; /* should contain ARFMAG */
2660 static int get_be32(const uint8_t *b
)
2662 return b
[3] | (b
[2] << 8) | (b
[1] << 16) | (b
[0] << 24);
2665 /* load only the objects which resolve undefined symbols */
2666 static int tcc_load_alacarte(TCCState
*s1
, int fd
, int size
)
2668 int i
, bound
, nsyms
, sym_index
, off
, ret
;
2670 const char *ar_names
, *p
;
2671 const uint8_t *ar_index
;
2674 data
= tcc_malloc(size
);
2675 if (read(fd
, data
, size
) != size
)
2677 nsyms
= get_be32(data
);
2678 ar_index
= data
+ 4;
2679 ar_names
= ar_index
+ nsyms
* 4;
2683 for(p
= ar_names
, i
= 0; i
< nsyms
; i
++, p
+= strlen(p
)+1) {
2684 sym_index
= find_elf_sym(symtab_section
, p
);
2686 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
2687 if(sym
->st_shndx
== SHN_UNDEF
) {
2688 off
= get_be32(ar_index
+ i
* 4) + sizeof(ArchiveHeader
);
2690 printf("%5d\t%s\t%08x\n", i
, p
, sym
->st_shndx
);
2693 lseek(fd
, off
, SEEK_SET
);
2694 if(tcc_load_object_file(s1
, fd
, off
) < 0) {
2709 /* load a '.a' file */
2710 ST_FUNC
int tcc_load_archive(TCCState
*s1
, int fd
)
2717 unsigned long file_offset
;
2719 /* skip magic which was already checked */
2720 read(fd
, magic
, sizeof(magic
));
2723 len
= read(fd
, &hdr
, sizeof(hdr
));
2726 if (len
!= sizeof(hdr
)) {
2727 tcc_error_noabort("invalid archive");
2730 memcpy(ar_size
, hdr
.ar_size
, sizeof(hdr
.ar_size
));
2731 ar_size
[sizeof(hdr
.ar_size
)] = '\0';
2732 size
= strtol(ar_size
, NULL
, 0);
2733 memcpy(ar_name
, hdr
.ar_name
, sizeof(hdr
.ar_name
));
2734 for(i
= sizeof(hdr
.ar_name
) - 1; i
>= 0; i
--) {
2735 if (ar_name
[i
] != ' ')
2738 ar_name
[i
+ 1] = '\0';
2739 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2740 file_offset
= lseek(fd
, 0, SEEK_CUR
);
2742 size
= (size
+ 1) & ~1;
2743 if (!strcmp(ar_name
, "/")) {
2744 /* coff symbol table : we handle it */
2745 if(s1
->alacarte_link
)
2746 return tcc_load_alacarte(s1
, fd
, size
);
2747 } else if (!strcmp(ar_name
, "//") ||
2748 !strcmp(ar_name
, "__.SYMDEF") ||
2749 !strcmp(ar_name
, "__.SYMDEF/") ||
2750 !strcmp(ar_name
, "ARFILENAMES/")) {
2751 /* skip symbol table or archive names */
2753 if (tcc_load_object_file(s1
, fd
, file_offset
) < 0)
2756 lseek(fd
, file_offset
+ size
, SEEK_SET
);
2761 #ifndef TCC_TARGET_PE
2762 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2763 is referenced by the user (so it should be added as DT_NEEDED in
2764 the generated ELF file) */
2765 ST_FUNC
int tcc_load_dll(TCCState
*s1
, int fd
, const char *filename
, int level
)
2768 ElfW(Shdr
) *shdr
, *sh
, *sh1
;
2769 int i
, j
, nb_syms
, nb_dts
, sym_bind
, ret
;
2770 ElfW(Sym
) *sym
, *dynsym
;
2771 ElfW(Dyn
) *dt
, *dynamic
;
2772 unsigned char *dynstr
;
2773 const char *name
, *soname
;
2774 DLLReference
*dllref
;
2776 read(fd
, &ehdr
, sizeof(ehdr
));
2778 /* test CPU specific stuff */
2779 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2780 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2781 tcc_error_noabort("bad architecture");
2786 shdr
= load_data(fd
, ehdr
.e_shoff
, sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2788 /* load dynamic section and dynamic symbols */
2792 dynsym
= NULL
; /* avoid warning */
2793 dynstr
= NULL
; /* avoid warning */
2794 for(i
= 0, sh
= shdr
; i
< ehdr
.e_shnum
; i
++, sh
++) {
2795 switch(sh
->sh_type
) {
2797 nb_dts
= sh
->sh_size
/ sizeof(ElfW(Dyn
));
2798 dynamic
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2801 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2802 dynsym
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2803 sh1
= &shdr
[sh
->sh_link
];
2804 dynstr
= load_data(fd
, sh1
->sh_offset
, sh1
->sh_size
);
2811 /* compute the real library name */
2812 soname
= tcc_basename(filename
);
2814 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2815 if (dt
->d_tag
== DT_SONAME
) {
2816 soname
= dynstr
+ dt
->d_un
.d_val
;
2820 /* if the dll is already loaded, do not load it */
2821 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
2822 dllref
= s1
->loaded_dlls
[i
];
2823 if (!strcmp(soname
, dllref
->name
)) {
2824 /* but update level if needed */
2825 if (level
< dllref
->level
)
2826 dllref
->level
= level
;
2832 // printf("loading dll '%s'\n", soname);
2834 /* add the dll and its level */
2835 dllref
= tcc_mallocz(sizeof(DLLReference
) + strlen(soname
));
2836 dllref
->level
= level
;
2837 strcpy(dllref
->name
, soname
);
2838 dynarray_add((void ***)&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
, dllref
);
2840 /* add dynamic symbols in dynsym_section */
2841 for(i
= 1, sym
= dynsym
+ 1; i
< nb_syms
; i
++, sym
++) {
2842 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
2843 if (sym_bind
== STB_LOCAL
)
2845 name
= dynstr
+ sym
->st_name
;
2846 add_elf_sym(s1
->dynsymtab_section
, sym
->st_value
, sym
->st_size
,
2847 sym
->st_info
, sym
->st_other
, sym
->st_shndx
, name
);
2850 /* load all referenced DLLs */
2851 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2854 name
= dynstr
+ dt
->d_un
.d_val
;
2855 for(j
= 0; j
< s1
->nb_loaded_dlls
; j
++) {
2856 dllref
= s1
->loaded_dlls
[j
];
2857 if (!strcmp(name
, dllref
->name
))
2858 goto already_loaded
;
2860 if (tcc_add_dll(s1
, name
, AFF_REFERENCED_DLL
) < 0) {
2861 tcc_error_noabort("referenced dll '%s' not found", name
);
2878 #define LD_TOK_NAME 256
2879 #define LD_TOK_EOF (-1)
2881 /* return next ld script token */
2882 static int ld_next(TCCState
*s1
, char *name
, int name_size
)
2900 file
->buf_ptr
= parse_comment(file
->buf_ptr
);
2901 ch
= file
->buf_ptr
[0];
2909 /* case 'a' ... 'z': */
2936 /* case 'A' ... 'z': */
2971 if (!((ch
>= 'a' && ch
<= 'z') ||
2972 (ch
>= 'A' && ch
<= 'Z') ||
2973 (ch
>= '0' && ch
<= '9') ||
2974 strchr("/.-_+=$:\\,~", ch
)))
2976 if ((q
- name
) < name_size
- 1) {
2993 printf("tok=%c %d\n", c
, c
);
2994 if (c
== LD_TOK_NAME
)
2995 printf(" name=%s\n", name
);
3001 * Extract the file name from the library name
3003 * /!\ No test on filename capacity, be careful
3005 static void libname_to_filename(TCCState
*s1
, const char libname
[], char filename
[])
3007 if (!s1
->static_link
) {
3008 sprintf(filename
, "lib%s.so", libname
);
3010 sprintf(filename
, "lib%s.a", libname
);
3014 static int ld_add_file(TCCState
*s1
, const char filename
[])
3018 ret
= tcc_add_file_internal(s1
, filename
, 0);
3020 ret
= tcc_add_dll(s1
, filename
, 0);
3024 static inline int new_undef_syms(void)
3027 ret
= new_undef_sym
;
3032 static int ld_add_file_list(TCCState
*s1
, const char *cmd
, int as_needed
)
3034 char filename
[1024], libname
[1024];
3035 int t
, group
, nblibs
= 0, ret
= 0;
3038 group
= !strcmp(cmd
, "GROUP");
3041 t
= ld_next(s1
, filename
, sizeof(filename
));
3044 t
= ld_next(s1
, filename
, sizeof(filename
));
3047 if (t
== LD_TOK_EOF
) {
3048 tcc_error_noabort("unexpected end of file");
3050 goto lib_parse_error
;
3051 } else if (t
== ')') {
3053 } else if (t
== '-') {
3054 t
= ld_next(s1
, filename
, sizeof(filename
));
3055 if ((t
!= LD_TOK_NAME
) || (filename
[0] != 'l')) {
3056 tcc_error_noabort("library name expected");
3058 goto lib_parse_error
;
3060 strcpy(libname
, &filename
[1]);
3061 libname_to_filename(s1
, libname
, filename
);
3062 } else if (t
!= LD_TOK_NAME
) {
3063 tcc_error_noabort("filename expected");
3065 goto lib_parse_error
;
3067 if (!strcmp(filename
, "AS_NEEDED")) {
3068 ret
= ld_add_file_list(s1
, cmd
, 1);
3070 goto lib_parse_error
;
3072 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3074 ret
= ld_add_file(s1
, filename
);
3076 goto lib_parse_error
;
3078 /* Add the filename *and* the libname to avoid future conversions */
3079 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(filename
));
3080 if (libname
[0] != '\0')
3081 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(libname
));
3085 t
= ld_next(s1
, filename
, sizeof(filename
));
3087 t
= ld_next(s1
, filename
, sizeof(filename
));
3090 if (group
&& !as_needed
) {
3091 while (new_undef_syms()) {
3094 for (i
= 0; i
< nblibs
; i
++)
3095 ld_add_file(s1
, libs
[i
]);
3099 dynarray_reset(&libs
, &nblibs
);
3103 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3105 ST_FUNC
int tcc_load_ldscript(TCCState
*s1
)
3108 char filename
[1024];
3111 ch
= file
->buf_ptr
[0];
3114 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3115 if (t
== LD_TOK_EOF
)
3117 else if (t
!= LD_TOK_NAME
)
3119 if (!strcmp(cmd
, "INPUT") ||
3120 !strcmp(cmd
, "GROUP")) {
3121 ret
= ld_add_file_list(s1
, cmd
, 0);
3124 } else if (!strcmp(cmd
, "OUTPUT_FORMAT") ||
3125 !strcmp(cmd
, "TARGET")) {
3126 /* ignore some commands */
3127 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3131 t
= ld_next(s1
, filename
, sizeof(filename
));
3132 if (t
== LD_TOK_EOF
) {
3133 tcc_error_noabort("unexpected end of file");
3135 } else if (t
== ')') {
3145 #endif /* ndef TCC_TARGET_PE */