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 /* XXX: avoid static variable */
24 static int new_undef_sym
= 0; /* Is there a new undefined sym since last new_undef_sym() */
26 ST_FUNC
int put_elf_str(Section
*s
, const char *sym
)
31 len
= strlen(sym
) + 1;
32 offset
= s
->data_offset
;
33 ptr
= section_ptr_add(s
, len
);
34 memcpy(ptr
, sym
, len
);
38 /* elf symbol hashing function */
39 static unsigned long elf_hash(const unsigned char *name
)
41 unsigned long h
= 0, g
;
44 h
= (h
<< 4) + *name
++;
53 /* rebuild hash table of section s */
54 /* NOTE: we do factorize the hash table code to go faster */
55 static void rebuild_hash(Section
*s
, unsigned int nb_buckets
)
58 int *ptr
, *hash
, nb_syms
, sym_index
, h
;
61 strtab
= s
->link
->data
;
62 nb_syms
= s
->data_offset
/ sizeof(ElfW(Sym
));
64 s
->hash
->data_offset
= 0;
65 ptr
= section_ptr_add(s
->hash
, (2 + nb_buckets
+ nb_syms
) * sizeof(int));
70 memset(hash
, 0, (nb_buckets
+ 1) * sizeof(int));
71 ptr
+= nb_buckets
+ 1;
73 sym
= (ElfW(Sym
) *)s
->data
+ 1;
74 for(sym_index
= 1; sym_index
< nb_syms
; sym_index
++) {
75 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
76 h
= elf_hash(strtab
+ sym
->st_name
) % nb_buckets
;
87 /* return the symbol number */
88 ST_FUNC
int put_elf_sym(Section
*s
, addr_t value
, unsigned long size
,
89 int info
, int other
, int shndx
, const char *name
)
91 int name_offset
, sym_index
;
96 sym
= section_ptr_add(s
, sizeof(ElfW(Sym
)));
98 name_offset
= put_elf_str(s
->link
, name
);
101 /* XXX: endianness */
102 sym
->st_name
= name_offset
;
103 sym
->st_value
= value
;
106 sym
->st_other
= other
;
107 sym
->st_shndx
= shndx
;
108 sym_index
= sym
- (ElfW(Sym
) *)s
->data
;
112 ptr
= section_ptr_add(hs
, sizeof(int));
113 base
= (int *)hs
->data
;
114 /* only add global or weak symbols */
115 if (ELFW(ST_BIND
)(info
) != STB_LOCAL
) {
116 /* add another hashing entry */
118 h
= elf_hash(name
) % nbuckets
;
120 base
[2 + h
] = sym_index
;
122 /* we resize the hash table */
123 hs
->nb_hashed_syms
++;
124 if (hs
->nb_hashed_syms
> 2 * nbuckets
) {
125 rebuild_hash(s
, 2 * nbuckets
);
135 /* find global ELF symbol 'name' and return its index. Return 0 if not
137 ST_FUNC
int find_elf_sym(Section
*s
, const char *name
)
141 int nbuckets
, sym_index
, h
;
147 nbuckets
= ((int *)hs
->data
)[0];
148 h
= elf_hash(name
) % nbuckets
;
149 sym_index
= ((int *)hs
->data
)[2 + h
];
150 while (sym_index
!= 0) {
151 sym
= &((ElfW(Sym
) *)s
->data
)[sym_index
];
152 name1
= s
->link
->data
+ sym
->st_name
;
153 if (!strcmp(name
, name1
))
155 sym_index
= ((int *)hs
->data
)[2 + nbuckets
+ sym_index
];
160 /* return elf symbol value, signal error if 'err' is nonzero */
161 ST_FUNC addr_t
get_elf_sym_addr(TCCState
*s
, const char *name
, int err
)
166 sym_index
= find_elf_sym(s
->symtab
, name
);
167 sym
= &((ElfW(Sym
) *)s
->symtab
->data
)[sym_index
];
168 if (!sym_index
|| sym
->st_shndx
== SHN_UNDEF
) {
170 tcc_error("%s not defined", name
);
173 return sym
->st_value
;
176 /* return elf symbol value */
177 LIBTCCAPI
void *tcc_get_symbol(TCCState
*s
, const char *name
)
179 return (void*)(uintptr_t)get_elf_sym_addr(s
, name
, 0);
182 #if defined TCC_IS_NATIVE || defined TCC_TARGET_PE
183 /* return elf symbol value or error */
184 ST_FUNC
void* tcc_get_symbol_err(TCCState
*s
, const char *name
)
186 return (void*)(uintptr_t)get_elf_sym_addr(s
, name
, 1);
190 /* add an elf symbol : check if it is already defined and patch
191 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
192 ST_FUNC
int add_elf_sym(Section
*s
, addr_t value
, unsigned long size
,
193 int info
, int other
, int sh_num
, const char *name
)
196 int sym_bind
, sym_index
, sym_type
, esym_bind
;
197 unsigned char sym_vis
, esym_vis
, new_vis
;
199 sym_bind
= ELFW(ST_BIND
)(info
);
200 sym_type
= ELFW(ST_TYPE
)(info
);
201 sym_vis
= ELFW(ST_VISIBILITY
)(other
);
203 if (sym_bind
!= STB_LOCAL
) {
204 /* we search global or weak symbols */
205 sym_index
= find_elf_sym(s
, name
);
208 esym
= &((ElfW(Sym
) *)s
->data
)[sym_index
];
209 if (esym
->st_shndx
!= SHN_UNDEF
) {
210 esym_bind
= ELFW(ST_BIND
)(esym
->st_info
);
211 /* propagate the most constraining visibility */
212 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
213 esym_vis
= ELFW(ST_VISIBILITY
)(esym
->st_other
);
214 if (esym_vis
== STV_DEFAULT
) {
216 } else if (sym_vis
== STV_DEFAULT
) {
219 new_vis
= (esym_vis
< sym_vis
) ? esym_vis
: sym_vis
;
221 esym
->st_other
= (esym
->st_other
& ~ELFW(ST_VISIBILITY
)(-1))
223 other
= esym
->st_other
; /* in case we have to patch esym */
224 if (sh_num
== SHN_UNDEF
) {
225 /* ignore adding of undefined symbol if the
226 corresponding symbol is already defined */
227 } else if (sym_bind
== STB_GLOBAL
&& esym_bind
== STB_WEAK
) {
228 /* global overrides weak, so patch */
230 } else if (sym_bind
== STB_WEAK
&& esym_bind
== STB_GLOBAL
) {
231 /* weak is ignored if already global */
232 } else if (sym_bind
== STB_WEAK
&& esym_bind
== STB_WEAK
) {
233 /* keep first-found weak definition, ignore subsequents */
234 } else if (sym_vis
== STV_HIDDEN
|| sym_vis
== STV_INTERNAL
) {
235 /* ignore hidden symbols after */
236 } else if (esym
->st_shndx
== SHN_COMMON
237 && (sh_num
< SHN_LORESERVE
|| sh_num
== SHN_COMMON
)) {
238 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
239 No idea if this is the correct solution ... */
241 } else if (s
== tcc_state
->dynsymtab_section
) {
242 /* we accept that two DLL define the same symbol */
245 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
246 sym_bind
, sh_num
, new_vis
, esym_bind
, esym
->st_shndx
, esym_vis
);
248 tcc_error_noabort("'%s' defined twice", name
);
252 esym
->st_info
= ELFW(ST_INFO
)(sym_bind
, sym_type
);
253 esym
->st_shndx
= sh_num
;
255 esym
->st_value
= value
;
256 esym
->st_size
= size
;
257 esym
->st_other
= other
;
261 sym_index
= put_elf_sym(s
, value
, size
,
262 ELFW(ST_INFO
)(sym_bind
, sym_type
), other
,
269 ST_FUNC
void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
270 int type
, int symbol
)
278 /* if no relocation section, create it */
279 snprintf(buf
, sizeof(buf
), REL_SECTION_FMT
, s
->name
);
280 /* if the symtab is allocated, then we consider the relocation
282 sr
= new_section(tcc_state
, buf
, SHT_RELX
, symtab
->sh_flags
);
283 sr
->sh_entsize
= sizeof(ElfW_Rel
);
285 sr
->sh_info
= s
->sh_num
;
288 rel
= section_ptr_add(sr
, sizeof(ElfW_Rel
));
289 rel
->r_offset
= offset
;
290 rel
->r_info
= ELFW(R_INFO
)(symbol
, type
);
291 #ifdef TCC_TARGET_X86_64
296 /* put stab debug information */
298 ST_FUNC
void put_stabs(const char *str
, int type
, int other
, int desc
,
303 sym
= section_ptr_add(stab_section
, sizeof(Stab_Sym
));
305 sym
->n_strx
= put_elf_str(stabstr_section
, str
);
310 sym
->n_other
= other
;
312 sym
->n_value
= value
;
315 ST_FUNC
void put_stabs_r(const char *str
, int type
, int other
, int desc
,
316 unsigned long value
, Section
*sec
, int sym_index
)
318 put_stabs(str
, type
, other
, desc
, value
);
319 put_elf_reloc(symtab_section
, stab_section
,
320 stab_section
->data_offset
- sizeof(unsigned int),
321 R_DATA_32
, sym_index
);
324 ST_FUNC
void put_stabn(int type
, int other
, int desc
, int value
)
326 put_stabs(NULL
, type
, other
, desc
, value
);
329 ST_FUNC
void put_stabd(int type
, int other
, int desc
)
331 put_stabs(NULL
, type
, other
, desc
, 0);
334 /* Browse each elem of type <type> in section <sec> starting at elem <startoff>
335 using variable <elem> */
336 #define for_each_elem(sec, startoff, elem, type) \
337 for (elem = (type *) sec->data + startoff; \
338 elem < (type *) (sec->data + sec->data_offset); elem++)
340 /* In an ELF file symbol table, the local symbols must appear below
341 the global and weak ones. Since TCC cannot sort it while generating
342 the code, we must do it after. All the relocation tables are also
343 modified to take into account the symbol table sorting */
344 static void sort_syms(TCCState
*s1
, Section
*s
)
346 int *old_to_new_syms
;
354 nb_syms
= s
->data_offset
/ sizeof(ElfW(Sym
));
355 new_syms
= tcc_malloc(nb_syms
* sizeof(ElfW(Sym
)));
356 old_to_new_syms
= tcc_malloc(nb_syms
* sizeof(int));
358 /* first pass for local symbols */
359 p
= (ElfW(Sym
) *)s
->data
;
361 for(i
= 0; i
< nb_syms
; i
++) {
362 if (ELFW(ST_BIND
)(p
->st_info
) == STB_LOCAL
) {
363 old_to_new_syms
[i
] = q
- new_syms
;
368 /* save the number of local symbols in section header */
369 s
->sh_info
= q
- new_syms
;
371 /* then second pass for non local symbols */
372 p
= (ElfW(Sym
) *)s
->data
;
373 for(i
= 0; i
< nb_syms
; i
++) {
374 if (ELFW(ST_BIND
)(p
->st_info
) != STB_LOCAL
) {
375 old_to_new_syms
[i
] = q
- new_syms
;
381 /* we copy the new symbols to the old */
382 memcpy(s
->data
, new_syms
, nb_syms
* sizeof(ElfW(Sym
)));
385 /* now we modify all the relocations */
386 for(i
= 1; i
< s1
->nb_sections
; i
++) {
387 sr
= s1
->sections
[i
];
388 if (sr
->sh_type
== SHT_RELX
&& sr
->link
== s
) {
389 for_each_elem(sr
, 0, rel
, ElfW_Rel
) {
390 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
391 type
= ELFW(R_TYPE
)(rel
->r_info
);
392 sym_index
= old_to_new_syms
[sym_index
];
393 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
398 tcc_free(old_to_new_syms
);
401 /* relocate common symbols in the .bss section */
402 ST_FUNC
void relocate_common_syms(void)
405 unsigned long offset
, align
;
407 for_each_elem(symtab_section
, 1, sym
, ElfW(Sym
)) {
408 if (sym
->st_shndx
== SHN_COMMON
) {
410 align
= sym
->st_value
;
411 offset
= bss_section
->data_offset
;
412 offset
= (offset
+ align
- 1) & -align
;
413 sym
->st_value
= offset
;
414 sym
->st_shndx
= bss_section
->sh_num
;
415 offset
+= sym
->st_size
;
416 bss_section
->data_offset
= offset
;
421 /* relocate symbol table, resolve undefined symbols if do_resolve is
422 true and output error if undefined symbol. */
423 ST_FUNC
void relocate_syms(TCCState
*s1
, int do_resolve
)
425 ElfW(Sym
) *sym
, *esym
;
426 int sym_bind
, sh_num
, sym_index
;
429 for_each_elem(symtab_section
, 1, sym
, ElfW(Sym
)) {
430 sh_num
= sym
->st_shndx
;
431 if (sh_num
== SHN_UNDEF
) {
432 name
= strtab_section
->data
+ sym
->st_name
;
433 /* Use ld.so to resolve symbol for us (for tcc -run) */
435 #if defined TCC_IS_NATIVE && !defined _WIN32
437 name
= symtab_section
->link
->data
+ sym
->st_name
;
438 addr
= resolve_sym(s1
, name
);
440 sym
->st_value
= (addr_t
)addr
;
444 } else if (s1
->dynsym
) {
445 /* if dynamic symbol exist, then use it */
446 sym_index
= find_elf_sym(s1
->dynsym
, name
);
448 esym
= &((ElfW(Sym
) *)s1
->dynsym
->data
)[sym_index
];
449 sym
->st_value
= esym
->st_value
;
453 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
455 if (!strcmp(name
, "_fp_hw"))
457 /* only weak symbols are accepted to be undefined. Their
459 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
460 if (sym_bind
== STB_WEAK
) {
463 tcc_error_noabort("undefined symbol '%s'", name
);
465 } else if (sh_num
< SHN_LORESERVE
) {
466 /* add section base */
467 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
473 #ifdef TCC_HAS_RUNTIME_PLTGOT
474 #ifdef TCC_TARGET_X86_64
475 #define JMP_TABLE_ENTRY_SIZE 14
476 static addr_t
add_jmp_table(TCCState
*s1
, addr_t val
)
478 char *p
= s1
->runtime_plt_and_got
+ s1
->runtime_plt_and_got_offset
;
479 s1
->runtime_plt_and_got_offset
+= JMP_TABLE_ENTRY_SIZE
;
484 *(addr_t
*)(p
+ 6) = val
;
488 static addr_t
add_got_table(TCCState
*s1
, addr_t val
)
490 addr_t
*p
= (addr_t
*)(s1
->runtime_plt_and_got
+ s1
->runtime_plt_and_got_offset
);
491 s1
->runtime_plt_and_got_offset
+= sizeof(addr_t
);
495 #elif defined TCC_TARGET_ARM
496 #define JMP_TABLE_ENTRY_SIZE 8
497 static addr_t
add_jmp_table(TCCState
*s1
, int val
)
499 uint32_t *p
= (uint32_t *)(s1
->runtime_plt_and_got
+ s1
->runtime_plt_and_got_offset
);
500 s1
->runtime_plt_and_got_offset
+= JMP_TABLE_ENTRY_SIZE
;
501 /* ldr pc, [pc, #-4] */
507 #endif /* def TCC_HAS_RUNTIME_PLTGOT */
509 /* relocate a given section (CPU dependent) by applying the relocations
510 in the associated relocation section */
511 ST_FUNC
void relocate_section(TCCState
*s1
, Section
*s
)
519 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
524 for_each_elem(sr
, 0, rel
, ElfW_Rel
) {
525 ptr
= s
->data
+ rel
->r_offset
;
527 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
528 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
530 #ifdef TCC_TARGET_X86_64
531 val
+= rel
->r_addend
;
533 type
= ELFW(R_TYPE
)(rel
->r_info
);
534 addr
= s
->sh_addr
+ rel
->r_offset
;
538 #if defined(TCC_TARGET_I386)
540 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
541 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
542 qrel
->r_offset
= rel
->r_offset
;
544 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_386_32
);
548 qrel
->r_info
= ELFW(R_INFO
)(0, R_386_RELATIVE
);
555 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
557 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
559 qrel
->r_offset
= rel
->r_offset
;
560 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_386_PC32
);
565 *(int *)ptr
+= val
- addr
;
568 *(int *)ptr
+= val
- addr
;
575 *(int *)ptr
+= s1
->got
->sh_addr
- addr
;
578 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
581 /* we load the got offset */
582 *(int *)ptr
+= s1
->sym_attrs
[sym_index
].got_offset
;
585 if (s1
->output_format
!= TCC_OUTPUT_FORMAT_BINARY
) {
587 tcc_error("can only produce 16-bit binary files");
589 *(short *)ptr
+= val
;
592 if (s1
->output_format
!= TCC_OUTPUT_FORMAT_BINARY
)
594 *(short *)ptr
+= val
- addr
;
596 #elif defined(TCC_TARGET_ARM)
602 int x
, is_thumb
, is_call
, h
, blx_avail
, is_bl
, th_ko
;
603 x
= (*(int *) ptr
) & 0xffffff;
604 (*(int *)ptr
) &= 0xff000000;
608 blx_avail
= (TCC_ARM_VERSION
>= 5);
610 is_bl
= (*(unsigned *) ptr
) >> 24 == 0xeb;
611 is_call
= (type
== R_ARM_CALL
|| (type
== R_ARM_PC24
&& is_bl
));
614 th_ko
= (x
& 3) && (!blx_avail
|| !is_call
);
615 #ifdef TCC_HAS_RUNTIME_PLTGOT
616 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
617 if (th_ko
|| x
>= 0x2000000 || x
< -0x2000000) {
618 x
+= add_jmp_table(s1
, val
) - val
; /* add veneer */
619 th_ko
= (x
& 3) && (!blx_avail
|| !is_call
);
620 is_thumb
= 0; /* Veneer uses ARM instructions */
624 if (th_ko
|| x
>= 0x2000000 || x
< -0x2000000)
625 tcc_error("can't relocate value at %x",addr
);
628 /* Only reached if blx is avail and it is a call */
631 (*(int *)ptr
) = 0xfa << 24; /* bl -> blx */
636 /* Since these relocations only concern Thumb-2 and blx instruction was
637 introduced before Thumb-2, we can assume blx is available and not
640 case R_ARM_THM_JUMP24
:
642 int x
, hi
, lo
, s
, j1
, j2
, i1
, i2
, imm10
, imm11
;
643 int to_thumb
, is_call
, to_plt
, blx_bit
= 1 << 12;
647 if (sym
->st_shndx
== SHN_UNDEF
&&
648 ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
651 /* Get initial offset */
652 hi
= (*(uint16_t *)ptr
);
653 lo
= (*(uint16_t *)(ptr
+2));
661 x
= (s
<< 24) | (i1
<< 23) | (i2
<< 22) |
662 (imm10
<< 12) | (imm11
<< 1);
666 /* Relocation infos */
669 to_plt
= (val
>= plt
->sh_addr
) &&
670 (val
< plt
->sh_addr
+ plt
->data_offset
);
671 is_call
= (type
== R_ARM_THM_PC22
);
673 /* Compute final offset */
674 if (to_plt
&& !is_call
) /* Point to 1st instr of Thumb stub */
677 if (!to_thumb
&& is_call
) {
678 blx_bit
= 0; /* bl -> blx */
679 x
= (x
+ 3) & -4; /* Compute offset from aligned PC */
682 /* Check that relocation is possible
683 * offset must not be out of range
684 * if target is to be entered in arm mode:
686 - instruction must be a call (bl) or a jump to PLT */
687 if (!to_thumb
|| x
>= 0x1000000 || x
< -0x1000000)
688 if (to_thumb
|| (val
& 2) || (!is_call
&& !to_plt
))
689 tcc_error("can't relocate value at %x",addr
);
691 /* Compute and store final offset */
697 imm10
= (x
>> 12) & 0x3ff;
698 imm11
= (x
>> 1) & 0x7ff;
699 (*(uint16_t *)ptr
) = (uint16_t) ((hi
& 0xf800) |
701 (*(uint16_t *)(ptr
+2)) = (uint16_t) ((lo
& 0xc000) |
702 (j1
<< 13) | blx_bit
| (j2
<< 11) |
707 case R_ARM_MOVW_ABS_NC
:
710 if (type
== R_ARM_MOVT_ABS
)
713 imm4
= (val
>> 12) & 0xf;
714 x
= (imm4
<< 16) | imm12
;
715 if (type
== R_ARM_THM_MOVT_ABS
)
721 case R_ARM_THM_MOVT_ABS
:
722 case R_ARM_THM_MOVW_ABS_NC
:
724 int x
, i
, imm4
, imm3
, imm8
;
725 if (type
== R_ARM_THM_MOVT_ABS
)
728 imm3
= (val
>> 8) & 0x7;
730 imm4
= (val
>> 12) & 0xf;
731 x
= (imm3
<< 28) | (imm8
<< 16) | (i
<< 10) | imm4
;
732 if (type
== R_ARM_THM_MOVT_ABS
)
741 x
= (*(int *)ptr
) & 0x7fffffff;
742 (*(int *)ptr
) &= 0x80000000;
745 if((x
^(x
>>1))&0x40000000)
746 tcc_error("can't relocate value at %x",addr
);
747 (*(int *)ptr
) |= x
& 0x7fffffff;
753 *(int *)ptr
+= val
- addr
;
756 *(int *)ptr
+= s1
->got
->sh_addr
- addr
;
759 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
762 /* we load the got offset */
763 *(int *)ptr
+= s1
->sym_attrs
[sym_index
].got_offset
;
768 /* trade Thumb support for ARMv4 support */
769 if ((0x0ffffff0 & *(int*)ptr
) == 0x012FFF10)
770 *(int*)ptr
^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
773 fprintf(stderr
,"FIXME: handle reloc type %x at %x [%p] to %x\n",
774 type
, (unsigned)addr
, ptr
, (unsigned)val
);
776 #elif defined(TCC_TARGET_C67)
784 /* put the low 16 bits of the absolute address
785 add to what is already there */
787 orig
= ((*(int *)(ptr
)) >> 7) & 0xffff;
788 orig
|= (((*(int *)(ptr
+4)) >> 7) & 0xffff) << 16;
790 /* patch both at once - assumes always in pairs Low - High */
792 *(int *) ptr
= (*(int *) ptr
& (~(0xffff << 7)) ) | (((val
+orig
) & 0xffff) << 7);
793 *(int *)(ptr
+4) = (*(int *)(ptr
+4) & (~(0xffff << 7)) ) | ((((val
+orig
)>>16) & 0xffff) << 7);
799 fprintf(stderr
,"FIXME: handle reloc type %x at %x [%p] to %x\n",
800 type
, (unsigned)addr
, ptr
, (unsigned)val
);
802 #elif defined(TCC_TARGET_X86_64)
804 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
805 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
806 qrel
->r_addend
= *(long long *)ptr
+ val
;
809 *(long long *)ptr
+= val
;
813 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
814 /* XXX: this logic may depend on TCC's codegen
815 now TCC uses R_X86_64_32 even for a 64bit pointer */
816 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
817 qrel
->r_addend
= *(int *)ptr
+ val
;
824 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
826 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
828 qrel
->r_offset
= rel
->r_offset
;
829 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_X86_64_PC32
);
830 qrel
->r_addend
= *(int *)ptr
;
836 case R_X86_64_PLT32
: {
838 diff
= (long long)val
- addr
;
839 if (diff
<= -2147483647 || diff
> 2147483647) {
840 #ifdef TCC_HAS_RUNTIME_PLTGOT
841 /* XXX: naive support for over 32bit jump */
842 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
843 val
= (add_jmp_table(s1
, val
- rel
->r_addend
) +
848 if (diff
<= -2147483647 || diff
> 2147483647) {
849 tcc_error("internal error: relocation failed");
855 case R_X86_64_GLOB_DAT
:
856 case R_X86_64_JUMP_SLOT
:
857 /* They don't need addend */
858 *(int *)ptr
= val
- rel
->r_addend
;
860 case R_X86_64_GOTPCREL
:
861 #ifdef TCC_HAS_RUNTIME_PLTGOT
862 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
863 val
= add_got_table(s1
, val
- rel
->r_addend
) + rel
->r_addend
;
864 *(int *)ptr
+= val
- addr
;
868 *(int *)ptr
+= (s1
->got
->sh_addr
- addr
+
869 s1
->sym_attrs
[sym_index
].got_offset
- 4);
871 case R_X86_64_GOTTPOFF
:
872 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
875 /* we load the got offset */
876 *(int *)ptr
+= s1
->sym_attrs
[sym_index
].got_offset
;
879 #error unsupported processor
883 /* if the relocation is allocated, we change its symbol table */
884 if (sr
->sh_flags
& SHF_ALLOC
)
885 sr
->link
= s1
->dynsym
;
888 /* relocate relocation table in 'sr' */
889 static void relocate_rel(TCCState
*s1
, Section
*sr
)
894 s
= s1
->sections
[sr
->sh_info
];
895 for_each_elem(sr
, 0, rel
, ElfW_Rel
)
896 rel
->r_offset
+= s
->sh_addr
;
899 /* count the number of dynamic relocations so that we can reserve
901 static int prepare_dynamic_rel(TCCState
*s1
, Section
*sr
)
904 int sym_index
, esym_index
, type
, count
;
907 for_each_elem(sr
, 0, rel
, ElfW_Rel
) {
908 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
909 type
= ELFW(R_TYPE
)(rel
->r_info
);
911 #if defined(TCC_TARGET_I386)
913 #elif defined(TCC_TARGET_X86_64)
920 #if defined(TCC_TARGET_I386)
922 #elif defined(TCC_TARGET_X86_64)
925 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
934 /* allocate the section */
935 sr
->sh_flags
|= SHF_ALLOC
;
936 sr
->sh_size
= count
* sizeof(ElfW_Rel
);
941 static struct sym_attr
*alloc_sym_attr(TCCState
*s1
, int index
)
944 struct sym_attr
*tab
;
946 if (index
>= s1
->nb_sym_attrs
) {
947 /* find immediately bigger power of 2 and reallocate array */
951 tab
= tcc_realloc(s1
->sym_attrs
, n
* sizeof(*s1
->sym_attrs
));
953 memset(s1
->sym_attrs
+ s1
->nb_sym_attrs
, 0,
954 (n
- s1
->nb_sym_attrs
) * sizeof(*s1
->sym_attrs
));
955 s1
->nb_sym_attrs
= n
;
957 return &s1
->sym_attrs
[index
];
960 /* XXX: suppress that */
961 static void put32(unsigned char *p
, uint32_t val
)
969 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
970 defined(TCC_TARGET_X86_64)
971 static uint32_t get32(unsigned char *p
)
973 return p
[0] | (p
[1] << 8) | (p
[2] << 16) | (p
[3] << 24);
977 static void build_got(TCCState
*s1
)
981 /* if no got, then create it */
982 s1
->got
= new_section(s1
, ".got", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
983 s1
->got
->sh_entsize
= 4;
984 add_elf_sym(symtab_section
, 0, 4, ELFW(ST_INFO
)(STB_GLOBAL
, STT_OBJECT
),
985 0, s1
->got
->sh_num
, "_GLOBAL_OFFSET_TABLE_");
986 ptr
= section_ptr_add(s1
->got
, 3 * PTR_SIZE
);
988 /* keep space for _DYNAMIC pointer, if present */
990 /* two dummy got entries */
994 /* keep space for _DYNAMIC pointer, if present */
997 /* two dummy got entries */
1005 /* put a got entry corresponding to a symbol in symtab_section. 'size'
1006 and 'info' can be modifed if more precise info comes from the DLL */
1007 static void put_got_entry(TCCState
*s1
,
1008 int reloc_type
, unsigned long size
, int info
,
1014 unsigned long offset
;
1020 /* if a got entry already exists for that symbol, no need to add one */
1021 if (sym_index
< s1
->nb_sym_attrs
&&
1022 s1
->sym_attrs
[sym_index
].got_offset
)
1025 alloc_sym_attr(s1
, sym_index
)->got_offset
= s1
->got
->data_offset
;
1028 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1029 name
= symtab_section
->link
->data
+ sym
->st_name
;
1030 offset
= sym
->st_value
;
1031 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1033 #ifdef TCC_TARGET_X86_64
1043 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1046 /* if we build a DLL, we add a %ebx offset */
1047 if (s1
->output_type
== TCC_OUTPUT_DLL
)
1053 /* add a PLT entry */
1055 if (plt
->data_offset
== 0) {
1056 /* first plt entry */
1057 p
= section_ptr_add(plt
, 16);
1058 p
[0] = 0xff; /* pushl got + PTR_SIZE */
1059 p
[1] = modrm
+ 0x10;
1060 put32(p
+ 2, PTR_SIZE
);
1061 p
[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1063 put32(p
+ 8, PTR_SIZE
* 2);
1066 p
= section_ptr_add(plt
, 16);
1067 p
[0] = 0xff; /* jmp *(got + x) */
1069 put32(p
+ 2, s1
->got
->data_offset
);
1070 p
[6] = 0x68; /* push $xxx */
1071 put32(p
+ 7, (plt
->data_offset
- 32) >> 1);
1072 p
[11] = 0xe9; /* jmp plt_start */
1073 put32(p
+ 12, -(plt
->data_offset
));
1075 /* the symbol is modified so that it will be relocated to
1077 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
1078 if (s1
->output_type
== TCC_OUTPUT_EXE
)
1080 offset
= plt
->data_offset
- 16;
1082 #elif defined(TCC_TARGET_ARM)
1083 if (reloc_type
== R_ARM_JUMP_SLOT
) {
1087 /* if we build a DLL, we add a %ebx offset */
1088 if (s1
->output_type
== TCC_OUTPUT_DLL
)
1089 tcc_error("DLLs unimplemented!");
1091 /* add a PLT entry */
1093 if (plt
->data_offset
== 0) {
1094 /* first plt entry */
1095 p
= section_ptr_add(plt
, 16);
1096 put32(p
, 0xe52de004); /* push {lr} */
1097 put32(p
+4, 0xe59fe010); /* ldr lr, [pc, #16] */
1098 put32(p
+8, 0xe08fe00e); /* add lr, pc, lr */
1099 put32(p
+12, 0xe5bef008); /* ldr pc, [lr, #8]! */
1102 if (s1
->sym_attrs
[sym_index
].plt_thumb_stub
) {
1103 p
= section_ptr_add(plt
, 20);
1104 put32(p
, 0x4778); /* bx pc */
1105 put32(p
+2, 0x46c0); /* nop */
1108 p
= section_ptr_add(plt
, 16);
1109 put32(p
, 0xe59fc004); /* ldr ip, [pc, #4] ; GOT entry offset */
1110 put32(p
+4, 0xe08fc00c); /* add ip, pc, ip ; addr of GOT entry */
1111 put32(p
+8, 0xe59cf000); /* ldr pc, [ip] ; jump to GOT entry */
1112 put32(p
+12, s1
->got
->data_offset
); /* GOT entry off once patched */
1114 /* the symbol is modified so that it will be relocated to
1116 if (s1
->output_type
== TCC_OUTPUT_EXE
)
1117 offset
= plt
->data_offset
- 16;
1119 #elif defined(TCC_TARGET_C67)
1120 tcc_error("C67 got not implemented");
1122 #error unsupported CPU
1124 index
= put_elf_sym(s1
->dynsym
, offset
,
1125 size
, info
, 0, sym
->st_shndx
, name
);
1126 /* put a got entry */
1127 put_elf_reloc(s1
->dynsym
, s1
->got
,
1128 s1
->got
->data_offset
,
1131 ptr
= section_ptr_add(s1
->got
, PTR_SIZE
);
1135 /* build GOT and PLT entries */
1136 ST_FUNC
void build_got_entries(TCCState
*s1
)
1141 int i
, type
, reloc_type
, sym_index
;
1143 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1144 s
= s1
->sections
[i
];
1145 if (s
->sh_type
!= SHT_RELX
)
1147 /* no need to handle got relocations */
1148 if (s
->link
!= symtab_section
)
1150 for_each_elem(s
, 0, rel
, ElfW_Rel
) {
1151 type
= ELFW(R_TYPE
)(rel
->r_info
);
1153 #if defined(TCC_TARGET_I386)
1160 if (type
== R_386_GOT32
|| type
== R_386_PLT32
) {
1161 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1162 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1163 /* look at the symbol got offset. If none, then add one */
1164 if (type
== R_386_GOT32
)
1165 reloc_type
= R_386_GLOB_DAT
;
1167 reloc_type
= R_386_JMP_SLOT
;
1168 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1172 #elif defined(TCC_TARGET_ARM)
1179 if (type
== R_ARM_GOT32
|| type
== R_ARM_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_ARM_GOT32
)
1184 reloc_type
= R_ARM_GLOB_DAT
;
1186 reloc_type
= R_ARM_JUMP_SLOT
;
1187 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1191 #elif defined(TCC_TARGET_C67)
1198 if (type
== R_C60_GOT32
|| type
== R_C60_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_C60_GOT32
)
1203 reloc_type
= R_C60_GLOB_DAT
;
1205 reloc_type
= R_C60_JMP_SLOT
;
1206 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1210 #elif defined(TCC_TARGET_X86_64)
1211 case R_X86_64_GOT32
:
1212 case R_X86_64_GOTTPOFF
:
1213 case R_X86_64_GOTPCREL
:
1214 case R_X86_64_PLT32
:
1217 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
||
1218 type
== R_X86_64_PLT32
) {
1219 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1220 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1221 /* look at the symbol got offset. If none, then add one */
1222 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
)
1223 reloc_type
= R_X86_64_GLOB_DAT
;
1225 reloc_type
= R_X86_64_JUMP_SLOT
;
1226 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1231 #error unsupported CPU
1240 ST_FUNC Section
*new_symtab(TCCState
*s1
,
1241 const char *symtab_name
, int sh_type
, int sh_flags
,
1242 const char *strtab_name
,
1243 const char *hash_name
, int hash_sh_flags
)
1245 Section
*symtab
, *strtab
, *hash
;
1246 int *ptr
, nb_buckets
;
1248 symtab
= new_section(s1
, symtab_name
, sh_type
, sh_flags
);
1249 symtab
->sh_entsize
= sizeof(ElfW(Sym
));
1250 strtab
= new_section(s1
, strtab_name
, SHT_STRTAB
, sh_flags
);
1251 put_elf_str(strtab
, "");
1252 symtab
->link
= strtab
;
1253 put_elf_sym(symtab
, 0, 0, 0, 0, 0, NULL
);
1257 hash
= new_section(s1
, hash_name
, SHT_HASH
, hash_sh_flags
);
1258 hash
->sh_entsize
= sizeof(int);
1259 symtab
->hash
= hash
;
1260 hash
->link
= symtab
;
1262 ptr
= section_ptr_add(hash
, (2 + nb_buckets
+ 1) * sizeof(int));
1263 ptr
[0] = nb_buckets
;
1265 memset(ptr
+ 2, 0, (nb_buckets
+ 1) * sizeof(int));
1269 /* put dynamic tag */
1270 static void put_dt(Section
*dynamic
, int dt
, addr_t val
)
1273 dyn
= section_ptr_add(dynamic
, sizeof(ElfW(Dyn
)));
1275 dyn
->d_un
.d_val
= val
;
1278 static void add_init_array_defines(TCCState
*s1
, const char *section_name
)
1282 char sym_start
[1024];
1285 snprintf(sym_start
, sizeof(sym_start
), "__%s_start", section_name
+ 1);
1286 snprintf(sym_end
, sizeof(sym_end
), "__%s_end", section_name
+ 1);
1288 s
= find_section(s1
, section_name
);
1293 end_offset
= s
->data_offset
;
1296 add_elf_sym(symtab_section
,
1298 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1299 s
->sh_num
, sym_start
);
1300 add_elf_sym(symtab_section
,
1302 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1303 s
->sh_num
, sym_end
);
1306 ST_FUNC
void tcc_add_bcheck(TCCState
*s1
)
1308 #ifdef CONFIG_TCC_BCHECK
1310 Section
*init_section
;
1311 unsigned char *pinit
;
1314 if (0 == s1
->do_bounds_check
)
1317 /* XXX: add an object file to do that */
1318 ptr
= section_ptr_add(bounds_section
, sizeof(unsigned long));
1320 add_elf_sym(symtab_section
, 0, 0,
1321 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1322 bounds_section
->sh_num
, "__bounds_start");
1323 #ifdef TCC_TARGET_I386
1324 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
) {
1325 /* add 'call __bound_init()' in .init section */
1326 init_section
= find_section(s1
, ".init");
1327 pinit
= section_ptr_add(init_section
, 5);
1329 put32(pinit
+ 1, -4);
1330 sym_index
= find_elf_sym(symtab_section
, "__bound_init");
1331 put_elf_reloc(symtab_section
, init_section
,
1332 init_section
->data_offset
- 4, R_386_PC32
, sym_index
);
1338 static inline int tcc_add_support(TCCState
*s1
, const char *filename
)
1341 snprintf(buf
, sizeof(buf
), "%s/%s", s1
->tcc_lib_path
, filename
);
1342 return tcc_add_file(s1
, buf
);
1345 /* add tcc runtime libraries */
1346 ST_FUNC
void tcc_add_runtime(TCCState
*s1
)
1351 if (!s1
->nostdlib
) {
1352 tcc_add_library(s1
, "c");
1353 #ifdef CONFIG_USE_LIBGCC
1354 if (!s1
->static_link
)
1355 tcc_add_file(s1
, TCC_LIBGCC
);
1357 tcc_add_support(s1
, "libtcc1.a");
1359 tcc_add_support(s1
, "libtcc1.a");
1361 /* add crt end if not memory output */
1362 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
)
1363 tcc_add_crt(s1
, "crtn.o");
1367 /* add various standard linker symbols (must be done after the
1368 sections are filled (for example after allocating common
1370 ST_FUNC
void tcc_add_linker_symbols(TCCState
*s1
)
1376 add_elf_sym(symtab_section
,
1377 text_section
->data_offset
, 0,
1378 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1379 text_section
->sh_num
, "_etext");
1380 add_elf_sym(symtab_section
,
1381 data_section
->data_offset
, 0,
1382 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1383 data_section
->sh_num
, "_edata");
1384 add_elf_sym(symtab_section
,
1385 bss_section
->data_offset
, 0,
1386 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1387 bss_section
->sh_num
, "_end");
1388 /* horrible new standard ldscript defines */
1389 add_init_array_defines(s1
, ".preinit_array");
1390 add_init_array_defines(s1
, ".init_array");
1391 add_init_array_defines(s1
, ".fini_array");
1393 /* add start and stop symbols for sections whose name can be
1395 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1396 s
= s1
->sections
[i
];
1397 if (s
->sh_type
== SHT_PROGBITS
&&
1398 (s
->sh_flags
& SHF_ALLOC
)) {
1402 /* check if section name can be expressed in C */
1408 if (!isid(ch
) && !isnum(ch
))
1412 snprintf(buf
, sizeof(buf
), "__start_%s", s
->name
);
1413 add_elf_sym(symtab_section
,
1415 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1417 snprintf(buf
, sizeof(buf
), "__stop_%s", s
->name
);
1418 add_elf_sym(symtab_section
,
1420 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1427 static void tcc_output_binary(TCCState
*s1
, FILE *f
,
1428 const int *sec_order
)
1431 int i
, offset
, size
;
1434 for(i
=1;i
<s1
->nb_sections
;i
++) {
1435 s
= s1
->sections
[sec_order
[i
]];
1436 if (s
->sh_type
!= SHT_NOBITS
&&
1437 (s
->sh_flags
& SHF_ALLOC
)) {
1438 while (offset
< s
->sh_offset
) {
1443 fwrite(s
->data
, 1, size
, f
);
1449 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1451 #define EXTRA_RELITEMS 14
1453 /* move the relocation value from .dynsym to .got */
1454 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1456 uint32_t *gotd
= (void *)s1
->got
->data
;
1459 gotd
+= 3; /* dummy entries in .got */
1460 /* relocate symbols in .dynsym */
1461 for_each_elem(s
, 1, sym
, ElfW(Sym
)) {
1462 if (sym
->st_shndx
== SHN_UNDEF
) {
1463 *gotd
++ = sym
->st_value
+ 6; /* XXX 6 is magic ? */
1470 #define EXTRA_RELITEMS 9
1472 /* zero plt offsets of weak symbols in .dynsym */
1473 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1477 for_each_elem(s
, 1, sym
, ElfW(Sym
))
1478 if (sym
->st_shndx
== SHN_UNDEF
&& ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
1483 ST_FUNC
void fill_got_entry(TCCState
*s1
, ElfW_Rel
*rel
)
1485 int sym_index
= ELFW(R_SYM
) (rel
->r_info
);
1486 ElfW(Sym
) *sym
= &((ElfW(Sym
) *) symtab_section
->data
)[sym_index
];
1487 unsigned long offset
;
1489 if (sym_index
>= s1
->nb_sym_attrs
)
1491 offset
= s1
->sym_attrs
[sym_index
].got_offset
;
1492 section_reserve(s1
->got
, offset
+ PTR_SIZE
);
1493 #ifdef TCC_TARGET_X86_64
1494 /* only works for x86-64 */
1495 put32(s1
->got
->data
+ offset
+ 4, sym
->st_value
>> 32);
1497 put32(s1
->got
->data
+ offset
, sym
->st_value
& 0xffffffff);
1500 /* Perform relocation to GOT or PLTÂ entries */
1501 ST_FUNC
void fill_got(TCCState
*s1
)
1507 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1508 s
= s1
->sections
[i
];
1509 if (s
->sh_type
!= SHT_RELX
)
1511 /* no need to handle got relocations */
1512 if (s
->link
!= symtab_section
)
1514 for_each_elem(s
, 0, rel
, ElfW_Rel
) {
1515 switch (ELFW(R_TYPE
) (rel
->r_info
)) {
1516 #ifdef TCC_TARGET_X86_64
1517 case R_X86_64_GOT32
:
1518 case R_X86_64_GOTPCREL
:
1519 case R_X86_64_PLT32
:
1520 fill_got_entry(s1
, rel
);
1528 /* Bind symbols of executable: resolve undefined symbols from exported symbols
1529 in shared libraries and export non local defined symbols to shared libraries
1530 if -rdynamic switch was given on command line */
1531 static void bind_exe_dynsyms(TCCState
*s1
)
1534 int sym_index
, index
;
1535 ElfW(Sym
) *sym
, *esym
;
1538 /* Resolve undefined symbols from dynamic symbols. When there is a match:
1539 - if STT_FUNC or STT_GNU_IFUNC symbol -> add it in PLT
1540 - if STT_OBJECT symbol -> add it in .bss section with suitable reloc */
1541 for_each_elem(symtab_section
, 1, sym
, ElfW(Sym
)) {
1542 if (sym
->st_shndx
== SHN_UNDEF
) {
1543 name
= symtab_section
->link
->data
+ sym
->st_name
;
1544 sym_index
= find_elf_sym(s1
->dynsymtab_section
, name
);
1546 esym
= &((ElfW(Sym
) *)s1
->dynsymtab_section
->data
)[sym_index
];
1547 type
= ELFW(ST_TYPE
)(esym
->st_info
);
1548 if ((type
== STT_FUNC
) || (type
== STT_GNU_IFUNC
)) {
1549 /* Indirect functions shall have STT_FUNC type in executable
1550 * dynsym section. Indeed, a dlsym call following a lazy
1551 * resolution would pick the symbol value from the
1552 * executable dynsym entry which would contain the address
1553 * of the function wanted by the caller of dlsym instead of
1554 * the address of the function that would return that
1556 put_got_entry(s1
, R_JMP_SLOT
, esym
->st_size
,
1557 ELFW(ST_INFO
)(STB_GLOBAL
,STT_FUNC
),
1558 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1559 } else if (type
== STT_OBJECT
) {
1560 unsigned long offset
;
1562 offset
= bss_section
->data_offset
;
1563 /* XXX: which alignment ? */
1564 offset
= (offset
+ 16 - 1) & -16;
1565 index
= put_elf_sym(s1
->dynsym
, offset
, esym
->st_size
,
1566 esym
->st_info
, 0, bss_section
->sh_num
,
1568 /* Ensure R_COPY works for weak symbol aliases */
1569 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1570 for_each_elem(s1
->dynsymtab_section
, 1, dynsym
, ElfW(Sym
)) {
1571 if ((dynsym
->st_value
== esym
->st_value
)
1572 && (ELFW(ST_BIND
)(dynsym
->st_info
) == STB_GLOBAL
)) {
1573 char *dynname
= s1
->dynsymtab_section
->link
->data
1575 put_elf_sym(s1
->dynsym
, offset
, dynsym
->st_size
,
1577 bss_section
->sh_num
, dynname
);
1582 put_elf_reloc(s1
->dynsym
, bss_section
,
1583 offset
, R_COPY
, index
);
1584 offset
+= esym
->st_size
;
1585 bss_section
->data_offset
= offset
;
1588 /* STB_WEAK undefined symbols are accepted */
1589 /* XXX: _fp_hw seems to be part of the ABI, so we ignore it */
1590 if (ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
||
1591 !strcmp(name
, "_fp_hw")) {
1593 tcc_error_noabort("undefined symbol '%s'", name
);
1596 } else if (s1
->rdynamic
&& ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1597 /* if -rdynamic option, then export all non local symbols */
1598 name
= symtab_section
->link
->data
+ sym
->st_name
;
1599 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
, sym
->st_info
,
1600 0, sym
->st_shndx
, name
);
1605 /* Bind symbols of libraries: export non local symbols of executable that
1606 resolve undefined symbols of shared libraries */
1607 static void bind_libs_dynsyms(TCCState
*s1
)
1611 ElfW(Sym
) *sym
, *esym
;
1613 /* now look at unresolved dynamic symbols and export
1614 corresponding symbol */
1615 for_each_elem(s1
->dynsymtab_section
, 1, esym
, ElfW(Sym
)) {
1616 if (esym
->st_shndx
== SHN_UNDEF
) {
1617 name
= s1
->dynsymtab_section
->link
->data
+ esym
->st_name
;
1618 sym_index
= find_elf_sym(symtab_section
, name
);
1620 /* XXX: avoid adding a symbol if already present because of
1622 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1623 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1624 sym
->st_info
, 0, sym
->st_shndx
, name
);
1626 /* weak symbols can stay undefined */
1627 if (ELFW(ST_BIND
)(esym
->st_info
) != STB_WEAK
)
1628 tcc_warning("undefined dynamic symbol '%s'", name
);
1634 /* Export all non local symbols (for shared libraries) */
1635 static void export_global_syms(TCCState
*s1
)
1637 int nb_syms
, dynindex
, index
;
1641 nb_syms
= symtab_section
->data_offset
/ sizeof(ElfW(Sym
));
1642 s1
->symtab_to_dynsym
= tcc_mallocz(sizeof(int) * nb_syms
);
1643 for_each_elem(symtab_section
, 1, sym
, ElfW(Sym
)) {
1644 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1645 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1646 int type
= ELFW(ST_TYPE
)(sym
->st_info
);
1647 if ((type
== STT_FUNC
|| type
== STT_GNU_IFUNC
)
1648 && sym
->st_shndx
== SHN_UNDEF
) {
1649 int visibility
= ELFW(ST_BIND
)(sym
->st_info
);
1650 put_got_entry(s1
, R_JMP_SLOT
, sym
->st_size
,
1651 ELFW(ST_INFO
)(visibility
, STT_FUNC
),
1652 sym
- (ElfW(Sym
) *) symtab_section
->data
);
1653 } else if (type
== STT_OBJECT
) {
1654 put_got_entry(s1
, R_X86_64_GLOB_DAT
, sym
->st_size
, sym
->st_info
,
1655 sym
- (ElfW(Sym
) *) symtab_section
->data
);
1659 name
= symtab_section
->link
->data
+ sym
->st_name
;
1660 dynindex
= put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1661 sym
->st_info
, 0, sym
->st_shndx
, name
);
1662 index
= sym
- (ElfW(Sym
) *) symtab_section
->data
;
1663 s1
->symtab_to_dynsym
[index
] = dynindex
;
1669 /* relocate the PLT: compute addresses and offsets in the PLT now that final
1670 address for PLT and GOT are known (see fill_program_header) */
1671 static void relocate_plt(TCCState
*s1
)
1676 p_end
= p
+ s1
->plt
->data_offset
;
1678 #if defined(TCC_TARGET_I386)
1679 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
1680 put32(p
+ 8, get32(p
+ 8) + s1
->got
->sh_addr
);
1683 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
1686 #elif defined(TCC_TARGET_X86_64)
1687 int x
= s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 6;
1688 put32(p
+ 2, get32(p
+ 2) + x
);
1689 put32(p
+ 8, get32(p
+ 8) + x
- 6);
1692 put32(p
+ 2, get32(p
+ 2) + x
+ s1
->plt
->data
- p
);
1695 #elif defined(TCC_TARGET_ARM)
1697 x
=s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 12;
1700 if (get32(p
) == 0x46c04778) /* PLT Thumb stub present */
1702 put32(p
+ 12, x
+ get32(p
+ 12) + s1
->plt
->data
- p
);
1705 #elif defined(TCC_TARGET_C67)
1708 #error unsupported CPU
1713 /* Allocate strings for section names and decide if an unallocated section
1716 NOTE: the strsec section comes last, so its size is also correct ! */
1717 static void alloc_sec_names(TCCState
*s1
, int file_type
, Section
*strsec
)
1722 /* Allocate strings for section names */
1723 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1724 s
= s1
->sections
[i
];
1725 s
->sh_name
= put_elf_str(strsec
, s
->name
);
1726 /* when generating a DLL, we include relocations but we may
1728 if (file_type
== TCC_OUTPUT_DLL
&&
1729 s
->sh_type
== SHT_RELX
&&
1730 !(s
->sh_flags
& SHF_ALLOC
)) {
1731 /* gr: avoid bogus relocs for empty (debug) sections */
1732 if (s1
->sections
[s
->sh_info
]->sh_flags
& SHF_ALLOC
)
1733 prepare_dynamic_rel(s1
, s
);
1734 else if (s1
->do_debug
)
1735 s
->sh_size
= s
->data_offset
;
1736 } else if (s1
->do_debug
||
1737 file_type
== TCC_OUTPUT_OBJ
||
1738 (s
->sh_flags
& SHF_ALLOC
) ||
1739 i
== (s1
->nb_sections
- 1)) {
1740 /* we output all sections if debug or object file */
1741 s
->sh_size
= s
->data_offset
;
1746 /* Info to be copied in dynamic section */
1750 unsigned long dyn_rel_off
;
1753 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1759 /* Assign sections to segments and decide how are sections laid out when loaded
1760 in memory. This function also fills corresponding program headers. */
1761 static int layout_sections(TCCState
*s1
, ElfW(Phdr
) *phdr
, int phnum
,
1762 Section
*interp
, struct dyn_inf
*dyninf
,
1765 int i
, j
, k
, file_type
, sh_order_index
, file_offset
;
1771 file_type
= s1
->output_type
;
1773 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
)
1774 file_offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
1779 if (s1
->has_text_addr
) {
1780 int a_offset
, p_offset
;
1781 addr
= s1
->text_addr
;
1782 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1784 a_offset
= (int) (addr
& (s1
->section_align
- 1));
1785 p_offset
= file_offset
& (s1
->section_align
- 1);
1786 if (a_offset
< p_offset
)
1787 a_offset
+= s1
->section_align
;
1788 file_offset
+= (a_offset
- p_offset
);
1790 if (file_type
== TCC_OUTPUT_DLL
)
1793 addr
= ELF_START_ADDR
;
1794 /* compute address after headers */
1795 addr
+= (file_offset
& (s1
->section_align
- 1));
1799 /* Leave one program headers for the program interpreter and one for
1800 the program header table itself if needed. These are done later as
1801 they require section layout to be done first. */
1803 ph
+= 1 + HAVE_PHDR
;
1805 /* dynamic relocation table information, for .dynamic section */
1806 dyninf
->rel_addr
= dyninf
->rel_size
= 0;
1807 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1808 dyninf
->bss_addr
= dyninf
->bss_size
= 0;
1811 for(j
= 0; j
< 2; j
++) {
1812 ph
->p_type
= PT_LOAD
;
1814 ph
->p_flags
= PF_R
| PF_X
;
1816 ph
->p_flags
= PF_R
| PF_W
;
1817 ph
->p_align
= s1
->section_align
;
1819 /* Decide the layout of sections loaded in memory. This must
1820 be done before program headers are filled since they contain
1821 info about the layout. We do the following ordering: interp,
1822 symbol tables, relocations, progbits, nobits */
1823 /* XXX: do faster and simpler sorting */
1824 for(k
= 0; k
< 5; k
++) {
1825 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1826 s
= s1
->sections
[i
];
1827 /* compute if section should be included */
1829 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1833 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1834 (SHF_ALLOC
| SHF_WRITE
))
1840 } else if (s
->sh_type
== SHT_DYNSYM
||
1841 s
->sh_type
== SHT_STRTAB
||
1842 s
->sh_type
== SHT_HASH
) {
1845 } else if (s
->sh_type
== SHT_RELX
) {
1848 } else if (s
->sh_type
== SHT_NOBITS
) {
1855 sec_order
[sh_order_index
++] = i
;
1857 /* section matches: we align it and add its size */
1859 addr
= (addr
+ s
->sh_addralign
- 1) &
1860 ~(s
->sh_addralign
- 1);
1861 file_offset
+= (int) ( addr
- tmp
);
1862 s
->sh_offset
= file_offset
;
1865 /* update program header infos */
1866 if (ph
->p_offset
== 0) {
1867 ph
->p_offset
= file_offset
;
1869 ph
->p_paddr
= ph
->p_vaddr
;
1871 /* update dynamic relocation infos */
1872 if (s
->sh_type
== SHT_RELX
) {
1873 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1874 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.got")) {
1875 dyninf
->rel_addr
= addr
;
1876 dyninf
->rel_size
+= s
->sh_size
; /* XXX only first rel. */
1878 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.bss")) {
1879 dyninf
->bss_addr
= addr
;
1880 dyninf
->bss_size
= s
->sh_size
; /* XXX only first rel. */
1883 if (dyninf
->rel_size
== 0)
1884 dyninf
->rel_addr
= addr
;
1885 dyninf
->rel_size
+= s
->sh_size
;
1889 if (s
->sh_type
!= SHT_NOBITS
)
1890 file_offset
+= s
->sh_size
;
1893 ph
->p_filesz
= file_offset
- ph
->p_offset
;
1894 ph
->p_memsz
= addr
- ph
->p_vaddr
;
1897 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1898 /* if in the middle of a page, we duplicate the page in
1899 memory so that one copy is RX and the other is RW */
1900 if ((addr
& (s1
->section_align
- 1)) != 0)
1901 addr
+= s1
->section_align
;
1903 addr
= (addr
+ s1
->section_align
- 1) & ~(s1
->section_align
- 1);
1904 file_offset
= (file_offset
+ s1
->section_align
- 1) &
1905 ~(s1
->section_align
- 1);
1911 /* all other sections come after */
1912 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1913 s
= s1
->sections
[i
];
1914 if (phnum
> 0 && (s
->sh_flags
& SHF_ALLOC
))
1916 sec_order
[sh_order_index
++] = i
;
1918 file_offset
= (file_offset
+ s
->sh_addralign
- 1) &
1919 ~(s
->sh_addralign
- 1);
1920 s
->sh_offset
= file_offset
;
1921 if (s
->sh_type
!= SHT_NOBITS
)
1922 file_offset
+= s
->sh_size
;
1928 static void fill_unloadable_phdr(ElfW(Phdr
) *phdr
, int phnum
, Section
*interp
,
1933 /* if interpreter, then add corresponding program header */
1939 int len
= phnum
* sizeof(ElfW(Phdr
));
1941 ph
->p_type
= PT_PHDR
;
1942 ph
->p_offset
= sizeof(ElfW(Ehdr
));
1943 ph
->p_vaddr
= interp
->sh_addr
- len
;
1944 ph
->p_paddr
= ph
->p_vaddr
;
1945 ph
->p_filesz
= ph
->p_memsz
= len
;
1946 ph
->p_flags
= PF_R
| PF_X
;
1947 ph
->p_align
= 4; /* interp->sh_addralign; */
1951 ph
->p_type
= PT_INTERP
;
1952 ph
->p_offset
= interp
->sh_offset
;
1953 ph
->p_vaddr
= interp
->sh_addr
;
1954 ph
->p_paddr
= ph
->p_vaddr
;
1955 ph
->p_filesz
= interp
->sh_size
;
1956 ph
->p_memsz
= interp
->sh_size
;
1958 ph
->p_align
= interp
->sh_addralign
;
1961 /* if dynamic section, then add corresponding program header */
1963 ph
= &phdr
[phnum
- 1];
1965 ph
->p_type
= PT_DYNAMIC
;
1966 ph
->p_offset
= dynamic
->sh_offset
;
1967 ph
->p_vaddr
= dynamic
->sh_addr
;
1968 ph
->p_paddr
= ph
->p_vaddr
;
1969 ph
->p_filesz
= dynamic
->sh_size
;
1970 ph
->p_memsz
= dynamic
->sh_size
;
1971 ph
->p_flags
= PF_R
| PF_W
;
1972 ph
->p_align
= dynamic
->sh_addralign
;
1976 /* Fill the dynamic section with tags describing the address and size of
1978 static void fill_dynamic(TCCState
*s1
, struct dyn_inf
*dyninf
)
1982 dynamic
= dyninf
->dynamic
;
1984 /* put dynamic section entries */
1985 dynamic
->data_offset
= dyninf
->dyn_rel_off
;
1986 put_dt(dynamic
, DT_HASH
, s1
->dynsym
->hash
->sh_addr
);
1987 put_dt(dynamic
, DT_STRTAB
, dyninf
->dynstr
->sh_addr
);
1988 put_dt(dynamic
, DT_SYMTAB
, s1
->dynsym
->sh_addr
);
1989 put_dt(dynamic
, DT_STRSZ
, dyninf
->dynstr
->data_offset
);
1990 put_dt(dynamic
, DT_SYMENT
, sizeof(ElfW(Sym
)));
1991 #ifdef TCC_TARGET_X86_64
1992 put_dt(dynamic
, DT_RELA
, dyninf
->rel_addr
);
1993 put_dt(dynamic
, DT_RELASZ
, dyninf
->rel_size
);
1994 put_dt(dynamic
, DT_RELAENT
, sizeof(ElfW_Rel
));
1996 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1997 put_dt(dynamic
, DT_PLTGOT
, s1
->got
->sh_addr
);
1998 put_dt(dynamic
, DT_PLTRELSZ
, dyninf
->rel_size
);
1999 put_dt(dynamic
, DT_JMPREL
, dyninf
->rel_addr
);
2000 put_dt(dynamic
, DT_PLTREL
, DT_REL
);
2001 put_dt(dynamic
, DT_REL
, dyninf
->bss_addr
);
2002 put_dt(dynamic
, DT_RELSZ
, dyninf
->bss_size
);
2004 put_dt(dynamic
, DT_REL
, dyninf
->rel_addr
);
2005 put_dt(dynamic
, DT_RELSZ
, dyninf
->rel_size
);
2006 put_dt(dynamic
, DT_RELENT
, sizeof(ElfW_Rel
));
2010 put_dt(dynamic
, DT_DEBUG
, 0);
2011 put_dt(dynamic
, DT_NULL
, 0);
2014 /* Relocate remaining sections and symbols (that is those not related to
2016 static int final_sections_reloc(TCCState
*s1
)
2021 relocate_syms(s1
, 0);
2023 if (s1
->nb_errors
!= 0)
2026 /* relocate sections */
2027 /* XXX: ignore sections with allocated relocations ? */
2028 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2029 s
= s1
->sections
[i
];
2030 if (s
->reloc
&& s
!= s1
->got
)
2031 relocate_section(s1
, s
);
2034 /* relocate relocation entries if the relocation tables are
2035 allocated in the executable */
2036 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2037 s
= s1
->sections
[i
];
2038 if ((s
->sh_flags
& SHF_ALLOC
) &&
2039 s
->sh_type
== SHT_RELX
) {
2040 relocate_rel(s1
, s
);
2046 /* Create an ELF file on disk.
2047 This function handle ELF specific layout requirements */
2048 static void tcc_output_elf(TCCState
*s1
, FILE *f
, int phnum
, ElfW(Phdr
) *phdr
,
2049 int file_offset
, int *sec_order
)
2051 int i
, shnum
, offset
, size
, file_type
;
2054 ElfW(Shdr
) shdr
, *sh
;
2056 file_type
= s1
->output_type
;
2057 shnum
= s1
->nb_sections
;
2059 memset(&ehdr
, 0, sizeof(ehdr
));
2062 ehdr
.e_phentsize
= sizeof(ElfW(Phdr
));
2063 ehdr
.e_phnum
= phnum
;
2064 ehdr
.e_phoff
= sizeof(ElfW(Ehdr
));
2068 file_offset
= (file_offset
+ 3) & -4;
2071 ehdr
.e_ident
[0] = ELFMAG0
;
2072 ehdr
.e_ident
[1] = ELFMAG1
;
2073 ehdr
.e_ident
[2] = ELFMAG2
;
2074 ehdr
.e_ident
[3] = ELFMAG3
;
2075 ehdr
.e_ident
[4] = ELFCLASSW
;
2076 ehdr
.e_ident
[5] = ELFDATA2LSB
;
2077 ehdr
.e_ident
[6] = EV_CURRENT
;
2078 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2079 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_FREEBSD
;
2081 #ifdef TCC_TARGET_ARM
2083 ehdr
.e_ident
[EI_OSABI
] = 0;
2084 ehdr
.e_flags
= EF_ARM_EABI_VER4
;
2085 if (file_type
== TCC_OUTPUT_EXE
|| file_type
== TCC_OUTPUT_DLL
)
2086 ehdr
.e_flags
|= EF_ARM_HASENTRY
;
2087 if (s1
->float_abi
== ARM_HARD_FLOAT
)
2088 ehdr
.e_flags
|= EF_ARM_VFP_FLOAT
;
2090 ehdr
.e_flags
|= EF_ARM_SOFT_FLOAT
;
2092 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_ARM
;
2097 case TCC_OUTPUT_EXE
:
2098 ehdr
.e_type
= ET_EXEC
;
2099 ehdr
.e_entry
= get_elf_sym_addr(s1
, "_start", 1);
2101 case TCC_OUTPUT_DLL
:
2102 ehdr
.e_type
= ET_DYN
;
2103 ehdr
.e_entry
= text_section
->sh_addr
; /* XXX: is it correct ? */
2105 case TCC_OUTPUT_OBJ
:
2106 ehdr
.e_type
= ET_REL
;
2109 ehdr
.e_machine
= EM_TCC_TARGET
;
2110 ehdr
.e_version
= EV_CURRENT
;
2111 ehdr
.e_shoff
= file_offset
;
2112 ehdr
.e_ehsize
= sizeof(ElfW(Ehdr
));
2113 ehdr
.e_shentsize
= sizeof(ElfW(Shdr
));
2114 ehdr
.e_shnum
= shnum
;
2115 ehdr
.e_shstrndx
= shnum
- 1;
2117 fwrite(&ehdr
, 1, sizeof(ElfW(Ehdr
)), f
);
2118 fwrite(phdr
, 1, phnum
* sizeof(ElfW(Phdr
)), f
);
2119 offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
2121 sort_syms(s1
, symtab_section
);
2122 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2123 s
= s1
->sections
[sec_order
[i
]];
2124 if (s
->sh_type
!= SHT_NOBITS
) {
2125 if (s
->sh_type
== SHT_DYNSYM
)
2126 patch_dynsym_undef(s1
, s
);
2127 while (offset
< s
->sh_offset
) {
2132 fwrite(s
->data
, 1, size
, f
);
2137 /* output section headers */
2138 while (offset
< ehdr
.e_shoff
) {
2143 for(i
= 0; i
< s1
->nb_sections
; i
++) {
2145 memset(sh
, 0, sizeof(ElfW(Shdr
)));
2146 s
= s1
->sections
[i
];
2148 sh
->sh_name
= s
->sh_name
;
2149 sh
->sh_type
= s
->sh_type
;
2150 sh
->sh_flags
= s
->sh_flags
;
2151 sh
->sh_entsize
= s
->sh_entsize
;
2152 sh
->sh_info
= s
->sh_info
;
2154 sh
->sh_link
= s
->link
->sh_num
;
2155 sh
->sh_addralign
= s
->sh_addralign
;
2156 sh
->sh_addr
= s
->sh_addr
;
2157 sh
->sh_offset
= s
->sh_offset
;
2158 sh
->sh_size
= s
->sh_size
;
2160 fwrite(sh
, 1, sizeof(ElfW(Shdr
)), f
);
2164 /* Write an elf, coff or "binary" file */
2165 static int tcc_write_elf_file(TCCState
*s1
, const char *filename
, int phnum
,
2166 ElfW(Phdr
) *phdr
, int file_offset
, int *sec_order
)
2168 int fd
, mode
, file_type
;
2171 file_type
= s1
->output_type
;
2172 if (file_type
== TCC_OUTPUT_OBJ
)
2177 fd
= open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
, mode
);
2179 tcc_error_noabort("could not write '%s'", filename
);
2182 f
= fdopen(fd
, "wb");
2184 printf("<- %s\n", filename
);
2186 #ifdef TCC_TARGET_COFF
2187 if (s1
->output_format
== TCC_OUTPUT_FORMAT_COFF
)
2188 tcc_output_coff(s1
, f
);
2191 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
)
2192 tcc_output_elf(s1
, f
, phnum
, phdr
, file_offset
, sec_order
);
2194 tcc_output_binary(s1
, f
, sec_order
);
2200 /* Output an elf, coff or binary file */
2201 /* XXX: suppress unneeded sections */
2202 static int elf_output_file(TCCState
*s1
, const char *filename
)
2204 int i
, ret
, phnum
, shnum
, file_type
, file_offset
, *sec_order
;
2205 struct dyn_inf dyninf
;
2208 Section
*strsec
, *interp
, *dynamic
, *dynstr
;
2210 file_type
= s1
->output_type
;
2213 /* if linking, also link in runtime libraries (libc, libgcc, etc.) */
2214 if (file_type
!= TCC_OUTPUT_OBJ
) {
2215 tcc_add_runtime(s1
);
2220 interp
= dynamic
= dynstr
= NULL
; /* avoid warning */
2221 dyninf
.dyn_rel_off
= 0; /* avoid warning */
2223 if (file_type
!= TCC_OUTPUT_OBJ
) {
2224 relocate_common_syms();
2226 tcc_add_linker_symbols(s1
);
2228 if (!s1
->static_link
) {
2229 if (file_type
== TCC_OUTPUT_EXE
) {
2231 /* allow override the dynamic loader */
2232 const char *elfint
= getenv("LD_SO");
2234 elfint
= DEFAULT_ELFINTERP(s1
);
2235 /* add interpreter section only if executable */
2236 interp
= new_section(s1
, ".interp", SHT_PROGBITS
, SHF_ALLOC
);
2237 interp
->sh_addralign
= 1;
2238 ptr
= section_ptr_add(interp
, 1 + strlen(elfint
));
2239 strcpy(ptr
, elfint
);
2242 /* add dynamic symbol table */
2243 s1
->dynsym
= new_symtab(s1
, ".dynsym", SHT_DYNSYM
, SHF_ALLOC
,
2245 ".hash", SHF_ALLOC
);
2246 dynstr
= s1
->dynsym
->link
;
2248 /* add dynamic section */
2249 dynamic
= new_section(s1
, ".dynamic", SHT_DYNAMIC
,
2250 SHF_ALLOC
| SHF_WRITE
);
2251 dynamic
->link
= dynstr
;
2252 dynamic
->sh_entsize
= sizeof(ElfW(Dyn
));
2255 s1
->plt
= new_section(s1
, ".plt", SHT_PROGBITS
,
2256 SHF_ALLOC
| SHF_EXECINSTR
);
2257 s1
->plt
->sh_entsize
= 4;
2261 if (file_type
== TCC_OUTPUT_EXE
) {
2262 bind_exe_dynsyms(s1
);
2264 if (s1
->nb_errors
) {
2269 bind_libs_dynsyms(s1
);
2270 } else /* shared library case: simply export all global symbols */
2271 export_global_syms(s1
);
2273 build_got_entries(s1
);
2275 /* add a list of needed dlls */
2276 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
2277 DLLReference
*dllref
= s1
->loaded_dlls
[i
];
2278 if (dllref
->level
== 0)
2279 put_dt(dynamic
, DT_NEEDED
, put_elf_str(dynstr
, dllref
->name
));
2283 put_dt(dynamic
, DT_RPATH
, put_elf_str(dynstr
, s1
->rpath
));
2285 /* XXX: currently, since we do not handle PIC code, we
2286 must relocate the readonly segments */
2287 if (file_type
== TCC_OUTPUT_DLL
) {
2289 put_dt(dynamic
, DT_SONAME
, put_elf_str(dynstr
, s1
->soname
));
2290 put_dt(dynamic
, DT_TEXTREL
, 0);
2294 put_dt(dynamic
, DT_SYMBOLIC
, 0);
2296 /* add necessary space for other entries */
2297 dyninf
.dyn_rel_off
= dynamic
->data_offset
;
2298 dynamic
->data_offset
+= sizeof(ElfW(Dyn
)) * EXTRA_RELITEMS
;
2300 /* still need to build got entries in case of static link */
2301 build_got_entries(s1
);
2305 /* we add a section for symbols */
2306 strsec
= new_section(s1
, ".shstrtab", SHT_STRTAB
, 0);
2307 put_elf_str(strsec
, "");
2309 /* compute number of sections */
2310 shnum
= s1
->nb_sections
;
2312 /* this array is used to reorder sections in the output file */
2313 sec_order
= tcc_malloc(sizeof(int) * shnum
);
2316 /* compute number of program headers */
2319 case TCC_OUTPUT_OBJ
:
2322 case TCC_OUTPUT_EXE
:
2323 if (!s1
->static_link
)
2324 phnum
= 4 + HAVE_PHDR
;
2328 case TCC_OUTPUT_DLL
:
2333 /* Allocate strings for section names */
2334 alloc_sec_names(s1
, file_type
, strsec
);
2336 /* allocate program segment headers */
2337 phdr
= tcc_mallocz(phnum
* sizeof(ElfW(Phdr
)));
2339 /* compute section to program header mapping */
2340 file_offset
= layout_sections(s1
, phdr
, phnum
, interp
, &dyninf
, sec_order
);
2342 /* Fill remaining program header and finalize relocation related to dynamic
2345 fill_unloadable_phdr(phdr
, phnum
, interp
, dynamic
);
2347 dyninf
.dynamic
= dynamic
;
2348 dyninf
.dynstr
= dynstr
;
2350 fill_dynamic(s1
, &dyninf
);
2352 /* put in GOT the dynamic section address and relocate PLT */
2353 put32(s1
->got
->data
, dynamic
->sh_addr
);
2354 if (file_type
== TCC_OUTPUT_EXE
2355 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2356 || file_type
== TCC_OUTPUT_DLL
2361 /* relocate symbols in .dynsym now that final addresses are known */
2362 for_each_elem(s1
->dynsym
, 1, sym
, ElfW(Sym
)) {
2363 /* relocate to PLT if symbol corresponds to a PLT entry */
2364 if (sym
->st_shndx
== SHN_UNDEF
) {
2366 sym
->st_value
+= s1
->plt
->sh_addr
;
2367 } else if (sym
->st_shndx
< SHN_LORESERVE
) {
2368 /* do symbol relocation */
2369 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
2375 /* if building executable or DLL, then relocate each section
2376 except the GOT which is already relocated */
2377 if (file_type
!= TCC_OUTPUT_OBJ
) {
2378 ret
= final_sections_reloc(s1
);
2383 /* Perform relocation to GOT or PLTÂ entries */
2384 if (file_type
== TCC_OUTPUT_EXE
&& s1
->static_link
)
2387 /* Create the ELF file with name 'filename' */
2388 ret
= tcc_write_elf_file(s1
, filename
, phnum
, phdr
, file_offset
, sec_order
);
2390 tcc_free(s1
->symtab_to_dynsym
);
2391 tcc_free(sec_order
);
2393 tcc_free(s1
->sym_attrs
);
2397 LIBTCCAPI
int tcc_output_file(TCCState
*s
, const char *filename
)
2400 #ifdef TCC_TARGET_PE
2401 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
2402 ret
= pe_output_file(s
, filename
);
2405 ret
= elf_output_file(s
, filename
);
2409 static void *load_data(int fd
, unsigned long file_offset
, unsigned long size
)
2413 data
= tcc_malloc(size
);
2414 lseek(fd
, file_offset
, SEEK_SET
);
2415 read(fd
, data
, size
);
2419 typedef struct SectionMergeInfo
{
2420 Section
*s
; /* corresponding existing section */
2421 unsigned long offset
; /* offset of the new section in the existing section */
2422 uint8_t new_section
; /* true if section 's' was added */
2423 uint8_t link_once
; /* true if link once section */
2426 /* load an object file and merge it with current files */
2427 /* XXX: handle correctly stab (debug) info */
2428 ST_FUNC
int tcc_load_object_file(TCCState
*s1
,
2429 int fd
, unsigned long file_offset
)
2432 ElfW(Shdr
) *shdr
, *sh
;
2433 int size
, i
, j
, offset
, offseti
, nb_syms
, sym_index
, ret
;
2434 unsigned char *strsec
, *strtab
;
2435 int *old_to_new_syms
;
2436 char *sh_name
, *name
;
2437 SectionMergeInfo
*sm_table
, *sm
;
2438 ElfW(Sym
) *sym
, *symtab
;
2445 stab_index
= stabstr_index
= 0;
2447 if (read(fd
, &ehdr
, sizeof(ehdr
)) != sizeof(ehdr
))
2449 if (ehdr
.e_ident
[0] != ELFMAG0
||
2450 ehdr
.e_ident
[1] != ELFMAG1
||
2451 ehdr
.e_ident
[2] != ELFMAG2
||
2452 ehdr
.e_ident
[3] != ELFMAG3
)
2454 /* test if object file */
2455 if (ehdr
.e_type
!= ET_REL
)
2457 /* test CPU specific stuff */
2458 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2459 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2461 tcc_error_noabort("invalid object file");
2465 shdr
= load_data(fd
, file_offset
+ ehdr
.e_shoff
,
2466 sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2467 sm_table
= tcc_mallocz(sizeof(SectionMergeInfo
) * ehdr
.e_shnum
);
2469 /* load section names */
2470 sh
= &shdr
[ehdr
.e_shstrndx
];
2471 strsec
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2473 /* load symtab and strtab */
2474 old_to_new_syms
= NULL
;
2478 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2480 if (sh
->sh_type
== SHT_SYMTAB
) {
2482 tcc_error_noabort("object must contain only one symtab");
2487 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2488 symtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2489 sm_table
[i
].s
= symtab_section
;
2491 /* now load strtab */
2492 sh
= &shdr
[sh
->sh_link
];
2493 strtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2497 /* now examine each section and try to merge its content with the
2499 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2500 /* no need to examine section name strtab */
2501 if (i
== ehdr
.e_shstrndx
)
2504 sh_name
= strsec
+ sh
->sh_name
;
2505 /* ignore sections types we do not handle */
2506 if (sh
->sh_type
!= SHT_PROGBITS
&&
2507 sh
->sh_type
!= SHT_RELX
&&
2509 sh
->sh_type
!= SHT_ARM_EXIDX
&&
2511 sh
->sh_type
!= SHT_NOBITS
&&
2512 sh
->sh_type
!= SHT_PREINIT_ARRAY
&&
2513 sh
->sh_type
!= SHT_INIT_ARRAY
&&
2514 sh
->sh_type
!= SHT_FINI_ARRAY
&&
2515 strcmp(sh_name
, ".stabstr")
2518 if (sh
->sh_addralign
< 1)
2519 sh
->sh_addralign
= 1;
2520 /* find corresponding section, if any */
2521 for(j
= 1; j
< s1
->nb_sections
;j
++) {
2522 s
= s1
->sections
[j
];
2523 if (!strcmp(s
->name
, sh_name
)) {
2524 if (!strncmp(sh_name
, ".gnu.linkonce",
2525 sizeof(".gnu.linkonce") - 1)) {
2526 /* if a 'linkonce' section is already present, we
2527 do not add it again. It is a little tricky as
2528 symbols can still be defined in
2530 sm_table
[i
].link_once
= 1;
2537 /* not found: create new section */
2538 s
= new_section(s1
, sh_name
, sh
->sh_type
, sh
->sh_flags
);
2539 /* take as much info as possible from the section. sh_link and
2540 sh_info will be updated later */
2541 s
->sh_addralign
= sh
->sh_addralign
;
2542 s
->sh_entsize
= sh
->sh_entsize
;
2543 sm_table
[i
].new_section
= 1;
2545 if (sh
->sh_type
!= s
->sh_type
) {
2546 tcc_error_noabort("invalid section type");
2550 /* align start of section */
2551 offset
= s
->data_offset
;
2553 if (0 == strcmp(sh_name
, ".stab")) {
2557 if (0 == strcmp(sh_name
, ".stabstr")) {
2562 size
= sh
->sh_addralign
- 1;
2563 offset
= (offset
+ size
) & ~size
;
2564 if (sh
->sh_addralign
> s
->sh_addralign
)
2565 s
->sh_addralign
= sh
->sh_addralign
;
2566 s
->data_offset
= offset
;
2568 sm_table
[i
].offset
= offset
;
2570 /* concatenate sections */
2572 if (sh
->sh_type
!= SHT_NOBITS
) {
2574 lseek(fd
, file_offset
+ sh
->sh_offset
, SEEK_SET
);
2575 ptr
= section_ptr_add(s
, size
);
2576 read(fd
, ptr
, size
);
2578 s
->data_offset
+= size
;
2583 /* gr relocate stab strings */
2584 if (stab_index
&& stabstr_index
) {
2587 s
= sm_table
[stab_index
].s
;
2588 a
= (Stab_Sym
*)(s
->data
+ sm_table
[stab_index
].offset
);
2589 b
= (Stab_Sym
*)(s
->data
+ s
->data_offset
);
2590 o
= sm_table
[stabstr_index
].offset
;
2592 a
->n_strx
+= o
, a
++;
2595 /* second short pass to update sh_link and sh_info fields of new
2597 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2599 if (!s
|| !sm_table
[i
].new_section
)
2602 if (sh
->sh_link
> 0)
2603 s
->link
= sm_table
[sh
->sh_link
].s
;
2604 if (sh
->sh_type
== SHT_RELX
) {
2605 s
->sh_info
= sm_table
[sh
->sh_info
].s
->sh_num
;
2606 /* update backward link */
2607 s1
->sections
[s
->sh_info
]->reloc
= s
;
2612 /* resolve symbols */
2613 old_to_new_syms
= tcc_mallocz(nb_syms
* sizeof(int));
2616 for(i
= 1; i
< nb_syms
; i
++, sym
++) {
2617 if (sym
->st_shndx
!= SHN_UNDEF
&&
2618 sym
->st_shndx
< SHN_LORESERVE
) {
2619 sm
= &sm_table
[sym
->st_shndx
];
2620 if (sm
->link_once
) {
2621 /* if a symbol is in a link once section, we use the
2622 already defined symbol. It is very important to get
2623 correct relocations */
2624 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
2625 name
= strtab
+ sym
->st_name
;
2626 sym_index
= find_elf_sym(symtab_section
, name
);
2628 old_to_new_syms
[i
] = sym_index
;
2632 /* if no corresponding section added, no need to add symbol */
2635 /* convert section number */
2636 sym
->st_shndx
= sm
->s
->sh_num
;
2638 sym
->st_value
+= sm
->offset
;
2641 name
= strtab
+ sym
->st_name
;
2642 sym_index
= add_elf_sym(symtab_section
, sym
->st_value
, sym
->st_size
,
2643 sym
->st_info
, sym
->st_other
,
2644 sym
->st_shndx
, name
);
2645 old_to_new_syms
[i
] = sym_index
;
2648 /* third pass to patch relocation entries */
2649 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2654 offset
= sm_table
[i
].offset
;
2655 switch(s
->sh_type
) {
2657 /* take relocation offset information */
2658 offseti
= sm_table
[sh
->sh_info
].offset
;
2659 for_each_elem(s
, (offset
/ sizeof(*rel
)), rel
, ElfW_Rel
) {
2662 /* convert symbol index */
2663 type
= ELFW(R_TYPE
)(rel
->r_info
);
2664 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
2665 /* NOTE: only one symtab assumed */
2666 if (sym_index
>= nb_syms
)
2668 sym_index
= old_to_new_syms
[sym_index
];
2669 /* ignore link_once in rel section. */
2670 if (!sym_index
&& !sm
->link_once
2671 #ifdef TCC_TARGET_ARM
2672 && type
!= R_ARM_V4BX
2676 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2677 i
, strsec
+ sh
->sh_name
, rel
->r_offset
);
2680 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
2681 /* offset the relocation offset */
2682 rel
->r_offset
+= offseti
;
2683 #ifdef TCC_TARGET_ARM
2684 /* Jumps and branches from a Thumb code to a PLT entry need
2685 special handling since PLT entries are ARM code.
2686 Unconditional bl instructions referencing PLT entries are
2687 handled by converting these instructions into blx
2688 instructions. Other case of instructions referencing a PLT
2689 entry require to add a Thumb stub before the PLT entry to
2690 switch to ARM mode. We set bit plt_thumb_stub of the
2691 attribute of a symbol to indicate such a case. */
2692 if (type
== R_ARM_THM_JUMP24
)
2693 alloc_sym_attr(s1
, sym_index
)->plt_thumb_stub
= 1;
2706 tcc_free(old_to_new_syms
);
2713 typedef struct ArchiveHeader
{
2714 char ar_name
[16]; /* name of this member */
2715 char ar_date
[12]; /* file mtime */
2716 char ar_uid
[6]; /* owner uid; printed as decimal */
2717 char ar_gid
[6]; /* owner gid; printed as decimal */
2718 char ar_mode
[8]; /* file mode, printed as octal */
2719 char ar_size
[10]; /* file size, printed as decimal */
2720 char ar_fmag
[2]; /* should contain ARFMAG */
2723 static int get_be32(const uint8_t *b
)
2725 return b
[3] | (b
[2] << 8) | (b
[1] << 16) | (b
[0] << 24);
2728 /* load only the objects which resolve undefined symbols */
2729 static int tcc_load_alacarte(TCCState
*s1
, int fd
, int size
)
2731 int i
, bound
, nsyms
, sym_index
, off
, ret
;
2733 const char *ar_names
, *p
;
2734 const uint8_t *ar_index
;
2737 data
= tcc_malloc(size
);
2738 if (read(fd
, data
, size
) != size
)
2740 nsyms
= get_be32(data
);
2741 ar_index
= data
+ 4;
2742 ar_names
= ar_index
+ nsyms
* 4;
2746 for(p
= ar_names
, i
= 0; i
< nsyms
; i
++, p
+= strlen(p
)+1) {
2747 sym_index
= find_elf_sym(symtab_section
, p
);
2749 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
2750 if(sym
->st_shndx
== SHN_UNDEF
) {
2751 off
= get_be32(ar_index
+ i
* 4) + sizeof(ArchiveHeader
);
2753 lseek(fd
, off
, SEEK_SET
);
2754 if(tcc_load_object_file(s1
, fd
, off
) < 0) {
2769 /* load a '.a' file */
2770 ST_FUNC
int tcc_load_archive(TCCState
*s1
, int fd
)
2777 unsigned long file_offset
;
2779 /* skip magic which was already checked */
2780 read(fd
, magic
, sizeof(magic
));
2783 len
= read(fd
, &hdr
, sizeof(hdr
));
2786 if (len
!= sizeof(hdr
)) {
2787 tcc_error_noabort("invalid archive");
2790 memcpy(ar_size
, hdr
.ar_size
, sizeof(hdr
.ar_size
));
2791 ar_size
[sizeof(hdr
.ar_size
)] = '\0';
2792 size
= strtol(ar_size
, NULL
, 0);
2793 memcpy(ar_name
, hdr
.ar_name
, sizeof(hdr
.ar_name
));
2794 for(i
= sizeof(hdr
.ar_name
) - 1; i
>= 0; i
--) {
2795 if (ar_name
[i
] != ' ')
2798 ar_name
[i
+ 1] = '\0';
2799 file_offset
= lseek(fd
, 0, SEEK_CUR
);
2801 size
= (size
+ 1) & ~1;
2802 if (!strcmp(ar_name
, "/")) {
2803 /* coff symbol table : we handle it */
2804 if(s1
->alacarte_link
)
2805 return tcc_load_alacarte(s1
, fd
, size
);
2806 } else if (!strcmp(ar_name
, "//") ||
2807 !strcmp(ar_name
, "__.SYMDEF") ||
2808 !strcmp(ar_name
, "__.SYMDEF/") ||
2809 !strcmp(ar_name
, "ARFILENAMES/")) {
2810 /* skip symbol table or archive names */
2812 if (tcc_load_object_file(s1
, fd
, file_offset
) < 0)
2815 lseek(fd
, file_offset
+ size
, SEEK_SET
);
2820 #ifndef TCC_TARGET_PE
2821 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2822 is referenced by the user (so it should be added as DT_NEEDED in
2823 the generated ELF file) */
2824 ST_FUNC
int tcc_load_dll(TCCState
*s1
, int fd
, const char *filename
, int level
)
2827 ElfW(Shdr
) *shdr
, *sh
, *sh1
;
2828 int i
, j
, nb_syms
, nb_dts
, sym_bind
, ret
;
2829 ElfW(Sym
) *sym
, *dynsym
;
2830 ElfW(Dyn
) *dt
, *dynamic
;
2831 unsigned char *dynstr
;
2832 const char *name
, *soname
;
2833 DLLReference
*dllref
;
2835 read(fd
, &ehdr
, sizeof(ehdr
));
2837 /* test CPU specific stuff */
2838 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2839 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2840 tcc_error_noabort("bad architecture");
2845 shdr
= load_data(fd
, ehdr
.e_shoff
, sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2847 /* load dynamic section and dynamic symbols */
2851 dynsym
= NULL
; /* avoid warning */
2852 dynstr
= NULL
; /* avoid warning */
2853 for(i
= 0, sh
= shdr
; i
< ehdr
.e_shnum
; i
++, sh
++) {
2854 switch(sh
->sh_type
) {
2856 nb_dts
= sh
->sh_size
/ sizeof(ElfW(Dyn
));
2857 dynamic
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2860 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2861 dynsym
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2862 sh1
= &shdr
[sh
->sh_link
];
2863 dynstr
= load_data(fd
, sh1
->sh_offset
, sh1
->sh_size
);
2870 /* compute the real library name */
2871 soname
= tcc_basename(filename
);
2873 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2874 if (dt
->d_tag
== DT_SONAME
) {
2875 soname
= dynstr
+ dt
->d_un
.d_val
;
2879 /* if the dll is already loaded, do not load it */
2880 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
2881 dllref
= s1
->loaded_dlls
[i
];
2882 if (!strcmp(soname
, dllref
->name
)) {
2883 /* but update level if needed */
2884 if (level
< dllref
->level
)
2885 dllref
->level
= level
;
2891 /* add the dll and its level */
2892 dllref
= tcc_mallocz(sizeof(DLLReference
) + strlen(soname
));
2893 dllref
->level
= level
;
2894 strcpy(dllref
->name
, soname
);
2895 dynarray_add((void ***)&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
, dllref
);
2897 /* add dynamic symbols in dynsym_section */
2898 for(i
= 1, sym
= dynsym
+ 1; i
< nb_syms
; i
++, sym
++) {
2899 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
2900 if (sym_bind
== STB_LOCAL
)
2902 name
= dynstr
+ sym
->st_name
;
2903 add_elf_sym(s1
->dynsymtab_section
, sym
->st_value
, sym
->st_size
,
2904 sym
->st_info
, sym
->st_other
, sym
->st_shndx
, name
);
2907 /* load all referenced DLLs */
2908 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2911 name
= dynstr
+ dt
->d_un
.d_val
;
2912 for(j
= 0; j
< s1
->nb_loaded_dlls
; j
++) {
2913 dllref
= s1
->loaded_dlls
[j
];
2914 if (!strcmp(name
, dllref
->name
))
2915 goto already_loaded
;
2917 if (tcc_add_dll(s1
, name
, AFF_REFERENCED_DLL
) < 0) {
2918 tcc_error_noabort("referenced dll '%s' not found", name
);
2935 #define LD_TOK_NAME 256
2936 #define LD_TOK_EOF (-1)
2938 /* return next ld script token */
2939 static int ld_next(TCCState
*s1
, char *name
, int name_size
)
2957 file
->buf_ptr
= parse_comment(file
->buf_ptr
);
2958 ch
= file
->buf_ptr
[0];
2966 /* case 'a' ... 'z': */
2993 /* case 'A' ... 'z': */
3028 if (!((ch
>= 'a' && ch
<= 'z') ||
3029 (ch
>= 'A' && ch
<= 'Z') ||
3030 (ch
>= '0' && ch
<= '9') ||
3031 strchr("/.-_+=$:\\,~", ch
)))
3033 if ((q
- name
) < name_size
- 1) {
3052 static int ld_add_file(TCCState
*s1
, const char filename
[])
3056 ret
= tcc_add_file_internal(s1
, filename
, 0);
3058 ret
= tcc_add_dll(s1
, filename
, 0);
3062 static inline int new_undef_syms(void)
3065 ret
= new_undef_sym
;
3070 static int ld_add_file_list(TCCState
*s1
, const char *cmd
, int as_needed
)
3072 char filename
[1024], libname
[1024];
3073 int t
, group
, nblibs
= 0, ret
= 0;
3076 group
= !strcmp(cmd
, "GROUP");
3079 t
= ld_next(s1
, filename
, sizeof(filename
));
3082 t
= ld_next(s1
, filename
, sizeof(filename
));
3085 if (t
== LD_TOK_EOF
) {
3086 tcc_error_noabort("unexpected end of file");
3088 goto lib_parse_error
;
3089 } else if (t
== ')') {
3091 } else if (t
== '-') {
3092 t
= ld_next(s1
, filename
, sizeof(filename
));
3093 if ((t
!= LD_TOK_NAME
) || (filename
[0] != 'l')) {
3094 tcc_error_noabort("library name expected");
3096 goto lib_parse_error
;
3098 pstrcpy(libname
, sizeof libname
, &filename
[1]);
3099 if (s1
->static_link
) {
3100 snprintf(filename
, sizeof filename
, "lib%s.a", libname
);
3102 snprintf(filename
, sizeof filename
, "lib%s.so", libname
);
3104 } else if (t
!= LD_TOK_NAME
) {
3105 tcc_error_noabort("filename expected");
3107 goto lib_parse_error
;
3109 if (!strcmp(filename
, "AS_NEEDED")) {
3110 ret
= ld_add_file_list(s1
, cmd
, 1);
3112 goto lib_parse_error
;
3114 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3116 ret
= ld_add_file(s1
, filename
);
3118 goto lib_parse_error
;
3120 /* Add the filename *and* the libname to avoid future conversions */
3121 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(filename
));
3122 if (libname
[0] != '\0')
3123 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(libname
));
3127 t
= ld_next(s1
, filename
, sizeof(filename
));
3129 t
= ld_next(s1
, filename
, sizeof(filename
));
3132 if (group
&& !as_needed
) {
3133 while (new_undef_syms()) {
3136 for (i
= 0; i
< nblibs
; i
++)
3137 ld_add_file(s1
, libs
[i
]);
3141 dynarray_reset(&libs
, &nblibs
);
3145 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3147 ST_FUNC
int tcc_load_ldscript(TCCState
*s1
)
3150 char filename
[1024];
3153 ch
= file
->buf_ptr
[0];
3156 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3157 if (t
== LD_TOK_EOF
)
3159 else if (t
!= LD_TOK_NAME
)
3161 if (!strcmp(cmd
, "INPUT") ||
3162 !strcmp(cmd
, "GROUP")) {
3163 ret
= ld_add_file_list(s1
, cmd
, 0);
3166 } else if (!strcmp(cmd
, "OUTPUT_FORMAT") ||
3167 !strcmp(cmd
, "TARGET")) {
3168 /* ignore some commands */
3169 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3173 t
= ld_next(s1
, filename
, sizeof(filename
));
3174 if (t
== LD_TOK_EOF
) {
3175 tcc_error_noabort("unexpected end of file");
3177 } else if (t
== ')') {
3187 #endif /* !TCC_TARGET_PE */