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
;
59 unsigned char *strtab
;
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((unsigned char *) 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((unsigned char *) 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
= (char *) 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
= (char *) 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
= (char *) 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
)
513 Section
*sr
= s
->reloc
;
519 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
520 ElfW_Rel
*qrel
= (ElfW_Rel
*) sr
->data
; /* ptr to next reloc entry reused */
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
= (char *) 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 case R_ARM_THM_JUMP24
:
1192 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1193 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1194 /* We are relocating a jump from thumb code to arm code */
1195 if (sym
->st_shndx
!= SHN_UNDEF
&& !(sym
->st_value
& 1)) {
1198 char *name
, buf
[1024];
1199 Section
*text_section
;
1201 name
= (char *) symtab_section
->link
->data
+ sym
->st_name
;
1202 text_section
= s1
->sections
[sym
->st_shndx
];
1203 /* Modify reloc to target a thumb stub to switch to ARM */
1204 snprintf(buf
, sizeof(buf
), "%s_from_thumb", name
);
1205 index
= put_elf_sym(symtab_section
,
1206 text_section
->data_offset
+ 1,
1207 sym
->st_size
, sym
->st_info
, 0,
1208 sym
->st_shndx
, buf
);
1209 rel
->r_info
= ELFW(R_INFO
)(index
, type
);
1210 /* Create a thumb stub fonction to switch to ARM mode */
1211 put_elf_reloc(symtab_section
, text_section
,
1212 text_section
->data_offset
+ 4, R_ARM_JUMP24
,
1214 p
= section_ptr_add(text_section
, 8);
1215 put32(p
, 0x4778); /* bx pc */
1216 put32(p
+2, 0x46c0); /* nop */
1217 put32(p
+4, 0xeafffffe); /* b $sym */
1219 #elif defined(TCC_TARGET_C67)
1226 if (type
== R_C60_GOT32
|| type
== R_C60_PLT32
) {
1227 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1228 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1229 /* look at the symbol got offset. If none, then add one */
1230 if (type
== R_C60_GOT32
)
1231 reloc_type
= R_C60_GLOB_DAT
;
1233 reloc_type
= R_C60_JMP_SLOT
;
1234 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1238 #elif defined(TCC_TARGET_X86_64)
1239 case R_X86_64_GOT32
:
1240 case R_X86_64_GOTTPOFF
:
1241 case R_X86_64_GOTPCREL
:
1242 case R_X86_64_PLT32
:
1245 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
||
1246 type
== R_X86_64_PLT32
) {
1247 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1248 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1249 /* look at the symbol got offset. If none, then add one */
1250 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
)
1251 reloc_type
= R_X86_64_GLOB_DAT
;
1253 reloc_type
= R_X86_64_JUMP_SLOT
;
1254 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1259 #error unsupported CPU
1268 ST_FUNC Section
*new_symtab(TCCState
*s1
,
1269 const char *symtab_name
, int sh_type
, int sh_flags
,
1270 const char *strtab_name
,
1271 const char *hash_name
, int hash_sh_flags
)
1273 Section
*symtab
, *strtab
, *hash
;
1274 int *ptr
, nb_buckets
;
1276 symtab
= new_section(s1
, symtab_name
, sh_type
, sh_flags
);
1277 symtab
->sh_entsize
= sizeof(ElfW(Sym
));
1278 strtab
= new_section(s1
, strtab_name
, SHT_STRTAB
, sh_flags
);
1279 put_elf_str(strtab
, "");
1280 symtab
->link
= strtab
;
1281 put_elf_sym(symtab
, 0, 0, 0, 0, 0, NULL
);
1285 hash
= new_section(s1
, hash_name
, SHT_HASH
, hash_sh_flags
);
1286 hash
->sh_entsize
= sizeof(int);
1287 symtab
->hash
= hash
;
1288 hash
->link
= symtab
;
1290 ptr
= section_ptr_add(hash
, (2 + nb_buckets
+ 1) * sizeof(int));
1291 ptr
[0] = nb_buckets
;
1293 memset(ptr
+ 2, 0, (nb_buckets
+ 1) * sizeof(int));
1297 /* put dynamic tag */
1298 static void put_dt(Section
*dynamic
, int dt
, addr_t val
)
1301 dyn
= section_ptr_add(dynamic
, sizeof(ElfW(Dyn
)));
1303 dyn
->d_un
.d_val
= val
;
1306 static void add_init_array_defines(TCCState
*s1
, const char *section_name
)
1310 char sym_start
[1024];
1313 snprintf(sym_start
, sizeof(sym_start
), "__%s_start", section_name
+ 1);
1314 snprintf(sym_end
, sizeof(sym_end
), "__%s_end", section_name
+ 1);
1316 s
= find_section(s1
, section_name
);
1321 end_offset
= s
->data_offset
;
1324 add_elf_sym(symtab_section
,
1326 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1327 s
->sh_num
, sym_start
);
1328 add_elf_sym(symtab_section
,
1330 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1331 s
->sh_num
, sym_end
);
1334 ST_FUNC
void tcc_add_bcheck(TCCState
*s1
)
1336 #ifdef CONFIG_TCC_BCHECK
1338 Section
*init_section
;
1339 unsigned char *pinit
;
1342 if (0 == s1
->do_bounds_check
)
1345 /* XXX: add an object file to do that */
1346 ptr
= section_ptr_add(bounds_section
, sizeof(unsigned long));
1348 add_elf_sym(symtab_section
, 0, 0,
1349 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1350 bounds_section
->sh_num
, "__bounds_start");
1351 #ifdef TCC_TARGET_I386
1352 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
) {
1353 /* add 'call __bound_init()' in .init section */
1354 init_section
= find_section(s1
, ".init");
1355 pinit
= section_ptr_add(init_section
, 5);
1357 put32(pinit
+ 1, -4);
1358 sym_index
= find_elf_sym(symtab_section
, "__bound_init");
1359 put_elf_reloc(symtab_section
, init_section
,
1360 init_section
->data_offset
- 4, R_386_PC32
, sym_index
);
1366 static inline int tcc_add_support(TCCState
*s1
, const char *filename
)
1369 snprintf(buf
, sizeof(buf
), "%s/%s", s1
->tcc_lib_path
, filename
);
1370 return tcc_add_file(s1
, buf
);
1373 /* add tcc runtime libraries */
1374 ST_FUNC
void tcc_add_runtime(TCCState
*s1
)
1377 if (!s1
->nostdlib
) {
1378 tcc_add_library(s1
, "c");
1379 #ifdef CONFIG_USE_LIBGCC
1380 if (!s1
->static_link
) {
1381 tcc_add_file(s1
, TCC_LIBGCC
);
1382 tcc_add_support(s1
, "libtcc1.a");
1384 tcc_add_support(s1
, "libtcc1.a");
1386 tcc_add_support(s1
, "libtcc1.a");
1390 /* tcc_add_bcheck tries to relocate a call to __bound_init in _init so
1391 libtcc1.a must be loaded before for __bound_init to be defined and
1392 crtn.o must be loaded after to not finalize _init too early. */
1395 if (!s1
->nostdlib
) {
1396 /* add crt end if not memory output */
1397 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
)
1398 tcc_add_crt(s1
, "crtn.o");
1402 /* add various standard linker symbols (must be done after the
1403 sections are filled (for example after allocating common
1405 ST_FUNC
void tcc_add_linker_symbols(TCCState
*s1
)
1411 add_elf_sym(symtab_section
,
1412 text_section
->data_offset
, 0,
1413 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1414 text_section
->sh_num
, "_etext");
1415 add_elf_sym(symtab_section
,
1416 data_section
->data_offset
, 0,
1417 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1418 data_section
->sh_num
, "_edata");
1419 add_elf_sym(symtab_section
,
1420 bss_section
->data_offset
, 0,
1421 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1422 bss_section
->sh_num
, "_end");
1423 /* horrible new standard ldscript defines */
1424 add_init_array_defines(s1
, ".preinit_array");
1425 add_init_array_defines(s1
, ".init_array");
1426 add_init_array_defines(s1
, ".fini_array");
1428 /* add start and stop symbols for sections whose name can be
1430 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1431 s
= s1
->sections
[i
];
1432 if (s
->sh_type
== SHT_PROGBITS
&&
1433 (s
->sh_flags
& SHF_ALLOC
)) {
1437 /* check if section name can be expressed in C */
1443 if (!isid(ch
) && !isnum(ch
))
1447 snprintf(buf
, sizeof(buf
), "__start_%s", s
->name
);
1448 add_elf_sym(symtab_section
,
1450 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1452 snprintf(buf
, sizeof(buf
), "__stop_%s", s
->name
);
1453 add_elf_sym(symtab_section
,
1455 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1462 static void tcc_output_binary(TCCState
*s1
, FILE *f
,
1463 const int *sec_order
)
1466 int i
, offset
, size
;
1469 for(i
=1;i
<s1
->nb_sections
;i
++) {
1470 s
= s1
->sections
[sec_order
[i
]];
1471 if (s
->sh_type
!= SHT_NOBITS
&&
1472 (s
->sh_flags
& SHF_ALLOC
)) {
1473 while (offset
< s
->sh_offset
) {
1478 fwrite(s
->data
, 1, size
, f
);
1484 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1486 #define EXTRA_RELITEMS 14
1488 /* move the relocation value from .dynsym to .got */
1489 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1491 uint32_t *gotd
= (void *)s1
->got
->data
;
1494 gotd
+= 3; /* dummy entries in .got */
1495 /* relocate symbols in .dynsym */
1496 for_each_elem(s
, 1, sym
, ElfW(Sym
)) {
1497 if (sym
->st_shndx
== SHN_UNDEF
) {
1498 *gotd
++ = sym
->st_value
+ 6; /* XXX 6 is magic ? */
1505 #define EXTRA_RELITEMS 9
1507 /* zero plt offsets of weak symbols in .dynsym */
1508 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1512 for_each_elem(s
, 1, sym
, ElfW(Sym
))
1513 if (sym
->st_shndx
== SHN_UNDEF
&& ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
1518 ST_FUNC
void fill_got_entry(TCCState
*s1
, ElfW_Rel
*rel
)
1520 int sym_index
= ELFW(R_SYM
) (rel
->r_info
);
1521 ElfW(Sym
) *sym
= &((ElfW(Sym
) *) symtab_section
->data
)[sym_index
];
1522 unsigned long offset
;
1524 if (sym_index
>= s1
->nb_sym_attrs
)
1526 offset
= s1
->sym_attrs
[sym_index
].got_offset
;
1527 section_reserve(s1
->got
, offset
+ PTR_SIZE
);
1528 #ifdef TCC_TARGET_X86_64
1529 /* only works for x86-64 */
1530 put32(s1
->got
->data
+ offset
+ 4, sym
->st_value
>> 32);
1532 put32(s1
->got
->data
+ offset
, sym
->st_value
& 0xffffffff);
1535 /* Perform relocation to GOT or PLTÂ entries */
1536 ST_FUNC
void fill_got(TCCState
*s1
)
1542 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1543 s
= s1
->sections
[i
];
1544 if (s
->sh_type
!= SHT_RELX
)
1546 /* no need to handle got relocations */
1547 if (s
->link
!= symtab_section
)
1549 for_each_elem(s
, 0, rel
, ElfW_Rel
) {
1550 switch (ELFW(R_TYPE
) (rel
->r_info
)) {
1551 case R_X86_64_GOT32
:
1552 case R_X86_64_GOTPCREL
:
1553 case R_X86_64_PLT32
:
1554 fill_got_entry(s1
, rel
);
1561 /* Bind symbols of executable: resolve undefined symbols from exported symbols
1562 in shared libraries and export non local defined symbols to shared libraries
1563 if -rdynamic switch was given on command line */
1564 static void bind_exe_dynsyms(TCCState
*s1
)
1567 int sym_index
, index
;
1568 ElfW(Sym
) *sym
, *esym
;
1571 /* Resolve undefined symbols from dynamic symbols. When there is a match:
1572 - if STT_FUNC or STT_GNU_IFUNC symbol -> add it in PLT
1573 - if STT_OBJECT symbol -> add it in .bss section with suitable reloc */
1574 for_each_elem(symtab_section
, 1, sym
, ElfW(Sym
)) {
1575 if (sym
->st_shndx
== SHN_UNDEF
) {
1576 name
= (char *) symtab_section
->link
->data
+ sym
->st_name
;
1577 sym_index
= find_elf_sym(s1
->dynsymtab_section
, name
);
1579 esym
= &((ElfW(Sym
) *)s1
->dynsymtab_section
->data
)[sym_index
];
1580 type
= ELFW(ST_TYPE
)(esym
->st_info
);
1581 if ((type
== STT_FUNC
) || (type
== STT_GNU_IFUNC
)) {
1582 /* Indirect functions shall have STT_FUNC type in executable
1583 * dynsym section. Indeed, a dlsym call following a lazy
1584 * resolution would pick the symbol value from the
1585 * executable dynsym entry which would contain the address
1586 * of the function wanted by the caller of dlsym instead of
1587 * the address of the function that would return that
1589 put_got_entry(s1
, R_JMP_SLOT
, esym
->st_size
,
1590 ELFW(ST_INFO
)(STB_GLOBAL
,STT_FUNC
),
1591 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1592 } else if (type
== STT_OBJECT
) {
1593 unsigned long offset
;
1595 offset
= bss_section
->data_offset
;
1596 /* XXX: which alignment ? */
1597 offset
= (offset
+ 16 - 1) & -16;
1598 index
= put_elf_sym(s1
->dynsym
, offset
, esym
->st_size
,
1599 esym
->st_info
, 0, bss_section
->sh_num
,
1601 /* Ensure R_COPY works for weak symbol aliases */
1602 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1603 for_each_elem(s1
->dynsymtab_section
, 1, dynsym
, ElfW(Sym
)) {
1604 if ((dynsym
->st_value
== esym
->st_value
)
1605 && (ELFW(ST_BIND
)(dynsym
->st_info
) == STB_GLOBAL
)) {
1606 char *dynname
= (char *) s1
->dynsymtab_section
->link
->data
1608 put_elf_sym(s1
->dynsym
, offset
, dynsym
->st_size
,
1610 bss_section
->sh_num
, dynname
);
1615 put_elf_reloc(s1
->dynsym
, bss_section
,
1616 offset
, R_COPY
, index
);
1617 offset
+= esym
->st_size
;
1618 bss_section
->data_offset
= offset
;
1621 /* STB_WEAK undefined symbols are accepted */
1622 /* XXX: _fp_hw seems to be part of the ABI, so we ignore it */
1623 if (ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
||
1624 !strcmp(name
, "_fp_hw")) {
1626 tcc_error_noabort("undefined symbol '%s'", name
);
1629 } else if (s1
->rdynamic
&& ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1630 /* if -rdynamic option, then export all non local symbols */
1631 name
= (char *) symtab_section
->link
->data
+ sym
->st_name
;
1632 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
, sym
->st_info
,
1633 0, sym
->st_shndx
, name
);
1638 /* Bind symbols of libraries: export non local symbols of executable that
1639 resolve undefined symbols of shared libraries */
1640 static void bind_libs_dynsyms(TCCState
*s1
)
1644 ElfW(Sym
) *sym
, *esym
;
1646 /* now look at unresolved dynamic symbols and export
1647 corresponding symbol */
1648 for_each_elem(s1
->dynsymtab_section
, 1, esym
, ElfW(Sym
)) {
1649 if (esym
->st_shndx
== SHN_UNDEF
) {
1650 name
= (char *) s1
->dynsymtab_section
->link
->data
+ esym
->st_name
;
1651 sym_index
= find_elf_sym(symtab_section
, name
);
1653 /* XXX: avoid adding a symbol if already present because of
1655 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1656 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1657 sym
->st_info
, 0, sym
->st_shndx
, name
);
1659 /* weak symbols can stay undefined */
1660 if (ELFW(ST_BIND
)(esym
->st_info
) != STB_WEAK
)
1661 tcc_warning("undefined dynamic symbol '%s'", name
);
1667 /* Export all non local symbols (for shared libraries) */
1668 static void export_global_syms(TCCState
*s1
)
1670 int nb_syms
, dynindex
, index
;
1674 nb_syms
= symtab_section
->data_offset
/ sizeof(ElfW(Sym
));
1675 s1
->symtab_to_dynsym
= tcc_mallocz(sizeof(int) * nb_syms
);
1676 for_each_elem(symtab_section
, 1, sym
, ElfW(Sym
)) {
1677 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1678 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1679 int type
= ELFW(ST_TYPE
)(sym
->st_info
);
1680 if ((type
== STT_FUNC
|| type
== STT_GNU_IFUNC
)
1681 && sym
->st_shndx
== SHN_UNDEF
) {
1682 int visibility
= ELFW(ST_BIND
)(sym
->st_info
);
1683 put_got_entry(s1
, R_JMP_SLOT
, sym
->st_size
,
1684 ELFW(ST_INFO
)(visibility
, STT_FUNC
),
1685 sym
- (ElfW(Sym
) *) symtab_section
->data
);
1686 } else if (type
== STT_OBJECT
) {
1687 put_got_entry(s1
, R_X86_64_GLOB_DAT
, sym
->st_size
, sym
->st_info
,
1688 sym
- (ElfW(Sym
) *) symtab_section
->data
);
1692 name
= (char *) symtab_section
->link
->data
+ sym
->st_name
;
1693 dynindex
= put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1694 sym
->st_info
, 0, sym
->st_shndx
, name
);
1695 index
= sym
- (ElfW(Sym
) *) symtab_section
->data
;
1696 s1
->symtab_to_dynsym
[index
] = dynindex
;
1702 /* relocate the PLT: compute addresses and offsets in the PLT now that final
1703 address for PLT and GOT are known (see fill_program_header) */
1704 static void relocate_plt(TCCState
*s1
)
1709 p_end
= p
+ s1
->plt
->data_offset
;
1711 #if defined(TCC_TARGET_I386)
1712 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
1713 put32(p
+ 8, get32(p
+ 8) + s1
->got
->sh_addr
);
1716 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
1719 #elif defined(TCC_TARGET_X86_64)
1720 int x
= s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 6;
1721 put32(p
+ 2, get32(p
+ 2) + x
);
1722 put32(p
+ 8, get32(p
+ 8) + x
- 6);
1725 put32(p
+ 2, get32(p
+ 2) + x
+ s1
->plt
->data
- p
);
1728 #elif defined(TCC_TARGET_ARM)
1730 x
=s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 12;
1733 if (get32(p
) == 0x46c04778) /* PLT Thumb stub present */
1735 put32(p
+ 12, x
+ get32(p
+ 12) + s1
->plt
->data
- p
);
1738 #elif defined(TCC_TARGET_C67)
1741 #error unsupported CPU
1746 /* Allocate strings for section names and decide if an unallocated section
1749 NOTE: the strsec section comes last, so its size is also correct ! */
1750 static void alloc_sec_names(TCCState
*s1
, int file_type
, Section
*strsec
)
1755 /* Allocate strings for section names */
1756 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1757 s
= s1
->sections
[i
];
1758 s
->sh_name
= put_elf_str(strsec
, s
->name
);
1759 /* when generating a DLL, we include relocations but we may
1761 if (file_type
== TCC_OUTPUT_DLL
&&
1762 s
->sh_type
== SHT_RELX
&&
1763 !(s
->sh_flags
& SHF_ALLOC
)) {
1764 /* gr: avoid bogus relocs for empty (debug) sections */
1765 if (s1
->sections
[s
->sh_info
]->sh_flags
& SHF_ALLOC
)
1766 prepare_dynamic_rel(s1
, s
);
1767 else if (s1
->do_debug
)
1768 s
->sh_size
= s
->data_offset
;
1769 } else if (s1
->do_debug
||
1770 file_type
== TCC_OUTPUT_OBJ
||
1771 (s
->sh_flags
& SHF_ALLOC
) ||
1772 i
== (s1
->nb_sections
- 1)) {
1773 /* we output all sections if debug or object file */
1774 s
->sh_size
= s
->data_offset
;
1779 /* Info to be copied in dynamic section */
1783 unsigned long dyn_rel_off
;
1786 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1792 /* Assign sections to segments and decide how are sections laid out when loaded
1793 in memory. This function also fills corresponding program headers. */
1794 static int layout_sections(TCCState
*s1
, ElfW(Phdr
) *phdr
, int phnum
,
1795 Section
*interp
, struct dyn_inf
*dyninf
,
1798 int i
, j
, k
, file_type
, sh_order_index
, file_offset
;
1804 file_type
= s1
->output_type
;
1806 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
)
1807 file_offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
1812 if (s1
->has_text_addr
) {
1813 int a_offset
, p_offset
;
1814 addr
= s1
->text_addr
;
1815 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1817 a_offset
= (int) (addr
& (s1
->section_align
- 1));
1818 p_offset
= file_offset
& (s1
->section_align
- 1);
1819 if (a_offset
< p_offset
)
1820 a_offset
+= s1
->section_align
;
1821 file_offset
+= (a_offset
- p_offset
);
1823 if (file_type
== TCC_OUTPUT_DLL
)
1826 addr
= ELF_START_ADDR
;
1827 /* compute address after headers */
1828 addr
+= (file_offset
& (s1
->section_align
- 1));
1832 /* Leave one program headers for the program interpreter and one for
1833 the program header table itself if needed. These are done later as
1834 they require section layout to be done first. */
1836 ph
+= 1 + HAVE_PHDR
;
1838 /* dynamic relocation table information, for .dynamic section */
1839 dyninf
->rel_addr
= dyninf
->rel_size
= 0;
1840 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1841 dyninf
->bss_addr
= dyninf
->bss_size
= 0;
1844 for(j
= 0; j
< 2; j
++) {
1845 ph
->p_type
= PT_LOAD
;
1847 ph
->p_flags
= PF_R
| PF_X
;
1849 ph
->p_flags
= PF_R
| PF_W
;
1850 ph
->p_align
= s1
->section_align
;
1852 /* Decide the layout of sections loaded in memory. This must
1853 be done before program headers are filled since they contain
1854 info about the layout. We do the following ordering: interp,
1855 symbol tables, relocations, progbits, nobits */
1856 /* XXX: do faster and simpler sorting */
1857 for(k
= 0; k
< 5; k
++) {
1858 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1859 s
= s1
->sections
[i
];
1860 /* compute if section should be included */
1862 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1866 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1867 (SHF_ALLOC
| SHF_WRITE
))
1873 } else if (s
->sh_type
== SHT_DYNSYM
||
1874 s
->sh_type
== SHT_STRTAB
||
1875 s
->sh_type
== SHT_HASH
) {
1878 } else if (s
->sh_type
== SHT_RELX
) {
1881 } else if (s
->sh_type
== SHT_NOBITS
) {
1888 sec_order
[sh_order_index
++] = i
;
1890 /* section matches: we align it and add its size */
1892 addr
= (addr
+ s
->sh_addralign
- 1) &
1893 ~(s
->sh_addralign
- 1);
1894 file_offset
+= (int) ( addr
- tmp
);
1895 s
->sh_offset
= file_offset
;
1898 /* update program header infos */
1899 if (ph
->p_offset
== 0) {
1900 ph
->p_offset
= file_offset
;
1902 ph
->p_paddr
= ph
->p_vaddr
;
1904 /* update dynamic relocation infos */
1905 if (s
->sh_type
== SHT_RELX
) {
1906 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1907 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.got")) {
1908 dyninf
->rel_addr
= addr
;
1909 dyninf
->rel_size
+= s
->sh_size
; /* XXX only first rel. */
1911 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.bss")) {
1912 dyninf
->bss_addr
= addr
;
1913 dyninf
->bss_size
= s
->sh_size
; /* XXX only first rel. */
1916 if (dyninf
->rel_size
== 0)
1917 dyninf
->rel_addr
= addr
;
1918 dyninf
->rel_size
+= s
->sh_size
;
1922 if (s
->sh_type
!= SHT_NOBITS
)
1923 file_offset
+= s
->sh_size
;
1926 ph
->p_filesz
= file_offset
- ph
->p_offset
;
1927 ph
->p_memsz
= addr
- ph
->p_vaddr
;
1930 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1931 /* if in the middle of a page, we duplicate the page in
1932 memory so that one copy is RX and the other is RW */
1933 if ((addr
& (s1
->section_align
- 1)) != 0)
1934 addr
+= s1
->section_align
;
1936 addr
= (addr
+ s1
->section_align
- 1) & ~(s1
->section_align
- 1);
1937 file_offset
= (file_offset
+ s1
->section_align
- 1) &
1938 ~(s1
->section_align
- 1);
1944 /* all other sections come after */
1945 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1946 s
= s1
->sections
[i
];
1947 if (phnum
> 0 && (s
->sh_flags
& SHF_ALLOC
))
1949 sec_order
[sh_order_index
++] = i
;
1951 file_offset
= (file_offset
+ s
->sh_addralign
- 1) &
1952 ~(s
->sh_addralign
- 1);
1953 s
->sh_offset
= file_offset
;
1954 if (s
->sh_type
!= SHT_NOBITS
)
1955 file_offset
+= s
->sh_size
;
1961 static void fill_unloadable_phdr(ElfW(Phdr
) *phdr
, int phnum
, Section
*interp
,
1966 /* if interpreter, then add corresponding program header */
1972 int len
= phnum
* sizeof(ElfW(Phdr
));
1974 ph
->p_type
= PT_PHDR
;
1975 ph
->p_offset
= sizeof(ElfW(Ehdr
));
1976 ph
->p_vaddr
= interp
->sh_addr
- len
;
1977 ph
->p_paddr
= ph
->p_vaddr
;
1978 ph
->p_filesz
= ph
->p_memsz
= len
;
1979 ph
->p_flags
= PF_R
| PF_X
;
1980 ph
->p_align
= 4; /* interp->sh_addralign; */
1984 ph
->p_type
= PT_INTERP
;
1985 ph
->p_offset
= interp
->sh_offset
;
1986 ph
->p_vaddr
= interp
->sh_addr
;
1987 ph
->p_paddr
= ph
->p_vaddr
;
1988 ph
->p_filesz
= interp
->sh_size
;
1989 ph
->p_memsz
= interp
->sh_size
;
1991 ph
->p_align
= interp
->sh_addralign
;
1994 /* if dynamic section, then add corresponding program header */
1996 ph
= &phdr
[phnum
- 1];
1998 ph
->p_type
= PT_DYNAMIC
;
1999 ph
->p_offset
= dynamic
->sh_offset
;
2000 ph
->p_vaddr
= dynamic
->sh_addr
;
2001 ph
->p_paddr
= ph
->p_vaddr
;
2002 ph
->p_filesz
= dynamic
->sh_size
;
2003 ph
->p_memsz
= dynamic
->sh_size
;
2004 ph
->p_flags
= PF_R
| PF_W
;
2005 ph
->p_align
= dynamic
->sh_addralign
;
2009 /* Fill the dynamic section with tags describing the address and size of
2011 static void fill_dynamic(TCCState
*s1
, struct dyn_inf
*dyninf
)
2015 dynamic
= dyninf
->dynamic
;
2017 /* put dynamic section entries */
2018 dynamic
->data_offset
= dyninf
->dyn_rel_off
;
2019 put_dt(dynamic
, DT_HASH
, s1
->dynsym
->hash
->sh_addr
);
2020 put_dt(dynamic
, DT_STRTAB
, dyninf
->dynstr
->sh_addr
);
2021 put_dt(dynamic
, DT_SYMTAB
, s1
->dynsym
->sh_addr
);
2022 put_dt(dynamic
, DT_STRSZ
, dyninf
->dynstr
->data_offset
);
2023 put_dt(dynamic
, DT_SYMENT
, sizeof(ElfW(Sym
)));
2024 #ifdef TCC_TARGET_X86_64
2025 put_dt(dynamic
, DT_RELA
, dyninf
->rel_addr
);
2026 put_dt(dynamic
, DT_RELASZ
, dyninf
->rel_size
);
2027 put_dt(dynamic
, DT_RELAENT
, sizeof(ElfW_Rel
));
2029 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2030 put_dt(dynamic
, DT_PLTGOT
, s1
->got
->sh_addr
);
2031 put_dt(dynamic
, DT_PLTRELSZ
, dyninf
->rel_size
);
2032 put_dt(dynamic
, DT_JMPREL
, dyninf
->rel_addr
);
2033 put_dt(dynamic
, DT_PLTREL
, DT_REL
);
2034 put_dt(dynamic
, DT_REL
, dyninf
->bss_addr
);
2035 put_dt(dynamic
, DT_RELSZ
, dyninf
->bss_size
);
2037 put_dt(dynamic
, DT_REL
, dyninf
->rel_addr
);
2038 put_dt(dynamic
, DT_RELSZ
, dyninf
->rel_size
);
2039 put_dt(dynamic
, DT_RELENT
, sizeof(ElfW_Rel
));
2043 put_dt(dynamic
, DT_DEBUG
, 0);
2044 put_dt(dynamic
, DT_NULL
, 0);
2047 /* Relocate remaining sections and symbols (that is those not related to
2049 static int final_sections_reloc(TCCState
*s1
)
2054 relocate_syms(s1
, 0);
2056 if (s1
->nb_errors
!= 0)
2059 /* relocate sections */
2060 /* XXX: ignore sections with allocated relocations ? */
2061 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2062 s
= s1
->sections
[i
];
2063 if (s
->reloc
&& s
!= s1
->got
)
2064 relocate_section(s1
, s
);
2067 /* relocate relocation entries if the relocation tables are
2068 allocated in the executable */
2069 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2070 s
= s1
->sections
[i
];
2071 if ((s
->sh_flags
& SHF_ALLOC
) &&
2072 s
->sh_type
== SHT_RELX
) {
2073 relocate_rel(s1
, s
);
2079 /* Create an ELF file on disk.
2080 This function handle ELF specific layout requirements */
2081 static void tcc_output_elf(TCCState
*s1
, FILE *f
, int phnum
, ElfW(Phdr
) *phdr
,
2082 int file_offset
, int *sec_order
)
2084 int i
, shnum
, offset
, size
, file_type
;
2087 ElfW(Shdr
) shdr
, *sh
;
2089 file_type
= s1
->output_type
;
2090 shnum
= s1
->nb_sections
;
2092 memset(&ehdr
, 0, sizeof(ehdr
));
2095 ehdr
.e_phentsize
= sizeof(ElfW(Phdr
));
2096 ehdr
.e_phnum
= phnum
;
2097 ehdr
.e_phoff
= sizeof(ElfW(Ehdr
));
2101 file_offset
= (file_offset
+ 3) & -4;
2104 ehdr
.e_ident
[0] = ELFMAG0
;
2105 ehdr
.e_ident
[1] = ELFMAG1
;
2106 ehdr
.e_ident
[2] = ELFMAG2
;
2107 ehdr
.e_ident
[3] = ELFMAG3
;
2108 ehdr
.e_ident
[4] = ELFCLASSW
;
2109 ehdr
.e_ident
[5] = ELFDATA2LSB
;
2110 ehdr
.e_ident
[6] = EV_CURRENT
;
2111 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2112 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_FREEBSD
;
2114 #ifdef TCC_TARGET_ARM
2116 ehdr
.e_ident
[EI_OSABI
] = 0;
2117 ehdr
.e_flags
= EF_ARM_EABI_VER4
;
2118 if (file_type
== TCC_OUTPUT_EXE
|| file_type
== TCC_OUTPUT_DLL
)
2119 ehdr
.e_flags
|= EF_ARM_HASENTRY
;
2120 if (s1
->float_abi
== ARM_HARD_FLOAT
)
2121 ehdr
.e_flags
|= EF_ARM_VFP_FLOAT
;
2123 ehdr
.e_flags
|= EF_ARM_SOFT_FLOAT
;
2125 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_ARM
;
2130 case TCC_OUTPUT_EXE
:
2131 ehdr
.e_type
= ET_EXEC
;
2132 ehdr
.e_entry
= get_elf_sym_addr(s1
, "_start", 1);
2134 case TCC_OUTPUT_DLL
:
2135 ehdr
.e_type
= ET_DYN
;
2136 ehdr
.e_entry
= text_section
->sh_addr
; /* XXX: is it correct ? */
2138 case TCC_OUTPUT_OBJ
:
2139 ehdr
.e_type
= ET_REL
;
2142 ehdr
.e_machine
= EM_TCC_TARGET
;
2143 ehdr
.e_version
= EV_CURRENT
;
2144 ehdr
.e_shoff
= file_offset
;
2145 ehdr
.e_ehsize
= sizeof(ElfW(Ehdr
));
2146 ehdr
.e_shentsize
= sizeof(ElfW(Shdr
));
2147 ehdr
.e_shnum
= shnum
;
2148 ehdr
.e_shstrndx
= shnum
- 1;
2150 fwrite(&ehdr
, 1, sizeof(ElfW(Ehdr
)), f
);
2151 fwrite(phdr
, 1, phnum
* sizeof(ElfW(Phdr
)), f
);
2152 offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
2154 sort_syms(s1
, symtab_section
);
2155 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2156 s
= s1
->sections
[sec_order
[i
]];
2157 if (s
->sh_type
!= SHT_NOBITS
) {
2158 if (s
->sh_type
== SHT_DYNSYM
)
2159 patch_dynsym_undef(s1
, s
);
2160 while (offset
< s
->sh_offset
) {
2165 fwrite(s
->data
, 1, size
, f
);
2170 /* output section headers */
2171 while (offset
< ehdr
.e_shoff
) {
2176 for(i
= 0; i
< s1
->nb_sections
; i
++) {
2178 memset(sh
, 0, sizeof(ElfW(Shdr
)));
2179 s
= s1
->sections
[i
];
2181 sh
->sh_name
= s
->sh_name
;
2182 sh
->sh_type
= s
->sh_type
;
2183 sh
->sh_flags
= s
->sh_flags
;
2184 sh
->sh_entsize
= s
->sh_entsize
;
2185 sh
->sh_info
= s
->sh_info
;
2187 sh
->sh_link
= s
->link
->sh_num
;
2188 sh
->sh_addralign
= s
->sh_addralign
;
2189 sh
->sh_addr
= s
->sh_addr
;
2190 sh
->sh_offset
= s
->sh_offset
;
2191 sh
->sh_size
= s
->sh_size
;
2193 fwrite(sh
, 1, sizeof(ElfW(Shdr
)), f
);
2197 /* Write an elf, coff or "binary" file */
2198 static int tcc_write_elf_file(TCCState
*s1
, const char *filename
, int phnum
,
2199 ElfW(Phdr
) *phdr
, int file_offset
, int *sec_order
)
2201 int fd
, mode
, file_type
;
2204 file_type
= s1
->output_type
;
2205 if (file_type
== TCC_OUTPUT_OBJ
)
2210 fd
= open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
, mode
);
2212 tcc_error_noabort("could not write '%s'", filename
);
2215 f
= fdopen(fd
, "wb");
2217 printf("<- %s\n", filename
);
2219 #ifdef TCC_TARGET_COFF
2220 if (s1
->output_format
== TCC_OUTPUT_FORMAT_COFF
)
2221 tcc_output_coff(s1
, f
);
2224 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
)
2225 tcc_output_elf(s1
, f
, phnum
, phdr
, file_offset
, sec_order
);
2227 tcc_output_binary(s1
, f
, sec_order
);
2233 /* Output an elf, coff or binary file */
2234 /* XXX: suppress unneeded sections */
2235 static int elf_output_file(TCCState
*s1
, const char *filename
)
2237 int i
, ret
, phnum
, shnum
, file_type
, file_offset
, *sec_order
;
2238 struct dyn_inf dyninf
;
2241 Section
*strsec
, *interp
, *dynamic
, *dynstr
;
2243 file_type
= s1
->output_type
;
2246 /* if linking, also link in runtime libraries (libc, libgcc, etc.) */
2247 if (file_type
!= TCC_OUTPUT_OBJ
) {
2248 tcc_add_runtime(s1
);
2253 interp
= dynamic
= dynstr
= NULL
; /* avoid warning */
2254 dyninf
.dyn_rel_off
= 0; /* avoid warning */
2256 if (file_type
!= TCC_OUTPUT_OBJ
) {
2257 relocate_common_syms();
2259 tcc_add_linker_symbols(s1
);
2261 if (!s1
->static_link
) {
2262 if (file_type
== TCC_OUTPUT_EXE
) {
2264 /* allow override the dynamic loader */
2265 const char *elfint
= getenv("LD_SO");
2267 elfint
= DEFAULT_ELFINTERP(s1
);
2268 /* add interpreter section only if executable */
2269 interp
= new_section(s1
, ".interp", SHT_PROGBITS
, SHF_ALLOC
);
2270 interp
->sh_addralign
= 1;
2271 ptr
= section_ptr_add(interp
, 1 + strlen(elfint
));
2272 strcpy(ptr
, elfint
);
2275 /* add dynamic symbol table */
2276 s1
->dynsym
= new_symtab(s1
, ".dynsym", SHT_DYNSYM
, SHF_ALLOC
,
2278 ".hash", SHF_ALLOC
);
2279 dynstr
= s1
->dynsym
->link
;
2281 /* add dynamic section */
2282 dynamic
= new_section(s1
, ".dynamic", SHT_DYNAMIC
,
2283 SHF_ALLOC
| SHF_WRITE
);
2284 dynamic
->link
= dynstr
;
2285 dynamic
->sh_entsize
= sizeof(ElfW(Dyn
));
2288 s1
->plt
= new_section(s1
, ".plt", SHT_PROGBITS
,
2289 SHF_ALLOC
| SHF_EXECINSTR
);
2290 s1
->plt
->sh_entsize
= 4;
2294 if (file_type
== TCC_OUTPUT_EXE
) {
2295 bind_exe_dynsyms(s1
);
2297 if (s1
->nb_errors
) {
2302 bind_libs_dynsyms(s1
);
2303 } else /* shared library case: simply export all global symbols */
2304 export_global_syms(s1
);
2306 build_got_entries(s1
);
2308 /* add a list of needed dlls */
2309 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
2310 DLLReference
*dllref
= s1
->loaded_dlls
[i
];
2311 if (dllref
->level
== 0)
2312 put_dt(dynamic
, DT_NEEDED
, put_elf_str(dynstr
, dllref
->name
));
2316 put_dt(dynamic
, DT_RPATH
, put_elf_str(dynstr
, s1
->rpath
));
2318 /* XXX: currently, since we do not handle PIC code, we
2319 must relocate the readonly segments */
2320 if (file_type
== TCC_OUTPUT_DLL
) {
2322 put_dt(dynamic
, DT_SONAME
, put_elf_str(dynstr
, s1
->soname
));
2323 put_dt(dynamic
, DT_TEXTREL
, 0);
2327 put_dt(dynamic
, DT_SYMBOLIC
, 0);
2329 /* add necessary space for other entries */
2330 dyninf
.dyn_rel_off
= dynamic
->data_offset
;
2331 dynamic
->data_offset
+= sizeof(ElfW(Dyn
)) * EXTRA_RELITEMS
;
2333 /* still need to build got entries in case of static link */
2334 build_got_entries(s1
);
2338 /* we add a section for symbols */
2339 strsec
= new_section(s1
, ".shstrtab", SHT_STRTAB
, 0);
2340 put_elf_str(strsec
, "");
2342 /* compute number of sections */
2343 shnum
= s1
->nb_sections
;
2345 /* this array is used to reorder sections in the output file */
2346 sec_order
= tcc_malloc(sizeof(int) * shnum
);
2349 /* compute number of program headers */
2352 case TCC_OUTPUT_OBJ
:
2355 case TCC_OUTPUT_EXE
:
2356 if (!s1
->static_link
)
2357 phnum
= 4 + HAVE_PHDR
;
2361 case TCC_OUTPUT_DLL
:
2366 /* Allocate strings for section names */
2367 alloc_sec_names(s1
, file_type
, strsec
);
2369 /* allocate program segment headers */
2370 phdr
= tcc_mallocz(phnum
* sizeof(ElfW(Phdr
)));
2372 /* compute section to program header mapping */
2373 file_offset
= layout_sections(s1
, phdr
, phnum
, interp
, &dyninf
, sec_order
);
2375 /* Fill remaining program header and finalize relocation related to dynamic
2378 fill_unloadable_phdr(phdr
, phnum
, interp
, dynamic
);
2380 dyninf
.dynamic
= dynamic
;
2381 dyninf
.dynstr
= dynstr
;
2383 fill_dynamic(s1
, &dyninf
);
2385 /* put in GOT the dynamic section address and relocate PLT */
2386 put32(s1
->got
->data
, dynamic
->sh_addr
);
2387 if (file_type
== TCC_OUTPUT_EXE
2388 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2389 || file_type
== TCC_OUTPUT_DLL
2394 /* relocate symbols in .dynsym now that final addresses are known */
2395 for_each_elem(s1
->dynsym
, 1, sym
, ElfW(Sym
)) {
2396 /* relocate to PLT if symbol corresponds to a PLT entry */
2397 if (sym
->st_shndx
== SHN_UNDEF
) {
2399 sym
->st_value
+= s1
->plt
->sh_addr
;
2400 } else if (sym
->st_shndx
< SHN_LORESERVE
) {
2401 /* do symbol relocation */
2402 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
2408 /* if building executable or DLL, then relocate each section
2409 except the GOT which is already relocated */
2410 if (file_type
!= TCC_OUTPUT_OBJ
) {
2411 ret
= final_sections_reloc(s1
);
2416 /* Perform relocation to GOT or PLTÂ entries */
2417 if (file_type
== TCC_OUTPUT_EXE
&& s1
->static_link
)
2420 /* Create the ELF file with name 'filename' */
2421 ret
= tcc_write_elf_file(s1
, filename
, phnum
, phdr
, file_offset
, sec_order
);
2423 tcc_free(s1
->symtab_to_dynsym
);
2424 tcc_free(sec_order
);
2426 tcc_free(s1
->sym_attrs
);
2430 LIBTCCAPI
int tcc_output_file(TCCState
*s
, const char *filename
)
2433 #ifdef TCC_TARGET_PE
2434 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
2435 ret
= pe_output_file(s
, filename
);
2438 ret
= elf_output_file(s
, filename
);
2442 static void *load_data(int fd
, unsigned long file_offset
, unsigned long size
)
2446 data
= tcc_malloc(size
);
2447 lseek(fd
, file_offset
, SEEK_SET
);
2448 read(fd
, data
, size
);
2452 typedef struct SectionMergeInfo
{
2453 Section
*s
; /* corresponding existing section */
2454 unsigned long offset
; /* offset of the new section in the existing section */
2455 uint8_t new_section
; /* true if section 's' was added */
2456 uint8_t link_once
; /* true if link once section */
2459 /* load an object file and merge it with current files */
2460 /* XXX: handle correctly stab (debug) info */
2461 ST_FUNC
int tcc_load_object_file(TCCState
*s1
,
2462 int fd
, unsigned long file_offset
)
2465 ElfW(Shdr
) *shdr
, *sh
;
2466 int size
, i
, j
, offset
, offseti
, nb_syms
, sym_index
, ret
;
2467 unsigned char *strsec
, *strtab
;
2468 int *old_to_new_syms
;
2469 char *sh_name
, *name
;
2470 SectionMergeInfo
*sm_table
, *sm
;
2471 ElfW(Sym
) *sym
, *symtab
;
2478 stab_index
= stabstr_index
= 0;
2480 if (read(fd
, &ehdr
, sizeof(ehdr
)) != sizeof(ehdr
))
2482 if (ehdr
.e_ident
[0] != ELFMAG0
||
2483 ehdr
.e_ident
[1] != ELFMAG1
||
2484 ehdr
.e_ident
[2] != ELFMAG2
||
2485 ehdr
.e_ident
[3] != ELFMAG3
)
2487 /* test if object file */
2488 if (ehdr
.e_type
!= ET_REL
)
2490 /* test CPU specific stuff */
2491 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2492 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2494 tcc_error_noabort("invalid object file");
2498 shdr
= load_data(fd
, file_offset
+ ehdr
.e_shoff
,
2499 sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2500 sm_table
= tcc_mallocz(sizeof(SectionMergeInfo
) * ehdr
.e_shnum
);
2502 /* load section names */
2503 sh
= &shdr
[ehdr
.e_shstrndx
];
2504 strsec
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2506 /* load symtab and strtab */
2507 old_to_new_syms
= NULL
;
2511 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2513 if (sh
->sh_type
== SHT_SYMTAB
) {
2515 tcc_error_noabort("object must contain only one symtab");
2520 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2521 symtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2522 sm_table
[i
].s
= symtab_section
;
2524 /* now load strtab */
2525 sh
= &shdr
[sh
->sh_link
];
2526 strtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2530 /* now examine each section and try to merge its content with the
2532 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2533 /* no need to examine section name strtab */
2534 if (i
== ehdr
.e_shstrndx
)
2537 sh_name
= (char *) strsec
+ sh
->sh_name
;
2538 /* ignore sections types we do not handle */
2539 if (sh
->sh_type
!= SHT_PROGBITS
&&
2540 sh
->sh_type
!= SHT_RELX
&&
2542 sh
->sh_type
!= SHT_ARM_EXIDX
&&
2544 sh
->sh_type
!= SHT_NOBITS
&&
2545 sh
->sh_type
!= SHT_PREINIT_ARRAY
&&
2546 sh
->sh_type
!= SHT_INIT_ARRAY
&&
2547 sh
->sh_type
!= SHT_FINI_ARRAY
&&
2548 strcmp(sh_name
, ".stabstr")
2551 if (sh
->sh_addralign
< 1)
2552 sh
->sh_addralign
= 1;
2553 /* find corresponding section, if any */
2554 for(j
= 1; j
< s1
->nb_sections
;j
++) {
2555 s
= s1
->sections
[j
];
2556 if (!strcmp(s
->name
, sh_name
)) {
2557 if (!strncmp(sh_name
, ".gnu.linkonce",
2558 sizeof(".gnu.linkonce") - 1)) {
2559 /* if a 'linkonce' section is already present, we
2560 do not add it again. It is a little tricky as
2561 symbols can still be defined in
2563 sm_table
[i
].link_once
= 1;
2570 /* not found: create new section */
2571 s
= new_section(s1
, sh_name
, sh
->sh_type
, sh
->sh_flags
);
2572 /* take as much info as possible from the section. sh_link and
2573 sh_info will be updated later */
2574 s
->sh_addralign
= sh
->sh_addralign
;
2575 s
->sh_entsize
= sh
->sh_entsize
;
2576 sm_table
[i
].new_section
= 1;
2578 if (sh
->sh_type
!= s
->sh_type
) {
2579 tcc_error_noabort("invalid section type");
2583 /* align start of section */
2584 offset
= s
->data_offset
;
2586 if (0 == strcmp(sh_name
, ".stab")) {
2590 if (0 == strcmp(sh_name
, ".stabstr")) {
2595 size
= sh
->sh_addralign
- 1;
2596 offset
= (offset
+ size
) & ~size
;
2597 if (sh
->sh_addralign
> s
->sh_addralign
)
2598 s
->sh_addralign
= sh
->sh_addralign
;
2599 s
->data_offset
= offset
;
2601 sm_table
[i
].offset
= offset
;
2603 /* concatenate sections */
2605 if (sh
->sh_type
!= SHT_NOBITS
) {
2607 lseek(fd
, file_offset
+ sh
->sh_offset
, SEEK_SET
);
2608 ptr
= section_ptr_add(s
, size
);
2609 read(fd
, ptr
, size
);
2611 s
->data_offset
+= size
;
2616 /* gr relocate stab strings */
2617 if (stab_index
&& stabstr_index
) {
2620 s
= sm_table
[stab_index
].s
;
2621 a
= (Stab_Sym
*)(s
->data
+ sm_table
[stab_index
].offset
);
2622 b
= (Stab_Sym
*)(s
->data
+ s
->data_offset
);
2623 o
= sm_table
[stabstr_index
].offset
;
2625 a
->n_strx
+= o
, a
++;
2628 /* second short pass to update sh_link and sh_info fields of new
2630 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2632 if (!s
|| !sm_table
[i
].new_section
)
2635 if (sh
->sh_link
> 0)
2636 s
->link
= sm_table
[sh
->sh_link
].s
;
2637 if (sh
->sh_type
== SHT_RELX
) {
2638 s
->sh_info
= sm_table
[sh
->sh_info
].s
->sh_num
;
2639 /* update backward link */
2640 s1
->sections
[s
->sh_info
]->reloc
= s
;
2645 /* resolve symbols */
2646 old_to_new_syms
= tcc_mallocz(nb_syms
* sizeof(int));
2649 for(i
= 1; i
< nb_syms
; i
++, sym
++) {
2650 if (sym
->st_shndx
!= SHN_UNDEF
&&
2651 sym
->st_shndx
< SHN_LORESERVE
) {
2652 sm
= &sm_table
[sym
->st_shndx
];
2653 if (sm
->link_once
) {
2654 /* if a symbol is in a link once section, we use the
2655 already defined symbol. It is very important to get
2656 correct relocations */
2657 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
2658 name
= (char *) strtab
+ sym
->st_name
;
2659 sym_index
= find_elf_sym(symtab_section
, name
);
2661 old_to_new_syms
[i
] = sym_index
;
2665 /* if no corresponding section added, no need to add symbol */
2668 /* convert section number */
2669 sym
->st_shndx
= sm
->s
->sh_num
;
2671 sym
->st_value
+= sm
->offset
;
2674 name
= (char *) strtab
+ sym
->st_name
;
2675 sym_index
= add_elf_sym(symtab_section
, sym
->st_value
, sym
->st_size
,
2676 sym
->st_info
, sym
->st_other
,
2677 sym
->st_shndx
, name
);
2678 old_to_new_syms
[i
] = sym_index
;
2681 /* third pass to patch relocation entries */
2682 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2687 offset
= sm_table
[i
].offset
;
2688 switch(s
->sh_type
) {
2690 /* take relocation offset information */
2691 offseti
= sm_table
[sh
->sh_info
].offset
;
2692 for_each_elem(s
, (offset
/ sizeof(*rel
)), rel
, ElfW_Rel
) {
2695 /* convert symbol index */
2696 type
= ELFW(R_TYPE
)(rel
->r_info
);
2697 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
2698 /* NOTE: only one symtab assumed */
2699 if (sym_index
>= nb_syms
)
2701 sym_index
= old_to_new_syms
[sym_index
];
2702 /* ignore link_once in rel section. */
2703 if (!sym_index
&& !sm
->link_once
2704 #ifdef TCC_TARGET_ARM
2705 && type
!= R_ARM_V4BX
2709 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2710 i
, strsec
+ sh
->sh_name
, rel
->r_offset
);
2713 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
2714 /* offset the relocation offset */
2715 rel
->r_offset
+= offseti
;
2716 #ifdef TCC_TARGET_ARM
2717 /* Jumps and branches from a Thumb code to a PLT entry need
2718 special handling since PLT entries are ARM code.
2719 Unconditional bl instructions referencing PLT entries are
2720 handled by converting these instructions into blx
2721 instructions. Other case of instructions referencing a PLT
2722 entry require to add a Thumb stub before the PLT entry to
2723 switch to ARM mode. We set bit plt_thumb_stub of the
2724 attribute of a symbol to indicate such a case. */
2725 if (type
== R_ARM_THM_JUMP24
)
2726 alloc_sym_attr(s1
, sym_index
)->plt_thumb_stub
= 1;
2739 tcc_free(old_to_new_syms
);
2746 typedef struct ArchiveHeader
{
2747 char ar_name
[16]; /* name of this member */
2748 char ar_date
[12]; /* file mtime */
2749 char ar_uid
[6]; /* owner uid; printed as decimal */
2750 char ar_gid
[6]; /* owner gid; printed as decimal */
2751 char ar_mode
[8]; /* file mode, printed as octal */
2752 char ar_size
[10]; /* file size, printed as decimal */
2753 char ar_fmag
[2]; /* should contain ARFMAG */
2756 static int get_be32(const uint8_t *b
)
2758 return b
[3] | (b
[2] << 8) | (b
[1] << 16) | (b
[0] << 24);
2761 /* load only the objects which resolve undefined symbols */
2762 static int tcc_load_alacarte(TCCState
*s1
, int fd
, int size
)
2764 int i
, bound
, nsyms
, sym_index
, off
, ret
;
2766 const char *ar_names
, *p
;
2767 const uint8_t *ar_index
;
2770 data
= tcc_malloc(size
);
2771 if (read(fd
, data
, size
) != size
)
2773 nsyms
= get_be32(data
);
2774 ar_index
= data
+ 4;
2775 ar_names
= (char *) ar_index
+ nsyms
* 4;
2779 for(p
= ar_names
, i
= 0; i
< nsyms
; i
++, p
+= strlen(p
)+1) {
2780 sym_index
= find_elf_sym(symtab_section
, p
);
2782 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
2783 if(sym
->st_shndx
== SHN_UNDEF
) {
2784 off
= get_be32(ar_index
+ i
* 4) + sizeof(ArchiveHeader
);
2786 lseek(fd
, off
, SEEK_SET
);
2787 if(tcc_load_object_file(s1
, fd
, off
) < 0) {
2802 /* load a '.a' file */
2803 ST_FUNC
int tcc_load_archive(TCCState
*s1
, int fd
)
2810 unsigned long file_offset
;
2812 /* skip magic which was already checked */
2813 read(fd
, magic
, sizeof(magic
));
2816 len
= read(fd
, &hdr
, sizeof(hdr
));
2819 if (len
!= sizeof(hdr
)) {
2820 tcc_error_noabort("invalid archive");
2823 memcpy(ar_size
, hdr
.ar_size
, sizeof(hdr
.ar_size
));
2824 ar_size
[sizeof(hdr
.ar_size
)] = '\0';
2825 size
= strtol(ar_size
, NULL
, 0);
2826 memcpy(ar_name
, hdr
.ar_name
, sizeof(hdr
.ar_name
));
2827 for(i
= sizeof(hdr
.ar_name
) - 1; i
>= 0; i
--) {
2828 if (ar_name
[i
] != ' ')
2831 ar_name
[i
+ 1] = '\0';
2832 file_offset
= lseek(fd
, 0, SEEK_CUR
);
2834 size
= (size
+ 1) & ~1;
2835 if (!strcmp(ar_name
, "/")) {
2836 /* coff symbol table : we handle it */
2837 if(s1
->alacarte_link
)
2838 return tcc_load_alacarte(s1
, fd
, size
);
2839 } else if (!strcmp(ar_name
, "//") ||
2840 !strcmp(ar_name
, "__.SYMDEF") ||
2841 !strcmp(ar_name
, "__.SYMDEF/") ||
2842 !strcmp(ar_name
, "ARFILENAMES/")) {
2843 /* skip symbol table or archive names */
2845 if (tcc_load_object_file(s1
, fd
, file_offset
) < 0)
2848 lseek(fd
, file_offset
+ size
, SEEK_SET
);
2853 #ifndef TCC_TARGET_PE
2854 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2855 is referenced by the user (so it should be added as DT_NEEDED in
2856 the generated ELF file) */
2857 ST_FUNC
int tcc_load_dll(TCCState
*s1
, int fd
, const char *filename
, int level
)
2860 ElfW(Shdr
) *shdr
, *sh
, *sh1
;
2861 int i
, j
, nb_syms
, nb_dts
, sym_bind
, ret
;
2862 ElfW(Sym
) *sym
, *dynsym
;
2863 ElfW(Dyn
) *dt
, *dynamic
;
2864 unsigned char *dynstr
;
2865 const char *name
, *soname
;
2866 DLLReference
*dllref
;
2868 read(fd
, &ehdr
, sizeof(ehdr
));
2870 /* test CPU specific stuff */
2871 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2872 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2873 tcc_error_noabort("bad architecture");
2878 shdr
= load_data(fd
, ehdr
.e_shoff
, sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2880 /* load dynamic section and dynamic symbols */
2884 dynsym
= NULL
; /* avoid warning */
2885 dynstr
= NULL
; /* avoid warning */
2886 for(i
= 0, sh
= shdr
; i
< ehdr
.e_shnum
; i
++, sh
++) {
2887 switch(sh
->sh_type
) {
2889 nb_dts
= sh
->sh_size
/ sizeof(ElfW(Dyn
));
2890 dynamic
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2893 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2894 dynsym
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2895 sh1
= &shdr
[sh
->sh_link
];
2896 dynstr
= load_data(fd
, sh1
->sh_offset
, sh1
->sh_size
);
2903 /* compute the real library name */
2904 soname
= tcc_basename(filename
);
2906 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2907 if (dt
->d_tag
== DT_SONAME
) {
2908 soname
= (char *) dynstr
+ dt
->d_un
.d_val
;
2912 /* if the dll is already loaded, do not load it */
2913 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
2914 dllref
= s1
->loaded_dlls
[i
];
2915 if (!strcmp(soname
, dllref
->name
)) {
2916 /* but update level if needed */
2917 if (level
< dllref
->level
)
2918 dllref
->level
= level
;
2924 /* add the dll and its level */
2925 dllref
= tcc_mallocz(sizeof(DLLReference
) + strlen(soname
));
2926 dllref
->level
= level
;
2927 strcpy(dllref
->name
, soname
);
2928 dynarray_add((void ***)&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
, dllref
);
2930 /* add dynamic symbols in dynsym_section */
2931 for(i
= 1, sym
= dynsym
+ 1; i
< nb_syms
; i
++, sym
++) {
2932 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
2933 if (sym_bind
== STB_LOCAL
)
2935 name
= (char *) dynstr
+ sym
->st_name
;
2936 add_elf_sym(s1
->dynsymtab_section
, sym
->st_value
, sym
->st_size
,
2937 sym
->st_info
, sym
->st_other
, sym
->st_shndx
, name
);
2940 /* load all referenced DLLs */
2941 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2944 name
= (char *) dynstr
+ dt
->d_un
.d_val
;
2945 for(j
= 0; j
< s1
->nb_loaded_dlls
; j
++) {
2946 dllref
= s1
->loaded_dlls
[j
];
2947 if (!strcmp(name
, dllref
->name
))
2948 goto already_loaded
;
2950 if (tcc_add_dll(s1
, name
, AFF_REFERENCED_DLL
) < 0) {
2951 tcc_error_noabort("referenced dll '%s' not found", name
);
2968 #define LD_TOK_NAME 256
2969 #define LD_TOK_EOF (-1)
2971 /* return next ld script token */
2972 static int ld_next(TCCState
*s1
, char *name
, int name_size
)
2990 file
->buf_ptr
= parse_comment(file
->buf_ptr
);
2991 ch
= file
->buf_ptr
[0];
2999 /* case 'a' ... 'z': */
3026 /* case 'A' ... 'z': */
3061 if (!((ch
>= 'a' && ch
<= 'z') ||
3062 (ch
>= 'A' && ch
<= 'Z') ||
3063 (ch
>= '0' && ch
<= '9') ||
3064 strchr("/.-_+=$:\\,~", ch
)))
3066 if ((q
- name
) < name_size
- 1) {
3085 static int ld_add_file(TCCState
*s1
, const char filename
[])
3089 ret
= tcc_add_file_internal(s1
, filename
, 0);
3091 ret
= tcc_add_dll(s1
, filename
, 0);
3095 static inline int new_undef_syms(void)
3098 ret
= new_undef_sym
;
3103 static int ld_add_file_list(TCCState
*s1
, const char *cmd
, int as_needed
)
3105 char filename
[1024], libname
[1024];
3106 int t
, group
, nblibs
= 0, ret
= 0;
3109 group
= !strcmp(cmd
, "GROUP");
3112 t
= ld_next(s1
, filename
, sizeof(filename
));
3115 t
= ld_next(s1
, filename
, sizeof(filename
));
3118 if (t
== LD_TOK_EOF
) {
3119 tcc_error_noabort("unexpected end of file");
3121 goto lib_parse_error
;
3122 } else if (t
== ')') {
3124 } else if (t
== '-') {
3125 t
= ld_next(s1
, filename
, sizeof(filename
));
3126 if ((t
!= LD_TOK_NAME
) || (filename
[0] != 'l')) {
3127 tcc_error_noabort("library name expected");
3129 goto lib_parse_error
;
3131 pstrcpy(libname
, sizeof libname
, &filename
[1]);
3132 if (s1
->static_link
) {
3133 snprintf(filename
, sizeof filename
, "lib%s.a", libname
);
3135 snprintf(filename
, sizeof filename
, "lib%s.so", libname
);
3137 } else if (t
!= LD_TOK_NAME
) {
3138 tcc_error_noabort("filename expected");
3140 goto lib_parse_error
;
3142 if (!strcmp(filename
, "AS_NEEDED")) {
3143 ret
= ld_add_file_list(s1
, cmd
, 1);
3145 goto lib_parse_error
;
3147 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3149 ret
= ld_add_file(s1
, filename
);
3151 goto lib_parse_error
;
3153 /* Add the filename *and* the libname to avoid future conversions */
3154 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(filename
));
3155 if (libname
[0] != '\0')
3156 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(libname
));
3160 t
= ld_next(s1
, filename
, sizeof(filename
));
3162 t
= ld_next(s1
, filename
, sizeof(filename
));
3165 if (group
&& !as_needed
) {
3166 while (new_undef_syms()) {
3169 for (i
= 0; i
< nblibs
; i
++)
3170 ld_add_file(s1
, libs
[i
]);
3174 dynarray_reset(&libs
, &nblibs
);
3178 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3180 ST_FUNC
int tcc_load_ldscript(TCCState
*s1
)
3183 char filename
[1024];
3186 ch
= file
->buf_ptr
[0];
3189 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3190 if (t
== LD_TOK_EOF
)
3192 else if (t
!= LD_TOK_NAME
)
3194 if (!strcmp(cmd
, "INPUT") ||
3195 !strcmp(cmd
, "GROUP")) {
3196 ret
= ld_add_file_list(s1
, cmd
, 0);
3199 } else if (!strcmp(cmd
, "OUTPUT_FORMAT") ||
3200 !strcmp(cmd
, "TARGET")) {
3201 /* ignore some commands */
3202 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3206 t
= ld_next(s1
, filename
, sizeof(filename
));
3207 if (t
== LD_TOK_EOF
) {
3208 tcc_error_noabort("unexpected end of file");
3210 } else if (t
== ')') {
3220 #endif /* !TCC_TARGET_PE */