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 */
621 if ((x
& 3) || x
>= 0x4000000 || x
< -0x4000000)
622 if (!(x
& 3) || !blx_avail
|| !is_call
)
623 tcc_error("can't relocate value at %x",addr
);
626 /* Only reached if blx is avail and it is a call */
629 (*(int *)ptr
) = 0xfa << 24; /* bl -> blx */
634 /* Since these relocations only concern Thumb-2 and blx instruction was
635 introduced before Thumb-2, we can assume blx is available and not
638 case R_ARM_THM_JUMP24
:
640 int x
, hi
, lo
, s
, j1
, j2
, i1
, i2
, imm10
, imm11
;
641 int to_thumb
, is_call
, to_plt
, blx_bit
= 1 << 12;
645 if (sym
->st_shndx
== SHN_UNDEF
&&
646 ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
649 /* Get initial offset */
650 hi
= (*(uint16_t *)ptr
);
651 lo
= (*(uint16_t *)(ptr
+2));
659 x
= (s
<< 24) | (i1
<< 23) | (i2
<< 22) |
660 (imm10
<< 12) | (imm11
<< 1);
664 /* Relocation infos */
667 to_plt
= (val
>= plt
->sh_addr
) &&
668 (val
< plt
->sh_addr
+ plt
->data_offset
);
669 is_call
= (type
== R_ARM_THM_CALL
);
671 /* Compute final offset */
672 if (to_plt
&& !is_call
) /* Point to 1st instr of Thumb stub */
675 if (!to_thumb
&& is_call
) {
676 blx_bit
= 0; /* bl -> blx */
677 x
= (x
+ 3) & -4; /* Compute offset from aligned PC */
680 /* Check that relocation is possible
681 * offset must not be out of range
682 * if target is to be entered in arm mode:
684 - instruction must be a call (bl) or a jump to PLT */
685 if (!to_thumb
|| x
>= 0x1000000 || x
< -0x1000000)
686 if (to_thumb
|| (val
& 2) || (!is_call
&& !to_plt
))
687 tcc_error("can't relocate value at %x",addr
);
689 /* Compute and store final offset */
695 imm10
= (x
>> 12) & 0x3ff;
696 imm11
= (x
>> 1) & 0x7ff;
697 (*(uint16_t *)ptr
) = (uint16_t) ((hi
& 0xf800) |
699 (*(uint16_t *)(ptr
+2)) = (uint16_t) ((lo
& 0xc000) |
700 (j1
<< 13) | blx_bit
| (j2
<< 11) |
705 case R_ARM_MOVW_ABS_NC
:
708 if (type
== R_ARM_MOVT_ABS
)
711 imm4
= (val
>> 12) & 0xf;
712 x
= (imm4
<< 16) | imm12
;
713 if (type
== R_ARM_THM_MOVT_ABS
)
719 case R_ARM_THM_MOVT_ABS
:
720 case R_ARM_THM_MOVW_ABS_NC
:
722 int x
, i
, imm4
, imm3
, imm8
;
723 if (type
== R_ARM_THM_MOVT_ABS
)
726 imm3
= (val
>> 8) & 0x7;
728 imm4
= (val
>> 12) & 0xf;
729 x
= (imm3
<< 28) | (imm8
<< 16) | (i
<< 10) | imm4
;
730 if (type
== R_ARM_THM_MOVT_ABS
)
739 x
= (*(int *)ptr
) & 0x7fffffff;
740 (*(int *)ptr
) &= 0x80000000;
743 if((x
^(x
>>1))&0x40000000)
744 tcc_error("can't relocate value at %x",addr
);
745 (*(int *)ptr
) |= x
& 0x7fffffff;
751 *(int *)ptr
+= val
- addr
;
753 case R_ARM_BASE_PREL
:
754 *(int *)ptr
+= s1
->got
->sh_addr
- addr
;
757 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
760 /* we load the got offset */
761 *(int *)ptr
+= s1
->sym_infos
[sym_index
].got_offset
<< 1;
766 /* trade Thumb support for ARMv4 support */
767 if ((0x0ffffff0 & *(int*)ptr
) == 0x012FFF10)
768 *(int*)ptr
^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
771 fprintf(stderr
,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
772 type
, (unsigned)addr
, (unsigned)(uplong
)ptr
, (unsigned)val
);
774 #elif defined(TCC_TARGET_C67)
782 /* put the low 16 bits of the absolute address */
783 // add to what is already there
785 orig
= ((*(int *)(ptr
)) >> 7) & 0xffff;
786 orig
|= (((*(int *)(ptr
+4)) >> 7) & 0xffff) << 16;
788 //patch both at once - assumes always in pairs Low - High
790 *(int *) ptr
= (*(int *) ptr
& (~(0xffff << 7)) ) | (((val
+orig
) & 0xffff) << 7);
791 *(int *)(ptr
+4) = (*(int *)(ptr
+4) & (~(0xffff << 7)) ) | ((((val
+orig
)>>16) & 0xffff) << 7);
797 fprintf(stderr
,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
798 type
, (unsigned)addr
, (unsigned)(uplong
)ptr
, (unsigned)val
);
800 #elif defined(TCC_TARGET_X86_64)
802 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
803 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
804 qrel
->r_addend
= *(long long *)ptr
+ val
;
807 *(long long *)ptr
+= val
;
811 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
812 /* XXX: this logic may depend on TCC's codegen
813 now TCC uses R_X86_64_32 even for a 64bit pointer */
814 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
815 qrel
->r_addend
= *(int *)ptr
+ val
;
822 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
824 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
826 qrel
->r_offset
= rel
->r_offset
;
827 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_X86_64_PC32
);
828 qrel
->r_addend
= *(int *)ptr
;
834 case R_X86_64_PLT32
: {
836 diff
= (long long)val
- addr
;
837 if (diff
<= -2147483647 || diff
> 2147483647) {
838 #ifndef TCC_TARGET_PE
839 /* XXX: naive support for over 32bit jump */
840 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
841 val
= (add_jmp_table(s1
, val
- rel
->r_addend
) +
846 if (diff
<= -2147483647 || diff
> 2147483647) {
847 tcc_error("internal error: relocation failed");
853 case R_X86_64_GLOB_DAT
:
854 case R_X86_64_JUMP_SLOT
:
855 /* They don't need addend */
856 *(int *)ptr
= val
- rel
->r_addend
;
858 case R_X86_64_GOTPCREL
:
859 #ifndef TCC_TARGET_PE
860 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
861 val
= add_got_table(s1
, val
- rel
->r_addend
) + rel
->r_addend
;
862 *(int *)ptr
+= val
- addr
;
866 *(int *)ptr
+= (s1
->got
->sh_addr
- addr
+
867 (s1
->sym_infos
[sym_index
].got_offset
<< 1) - 4);
869 case R_X86_64_GOTTPOFF
:
870 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
873 /* we load the got offset */
874 *(int *)ptr
+= s1
->sym_infos
[sym_index
].got_offset
<< 1;
877 #error unsupported processor
881 /* if the relocation is allocated, we change its symbol table */
882 if (sr
->sh_flags
& SHF_ALLOC
)
883 sr
->link
= s1
->dynsym
;
886 /* relocate relocation table in 'sr' */
887 static void relocate_rel(TCCState
*s1
, Section
*sr
)
890 ElfW_Rel
*rel
, *rel_end
;
892 s
= s1
->sections
[sr
->sh_info
];
893 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
894 for(rel
= (ElfW_Rel
*)sr
->data
;
897 rel
->r_offset
+= s
->sh_addr
;
901 /* count the number of dynamic relocations so that we can reserve
903 static int prepare_dynamic_rel(TCCState
*s1
, Section
*sr
)
905 ElfW_Rel
*rel
, *rel_end
;
906 int sym_index
, esym_index
, type
, count
;
909 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
910 for(rel
= (ElfW_Rel
*)sr
->data
; rel
< rel_end
; rel
++) {
911 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
912 type
= ELFW(R_TYPE
)(rel
->r_info
);
914 #if defined(TCC_TARGET_I386)
916 #elif defined(TCC_TARGET_X86_64)
923 #if defined(TCC_TARGET_I386)
925 #elif defined(TCC_TARGET_X86_64)
928 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
937 /* allocate the section */
938 sr
->sh_flags
|= SHF_ALLOC
;
939 sr
->sh_size
= count
* sizeof(ElfW_Rel
);
944 static void put_sym_info(TCCState
*s1
, int index
)
947 typeof(s1
->sym_infos
) tab
;
949 if (index
>= s1
->nb_sym_infos
) {
950 /* find immediately bigger power of 2 and reallocate array */
954 tab
= tcc_realloc(s1
->sym_infos
, n
* sizeof(unsigned long));
956 memset(s1
->sym_infos
+ s1
->nb_sym_infos
, 0,
957 (n
- s1
->nb_sym_infos
) * sizeof(unsigned long));
958 s1
->nb_sym_infos
= n
;
962 #ifdef TCC_TARGET_ARM
963 static void put_plt_thumb_stub(TCCState
*s1
, int index
, unsigned char bit
)
965 put_sym_info(s1
, index
);
966 s1
->sym_infos
[index
].plt_thumb_stub
= bit
;
970 static void put_got_offset(TCCState
*s1
, int index
, unsigned long val
)
972 put_sym_info(s1
, index
);
973 s1
->sym_infos
[index
].got_offset
= val
>> 1;
976 /* XXX: suppress that */
977 static void put32(unsigned char *p
, uint32_t val
)
985 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
986 defined(TCC_TARGET_X86_64)
987 static uint32_t get32(unsigned char *p
)
989 return p
[0] | (p
[1] << 8) | (p
[2] << 16) | (p
[3] << 24);
993 static void build_got(TCCState
*s1
)
997 /* if no got, then create it */
998 s1
->got
= new_section(s1
, ".got", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
999 s1
->got
->sh_entsize
= 4;
1000 add_elf_sym(symtab_section
, 0, 4, ELFW(ST_INFO
)(STB_GLOBAL
, STT_OBJECT
),
1001 0, s1
->got
->sh_num
, "_GLOBAL_OFFSET_TABLE_");
1002 ptr
= section_ptr_add(s1
->got
, 3 * PTR_SIZE
);
1004 /* keep space for _DYNAMIC pointer, if present */
1006 /* two dummy got entries */
1010 /* keep space for _DYNAMIC pointer, if present */
1013 /* two dummy got entries */
1021 /* put a got entry corresponding to a symbol in symtab_section. 'size'
1022 and 'info' can be modifed if more precise info comes from the DLL */
1023 static void put_got_entry(TCCState
*s1
,
1024 int reloc_type
, unsigned long size
, int info
,
1030 unsigned long offset
;
1036 /* if a got entry already exists for that symbol, no need to add one */
1037 if (sym_index
< s1
->nb_sym_infos
&&
1038 s1
->sym_infos
[sym_index
].got_offset
<< 1)
1041 put_got_offset(s1
, sym_index
, s1
->got
->data_offset
);
1044 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1045 name
= symtab_section
->link
->data
+ sym
->st_name
;
1046 offset
= sym
->st_value
;
1047 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1049 #ifdef TCC_TARGET_X86_64
1059 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1062 /* if we build a DLL, we add a %ebx offset */
1063 if (s1
->output_type
== TCC_OUTPUT_DLL
)
1069 /* add a PLT entry */
1071 if (plt
->data_offset
== 0) {
1072 /* first plt entry */
1073 p
= section_ptr_add(plt
, 16);
1074 p
[0] = 0xff; /* pushl got + PTR_SIZE */
1075 p
[1] = modrm
+ 0x10;
1076 put32(p
+ 2, PTR_SIZE
);
1077 p
[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1079 put32(p
+ 8, PTR_SIZE
* 2);
1082 p
= section_ptr_add(plt
, 16);
1083 p
[0] = 0xff; /* jmp *(got + x) */
1085 put32(p
+ 2, s1
->got
->data_offset
);
1086 p
[6] = 0x68; /* push $xxx */
1087 put32(p
+ 7, (plt
->data_offset
- 32) >> 1);
1088 p
[11] = 0xe9; /* jmp plt_start */
1089 put32(p
+ 12, -(plt
->data_offset
));
1091 /* the symbol is modified so that it will be relocated to
1093 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
1094 if (s1
->output_type
== TCC_OUTPUT_EXE
)
1096 offset
= plt
->data_offset
- 16;
1098 #elif defined(TCC_TARGET_ARM)
1099 if (reloc_type
== R_ARM_JUMP_SLOT
) {
1103 /* if we build a DLL, we add a %ebx offset */
1104 if (s1
->output_type
== TCC_OUTPUT_DLL
)
1105 tcc_error("DLLs unimplemented!");
1107 /* add a PLT entry */
1109 if (plt
->data_offset
== 0) {
1110 /* first plt entry */
1111 p
= section_ptr_add(plt
, 16);
1112 put32(p
, 0xe52de004);
1113 put32(p
+ 4, 0xe59fe010);
1114 put32(p
+ 8, 0xe08fe00e);
1115 put32(p
+ 12, 0xe5bef008);
1118 if (s1
->sym_infos
[sym_index
].plt_thumb_stub
) {
1119 p
= section_ptr_add(plt
, 20);
1120 put32(p
, 0x4778); // bx pc
1121 put32(p
+2, 0x46c0); // nop
1124 p
= section_ptr_add(plt
, 16);
1125 put32(p
, 0xe59fc004); // ldr ip, [pc, #4] // offset in GOT
1126 put32(p
+4, 0xe08fc00c); // add ip, pc, ip // absolute address or offset
1127 put32(p
+8, 0xe59cf000); // ldr pc, [ip] // load absolute address or load offset
1128 put32(p
+12, s1
->got
->data_offset
);
1130 /* the symbol is modified so that it will be relocated to
1132 if (s1
->output_type
== TCC_OUTPUT_EXE
)
1133 offset
= plt
->data_offset
- 16;
1135 #elif defined(TCC_TARGET_C67)
1136 tcc_error("C67 got not implemented");
1138 #error unsupported CPU
1140 index
= put_elf_sym(s1
->dynsym
, offset
,
1141 size
, info
, 0, sym
->st_shndx
, name
);
1142 /* put a got entry */
1143 put_elf_reloc(s1
->dynsym
, s1
->got
,
1144 s1
->got
->data_offset
,
1147 ptr
= section_ptr_add(s1
->got
, PTR_SIZE
);
1151 /* build GOT and PLT entries */
1152 ST_FUNC
void build_got_entries(TCCState
*s1
)
1155 ElfW_Rel
*rel
, *rel_end
;
1157 int i
, type
, reloc_type
, sym_index
;
1159 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1160 s
= s1
->sections
[i
];
1161 if (s
->sh_type
!= SHT_RELX
)
1163 /* no need to handle got relocations */
1164 if (s
->link
!= symtab_section
)
1166 rel_end
= (ElfW_Rel
*)(s
->data
+ s
->data_offset
);
1167 for(rel
= (ElfW_Rel
*)s
->data
;
1170 type
= ELFW(R_TYPE
)(rel
->r_info
);
1172 #if defined(TCC_TARGET_I386)
1179 if (type
== R_386_GOT32
|| type
== R_386_PLT32
) {
1180 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1181 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1182 /* look at the symbol got offset. If none, then add one */
1183 if (type
== R_386_GOT32
)
1184 reloc_type
= R_386_GLOB_DAT
;
1186 reloc_type
= R_386_JMP_SLOT
;
1187 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1191 #elif defined(TCC_TARGET_ARM)
1192 case R_ARM_GOT_BREL
:
1193 case R_ARM_GOTOFF32
:
1194 case R_ARM_BASE_PREL
:
1198 if (type
== R_ARM_GOT_BREL
|| type
== R_ARM_PLT32
) {
1199 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1200 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1201 /* look at the symbol got offset. If none, then add one */
1202 if (type
== R_ARM_GOT_BREL
)
1203 reloc_type
= R_ARM_GLOB_DAT
;
1205 reloc_type
= R_ARM_JUMP_SLOT
;
1206 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1210 #elif defined(TCC_TARGET_C67)
1217 if (type
== R_C60_GOT32
|| type
== R_C60_PLT32
) {
1218 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1219 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1220 /* look at the symbol got offset. If none, then add one */
1221 if (type
== R_C60_GOT32
)
1222 reloc_type
= R_C60_GLOB_DAT
;
1224 reloc_type
= R_C60_JMP_SLOT
;
1225 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1229 #elif defined(TCC_TARGET_X86_64)
1230 case R_X86_64_GOT32
:
1231 case R_X86_64_GOTTPOFF
:
1232 case R_X86_64_GOTPCREL
:
1233 case R_X86_64_PLT32
:
1236 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
||
1237 type
== R_X86_64_PLT32
) {
1238 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1239 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1240 /* look at the symbol got offset. If none, then add one */
1241 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
)
1242 reloc_type
= R_X86_64_GLOB_DAT
;
1244 reloc_type
= R_X86_64_JUMP_SLOT
;
1245 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1250 #error unsupported CPU
1259 ST_FUNC Section
*new_symtab(TCCState
*s1
,
1260 const char *symtab_name
, int sh_type
, int sh_flags
,
1261 const char *strtab_name
,
1262 const char *hash_name
, int hash_sh_flags
)
1264 Section
*symtab
, *strtab
, *hash
;
1265 int *ptr
, nb_buckets
;
1267 symtab
= new_section(s1
, symtab_name
, sh_type
, sh_flags
);
1268 symtab
->sh_entsize
= sizeof(ElfW(Sym
));
1269 strtab
= new_section(s1
, strtab_name
, SHT_STRTAB
, sh_flags
);
1270 put_elf_str(strtab
, "");
1271 symtab
->link
= strtab
;
1272 put_elf_sym(symtab
, 0, 0, 0, 0, 0, NULL
);
1276 hash
= new_section(s1
, hash_name
, SHT_HASH
, hash_sh_flags
);
1277 hash
->sh_entsize
= sizeof(int);
1278 symtab
->hash
= hash
;
1279 hash
->link
= symtab
;
1281 ptr
= section_ptr_add(hash
, (2 + nb_buckets
+ 1) * sizeof(int));
1282 ptr
[0] = nb_buckets
;
1284 memset(ptr
+ 2, 0, (nb_buckets
+ 1) * sizeof(int));
1288 /* put dynamic tag */
1289 static void put_dt(Section
*dynamic
, int dt
, uplong val
)
1292 dyn
= section_ptr_add(dynamic
, sizeof(ElfW(Dyn
)));
1294 dyn
->d_un
.d_val
= val
;
1297 static void add_init_array_defines(TCCState
*s1
, const char *section_name
)
1301 char sym_start
[1024];
1304 snprintf(sym_start
, sizeof(sym_start
), "__%s_start", section_name
+ 1);
1305 snprintf(sym_end
, sizeof(sym_end
), "__%s_end", section_name
+ 1);
1307 s
= find_section(s1
, section_name
);
1312 end_offset
= s
->data_offset
;
1315 add_elf_sym(symtab_section
,
1317 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1318 s
->sh_num
, sym_start
);
1319 add_elf_sym(symtab_section
,
1321 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1322 s
->sh_num
, sym_end
);
1325 static int tcc_add_support(TCCState
*s1
, const char *filename
)
1328 snprintf(buf
, sizeof(buf
), "%s/%s", s1
->tcc_lib_path
, filename
);
1329 return tcc_add_file(s1
, buf
);
1332 ST_FUNC
void tcc_add_bcheck(TCCState
*s1
)
1334 #ifdef CONFIG_TCC_BCHECK
1336 Section
*init_section
;
1337 unsigned char *pinit
;
1340 if (0 == s1
->do_bounds_check
)
1343 /* XXX: add an object file to do that */
1344 ptr
= section_ptr_add(bounds_section
, sizeof(unsigned long));
1346 add_elf_sym(symtab_section
, 0, 0,
1347 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1348 bounds_section
->sh_num
, "__bounds_start");
1349 /* add bound check code */
1350 #ifndef TCC_TARGET_PE
1351 tcc_add_support(s1
, "bcheck.o");
1353 #ifdef TCC_TARGET_I386
1354 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
) {
1355 /* add 'call __bound_init()' in .init section */
1356 init_section
= find_section(s1
, ".init");
1357 pinit
= section_ptr_add(init_section
, 5);
1359 put32(pinit
+ 1, -4);
1360 sym_index
= find_elf_sym(symtab_section
, "__bound_init");
1361 put_elf_reloc(symtab_section
, init_section
,
1362 init_section
->data_offset
- 4, R_386_PC32
, sym_index
);
1368 /* add tcc runtime libraries */
1369 ST_FUNC
void tcc_add_runtime(TCCState
*s1
)
1374 if (!s1
->nostdlib
) {
1375 tcc_add_library(s1
, "c");
1376 #ifdef CONFIG_USE_LIBGCC
1377 tcc_add_file(s1
, TCC_LIBGCC
);
1378 #elif !defined WITHOUT_LIBTCC
1379 tcc_add_support(s1
, "libtcc1.a");
1381 /* add crt end if not memory output */
1382 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
)
1383 tcc_add_crt(s1
, "crtn.o");
1387 /* add various standard linker symbols (must be done after the
1388 sections are filled (for example after allocating common
1390 ST_FUNC
void tcc_add_linker_symbols(TCCState
*s1
)
1396 add_elf_sym(symtab_section
,
1397 text_section
->data_offset
, 0,
1398 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1399 text_section
->sh_num
, "_etext");
1400 add_elf_sym(symtab_section
,
1401 data_section
->data_offset
, 0,
1402 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1403 data_section
->sh_num
, "_edata");
1404 add_elf_sym(symtab_section
,
1405 bss_section
->data_offset
, 0,
1406 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1407 bss_section
->sh_num
, "_end");
1408 /* horrible new standard ldscript defines */
1409 add_init_array_defines(s1
, ".preinit_array");
1410 add_init_array_defines(s1
, ".init_array");
1411 add_init_array_defines(s1
, ".fini_array");
1413 /* add start and stop symbols for sections whose name can be
1415 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1416 s
= s1
->sections
[i
];
1417 if (s
->sh_type
== SHT_PROGBITS
&&
1418 (s
->sh_flags
& SHF_ALLOC
)) {
1422 /* check if section name can be expressed in C */
1428 if (!isid(ch
) && !isnum(ch
))
1432 snprintf(buf
, sizeof(buf
), "__start_%s", s
->name
);
1433 add_elf_sym(symtab_section
,
1435 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1437 snprintf(buf
, sizeof(buf
), "__stop_%s", s
->name
);
1438 add_elf_sym(symtab_section
,
1440 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1447 static void tcc_output_binary(TCCState
*s1
, FILE *f
,
1448 const int *section_order
)
1451 int i
, offset
, size
;
1454 for(i
=1;i
<s1
->nb_sections
;i
++) {
1455 s
= s1
->sections
[section_order
[i
]];
1456 if (s
->sh_type
!= SHT_NOBITS
&&
1457 (s
->sh_flags
& SHF_ALLOC
)) {
1458 while (offset
< s
->sh_offset
) {
1463 fwrite(s
->data
, 1, size
, f
);
1469 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1471 #define EXTRA_RELITEMS 14
1473 /* move the relocation value from .dynsym to .got */
1474 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1476 uint32_t *gotd
= (void *)s1
->got
->data
;
1477 ElfW(Sym
) *sym
, *sym_end
;
1479 gotd
+= 3; // dummy entries in .got
1480 /* relocate symbols in .dynsym */
1481 sym_end
= (ElfW(Sym
) *)(s
->data
+ s
->data_offset
);
1482 for (sym
= (ElfW(Sym
) *)s
->data
+ 1; sym
< sym_end
; sym
++) {
1483 if (sym
->st_shndx
== SHN_UNDEF
) {
1484 *gotd
++ = sym
->st_value
+ 6; // XXX 6 is magic ?
1491 #define EXTRA_RELITEMS 9
1493 /* zero plt offsets of weak symbols in .dynsym */
1494 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1496 ElfW(Sym
) *sym
, *sym_end
;
1498 sym_end
= (ElfW(Sym
) *)(s
->data
+ s
->data_offset
);
1499 for (sym
= (ElfW(Sym
) *)s
->data
+ 1; sym
< sym_end
; sym
++)
1500 if (sym
->st_shndx
== SHN_UNDEF
&& ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
1505 ST_FUNC
void fill_got_entry(TCCState
*s1
, ElfW_Rel
*rel
)
1507 int sym_index
= ELFW(R_SYM
) (rel
->r_info
);
1508 ElfW(Sym
) *sym
= &((ElfW(Sym
) *) symtab_section
->data
)[sym_index
];
1509 unsigned long offset
;
1511 if (sym_index
>= s1
->nb_sym_infos
)
1513 offset
= s1
->sym_infos
[sym_index
].got_offset
<< 1;
1514 section_reserve(s1
->got
, offset
+ PTR_SIZE
);
1515 #ifdef TCC_TARGET_X86_64
1516 /* only works for x86-64 */
1517 put32(s1
->got
->data
+ offset
+ 4, sym
->st_value
>> 32);
1519 put32(s1
->got
->data
+ offset
, sym
->st_value
& 0xffffffff);
1522 ST_FUNC
void fill_got(TCCState
*s1
)
1525 ElfW_Rel
*rel
, *rel_end
;
1528 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1529 s
= s1
->sections
[i
];
1530 if (s
->sh_type
!= SHT_RELX
)
1532 /* no need to handle got relocations */
1533 if (s
->link
!= symtab_section
)
1535 rel_end
= (ElfW_Rel
*) (s
->data
+ s
->data_offset
);
1536 for(rel
= (ElfW_Rel
*) s
->data
; rel
< rel_end
; rel
++) {
1537 switch (ELFW(R_TYPE
) (rel
->r_info
)) {
1538 case R_X86_64_GOT32
:
1539 case R_X86_64_GOTPCREL
:
1540 case R_X86_64_PLT32
:
1541 fill_got_entry(s1
, rel
);
1549 /* output an ELF file */
1550 /* XXX: suppress unneeded sections */
1551 static int elf_output_file(TCCState
*s1
, const char *filename
)
1557 int shnum
, i
, phnum
, file_offset
, offset
, size
, j
, sh_order_index
, k
;
1560 Section
*strsec
, *s
;
1561 ElfW(Shdr
) shdr
, *sh
;
1562 ElfW(Phdr
) *phdr
, *ph
;
1563 Section
*interp
, *dynamic
, *dynstr
;
1564 unsigned long saved_dynamic_data_offset
;
1566 int type
, file_type
;
1567 uplong rel_addr
, rel_size
;
1568 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1569 uplong bss_addr
, bss_size
;
1572 file_type
= s1
->output_type
;
1575 if (file_type
!= TCC_OUTPUT_OBJ
) {
1576 tcc_add_runtime(s1
);
1580 section_order
= NULL
;
1583 dynstr
= NULL
; /* avoid warning */
1584 saved_dynamic_data_offset
= 0; /* avoid warning */
1586 if (file_type
!= TCC_OUTPUT_OBJ
) {
1587 relocate_common_syms();
1589 tcc_add_linker_symbols(s1
);
1591 if (!s1
->static_link
) {
1593 int sym_index
, index
;
1594 ElfW(Sym
) *esym
, *sym_end
;
1596 if (file_type
== TCC_OUTPUT_EXE
) {
1598 /* allow override the dynamic loader */
1599 const char *elfint
= getenv("LD_SO");
1601 elfint
= CONFIG_TCC_ELFINTERP
;
1602 /* add interpreter section only if executable */
1603 interp
= new_section(s1
, ".interp", SHT_PROGBITS
, SHF_ALLOC
);
1604 interp
->sh_addralign
= 1;
1605 ptr
= section_ptr_add(interp
, 1+strlen(elfint
));
1606 strcpy(ptr
, elfint
);
1609 /* add dynamic symbol table */
1610 s1
->dynsym
= new_symtab(s1
, ".dynsym", SHT_DYNSYM
, SHF_ALLOC
,
1612 ".hash", SHF_ALLOC
);
1613 dynstr
= s1
->dynsym
->link
;
1615 /* add dynamic section */
1616 dynamic
= new_section(s1
, ".dynamic", SHT_DYNAMIC
,
1617 SHF_ALLOC
| SHF_WRITE
);
1618 dynamic
->link
= dynstr
;
1619 dynamic
->sh_entsize
= sizeof(ElfW(Dyn
));
1622 s1
->plt
= new_section(s1
, ".plt", SHT_PROGBITS
,
1623 SHF_ALLOC
| SHF_EXECINSTR
);
1624 s1
->plt
->sh_entsize
= 4;
1628 /* scan for undefined symbols and see if they are in the
1629 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1630 is found, then we add it in the PLT. If a symbol
1631 STT_OBJECT is found, we add it in the .bss section with
1632 a suitable relocation */
1633 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+
1634 symtab_section
->data_offset
);
1635 if (file_type
== TCC_OUTPUT_EXE
) {
1636 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
1639 if (sym
->st_shndx
== SHN_UNDEF
) {
1640 name
= symtab_section
->link
->data
+ sym
->st_name
;
1641 sym_index
= find_elf_sym(s1
->dynsymtab_section
, name
);
1643 esym
= &((ElfW(Sym
) *)s1
->dynsymtab_section
->data
)[sym_index
];
1644 type
= ELFW(ST_TYPE
)(esym
->st_info
);
1645 if ((type
== STT_FUNC
) || (type
== STT_GNU_IFUNC
)) {
1646 put_got_entry(s1
, R_JMP_SLOT
, esym
->st_size
,
1647 ELFW(ST_INFO
)(STB_GLOBAL
,type
),
1648 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1649 } else if (type
== STT_OBJECT
) {
1650 unsigned long offset
;
1651 ElfW(Sym
) *dynsym
, *dynsym_end
;
1652 offset
= bss_section
->data_offset
;
1653 /* XXX: which alignment ? */
1654 offset
= (offset
+ 16 - 1) & -16;
1655 index
= put_elf_sym(s1
->dynsym
, offset
, esym
->st_size
,
1657 bss_section
->sh_num
, name
);
1658 // Ensure R_COPY works for weak symbol aliases
1659 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1660 dynsym_end
= (ElfW(Sym
) *)
1661 (s1
->dynsymtab_section
->data
+
1662 s1
->dynsymtab_section
->data_offset
);
1663 for(dynsym
= (ElfW(Sym
) *)s1
->dynsymtab_section
->data
+ 1;
1664 dynsym
< dynsym_end
; dynsym
++) {
1665 if ((dynsym
->st_value
== esym
->st_value
)
1666 && (ELFW(ST_BIND
)(dynsym
->st_info
) == STB_GLOBAL
)) {
1668 dynname
= s1
->dynsymtab_section
->link
->data
1670 put_elf_sym(s1
->dynsym
, offset
,
1673 bss_section
->sh_num
,
1679 put_elf_reloc(s1
->dynsym
, bss_section
,
1680 offset
, R_COPY
, index
);
1681 offset
+= esym
->st_size
;
1682 bss_section
->data_offset
= offset
;
1685 /* STB_WEAK undefined symbols are accepted */
1686 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1688 if (ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
||
1689 !strcmp(name
, "_fp_hw")) {
1691 tcc_error_noabort("undefined symbol '%s'", name
);
1694 } else if (s1
->rdynamic
&&
1695 ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1696 /* if -rdynamic option, then export all non
1698 name
= symtab_section
->link
->data
+ sym
->st_name
;
1699 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1701 sym
->st_shndx
, name
);
1708 /* now look at unresolved dynamic symbols and export
1709 corresponding symbol */
1710 sym_end
= (ElfW(Sym
) *)(s1
->dynsymtab_section
->data
+
1711 s1
->dynsymtab_section
->data_offset
);
1712 for(esym
= (ElfW(Sym
) *)s1
->dynsymtab_section
->data
+ 1;
1715 if (esym
->st_shndx
== SHN_UNDEF
) {
1716 name
= s1
->dynsymtab_section
->link
->data
+ esym
->st_name
;
1717 sym_index
= find_elf_sym(symtab_section
, name
);
1719 /* XXX: avoid adding a symbol if already
1720 present because of -rdynamic ? */
1721 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1722 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1724 sym
->st_shndx
, name
);
1726 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1727 /* weak symbols can stay undefined */
1729 tcc_warning("undefined dynamic symbol '%s'", name
);
1736 /* shared library case : we simply export all the global symbols */
1737 nb_syms
= symtab_section
->data_offset
/ sizeof(ElfW(Sym
));
1738 s1
->symtab_to_dynsym
= tcc_mallocz(sizeof(int) * nb_syms
);
1739 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
1742 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1743 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1744 if ((ELFW(ST_TYPE
)(sym
->st_info
) == STT_FUNC
||
1745 ELFW(ST_TYPE
)(sym
->st_info
) == STT_GNU_IFUNC
)
1746 && sym
->st_shndx
== SHN_UNDEF
) {
1747 put_got_entry(s1
, R_JMP_SLOT
, sym
->st_size
,
1749 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1751 else if (ELFW(ST_TYPE
)(sym
->st_info
) == STT_OBJECT
) {
1752 put_got_entry(s1
, R_X86_64_GLOB_DAT
, sym
->st_size
,
1754 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1759 name
= symtab_section
->link
->data
+ sym
->st_name
;
1760 index
= put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1762 sym
->st_shndx
, name
);
1763 s1
->symtab_to_dynsym
[sym
-
1764 (ElfW(Sym
) *)symtab_section
->data
] =
1771 build_got_entries(s1
);
1773 /* add a list of needed dlls */
1774 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
1775 DLLReference
*dllref
= s1
->loaded_dlls
[i
];
1776 if (dllref
->level
== 0)
1777 put_dt(dynamic
, DT_NEEDED
, put_elf_str(dynstr
, dllref
->name
));
1781 put_dt(dynamic
, DT_RPATH
, put_elf_str(dynstr
, s1
->rpath
));
1783 /* XXX: currently, since we do not handle PIC code, we
1784 must relocate the readonly segments */
1785 if (file_type
== TCC_OUTPUT_DLL
) {
1787 put_dt(dynamic
, DT_SONAME
, put_elf_str(dynstr
, s1
->soname
));
1788 put_dt(dynamic
, DT_TEXTREL
, 0);
1792 put_dt(dynamic
, DT_SYMBOLIC
, 0);
1794 /* add necessary space for other entries */
1795 saved_dynamic_data_offset
= dynamic
->data_offset
;
1796 dynamic
->data_offset
+= sizeof(ElfW(Dyn
)) * EXTRA_RELITEMS
;
1798 /* still need to build got entries in case of static link */
1799 build_got_entries(s1
);
1803 memset(&ehdr
, 0, sizeof(ehdr
));
1805 /* we add a section for symbols */
1806 strsec
= new_section(s1
, ".shstrtab", SHT_STRTAB
, 0);
1807 put_elf_str(strsec
, "");
1809 /* compute number of sections */
1810 shnum
= s1
->nb_sections
;
1812 /* this array is used to reorder sections in the output file */
1813 section_order
= tcc_malloc(sizeof(int) * shnum
);
1814 section_order
[0] = 0;
1817 /* compute number of program headers */
1820 case TCC_OUTPUT_OBJ
:
1823 case TCC_OUTPUT_EXE
:
1824 if (!s1
->static_link
)
1825 phnum
= 4 + HAVE_PHDR
;
1829 case TCC_OUTPUT_DLL
:
1834 /* allocate strings for section names and decide if an unallocated
1835 section should be output */
1836 /* NOTE: the strsec section comes last, so its size is also
1838 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1839 s
= s1
->sections
[i
];
1840 s
->sh_name
= put_elf_str(strsec
, s
->name
);
1842 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1847 s
->reloc
? s
->reloc
->name
: "n"
1850 /* when generating a DLL, we include relocations but we may
1852 if (file_type
== TCC_OUTPUT_DLL
&&
1853 s
->sh_type
== SHT_RELX
&&
1854 !(s
->sh_flags
& SHF_ALLOC
)) {
1855 /* //gr: avoid bogus relocs for empty (debug) sections */
1856 if (s1
->sections
[s
->sh_info
]->sh_flags
& SHF_ALLOC
)
1857 prepare_dynamic_rel(s1
, s
);
1858 else if (s1
->do_debug
)
1859 s
->sh_size
= s
->data_offset
;
1860 } else if (s1
->do_debug
||
1861 file_type
== TCC_OUTPUT_OBJ
||
1862 (s
->sh_flags
& SHF_ALLOC
) ||
1863 i
== (s1
->nb_sections
- 1)) {
1864 /* we output all sections if debug or object file */
1865 s
->sh_size
= s
->data_offset
;
1869 /* allocate program segment headers */
1870 phdr
= tcc_mallocz(phnum
* sizeof(ElfW(Phdr
)));
1872 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1873 file_offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
1878 /* compute section to program header mapping */
1879 if (s1
->has_text_addr
) {
1880 int a_offset
, p_offset
;
1881 addr
= s1
->text_addr
;
1882 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1884 a_offset
= (int) (addr
& (s1
->section_align
- 1));
1885 p_offset
= file_offset
& (s1
->section_align
- 1);
1886 if (a_offset
< p_offset
)
1887 a_offset
+= s1
->section_align
;
1888 file_offset
+= (a_offset
- p_offset
);
1890 if (file_type
== TCC_OUTPUT_DLL
)
1893 addr
= ELF_START_ADDR
;
1894 /* compute address after headers */
1895 addr
+= (file_offset
& (s1
->section_align
- 1));
1898 /* dynamic relocation table information, for .dynamic section */
1902 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1903 bss_addr
= bss_size
= 0;
1905 /* leave one program header for the program interpreter */
1908 ph
+= 1 + HAVE_PHDR
;
1910 for(j
= 0; j
< 2; j
++) {
1911 ph
->p_type
= PT_LOAD
;
1913 ph
->p_flags
= PF_R
| PF_X
;
1915 ph
->p_flags
= PF_R
| PF_W
;
1916 ph
->p_align
= s1
->section_align
;
1918 /* we do the following ordering: interp, symbol tables,
1919 relocations, progbits, nobits */
1920 /* XXX: do faster and simpler sorting */
1921 for(k
= 0; k
< 5; k
++) {
1922 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1923 s
= s1
->sections
[i
];
1924 /* compute if section should be included */
1926 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1930 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1931 (SHF_ALLOC
| SHF_WRITE
))
1937 } else if (s
->sh_type
== SHT_DYNSYM
||
1938 s
->sh_type
== SHT_STRTAB
||
1939 s
->sh_type
== SHT_HASH
) {
1942 } else if (s
->sh_type
== SHT_RELX
) {
1945 } else if (s
->sh_type
== SHT_NOBITS
) {
1952 section_order
[sh_order_index
++] = i
;
1954 /* section matches: we align it and add its size */
1956 addr
= (addr
+ s
->sh_addralign
- 1) &
1957 ~(s
->sh_addralign
- 1);
1958 file_offset
+= (int) ( addr
- tmp
);
1959 s
->sh_offset
= file_offset
;
1962 /* update program header infos */
1963 if (ph
->p_offset
== 0) {
1964 ph
->p_offset
= file_offset
;
1966 ph
->p_paddr
= ph
->p_vaddr
;
1968 /* update dynamic relocation infos */
1969 if (s
->sh_type
== SHT_RELX
) {
1970 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1971 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.got")) { // rel_size == 0) {
1973 rel_size
+= s
->sh_size
; // XXX only first rel.
1975 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.bss")) { // rel_size == 0) {
1977 bss_size
= s
->sh_size
; // XXX only first rel.
1982 rel_size
+= s
->sh_size
;
1986 if (s
->sh_type
!= SHT_NOBITS
)
1987 file_offset
+= s
->sh_size
;
1990 ph
->p_filesz
= file_offset
- ph
->p_offset
;
1991 ph
->p_memsz
= addr
- ph
->p_vaddr
;
1994 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1995 /* if in the middle of a page, we duplicate the page in
1996 memory so that one copy is RX and the other is RW */
1997 if ((addr
& (s1
->section_align
- 1)) != 0)
1998 addr
+= s1
->section_align
;
2000 addr
= (addr
+ s1
->section_align
- 1) & ~(s1
->section_align
- 1);
2001 file_offset
= (file_offset
+ s1
->section_align
- 1) &
2002 ~(s1
->section_align
- 1);
2007 /* if interpreter, then add corresponing program header */
2011 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2013 int len
= phnum
* sizeof(ElfW(Phdr
));
2015 ph
->p_type
= PT_PHDR
;
2016 ph
->p_offset
= sizeof(ElfW(Ehdr
));
2017 ph
->p_vaddr
= interp
->sh_addr
- len
;
2018 ph
->p_paddr
= ph
->p_vaddr
;
2019 ph
->p_filesz
= ph
->p_memsz
= len
;
2020 ph
->p_flags
= PF_R
| PF_X
;
2021 ph
->p_align
= 4; // interp->sh_addralign;
2026 ph
->p_type
= PT_INTERP
;
2027 ph
->p_offset
= interp
->sh_offset
;
2028 ph
->p_vaddr
= interp
->sh_addr
;
2029 ph
->p_paddr
= ph
->p_vaddr
;
2030 ph
->p_filesz
= interp
->sh_size
;
2031 ph
->p_memsz
= interp
->sh_size
;
2033 ph
->p_align
= interp
->sh_addralign
;
2036 /* if dynamic section, then add corresponing program header */
2040 ph
= &phdr
[phnum
- 1];
2042 ph
->p_type
= PT_DYNAMIC
;
2043 ph
->p_offset
= dynamic
->sh_offset
;
2044 ph
->p_vaddr
= dynamic
->sh_addr
;
2045 ph
->p_paddr
= ph
->p_vaddr
;
2046 ph
->p_filesz
= dynamic
->sh_size
;
2047 ph
->p_memsz
= dynamic
->sh_size
;
2048 ph
->p_flags
= PF_R
| PF_W
;
2049 ph
->p_align
= dynamic
->sh_addralign
;
2051 /* put GOT dynamic section address */
2052 put32(s1
->got
->data
, dynamic
->sh_addr
);
2054 /* relocate the PLT */
2055 if (file_type
== TCC_OUTPUT_EXE
2056 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2057 || file_type
== TCC_OUTPUT_DLL
2063 p_end
= p
+ s1
->plt
->data_offset
;
2065 #if defined(TCC_TARGET_I386)
2066 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
2067 put32(p
+ 8, get32(p
+ 8) + s1
->got
->sh_addr
);
2070 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
2073 #elif defined(TCC_TARGET_X86_64)
2074 int x
= s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 6;
2075 put32(p
+ 2, get32(p
+ 2) + x
);
2076 put32(p
+ 8, get32(p
+ 8) + x
- 6);
2079 put32(p
+ 2, get32(p
+ 2) + x
+ s1
->plt
->data
- p
);
2082 #elif defined(TCC_TARGET_ARM)
2084 x
=s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 12;
2087 if (get32(p
) == 0x46c04778) /* PLT Thumb stub present */
2089 put32(p
+ 12, x
+ get32(p
+ 12) + s1
->plt
->data
- p
);
2092 #elif defined(TCC_TARGET_C67)
2095 #error unsupported CPU
2100 /* relocate symbols in .dynsym */
2101 sym_end
= (ElfW(Sym
) *)(s1
->dynsym
->data
+ s1
->dynsym
->data_offset
);
2102 for(sym
= (ElfW(Sym
) *)s1
->dynsym
->data
+ 1;
2105 if (sym
->st_shndx
== SHN_UNDEF
) {
2106 /* relocate to the PLT if the symbol corresponds
2109 sym
->st_value
+= s1
->plt
->sh_addr
;
2110 } else if (sym
->st_shndx
< SHN_LORESERVE
) {
2111 /* do symbol relocation */
2112 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
2116 /* put dynamic section entries */
2117 dynamic
->data_offset
= saved_dynamic_data_offset
;
2118 put_dt(dynamic
, DT_HASH
, s1
->dynsym
->hash
->sh_addr
);
2119 put_dt(dynamic
, DT_STRTAB
, dynstr
->sh_addr
);
2120 put_dt(dynamic
, DT_SYMTAB
, s1
->dynsym
->sh_addr
);
2121 put_dt(dynamic
, DT_STRSZ
, dynstr
->data_offset
);
2122 put_dt(dynamic
, DT_SYMENT
, sizeof(ElfW(Sym
)));
2123 #ifdef TCC_TARGET_X86_64
2124 put_dt(dynamic
, DT_RELA
, rel_addr
);
2125 put_dt(dynamic
, DT_RELASZ
, rel_size
);
2126 put_dt(dynamic
, DT_RELAENT
, sizeof(ElfW_Rel
));
2128 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2129 put_dt(dynamic
, DT_PLTGOT
, s1
->got
->sh_addr
);
2130 put_dt(dynamic
, DT_PLTRELSZ
, rel_size
);
2131 put_dt(dynamic
, DT_JMPREL
, rel_addr
);
2132 put_dt(dynamic
, DT_PLTREL
, DT_REL
);
2133 put_dt(dynamic
, DT_REL
, bss_addr
);
2134 put_dt(dynamic
, DT_RELSZ
, bss_size
);
2136 put_dt(dynamic
, DT_REL
, rel_addr
);
2137 put_dt(dynamic
, DT_RELSZ
, rel_size
);
2138 put_dt(dynamic
, DT_RELENT
, sizeof(ElfW_Rel
));
2142 put_dt(dynamic
, DT_DEBUG
, 0);
2143 put_dt(dynamic
, DT_NULL
, 0);
2146 ehdr
.e_phentsize
= sizeof(ElfW(Phdr
));
2147 ehdr
.e_phnum
= phnum
;
2148 ehdr
.e_phoff
= sizeof(ElfW(Ehdr
));
2151 /* all other sections come after */
2152 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2153 s
= s1
->sections
[i
];
2154 if (phnum
> 0 && (s
->sh_flags
& SHF_ALLOC
))
2156 section_order
[sh_order_index
++] = i
;
2158 file_offset
= (file_offset
+ s
->sh_addralign
- 1) &
2159 ~(s
->sh_addralign
- 1);
2160 s
->sh_offset
= file_offset
;
2161 if (s
->sh_type
!= SHT_NOBITS
)
2162 file_offset
+= s
->sh_size
;
2165 /* if building executable or DLL, then relocate each section
2166 except the GOT which is already relocated */
2167 if (file_type
!= TCC_OUTPUT_OBJ
) {
2168 relocate_syms(s1
, 0);
2170 if (s1
->nb_errors
!= 0) {
2176 /* relocate sections */
2177 /* XXX: ignore sections with allocated relocations ? */
2178 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2179 s
= s1
->sections
[i
];
2180 if (s
->reloc
&& s
!= s1
->got
&& (s
->sh_flags
& SHF_ALLOC
)) //gr
2181 relocate_section(s1
, s
);
2184 /* relocate relocation entries if the relocation tables are
2185 allocated in the executable */
2186 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2187 s
= s1
->sections
[i
];
2188 if ((s
->sh_flags
& SHF_ALLOC
) &&
2189 s
->sh_type
== SHT_RELX
) {
2190 relocate_rel(s1
, s
);
2194 /* get entry point address */
2195 if (file_type
== TCC_OUTPUT_EXE
)
2196 ehdr
.e_entry
= (uplong
)tcc_get_symbol_err(s1
, "_start");
2198 ehdr
.e_entry
= text_section
->sh_addr
; /* XXX: is it correct ? */
2200 if (file_type
== TCC_OUTPUT_EXE
&& s1
->static_link
)
2203 /* write elf file */
2204 if (file_type
== TCC_OUTPUT_OBJ
)
2209 fd
= open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
, mode
);
2211 tcc_error_noabort("could not write '%s'", filename
);
2214 f
= fdopen(fd
, "wb");
2216 printf("<- %s\n", filename
);
2218 #ifdef TCC_TARGET_COFF
2219 if (s1
->output_format
== TCC_OUTPUT_FORMAT_COFF
) {
2220 tcc_output_coff(s1
, f
);
2223 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
2224 sort_syms(s1
, symtab_section
);
2227 file_offset
= (file_offset
+ 3) & -4;
2230 ehdr
.e_ident
[0] = ELFMAG0
;
2231 ehdr
.e_ident
[1] = ELFMAG1
;
2232 ehdr
.e_ident
[2] = ELFMAG2
;
2233 ehdr
.e_ident
[3] = ELFMAG3
;
2234 ehdr
.e_ident
[4] = ELFCLASSW
;
2235 ehdr
.e_ident
[5] = ELFDATA2LSB
;
2236 ehdr
.e_ident
[6] = EV_CURRENT
;
2237 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2238 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_FREEBSD
;
2240 #ifdef TCC_TARGET_ARM
2242 ehdr
.e_ident
[EI_OSABI
] = 0;
2243 ehdr
.e_flags
= 4 << 24;
2245 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_ARM
;
2250 case TCC_OUTPUT_EXE
:
2251 ehdr
.e_type
= ET_EXEC
;
2253 case TCC_OUTPUT_DLL
:
2254 ehdr
.e_type
= ET_DYN
;
2256 case TCC_OUTPUT_OBJ
:
2257 ehdr
.e_type
= ET_REL
;
2260 ehdr
.e_machine
= EM_TCC_TARGET
;
2261 ehdr
.e_version
= EV_CURRENT
;
2262 ehdr
.e_shoff
= file_offset
;
2263 ehdr
.e_ehsize
= sizeof(ElfW(Ehdr
));
2264 ehdr
.e_shentsize
= sizeof(ElfW(Shdr
));
2265 ehdr
.e_shnum
= shnum
;
2266 ehdr
.e_shstrndx
= shnum
- 1;
2268 fwrite(&ehdr
, 1, sizeof(ElfW(Ehdr
)), f
);
2269 fwrite(phdr
, 1, phnum
* sizeof(ElfW(Phdr
)), f
);
2270 offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
2272 for(i
=1;i
<s1
->nb_sections
;i
++) {
2273 s
= s1
->sections
[section_order
[i
]];
2274 if (s
->sh_type
!= SHT_NOBITS
) {
2275 if (s
->sh_type
== SHT_DYNSYM
)
2276 patch_dynsym_undef(s1
, s
);
2277 while (offset
< s
->sh_offset
) {
2282 fwrite(s
->data
, 1, size
, f
);
2287 /* output section headers */
2288 while (offset
< ehdr
.e_shoff
) {
2293 for(i
=0;i
<s1
->nb_sections
;i
++) {
2295 memset(sh
, 0, sizeof(ElfW(Shdr
)));
2296 s
= s1
->sections
[i
];
2298 sh
->sh_name
= s
->sh_name
;
2299 sh
->sh_type
= s
->sh_type
;
2300 sh
->sh_flags
= s
->sh_flags
;
2301 sh
->sh_entsize
= s
->sh_entsize
;
2302 sh
->sh_info
= s
->sh_info
;
2304 sh
->sh_link
= s
->link
->sh_num
;
2305 sh
->sh_addralign
= s
->sh_addralign
;
2306 sh
->sh_addr
= s
->sh_addr
;
2307 sh
->sh_offset
= s
->sh_offset
;
2308 sh
->sh_size
= s
->sh_size
;
2310 fwrite(sh
, 1, sizeof(ElfW(Shdr
)), f
);
2313 tcc_output_binary(s1
, f
, section_order
);
2319 tcc_free(s1
->symtab_to_dynsym
);
2320 tcc_free(section_order
);
2322 tcc_free(s1
->sym_infos
);
2326 LIBTCCAPI
int tcc_output_file(TCCState
*s
, const char *filename
)
2329 #ifdef TCC_TARGET_PE
2330 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
2331 ret
= pe_output_file(s
, filename
);
2335 ret
= elf_output_file(s
, filename
);
2340 static void *load_data(int fd
, unsigned long file_offset
, unsigned long size
)
2344 data
= tcc_malloc(size
);
2345 lseek(fd
, file_offset
, SEEK_SET
);
2346 read(fd
, data
, size
);
2350 typedef struct SectionMergeInfo
{
2351 Section
*s
; /* corresponding existing section */
2352 unsigned long offset
; /* offset of the new section in the existing section */
2353 uint8_t new_section
; /* true if section 's' was added */
2354 uint8_t link_once
; /* true if link once section */
2357 /* load an object file and merge it with current files */
2358 /* XXX: handle correctly stab (debug) info */
2359 ST_FUNC
int tcc_load_object_file(TCCState
*s1
,
2360 int fd
, unsigned long file_offset
)
2363 ElfW(Shdr
) *shdr
, *sh
;
2364 int size
, i
, j
, offset
, offseti
, nb_syms
, sym_index
, ret
;
2365 unsigned char *strsec
, *strtab
;
2366 int *old_to_new_syms
;
2367 char *sh_name
, *name
;
2368 SectionMergeInfo
*sm_table
, *sm
;
2369 ElfW(Sym
) *sym
, *symtab
;
2370 ElfW_Rel
*rel
, *rel_end
;
2376 stab_index
= stabstr_index
= 0;
2378 if (read(fd
, &ehdr
, sizeof(ehdr
)) != sizeof(ehdr
))
2380 if (ehdr
.e_ident
[0] != ELFMAG0
||
2381 ehdr
.e_ident
[1] != ELFMAG1
||
2382 ehdr
.e_ident
[2] != ELFMAG2
||
2383 ehdr
.e_ident
[3] != ELFMAG3
)
2385 /* test if object file */
2386 if (ehdr
.e_type
!= ET_REL
)
2388 /* test CPU specific stuff */
2389 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2390 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2392 tcc_error_noabort("invalid object file");
2396 shdr
= load_data(fd
, file_offset
+ ehdr
.e_shoff
,
2397 sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2398 sm_table
= tcc_mallocz(sizeof(SectionMergeInfo
) * ehdr
.e_shnum
);
2400 /* load section names */
2401 sh
= &shdr
[ehdr
.e_shstrndx
];
2402 strsec
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2404 /* load symtab and strtab */
2405 old_to_new_syms
= NULL
;
2409 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2411 if (sh
->sh_type
== SHT_SYMTAB
) {
2413 tcc_error_noabort("object must contain only one symtab");
2418 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2419 symtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2420 sm_table
[i
].s
= symtab_section
;
2422 /* now load strtab */
2423 sh
= &shdr
[sh
->sh_link
];
2424 strtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2428 /* now examine each section and try to merge its content with the
2430 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2431 /* no need to examine section name strtab */
2432 if (i
== ehdr
.e_shstrndx
)
2435 sh_name
= strsec
+ sh
->sh_name
;
2436 /* ignore sections types we do not handle */
2437 if (sh
->sh_type
!= SHT_PROGBITS
&&
2438 sh
->sh_type
!= SHT_RELX
&&
2440 sh
->sh_type
!= SHT_ARM_EXIDX
&&
2442 sh
->sh_type
!= SHT_NOBITS
&&
2443 sh
->sh_type
!= SHT_PREINIT_ARRAY
&&
2444 sh
->sh_type
!= SHT_INIT_ARRAY
&&
2445 sh
->sh_type
!= SHT_FINI_ARRAY
&&
2446 strcmp(sh_name
, ".stabstr")
2449 if (sh
->sh_addralign
< 1)
2450 sh
->sh_addralign
= 1;
2451 /* find corresponding section, if any */
2452 for(j
= 1; j
< s1
->nb_sections
;j
++) {
2453 s
= s1
->sections
[j
];
2454 if (!strcmp(s
->name
, sh_name
)) {
2455 if (!strncmp(sh_name
, ".gnu.linkonce",
2456 sizeof(".gnu.linkonce") - 1)) {
2457 /* if a 'linkonce' section is already present, we
2458 do not add it again. It is a little tricky as
2459 symbols can still be defined in
2461 sm_table
[i
].link_once
= 1;
2468 /* not found: create new section */
2469 s
= new_section(s1
, sh_name
, sh
->sh_type
, sh
->sh_flags
);
2470 /* take as much info as possible from the section. sh_link and
2471 sh_info will be updated later */
2472 s
->sh_addralign
= sh
->sh_addralign
;
2473 s
->sh_entsize
= sh
->sh_entsize
;
2474 sm_table
[i
].new_section
= 1;
2476 if (sh
->sh_type
!= s
->sh_type
) {
2477 tcc_error_noabort("invalid section type");
2481 /* align start of section */
2482 offset
= s
->data_offset
;
2484 if (0 == strcmp(sh_name
, ".stab")) {
2488 if (0 == strcmp(sh_name
, ".stabstr")) {
2493 size
= sh
->sh_addralign
- 1;
2494 offset
= (offset
+ size
) & ~size
;
2495 if (sh
->sh_addralign
> s
->sh_addralign
)
2496 s
->sh_addralign
= sh
->sh_addralign
;
2497 s
->data_offset
= offset
;
2499 sm_table
[i
].offset
= offset
;
2501 /* concatenate sections */
2503 if (sh
->sh_type
!= SHT_NOBITS
) {
2505 lseek(fd
, file_offset
+ sh
->sh_offset
, SEEK_SET
);
2506 ptr
= section_ptr_add(s
, size
);
2507 read(fd
, ptr
, size
);
2509 s
->data_offset
+= size
;
2514 /* //gr relocate stab strings */
2515 if (stab_index
&& stabstr_index
) {
2518 s
= sm_table
[stab_index
].s
;
2519 a
= (Stab_Sym
*)(s
->data
+ sm_table
[stab_index
].offset
);
2520 b
= (Stab_Sym
*)(s
->data
+ s
->data_offset
);
2521 o
= sm_table
[stabstr_index
].offset
;
2523 a
->n_strx
+= o
, a
++;
2526 /* second short pass to update sh_link and sh_info fields of new
2528 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2530 if (!s
|| !sm_table
[i
].new_section
)
2533 if (sh
->sh_link
> 0)
2534 s
->link
= sm_table
[sh
->sh_link
].s
;
2535 if (sh
->sh_type
== SHT_RELX
) {
2536 s
->sh_info
= sm_table
[sh
->sh_info
].s
->sh_num
;
2537 /* update backward link */
2538 s1
->sections
[s
->sh_info
]->reloc
= s
;
2543 /* resolve symbols */
2544 old_to_new_syms
= tcc_mallocz(nb_syms
* sizeof(int));
2547 for(i
= 1; i
< nb_syms
; i
++, sym
++) {
2548 if (sym
->st_shndx
!= SHN_UNDEF
&&
2549 sym
->st_shndx
< SHN_LORESERVE
) {
2550 sm
= &sm_table
[sym
->st_shndx
];
2551 if (sm
->link_once
) {
2552 /* if a symbol is in a link once section, we use the
2553 already defined symbol. It is very important to get
2554 correct relocations */
2555 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
2556 name
= strtab
+ sym
->st_name
;
2557 sym_index
= find_elf_sym(symtab_section
, name
);
2559 old_to_new_syms
[i
] = sym_index
;
2563 /* if no corresponding section added, no need to add symbol */
2566 /* convert section number */
2567 sym
->st_shndx
= sm
->s
->sh_num
;
2569 sym
->st_value
+= sm
->offset
;
2572 name
= strtab
+ sym
->st_name
;
2573 sym_index
= add_elf_sym(symtab_section
, sym
->st_value
, sym
->st_size
,
2574 sym
->st_info
, sym
->st_other
,
2575 sym
->st_shndx
, name
);
2576 old_to_new_syms
[i
] = sym_index
;
2579 /* third pass to patch relocation entries */
2580 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2585 offset
= sm_table
[i
].offset
;
2586 switch(s
->sh_type
) {
2588 /* take relocation offset information */
2589 offseti
= sm_table
[sh
->sh_info
].offset
;
2590 rel_end
= (ElfW_Rel
*)(s
->data
+ s
->data_offset
);
2591 for(rel
= (ElfW_Rel
*)(s
->data
+ offset
);
2596 /* convert symbol index */
2597 type
= ELFW(R_TYPE
)(rel
->r_info
);
2598 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
2599 /* NOTE: only one symtab assumed */
2600 if (sym_index
>= nb_syms
)
2602 sym_index
= old_to_new_syms
[sym_index
];
2603 /* ignore link_once in rel section. */
2604 if (!sym_index
&& !sm
->link_once
2605 #ifdef TCC_TARGET_ARM
2606 && type
!= R_ARM_V4BX
2610 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2611 i
, strsec
+ sh
->sh_name
, rel
->r_offset
);
2614 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
2615 /* offset the relocation offset */
2616 rel
->r_offset
+= offseti
;
2617 #ifdef TCC_TARGET_ARM
2618 /* Jumps and branches from a Thumb code to a PLT entry need
2619 special handling since PLT entries are ARM code.
2620 Unconditional bl instructions referencing PLT entries are
2621 handled by converting these instructions into blx
2622 instructions. Other case of instructions referencing a PLT
2623 entry require to add a Thumb stub before the PLT entry to
2624 switch to ARM mode. We set bit 0 of the got offset of a
2625 symbol to indicate such a case. */
2626 if (type
== R_ARM_THM_JUMP24
) {
2627 put_plt_thumb_stub(s1
, sym_index
, 1);
2641 tcc_free(old_to_new_syms
);
2648 typedef struct ArchiveHeader
{
2649 char ar_name
[16]; /* name of this member */
2650 char ar_date
[12]; /* file mtime */
2651 char ar_uid
[6]; /* owner uid; printed as decimal */
2652 char ar_gid
[6]; /* owner gid; printed as decimal */
2653 char ar_mode
[8]; /* file mode, printed as octal */
2654 char ar_size
[10]; /* file size, printed as decimal */
2655 char ar_fmag
[2]; /* should contain ARFMAG */
2658 static int get_be32(const uint8_t *b
)
2660 return b
[3] | (b
[2] << 8) | (b
[1] << 16) | (b
[0] << 24);
2663 /* load only the objects which resolve undefined symbols */
2664 static int tcc_load_alacarte(TCCState
*s1
, int fd
, int size
)
2666 int i
, bound
, nsyms
, sym_index
, off
, ret
;
2668 const char *ar_names
, *p
;
2669 const uint8_t *ar_index
;
2672 data
= tcc_malloc(size
);
2673 if (read(fd
, data
, size
) != size
)
2675 nsyms
= get_be32(data
);
2676 ar_index
= data
+ 4;
2677 ar_names
= ar_index
+ nsyms
* 4;
2681 for(p
= ar_names
, i
= 0; i
< nsyms
; i
++, p
+= strlen(p
)+1) {
2682 sym_index
= find_elf_sym(symtab_section
, p
);
2684 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
2685 if(sym
->st_shndx
== SHN_UNDEF
) {
2686 off
= get_be32(ar_index
+ i
* 4) + sizeof(ArchiveHeader
);
2688 printf("%5d\t%s\t%08x\n", i
, p
, sym
->st_shndx
);
2691 lseek(fd
, off
, SEEK_SET
);
2692 if(tcc_load_object_file(s1
, fd
, off
) < 0) {
2707 /* load a '.a' file */
2708 ST_FUNC
int tcc_load_archive(TCCState
*s1
, int fd
)
2715 unsigned long file_offset
;
2717 /* skip magic which was already checked */
2718 read(fd
, magic
, sizeof(magic
));
2721 len
= read(fd
, &hdr
, sizeof(hdr
));
2724 if (len
!= sizeof(hdr
)) {
2725 tcc_error_noabort("invalid archive");
2728 memcpy(ar_size
, hdr
.ar_size
, sizeof(hdr
.ar_size
));
2729 ar_size
[sizeof(hdr
.ar_size
)] = '\0';
2730 size
= strtol(ar_size
, NULL
, 0);
2731 memcpy(ar_name
, hdr
.ar_name
, sizeof(hdr
.ar_name
));
2732 for(i
= sizeof(hdr
.ar_name
) - 1; i
>= 0; i
--) {
2733 if (ar_name
[i
] != ' ')
2736 ar_name
[i
+ 1] = '\0';
2737 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2738 file_offset
= lseek(fd
, 0, SEEK_CUR
);
2740 size
= (size
+ 1) & ~1;
2741 if (!strcmp(ar_name
, "/")) {
2742 /* coff symbol table : we handle it */
2743 if(s1
->alacarte_link
)
2744 return tcc_load_alacarte(s1
, fd
, size
);
2745 } else if (!strcmp(ar_name
, "//") ||
2746 !strcmp(ar_name
, "__.SYMDEF") ||
2747 !strcmp(ar_name
, "__.SYMDEF/") ||
2748 !strcmp(ar_name
, "ARFILENAMES/")) {
2749 /* skip symbol table or archive names */
2751 if (tcc_load_object_file(s1
, fd
, file_offset
) < 0)
2754 lseek(fd
, file_offset
+ size
, SEEK_SET
);
2759 #ifndef TCC_TARGET_PE
2760 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2761 is referenced by the user (so it should be added as DT_NEEDED in
2762 the generated ELF file) */
2763 ST_FUNC
int tcc_load_dll(TCCState
*s1
, int fd
, const char *filename
, int level
)
2766 ElfW(Shdr
) *shdr
, *sh
, *sh1
;
2767 int i
, j
, nb_syms
, nb_dts
, sym_bind
, ret
;
2768 ElfW(Sym
) *sym
, *dynsym
;
2769 ElfW(Dyn
) *dt
, *dynamic
;
2770 unsigned char *dynstr
;
2771 const char *name
, *soname
;
2772 DLLReference
*dllref
;
2774 read(fd
, &ehdr
, sizeof(ehdr
));
2776 /* test CPU specific stuff */
2777 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2778 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2779 tcc_error_noabort("bad architecture");
2784 shdr
= load_data(fd
, ehdr
.e_shoff
, sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2786 /* load dynamic section and dynamic symbols */
2790 dynsym
= NULL
; /* avoid warning */
2791 dynstr
= NULL
; /* avoid warning */
2792 for(i
= 0, sh
= shdr
; i
< ehdr
.e_shnum
; i
++, sh
++) {
2793 switch(sh
->sh_type
) {
2795 nb_dts
= sh
->sh_size
/ sizeof(ElfW(Dyn
));
2796 dynamic
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2799 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2800 dynsym
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2801 sh1
= &shdr
[sh
->sh_link
];
2802 dynstr
= load_data(fd
, sh1
->sh_offset
, sh1
->sh_size
);
2809 /* compute the real library name */
2810 soname
= tcc_basename(filename
);
2812 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2813 if (dt
->d_tag
== DT_SONAME
) {
2814 soname
= dynstr
+ dt
->d_un
.d_val
;
2818 /* if the dll is already loaded, do not load it */
2819 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
2820 dllref
= s1
->loaded_dlls
[i
];
2821 if (!strcmp(soname
, dllref
->name
)) {
2822 /* but update level if needed */
2823 if (level
< dllref
->level
)
2824 dllref
->level
= level
;
2830 // printf("loading dll '%s'\n", soname);
2832 /* add the dll and its level */
2833 dllref
= tcc_mallocz(sizeof(DLLReference
) + strlen(soname
));
2834 dllref
->level
= level
;
2835 strcpy(dllref
->name
, soname
);
2836 dynarray_add((void ***)&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
, dllref
);
2838 /* add dynamic symbols in dynsym_section */
2839 for(i
= 1, sym
= dynsym
+ 1; i
< nb_syms
; i
++, sym
++) {
2840 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
2841 if (sym_bind
== STB_LOCAL
)
2843 name
= dynstr
+ sym
->st_name
;
2844 add_elf_sym(s1
->dynsymtab_section
, sym
->st_value
, sym
->st_size
,
2845 sym
->st_info
, sym
->st_other
, sym
->st_shndx
, name
);
2848 /* load all referenced DLLs */
2849 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2852 name
= dynstr
+ dt
->d_un
.d_val
;
2853 for(j
= 0; j
< s1
->nb_loaded_dlls
; j
++) {
2854 dllref
= s1
->loaded_dlls
[j
];
2855 if (!strcmp(name
, dllref
->name
))
2856 goto already_loaded
;
2858 if (tcc_add_dll(s1
, name
, AFF_REFERENCED_DLL
) < 0) {
2859 tcc_error_noabort("referenced dll '%s' not found", name
);
2876 #define LD_TOK_NAME 256
2877 #define LD_TOK_EOF (-1)
2879 /* return next ld script token */
2880 static int ld_next(TCCState
*s1
, char *name
, int name_size
)
2898 file
->buf_ptr
= parse_comment(file
->buf_ptr
);
2899 ch
= file
->buf_ptr
[0];
2907 /* case 'a' ... 'z': */
2934 /* case 'A' ... 'z': */
2969 if (!((ch
>= 'a' && ch
<= 'z') ||
2970 (ch
>= 'A' && ch
<= 'Z') ||
2971 (ch
>= '0' && ch
<= '9') ||
2972 strchr("/.-_+=$:\\,~", ch
)))
2974 if ((q
- name
) < name_size
- 1) {
2991 printf("tok=%c %d\n", c
, c
);
2992 if (c
== LD_TOK_NAME
)
2993 printf(" name=%s\n", name
);
2999 * Extract the file name from the library name
3001 * /!\ No test on filename capacity, be careful
3003 static void libname_to_filename(TCCState
*s1
, const char libname
[], char filename
[])
3005 if (!s1
->static_link
) {
3006 sprintf(filename
, "lib%s.so", libname
);
3008 sprintf(filename
, "lib%s.a", libname
);
3012 static int ld_add_file(TCCState
*s1
, const char filename
[])
3016 ret
= tcc_add_file_internal(s1
, filename
, 0);
3018 ret
= tcc_add_dll(s1
, filename
, 0);
3022 static inline int new_undef_syms(void)
3025 ret
= new_undef_sym
;
3030 static int ld_add_file_list(TCCState
*s1
, const char *cmd
, int as_needed
)
3032 char filename
[1024], libname
[1024];
3033 int t
, group
, nblibs
= 0, ret
= 0;
3036 group
= !strcmp(cmd
, "GROUP");
3039 t
= ld_next(s1
, filename
, sizeof(filename
));
3042 t
= ld_next(s1
, filename
, sizeof(filename
));
3045 if (t
== LD_TOK_EOF
) {
3046 tcc_error_noabort("unexpected end of file");
3048 goto lib_parse_error
;
3049 } else if (t
== ')') {
3051 } else if (t
== '-') {
3052 t
= ld_next(s1
, filename
, sizeof(filename
));
3053 if ((t
!= LD_TOK_NAME
) || (filename
[0] != 'l')) {
3054 tcc_error_noabort("library name expected");
3056 goto lib_parse_error
;
3058 strcpy(libname
, &filename
[1]);
3059 libname_to_filename(s1
, libname
, filename
);
3060 } else if (t
!= LD_TOK_NAME
) {
3061 tcc_error_noabort("filename expected");
3063 goto lib_parse_error
;
3065 if (!strcmp(filename
, "AS_NEEDED")) {
3066 ret
= ld_add_file_list(s1
, cmd
, 1);
3068 goto lib_parse_error
;
3070 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3072 ret
= ld_add_file(s1
, filename
);
3074 goto lib_parse_error
;
3076 /* Add the filename *and* the libname to avoid future conversions */
3077 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(filename
));
3078 if (libname
[0] != '\0')
3079 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(libname
));
3083 t
= ld_next(s1
, filename
, sizeof(filename
));
3085 t
= ld_next(s1
, filename
, sizeof(filename
));
3088 if (group
&& !as_needed
) {
3089 while (new_undef_syms()) {
3092 for (i
= 0; i
< nblibs
; i
++)
3093 ld_add_file(s1
, libs
[i
]);
3097 dynarray_reset(&libs
, &nblibs
);
3101 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3103 ST_FUNC
int tcc_load_ldscript(TCCState
*s1
)
3106 char filename
[1024];
3109 ch
= file
->buf_ptr
[0];
3112 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3113 if (t
== LD_TOK_EOF
)
3115 else if (t
!= LD_TOK_NAME
)
3117 if (!strcmp(cmd
, "INPUT") ||
3118 !strcmp(cmd
, "GROUP")) {
3119 ret
= ld_add_file_list(s1
, cmd
, 0);
3122 } else if (!strcmp(cmd
, "OUTPUT_FORMAT") ||
3123 !strcmp(cmd
, "TARGET")) {
3124 /* ignore some commands */
3125 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3129 t
= ld_next(s1
, filename
, sizeof(filename
));
3130 if (t
== LD_TOK_EOF
) {
3131 tcc_error_noabort("unexpected end of file");
3133 } else if (t
== ')') {
3143 #endif /* ndef TCC_TARGET_PE */