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 /* Define this to get some debug output during relocation processing. */
26 /* XXX: avoid static variable */
27 static int new_undef_sym
= 0; /* Is there a new undefined sym since last new_undef_sym() */
29 ST_FUNC
int put_elf_str(Section
*s
, const char *sym
)
34 len
= strlen(sym
) + 1;
35 offset
= s
->data_offset
;
36 ptr
= section_ptr_add(s
, len
);
37 memcpy(ptr
, sym
, len
);
41 /* elf symbol hashing function */
42 static unsigned long elf_hash(const unsigned char *name
)
44 unsigned long h
= 0, g
;
47 h
= (h
<< 4) + *name
++;
56 /* rebuild hash table of section s */
57 /* NOTE: we do factorize the hash table code to go faster */
58 static void rebuild_hash(Section
*s
, unsigned int nb_buckets
)
61 int *ptr
, *hash
, nb_syms
, sym_index
, h
;
62 unsigned char *strtab
;
64 strtab
= s
->link
->data
;
65 nb_syms
= s
->data_offset
/ sizeof(ElfW(Sym
));
67 s
->hash
->data_offset
= 0;
68 ptr
= section_ptr_add(s
->hash
, (2 + nb_buckets
+ nb_syms
) * sizeof(int));
73 memset(hash
, 0, (nb_buckets
+ 1) * sizeof(int));
74 ptr
+= nb_buckets
+ 1;
76 sym
= (ElfW(Sym
) *)s
->data
+ 1;
77 for(sym_index
= 1; sym_index
< nb_syms
; sym_index
++) {
78 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
79 h
= elf_hash(strtab
+ sym
->st_name
) % nb_buckets
;
90 /* return the symbol number */
91 ST_FUNC
int put_elf_sym(Section
*s
, addr_t value
, unsigned long size
,
92 int info
, int other
, int shndx
, const char *name
)
94 int name_offset
, sym_index
;
99 sym
= section_ptr_add(s
, sizeof(ElfW(Sym
)));
101 name_offset
= put_elf_str(s
->link
, name
);
104 /* XXX: endianness */
105 sym
->st_name
= name_offset
;
106 sym
->st_value
= value
;
109 sym
->st_other
= other
;
110 sym
->st_shndx
= shndx
;
111 sym_index
= sym
- (ElfW(Sym
) *)s
->data
;
115 ptr
= section_ptr_add(hs
, sizeof(int));
116 base
= (int *)hs
->data
;
117 /* only add global or weak symbols */
118 if (ELFW(ST_BIND
)(info
) != STB_LOCAL
) {
119 /* add another hashing entry */
121 h
= elf_hash((unsigned char *) name
) % nbuckets
;
123 base
[2 + h
] = sym_index
;
125 /* we resize the hash table */
126 hs
->nb_hashed_syms
++;
127 if (hs
->nb_hashed_syms
> 2 * nbuckets
) {
128 rebuild_hash(s
, 2 * nbuckets
);
138 /* find global ELF symbol 'name' and return its index. Return 0 if not
140 ST_FUNC
int find_elf_sym(Section
*s
, const char *name
)
144 int nbuckets
, sym_index
, h
;
150 nbuckets
= ((int *)hs
->data
)[0];
151 h
= elf_hash((unsigned char *) name
) % nbuckets
;
152 sym_index
= ((int *)hs
->data
)[2 + h
];
153 while (sym_index
!= 0) {
154 sym
= &((ElfW(Sym
) *)s
->data
)[sym_index
];
155 name1
= (char *) s
->link
->data
+ sym
->st_name
;
156 if (!strcmp(name
, name1
))
158 sym_index
= ((int *)hs
->data
)[2 + nbuckets
+ sym_index
];
163 /* return elf symbol value, signal error if 'err' is nonzero */
164 ST_FUNC addr_t
get_elf_sym_addr(TCCState
*s
, const char *name
, int err
)
169 sym_index
= find_elf_sym(s
->symtab
, name
);
170 sym
= &((ElfW(Sym
) *)s
->symtab
->data
)[sym_index
];
171 if (!sym_index
|| sym
->st_shndx
== SHN_UNDEF
) {
173 tcc_error("%s not defined", name
);
176 return sym
->st_value
;
179 /* return elf symbol value */
180 LIBTCCAPI
void *tcc_get_symbol(TCCState
*s
, const char *name
)
182 return (void*)(uintptr_t)get_elf_sym_addr(s
, name
, 0);
185 #if defined TCC_IS_NATIVE || defined TCC_TARGET_PE
186 /* return elf symbol value or error */
187 ST_FUNC
void* tcc_get_symbol_err(TCCState
*s
, const char *name
)
189 return (void*)(uintptr_t)get_elf_sym_addr(s
, name
, 1);
193 /* add an elf symbol : check if it is already defined and patch
194 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
195 ST_FUNC
int add_elf_sym(Section
*s
, addr_t value
, unsigned long size
,
196 int info
, int other
, int sh_num
, const char *name
)
199 int sym_bind
, sym_index
, sym_type
, esym_bind
;
200 unsigned char sym_vis
, esym_vis
, new_vis
;
202 sym_bind
= ELFW(ST_BIND
)(info
);
203 sym_type
= ELFW(ST_TYPE
)(info
);
204 sym_vis
= ELFW(ST_VISIBILITY
)(other
);
206 if (sym_bind
!= STB_LOCAL
) {
207 /* we search global or weak symbols */
208 sym_index
= find_elf_sym(s
, name
);
211 esym
= &((ElfW(Sym
) *)s
->data
)[sym_index
];
212 if (esym
->st_shndx
!= SHN_UNDEF
) {
213 esym_bind
= ELFW(ST_BIND
)(esym
->st_info
);
214 /* propagate the most constraining visibility */
215 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
216 esym_vis
= ELFW(ST_VISIBILITY
)(esym
->st_other
);
217 if (esym_vis
== STV_DEFAULT
) {
219 } else if (sym_vis
== STV_DEFAULT
) {
222 new_vis
= (esym_vis
< sym_vis
) ? esym_vis
: sym_vis
;
224 esym
->st_other
= (esym
->st_other
& ~ELFW(ST_VISIBILITY
)(-1))
226 other
= esym
->st_other
; /* in case we have to patch esym */
227 if (sh_num
== SHN_UNDEF
) {
228 /* ignore adding of undefined symbol if the
229 corresponding symbol is already defined */
230 } else if (sym_bind
== STB_GLOBAL
&& esym_bind
== STB_WEAK
) {
231 /* global overrides weak, so patch */
233 } else if (sym_bind
== STB_WEAK
&& esym_bind
== STB_GLOBAL
) {
234 /* weak is ignored if already global */
235 } else if (sym_bind
== STB_WEAK
&& esym_bind
== STB_WEAK
) {
236 /* keep first-found weak definition, ignore subsequents */
237 } else if (sym_vis
== STV_HIDDEN
|| sym_vis
== STV_INTERNAL
) {
238 /* ignore hidden symbols after */
239 } else if (esym
->st_shndx
== SHN_COMMON
240 && (sh_num
< SHN_LORESERVE
|| sh_num
== SHN_COMMON
)) {
241 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
242 No idea if this is the correct solution ... */
244 } else if (s
== tcc_state
->dynsymtab_section
) {
245 /* we accept that two DLL define the same symbol */
248 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
249 sym_bind
, sh_num
, new_vis
, esym_bind
, esym
->st_shndx
, esym_vis
);
251 tcc_error_noabort("'%s' defined twice", name
);
255 esym
->st_info
= ELFW(ST_INFO
)(sym_bind
, sym_type
);
256 esym
->st_shndx
= sh_num
;
258 esym
->st_value
= value
;
259 esym
->st_size
= size
;
260 esym
->st_other
= other
;
264 sym_index
= put_elf_sym(s
, value
, size
,
265 ELFW(ST_INFO
)(sym_bind
, sym_type
), other
,
272 ST_FUNC
void put_elf_reloca(Section
*symtab
, Section
*s
, unsigned long offset
,
273 int type
, int symbol
, unsigned long addend
)
281 /* if no relocation section, create it */
282 snprintf(buf
, sizeof(buf
), REL_SECTION_FMT
, s
->name
);
283 /* if the symtab is allocated, then we consider the relocation
285 sr
= new_section(tcc_state
, buf
, SHT_RELX
, symtab
->sh_flags
);
286 sr
->sh_entsize
= sizeof(ElfW_Rel
);
288 sr
->sh_info
= s
->sh_num
;
291 rel
= section_ptr_add(sr
, sizeof(ElfW_Rel
));
292 rel
->r_offset
= offset
;
293 rel
->r_info
= ELFW(R_INFO
)(symbol
, type
);
294 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
295 rel
->r_addend
= addend
;
298 tcc_error("non-zero addend on REL architecture");
302 ST_FUNC
void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
303 int type
, int symbol
)
305 put_elf_reloca(symtab
, s
, offset
, type
, symbol
, 0);
308 /* put stab debug information */
310 ST_FUNC
void put_stabs(const char *str
, int type
, int other
, int desc
,
315 sym
= section_ptr_add(stab_section
, sizeof(Stab_Sym
));
317 sym
->n_strx
= put_elf_str(stabstr_section
, str
);
322 sym
->n_other
= other
;
324 sym
->n_value
= value
;
327 ST_FUNC
void put_stabs_r(const char *str
, int type
, int other
, int desc
,
328 unsigned long value
, Section
*sec
, int sym_index
)
330 put_stabs(str
, type
, other
, desc
, value
);
331 put_elf_reloc(symtab_section
, stab_section
,
332 stab_section
->data_offset
- sizeof(unsigned int),
333 R_DATA_32
, sym_index
);
336 ST_FUNC
void put_stabn(int type
, int other
, int desc
, int value
)
338 put_stabs(NULL
, type
, other
, desc
, value
);
341 ST_FUNC
void put_stabd(int type
, int other
, int desc
)
343 put_stabs(NULL
, type
, other
, desc
, 0);
346 /* Browse each elem of type <type> in section <sec> starting at elem <startoff>
347 using variable <elem> */
348 #define for_each_elem(sec, startoff, elem, type) \
349 for (elem = (type *) sec->data + startoff; \
350 elem < (type *) (sec->data + sec->data_offset); elem++)
352 /* In an ELF file symbol table, the local symbols must appear below
353 the global and weak ones. Since TCC cannot sort it while generating
354 the code, we must do it after. All the relocation tables are also
355 modified to take into account the symbol table sorting */
356 static void sort_syms(TCCState
*s1
, Section
*s
)
358 int *old_to_new_syms
;
366 nb_syms
= s
->data_offset
/ sizeof(ElfW(Sym
));
367 new_syms
= tcc_malloc(nb_syms
* sizeof(ElfW(Sym
)));
368 old_to_new_syms
= tcc_malloc(nb_syms
* sizeof(int));
370 /* first pass for local symbols */
371 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
;
380 /* save the number of local symbols in section header */
381 s
->sh_info
= q
- new_syms
;
383 /* then second pass for non local symbols */
384 p
= (ElfW(Sym
) *)s
->data
;
385 for(i
= 0; i
< nb_syms
; i
++) {
386 if (ELFW(ST_BIND
)(p
->st_info
) != STB_LOCAL
) {
387 old_to_new_syms
[i
] = q
- new_syms
;
393 /* we copy the new symbols to the old */
394 memcpy(s
->data
, new_syms
, nb_syms
* sizeof(ElfW(Sym
)));
397 /* now we modify all the relocations */
398 for(i
= 1; i
< s1
->nb_sections
; i
++) {
399 sr
= s1
->sections
[i
];
400 if (sr
->sh_type
== SHT_RELX
&& sr
->link
== s
) {
401 for_each_elem(sr
, 0, rel
, ElfW_Rel
) {
402 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
403 type
= ELFW(R_TYPE
)(rel
->r_info
);
404 sym_index
= old_to_new_syms
[sym_index
];
405 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
410 tcc_free(old_to_new_syms
);
413 /* relocate common symbols in the .bss section */
414 ST_FUNC
void relocate_common_syms(void)
417 unsigned long offset
, align
;
419 for_each_elem(symtab_section
, 1, sym
, ElfW(Sym
)) {
420 if (sym
->st_shndx
== SHN_COMMON
) {
422 align
= sym
->st_value
;
423 offset
= bss_section
->data_offset
;
424 offset
= (offset
+ align
- 1) & -align
;
425 sym
->st_value
= offset
;
426 sym
->st_shndx
= bss_section
->sh_num
;
427 offset
+= sym
->st_size
;
428 bss_section
->data_offset
= offset
;
433 /* relocate symbol table, resolve undefined symbols if do_resolve is
434 true and output error if undefined symbol. */
435 ST_FUNC
void relocate_syms(TCCState
*s1
, int do_resolve
)
437 ElfW(Sym
) *sym
, *esym
;
438 int sym_bind
, sh_num
, sym_index
;
441 for_each_elem(symtab_section
, 1, sym
, ElfW(Sym
)) {
442 sh_num
= sym
->st_shndx
;
443 if (sh_num
== SHN_UNDEF
) {
444 name
= (char *) strtab_section
->data
+ sym
->st_name
;
445 /* Use ld.so to resolve symbol for us (for tcc -run) */
447 #if defined TCC_IS_NATIVE && !defined _WIN32
449 name
= (char *) symtab_section
->link
->data
+ sym
->st_name
;
450 addr
= resolve_sym(s1
, name
);
452 sym
->st_value
= (addr_t
)addr
;
454 printf ("relocate_sym: %s -> 0x%x\n", name
, sym
->st_value
);
459 } else if (s1
->dynsym
) {
460 /* if dynamic symbol exist, then use it */
461 sym_index
= find_elf_sym(s1
->dynsym
, name
);
463 esym
= &((ElfW(Sym
) *)s1
->dynsym
->data
)[sym_index
];
464 sym
->st_value
= esym
->st_value
;
468 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
470 if (!strcmp(name
, "_fp_hw"))
472 /* only weak symbols are accepted to be undefined. Their
474 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
475 if (sym_bind
== STB_WEAK
) {
478 tcc_error_noabort("undefined symbol '%s'", name
);
480 } else if (sh_num
< SHN_LORESERVE
) {
481 /* add section base */
482 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
488 /* relocate a given section (CPU dependent) by applying the relocations
489 in the associated relocation section */
490 ST_FUNC
void relocate_section(TCCState
*s1
, Section
*s
)
492 Section
*sr
= s
->reloc
;
498 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
499 ElfW_Rel
*qrel
= (ElfW_Rel
*) sr
->data
; /* ptr to next reloc entry reused */
503 for_each_elem(sr
, 0, rel
, ElfW_Rel
) {
504 ptr
= s
->data
+ rel
->r_offset
;
506 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
507 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
509 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
510 val
+= rel
->r_addend
;
512 type
= ELFW(R_TYPE
)(rel
->r_info
);
513 addr
= s
->sh_addr
+ rel
->r_offset
;
517 #if defined(TCC_TARGET_I386)
519 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
520 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
521 qrel
->r_offset
= rel
->r_offset
;
523 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_386_32
);
527 qrel
->r_info
= ELFW(R_INFO
)(0, R_386_RELATIVE
);
534 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
536 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
538 qrel
->r_offset
= rel
->r_offset
;
539 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_386_PC32
);
544 *(int *)ptr
+= val
- addr
;
547 *(int *)ptr
+= val
- addr
;
554 *(int *)ptr
+= s1
->got
->sh_addr
- addr
;
557 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
560 /* we load the got offset */
561 *(int *)ptr
+= s1
->sym_attrs
[sym_index
].got_offset
;
564 if (s1
->output_format
!= TCC_OUTPUT_FORMAT_BINARY
) {
566 tcc_error("can only produce 16-bit binary files");
568 *(short *)ptr
+= val
;
571 if (s1
->output_format
!= TCC_OUTPUT_FORMAT_BINARY
)
573 *(short *)ptr
+= val
- addr
;
575 #elif defined(TCC_TARGET_ARM)
581 int x
, is_thumb
, is_call
, h
, blx_avail
, is_bl
, th_ko
;
582 x
= (*(int *) ptr
) & 0xffffff;
583 if (sym
->st_shndx
== SHN_UNDEF
)
584 val
= s1
->plt
->sh_addr
;
586 printf ("reloc %d: x=0x%x val=0x%x ", type
, x
, val
);
588 (*(int *)ptr
) &= 0xff000000;
592 blx_avail
= (TCC_ARM_VERSION
>= 5);
594 is_bl
= (*(unsigned *) ptr
) >> 24 == 0xeb;
595 is_call
= (type
== R_ARM_CALL
|| (type
== R_ARM_PC24
&& is_bl
));
598 printf (" newx=0x%x name=%s\n", x
,
599 (char *) symtab_section
->link
->data
+ sym
->st_name
);
602 th_ko
= (x
& 3) && (!blx_avail
|| !is_call
);
603 if (th_ko
|| x
>= 0x2000000 || x
< -0x2000000)
604 tcc_error("can't relocate value at %x,%d",addr
, type
);
607 /* Only reached if blx is avail and it is a call */
610 (*(int *)ptr
) = 0xfa << 24; /* bl -> blx */
615 /* Since these relocations only concern Thumb-2 and blx instruction was
616 introduced before Thumb-2, we can assume blx is available and not
619 case R_ARM_THM_JUMP24
:
621 int x
, hi
, lo
, s
, j1
, j2
, i1
, i2
, imm10
, imm11
;
622 int to_thumb
, is_call
, to_plt
, blx_bit
= 1 << 12;
626 if (sym
->st_shndx
== SHN_UNDEF
&&
627 ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
630 /* Get initial offset */
631 hi
= (*(uint16_t *)ptr
);
632 lo
= (*(uint16_t *)(ptr
+2));
640 x
= (s
<< 24) | (i1
<< 23) | (i2
<< 22) |
641 (imm10
<< 12) | (imm11
<< 1);
645 /* Relocation infos */
648 to_plt
= (val
>= plt
->sh_addr
) &&
649 (val
< plt
->sh_addr
+ plt
->data_offset
);
650 is_call
= (type
== R_ARM_THM_PC22
);
652 /* Compute final offset */
653 if (to_plt
&& !is_call
) /* Point to 1st instr of Thumb stub */
656 if (!to_thumb
&& is_call
) {
657 blx_bit
= 0; /* bl -> blx */
658 x
= (x
+ 3) & -4; /* Compute offset from aligned PC */
661 /* Check that relocation is possible
662 * offset must not be out of range
663 * if target is to be entered in arm mode:
665 - instruction must be a call (bl) or a jump to PLT */
666 if (!to_thumb
|| x
>= 0x1000000 || x
< -0x1000000)
667 if (to_thumb
|| (val
& 2) || (!is_call
&& !to_plt
))
668 tcc_error("can't relocate value at %x,%d",addr
, type
);
670 /* Compute and store final offset */
676 imm10
= (x
>> 12) & 0x3ff;
677 imm11
= (x
>> 1) & 0x7ff;
678 (*(uint16_t *)ptr
) = (uint16_t) ((hi
& 0xf800) |
680 (*(uint16_t *)(ptr
+2)) = (uint16_t) ((lo
& 0xc000) |
681 (j1
<< 13) | blx_bit
| (j2
<< 11) |
686 case R_ARM_MOVW_ABS_NC
:
689 if (type
== R_ARM_MOVT_ABS
)
692 imm4
= (val
>> 12) & 0xf;
693 x
= (imm4
<< 16) | imm12
;
694 if (type
== R_ARM_THM_MOVT_ABS
)
700 case R_ARM_THM_MOVT_ABS
:
701 case R_ARM_THM_MOVW_ABS_NC
:
703 int x
, i
, imm4
, imm3
, imm8
;
704 if (type
== R_ARM_THM_MOVT_ABS
)
707 imm3
= (val
>> 8) & 0x7;
709 imm4
= (val
>> 12) & 0xf;
710 x
= (imm3
<< 28) | (imm8
<< 16) | (i
<< 10) | imm4
;
711 if (type
== R_ARM_THM_MOVT_ABS
)
720 x
= (*(int *)ptr
) & 0x7fffffff;
721 (*(int *)ptr
) &= 0x80000000;
724 if((x
^(x
>>1))&0x40000000)
725 tcc_error("can't relocate value at %x,%d",addr
, type
);
726 (*(int *)ptr
) |= x
& 0x7fffffff;
732 *(int *)ptr
+= val
- addr
;
735 *(int *)ptr
+= s1
->got
->sh_addr
- addr
;
738 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
741 /* we load the got offset */
742 *(int *)ptr
+= s1
->sym_attrs
[sym_index
].got_offset
;
747 /* trade Thumb support for ARMv4 support */
748 if ((0x0ffffff0 & *(int*)ptr
) == 0x012FFF10)
749 *(int*)ptr
^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
752 case R_ARM_JUMP_SLOT
:
753 *(addr_t
*)ptr
= val
;
756 /* Nothing to do. Normally used to indicate a dependency
757 on a certain symbol (like for exception handling under EABI). */
760 fprintf(stderr
,"FIXME: handle reloc type %x at %x [%p] to %x\n",
761 type
, (unsigned)addr
, ptr
, (unsigned)val
);
763 #elif defined(TCC_TARGET_ARM64)
764 case R_AARCH64_ABS64
:
765 *(uint64_t *)ptr
= val
;
767 case R_AARCH64_ABS32
:
768 *(uint32_t *)ptr
= val
;
770 case R_AARCH64_MOVW_UABS_G0_NC
:
771 *(uint32_t *)ptr
= (*(uint32_t *)ptr
& 0xffe0001f) |
774 case R_AARCH64_MOVW_UABS_G1_NC
:
775 *(uint32_t *)ptr
= (*(uint32_t *)ptr
& 0xffe0001f) |
776 (val
>> 16 & 0xffff) << 5;
778 case R_AARCH64_MOVW_UABS_G2_NC
:
779 *(uint32_t *)ptr
= (*(uint32_t *)ptr
& 0xffe0001f) |
780 (val
>> 32 & 0xffff) << 5;
782 case R_AARCH64_MOVW_UABS_G3
:
783 *(uint32_t *)ptr
= (*(uint32_t *)ptr
& 0xffe0001f) |
784 (val
>> 48 & 0xffff) << 5;
786 case R_AARCH64_ADR_PREL_PG_HI21
: {
787 uint64_t off
= (val
>> 12) - (addr
>> 12);
788 if ((off
+ ((uint64_t)1 << 20)) >> 21)
789 tcc_error("R_AARCH64_ADR_PREL_PG_HI21 relocation failed");
790 *(uint32_t *)ptr
= (*(uint32_t *)ptr
& 0x9f00001f) |
791 (off
& 0x1ffffc) << 3 | (off
& 3) << 29;
794 case R_AARCH64_ADD_ABS_LO12_NC
:
795 *(uint32_t *)ptr
= (*(uint32_t *)ptr
& 0xffc003ff) |
798 case R_AARCH64_JUMP26
:
799 case R_AARCH64_CALL26
:
800 if (((val
- addr
) + ((uint64_t)1 << 27)) & ~(uint64_t)0xffffffc)
801 tcc_error("R_AARCH64_(JUMP|CALL)26 relocation failed");
802 *(uint32_t *)ptr
= 0x14000000 | (type
== R_AARCH64_CALL26
) << 31 |
803 ((val
- addr
) >> 2 & 0x3ffffff);
805 case R_AARCH64_ADR_GOT_PAGE
: {
807 (((s1
->got
->sh_addr
+
808 s1
->sym_attrs
[sym_index
].got_offset
) >> 12) - (addr
>> 12));
809 if ((off
+ ((uint64_t)1 << 20)) >> 21)
810 tcc_error("R_AARCH64_ADR_GOT_PAGE relocation failed");
811 *(uint32_t *)ptr
= (*(uint32_t *)ptr
& 0x9f00001f) |
812 (off
& 0x1ffffc) << 3 | (off
& 3) << 29;
815 case R_AARCH64_LD64_GOT_LO12_NC
:
816 *(uint32_t *)ptr
= (*(uint32_t *)ptr
& 0xfff803ff) |
817 ((s1
->got
->sh_addr
+ s1
->sym_attrs
[sym_index
].got_offset
)
823 fprintf(stderr
, "FIXME: handle reloc type %x at %x [%p] to %x\n",
824 type
, (unsigned)addr
, ptr
, (unsigned)val
);
826 #elif defined(TCC_TARGET_C67)
834 /* put the low 16 bits of the absolute address
835 add to what is already there */
837 orig
= ((*(int *)(ptr
)) >> 7) & 0xffff;
838 orig
|= (((*(int *)(ptr
+4)) >> 7) & 0xffff) << 16;
840 /* patch both at once - assumes always in pairs Low - High */
842 *(int *) ptr
= (*(int *) ptr
& (~(0xffff << 7)) ) | (((val
+orig
) & 0xffff) << 7);
843 *(int *)(ptr
+4) = (*(int *)(ptr
+4) & (~(0xffff << 7)) ) | ((((val
+orig
)>>16) & 0xffff) << 7);
849 fprintf(stderr
,"FIXME: handle reloc type %x at %x [%p] to %x\n",
850 type
, (unsigned)addr
, ptr
, (unsigned)val
);
852 #elif defined(TCC_TARGET_X86_64)
854 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
855 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
856 qrel
->r_offset
= rel
->r_offset
;
858 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_X86_64_64
);
859 qrel
->r_addend
= rel
->r_addend
;
863 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
864 qrel
->r_addend
= *(long long *)ptr
+ val
;
868 *(long long *)ptr
+= val
;
872 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
873 /* XXX: this logic may depend on TCC's codegen
874 now TCC uses R_X86_64_32 even for a 64bit pointer */
875 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
876 qrel
->r_addend
= *(int *)ptr
+ val
;
883 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
885 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
887 qrel
->r_offset
= rel
->r_offset
;
888 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_X86_64_PC32
);
889 qrel
->r_addend
= *(int *)ptr
;
897 /* We've put the PLT slot offset into r_addend when generating
898 it, and that's what we must use as relocation value (adjusted
899 by section offset of course). */
900 val
= s1
->plt
->sh_addr
+ rel
->r_addend
;
906 diff
= (long long)val
- addr
;
907 if (diff
<= -2147483647 || diff
> 2147483647) {
908 tcc_error("internal error: relocation failed");
913 case R_X86_64_GLOB_DAT
:
914 case R_X86_64_JUMP_SLOT
:
915 /* They don't need addend */
916 *(addr_t
*)ptr
= val
- rel
->r_addend
;
918 case R_X86_64_GOTPCREL
:
919 *(int *)ptr
+= (s1
->got
->sh_addr
- addr
+
920 s1
->sym_attrs
[sym_index
].got_offset
- 4);
922 case R_X86_64_GOTTPOFF
:
923 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
926 /* we load the got offset */
927 *(int *)ptr
+= s1
->sym_attrs
[sym_index
].got_offset
;
930 #error unsupported processor
934 /* if the relocation is allocated, we change its symbol table */
935 if (sr
->sh_flags
& SHF_ALLOC
)
936 sr
->link
= s1
->dynsym
;
939 /* relocate relocation table in 'sr' */
940 static void relocate_rel(TCCState
*s1
, Section
*sr
)
945 s
= s1
->sections
[sr
->sh_info
];
946 for_each_elem(sr
, 0, rel
, ElfW_Rel
)
947 rel
->r_offset
+= s
->sh_addr
;
950 /* count the number of dynamic relocations so that we can reserve
952 static int prepare_dynamic_rel(TCCState
*s1
, Section
*sr
)
955 int sym_index
, esym_index
, type
, count
;
958 for_each_elem(sr
, 0, rel
, ElfW_Rel
) {
959 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
960 type
= ELFW(R_TYPE
)(rel
->r_info
);
962 #if defined(TCC_TARGET_I386)
964 #elif defined(TCC_TARGET_X86_64)
971 #if defined(TCC_TARGET_I386)
973 #elif defined(TCC_TARGET_X86_64)
976 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
985 /* allocate the section */
986 sr
->sh_flags
|= SHF_ALLOC
;
987 sr
->sh_size
= count
* sizeof(ElfW_Rel
);
992 static struct sym_attr
*alloc_sym_attr(TCCState
*s1
, int index
)
995 struct sym_attr
*tab
;
997 if (index
>= s1
->nb_sym_attrs
) {
998 /* find immediately bigger power of 2 and reallocate array */
1002 tab
= tcc_realloc(s1
->sym_attrs
, n
* sizeof(*s1
->sym_attrs
));
1003 s1
->sym_attrs
= tab
;
1004 memset(s1
->sym_attrs
+ s1
->nb_sym_attrs
, 0,
1005 (n
- s1
->nb_sym_attrs
) * sizeof(*s1
->sym_attrs
));
1006 s1
->nb_sym_attrs
= n
;
1008 return &s1
->sym_attrs
[index
];
1011 /* XXX: suppress that */
1012 static void put32(unsigned char *p
, uint32_t val
)
1020 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
1021 defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
1022 static uint32_t get32(unsigned char *p
)
1024 return p
[0] | (p
[1] << 8) | (p
[2] << 16) | (p
[3] << 24);
1028 static void build_got(TCCState
*s1
)
1032 /* if no got, then create it */
1033 s1
->got
= new_section(s1
, ".got", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
1034 s1
->got
->sh_entsize
= 4;
1035 add_elf_sym(symtab_section
, 0, 4, ELFW(ST_INFO
)(STB_GLOBAL
, STT_OBJECT
),
1036 0, s1
->got
->sh_num
, "_GLOBAL_OFFSET_TABLE_");
1037 ptr
= section_ptr_add(s1
->got
, 3 * PTR_SIZE
);
1039 /* keep space for _DYNAMIC pointer, if present */
1041 /* two dummy got entries */
1045 /* keep space for _DYNAMIC pointer, if present */
1048 /* two dummy got entries */
1056 /* put a got or plt entry corresponding to a symbol in symtab_section. 'size'
1057 and 'info' can be modifed if more precise info comes from the DLL.
1058 Returns offset of GOT or PLT slot. */
1059 static unsigned long put_got_entry(TCCState
*s1
,
1060 int reloc_type
, unsigned long size
, int info
,
1063 int index
, need_plt_entry
;
1066 unsigned long offset
;
1068 struct sym_attr
*symattr
;
1074 #ifdef TCC_TARGET_X86_64
1075 (reloc_type
== R_X86_64_JUMP_SLOT
);
1076 #elif defined(TCC_TARGET_I386)
1077 (reloc_type
== R_386_JMP_SLOT
);
1078 #elif defined(TCC_TARGET_ARM)
1079 (reloc_type
== R_ARM_JUMP_SLOT
);
1080 #elif defined(TCC_TARGET_ARM64)
1081 (reloc_type
== R_AARCH64_JUMP_SLOT
);
1086 if (need_plt_entry
&& !s1
->plt
) {
1088 s1
->plt
= new_section(s1
, ".plt", SHT_PROGBITS
,
1089 SHF_ALLOC
| SHF_EXECINSTR
);
1090 s1
->plt
->sh_entsize
= 4;
1093 /* If a got/plt entry already exists for that symbol, no need to add one */
1094 if (sym_index
< s1
->nb_sym_attrs
) {
1095 if (need_plt_entry
&& s1
->sym_attrs
[sym_index
].plt_offset
)
1096 return s1
->sym_attrs
[sym_index
].plt_offset
;
1097 else if (!need_plt_entry
&& s1
->sym_attrs
[sym_index
].got_offset
)
1098 return s1
->sym_attrs
[sym_index
].got_offset
;
1101 symattr
= alloc_sym_attr(s1
, sym_index
);
1103 /* Only store the GOT offset if it's not generated for the PLT entry. */
1104 if (!need_plt_entry
)
1105 symattr
->got_offset
= s1
->got
->data_offset
;
1107 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1108 name
= (char *) symtab_section
->link
->data
+ sym
->st_name
;
1109 offset
= sym
->st_value
;
1110 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1111 if (need_plt_entry
) {
1115 unsigned long relofs
;
1117 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1120 /* if we build a DLL, we add a %ebx offset */
1121 if (s1
->output_type
== TCC_OUTPUT_DLL
)
1127 /* add a PLT entry */
1129 if (plt
->data_offset
== 0) {
1130 /* first plt entry */
1131 p
= section_ptr_add(plt
, 16);
1132 p
[0] = 0xff; /* pushl got + PTR_SIZE */
1133 p
[1] = modrm
+ 0x10;
1134 put32(p
+ 2, PTR_SIZE
);
1135 p
[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1137 put32(p
+ 8, PTR_SIZE
* 2);
1140 /* The PLT slot refers to the relocation entry it needs
1141 via offset. The reloc entry is created below, so its
1142 offset is the current data_offset. */
1143 relofs
= s1
->got
->reloc
? s1
->got
->reloc
->data_offset
: 0;
1144 symattr
->plt_offset
= plt
->data_offset
;
1145 p
= section_ptr_add(plt
, 16);
1146 p
[0] = 0xff; /* jmp *(got + x) */
1148 put32(p
+ 2, s1
->got
->data_offset
);
1149 p
[6] = 0x68; /* push $xxx */
1150 #ifdef TCC_TARGET_X86_64
1151 /* On x86-64, the relocation is referred to by _index_. */
1152 put32(p
+ 7, relofs
/ sizeof (ElfW_Rel
));
1154 put32(p
+ 7, relofs
);
1156 p
[11] = 0xe9; /* jmp plt_start */
1157 put32(p
+ 12, -(plt
->data_offset
));
1159 /* If this was an UNDEF symbol set the offset in the
1160 dynsymtab to the PLT slot, so that PC32 relocs to it
1162 if (sym
->st_shndx
== SHN_UNDEF
)
1163 offset
= plt
->data_offset
- 16;
1165 #elif defined(TCC_TARGET_ARM)
1166 if (need_plt_entry
) {
1170 /* if we build a DLL, we add a %ebx offset */
1171 if (s1
->output_type
== TCC_OUTPUT_DLL
)
1172 tcc_error("DLLs unimplemented!");
1174 /* add a PLT entry */
1176 if (plt
->data_offset
== 0) {
1177 /* first plt entry */
1178 p
= section_ptr_add(plt
, 16);
1179 put32(p
, 0xe52de004); /* push {lr} */
1180 put32(p
+4, 0xe59fe010); /* ldr lr, [pc, #16] */
1181 put32(p
+8, 0xe08fe00e); /* add lr, pc, lr */
1182 put32(p
+12, 0xe5bef008); /* ldr pc, [lr, #8]! */
1185 symattr
->plt_offset
= plt
->data_offset
;
1186 if (symattr
->plt_thumb_stub
) {
1187 p
= section_ptr_add(plt
, 20);
1188 put32(p
, 0x4778); /* bx pc */
1189 put32(p
+2, 0x46c0); /* nop */
1192 p
= section_ptr_add(plt
, 16);
1193 put32(p
, 0xe59fc004); /* ldr ip, [pc, #4] ; GOT entry offset */
1194 put32(p
+4, 0xe08fc00c); /* add ip, pc, ip ; addr of GOT entry */
1195 put32(p
+8, 0xe59cf000); /* ldr pc, [ip] ; jump to GOT entry */
1196 put32(p
+12, s1
->got
->data_offset
); /* GOT entry off once patched */
1198 /* the symbol is modified so that it will be relocated to
1200 if (sym
->st_shndx
== SHN_UNDEF
)
1201 offset
= plt
->data_offset
- 16;
1203 #elif defined(TCC_TARGET_ARM64)
1204 if (need_plt_entry
) {
1208 if (s1
->output_type
== TCC_OUTPUT_DLL
)
1209 tcc_error("DLLs unimplemented!");
1212 if (plt
->data_offset
== 0)
1213 section_ptr_add(plt
, 32);
1214 p
= section_ptr_add(plt
, 16);
1215 put32(p
, s1
->got
->data_offset
);
1216 put32(p
+ 4, (uint64_t)s1
->got
->data_offset
>> 32);
1218 if (sym
->st_shndx
== SHN_UNDEF
)
1219 offset
= plt
->data_offset
- 16;
1221 #elif defined(TCC_TARGET_C67)
1223 tcc_error("C67 got not implemented");
1226 #error unsupported CPU
1229 /* XXX This might generate multiple syms for name. */
1230 index
= put_elf_sym(s1
->dynsym
, offset
,
1231 size
, info
, 0, sym
->st_shndx
, name
);
1232 /* Create the relocation (it's against the GOT for PLT
1234 put_elf_reloc(s1
->dynsym
, s1
->got
,
1235 s1
->got
->data_offset
,
1238 /* Without .dynsym (i.e. static link or memory output) we
1239 still need relocs against the generated got, so as to fill
1240 the entries with the symbol values (determined later). */
1241 put_elf_reloc(symtab_section
, s1
->got
,
1242 s1
->got
->data_offset
,
1243 reloc_type
, sym_index
);
1245 /* And now create the GOT slot itself. */
1246 ptr
= section_ptr_add(s1
->got
, PTR_SIZE
);
1249 return symattr
->plt_offset
;
1251 return symattr
->got_offset
;
1254 /* build GOT and PLT entries */
1255 ST_FUNC
void build_got_entries(TCCState
*s1
)
1260 int i
, type
, reloc_type
, sym_index
;
1262 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1263 s
= s1
->sections
[i
];
1264 if (s
->sh_type
!= SHT_RELX
)
1266 /* no need to handle got relocations */
1267 if (s
->link
!= symtab_section
)
1269 for_each_elem(s
, 0, rel
, ElfW_Rel
) {
1270 type
= ELFW(R_TYPE
)(rel
->r_info
);
1272 #if defined(TCC_TARGET_I386)
1279 if (type
== R_386_GOT32
|| type
== R_386_PLT32
) {
1280 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1281 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1282 /* look at the symbol got offset. If none, then add one */
1283 if (type
== R_386_GOT32
)
1284 reloc_type
= R_386_GLOB_DAT
;
1286 reloc_type
= R_386_JMP_SLOT
;
1287 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1291 #elif defined(TCC_TARGET_ARM)
1301 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1302 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1303 if (type
!= R_ARM_GOTOFF
&& type
!= R_ARM_GOTPC
1304 && sym
->st_shndx
== SHN_UNDEF
) {
1306 /* look at the symbol got offset. If none, then add one */
1307 if (type
== R_ARM_GOT32
)
1308 reloc_type
= R_ARM_GLOB_DAT
;
1310 reloc_type
= R_ARM_JUMP_SLOT
;
1311 ofs
= put_got_entry(s1
, reloc_type
, sym
->st_size
,
1312 sym
->st_info
, sym_index
);
1314 printf ("maybegot: %s, %d, %d --> ofs=0x%x\n",
1315 (char *) symtab_section
->link
->data
+ sym
->st_name
,
1316 type
, sym
->st_shndx
, ofs
);
1318 if (type
!= R_ARM_GOT32
) {
1319 addr_t
*ptr
= (addr_t
*)(s1
->sections
[s
->sh_info
]->data
1321 /* x must be signed! */
1322 int x
= *ptr
& 0xffffff;
1328 printf ("insn=0x%x --> 0x%x (x==0x%x)\n", *ptr
,
1329 (*ptr
& 0xff000000) | x
, x
);
1331 *ptr
= (*ptr
& 0xff000000) | x
;
1335 case R_ARM_THM_JUMP24
:
1336 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1337 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1338 /* We are relocating a jump from thumb code to arm code */
1339 if (sym
->st_shndx
!= SHN_UNDEF
&& !(sym
->st_value
& 1)) {
1342 char *name
, buf
[1024];
1343 Section
*text_section
;
1345 name
= (char *) symtab_section
->link
->data
+ sym
->st_name
;
1346 text_section
= s1
->sections
[sym
->st_shndx
];
1347 /* Modify reloc to target a thumb stub to switch to ARM */
1348 snprintf(buf
, sizeof(buf
), "%s_from_thumb", name
);
1349 index
= put_elf_sym(symtab_section
,
1350 text_section
->data_offset
+ 1,
1351 sym
->st_size
, sym
->st_info
, 0,
1352 sym
->st_shndx
, buf
);
1353 rel
->r_info
= ELFW(R_INFO
)(index
, type
);
1354 /* Create a thumb stub fonction to switch to ARM mode */
1355 put_elf_reloc(symtab_section
, text_section
,
1356 text_section
->data_offset
+ 4, R_ARM_JUMP24
,
1358 p
= section_ptr_add(text_section
, 8);
1359 put32(p
, 0x4778); /* bx pc */
1360 put32(p
+2, 0x46c0); /* nop */
1361 put32(p
+4, 0xeafffffe); /* b $sym */
1363 #elif defined(TCC_TARGET_ARM64)
1364 //xx Other cases may be required here:
1365 case R_AARCH64_ADR_GOT_PAGE
:
1366 case R_AARCH64_LD64_GOT_LO12_NC
:
1369 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1370 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1371 reloc_type
= R_AARCH64_GLOB_DAT
;
1372 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1375 #elif defined(TCC_TARGET_C67)
1382 if (type
== R_C60_GOT32
|| type
== R_C60_PLT32
) {
1383 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1384 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1385 /* look at the symbol got offset. If none, then add one */
1386 if (type
== R_C60_GOT32
)
1387 reloc_type
= R_C60_GLOB_DAT
;
1389 reloc_type
= R_C60_JMP_SLOT
;
1390 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1394 #elif defined(TCC_TARGET_X86_64)
1395 case R_X86_64_GOT32
:
1396 case R_X86_64_GOTTPOFF
:
1397 case R_X86_64_GOTPCREL
:
1398 case R_X86_64_PLT32
:
1399 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1400 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1401 if (type
== R_X86_64_PLT32
&&
1402 ELFW(ST_VISIBILITY
)(sym
->st_other
) != STV_DEFAULT
)
1404 rel
->r_info
= ELFW(R_INFO
)(sym_index
, R_X86_64_PC32
);
1410 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
||
1411 type
== R_X86_64_PLT32
) {
1413 /* look at the symbol got offset. If none, then add one */
1414 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
)
1415 reloc_type
= R_X86_64_GLOB_DAT
;
1417 reloc_type
= R_X86_64_JUMP_SLOT
;
1418 ofs
= put_got_entry(s1
, reloc_type
, sym
->st_size
,
1419 sym
->st_info
, sym_index
);
1420 if (type
== R_X86_64_PLT32
)
1421 /* We store the place of the generated PLT slot
1423 rel
->r_addend
+= ofs
;
1427 #error unsupported CPU
1436 ST_FUNC Section
*new_symtab(TCCState
*s1
,
1437 const char *symtab_name
, int sh_type
, int sh_flags
,
1438 const char *strtab_name
,
1439 const char *hash_name
, int hash_sh_flags
)
1441 Section
*symtab
, *strtab
, *hash
;
1442 int *ptr
, nb_buckets
;
1444 symtab
= new_section(s1
, symtab_name
, sh_type
, sh_flags
);
1445 symtab
->sh_entsize
= sizeof(ElfW(Sym
));
1446 strtab
= new_section(s1
, strtab_name
, SHT_STRTAB
, sh_flags
);
1447 put_elf_str(strtab
, "");
1448 symtab
->link
= strtab
;
1449 put_elf_sym(symtab
, 0, 0, 0, 0, 0, NULL
);
1453 hash
= new_section(s1
, hash_name
, SHT_HASH
, hash_sh_flags
);
1454 hash
->sh_entsize
= sizeof(int);
1455 symtab
->hash
= hash
;
1456 hash
->link
= symtab
;
1458 ptr
= section_ptr_add(hash
, (2 + nb_buckets
+ 1) * sizeof(int));
1459 ptr
[0] = nb_buckets
;
1461 memset(ptr
+ 2, 0, (nb_buckets
+ 1) * sizeof(int));
1465 /* put dynamic tag */
1466 static void put_dt(Section
*dynamic
, int dt
, addr_t val
)
1469 dyn
= section_ptr_add(dynamic
, sizeof(ElfW(Dyn
)));
1471 dyn
->d_un
.d_val
= val
;
1474 static void add_init_array_defines(TCCState
*s1
, const char *section_name
)
1478 char sym_start
[1024];
1481 snprintf(sym_start
, sizeof(sym_start
), "__%s_start", section_name
+ 1);
1482 snprintf(sym_end
, sizeof(sym_end
), "__%s_end", section_name
+ 1);
1484 s
= find_section(s1
, section_name
);
1489 end_offset
= s
->data_offset
;
1492 add_elf_sym(symtab_section
,
1494 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1495 s
->sh_num
, sym_start
);
1496 add_elf_sym(symtab_section
,
1498 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1499 s
->sh_num
, sym_end
);
1502 ST_FUNC
void tcc_add_bcheck(TCCState
*s1
)
1504 #ifdef CONFIG_TCC_BCHECK
1506 Section
*init_section
;
1507 unsigned char *pinit
;
1510 if (0 == s1
->do_bounds_check
)
1513 /* XXX: add an object file to do that */
1514 ptr
= section_ptr_add(bounds_section
, sizeof(unsigned long));
1516 add_elf_sym(symtab_section
, 0, 0,
1517 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1518 bounds_section
->sh_num
, "__bounds_start");
1519 #ifdef TCC_TARGET_I386
1520 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
) {
1521 /* add 'call __bound_init()' in .init section */
1522 init_section
= find_section(s1
, ".init");
1523 pinit
= section_ptr_add(init_section
, 5);
1525 put32(pinit
+ 1, -4);
1526 sym_index
= find_elf_sym(symtab_section
, "__bound_init");
1527 put_elf_reloc(symtab_section
, init_section
,
1528 init_section
->data_offset
- 4, R_386_PC32
, sym_index
);
1534 static inline int tcc_add_support(TCCState
*s1
, const char *filename
)
1537 snprintf(buf
, sizeof(buf
), "%s/%s", s1
->tcc_lib_path
, filename
);
1538 return tcc_add_file(s1
, buf
);
1541 /* add tcc runtime libraries */
1542 ST_FUNC
void tcc_add_runtime(TCCState
*s1
)
1545 if (!s1
->nostdlib
) {
1546 tcc_add_library(s1
, "c");
1547 #ifdef CONFIG_USE_LIBGCC
1548 if (!s1
->static_link
) {
1549 tcc_add_file(s1
, TCC_LIBGCC
);
1550 tcc_add_support(s1
, "libtcc1.a");
1552 tcc_add_support(s1
, "libtcc1.a");
1554 tcc_add_support(s1
, "libtcc1.a");
1558 /* tcc_add_bcheck tries to relocate a call to __bound_init in _init so
1559 libtcc1.a must be loaded before for __bound_init to be defined and
1560 crtn.o must be loaded after to not finalize _init too early. */
1563 if (!s1
->nostdlib
) {
1564 /* add crt end if not memory output */
1565 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
)
1566 tcc_add_crt(s1
, "crtn.o");
1570 /* add various standard linker symbols (must be done after the
1571 sections are filled (for example after allocating common
1573 ST_FUNC
void tcc_add_linker_symbols(TCCState
*s1
)
1579 add_elf_sym(symtab_section
,
1580 text_section
->data_offset
, 0,
1581 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1582 text_section
->sh_num
, "_etext");
1583 add_elf_sym(symtab_section
,
1584 data_section
->data_offset
, 0,
1585 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1586 data_section
->sh_num
, "_edata");
1587 add_elf_sym(symtab_section
,
1588 bss_section
->data_offset
, 0,
1589 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1590 bss_section
->sh_num
, "_end");
1591 /* horrible new standard ldscript defines */
1592 add_init_array_defines(s1
, ".preinit_array");
1593 add_init_array_defines(s1
, ".init_array");
1594 add_init_array_defines(s1
, ".fini_array");
1596 /* add start and stop symbols for sections whose name can be
1598 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1599 s
= s1
->sections
[i
];
1600 if (s
->sh_type
== SHT_PROGBITS
&&
1601 (s
->sh_flags
& SHF_ALLOC
)) {
1605 /* check if section name can be expressed in C */
1611 if (!isid(ch
) && !isnum(ch
))
1615 snprintf(buf
, sizeof(buf
), "__start_%s", s
->name
);
1616 add_elf_sym(symtab_section
,
1618 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1620 snprintf(buf
, sizeof(buf
), "__stop_%s", s
->name
);
1621 add_elf_sym(symtab_section
,
1623 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1630 static void tcc_output_binary(TCCState
*s1
, FILE *f
,
1631 const int *sec_order
)
1634 int i
, offset
, size
;
1637 for(i
=1;i
<s1
->nb_sections
;i
++) {
1638 s
= s1
->sections
[sec_order
[i
]];
1639 if (s
->sh_type
!= SHT_NOBITS
&&
1640 (s
->sh_flags
& SHF_ALLOC
)) {
1641 while (offset
< s
->sh_offset
) {
1646 fwrite(s
->data
, 1, size
, f
);
1652 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1654 #define EXTRA_RELITEMS 14
1656 /* move the relocation value from .dynsym to .got */
1657 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1659 uint32_t *gotd
= (void *)s1
->got
->data
;
1662 gotd
+= 3; /* dummy entries in .got */
1663 /* relocate symbols in .dynsym */
1664 for_each_elem(s
, 1, sym
, ElfW(Sym
)) {
1665 if (sym
->st_shndx
== SHN_UNDEF
) {
1666 *gotd
++ = sym
->st_value
+ 6; /* XXX 6 is magic ? */
1673 #define EXTRA_RELITEMS 9
1675 /* zero plt offsets of weak symbols in .dynsym */
1676 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1680 for_each_elem(s
, 1, sym
, ElfW(Sym
))
1681 if (sym
->st_shndx
== SHN_UNDEF
&& ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
1686 ST_FUNC
void fill_got_entry(TCCState
*s1
, ElfW_Rel
*rel
)
1688 int sym_index
= ELFW(R_SYM
) (rel
->r_info
);
1689 ElfW(Sym
) *sym
= &((ElfW(Sym
) *) symtab_section
->data
)[sym_index
];
1690 unsigned long offset
;
1692 if (sym_index
>= s1
->nb_sym_attrs
)
1694 offset
= s1
->sym_attrs
[sym_index
].got_offset
;
1695 section_reserve(s1
->got
, offset
+ PTR_SIZE
);
1696 #ifdef TCC_TARGET_X86_64
1697 /* only works for x86-64 */
1698 put32(s1
->got
->data
+ offset
+ 4, sym
->st_value
>> 32);
1700 put32(s1
->got
->data
+ offset
, sym
->st_value
& 0xffffffff);
1703 /* Perform relocation to GOT or PLT entries */
1704 ST_FUNC
void fill_got(TCCState
*s1
)
1710 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1711 s
= s1
->sections
[i
];
1712 if (s
->sh_type
!= SHT_RELX
)
1714 /* no need to handle got relocations */
1715 if (s
->link
!= symtab_section
)
1717 for_each_elem(s
, 0, rel
, ElfW_Rel
) {
1718 switch (ELFW(R_TYPE
) (rel
->r_info
)) {
1719 case R_X86_64_GOT32
:
1720 case R_X86_64_GOTPCREL
:
1721 case R_X86_64_PLT32
:
1722 fill_got_entry(s1
, rel
);
1729 /* Bind symbols of executable: resolve undefined symbols from exported symbols
1730 in shared libraries and export non local defined symbols to shared libraries
1731 if -rdynamic switch was given on command line */
1732 static void bind_exe_dynsyms(TCCState
*s1
)
1735 int sym_index
, index
;
1736 ElfW(Sym
) *sym
, *esym
;
1739 /* Resolve undefined symbols from dynamic symbols. When there is a match:
1740 - if STT_FUNC or STT_GNU_IFUNC symbol -> add it in PLT
1741 - if STT_OBJECT symbol -> add it in .bss section with suitable reloc */
1742 for_each_elem(symtab_section
, 1, sym
, ElfW(Sym
)) {
1743 if (sym
->st_shndx
== SHN_UNDEF
) {
1744 name
= (char *) symtab_section
->link
->data
+ sym
->st_name
;
1745 sym_index
= find_elf_sym(s1
->dynsymtab_section
, name
);
1747 esym
= &((ElfW(Sym
) *)s1
->dynsymtab_section
->data
)[sym_index
];
1748 type
= ELFW(ST_TYPE
)(esym
->st_info
);
1749 if ((type
== STT_FUNC
) || (type
== STT_GNU_IFUNC
)) {
1750 /* Indirect functions shall have STT_FUNC type in executable
1751 * dynsym section. Indeed, a dlsym call following a lazy
1752 * resolution would pick the symbol value from the
1753 * executable dynsym entry which would contain the address
1754 * of the function wanted by the caller of dlsym instead of
1755 * the address of the function that would return that
1757 put_got_entry(s1
, R_JMP_SLOT
, esym
->st_size
,
1758 ELFW(ST_INFO
)(STB_GLOBAL
,STT_FUNC
),
1759 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1760 } else if (type
== STT_OBJECT
) {
1761 unsigned long offset
;
1763 offset
= bss_section
->data_offset
;
1764 /* XXX: which alignment ? */
1765 offset
= (offset
+ 16 - 1) & -16;
1766 index
= put_elf_sym(s1
->dynsym
, offset
, esym
->st_size
,
1767 esym
->st_info
, 0, bss_section
->sh_num
,
1769 /* Ensure R_COPY works for weak symbol aliases */
1770 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1771 for_each_elem(s1
->dynsymtab_section
, 1, dynsym
, ElfW(Sym
)) {
1772 if ((dynsym
->st_value
== esym
->st_value
)
1773 && (ELFW(ST_BIND
)(dynsym
->st_info
) == STB_GLOBAL
)) {
1774 char *dynname
= (char *) s1
->dynsymtab_section
->link
->data
1776 put_elf_sym(s1
->dynsym
, offset
, dynsym
->st_size
,
1778 bss_section
->sh_num
, dynname
);
1783 put_elf_reloc(s1
->dynsym
, bss_section
,
1784 offset
, R_COPY
, index
);
1785 offset
+= esym
->st_size
;
1786 bss_section
->data_offset
= offset
;
1789 /* STB_WEAK undefined symbols are accepted */
1790 /* XXX: _fp_hw seems to be part of the ABI, so we ignore it */
1791 if (ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
||
1792 !strcmp(name
, "_fp_hw")) {
1794 tcc_error_noabort("undefined symbol '%s'", name
);
1797 } else if (s1
->rdynamic
&& ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1798 /* if -rdynamic option, then export all non local symbols */
1799 name
= (char *) symtab_section
->link
->data
+ sym
->st_name
;
1800 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
, sym
->st_info
,
1801 0, sym
->st_shndx
, name
);
1806 /* Bind symbols of libraries: export non local symbols of executable that
1807 resolve undefined symbols of shared libraries */
1808 static void bind_libs_dynsyms(TCCState
*s1
)
1812 ElfW(Sym
) *sym
, *esym
;
1814 /* now look at unresolved dynamic symbols and export
1815 corresponding symbol */
1816 for_each_elem(s1
->dynsymtab_section
, 1, esym
, ElfW(Sym
)) {
1817 if (esym
->st_shndx
== SHN_UNDEF
) {
1818 name
= (char *) s1
->dynsymtab_section
->link
->data
+ esym
->st_name
;
1819 sym_index
= find_elf_sym(symtab_section
, name
);
1821 /* XXX: avoid adding a symbol if already present because of
1823 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1824 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1825 sym
->st_info
, 0, sym
->st_shndx
, name
);
1827 /* weak symbols can stay undefined */
1828 if (ELFW(ST_BIND
)(esym
->st_info
) != STB_WEAK
)
1829 tcc_warning("undefined dynamic symbol '%s'", name
);
1835 /* Export all non local symbols (for shared libraries) */
1836 static void export_global_syms(TCCState
*s1
)
1838 int nb_syms
, dynindex
, index
;
1842 nb_syms
= symtab_section
->data_offset
/ sizeof(ElfW(Sym
));
1843 s1
->symtab_to_dynsym
= tcc_mallocz(sizeof(int) * nb_syms
);
1844 for_each_elem(symtab_section
, 1, sym
, ElfW(Sym
)) {
1845 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1846 name
= (char *) symtab_section
->link
->data
+ sym
->st_name
;
1847 dynindex
= put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1848 sym
->st_info
, 0, sym
->st_shndx
, name
);
1849 index
= sym
- (ElfW(Sym
) *) symtab_section
->data
;
1850 s1
->symtab_to_dynsym
[index
] = dynindex
;
1855 /* relocate the PLT: compute addresses and offsets in the PLT now that final
1856 address for PLT and GOT are known (see fill_program_header) */
1857 ST_FUNC
void relocate_plt(TCCState
*s1
)
1865 p_end
= p
+ s1
->plt
->data_offset
;
1867 #if defined(TCC_TARGET_I386)
1868 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
1869 put32(p
+ 8, get32(p
+ 8) + s1
->got
->sh_addr
);
1872 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
1875 #elif defined(TCC_TARGET_X86_64)
1876 int x
= s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 6;
1877 put32(p
+ 2, get32(p
+ 2) + x
);
1878 put32(p
+ 8, get32(p
+ 8) + x
- 6);
1881 put32(p
+ 2, get32(p
+ 2) + x
+ s1
->plt
->data
- p
);
1884 #elif defined(TCC_TARGET_ARM)
1886 x
=s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 12;
1889 if (get32(p
) == 0x46c04778) /* PLT Thumb stub present */
1891 put32(p
+ 12, x
+ get32(p
+ 12) + s1
->plt
->data
- p
);
1894 #elif defined(TCC_TARGET_ARM64)
1895 uint64_t plt
= s1
->plt
->sh_addr
;
1896 uint64_t got
= s1
->got
->sh_addr
;
1897 uint64_t off
= (got
>> 12) - (plt
>> 12);
1898 if ((off
+ ((uint64_t)1 << 20)) >> 21)
1899 tcc_error("Failed relocating PLT");
1900 put32(p
, 0xa9bf7bf0); // stp x16,x30,[sp,#-16]!
1901 put32(p
+ 4, (0x90000010 | // adrp x16,...
1902 (off
& 0x1ffffc) << 3 | (off
& 3) << 29));
1903 put32(p
+ 8, (0xf9400211 | // ldr x17,[x16,#...]
1904 (got
& 0xff8) << 7));
1905 put32(p
+ 12, (0x91000210 | // add x16,x16,#...
1906 (got
& 0xfff) << 10));
1907 put32(p
+ 16, 0xd61f0220); // br x17
1908 put32(p
+ 20, 0xd503201f); // nop
1909 put32(p
+ 24, 0xd503201f); // nop
1910 put32(p
+ 28, 0xd503201f); // nop
1913 uint64_t pc
= plt
+ (p
- s1
->plt
->data
);
1914 uint64_t addr
= got
+
1915 (get32(p
) | (uint64_t)get32(p
+ 4) << 32);
1916 uint32_t off
= (addr
>> 12) - (pc
>> 12);
1917 if ((off
+ ((uint64_t)1 << 20)) >> 21)
1918 tcc_error("Failed relocating PLT");
1919 put32(p
, (0x90000010 | // adrp x16,...
1920 (off
& 0x1ffffc) << 3 | (off
& 3) << 29));
1921 put32(p
+ 4, (0xf9400211 | // ldr x17,[x16,#...]
1922 (addr
& 0xff8) << 7));
1923 put32(p
+ 8, (0x91000210 | // add x16,x16,#...
1924 (addr
& 0xfff) << 10));
1925 put32(p
+ 12, 0xd61f0220); // br x17
1928 #elif defined(TCC_TARGET_C67)
1931 #error unsupported CPU
1936 /* Allocate strings for section names and decide if an unallocated section
1939 NOTE: the strsec section comes last, so its size is also correct ! */
1940 static void alloc_sec_names(TCCState
*s1
, int file_type
, Section
*strsec
)
1945 /* Allocate strings for section names */
1946 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1947 s
= s1
->sections
[i
];
1948 s
->sh_name
= put_elf_str(strsec
, s
->name
);
1949 /* when generating a DLL, we include relocations but we may
1951 if (file_type
== TCC_OUTPUT_DLL
&&
1952 s
->sh_type
== SHT_RELX
&&
1953 !(s
->sh_flags
& SHF_ALLOC
)) {
1954 /* gr: avoid bogus relocs for empty (debug) sections */
1955 if (s1
->sections
[s
->sh_info
]->sh_flags
& SHF_ALLOC
)
1956 prepare_dynamic_rel(s1
, s
);
1957 else if (s1
->do_debug
)
1958 s
->sh_size
= s
->data_offset
;
1959 } else if (s1
->do_debug
||
1960 file_type
== TCC_OUTPUT_OBJ
||
1961 (s
->sh_flags
& SHF_ALLOC
) ||
1962 i
== (s1
->nb_sections
- 1)) {
1963 /* we output all sections if debug or object file */
1964 s
->sh_size
= s
->data_offset
;
1969 /* Info to be copied in dynamic section */
1973 unsigned long dyn_rel_off
;
1976 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1982 /* Assign sections to segments and decide how are sections laid out when loaded
1983 in memory. This function also fills corresponding program headers. */
1984 static int layout_sections(TCCState
*s1
, ElfW(Phdr
) *phdr
, int phnum
,
1985 Section
*interp
, Section
* strsec
,
1986 struct dyn_inf
*dyninf
, int *sec_order
)
1988 int i
, j
, k
, file_type
, sh_order_index
, file_offset
;
1989 unsigned long s_align
;
1995 file_type
= s1
->output_type
;
1998 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
)
1999 file_offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
2000 s_align
= ELF_PAGE_SIZE
;
2001 if (s1
->section_align
)
2002 s_align
= s1
->section_align
;
2005 if (s1
->has_text_addr
) {
2006 int a_offset
, p_offset
;
2007 addr
= s1
->text_addr
;
2008 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
2010 a_offset
= (int) (addr
& (s_align
- 1));
2011 p_offset
= file_offset
& (s_align
- 1);
2012 if (a_offset
< p_offset
)
2013 a_offset
+= s_align
;
2014 file_offset
+= (a_offset
- p_offset
);
2016 if (file_type
== TCC_OUTPUT_DLL
)
2019 addr
= ELF_START_ADDR
;
2020 /* compute address after headers */
2021 addr
+= (file_offset
& (s_align
- 1));
2025 /* Leave one program headers for the program interpreter and one for
2026 the program header table itself if needed. These are done later as
2027 they require section layout to be done first. */
2029 ph
+= 1 + HAVE_PHDR
;
2031 /* dynamic relocation table information, for .dynamic section */
2032 dyninf
->rel_addr
= dyninf
->rel_size
= 0;
2033 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2034 dyninf
->bss_addr
= dyninf
->bss_size
= 0;
2037 for(j
= 0; j
< 2; j
++) {
2038 ph
->p_type
= PT_LOAD
;
2040 ph
->p_flags
= PF_R
| PF_X
;
2042 ph
->p_flags
= PF_R
| PF_W
;
2043 ph
->p_align
= s_align
;
2045 /* Decide the layout of sections loaded in memory. This must
2046 be done before program headers are filled since they contain
2047 info about the layout. We do the following ordering: interp,
2048 symbol tables, relocations, progbits, nobits */
2049 /* XXX: do faster and simpler sorting */
2050 for(k
= 0; k
< 5; k
++) {
2051 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2052 s
= s1
->sections
[i
];
2053 /* compute if section should be included */
2055 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
2059 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
2060 (SHF_ALLOC
| SHF_WRITE
))
2066 } else if (s
->sh_type
== SHT_DYNSYM
||
2067 s
->sh_type
== SHT_STRTAB
||
2068 s
->sh_type
== SHT_HASH
) {
2071 } else if (s
->sh_type
== SHT_RELX
) {
2074 } else if (s
->sh_type
== SHT_NOBITS
) {
2081 sec_order
[sh_order_index
++] = i
;
2083 /* section matches: we align it and add its size */
2085 addr
= (addr
+ s
->sh_addralign
- 1) &
2086 ~(s
->sh_addralign
- 1);
2087 file_offset
+= (int) ( addr
- tmp
);
2088 s
->sh_offset
= file_offset
;
2091 /* update program header infos */
2092 if (ph
->p_offset
== 0) {
2093 ph
->p_offset
= file_offset
;
2095 ph
->p_paddr
= ph
->p_vaddr
;
2097 /* update dynamic relocation infos */
2098 if (s
->sh_type
== SHT_RELX
) {
2099 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2100 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.got")) {
2101 dyninf
->rel_addr
= addr
;
2102 dyninf
->rel_size
+= s
->sh_size
; /* XXX only first rel. */
2104 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.bss")) {
2105 dyninf
->bss_addr
= addr
;
2106 dyninf
->bss_size
= s
->sh_size
; /* XXX only first rel. */
2109 if (dyninf
->rel_size
== 0)
2110 dyninf
->rel_addr
= addr
;
2111 dyninf
->rel_size
+= s
->sh_size
;
2115 if (s
->sh_type
!= SHT_NOBITS
)
2116 file_offset
+= s
->sh_size
;
2120 /* Make the first PT_LOAD segment include the program
2121 headers itself (and the ELF header as well), it'll
2122 come out with same memory use but will make various
2123 tools like binutils strip work better. */
2124 ph
->p_offset
&= ~(ph
->p_align
- 1);
2125 ph
->p_vaddr
&= ~(ph
->p_align
- 1);
2126 ph
->p_paddr
&= ~(ph
->p_align
- 1);
2128 ph
->p_filesz
= file_offset
- ph
->p_offset
;
2129 ph
->p_memsz
= addr
- ph
->p_vaddr
;
2132 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
2133 /* if in the middle of a page, we duplicate the page in
2134 memory so that one copy is RX and the other is RW */
2135 if ((addr
& (s_align
- 1)) != 0)
2138 addr
= (addr
+ s_align
- 1) & ~(s_align
- 1);
2139 file_offset
= (file_offset
+ s_align
- 1) & ~(s_align
- 1);
2145 /* all other sections come after */
2146 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2147 s
= s1
->sections
[i
];
2148 if (phnum
> 0 && (s
->sh_flags
& SHF_ALLOC
))
2150 sec_order
[sh_order_index
++] = i
;
2152 file_offset
= (file_offset
+ s
->sh_addralign
- 1) &
2153 ~(s
->sh_addralign
- 1);
2154 s
->sh_offset
= file_offset
;
2155 if (s
->sh_type
!= SHT_NOBITS
)
2156 file_offset
+= s
->sh_size
;
2162 static void fill_unloadable_phdr(ElfW(Phdr
) *phdr
, int phnum
, Section
*interp
,
2167 /* if interpreter, then add corresponding program header */
2173 int len
= phnum
* sizeof(ElfW(Phdr
));
2175 ph
->p_type
= PT_PHDR
;
2176 ph
->p_offset
= sizeof(ElfW(Ehdr
));
2177 ph
->p_vaddr
= interp
->sh_addr
- len
;
2178 ph
->p_paddr
= ph
->p_vaddr
;
2179 ph
->p_filesz
= ph
->p_memsz
= len
;
2180 ph
->p_flags
= PF_R
| PF_X
;
2181 ph
->p_align
= 4; /* interp->sh_addralign; */
2185 ph
->p_type
= PT_INTERP
;
2186 ph
->p_offset
= interp
->sh_offset
;
2187 ph
->p_vaddr
= interp
->sh_addr
;
2188 ph
->p_paddr
= ph
->p_vaddr
;
2189 ph
->p_filesz
= interp
->sh_size
;
2190 ph
->p_memsz
= interp
->sh_size
;
2192 ph
->p_align
= interp
->sh_addralign
;
2195 /* if dynamic section, then add corresponding program header */
2197 ph
= &phdr
[phnum
- 1];
2199 ph
->p_type
= PT_DYNAMIC
;
2200 ph
->p_offset
= dynamic
->sh_offset
;
2201 ph
->p_vaddr
= dynamic
->sh_addr
;
2202 ph
->p_paddr
= ph
->p_vaddr
;
2203 ph
->p_filesz
= dynamic
->sh_size
;
2204 ph
->p_memsz
= dynamic
->sh_size
;
2205 ph
->p_flags
= PF_R
| PF_W
;
2206 ph
->p_align
= dynamic
->sh_addralign
;
2210 /* Fill the dynamic section with tags describing the address and size of
2212 static void fill_dynamic(TCCState
*s1
, struct dyn_inf
*dyninf
)
2216 dynamic
= dyninf
->dynamic
;
2218 /* put dynamic section entries */
2219 dynamic
->data_offset
= dyninf
->dyn_rel_off
;
2220 put_dt(dynamic
, DT_HASH
, s1
->dynsym
->hash
->sh_addr
);
2221 put_dt(dynamic
, DT_STRTAB
, dyninf
->dynstr
->sh_addr
);
2222 put_dt(dynamic
, DT_SYMTAB
, s1
->dynsym
->sh_addr
);
2223 put_dt(dynamic
, DT_STRSZ
, dyninf
->dynstr
->data_offset
);
2224 put_dt(dynamic
, DT_SYMENT
, sizeof(ElfW(Sym
)));
2225 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
2226 put_dt(dynamic
, DT_RELA
, dyninf
->rel_addr
);
2227 put_dt(dynamic
, DT_RELASZ
, dyninf
->rel_size
);
2228 put_dt(dynamic
, DT_RELAENT
, sizeof(ElfW_Rel
));
2230 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2231 put_dt(dynamic
, DT_PLTGOT
, s1
->got
->sh_addr
);
2232 put_dt(dynamic
, DT_PLTRELSZ
, dyninf
->rel_size
);
2233 put_dt(dynamic
, DT_JMPREL
, dyninf
->rel_addr
);
2234 put_dt(dynamic
, DT_PLTREL
, DT_REL
);
2235 put_dt(dynamic
, DT_REL
, dyninf
->bss_addr
);
2236 put_dt(dynamic
, DT_RELSZ
, dyninf
->bss_size
);
2238 put_dt(dynamic
, DT_REL
, dyninf
->rel_addr
);
2239 put_dt(dynamic
, DT_RELSZ
, dyninf
->rel_size
);
2240 put_dt(dynamic
, DT_RELENT
, sizeof(ElfW_Rel
));
2244 put_dt(dynamic
, DT_DEBUG
, 0);
2245 put_dt(dynamic
, DT_NULL
, 0);
2248 /* Relocate remaining sections and symbols (that is those not related to
2250 static int final_sections_reloc(TCCState
*s1
)
2255 relocate_syms(s1
, 0);
2257 if (s1
->nb_errors
!= 0)
2260 /* relocate sections */
2261 /* XXX: ignore sections with allocated relocations ? */
2262 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2263 s
= s1
->sections
[i
];
2264 if (s
->reloc
&& s
!= s1
->got
)
2265 relocate_section(s1
, s
);
2268 /* relocate relocation entries if the relocation tables are
2269 allocated in the executable */
2270 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2271 s
= s1
->sections
[i
];
2272 if ((s
->sh_flags
& SHF_ALLOC
) &&
2273 s
->sh_type
== SHT_RELX
) {
2274 relocate_rel(s1
, s
);
2280 /* Create an ELF file on disk.
2281 This function handle ELF specific layout requirements */
2282 static void tcc_output_elf(TCCState
*s1
, FILE *f
, int phnum
, ElfW(Phdr
) *phdr
,
2283 int file_offset
, int *sec_order
)
2285 int i
, shnum
, offset
, size
, file_type
;
2288 ElfW(Shdr
) shdr
, *sh
;
2290 file_type
= s1
->output_type
;
2291 shnum
= s1
->nb_sections
;
2293 memset(&ehdr
, 0, sizeof(ehdr
));
2296 ehdr
.e_phentsize
= sizeof(ElfW(Phdr
));
2297 ehdr
.e_phnum
= phnum
;
2298 ehdr
.e_phoff
= sizeof(ElfW(Ehdr
));
2302 file_offset
= (file_offset
+ 3) & -4;
2305 ehdr
.e_ident
[0] = ELFMAG0
;
2306 ehdr
.e_ident
[1] = ELFMAG1
;
2307 ehdr
.e_ident
[2] = ELFMAG2
;
2308 ehdr
.e_ident
[3] = ELFMAG3
;
2309 ehdr
.e_ident
[4] = ELFCLASSW
;
2310 ehdr
.e_ident
[5] = ELFDATA2LSB
;
2311 ehdr
.e_ident
[6] = EV_CURRENT
;
2312 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2313 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_FREEBSD
;
2315 #ifdef TCC_TARGET_ARM
2317 ehdr
.e_ident
[EI_OSABI
] = 0;
2318 ehdr
.e_flags
= EF_ARM_EABI_VER4
;
2319 if (file_type
== TCC_OUTPUT_EXE
|| file_type
== TCC_OUTPUT_DLL
)
2320 ehdr
.e_flags
|= EF_ARM_HASENTRY
;
2321 if (s1
->float_abi
== ARM_HARD_FLOAT
)
2322 ehdr
.e_flags
|= EF_ARM_VFP_FLOAT
;
2324 ehdr
.e_flags
|= EF_ARM_SOFT_FLOAT
;
2326 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_ARM
;
2331 case TCC_OUTPUT_EXE
:
2332 ehdr
.e_type
= ET_EXEC
;
2333 ehdr
.e_entry
= get_elf_sym_addr(s1
, "_start", 1);
2335 case TCC_OUTPUT_DLL
:
2336 ehdr
.e_type
= ET_DYN
;
2337 ehdr
.e_entry
= text_section
->sh_addr
; /* XXX: is it correct ? */
2339 case TCC_OUTPUT_OBJ
:
2340 ehdr
.e_type
= ET_REL
;
2343 ehdr
.e_machine
= EM_TCC_TARGET
;
2344 ehdr
.e_version
= EV_CURRENT
;
2345 ehdr
.e_shoff
= file_offset
;
2346 ehdr
.e_ehsize
= sizeof(ElfW(Ehdr
));
2347 ehdr
.e_shentsize
= sizeof(ElfW(Shdr
));
2348 ehdr
.e_shnum
= shnum
;
2349 ehdr
.e_shstrndx
= shnum
- 1;
2351 fwrite(&ehdr
, 1, sizeof(ElfW(Ehdr
)), f
);
2352 fwrite(phdr
, 1, phnum
* sizeof(ElfW(Phdr
)), f
);
2353 offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
2355 sort_syms(s1
, symtab_section
);
2356 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2357 s
= s1
->sections
[sec_order
[i
]];
2358 if (s
->sh_type
!= SHT_NOBITS
) {
2359 if (s
->sh_type
== SHT_DYNSYM
)
2360 patch_dynsym_undef(s1
, s
);
2361 while (offset
< s
->sh_offset
) {
2366 fwrite(s
->data
, 1, size
, f
);
2371 /* output section headers */
2372 while (offset
< ehdr
.e_shoff
) {
2377 for(i
= 0; i
< s1
->nb_sections
; i
++) {
2379 memset(sh
, 0, sizeof(ElfW(Shdr
)));
2380 s
= s1
->sections
[i
];
2382 sh
->sh_name
= s
->sh_name
;
2383 sh
->sh_type
= s
->sh_type
;
2384 sh
->sh_flags
= s
->sh_flags
;
2385 sh
->sh_entsize
= s
->sh_entsize
;
2386 sh
->sh_info
= s
->sh_info
;
2388 sh
->sh_link
= s
->link
->sh_num
;
2389 sh
->sh_addralign
= s
->sh_addralign
;
2390 sh
->sh_addr
= s
->sh_addr
;
2391 sh
->sh_offset
= s
->sh_offset
;
2392 sh
->sh_size
= s
->sh_size
;
2394 fwrite(sh
, 1, sizeof(ElfW(Shdr
)), f
);
2398 /* Write an elf, coff or "binary" file */
2399 static int tcc_write_elf_file(TCCState
*s1
, const char *filename
, int phnum
,
2400 ElfW(Phdr
) *phdr
, int file_offset
, int *sec_order
)
2402 int fd
, mode
, file_type
;
2405 file_type
= s1
->output_type
;
2406 if (file_type
== TCC_OUTPUT_OBJ
)
2411 fd
= open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
, mode
);
2413 tcc_error_noabort("could not write '%s'", filename
);
2416 f
= fdopen(fd
, "wb");
2418 printf("<- %s\n", filename
);
2420 #ifdef TCC_TARGET_COFF
2421 if (s1
->output_format
== TCC_OUTPUT_FORMAT_COFF
)
2422 tcc_output_coff(s1
, f
);
2425 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
)
2426 tcc_output_elf(s1
, f
, phnum
, phdr
, file_offset
, sec_order
);
2428 tcc_output_binary(s1
, f
, sec_order
);
2434 /* Output an elf, coff or binary file */
2435 /* XXX: suppress unneeded sections */
2436 static int elf_output_file(TCCState
*s1
, const char *filename
)
2438 int i
, ret
, phnum
, shnum
, file_type
, file_offset
, *sec_order
;
2439 struct dyn_inf dyninf
;
2442 Section
*strsec
, *interp
, *dynamic
, *dynstr
;
2444 file_type
= s1
->output_type
;
2447 /* if linking, also link in runtime libraries (libc, libgcc, etc.) */
2448 if (file_type
!= TCC_OUTPUT_OBJ
) {
2449 tcc_add_runtime(s1
);
2454 interp
= dynamic
= dynstr
= NULL
; /* avoid warning */
2455 dyninf
.dyn_rel_off
= 0; /* avoid warning */
2457 if (file_type
!= TCC_OUTPUT_OBJ
) {
2458 relocate_common_syms();
2460 tcc_add_linker_symbols(s1
);
2462 if (!s1
->static_link
) {
2463 if (file_type
== TCC_OUTPUT_EXE
) {
2465 /* allow override the dynamic loader */
2466 const char *elfint
= getenv("LD_SO");
2468 elfint
= DEFAULT_ELFINTERP(s1
);
2469 /* add interpreter section only if executable */
2470 interp
= new_section(s1
, ".interp", SHT_PROGBITS
, SHF_ALLOC
);
2471 interp
->sh_addralign
= 1;
2472 ptr
= section_ptr_add(interp
, 1 + strlen(elfint
));
2473 strcpy(ptr
, elfint
);
2476 /* add dynamic symbol table */
2477 s1
->dynsym
= new_symtab(s1
, ".dynsym", SHT_DYNSYM
, SHF_ALLOC
,
2479 ".hash", SHF_ALLOC
);
2480 dynstr
= s1
->dynsym
->link
;
2482 /* add dynamic section */
2483 dynamic
= new_section(s1
, ".dynamic", SHT_DYNAMIC
,
2484 SHF_ALLOC
| SHF_WRITE
);
2485 dynamic
->link
= dynstr
;
2486 dynamic
->sh_entsize
= sizeof(ElfW(Dyn
));
2490 if (file_type
== TCC_OUTPUT_EXE
) {
2491 bind_exe_dynsyms(s1
);
2493 if (s1
->nb_errors
) {
2498 bind_libs_dynsyms(s1
);
2499 } else /* shared library case: simply export all global symbols */
2500 export_global_syms(s1
);
2502 build_got_entries(s1
);
2504 /* add a list of needed dlls */
2505 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
2506 DLLReference
*dllref
= s1
->loaded_dlls
[i
];
2507 if (dllref
->level
== 0)
2508 put_dt(dynamic
, DT_NEEDED
, put_elf_str(dynstr
, dllref
->name
));
2512 put_dt(dynamic
, DT_RPATH
, put_elf_str(dynstr
, s1
->rpath
));
2514 /* XXX: currently, since we do not handle PIC code, we
2515 must relocate the readonly segments */
2516 if (file_type
== TCC_OUTPUT_DLL
) {
2518 put_dt(dynamic
, DT_SONAME
, put_elf_str(dynstr
, s1
->soname
));
2519 put_dt(dynamic
, DT_TEXTREL
, 0);
2523 put_dt(dynamic
, DT_SYMBOLIC
, 0);
2525 /* add necessary space for other entries */
2526 dyninf
.dyn_rel_off
= dynamic
->data_offset
;
2527 dynamic
->data_offset
+= sizeof(ElfW(Dyn
)) * EXTRA_RELITEMS
;
2529 /* still need to build got entries in case of static link */
2530 build_got_entries(s1
);
2534 /* we add a section for symbols */
2535 strsec
= new_section(s1
, ".shstrtab", SHT_STRTAB
, 0);
2536 put_elf_str(strsec
, "");
2538 /* compute number of sections */
2539 shnum
= s1
->nb_sections
;
2541 /* this array is used to reorder sections in the output file */
2542 sec_order
= tcc_malloc(sizeof(int) * shnum
);
2545 /* compute number of program headers */
2548 case TCC_OUTPUT_OBJ
:
2551 case TCC_OUTPUT_EXE
:
2552 if (!s1
->static_link
)
2553 phnum
= 4 + HAVE_PHDR
;
2557 case TCC_OUTPUT_DLL
:
2562 /* Allocate strings for section names */
2563 alloc_sec_names(s1
, file_type
, strsec
);
2565 /* allocate program segment headers */
2566 phdr
= tcc_mallocz(phnum
* sizeof(ElfW(Phdr
)));
2568 /* compute section to program header mapping */
2569 file_offset
= layout_sections(s1
, phdr
, phnum
, interp
, strsec
, &dyninf
,
2572 /* Fill remaining program header and finalize relocation related to dynamic
2575 fill_unloadable_phdr(phdr
, phnum
, interp
, dynamic
);
2577 dyninf
.dynamic
= dynamic
;
2578 dyninf
.dynstr
= dynstr
;
2580 fill_dynamic(s1
, &dyninf
);
2582 /* put in GOT the dynamic section address and relocate PLT */
2583 put32(s1
->got
->data
, dynamic
->sh_addr
);
2584 if (file_type
== TCC_OUTPUT_EXE
2585 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2586 || file_type
== TCC_OUTPUT_DLL
2591 /* relocate symbols in .dynsym now that final addresses are known */
2592 for_each_elem(s1
->dynsym
, 1, sym
, ElfW(Sym
)) {
2593 /* relocate to PLT if symbol corresponds to a PLT entry */
2594 if (sym
->st_shndx
== SHN_UNDEF
) {
2596 sym
->st_value
+= s1
->plt
->sh_addr
;
2597 } else if (sym
->st_shndx
< SHN_LORESERVE
) {
2598 /* do symbol relocation */
2599 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
2605 /* if building executable or DLL, then relocate each section
2606 except the GOT which is already relocated */
2607 if (file_type
!= TCC_OUTPUT_OBJ
) {
2608 ret
= final_sections_reloc(s1
);
2613 /* Perform relocation to GOT or PLT entries */
2614 if (file_type
== TCC_OUTPUT_EXE
&& s1
->static_link
)
2617 /* Create the ELF file with name 'filename' */
2618 ret
= tcc_write_elf_file(s1
, filename
, phnum
, phdr
, file_offset
, sec_order
);
2620 tcc_free(s1
->symtab_to_dynsym
);
2621 tcc_free(sec_order
);
2623 tcc_free(s1
->sym_attrs
);
2624 s1
->sym_attrs
= NULL
;
2628 LIBTCCAPI
int tcc_output_file(TCCState
*s
, const char *filename
)
2631 #ifdef TCC_TARGET_PE
2632 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
2633 ret
= pe_output_file(s
, filename
);
2636 ret
= elf_output_file(s
, filename
);
2640 static void *load_data(int fd
, unsigned long file_offset
, unsigned long size
)
2644 data
= tcc_malloc(size
);
2645 lseek(fd
, file_offset
, SEEK_SET
);
2646 read(fd
, data
, size
);
2650 typedef struct SectionMergeInfo
{
2651 Section
*s
; /* corresponding existing section */
2652 unsigned long offset
; /* offset of the new section in the existing section */
2653 uint8_t new_section
; /* true if section 's' was added */
2654 uint8_t link_once
; /* true if link once section */
2657 /* load an object file and merge it with current files */
2658 /* XXX: handle correctly stab (debug) info */
2659 ST_FUNC
int tcc_load_object_file(TCCState
*s1
,
2660 int fd
, unsigned long file_offset
)
2663 ElfW(Shdr
) *shdr
, *sh
;
2664 int size
, i
, j
, offset
, offseti
, nb_syms
, sym_index
, ret
;
2665 unsigned char *strsec
, *strtab
;
2666 int *old_to_new_syms
;
2667 char *sh_name
, *name
;
2668 SectionMergeInfo
*sm_table
, *sm
;
2669 ElfW(Sym
) *sym
, *symtab
;
2676 stab_index
= stabstr_index
= 0;
2678 if (read(fd
, &ehdr
, sizeof(ehdr
)) != sizeof(ehdr
))
2680 if (ehdr
.e_ident
[0] != ELFMAG0
||
2681 ehdr
.e_ident
[1] != ELFMAG1
||
2682 ehdr
.e_ident
[2] != ELFMAG2
||
2683 ehdr
.e_ident
[3] != ELFMAG3
)
2685 /* test if object file */
2686 if (ehdr
.e_type
!= ET_REL
)
2688 /* test CPU specific stuff */
2689 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2690 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2692 tcc_error_noabort("invalid object file");
2696 shdr
= load_data(fd
, file_offset
+ ehdr
.e_shoff
,
2697 sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2698 sm_table
= tcc_mallocz(sizeof(SectionMergeInfo
) * ehdr
.e_shnum
);
2700 /* load section names */
2701 sh
= &shdr
[ehdr
.e_shstrndx
];
2702 strsec
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2704 /* load symtab and strtab */
2705 old_to_new_syms
= NULL
;
2709 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2711 if (sh
->sh_type
== SHT_SYMTAB
) {
2713 tcc_error_noabort("object must contain only one symtab");
2718 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2719 symtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2720 sm_table
[i
].s
= symtab_section
;
2722 /* now load strtab */
2723 sh
= &shdr
[sh
->sh_link
];
2724 strtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2728 /* now examine each section and try to merge its content with the
2730 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2731 /* no need to examine section name strtab */
2732 if (i
== ehdr
.e_shstrndx
)
2735 sh_name
= (char *) strsec
+ sh
->sh_name
;
2736 /* ignore sections types we do not handle */
2737 if (sh
->sh_type
!= SHT_PROGBITS
&&
2738 sh
->sh_type
!= SHT_RELX
&&
2740 sh
->sh_type
!= SHT_ARM_EXIDX
&&
2742 sh
->sh_type
!= SHT_NOBITS
&&
2743 sh
->sh_type
!= SHT_PREINIT_ARRAY
&&
2744 sh
->sh_type
!= SHT_INIT_ARRAY
&&
2745 sh
->sh_type
!= SHT_FINI_ARRAY
&&
2746 strcmp(sh_name
, ".stabstr")
2749 if (sh
->sh_addralign
< 1)
2750 sh
->sh_addralign
= 1;
2751 /* find corresponding section, if any */
2752 for(j
= 1; j
< s1
->nb_sections
;j
++) {
2753 s
= s1
->sections
[j
];
2754 if (!strcmp(s
->name
, sh_name
)) {
2755 if (!strncmp(sh_name
, ".gnu.linkonce",
2756 sizeof(".gnu.linkonce") - 1)) {
2757 /* if a 'linkonce' section is already present, we
2758 do not add it again. It is a little tricky as
2759 symbols can still be defined in
2761 sm_table
[i
].link_once
= 1;
2768 /* not found: create new section */
2769 s
= new_section(s1
, sh_name
, sh
->sh_type
, sh
->sh_flags
);
2770 /* take as much info as possible from the section. sh_link and
2771 sh_info will be updated later */
2772 s
->sh_addralign
= sh
->sh_addralign
;
2773 s
->sh_entsize
= sh
->sh_entsize
;
2774 sm_table
[i
].new_section
= 1;
2776 if (sh
->sh_type
!= s
->sh_type
) {
2777 tcc_error_noabort("invalid section type");
2781 /* align start of section */
2782 offset
= s
->data_offset
;
2784 if (0 == strcmp(sh_name
, ".stab")) {
2788 if (0 == strcmp(sh_name
, ".stabstr")) {
2793 size
= sh
->sh_addralign
- 1;
2794 offset
= (offset
+ size
) & ~size
;
2795 if (sh
->sh_addralign
> s
->sh_addralign
)
2796 s
->sh_addralign
= sh
->sh_addralign
;
2797 s
->data_offset
= offset
;
2799 sm_table
[i
].offset
= offset
;
2801 /* concatenate sections */
2803 if (sh
->sh_type
!= SHT_NOBITS
) {
2805 lseek(fd
, file_offset
+ sh
->sh_offset
, SEEK_SET
);
2806 ptr
= section_ptr_add(s
, size
);
2807 read(fd
, ptr
, size
);
2809 s
->data_offset
+= size
;
2814 /* gr relocate stab strings */
2815 if (stab_index
&& stabstr_index
) {
2818 s
= sm_table
[stab_index
].s
;
2819 a
= (Stab_Sym
*)(s
->data
+ sm_table
[stab_index
].offset
);
2820 b
= (Stab_Sym
*)(s
->data
+ s
->data_offset
);
2821 o
= sm_table
[stabstr_index
].offset
;
2823 a
->n_strx
+= o
, a
++;
2826 /* second short pass to update sh_link and sh_info fields of new
2828 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2830 if (!s
|| !sm_table
[i
].new_section
)
2833 if (sh
->sh_link
> 0)
2834 s
->link
= sm_table
[sh
->sh_link
].s
;
2835 if (sh
->sh_type
== SHT_RELX
) {
2836 s
->sh_info
= sm_table
[sh
->sh_info
].s
->sh_num
;
2837 /* update backward link */
2838 s1
->sections
[s
->sh_info
]->reloc
= s
;
2843 /* resolve symbols */
2844 old_to_new_syms
= tcc_mallocz(nb_syms
* sizeof(int));
2847 for(i
= 1; i
< nb_syms
; i
++, sym
++) {
2848 if (sym
->st_shndx
!= SHN_UNDEF
&&
2849 sym
->st_shndx
< SHN_LORESERVE
) {
2850 sm
= &sm_table
[sym
->st_shndx
];
2851 if (sm
->link_once
) {
2852 /* if a symbol is in a link once section, we use the
2853 already defined symbol. It is very important to get
2854 correct relocations */
2855 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
2856 name
= (char *) strtab
+ sym
->st_name
;
2857 sym_index
= find_elf_sym(symtab_section
, name
);
2859 old_to_new_syms
[i
] = sym_index
;
2863 /* if no corresponding section added, no need to add symbol */
2866 /* convert section number */
2867 sym
->st_shndx
= sm
->s
->sh_num
;
2869 sym
->st_value
+= sm
->offset
;
2872 name
= (char *) strtab
+ sym
->st_name
;
2873 sym_index
= add_elf_sym(symtab_section
, sym
->st_value
, sym
->st_size
,
2874 sym
->st_info
, sym
->st_other
,
2875 sym
->st_shndx
, name
);
2876 old_to_new_syms
[i
] = sym_index
;
2879 /* third pass to patch relocation entries */
2880 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2885 offset
= sm_table
[i
].offset
;
2886 switch(s
->sh_type
) {
2888 /* take relocation offset information */
2889 offseti
= sm_table
[sh
->sh_info
].offset
;
2890 for_each_elem(s
, (offset
/ sizeof(*rel
)), rel
, ElfW_Rel
) {
2893 /* convert symbol index */
2894 type
= ELFW(R_TYPE
)(rel
->r_info
);
2895 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
2896 /* NOTE: only one symtab assumed */
2897 if (sym_index
>= nb_syms
)
2899 sym_index
= old_to_new_syms
[sym_index
];
2900 /* ignore link_once in rel section. */
2901 if (!sym_index
&& !sm
->link_once
2902 #ifdef TCC_TARGET_ARM
2903 && type
!= R_ARM_V4BX
2907 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2908 i
, strsec
+ sh
->sh_name
, rel
->r_offset
);
2911 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
2912 /* offset the relocation offset */
2913 rel
->r_offset
+= offseti
;
2914 #ifdef TCC_TARGET_ARM
2915 /* Jumps and branches from a Thumb code to a PLT entry need
2916 special handling since PLT entries are ARM code.
2917 Unconditional bl instructions referencing PLT entries are
2918 handled by converting these instructions into blx
2919 instructions. Other case of instructions referencing a PLT
2920 entry require to add a Thumb stub before the PLT entry to
2921 switch to ARM mode. We set bit plt_thumb_stub of the
2922 attribute of a symbol to indicate such a case. */
2923 if (type
== R_ARM_THM_JUMP24
)
2924 alloc_sym_attr(s1
, sym_index
)->plt_thumb_stub
= 1;
2937 tcc_free(old_to_new_syms
);
2944 typedef struct ArchiveHeader
{
2945 char ar_name
[16]; /* name of this member */
2946 char ar_date
[12]; /* file mtime */
2947 char ar_uid
[6]; /* owner uid; printed as decimal */
2948 char ar_gid
[6]; /* owner gid; printed as decimal */
2949 char ar_mode
[8]; /* file mode, printed as octal */
2950 char ar_size
[10]; /* file size, printed as decimal */
2951 char ar_fmag
[2]; /* should contain ARFMAG */
2954 static int get_be32(const uint8_t *b
)
2956 return b
[3] | (b
[2] << 8) | (b
[1] << 16) | (b
[0] << 24);
2959 /* load only the objects which resolve undefined symbols */
2960 static int tcc_load_alacarte(TCCState
*s1
, int fd
, int size
)
2962 int i
, bound
, nsyms
, sym_index
, off
, ret
;
2964 const char *ar_names
, *p
;
2965 const uint8_t *ar_index
;
2968 data
= tcc_malloc(size
);
2969 if (read(fd
, data
, size
) != size
)
2971 nsyms
= get_be32(data
);
2972 ar_index
= data
+ 4;
2973 ar_names
= (char *) ar_index
+ nsyms
* 4;
2977 for(p
= ar_names
, i
= 0; i
< nsyms
; i
++, p
+= strlen(p
)+1) {
2978 sym_index
= find_elf_sym(symtab_section
, p
);
2980 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
2981 if(sym
->st_shndx
== SHN_UNDEF
) {
2982 off
= get_be32(ar_index
+ i
* 4) + sizeof(ArchiveHeader
);
2984 lseek(fd
, off
, SEEK_SET
);
2985 if(tcc_load_object_file(s1
, fd
, off
) < 0) {
3000 /* load a '.a' file */
3001 ST_FUNC
int tcc_load_archive(TCCState
*s1
, int fd
)
3008 unsigned long file_offset
;
3010 /* skip magic which was already checked */
3011 read(fd
, magic
, sizeof(magic
));
3014 len
= read(fd
, &hdr
, sizeof(hdr
));
3017 if (len
!= sizeof(hdr
)) {
3018 tcc_error_noabort("invalid archive");
3021 memcpy(ar_size
, hdr
.ar_size
, sizeof(hdr
.ar_size
));
3022 ar_size
[sizeof(hdr
.ar_size
)] = '\0';
3023 size
= strtol(ar_size
, NULL
, 0);
3024 memcpy(ar_name
, hdr
.ar_name
, sizeof(hdr
.ar_name
));
3025 for(i
= sizeof(hdr
.ar_name
) - 1; i
>= 0; i
--) {
3026 if (ar_name
[i
] != ' ')
3029 ar_name
[i
+ 1] = '\0';
3030 file_offset
= lseek(fd
, 0, SEEK_CUR
);
3032 size
= (size
+ 1) & ~1;
3033 if (!strcmp(ar_name
, "/")) {
3034 /* coff symbol table : we handle it */
3035 if(s1
->alacarte_link
)
3036 return tcc_load_alacarte(s1
, fd
, size
);
3037 } else if (!strcmp(ar_name
, "//") ||
3038 !strcmp(ar_name
, "__.SYMDEF") ||
3039 !strcmp(ar_name
, "__.SYMDEF/") ||
3040 !strcmp(ar_name
, "ARFILENAMES/")) {
3041 /* skip symbol table or archive names */
3043 if (tcc_load_object_file(s1
, fd
, file_offset
) < 0)
3046 lseek(fd
, file_offset
+ size
, SEEK_SET
);
3051 #ifndef TCC_TARGET_PE
3052 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
3053 is referenced by the user (so it should be added as DT_NEEDED in
3054 the generated ELF file) */
3055 ST_FUNC
int tcc_load_dll(TCCState
*s1
, int fd
, const char *filename
, int level
)
3058 ElfW(Shdr
) *shdr
, *sh
, *sh1
;
3059 int i
, j
, nb_syms
, nb_dts
, sym_bind
, ret
;
3060 ElfW(Sym
) *sym
, *dynsym
;
3061 ElfW(Dyn
) *dt
, *dynamic
;
3062 unsigned char *dynstr
;
3063 const char *name
, *soname
;
3064 DLLReference
*dllref
;
3066 read(fd
, &ehdr
, sizeof(ehdr
));
3068 /* test CPU specific stuff */
3069 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
3070 ehdr
.e_machine
!= EM_TCC_TARGET
) {
3071 tcc_error_noabort("bad architecture");
3076 shdr
= load_data(fd
, ehdr
.e_shoff
, sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
3078 /* load dynamic section and dynamic symbols */
3082 dynsym
= NULL
; /* avoid warning */
3083 dynstr
= NULL
; /* avoid warning */
3084 for(i
= 0, sh
= shdr
; i
< ehdr
.e_shnum
; i
++, sh
++) {
3085 switch(sh
->sh_type
) {
3087 nb_dts
= sh
->sh_size
/ sizeof(ElfW(Dyn
));
3088 dynamic
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
3091 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
3092 dynsym
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
3093 sh1
= &shdr
[sh
->sh_link
];
3094 dynstr
= load_data(fd
, sh1
->sh_offset
, sh1
->sh_size
);
3101 /* compute the real library name */
3102 soname
= tcc_basename(filename
);
3104 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
3105 if (dt
->d_tag
== DT_SONAME
) {
3106 soname
= (char *) dynstr
+ dt
->d_un
.d_val
;
3110 /* if the dll is already loaded, do not load it */
3111 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
3112 dllref
= s1
->loaded_dlls
[i
];
3113 if (!strcmp(soname
, dllref
->name
)) {
3114 /* but update level if needed */
3115 if (level
< dllref
->level
)
3116 dllref
->level
= level
;
3122 /* add the dll and its level */
3123 dllref
= tcc_mallocz(sizeof(DLLReference
) + strlen(soname
));
3124 dllref
->level
= level
;
3125 strcpy(dllref
->name
, soname
);
3126 dynarray_add((void ***)&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
, dllref
);
3128 /* add dynamic symbols in dynsym_section */
3129 for(i
= 1, sym
= dynsym
+ 1; i
< nb_syms
; i
++, sym
++) {
3130 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
3131 if (sym_bind
== STB_LOCAL
)
3133 name
= (char *) dynstr
+ sym
->st_name
;
3134 add_elf_sym(s1
->dynsymtab_section
, sym
->st_value
, sym
->st_size
,
3135 sym
->st_info
, sym
->st_other
, sym
->st_shndx
, name
);
3138 /* load all referenced DLLs */
3139 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
3142 name
= (char *) dynstr
+ dt
->d_un
.d_val
;
3143 for(j
= 0; j
< s1
->nb_loaded_dlls
; j
++) {
3144 dllref
= s1
->loaded_dlls
[j
];
3145 if (!strcmp(name
, dllref
->name
))
3146 goto already_loaded
;
3148 if (tcc_add_dll(s1
, name
, AFF_REFERENCED_DLL
) < 0) {
3149 tcc_error_noabort("referenced dll '%s' not found", name
);
3166 #define LD_TOK_NAME 256
3167 #define LD_TOK_EOF (-1)
3169 /* return next ld script token */
3170 static int ld_next(TCCState
*s1
, char *name
, int name_size
)
3188 file
->buf_ptr
= parse_comment(file
->buf_ptr
);
3189 ch
= file
->buf_ptr
[0];
3197 /* case 'a' ... 'z': */
3224 /* case 'A' ... 'z': */
3259 if (!((ch
>= 'a' && ch
<= 'z') ||
3260 (ch
>= 'A' && ch
<= 'Z') ||
3261 (ch
>= '0' && ch
<= '9') ||
3262 strchr("/.-_+=$:\\,~", ch
)))
3264 if ((q
- name
) < name_size
- 1) {
3283 static int ld_add_file(TCCState
*s1
, const char filename
[])
3287 ret
= tcc_add_file_internal(s1
, filename
, 0);
3289 ret
= tcc_add_dll(s1
, filename
, 0);
3293 static inline int new_undef_syms(void)
3296 ret
= new_undef_sym
;
3301 static int ld_add_file_list(TCCState
*s1
, const char *cmd
, int as_needed
)
3303 char filename
[1024], libname
[1024];
3304 int t
, group
, nblibs
= 0, ret
= 0;
3307 group
= !strcmp(cmd
, "GROUP");
3310 t
= ld_next(s1
, filename
, sizeof(filename
));
3313 t
= ld_next(s1
, filename
, sizeof(filename
));
3316 if (t
== LD_TOK_EOF
) {
3317 tcc_error_noabort("unexpected end of file");
3319 goto lib_parse_error
;
3320 } else if (t
== ')') {
3322 } else if (t
== '-') {
3323 t
= ld_next(s1
, filename
, sizeof(filename
));
3324 if ((t
!= LD_TOK_NAME
) || (filename
[0] != 'l')) {
3325 tcc_error_noabort("library name expected");
3327 goto lib_parse_error
;
3329 pstrcpy(libname
, sizeof libname
, &filename
[1]);
3330 if (s1
->static_link
) {
3331 snprintf(filename
, sizeof filename
, "lib%s.a", libname
);
3333 snprintf(filename
, sizeof filename
, "lib%s.so", libname
);
3335 } else if (t
!= LD_TOK_NAME
) {
3336 tcc_error_noabort("filename expected");
3338 goto lib_parse_error
;
3340 if (!strcmp(filename
, "AS_NEEDED")) {
3341 ret
= ld_add_file_list(s1
, cmd
, 1);
3343 goto lib_parse_error
;
3345 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3347 ret
= ld_add_file(s1
, filename
);
3349 goto lib_parse_error
;
3351 /* Add the filename *and* the libname to avoid future conversions */
3352 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(filename
));
3353 if (libname
[0] != '\0')
3354 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(libname
));
3358 t
= ld_next(s1
, filename
, sizeof(filename
));
3360 t
= ld_next(s1
, filename
, sizeof(filename
));
3363 if (group
&& !as_needed
) {
3364 while (new_undef_syms()) {
3367 for (i
= 0; i
< nblibs
; i
++)
3368 ld_add_file(s1
, libs
[i
]);
3372 dynarray_reset(&libs
, &nblibs
);
3376 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3378 ST_FUNC
int tcc_load_ldscript(TCCState
*s1
)
3381 char filename
[1024];
3384 ch
= file
->buf_ptr
[0];
3387 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3388 if (t
== LD_TOK_EOF
)
3390 else if (t
!= LD_TOK_NAME
)
3392 if (!strcmp(cmd
, "INPUT") ||
3393 !strcmp(cmd
, "GROUP")) {
3394 ret
= ld_add_file_list(s1
, cmd
, 0);
3397 } else if (!strcmp(cmd
, "OUTPUT_FORMAT") ||
3398 !strcmp(cmd
, "TARGET")) {
3399 /* ignore some commands */
3400 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3404 t
= ld_next(s1
, filename
, sizeof(filename
));
3405 if (t
== LD_TOK_EOF
) {
3406 tcc_error_noabort("unexpected end of file");
3408 } else if (t
== ')') {
3418 #endif /* !TCC_TARGET_PE */