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
, addr_t 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 ST_FUNC addr_t
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 sym
->st_value
;
175 /* return elf symbol value */
176 LIBTCCAPI
void *tcc_get_symbol(TCCState
*s
, const char *name
)
178 return (void*)(uintptr_t)get_elf_sym_addr(s
, name
, 0);
181 #if defined TCC_IS_NATIVE || defined TCC_TARGET_PE
182 /* return elf symbol value or error */
183 ST_FUNC
void* tcc_get_symbol_err(TCCState
*s
, const char *name
)
185 return (void*)(uintptr_t)get_elf_sym_addr(s
, name
, 1);
189 /* add an elf symbol : check if it is already defined and patch
190 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
191 ST_FUNC
int add_elf_sym(Section
*s
, addr_t value
, unsigned long size
,
192 int info
, int other
, int sh_num
, const char *name
)
195 int sym_bind
, sym_index
, sym_type
, esym_bind
;
196 unsigned char sym_vis
, esym_vis
, new_vis
;
198 sym_bind
= ELFW(ST_BIND
)(info
);
199 sym_type
= ELFW(ST_TYPE
)(info
);
200 sym_vis
= ELFW(ST_VISIBILITY
)(other
);
202 if (sym_bind
!= STB_LOCAL
) {
203 /* we search global or weak symbols */
204 sym_index
= find_elf_sym(s
, name
);
207 esym
= &((ElfW(Sym
) *)s
->data
)[sym_index
];
208 if (esym
->st_shndx
!= SHN_UNDEF
) {
209 esym_bind
= ELFW(ST_BIND
)(esym
->st_info
);
210 /* propagate the most constraining visibility */
211 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
212 esym_vis
= ELFW(ST_VISIBILITY
)(esym
->st_other
);
213 if (esym_vis
== STV_DEFAULT
) {
215 } else if (sym_vis
== STV_DEFAULT
) {
218 new_vis
= (esym_vis
< sym_vis
) ? esym_vis
: sym_vis
;
220 esym
->st_other
= (esym
->st_other
& ~ELFW(ST_VISIBILITY
)(-1))
222 other
= esym
->st_other
; /* in case we have to patch esym */
223 if (sh_num
== SHN_UNDEF
) {
224 /* ignore adding of undefined symbol if the
225 corresponding symbol is already defined */
226 } else if (sym_bind
== STB_GLOBAL
&& esym_bind
== STB_WEAK
) {
227 /* global overrides weak, so patch */
229 } else if (sym_bind
== STB_WEAK
&& esym_bind
== STB_GLOBAL
) {
230 /* weak is ignored if already global */
231 } else if (sym_bind
== STB_WEAK
&& esym_bind
== STB_WEAK
) {
232 /* keep first-found weak definition, ignore subsequents */
233 } else if (sym_vis
== STV_HIDDEN
|| sym_vis
== STV_INTERNAL
) {
234 /* ignore hidden symbols after */
235 } else if (esym
->st_shndx
== SHN_COMMON
236 && (sh_num
< SHN_LORESERVE
|| sh_num
== SHN_COMMON
)) {
237 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
238 No idea if this is the correct solution ... */
240 } else if (s
== tcc_state
->dynsymtab_section
) {
241 /* we accept that two DLL define the same symbol */
244 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
245 sym_bind
, sh_num
, new_vis
, esym_bind
, esym
->st_shndx
, esym_vis
);
247 tcc_error_noabort("'%s' defined twice", name
);
251 esym
->st_info
= ELFW(ST_INFO
)(sym_bind
, sym_type
);
252 esym
->st_shndx
= sh_num
;
254 esym
->st_value
= value
;
255 esym
->st_size
= size
;
256 esym
->st_other
= other
;
260 sym_index
= put_elf_sym(s
, value
, size
,
261 ELFW(ST_INFO
)(sym_bind
, sym_type
), other
,
268 ST_FUNC
void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
269 int type
, int symbol
)
277 /* if no relocation section, create it */
278 snprintf(buf
, sizeof(buf
), REL_SECTION_FMT
, s
->name
);
279 /* if the symtab is allocated, then we consider the relocation
281 sr
= new_section(tcc_state
, buf
, SHT_RELX
, symtab
->sh_flags
);
282 sr
->sh_entsize
= sizeof(ElfW_Rel
);
284 sr
->sh_info
= s
->sh_num
;
287 rel
= section_ptr_add(sr
, sizeof(ElfW_Rel
));
288 rel
->r_offset
= offset
;
289 rel
->r_info
= ELFW(R_INFO
)(symbol
, type
);
290 #ifdef TCC_TARGET_X86_64
295 /* put stab debug information */
297 ST_FUNC
void put_stabs(const char *str
, int type
, int other
, int desc
,
302 sym
= section_ptr_add(stab_section
, sizeof(Stab_Sym
));
304 sym
->n_strx
= put_elf_str(stabstr_section
, str
);
309 sym
->n_other
= other
;
311 sym
->n_value
= value
;
314 ST_FUNC
void put_stabs_r(const char *str
, int type
, int other
, int desc
,
315 unsigned long value
, Section
*sec
, int sym_index
)
317 put_stabs(str
, type
, other
, desc
, value
);
318 put_elf_reloc(symtab_section
, stab_section
,
319 stab_section
->data_offset
- sizeof(unsigned int),
320 R_DATA_32
, sym_index
);
323 ST_FUNC
void put_stabn(int type
, int other
, int desc
, int value
)
325 put_stabs(NULL
, type
, other
, desc
, value
);
328 ST_FUNC
void put_stabd(int type
, int other
, int desc
)
330 put_stabs(NULL
, type
, other
, desc
, 0);
333 /* Browse each elem of type <type> in section <sec> starting at elem <startoff>
334 using variable <elem> */
335 #define for_each_elem(sec, startoff, elem, type) \
336 for (elem = (type *) sec->data + startoff; \
337 elem < (type *) (sec->data + sec->data_offset); elem++)
339 /* In an ELF file symbol table, the local symbols must appear below
340 the global and weak ones. Since TCC cannot sort it while generating
341 the code, we must do it after. All the relocation tables are also
342 modified to take into account the symbol table sorting */
343 static void sort_syms(TCCState
*s1
, Section
*s
)
345 int *old_to_new_syms
;
353 nb_syms
= s
->data_offset
/ sizeof(ElfW(Sym
));
354 new_syms
= tcc_malloc(nb_syms
* sizeof(ElfW(Sym
)));
355 old_to_new_syms
= tcc_malloc(nb_syms
* sizeof(int));
357 /* first pass for local symbols */
358 p
= (ElfW(Sym
) *)s
->data
;
360 for(i
= 0; i
< nb_syms
; i
++) {
361 if (ELFW(ST_BIND
)(p
->st_info
) == STB_LOCAL
) {
362 old_to_new_syms
[i
] = q
- new_syms
;
367 /* save the number of local symbols in section header */
368 s
->sh_info
= q
- new_syms
;
370 /* then second pass for non local symbols */
371 p
= (ElfW(Sym
) *)s
->data
;
372 for(i
= 0; i
< nb_syms
; i
++) {
373 if (ELFW(ST_BIND
)(p
->st_info
) != STB_LOCAL
) {
374 old_to_new_syms
[i
] = q
- new_syms
;
380 /* we copy the new symbols to the old */
381 memcpy(s
->data
, new_syms
, nb_syms
* sizeof(ElfW(Sym
)));
384 /* now we modify all the relocations */
385 for(i
= 1; i
< s1
->nb_sections
; i
++) {
386 sr
= s1
->sections
[i
];
387 if (sr
->sh_type
== SHT_RELX
&& sr
->link
== s
) {
388 for_each_elem(sr
, 0, rel
, ElfW_Rel
) {
389 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
390 type
= ELFW(R_TYPE
)(rel
->r_info
);
391 sym_index
= old_to_new_syms
[sym_index
];
392 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
397 tcc_free(old_to_new_syms
);
400 /* relocate common symbols in the .bss section */
401 ST_FUNC
void relocate_common_syms(void)
404 unsigned long offset
, align
;
406 for_each_elem(symtab_section
, 1, sym
, ElfW(Sym
)) {
407 if (sym
->st_shndx
== SHN_COMMON
) {
409 align
= sym
->st_value
;
410 offset
= bss_section
->data_offset
;
411 offset
= (offset
+ align
- 1) & -align
;
412 sym
->st_value
= offset
;
413 sym
->st_shndx
= bss_section
->sh_num
;
414 offset
+= sym
->st_size
;
415 bss_section
->data_offset
= offset
;
420 /* relocate symbol table, resolve undefined symbols if do_resolve is
421 true and output error if undefined symbol. */
422 ST_FUNC
void relocate_syms(TCCState
*s1
, int do_resolve
)
424 ElfW(Sym
) *sym
, *esym
;
425 int sym_bind
, sh_num
, sym_index
;
428 for_each_elem(symtab_section
, 1, sym
, ElfW(Sym
)) {
429 sh_num
= sym
->st_shndx
;
430 if (sh_num
== SHN_UNDEF
) {
431 name
= strtab_section
->data
+ sym
->st_name
;
433 #if defined TCC_IS_NATIVE && !defined _WIN32
435 name
= symtab_section
->link
->data
+ sym
->st_name
;
436 addr
= resolve_sym(s1
, name
);
438 sym
->st_value
= (addr_t
)addr
;
442 } else if (s1
->dynsym
) {
443 /* if dynamic symbol exist, then use it */
444 sym_index
= find_elf_sym(s1
->dynsym
, name
);
446 esym
= &((ElfW(Sym
) *)s1
->dynsym
->data
)[sym_index
];
447 sym
->st_value
= esym
->st_value
;
451 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
453 if (!strcmp(name
, "_fp_hw"))
455 /* only weak symbols are accepted to be undefined. Their
457 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
458 if (sym_bind
== STB_WEAK
) {
461 tcc_error_noabort("undefined symbol '%s'", name
);
463 } else if (sh_num
< SHN_LORESERVE
) {
464 /* add section base */
465 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
471 #ifdef TCC_HAS_RUNTIME_PLTGOT
472 #ifdef TCC_TARGET_X86_64
473 #define JMP_TABLE_ENTRY_SIZE 14
474 static addr_t
add_jmp_table(TCCState
*s1
, addr_t val
)
476 char *p
= s1
->runtime_plt_and_got
+ s1
->runtime_plt_and_got_offset
;
477 s1
->runtime_plt_and_got_offset
+= JMP_TABLE_ENTRY_SIZE
;
482 *(addr_t
*)(p
+ 6) = val
;
486 static addr_t
add_got_table(TCCState
*s1
, addr_t val
)
488 addr_t
*p
= (addr_t
*)(s1
->runtime_plt_and_got
+ s1
->runtime_plt_and_got_offset
);
489 s1
->runtime_plt_and_got_offset
+= sizeof(addr_t
);
493 #elif defined TCC_TARGET_ARM
494 #define JMP_TABLE_ENTRY_SIZE 8
495 static addr_t
add_jmp_table(TCCState
*s1
, int val
)
497 uint32_t *p
= (uint32_t *)(s1
->runtime_plt_and_got
+ s1
->runtime_plt_and_got_offset
);
498 s1
->runtime_plt_and_got_offset
+= JMP_TABLE_ENTRY_SIZE
;
499 /* ldr pc, [pc, #-4] */
505 #endif /* def TCC_HAS_RUNTIME_PLTGOT */
507 /* relocate a given section (CPU dependent) */
508 ST_FUNC
void relocate_section(TCCState
*s1
, Section
*s
)
516 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
521 for_each_elem(sr
, 0, rel
, ElfW_Rel
) {
522 ptr
= s
->data
+ rel
->r_offset
;
524 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
525 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
527 #ifdef TCC_TARGET_X86_64
528 val
+= rel
->r_addend
;
530 type
= ELFW(R_TYPE
)(rel
->r_info
);
531 addr
= s
->sh_addr
+ rel
->r_offset
;
535 #if defined(TCC_TARGET_I386)
537 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
538 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
539 qrel
->r_offset
= rel
->r_offset
;
541 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_386_32
);
545 qrel
->r_info
= ELFW(R_INFO
)(0, R_386_RELATIVE
);
552 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
554 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
556 qrel
->r_offset
= rel
->r_offset
;
557 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_386_PC32
);
562 *(int *)ptr
+= val
- addr
;
565 *(int *)ptr
+= val
- addr
;
572 *(int *)ptr
+= s1
->got
->sh_addr
- addr
;
575 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
578 /* we load the got offset */
579 *(int *)ptr
+= s1
->sym_attrs
[sym_index
].got_offset
;
582 if (s1
->output_format
!= TCC_OUTPUT_FORMAT_BINARY
) {
584 tcc_error("can only produce 16-bit binary files");
586 *(short *)ptr
+= val
;
589 if (s1
->output_format
!= TCC_OUTPUT_FORMAT_BINARY
)
591 *(short *)ptr
+= val
- addr
;
593 #elif defined(TCC_TARGET_ARM)
599 int x
, is_thumb
, is_call
, h
, blx_avail
, is_bl
, th_ko
;
600 x
= (*(int *) ptr
) & 0xffffff;
601 (*(int *)ptr
) &= 0xff000000;
605 blx_avail
= (TCC_ARM_VERSION
>= 5);
607 is_bl
= (*(unsigned *) ptr
) >> 24 == 0xeb;
608 is_call
= (type
== R_ARM_CALL
|| (type
== R_ARM_PC24
&& is_bl
));
611 th_ko
= (x
& 3) && (!blx_avail
|| !is_call
);
612 #ifdef TCC_HAS_RUNTIME_PLTGOT
613 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
614 if (th_ko
|| x
>= 0x2000000 || x
< -0x2000000) {
615 x
+= add_jmp_table(s1
, val
) - val
; /* add veneer */
616 th_ko
= (x
& 3) && (!blx_avail
|| !is_call
);
617 is_thumb
= 0; /* Veneer uses ARM instructions */
621 if (th_ko
|| x
>= 0x2000000 || x
< -0x2000000)
622 tcc_error("can't relocate value at %x",addr
);
625 /* Only reached if blx is avail and it is a call */
628 (*(int *)ptr
) = 0xfa << 24; /* bl -> blx */
633 /* Since these relocations only concern Thumb-2 and blx instruction was
634 introduced before Thumb-2, we can assume blx is available and not
637 case R_ARM_THM_JUMP24
:
639 int x
, hi
, lo
, s
, j1
, j2
, i1
, i2
, imm10
, imm11
;
640 int to_thumb
, is_call
, to_plt
, blx_bit
= 1 << 12;
644 if (sym
->st_shndx
== SHN_UNDEF
&&
645 ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
648 /* Get initial offset */
649 hi
= (*(uint16_t *)ptr
);
650 lo
= (*(uint16_t *)(ptr
+2));
658 x
= (s
<< 24) | (i1
<< 23) | (i2
<< 22) |
659 (imm10
<< 12) | (imm11
<< 1);
663 /* Relocation infos */
666 to_plt
= (val
>= plt
->sh_addr
) &&
667 (val
< plt
->sh_addr
+ plt
->data_offset
);
668 is_call
= (type
== R_ARM_THM_PC22
);
670 /* Compute final offset */
671 if (to_plt
&& !is_call
) /* Point to 1st instr of Thumb stub */
674 if (!to_thumb
&& is_call
) {
675 blx_bit
= 0; /* bl -> blx */
676 x
= (x
+ 3) & -4; /* Compute offset from aligned PC */
679 /* Check that relocation is possible
680 * offset must not be out of range
681 * if target is to be entered in arm mode:
683 - instruction must be a call (bl) or a jump to PLT */
684 if (!to_thumb
|| x
>= 0x1000000 || x
< -0x1000000)
685 if (to_thumb
|| (val
& 2) || (!is_call
&& !to_plt
))
686 tcc_error("can't relocate value at %x",addr
);
688 /* Compute and store final offset */
694 imm10
= (x
>> 12) & 0x3ff;
695 imm11
= (x
>> 1) & 0x7ff;
696 (*(uint16_t *)ptr
) = (uint16_t) ((hi
& 0xf800) |
698 (*(uint16_t *)(ptr
+2)) = (uint16_t) ((lo
& 0xc000) |
699 (j1
<< 13) | blx_bit
| (j2
<< 11) |
704 case R_ARM_MOVW_ABS_NC
:
707 if (type
== R_ARM_MOVT_ABS
)
710 imm4
= (val
>> 12) & 0xf;
711 x
= (imm4
<< 16) | imm12
;
712 if (type
== R_ARM_THM_MOVT_ABS
)
718 case R_ARM_THM_MOVT_ABS
:
719 case R_ARM_THM_MOVW_ABS_NC
:
721 int x
, i
, imm4
, imm3
, imm8
;
722 if (type
== R_ARM_THM_MOVT_ABS
)
725 imm3
= (val
>> 8) & 0x7;
727 imm4
= (val
>> 12) & 0xf;
728 x
= (imm3
<< 28) | (imm8
<< 16) | (i
<< 10) | imm4
;
729 if (type
== R_ARM_THM_MOVT_ABS
)
738 x
= (*(int *)ptr
) & 0x7fffffff;
739 (*(int *)ptr
) &= 0x80000000;
742 if((x
^(x
>>1))&0x40000000)
743 tcc_error("can't relocate value at %x",addr
);
744 (*(int *)ptr
) |= x
& 0x7fffffff;
750 *(int *)ptr
+= val
- addr
;
753 *(int *)ptr
+= s1
->got
->sh_addr
- addr
;
756 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
759 /* we load the got offset */
760 *(int *)ptr
+= s1
->sym_attrs
[sym_index
].got_offset
;
765 /* trade Thumb support for ARMv4 support */
766 if ((0x0ffffff0 & *(int*)ptr
) == 0x012FFF10)
767 *(int*)ptr
^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
770 fprintf(stderr
,"FIXME: handle reloc type %x at %x [%p] to %x\n",
771 type
, (unsigned)addr
, ptr
, (unsigned)val
);
773 #elif defined(TCC_TARGET_C67)
781 /* put the low 16 bits of the absolute address
782 add to what is already there */
784 orig
= ((*(int *)(ptr
)) >> 7) & 0xffff;
785 orig
|= (((*(int *)(ptr
+4)) >> 7) & 0xffff) << 16;
787 /* patch both at once - assumes always in pairs Low - High */
789 *(int *) ptr
= (*(int *) ptr
& (~(0xffff << 7)) ) | (((val
+orig
) & 0xffff) << 7);
790 *(int *)(ptr
+4) = (*(int *)(ptr
+4) & (~(0xffff << 7)) ) | ((((val
+orig
)>>16) & 0xffff) << 7);
796 fprintf(stderr
,"FIXME: handle reloc type %x at %x [%p] to %x\n",
797 type
, (unsigned)addr
, ptr
, (unsigned)val
);
799 #elif defined(TCC_TARGET_X86_64)
801 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
802 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
803 qrel
->r_addend
= *(long long *)ptr
+ val
;
806 *(long long *)ptr
+= val
;
810 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
811 /* XXX: this logic may depend on TCC's codegen
812 now TCC uses R_X86_64_32 even for a 64bit pointer */
813 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
814 qrel
->r_addend
= *(int *)ptr
+ val
;
821 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
823 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
825 qrel
->r_offset
= rel
->r_offset
;
826 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_X86_64_PC32
);
827 qrel
->r_addend
= *(int *)ptr
;
833 case R_X86_64_PLT32
: {
835 diff
= (long long)val
- addr
;
836 if (diff
<= -2147483647 || diff
> 2147483647) {
837 #ifdef TCC_HAS_RUNTIME_PLTGOT
838 /* XXX: naive support for over 32bit jump */
839 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
840 val
= (add_jmp_table(s1
, val
- rel
->r_addend
) +
845 if (diff
<= -2147483647 || diff
> 2147483647) {
846 tcc_error("internal error: relocation failed");
852 case R_X86_64_GLOB_DAT
:
853 case R_X86_64_JUMP_SLOT
:
854 /* They don't need addend */
855 *(int *)ptr
= val
- rel
->r_addend
;
857 case R_X86_64_GOTPCREL
:
858 #ifdef TCC_HAS_RUNTIME_PLTGOT
859 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
860 val
= add_got_table(s1
, val
- rel
->r_addend
) + rel
->r_addend
;
861 *(int *)ptr
+= val
- addr
;
865 *(int *)ptr
+= (s1
->got
->sh_addr
- addr
+
866 s1
->sym_attrs
[sym_index
].got_offset
- 4);
868 case R_X86_64_GOTTPOFF
:
869 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
872 /* we load the got offset */
873 *(int *)ptr
+= s1
->sym_attrs
[sym_index
].got_offset
;
876 #error unsupported processor
880 /* if the relocation is allocated, we change its symbol table */
881 if (sr
->sh_flags
& SHF_ALLOC
)
882 sr
->link
= s1
->dynsym
;
885 /* relocate relocation table in 'sr' */
886 static void relocate_rel(TCCState
*s1
, Section
*sr
)
891 s
= s1
->sections
[sr
->sh_info
];
892 for_each_elem(sr
, 0, rel
, ElfW_Rel
)
893 rel
->r_offset
+= s
->sh_addr
;
896 /* count the number of dynamic relocations so that we can reserve
898 static int prepare_dynamic_rel(TCCState
*s1
, Section
*sr
)
901 int sym_index
, esym_index
, type
, count
;
904 for_each_elem(sr
, 0, rel
, ElfW_Rel
) {
905 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
906 type
= ELFW(R_TYPE
)(rel
->r_info
);
908 #if defined(TCC_TARGET_I386)
910 #elif defined(TCC_TARGET_X86_64)
917 #if defined(TCC_TARGET_I386)
919 #elif defined(TCC_TARGET_X86_64)
922 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
931 /* allocate the section */
932 sr
->sh_flags
|= SHF_ALLOC
;
933 sr
->sh_size
= count
* sizeof(ElfW_Rel
);
938 static struct sym_attr
*alloc_sym_attr(TCCState
*s1
, int index
)
941 struct sym_attr
*tab
;
943 if (index
>= s1
->nb_sym_attrs
) {
944 /* find immediately bigger power of 2 and reallocate array */
948 tab
= tcc_realloc(s1
->sym_attrs
, n
* sizeof(*s1
->sym_attrs
));
950 memset(s1
->sym_attrs
+ s1
->nb_sym_attrs
, 0,
951 (n
- s1
->nb_sym_attrs
) * sizeof(*s1
->sym_attrs
));
952 s1
->nb_sym_attrs
= n
;
954 return &s1
->sym_attrs
[index
];
957 /* XXX: suppress that */
958 static void put32(unsigned char *p
, uint32_t val
)
966 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
967 defined(TCC_TARGET_X86_64)
968 static uint32_t get32(unsigned char *p
)
970 return p
[0] | (p
[1] << 8) | (p
[2] << 16) | (p
[3] << 24);
974 static void build_got(TCCState
*s1
)
978 /* if no got, then create it */
979 s1
->got
= new_section(s1
, ".got", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
980 s1
->got
->sh_entsize
= 4;
981 add_elf_sym(symtab_section
, 0, 4, ELFW(ST_INFO
)(STB_GLOBAL
, STT_OBJECT
),
982 0, s1
->got
->sh_num
, "_GLOBAL_OFFSET_TABLE_");
983 ptr
= section_ptr_add(s1
->got
, 3 * PTR_SIZE
);
985 /* keep space for _DYNAMIC pointer, if present */
987 /* two dummy got entries */
991 /* keep space for _DYNAMIC pointer, if present */
994 /* two dummy got entries */
1002 /* put a got entry corresponding to a symbol in symtab_section. 'size'
1003 and 'info' can be modifed if more precise info comes from the DLL */
1004 static void put_got_entry(TCCState
*s1
,
1005 int reloc_type
, unsigned long size
, int info
,
1011 unsigned long offset
;
1017 /* if a got entry already exists for that symbol, no need to add one */
1018 if (sym_index
< s1
->nb_sym_attrs
&&
1019 s1
->sym_attrs
[sym_index
].got_offset
)
1022 alloc_sym_attr(s1
, sym_index
)->got_offset
= s1
->got
->data_offset
;
1025 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1026 name
= symtab_section
->link
->data
+ sym
->st_name
;
1027 offset
= sym
->st_value
;
1028 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1030 #ifdef TCC_TARGET_X86_64
1040 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1043 /* if we build a DLL, we add a %ebx offset */
1044 if (s1
->output_type
== TCC_OUTPUT_DLL
)
1050 /* add a PLT entry */
1052 if (plt
->data_offset
== 0) {
1053 /* first plt entry */
1054 p
= section_ptr_add(plt
, 16);
1055 p
[0] = 0xff; /* pushl got + PTR_SIZE */
1056 p
[1] = modrm
+ 0x10;
1057 put32(p
+ 2, PTR_SIZE
);
1058 p
[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1060 put32(p
+ 8, PTR_SIZE
* 2);
1063 p
= section_ptr_add(plt
, 16);
1064 p
[0] = 0xff; /* jmp *(got + x) */
1066 put32(p
+ 2, s1
->got
->data_offset
);
1067 p
[6] = 0x68; /* push $xxx */
1068 put32(p
+ 7, (plt
->data_offset
- 32) >> 1);
1069 p
[11] = 0xe9; /* jmp plt_start */
1070 put32(p
+ 12, -(plt
->data_offset
));
1072 /* the symbol is modified so that it will be relocated to
1074 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
1075 if (s1
->output_type
== TCC_OUTPUT_EXE
)
1077 offset
= plt
->data_offset
- 16;
1079 #elif defined(TCC_TARGET_ARM)
1080 if (reloc_type
== R_ARM_JUMP_SLOT
) {
1084 /* if we build a DLL, we add a %ebx offset */
1085 if (s1
->output_type
== TCC_OUTPUT_DLL
)
1086 tcc_error("DLLs unimplemented!");
1088 /* add a PLT entry */
1090 if (plt
->data_offset
== 0) {
1091 /* first plt entry */
1092 p
= section_ptr_add(plt
, 16);
1093 put32(p
, 0xe52de004); /* push {lr} */
1094 put32(p
+4, 0xe59fe010); /* ldr lr, [pc, #16] */
1095 put32(p
+8, 0xe08fe00e); /* add lr, pc, lr */
1096 put32(p
+12, 0xe5bef008); /* ldr pc, [lr, #8]! */
1099 if (s1
->sym_attrs
[sym_index
].plt_thumb_stub
) {
1100 p
= section_ptr_add(plt
, 20);
1101 put32(p
, 0x4778); /* bx pc */
1102 put32(p
+2, 0x46c0); /* nop */
1105 p
= section_ptr_add(plt
, 16);
1106 put32(p
, 0xe59fc004); /* ldr ip, [pc, #4] ; GOT entry offset */
1107 put32(p
+4, 0xe08fc00c); /* add ip, pc, ip ; addr of GOT entry */
1108 put32(p
+8, 0xe59cf000); /* ldr pc, [ip] ; jump to GOT entry */
1109 put32(p
+12, s1
->got
->data_offset
); /* GOT entry off once patched */
1111 /* the symbol is modified so that it will be relocated to
1113 if (s1
->output_type
== TCC_OUTPUT_EXE
)
1114 offset
= plt
->data_offset
- 16;
1116 #elif defined(TCC_TARGET_C67)
1117 tcc_error("C67 got not implemented");
1119 #error unsupported CPU
1121 index
= put_elf_sym(s1
->dynsym
, offset
,
1122 size
, info
, 0, sym
->st_shndx
, name
);
1123 /* put a got entry */
1124 put_elf_reloc(s1
->dynsym
, s1
->got
,
1125 s1
->got
->data_offset
,
1128 ptr
= section_ptr_add(s1
->got
, PTR_SIZE
);
1132 /* build GOT and PLT entries */
1133 ST_FUNC
void build_got_entries(TCCState
*s1
)
1138 int i
, type
, reloc_type
, sym_index
;
1140 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1141 s
= s1
->sections
[i
];
1142 if (s
->sh_type
!= SHT_RELX
)
1144 /* no need to handle got relocations */
1145 if (s
->link
!= symtab_section
)
1147 for_each_elem(s
, 0, rel
, ElfW_Rel
) {
1148 type
= ELFW(R_TYPE
)(rel
->r_info
);
1150 #if defined(TCC_TARGET_I386)
1157 if (type
== R_386_GOT32
|| type
== R_386_PLT32
) {
1158 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1159 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1160 /* look at the symbol got offset. If none, then add one */
1161 if (type
== R_386_GOT32
)
1162 reloc_type
= R_386_GLOB_DAT
;
1164 reloc_type
= R_386_JMP_SLOT
;
1165 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1169 #elif defined(TCC_TARGET_ARM)
1176 if (type
== R_ARM_GOT32
|| type
== R_ARM_PLT32
) {
1177 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1178 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1179 /* look at the symbol got offset. If none, then add one */
1180 if (type
== R_ARM_GOT32
)
1181 reloc_type
= R_ARM_GLOB_DAT
;
1183 reloc_type
= R_ARM_JUMP_SLOT
;
1184 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1188 #elif defined(TCC_TARGET_C67)
1195 if (type
== R_C60_GOT32
|| type
== R_C60_PLT32
) {
1196 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1197 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1198 /* look at the symbol got offset. If none, then add one */
1199 if (type
== R_C60_GOT32
)
1200 reloc_type
= R_C60_GLOB_DAT
;
1202 reloc_type
= R_C60_JMP_SLOT
;
1203 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1207 #elif defined(TCC_TARGET_X86_64)
1208 case R_X86_64_GOT32
:
1209 case R_X86_64_GOTTPOFF
:
1210 case R_X86_64_GOTPCREL
:
1211 case R_X86_64_PLT32
:
1214 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
||
1215 type
== R_X86_64_PLT32
) {
1216 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1217 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1218 /* look at the symbol got offset. If none, then add one */
1219 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
)
1220 reloc_type
= R_X86_64_GLOB_DAT
;
1222 reloc_type
= R_X86_64_JUMP_SLOT
;
1223 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1228 #error unsupported CPU
1237 ST_FUNC Section
*new_symtab(TCCState
*s1
,
1238 const char *symtab_name
, int sh_type
, int sh_flags
,
1239 const char *strtab_name
,
1240 const char *hash_name
, int hash_sh_flags
)
1242 Section
*symtab
, *strtab
, *hash
;
1243 int *ptr
, nb_buckets
;
1245 symtab
= new_section(s1
, symtab_name
, sh_type
, sh_flags
);
1246 symtab
->sh_entsize
= sizeof(ElfW(Sym
));
1247 strtab
= new_section(s1
, strtab_name
, SHT_STRTAB
, sh_flags
);
1248 put_elf_str(strtab
, "");
1249 symtab
->link
= strtab
;
1250 put_elf_sym(symtab
, 0, 0, 0, 0, 0, NULL
);
1254 hash
= new_section(s1
, hash_name
, SHT_HASH
, hash_sh_flags
);
1255 hash
->sh_entsize
= sizeof(int);
1256 symtab
->hash
= hash
;
1257 hash
->link
= symtab
;
1259 ptr
= section_ptr_add(hash
, (2 + nb_buckets
+ 1) * sizeof(int));
1260 ptr
[0] = nb_buckets
;
1262 memset(ptr
+ 2, 0, (nb_buckets
+ 1) * sizeof(int));
1266 /* put dynamic tag */
1267 static void put_dt(Section
*dynamic
, int dt
, addr_t val
)
1270 dyn
= section_ptr_add(dynamic
, sizeof(ElfW(Dyn
)));
1272 dyn
->d_un
.d_val
= val
;
1275 static void add_init_array_defines(TCCState
*s1
, const char *section_name
)
1279 char sym_start
[1024];
1282 snprintf(sym_start
, sizeof(sym_start
), "__%s_start", section_name
+ 1);
1283 snprintf(sym_end
, sizeof(sym_end
), "__%s_end", section_name
+ 1);
1285 s
= find_section(s1
, section_name
);
1290 end_offset
= s
->data_offset
;
1293 add_elf_sym(symtab_section
,
1295 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1296 s
->sh_num
, sym_start
);
1297 add_elf_sym(symtab_section
,
1299 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1300 s
->sh_num
, sym_end
);
1303 ST_FUNC
void tcc_add_bcheck(TCCState
*s1
)
1305 #ifdef CONFIG_TCC_BCHECK
1307 Section
*init_section
;
1308 unsigned char *pinit
;
1311 if (0 == s1
->do_bounds_check
)
1314 /* XXX: add an object file to do that */
1315 ptr
= section_ptr_add(bounds_section
, sizeof(unsigned long));
1317 add_elf_sym(symtab_section
, 0, 0,
1318 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1319 bounds_section
->sh_num
, "__bounds_start");
1320 #ifdef TCC_TARGET_I386
1321 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
) {
1322 /* add 'call __bound_init()' in .init section */
1323 init_section
= find_section(s1
, ".init");
1324 pinit
= section_ptr_add(init_section
, 5);
1326 put32(pinit
+ 1, -4);
1327 sym_index
= find_elf_sym(symtab_section
, "__bound_init");
1328 put_elf_reloc(symtab_section
, init_section
,
1329 init_section
->data_offset
- 4, R_386_PC32
, sym_index
);
1335 static inline int tcc_add_support(TCCState
*s1
, const char *filename
)
1338 snprintf(buf
, sizeof(buf
), "%s/%s", s1
->tcc_lib_path
, filename
);
1339 return tcc_add_file(s1
, buf
);
1342 /* add tcc runtime libraries */
1343 ST_FUNC
void tcc_add_runtime(TCCState
*s1
)
1348 if (!s1
->nostdlib
) {
1349 tcc_add_library(s1
, "c");
1350 #ifdef CONFIG_USE_LIBGCC
1351 if (!s1
->static_link
)
1352 tcc_add_file(s1
, TCC_LIBGCC
);
1354 tcc_add_support(s1
, "libtcc1.a");
1356 tcc_add_support(s1
, "libtcc1.a");
1358 /* add crt end if not memory output */
1359 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
)
1360 tcc_add_crt(s1
, "crtn.o");
1364 /* add various standard linker symbols (must be done after the
1365 sections are filled (for example after allocating common
1367 ST_FUNC
void tcc_add_linker_symbols(TCCState
*s1
)
1373 add_elf_sym(symtab_section
,
1374 text_section
->data_offset
, 0,
1375 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1376 text_section
->sh_num
, "_etext");
1377 add_elf_sym(symtab_section
,
1378 data_section
->data_offset
, 0,
1379 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1380 data_section
->sh_num
, "_edata");
1381 add_elf_sym(symtab_section
,
1382 bss_section
->data_offset
, 0,
1383 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1384 bss_section
->sh_num
, "_end");
1385 /* horrible new standard ldscript defines */
1386 add_init_array_defines(s1
, ".preinit_array");
1387 add_init_array_defines(s1
, ".init_array");
1388 add_init_array_defines(s1
, ".fini_array");
1390 /* add start and stop symbols for sections whose name can be
1392 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1393 s
= s1
->sections
[i
];
1394 if (s
->sh_type
== SHT_PROGBITS
&&
1395 (s
->sh_flags
& SHF_ALLOC
)) {
1399 /* check if section name can be expressed in C */
1405 if (!isid(ch
) && !isnum(ch
))
1409 snprintf(buf
, sizeof(buf
), "__start_%s", s
->name
);
1410 add_elf_sym(symtab_section
,
1412 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1414 snprintf(buf
, sizeof(buf
), "__stop_%s", s
->name
);
1415 add_elf_sym(symtab_section
,
1417 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1424 static void tcc_output_binary(TCCState
*s1
, FILE *f
,
1425 const int *section_order
)
1428 int i
, offset
, size
;
1431 for(i
=1;i
<s1
->nb_sections
;i
++) {
1432 s
= s1
->sections
[section_order
[i
]];
1433 if (s
->sh_type
!= SHT_NOBITS
&&
1434 (s
->sh_flags
& SHF_ALLOC
)) {
1435 while (offset
< s
->sh_offset
) {
1440 fwrite(s
->data
, 1, size
, f
);
1446 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1448 #define EXTRA_RELITEMS 14
1450 /* move the relocation value from .dynsym to .got */
1451 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1453 uint32_t *gotd
= (void *)s1
->got
->data
;
1456 gotd
+= 3; /* dummy entries in .got */
1457 /* relocate symbols in .dynsym */
1458 for_each_elem(s
, 1, sym
, ElfW(Sym
)) {
1459 if (sym
->st_shndx
== SHN_UNDEF
) {
1460 *gotd
++ = sym
->st_value
+ 6; /* XXX 6 is magic ? */
1467 #define EXTRA_RELITEMS 9
1469 /* zero plt offsets of weak symbols in .dynsym */
1470 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1474 for_each_elem(s
, 1, sym
, ElfW(Sym
))
1475 if (sym
->st_shndx
== SHN_UNDEF
&& ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
1480 ST_FUNC
void fill_got_entry(TCCState
*s1
, ElfW_Rel
*rel
)
1482 int sym_index
= ELFW(R_SYM
) (rel
->r_info
);
1483 ElfW(Sym
) *sym
= &((ElfW(Sym
) *) symtab_section
->data
)[sym_index
];
1484 unsigned long offset
;
1486 if (sym_index
>= s1
->nb_sym_attrs
)
1488 offset
= s1
->sym_attrs
[sym_index
].got_offset
;
1489 section_reserve(s1
->got
, offset
+ PTR_SIZE
);
1490 #ifdef TCC_TARGET_X86_64
1491 /* only works for x86-64 */
1492 put32(s1
->got
->data
+ offset
+ 4, sym
->st_value
>> 32);
1494 put32(s1
->got
->data
+ offset
, sym
->st_value
& 0xffffffff);
1497 ST_FUNC
void fill_got(TCCState
*s1
)
1503 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1504 s
= s1
->sections
[i
];
1505 if (s
->sh_type
!= SHT_RELX
)
1507 /* no need to handle got relocations */
1508 if (s
->link
!= symtab_section
)
1510 for_each_elem(s
, 0, rel
, ElfW_Rel
) {
1511 switch (ELFW(R_TYPE
) (rel
->r_info
)) {
1512 case R_X86_64_GOT32
:
1513 case R_X86_64_GOTPCREL
:
1514 case R_X86_64_PLT32
:
1515 fill_got_entry(s1
, rel
);
1523 /* output an ELF file */
1524 /* XXX: suppress unneeded sections */
1525 static int elf_output_file(TCCState
*s1
, const char *filename
)
1531 int shnum
, i
, phnum
, file_offset
, offset
, size
, j
, sh_order_index
, k
;
1534 Section
*strsec
, *s
;
1535 ElfW(Shdr
) shdr
, *sh
;
1536 ElfW(Phdr
) *phdr
, *ph
;
1537 Section
*interp
, *dynamic
, *dynstr
;
1538 unsigned long saved_dynamic_data_offset
;
1540 int type
, file_type
;
1541 addr_t rel_addr
, rel_size
;
1542 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1543 addr_t bss_addr
, bss_size
;
1546 file_type
= s1
->output_type
;
1549 if (file_type
!= TCC_OUTPUT_OBJ
) {
1550 tcc_add_runtime(s1
);
1554 section_order
= NULL
;
1557 dynstr
= NULL
; /* avoid warning */
1558 saved_dynamic_data_offset
= 0; /* avoid warning */
1560 if (file_type
!= TCC_OUTPUT_OBJ
) {
1561 relocate_common_syms();
1563 tcc_add_linker_symbols(s1
);
1565 if (!s1
->static_link
) {
1567 int sym_index
, index
;
1570 if (file_type
== TCC_OUTPUT_EXE
) {
1572 /* allow override the dynamic loader */
1573 const char *elfint
= getenv("LD_SO");
1575 elfint
= DEFAULT_ELFINTERP(s1
);
1576 /* add interpreter section only if executable */
1577 interp
= new_section(s1
, ".interp", SHT_PROGBITS
, SHF_ALLOC
);
1578 interp
->sh_addralign
= 1;
1579 ptr
= section_ptr_add(interp
, 1+strlen(elfint
));
1580 strcpy(ptr
, elfint
);
1583 /* add dynamic symbol table */
1584 s1
->dynsym
= new_symtab(s1
, ".dynsym", SHT_DYNSYM
, SHF_ALLOC
,
1586 ".hash", SHF_ALLOC
);
1587 dynstr
= s1
->dynsym
->link
;
1589 /* add dynamic section */
1590 dynamic
= new_section(s1
, ".dynamic", SHT_DYNAMIC
,
1591 SHF_ALLOC
| SHF_WRITE
);
1592 dynamic
->link
= dynstr
;
1593 dynamic
->sh_entsize
= sizeof(ElfW(Dyn
));
1596 s1
->plt
= new_section(s1
, ".plt", SHT_PROGBITS
,
1597 SHF_ALLOC
| SHF_EXECINSTR
);
1598 s1
->plt
->sh_entsize
= 4;
1602 /* scan for undefined symbols and see if they are in the
1603 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1604 is found, then we add it in the PLT. If a symbol
1605 STT_OBJECT is found, we add it in the .bss section with
1606 a suitable relocation */
1607 if (file_type
== TCC_OUTPUT_EXE
) {
1608 for_each_elem(symtab_section
, 1, sym
, ElfW(Sym
)) {
1609 if (sym
->st_shndx
== SHN_UNDEF
) {
1610 name
= symtab_section
->link
->data
+ sym
->st_name
;
1611 sym_index
= find_elf_sym(s1
->dynsymtab_section
, name
);
1613 esym
= &((ElfW(Sym
) *)s1
->dynsymtab_section
->data
)[sym_index
];
1614 type
= ELFW(ST_TYPE
)(esym
->st_info
);
1615 if ((type
== STT_FUNC
) || (type
== STT_GNU_IFUNC
)) {
1616 /* Indirect functions shall have STT_FUNC type
1617 * in executable dynsym section. Indeed, a dlsym
1618 * call following a lazy resolution would pick
1619 * the symbol value from the executable dynsym
1620 * entry which would contain the address of the
1621 * function wanted by the caller of dlsym
1622 * instead of the address of the function that
1623 * would return that address */
1624 put_got_entry(s1
, R_JMP_SLOT
, esym
->st_size
,
1625 ELFW(ST_INFO
)(STB_GLOBAL
,STT_FUNC
),
1626 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1627 } else if (type
== STT_OBJECT
) {
1628 unsigned long offset
;
1630 offset
= bss_section
->data_offset
;
1631 /* XXX: which alignment ? */
1632 offset
= (offset
+ 16 - 1) & -16;
1633 index
= put_elf_sym(s1
->dynsym
, offset
, esym
->st_size
,
1635 bss_section
->sh_num
, name
);
1636 /* Ensure R_COPY works for weak symbol aliases */
1637 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1638 for_each_elem(s1
->dynsymtab_section
, 1, dynsym
, ElfW(Sym
)) {
1639 if ((dynsym
->st_value
== esym
->st_value
)
1640 && (ELFW(ST_BIND
)(dynsym
->st_info
) == STB_GLOBAL
)) {
1642 dynname
= s1
->dynsymtab_section
->link
->data
1644 put_elf_sym(s1
->dynsym
, offset
,
1647 bss_section
->sh_num
,
1653 put_elf_reloc(s1
->dynsym
, bss_section
,
1654 offset
, R_COPY
, index
);
1655 offset
+= esym
->st_size
;
1656 bss_section
->data_offset
= offset
;
1659 /* STB_WEAK undefined symbols are accepted */
1660 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1662 if (ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
||
1663 !strcmp(name
, "_fp_hw")) {
1665 tcc_error_noabort("undefined symbol '%s'", name
);
1668 } else if (s1
->rdynamic
&&
1669 ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1670 /* if -rdynamic option, then export all non
1672 name
= symtab_section
->link
->data
+ sym
->st_name
;
1673 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1675 sym
->st_shndx
, name
);
1682 /* now look at unresolved dynamic symbols and export
1683 corresponding symbol */
1684 for_each_elem(s1
->dynsymtab_section
, 1, esym
, ElfW(Sym
)) {
1685 if (esym
->st_shndx
== SHN_UNDEF
) {
1686 name
= s1
->dynsymtab_section
->link
->data
+ esym
->st_name
;
1687 sym_index
= find_elf_sym(symtab_section
, name
);
1689 /* XXX: avoid adding a symbol if already
1690 present because of -rdynamic ? */
1691 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1692 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1694 sym
->st_shndx
, name
);
1696 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1697 /* weak symbols can stay undefined */
1699 tcc_warning("undefined dynamic symbol '%s'", name
);
1706 /* shared library case : we simply export all the global symbols */
1707 nb_syms
= symtab_section
->data_offset
/ sizeof(ElfW(Sym
));
1708 s1
->symtab_to_dynsym
= tcc_mallocz(sizeof(int) * nb_syms
);
1709 for_each_elem(symtab_section
, 1, sym
, ElfW(Sym
)) {
1710 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1711 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1712 if ((ELFW(ST_TYPE
)(sym
->st_info
) == STT_FUNC
||
1713 ELFW(ST_TYPE
)(sym
->st_info
) == STT_GNU_IFUNC
)
1714 && sym
->st_shndx
== SHN_UNDEF
) {
1715 int visibility
= ELFW(ST_BIND
)(sym
->st_info
);
1716 put_got_entry(s1
, R_JMP_SLOT
, sym
->st_size
,
1717 ELFW(ST_INFO
)(visibility
,STT_FUNC
),
1718 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1720 else if (ELFW(ST_TYPE
)(sym
->st_info
) == STT_OBJECT
) {
1721 put_got_entry(s1
, R_X86_64_GLOB_DAT
, sym
->st_size
,
1723 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1728 name
= symtab_section
->link
->data
+ sym
->st_name
;
1729 index
= put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1731 sym
->st_shndx
, name
);
1732 s1
->symtab_to_dynsym
[sym
-
1733 (ElfW(Sym
) *)symtab_section
->data
] =
1740 build_got_entries(s1
);
1742 /* add a list of needed dlls */
1743 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
1744 DLLReference
*dllref
= s1
->loaded_dlls
[i
];
1745 if (dllref
->level
== 0)
1746 put_dt(dynamic
, DT_NEEDED
, put_elf_str(dynstr
, dllref
->name
));
1750 put_dt(dynamic
, DT_RPATH
, put_elf_str(dynstr
, s1
->rpath
));
1752 /* XXX: currently, since we do not handle PIC code, we
1753 must relocate the readonly segments */
1754 if (file_type
== TCC_OUTPUT_DLL
) {
1756 put_dt(dynamic
, DT_SONAME
, put_elf_str(dynstr
, s1
->soname
));
1757 put_dt(dynamic
, DT_TEXTREL
, 0);
1761 put_dt(dynamic
, DT_SYMBOLIC
, 0);
1763 /* add necessary space for other entries */
1764 saved_dynamic_data_offset
= dynamic
->data_offset
;
1765 dynamic
->data_offset
+= sizeof(ElfW(Dyn
)) * EXTRA_RELITEMS
;
1767 /* still need to build got entries in case of static link */
1768 build_got_entries(s1
);
1772 memset(&ehdr
, 0, sizeof(ehdr
));
1774 /* we add a section for symbols */
1775 strsec
= new_section(s1
, ".shstrtab", SHT_STRTAB
, 0);
1776 put_elf_str(strsec
, "");
1778 /* compute number of sections */
1779 shnum
= s1
->nb_sections
;
1781 /* this array is used to reorder sections in the output file */
1782 section_order
= tcc_malloc(sizeof(int) * shnum
);
1783 section_order
[0] = 0;
1786 /* compute number of program headers */
1789 case TCC_OUTPUT_OBJ
:
1792 case TCC_OUTPUT_EXE
:
1793 if (!s1
->static_link
)
1794 phnum
= 4 + HAVE_PHDR
;
1798 case TCC_OUTPUT_DLL
:
1803 /* allocate strings for section names and decide if an unallocated
1804 section should be output */
1805 /* NOTE: the strsec section comes last, so its size is also
1807 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1808 s
= s1
->sections
[i
];
1809 s
->sh_name
= put_elf_str(strsec
, s
->name
);
1810 /* when generating a DLL, we include relocations but we may
1812 if (file_type
== TCC_OUTPUT_DLL
&&
1813 s
->sh_type
== SHT_RELX
&&
1814 !(s
->sh_flags
& SHF_ALLOC
)) {
1815 /* gr: avoid bogus relocs for empty (debug) sections */
1816 if (s1
->sections
[s
->sh_info
]->sh_flags
& SHF_ALLOC
)
1817 prepare_dynamic_rel(s1
, s
);
1818 else if (s1
->do_debug
)
1819 s
->sh_size
= s
->data_offset
;
1820 } else if (s1
->do_debug
||
1821 file_type
== TCC_OUTPUT_OBJ
||
1822 (s
->sh_flags
& SHF_ALLOC
) ||
1823 i
== (s1
->nb_sections
- 1)) {
1824 /* we output all sections if debug or object file */
1825 s
->sh_size
= s
->data_offset
;
1829 /* allocate program segment headers */
1830 phdr
= tcc_mallocz(phnum
* sizeof(ElfW(Phdr
)));
1832 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1833 file_offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
1838 /* compute section to program header mapping */
1839 if (s1
->has_text_addr
) {
1840 int a_offset
, p_offset
;
1841 addr
= s1
->text_addr
;
1842 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1844 a_offset
= (int) (addr
& (s1
->section_align
- 1));
1845 p_offset
= file_offset
& (s1
->section_align
- 1);
1846 if (a_offset
< p_offset
)
1847 a_offset
+= s1
->section_align
;
1848 file_offset
+= (a_offset
- p_offset
);
1850 if (file_type
== TCC_OUTPUT_DLL
)
1853 addr
= ELF_START_ADDR
;
1854 /* compute address after headers */
1855 addr
+= (file_offset
& (s1
->section_align
- 1));
1858 /* dynamic relocation table information, for .dynamic section */
1862 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1863 bss_addr
= bss_size
= 0;
1865 /* leave one program header for the program interpreter */
1868 ph
+= 1 + HAVE_PHDR
;
1870 for(j
= 0; j
< 2; j
++) {
1871 ph
->p_type
= PT_LOAD
;
1873 ph
->p_flags
= PF_R
| PF_X
;
1875 ph
->p_flags
= PF_R
| PF_W
;
1876 ph
->p_align
= s1
->section_align
;
1878 /* we do the following ordering: interp, symbol tables,
1879 relocations, progbits, nobits */
1880 /* XXX: do faster and simpler sorting */
1881 for(k
= 0; k
< 5; k
++) {
1882 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1883 s
= s1
->sections
[i
];
1884 /* compute if section should be included */
1886 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1890 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1891 (SHF_ALLOC
| SHF_WRITE
))
1897 } else if (s
->sh_type
== SHT_DYNSYM
||
1898 s
->sh_type
== SHT_STRTAB
||
1899 s
->sh_type
== SHT_HASH
) {
1902 } else if (s
->sh_type
== SHT_RELX
) {
1905 } else if (s
->sh_type
== SHT_NOBITS
) {
1912 section_order
[sh_order_index
++] = i
;
1914 /* section matches: we align it and add its size */
1916 addr
= (addr
+ s
->sh_addralign
- 1) &
1917 ~(s
->sh_addralign
- 1);
1918 file_offset
+= (int) ( addr
- tmp
);
1919 s
->sh_offset
= file_offset
;
1922 /* update program header infos */
1923 if (ph
->p_offset
== 0) {
1924 ph
->p_offset
= file_offset
;
1926 ph
->p_paddr
= ph
->p_vaddr
;
1928 /* update dynamic relocation infos */
1929 if (s
->sh_type
== SHT_RELX
) {
1930 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1931 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.got")) {
1933 rel_size
+= s
->sh_size
; /* XXX only first rel. */
1935 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.bss")) {
1937 bss_size
= s
->sh_size
; /* XXX only first rel. */
1942 rel_size
+= s
->sh_size
;
1946 if (s
->sh_type
!= SHT_NOBITS
)
1947 file_offset
+= s
->sh_size
;
1950 ph
->p_filesz
= file_offset
- ph
->p_offset
;
1951 ph
->p_memsz
= addr
- ph
->p_vaddr
;
1954 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1955 /* if in the middle of a page, we duplicate the page in
1956 memory so that one copy is RX and the other is RW */
1957 if ((addr
& (s1
->section_align
- 1)) != 0)
1958 addr
+= s1
->section_align
;
1960 addr
= (addr
+ s1
->section_align
- 1) & ~(s1
->section_align
- 1);
1961 file_offset
= (file_offset
+ s1
->section_align
- 1) &
1962 ~(s1
->section_align
- 1);
1967 /* if interpreter, then add corresponing program header */
1971 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1973 int len
= phnum
* sizeof(ElfW(Phdr
));
1975 ph
->p_type
= PT_PHDR
;
1976 ph
->p_offset
= sizeof(ElfW(Ehdr
));
1977 ph
->p_vaddr
= interp
->sh_addr
- len
;
1978 ph
->p_paddr
= ph
->p_vaddr
;
1979 ph
->p_filesz
= ph
->p_memsz
= len
;
1980 ph
->p_flags
= PF_R
| PF_X
;
1981 ph
->p_align
= 4; /* interp->sh_addralign; */
1986 ph
->p_type
= PT_INTERP
;
1987 ph
->p_offset
= interp
->sh_offset
;
1988 ph
->p_vaddr
= interp
->sh_addr
;
1989 ph
->p_paddr
= ph
->p_vaddr
;
1990 ph
->p_filesz
= interp
->sh_size
;
1991 ph
->p_memsz
= interp
->sh_size
;
1993 ph
->p_align
= interp
->sh_addralign
;
1996 /* if dynamic section, then add corresponing program header */
1998 ph
= &phdr
[phnum
- 1];
2000 ph
->p_type
= PT_DYNAMIC
;
2001 ph
->p_offset
= dynamic
->sh_offset
;
2002 ph
->p_vaddr
= dynamic
->sh_addr
;
2003 ph
->p_paddr
= ph
->p_vaddr
;
2004 ph
->p_filesz
= dynamic
->sh_size
;
2005 ph
->p_memsz
= dynamic
->sh_size
;
2006 ph
->p_flags
= PF_R
| PF_W
;
2007 ph
->p_align
= dynamic
->sh_addralign
;
2009 /* put GOT dynamic section address */
2010 put32(s1
->got
->data
, dynamic
->sh_addr
);
2012 /* relocate the PLT */
2013 if (file_type
== TCC_OUTPUT_EXE
2014 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2015 || file_type
== TCC_OUTPUT_DLL
2021 p_end
= p
+ s1
->plt
->data_offset
;
2023 #if defined(TCC_TARGET_I386)
2024 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
2025 put32(p
+ 8, get32(p
+ 8) + s1
->got
->sh_addr
);
2028 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
2031 #elif defined(TCC_TARGET_X86_64)
2032 int x
= s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 6;
2033 put32(p
+ 2, get32(p
+ 2) + x
);
2034 put32(p
+ 8, get32(p
+ 8) + x
- 6);
2037 put32(p
+ 2, get32(p
+ 2) + x
+ s1
->plt
->data
- p
);
2040 #elif defined(TCC_TARGET_ARM)
2042 x
=s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 12;
2045 if (get32(p
) == 0x46c04778) /* PLT Thumb stub present */
2047 put32(p
+ 12, x
+ get32(p
+ 12) + s1
->plt
->data
- p
);
2050 #elif defined(TCC_TARGET_C67)
2053 #error unsupported CPU
2058 /* relocate symbols in .dynsym */
2059 for_each_elem(s1
->dynsym
, 1, sym
, ElfW(Sym
)) {
2060 if (sym
->st_shndx
== SHN_UNDEF
) {
2061 /* relocate to the PLT if the symbol corresponds
2064 sym
->st_value
+= s1
->plt
->sh_addr
;
2065 } else if (sym
->st_shndx
< SHN_LORESERVE
) {
2066 /* do symbol relocation */
2067 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
2071 /* put dynamic section entries */
2072 dynamic
->data_offset
= saved_dynamic_data_offset
;
2073 put_dt(dynamic
, DT_HASH
, s1
->dynsym
->hash
->sh_addr
);
2074 put_dt(dynamic
, DT_STRTAB
, dynstr
->sh_addr
);
2075 put_dt(dynamic
, DT_SYMTAB
, s1
->dynsym
->sh_addr
);
2076 put_dt(dynamic
, DT_STRSZ
, dynstr
->data_offset
);
2077 put_dt(dynamic
, DT_SYMENT
, sizeof(ElfW(Sym
)));
2078 #ifdef TCC_TARGET_X86_64
2079 put_dt(dynamic
, DT_RELA
, rel_addr
);
2080 put_dt(dynamic
, DT_RELASZ
, rel_size
);
2081 put_dt(dynamic
, DT_RELAENT
, sizeof(ElfW_Rel
));
2083 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2084 put_dt(dynamic
, DT_PLTGOT
, s1
->got
->sh_addr
);
2085 put_dt(dynamic
, DT_PLTRELSZ
, rel_size
);
2086 put_dt(dynamic
, DT_JMPREL
, rel_addr
);
2087 put_dt(dynamic
, DT_PLTREL
, DT_REL
);
2088 put_dt(dynamic
, DT_REL
, bss_addr
);
2089 put_dt(dynamic
, DT_RELSZ
, bss_size
);
2091 put_dt(dynamic
, DT_REL
, rel_addr
);
2092 put_dt(dynamic
, DT_RELSZ
, rel_size
);
2093 put_dt(dynamic
, DT_RELENT
, sizeof(ElfW_Rel
));
2097 put_dt(dynamic
, DT_DEBUG
, 0);
2098 put_dt(dynamic
, DT_NULL
, 0);
2101 ehdr
.e_phentsize
= sizeof(ElfW(Phdr
));
2102 ehdr
.e_phnum
= phnum
;
2103 ehdr
.e_phoff
= sizeof(ElfW(Ehdr
));
2106 /* all other sections come after */
2107 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2108 s
= s1
->sections
[i
];
2109 if (phnum
> 0 && (s
->sh_flags
& SHF_ALLOC
))
2111 section_order
[sh_order_index
++] = i
;
2113 file_offset
= (file_offset
+ s
->sh_addralign
- 1) &
2114 ~(s
->sh_addralign
- 1);
2115 s
->sh_offset
= file_offset
;
2116 if (s
->sh_type
!= SHT_NOBITS
)
2117 file_offset
+= s
->sh_size
;
2120 /* if building executable or DLL, then relocate each section
2121 except the GOT which is already relocated */
2122 if (file_type
!= TCC_OUTPUT_OBJ
) {
2123 relocate_syms(s1
, 0);
2125 if (s1
->nb_errors
!= 0) {
2131 /* relocate sections */
2132 /* XXX: ignore sections with allocated relocations ? */
2133 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2134 s
= s1
->sections
[i
];
2135 if (s
->reloc
&& s
!= s1
->got
)
2136 relocate_section(s1
, s
);
2139 /* relocate relocation entries if the relocation tables are
2140 allocated in the executable */
2141 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2142 s
= s1
->sections
[i
];
2143 if ((s
->sh_flags
& SHF_ALLOC
) &&
2144 s
->sh_type
== SHT_RELX
) {
2145 relocate_rel(s1
, s
);
2149 /* get entry point address */
2150 if (file_type
== TCC_OUTPUT_EXE
)
2151 ehdr
.e_entry
= get_elf_sym_addr(s1
, "_start", 1);
2153 ehdr
.e_entry
= text_section
->sh_addr
; /* XXX: is it correct ? */
2155 if (file_type
== TCC_OUTPUT_EXE
&& s1
->static_link
)
2158 /* write elf file */
2159 if (file_type
== TCC_OUTPUT_OBJ
)
2164 fd
= open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
, mode
);
2166 tcc_error_noabort("could not write '%s'", filename
);
2169 f
= fdopen(fd
, "wb");
2171 printf("<- %s\n", filename
);
2173 #ifdef TCC_TARGET_COFF
2174 if (s1
->output_format
== TCC_OUTPUT_FORMAT_COFF
) {
2175 tcc_output_coff(s1
, f
);
2178 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
2179 sort_syms(s1
, symtab_section
);
2182 file_offset
= (file_offset
+ 3) & -4;
2185 ehdr
.e_ident
[0] = ELFMAG0
;
2186 ehdr
.e_ident
[1] = ELFMAG1
;
2187 ehdr
.e_ident
[2] = ELFMAG2
;
2188 ehdr
.e_ident
[3] = ELFMAG3
;
2189 ehdr
.e_ident
[4] = ELFCLASSW
;
2190 ehdr
.e_ident
[5] = ELFDATA2LSB
;
2191 ehdr
.e_ident
[6] = EV_CURRENT
;
2192 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2193 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_FREEBSD
;
2195 #ifdef TCC_TARGET_ARM
2197 ehdr
.e_ident
[EI_OSABI
] = 0;
2198 ehdr
.e_flags
= EF_ARM_EABI_VER4
;
2199 if (file_type
== TCC_OUTPUT_EXE
|| file_type
== TCC_OUTPUT_DLL
)
2200 ehdr
.e_flags
|= EF_ARM_HASENTRY
;
2201 if (s1
->float_abi
== ARM_HARD_FLOAT
)
2202 ehdr
.e_flags
|= EF_ARM_VFP_FLOAT
;
2204 ehdr
.e_flags
|= EF_ARM_SOFT_FLOAT
;
2206 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_ARM
;
2211 case TCC_OUTPUT_EXE
:
2212 ehdr
.e_type
= ET_EXEC
;
2214 case TCC_OUTPUT_DLL
:
2215 ehdr
.e_type
= ET_DYN
;
2217 case TCC_OUTPUT_OBJ
:
2218 ehdr
.e_type
= ET_REL
;
2221 ehdr
.e_machine
= EM_TCC_TARGET
;
2222 ehdr
.e_version
= EV_CURRENT
;
2223 ehdr
.e_shoff
= file_offset
;
2224 ehdr
.e_ehsize
= sizeof(ElfW(Ehdr
));
2225 ehdr
.e_shentsize
= sizeof(ElfW(Shdr
));
2226 ehdr
.e_shnum
= shnum
;
2227 ehdr
.e_shstrndx
= shnum
- 1;
2229 fwrite(&ehdr
, 1, sizeof(ElfW(Ehdr
)), f
);
2230 fwrite(phdr
, 1, phnum
* sizeof(ElfW(Phdr
)), f
);
2231 offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
2233 for(i
=1;i
<s1
->nb_sections
;i
++) {
2234 s
= s1
->sections
[section_order
[i
]];
2235 if (s
->sh_type
!= SHT_NOBITS
) {
2236 if (s
->sh_type
== SHT_DYNSYM
)
2237 patch_dynsym_undef(s1
, s
);
2238 while (offset
< s
->sh_offset
) {
2243 fwrite(s
->data
, 1, size
, f
);
2248 /* output section headers */
2249 while (offset
< ehdr
.e_shoff
) {
2254 for(i
=0;i
<s1
->nb_sections
;i
++) {
2256 memset(sh
, 0, sizeof(ElfW(Shdr
)));
2257 s
= s1
->sections
[i
];
2259 sh
->sh_name
= s
->sh_name
;
2260 sh
->sh_type
= s
->sh_type
;
2261 sh
->sh_flags
= s
->sh_flags
;
2262 sh
->sh_entsize
= s
->sh_entsize
;
2263 sh
->sh_info
= s
->sh_info
;
2265 sh
->sh_link
= s
->link
->sh_num
;
2266 sh
->sh_addralign
= s
->sh_addralign
;
2267 sh
->sh_addr
= s
->sh_addr
;
2268 sh
->sh_offset
= s
->sh_offset
;
2269 sh
->sh_size
= s
->sh_size
;
2271 fwrite(sh
, 1, sizeof(ElfW(Shdr
)), f
);
2274 tcc_output_binary(s1
, f
, section_order
);
2280 tcc_free(s1
->symtab_to_dynsym
);
2281 tcc_free(section_order
);
2283 tcc_free(s1
->sym_attrs
);
2287 LIBTCCAPI
int tcc_output_file(TCCState
*s
, const char *filename
)
2290 #ifdef TCC_TARGET_PE
2291 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
2292 ret
= pe_output_file(s
, filename
);
2296 ret
= elf_output_file(s
, filename
);
2301 static void *load_data(int fd
, unsigned long file_offset
, unsigned long size
)
2305 data
= tcc_malloc(size
);
2306 lseek(fd
, file_offset
, SEEK_SET
);
2307 read(fd
, data
, size
);
2311 typedef struct SectionMergeInfo
{
2312 Section
*s
; /* corresponding existing section */
2313 unsigned long offset
; /* offset of the new section in the existing section */
2314 uint8_t new_section
; /* true if section 's' was added */
2315 uint8_t link_once
; /* true if link once section */
2318 /* load an object file and merge it with current files */
2319 /* XXX: handle correctly stab (debug) info */
2320 ST_FUNC
int tcc_load_object_file(TCCState
*s1
,
2321 int fd
, unsigned long file_offset
)
2324 ElfW(Shdr
) *shdr
, *sh
;
2325 int size
, i
, j
, offset
, offseti
, nb_syms
, sym_index
, ret
;
2326 unsigned char *strsec
, *strtab
;
2327 int *old_to_new_syms
;
2328 char *sh_name
, *name
;
2329 SectionMergeInfo
*sm_table
, *sm
;
2330 ElfW(Sym
) *sym
, *symtab
;
2337 stab_index
= stabstr_index
= 0;
2339 if (read(fd
, &ehdr
, sizeof(ehdr
)) != sizeof(ehdr
))
2341 if (ehdr
.e_ident
[0] != ELFMAG0
||
2342 ehdr
.e_ident
[1] != ELFMAG1
||
2343 ehdr
.e_ident
[2] != ELFMAG2
||
2344 ehdr
.e_ident
[3] != ELFMAG3
)
2346 /* test if object file */
2347 if (ehdr
.e_type
!= ET_REL
)
2349 /* test CPU specific stuff */
2350 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2351 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2353 tcc_error_noabort("invalid object file");
2357 shdr
= load_data(fd
, file_offset
+ ehdr
.e_shoff
,
2358 sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2359 sm_table
= tcc_mallocz(sizeof(SectionMergeInfo
) * ehdr
.e_shnum
);
2361 /* load section names */
2362 sh
= &shdr
[ehdr
.e_shstrndx
];
2363 strsec
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2365 /* load symtab and strtab */
2366 old_to_new_syms
= NULL
;
2370 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2372 if (sh
->sh_type
== SHT_SYMTAB
) {
2374 tcc_error_noabort("object must contain only one symtab");
2379 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2380 symtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2381 sm_table
[i
].s
= symtab_section
;
2383 /* now load strtab */
2384 sh
= &shdr
[sh
->sh_link
];
2385 strtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2389 /* now examine each section and try to merge its content with the
2391 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2392 /* no need to examine section name strtab */
2393 if (i
== ehdr
.e_shstrndx
)
2396 sh_name
= strsec
+ sh
->sh_name
;
2397 /* ignore sections types we do not handle */
2398 if (sh
->sh_type
!= SHT_PROGBITS
&&
2399 sh
->sh_type
!= SHT_RELX
&&
2401 sh
->sh_type
!= SHT_ARM_EXIDX
&&
2403 sh
->sh_type
!= SHT_NOBITS
&&
2404 sh
->sh_type
!= SHT_PREINIT_ARRAY
&&
2405 sh
->sh_type
!= SHT_INIT_ARRAY
&&
2406 sh
->sh_type
!= SHT_FINI_ARRAY
&&
2407 strcmp(sh_name
, ".stabstr")
2410 if (sh
->sh_addralign
< 1)
2411 sh
->sh_addralign
= 1;
2412 /* find corresponding section, if any */
2413 for(j
= 1; j
< s1
->nb_sections
;j
++) {
2414 s
= s1
->sections
[j
];
2415 if (!strcmp(s
->name
, sh_name
)) {
2416 if (!strncmp(sh_name
, ".gnu.linkonce",
2417 sizeof(".gnu.linkonce") - 1)) {
2418 /* if a 'linkonce' section is already present, we
2419 do not add it again. It is a little tricky as
2420 symbols can still be defined in
2422 sm_table
[i
].link_once
= 1;
2429 /* not found: create new section */
2430 s
= new_section(s1
, sh_name
, sh
->sh_type
, sh
->sh_flags
);
2431 /* take as much info as possible from the section. sh_link and
2432 sh_info will be updated later */
2433 s
->sh_addralign
= sh
->sh_addralign
;
2434 s
->sh_entsize
= sh
->sh_entsize
;
2435 sm_table
[i
].new_section
= 1;
2437 if (sh
->sh_type
!= s
->sh_type
) {
2438 tcc_error_noabort("invalid section type");
2442 /* align start of section */
2443 offset
= s
->data_offset
;
2445 if (0 == strcmp(sh_name
, ".stab")) {
2449 if (0 == strcmp(sh_name
, ".stabstr")) {
2454 size
= sh
->sh_addralign
- 1;
2455 offset
= (offset
+ size
) & ~size
;
2456 if (sh
->sh_addralign
> s
->sh_addralign
)
2457 s
->sh_addralign
= sh
->sh_addralign
;
2458 s
->data_offset
= offset
;
2460 sm_table
[i
].offset
= offset
;
2462 /* concatenate sections */
2464 if (sh
->sh_type
!= SHT_NOBITS
) {
2466 lseek(fd
, file_offset
+ sh
->sh_offset
, SEEK_SET
);
2467 ptr
= section_ptr_add(s
, size
);
2468 read(fd
, ptr
, size
);
2470 s
->data_offset
+= size
;
2475 /* gr relocate stab strings */
2476 if (stab_index
&& stabstr_index
) {
2479 s
= sm_table
[stab_index
].s
;
2480 a
= (Stab_Sym
*)(s
->data
+ sm_table
[stab_index
].offset
);
2481 b
= (Stab_Sym
*)(s
->data
+ s
->data_offset
);
2482 o
= sm_table
[stabstr_index
].offset
;
2484 a
->n_strx
+= o
, a
++;
2487 /* second short pass to update sh_link and sh_info fields of new
2489 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2491 if (!s
|| !sm_table
[i
].new_section
)
2494 if (sh
->sh_link
> 0)
2495 s
->link
= sm_table
[sh
->sh_link
].s
;
2496 if (sh
->sh_type
== SHT_RELX
) {
2497 s
->sh_info
= sm_table
[sh
->sh_info
].s
->sh_num
;
2498 /* update backward link */
2499 s1
->sections
[s
->sh_info
]->reloc
= s
;
2504 /* resolve symbols */
2505 old_to_new_syms
= tcc_mallocz(nb_syms
* sizeof(int));
2508 for(i
= 1; i
< nb_syms
; i
++, sym
++) {
2509 if (sym
->st_shndx
!= SHN_UNDEF
&&
2510 sym
->st_shndx
< SHN_LORESERVE
) {
2511 sm
= &sm_table
[sym
->st_shndx
];
2512 if (sm
->link_once
) {
2513 /* if a symbol is in a link once section, we use the
2514 already defined symbol. It is very important to get
2515 correct relocations */
2516 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
2517 name
= strtab
+ sym
->st_name
;
2518 sym_index
= find_elf_sym(symtab_section
, name
);
2520 old_to_new_syms
[i
] = sym_index
;
2524 /* if no corresponding section added, no need to add symbol */
2527 /* convert section number */
2528 sym
->st_shndx
= sm
->s
->sh_num
;
2530 sym
->st_value
+= sm
->offset
;
2533 name
= strtab
+ sym
->st_name
;
2534 sym_index
= add_elf_sym(symtab_section
, sym
->st_value
, sym
->st_size
,
2535 sym
->st_info
, sym
->st_other
,
2536 sym
->st_shndx
, name
);
2537 old_to_new_syms
[i
] = sym_index
;
2540 /* third pass to patch relocation entries */
2541 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2546 offset
= sm_table
[i
].offset
;
2547 switch(s
->sh_type
) {
2549 /* take relocation offset information */
2550 offseti
= sm_table
[sh
->sh_info
].offset
;
2551 for_each_elem(s
, (offset
/ sizeof(*rel
)), rel
, ElfW_Rel
) {
2554 /* convert symbol index */
2555 type
= ELFW(R_TYPE
)(rel
->r_info
);
2556 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
2557 /* NOTE: only one symtab assumed */
2558 if (sym_index
>= nb_syms
)
2560 sym_index
= old_to_new_syms
[sym_index
];
2561 /* ignore link_once in rel section. */
2562 if (!sym_index
&& !sm
->link_once
2563 #ifdef TCC_TARGET_ARM
2564 && type
!= R_ARM_V4BX
2568 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2569 i
, strsec
+ sh
->sh_name
, rel
->r_offset
);
2572 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
2573 /* offset the relocation offset */
2574 rel
->r_offset
+= offseti
;
2575 #ifdef TCC_TARGET_ARM
2576 /* Jumps and branches from a Thumb code to a PLT entry need
2577 special handling since PLT entries are ARM code.
2578 Unconditional bl instructions referencing PLT entries are
2579 handled by converting these instructions into blx
2580 instructions. Other case of instructions referencing a PLT
2581 entry require to add a Thumb stub before the PLT entry to
2582 switch to ARM mode. We set bit 0 of the got offset of a
2583 symbol to indicate such a case. */
2584 if (type
== R_ARM_THM_JUMP24
)
2585 alloc_sym_attr(s1
, sym_index
)->plt_thumb_stub
= 1;
2598 tcc_free(old_to_new_syms
);
2605 typedef struct ArchiveHeader
{
2606 char ar_name
[16]; /* name of this member */
2607 char ar_date
[12]; /* file mtime */
2608 char ar_uid
[6]; /* owner uid; printed as decimal */
2609 char ar_gid
[6]; /* owner gid; printed as decimal */
2610 char ar_mode
[8]; /* file mode, printed as octal */
2611 char ar_size
[10]; /* file size, printed as decimal */
2612 char ar_fmag
[2]; /* should contain ARFMAG */
2615 static int get_be32(const uint8_t *b
)
2617 return b
[3] | (b
[2] << 8) | (b
[1] << 16) | (b
[0] << 24);
2620 /* load only the objects which resolve undefined symbols */
2621 static int tcc_load_alacarte(TCCState
*s1
, int fd
, int size
)
2623 int i
, bound
, nsyms
, sym_index
, off
, ret
;
2625 const char *ar_names
, *p
;
2626 const uint8_t *ar_index
;
2629 data
= tcc_malloc(size
);
2630 if (read(fd
, data
, size
) != size
)
2632 nsyms
= get_be32(data
);
2633 ar_index
= data
+ 4;
2634 ar_names
= ar_index
+ nsyms
* 4;
2638 for(p
= ar_names
, i
= 0; i
< nsyms
; i
++, p
+= strlen(p
)+1) {
2639 sym_index
= find_elf_sym(symtab_section
, p
);
2641 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
2642 if(sym
->st_shndx
== SHN_UNDEF
) {
2643 off
= get_be32(ar_index
+ i
* 4) + sizeof(ArchiveHeader
);
2645 lseek(fd
, off
, SEEK_SET
);
2646 if(tcc_load_object_file(s1
, fd
, off
) < 0) {
2661 /* load a '.a' file */
2662 ST_FUNC
int tcc_load_archive(TCCState
*s1
, int fd
)
2669 unsigned long file_offset
;
2671 /* skip magic which was already checked */
2672 read(fd
, magic
, sizeof(magic
));
2675 len
= read(fd
, &hdr
, sizeof(hdr
));
2678 if (len
!= sizeof(hdr
)) {
2679 tcc_error_noabort("invalid archive");
2682 memcpy(ar_size
, hdr
.ar_size
, sizeof(hdr
.ar_size
));
2683 ar_size
[sizeof(hdr
.ar_size
)] = '\0';
2684 size
= strtol(ar_size
, NULL
, 0);
2685 memcpy(ar_name
, hdr
.ar_name
, sizeof(hdr
.ar_name
));
2686 for(i
= sizeof(hdr
.ar_name
) - 1; i
>= 0; i
--) {
2687 if (ar_name
[i
] != ' ')
2690 ar_name
[i
+ 1] = '\0';
2691 file_offset
= lseek(fd
, 0, SEEK_CUR
);
2693 size
= (size
+ 1) & ~1;
2694 if (!strcmp(ar_name
, "/")) {
2695 /* coff symbol table : we handle it */
2696 if(s1
->alacarte_link
)
2697 return tcc_load_alacarte(s1
, fd
, size
);
2698 } else if (!strcmp(ar_name
, "//") ||
2699 !strcmp(ar_name
, "__.SYMDEF") ||
2700 !strcmp(ar_name
, "__.SYMDEF/") ||
2701 !strcmp(ar_name
, "ARFILENAMES/")) {
2702 /* skip symbol table or archive names */
2704 if (tcc_load_object_file(s1
, fd
, file_offset
) < 0)
2707 lseek(fd
, file_offset
+ size
, SEEK_SET
);
2712 #ifndef TCC_TARGET_PE
2713 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2714 is referenced by the user (so it should be added as DT_NEEDED in
2715 the generated ELF file) */
2716 ST_FUNC
int tcc_load_dll(TCCState
*s1
, int fd
, const char *filename
, int level
)
2719 ElfW(Shdr
) *shdr
, *sh
, *sh1
;
2720 int i
, j
, nb_syms
, nb_dts
, sym_bind
, ret
;
2721 ElfW(Sym
) *sym
, *dynsym
;
2722 ElfW(Dyn
) *dt
, *dynamic
;
2723 unsigned char *dynstr
;
2724 const char *name
, *soname
;
2725 DLLReference
*dllref
;
2727 read(fd
, &ehdr
, sizeof(ehdr
));
2729 /* test CPU specific stuff */
2730 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2731 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2732 tcc_error_noabort("bad architecture");
2737 shdr
= load_data(fd
, ehdr
.e_shoff
, sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2739 /* load dynamic section and dynamic symbols */
2743 dynsym
= NULL
; /* avoid warning */
2744 dynstr
= NULL
; /* avoid warning */
2745 for(i
= 0, sh
= shdr
; i
< ehdr
.e_shnum
; i
++, sh
++) {
2746 switch(sh
->sh_type
) {
2748 nb_dts
= sh
->sh_size
/ sizeof(ElfW(Dyn
));
2749 dynamic
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2752 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2753 dynsym
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2754 sh1
= &shdr
[sh
->sh_link
];
2755 dynstr
= load_data(fd
, sh1
->sh_offset
, sh1
->sh_size
);
2762 /* compute the real library name */
2763 soname
= tcc_basename(filename
);
2765 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2766 if (dt
->d_tag
== DT_SONAME
) {
2767 soname
= dynstr
+ dt
->d_un
.d_val
;
2771 /* if the dll is already loaded, do not load it */
2772 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
2773 dllref
= s1
->loaded_dlls
[i
];
2774 if (!strcmp(soname
, dllref
->name
)) {
2775 /* but update level if needed */
2776 if (level
< dllref
->level
)
2777 dllref
->level
= level
;
2783 /* add the dll and its level */
2784 dllref
= tcc_mallocz(sizeof(DLLReference
) + strlen(soname
));
2785 dllref
->level
= level
;
2786 strcpy(dllref
->name
, soname
);
2787 dynarray_add((void ***)&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
, dllref
);
2789 /* add dynamic symbols in dynsym_section */
2790 for(i
= 1, sym
= dynsym
+ 1; i
< nb_syms
; i
++, sym
++) {
2791 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
2792 if (sym_bind
== STB_LOCAL
)
2794 name
= dynstr
+ sym
->st_name
;
2795 add_elf_sym(s1
->dynsymtab_section
, sym
->st_value
, sym
->st_size
,
2796 sym
->st_info
, sym
->st_other
, sym
->st_shndx
, name
);
2799 /* load all referenced DLLs */
2800 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2803 name
= dynstr
+ dt
->d_un
.d_val
;
2804 for(j
= 0; j
< s1
->nb_loaded_dlls
; j
++) {
2805 dllref
= s1
->loaded_dlls
[j
];
2806 if (!strcmp(name
, dllref
->name
))
2807 goto already_loaded
;
2809 if (tcc_add_dll(s1
, name
, AFF_REFERENCED_DLL
) < 0) {
2810 tcc_error_noabort("referenced dll '%s' not found", name
);
2827 #define LD_TOK_NAME 256
2828 #define LD_TOK_EOF (-1)
2830 /* return next ld script token */
2831 static int ld_next(TCCState
*s1
, char *name
, int name_size
)
2849 file
->buf_ptr
= parse_comment(file
->buf_ptr
);
2850 ch
= file
->buf_ptr
[0];
2858 /* case 'a' ... 'z': */
2885 /* case 'A' ... 'z': */
2920 if (!((ch
>= 'a' && ch
<= 'z') ||
2921 (ch
>= 'A' && ch
<= 'Z') ||
2922 (ch
>= '0' && ch
<= '9') ||
2923 strchr("/.-_+=$:\\,~", ch
)))
2925 if ((q
- name
) < name_size
- 1) {
2944 static int ld_add_file(TCCState
*s1
, const char filename
[])
2948 ret
= tcc_add_file_internal(s1
, filename
, 0);
2950 ret
= tcc_add_dll(s1
, filename
, 0);
2954 static inline int new_undef_syms(void)
2957 ret
= new_undef_sym
;
2962 static int ld_add_file_list(TCCState
*s1
, const char *cmd
, int as_needed
)
2964 char filename
[1024], libname
[1024];
2965 int t
, group
, nblibs
= 0, ret
= 0;
2968 group
= !strcmp(cmd
, "GROUP");
2971 t
= ld_next(s1
, filename
, sizeof(filename
));
2974 t
= ld_next(s1
, filename
, sizeof(filename
));
2977 if (t
== LD_TOK_EOF
) {
2978 tcc_error_noabort("unexpected end of file");
2980 goto lib_parse_error
;
2981 } else if (t
== ')') {
2983 } else if (t
== '-') {
2984 t
= ld_next(s1
, filename
, sizeof(filename
));
2985 if ((t
!= LD_TOK_NAME
) || (filename
[0] != 'l')) {
2986 tcc_error_noabort("library name expected");
2988 goto lib_parse_error
;
2990 pstrcpy(libname
, sizeof libname
, &filename
[1]);
2991 if (s1
->static_link
) {
2992 snprintf(filename
, sizeof filename
, "lib%s.a", libname
);
2994 snprintf(filename
, sizeof filename
, "lib%s.so", libname
);
2996 } else if (t
!= LD_TOK_NAME
) {
2997 tcc_error_noabort("filename expected");
2999 goto lib_parse_error
;
3001 if (!strcmp(filename
, "AS_NEEDED")) {
3002 ret
= ld_add_file_list(s1
, cmd
, 1);
3004 goto lib_parse_error
;
3006 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3008 ret
= ld_add_file(s1
, filename
);
3010 goto lib_parse_error
;
3012 /* Add the filename *and* the libname to avoid future conversions */
3013 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(filename
));
3014 if (libname
[0] != '\0')
3015 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(libname
));
3019 t
= ld_next(s1
, filename
, sizeof(filename
));
3021 t
= ld_next(s1
, filename
, sizeof(filename
));
3024 if (group
&& !as_needed
) {
3025 while (new_undef_syms()) {
3028 for (i
= 0; i
< nblibs
; i
++)
3029 ld_add_file(s1
, libs
[i
]);
3033 dynarray_reset(&libs
, &nblibs
);
3037 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3039 ST_FUNC
int tcc_load_ldscript(TCCState
*s1
)
3042 char filename
[1024];
3045 ch
= file
->buf_ptr
[0];
3048 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3049 if (t
== LD_TOK_EOF
)
3051 else if (t
!= LD_TOK_NAME
)
3053 if (!strcmp(cmd
, "INPUT") ||
3054 !strcmp(cmd
, "GROUP")) {
3055 ret
= ld_add_file_list(s1
, cmd
, 0);
3058 } else if (!strcmp(cmd
, "OUTPUT_FORMAT") ||
3059 !strcmp(cmd
, "TARGET")) {
3060 /* ignore some commands */
3061 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3065 t
= ld_next(s1
, filename
, sizeof(filename
));
3066 if (t
== LD_TOK_EOF
) {
3067 tcc_error_noabort("unexpected end of file");
3069 } else if (t
== ')') {
3079 #endif /* !TCC_TARGET_PE */