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 /********************************************************/
27 /* global variables */
29 ST_DATA Section
*text_section
, *data_section
, *bss_section
; /* predefined sections */
30 ST_DATA Section
*cur_text_section
; /* current section where function code is generated */
32 ST_DATA Section
*last_text_section
; /* to handle .previous asm directive */
34 #ifdef CONFIG_TCC_BCHECK
35 /* bound check related sections */
36 ST_DATA Section
*bounds_section
; /* contains global data bound description */
37 ST_DATA Section
*lbounds_section
; /* contains local data bound description */
40 ST_DATA Section
*symtab_section
, *strtab_section
;
42 ST_DATA Section
*stab_section
, *stabstr_section
;
44 /* XXX: avoid static variable */
45 static int new_undef_sym
= 0; /* Is there a new undefined sym since last new_undef_sym() */
47 /* ------------------------------------------------------------------------- */
49 ST_FUNC
void tccelf_new(TCCState
*s
)
52 dynarray_add((void ***)&s
->sections
, &s
->nb_sections
, NULL
);
54 /* create standard sections */
55 text_section
= new_section(s
, ".text", SHT_PROGBITS
, SHF_ALLOC
| SHF_EXECINSTR
);
56 data_section
= new_section(s
, ".data", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
57 bss_section
= new_section(s
, ".bss", SHT_NOBITS
, SHF_ALLOC
| SHF_WRITE
);
59 /* symbols are always generated for linking stage */
60 symtab_section
= new_symtab(s
, ".symtab", SHT_SYMTAB
, 0,
62 ".hashtab", SHF_PRIVATE
);
63 strtab_section
= symtab_section
->link
;
64 s
->symtab
= symtab_section
;
66 /* private symbol table for dynamic symbols */
67 s
->dynsymtab_section
= new_symtab(s
, ".dynsymtab", SHT_SYMTAB
, SHF_PRIVATE
,
69 ".dynhashtab", SHF_PRIVATE
);
72 static void free_section(Section
*s
)
77 ST_FUNC
void tccelf_delete(TCCState
*s1
)
81 /* free all sections */
82 for(i
= 1; i
< s1
->nb_sections
; i
++)
83 free_section(s1
->sections
[i
]);
84 dynarray_reset(&s1
->sections
, &s1
->nb_sections
);
86 for(i
= 0; i
< s1
->nb_priv_sections
; i
++)
87 free_section(s1
->priv_sections
[i
]);
88 dynarray_reset(&s1
->priv_sections
, &s1
->nb_priv_sections
);
90 /* free any loaded DLLs */
92 for ( i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
93 DLLReference
*ref
= s1
->loaded_dlls
[i
];
96 FreeLibrary((HMODULE
)ref
->handle
);
102 /* free loaded dlls array */
103 dynarray_reset(&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
);
106 ST_FUNC Section
*new_section(TCCState
*s1
, const char *name
, int sh_type
, int sh_flags
)
110 sec
= tcc_mallocz(sizeof(Section
) + strlen(name
));
111 strcpy(sec
->name
, name
);
112 sec
->sh_type
= sh_type
;
113 sec
->sh_flags
= sh_flags
;
121 sec
->sh_addralign
= 4;
124 sec
->sh_addralign
= 1;
127 sec
->sh_addralign
= PTR_SIZE
; /* gcc/pcc default aligment */
131 if (sh_flags
& SHF_PRIVATE
) {
132 dynarray_add((void ***)&s1
->priv_sections
, &s1
->nb_priv_sections
, sec
);
134 sec
->sh_num
= s1
->nb_sections
;
135 dynarray_add((void ***)&s1
->sections
, &s1
->nb_sections
, sec
);
141 /* realloc section and set its content to zero */
142 ST_FUNC
void section_realloc(Section
*sec
, unsigned long new_size
)
147 size
= sec
->data_allocated
;
150 while (size
< new_size
)
152 data
= tcc_realloc(sec
->data
, size
);
153 memset(data
+ sec
->data_allocated
, 0, size
- sec
->data_allocated
);
155 sec
->data_allocated
= size
;
158 /* reserve at least 'size' bytes in section 'sec' from
160 ST_FUNC
void *section_ptr_add(Section
*sec
, addr_t size
)
162 size_t offset
, offset1
;
164 offset
= sec
->data_offset
;
165 offset1
= offset
+ size
;
166 if (offset1
> sec
->data_allocated
)
167 section_realloc(sec
, offset1
);
168 sec
->data_offset
= offset1
;
169 return sec
->data
+ offset
;
172 /* reserve at least 'size' bytes from section start */
173 ST_FUNC
void section_reserve(Section
*sec
, unsigned long size
)
175 if (size
> sec
->data_allocated
)
176 section_realloc(sec
, size
);
177 if (size
> sec
->data_offset
)
178 sec
->data_offset
= size
;
181 /* return a reference to a section, and create it if it does not
183 ST_FUNC Section
*find_section(TCCState
*s1
, const char *name
)
187 for(i
= 1; i
< s1
->nb_sections
; i
++) {
188 sec
= s1
->sections
[i
];
189 if (!strcmp(name
, sec
->name
))
192 /* sections are created as PROGBITS */
193 return new_section(s1
, name
, SHT_PROGBITS
, SHF_ALLOC
);
196 /* ------------------------------------------------------------------------- */
198 ST_FUNC
int put_elf_str(Section
*s
, const char *sym
)
203 len
= strlen(sym
) + 1;
204 offset
= s
->data_offset
;
205 ptr
= section_ptr_add(s
, len
);
206 memcpy(ptr
, sym
, len
);
210 /* elf symbol hashing function */
211 static unsigned long elf_hash(const unsigned char *name
)
213 unsigned long h
= 0, g
;
216 h
= (h
<< 4) + *name
++;
225 /* rebuild hash table of section s */
226 /* NOTE: we do factorize the hash table code to go faster */
227 static void rebuild_hash(Section
*s
, unsigned int nb_buckets
)
230 int *ptr
, *hash
, nb_syms
, sym_index
, h
;
231 unsigned char *strtab
;
233 strtab
= s
->link
->data
;
234 nb_syms
= s
->data_offset
/ sizeof(ElfW(Sym
));
236 s
->hash
->data_offset
= 0;
237 ptr
= section_ptr_add(s
->hash
, (2 + nb_buckets
+ nb_syms
) * sizeof(int));
242 memset(hash
, 0, (nb_buckets
+ 1) * sizeof(int));
243 ptr
+= nb_buckets
+ 1;
245 sym
= (ElfW(Sym
) *)s
->data
+ 1;
246 for(sym_index
= 1; sym_index
< nb_syms
; sym_index
++) {
247 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
248 h
= elf_hash(strtab
+ sym
->st_name
) % nb_buckets
;
259 /* return the symbol number */
260 ST_FUNC
int put_elf_sym(Section
*s
, addr_t value
, unsigned long size
,
261 int info
, int other
, int shndx
, const char *name
)
263 int name_offset
, sym_index
;
268 sym
= section_ptr_add(s
, sizeof(ElfW(Sym
)));
270 name_offset
= put_elf_str(s
->link
, name
);
273 /* XXX: endianness */
274 sym
->st_name
= name_offset
;
275 sym
->st_value
= value
;
278 sym
->st_other
= other
;
279 sym
->st_shndx
= shndx
;
280 sym_index
= sym
- (ElfW(Sym
) *)s
->data
;
284 ptr
= section_ptr_add(hs
, sizeof(int));
285 base
= (int *)hs
->data
;
286 /* only add global or weak symbols */
287 if (ELFW(ST_BIND
)(info
) != STB_LOCAL
) {
288 /* add another hashing entry */
290 h
= elf_hash((unsigned char *) name
) % nbuckets
;
292 base
[2 + h
] = sym_index
;
294 /* we resize the hash table */
295 hs
->nb_hashed_syms
++;
296 if (hs
->nb_hashed_syms
> 2 * nbuckets
) {
297 rebuild_hash(s
, 2 * nbuckets
);
307 /* find global ELF symbol 'name' and return its index. Return 0 if not
309 ST_FUNC
int find_elf_sym(Section
*s
, const char *name
)
313 int nbuckets
, sym_index
, h
;
319 nbuckets
= ((int *)hs
->data
)[0];
320 h
= elf_hash((unsigned char *) name
) % nbuckets
;
321 sym_index
= ((int *)hs
->data
)[2 + h
];
322 while (sym_index
!= 0) {
323 sym
= &((ElfW(Sym
) *)s
->data
)[sym_index
];
324 name1
= (char *) s
->link
->data
+ sym
->st_name
;
325 if (!strcmp(name
, name1
))
327 sym_index
= ((int *)hs
->data
)[2 + nbuckets
+ sym_index
];
332 /* return elf symbol value, signal error if 'err' is nonzero */
333 ST_FUNC addr_t
get_elf_sym_addr(TCCState
*s
, const char *name
, int err
)
338 sym_index
= find_elf_sym(s
->symtab
, name
);
339 sym
= &((ElfW(Sym
) *)s
->symtab
->data
)[sym_index
];
340 if (!sym_index
|| sym
->st_shndx
== SHN_UNDEF
) {
342 tcc_error("%s not defined", name
);
345 return sym
->st_value
;
348 /* return elf symbol value */
349 LIBTCCAPI
void *tcc_get_symbol(TCCState
*s
, const char *name
)
351 return (void*)(uintptr_t)get_elf_sym_addr(s
, name
, 0);
354 #if defined TCC_IS_NATIVE || defined TCC_TARGET_PE
355 /* return elf symbol value or error */
356 ST_FUNC
void* tcc_get_symbol_err(TCCState
*s
, const char *name
)
358 return (void*)(uintptr_t)get_elf_sym_addr(s
, name
, 1);
362 /* add an elf symbol : check if it is already defined and patch
363 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
364 ST_FUNC
int add_elf_sym(Section
*s
, addr_t value
, unsigned long size
,
365 int info
, int other
, int sh_num
, const char *name
)
368 int sym_bind
, sym_index
, sym_type
, esym_bind
;
369 unsigned char sym_vis
, esym_vis
, new_vis
;
371 sym_bind
= ELFW(ST_BIND
)(info
);
372 sym_type
= ELFW(ST_TYPE
)(info
);
373 sym_vis
= ELFW(ST_VISIBILITY
)(other
);
375 if (sym_bind
!= STB_LOCAL
) {
376 /* we search global or weak symbols */
377 sym_index
= find_elf_sym(s
, name
);
380 esym
= &((ElfW(Sym
) *)s
->data
)[sym_index
];
381 if (esym
->st_shndx
!= SHN_UNDEF
) {
382 esym_bind
= ELFW(ST_BIND
)(esym
->st_info
);
383 /* propagate the most constraining visibility */
384 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
385 esym_vis
= ELFW(ST_VISIBILITY
)(esym
->st_other
);
386 if (esym_vis
== STV_DEFAULT
) {
388 } else if (sym_vis
== STV_DEFAULT
) {
391 new_vis
= (esym_vis
< sym_vis
) ? esym_vis
: sym_vis
;
393 esym
->st_other
= (esym
->st_other
& ~ELFW(ST_VISIBILITY
)(-1))
395 other
= esym
->st_other
; /* in case we have to patch esym */
396 if (sh_num
== SHN_UNDEF
) {
397 /* ignore adding of undefined symbol if the
398 corresponding symbol is already defined */
399 } else if (sym_bind
== STB_GLOBAL
&& esym_bind
== STB_WEAK
) {
400 /* global overrides weak, so patch */
402 } else if (sym_bind
== STB_WEAK
&& esym_bind
== STB_GLOBAL
) {
403 /* weak is ignored if already global */
404 } else if (sym_bind
== STB_WEAK
&& esym_bind
== STB_WEAK
) {
405 /* keep first-found weak definition, ignore subsequents */
406 } else if (sym_vis
== STV_HIDDEN
|| sym_vis
== STV_INTERNAL
) {
407 /* ignore hidden symbols after */
408 } else if ((esym
->st_shndx
== SHN_COMMON
409 || esym
->st_shndx
== bss_section
->sh_num
)
410 && (sh_num
< SHN_LORESERVE
411 && sh_num
!= bss_section
->sh_num
)) {
412 /* data symbol gets precedence over common/bss */
414 } else if (sh_num
== SHN_COMMON
|| sh_num
== bss_section
->sh_num
) {
415 /* data symbol keeps precedence over common/bss */
416 } else if (s
== tcc_state
->dynsymtab_section
) {
417 /* we accept that two DLL define the same symbol */
420 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
421 sym_bind
, sh_num
, new_vis
, esym_bind
, esym
->st_shndx
, esym_vis
);
423 tcc_error_noabort("'%s' defined twice", name
);
427 esym
->st_info
= ELFW(ST_INFO
)(sym_bind
, sym_type
);
428 esym
->st_shndx
= sh_num
;
430 esym
->st_value
= value
;
431 esym
->st_size
= size
;
432 esym
->st_other
= other
;
436 sym_index
= put_elf_sym(s
, value
, size
,
437 ELFW(ST_INFO
)(sym_bind
, sym_type
), other
,
444 ST_FUNC
void put_elf_reloca(Section
*symtab
, Section
*s
, unsigned long offset
,
445 int type
, int symbol
, addr_t addend
)
453 /* if no relocation section, create it */
454 snprintf(buf
, sizeof(buf
), REL_SECTION_FMT
, s
->name
);
455 /* if the symtab is allocated, then we consider the relocation
457 sr
= new_section(tcc_state
, buf
, SHT_RELX
, symtab
->sh_flags
);
458 sr
->sh_entsize
= sizeof(ElfW_Rel
);
460 sr
->sh_info
= s
->sh_num
;
463 rel
= section_ptr_add(sr
, sizeof(ElfW_Rel
));
464 rel
->r_offset
= offset
;
465 rel
->r_info
= ELFW(R_INFO
)(symbol
, type
);
466 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
467 rel
->r_addend
= addend
;
470 tcc_error("non-zero addend on REL architecture");
474 ST_FUNC
void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
475 int type
, int symbol
)
477 put_elf_reloca(symtab
, s
, offset
, type
, symbol
, 0);
480 /* put stab debug information */
482 ST_FUNC
void put_stabs(const char *str
, int type
, int other
, int desc
,
487 sym
= section_ptr_add(stab_section
, sizeof(Stab_Sym
));
489 sym
->n_strx
= put_elf_str(stabstr_section
, str
);
494 sym
->n_other
= other
;
496 sym
->n_value
= value
;
499 ST_FUNC
void put_stabs_r(const char *str
, int type
, int other
, int desc
,
500 unsigned long value
, Section
*sec
, int sym_index
)
502 put_stabs(str
, type
, other
, desc
, value
);
503 put_elf_reloc(symtab_section
, stab_section
,
504 stab_section
->data_offset
- sizeof(unsigned int),
505 R_DATA_32
, sym_index
);
508 ST_FUNC
void put_stabn(int type
, int other
, int desc
, int value
)
510 put_stabs(NULL
, type
, other
, desc
, value
);
513 ST_FUNC
void put_stabd(int type
, int other
, int desc
)
515 put_stabs(NULL
, type
, other
, desc
, 0);
518 /* Browse each elem of type <type> in section <sec> starting at elem <startoff>
519 using variable <elem> */
520 #define for_each_elem(sec, startoff, elem, type) \
521 for (elem = (type *) sec->data + startoff; \
522 elem < (type *) (sec->data + sec->data_offset); elem++)
524 /* In an ELF file symbol table, the local symbols must appear below
525 the global and weak ones. Since TCC cannot sort it while generating
526 the code, we must do it after. All the relocation tables are also
527 modified to take into account the symbol table sorting */
528 static void sort_syms(TCCState
*s1
, Section
*s
)
530 int *old_to_new_syms
;
538 nb_syms
= s
->data_offset
/ sizeof(ElfW(Sym
));
539 new_syms
= tcc_malloc(nb_syms
* sizeof(ElfW(Sym
)));
540 old_to_new_syms
= tcc_malloc(nb_syms
* sizeof(int));
542 /* first pass for local symbols */
543 p
= (ElfW(Sym
) *)s
->data
;
545 for(i
= 0; i
< nb_syms
; i
++) {
546 if (ELFW(ST_BIND
)(p
->st_info
) == STB_LOCAL
) {
547 old_to_new_syms
[i
] = q
- new_syms
;
552 /* save the number of local symbols in section header */
553 s
->sh_info
= q
- new_syms
;
555 /* then second pass for non local symbols */
556 p
= (ElfW(Sym
) *)s
->data
;
557 for(i
= 0; i
< nb_syms
; i
++) {
558 if (ELFW(ST_BIND
)(p
->st_info
) != STB_LOCAL
) {
559 old_to_new_syms
[i
] = q
- new_syms
;
565 /* we copy the new symbols to the old */
566 memcpy(s
->data
, new_syms
, nb_syms
* sizeof(ElfW(Sym
)));
569 /* now we modify all the relocations */
570 for(i
= 1; i
< s1
->nb_sections
; i
++) {
571 sr
= s1
->sections
[i
];
572 if (sr
->sh_type
== SHT_RELX
&& sr
->link
== s
) {
573 for_each_elem(sr
, 0, rel
, ElfW_Rel
) {
574 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
575 type
= ELFW(R_TYPE
)(rel
->r_info
);
576 sym_index
= old_to_new_syms
[sym_index
];
577 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
582 tcc_free(old_to_new_syms
);
585 /* relocate common symbols in the .bss section */
586 ST_FUNC
void relocate_common_syms(void)
589 unsigned long offset
, align
;
591 for_each_elem(symtab_section
, 1, sym
, ElfW(Sym
)) {
592 if (sym
->st_shndx
== SHN_COMMON
) {
594 align
= sym
->st_value
;
595 offset
= bss_section
->data_offset
;
596 offset
= (offset
+ align
- 1) & -align
;
597 sym
->st_value
= offset
;
598 sym
->st_shndx
= bss_section
->sh_num
;
599 offset
+= sym
->st_size
;
600 bss_section
->data_offset
= offset
;
605 /* relocate symbol table, resolve undefined symbols if do_resolve is
606 true and output error if undefined symbol. */
607 ST_FUNC
void relocate_syms(TCCState
*s1
, int do_resolve
)
609 ElfW(Sym
) *sym
, *esym
;
610 int sym_bind
, sh_num
, sym_index
;
613 for_each_elem(symtab_section
, 1, sym
, ElfW(Sym
)) {
614 sh_num
= sym
->st_shndx
;
615 if (sh_num
== SHN_UNDEF
) {
616 name
= (char *) strtab_section
->data
+ sym
->st_name
;
617 /* Use ld.so to resolve symbol for us (for tcc -run) */
619 #if defined TCC_IS_NATIVE && !defined _WIN32
621 name
= (char *) symtab_section
->link
->data
+ sym
->st_name
;
622 addr
= dlsym(RTLD_DEFAULT
, name
);
624 sym
->st_value
= (addr_t
)addr
;
626 printf ("relocate_sym: %s -> 0x%lx\n", name
, sym
->st_value
);
631 } else if (s1
->dynsym
) {
632 /* if dynamic symbol exist, then use it */
633 sym_index
= find_elf_sym(s1
->dynsym
, name
);
635 esym
= &((ElfW(Sym
) *)s1
->dynsym
->data
)[sym_index
];
636 sym
->st_value
= esym
->st_value
;
640 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
642 if (!strcmp(name
, "_fp_hw"))
644 /* only weak symbols are accepted to be undefined. Their
646 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
647 if (sym_bind
== STB_WEAK
) {
650 tcc_error_noabort("undefined symbol '%s'", name
);
652 } else if (sh_num
< SHN_LORESERVE
) {
653 /* add section base */
654 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
660 /* relocate a given section (CPU dependent) by applying the relocations
661 in the associated relocation section */
662 ST_FUNC
void relocate_section(TCCState
*s1
, Section
*s
)
664 Section
*sr
= s
->reloc
;
670 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
671 ElfW_Rel
*qrel
= (ElfW_Rel
*) sr
->data
; /* ptr to next reloc entry reused */
675 for_each_elem(sr
, 0, rel
, ElfW_Rel
) {
676 ptr
= s
->data
+ rel
->r_offset
;
678 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
679 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
681 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
682 val
+= rel
->r_addend
;
684 type
= ELFW(R_TYPE
)(rel
->r_info
);
685 addr
= s
->sh_addr
+ rel
->r_offset
;
689 #if defined(TCC_TARGET_I386)
691 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
692 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
693 qrel
->r_offset
= rel
->r_offset
;
695 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_386_32
);
699 qrel
->r_info
= ELFW(R_INFO
)(0, R_386_RELATIVE
);
703 write32le(ptr
, read32le(ptr
) + val
);
706 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
708 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
710 qrel
->r_offset
= rel
->r_offset
;
711 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_386_PC32
);
716 write32le(ptr
, read32le(ptr
) + val
- addr
);
719 write32le(ptr
, read32le(ptr
) + val
- addr
);
726 write32le(ptr
, read32le(ptr
) + s1
->got
->sh_addr
- addr
);
729 write32le(ptr
, read32le(ptr
) + val
- s1
->got
->sh_addr
);
733 /* we load the got offset */
734 write32le(ptr
, read32le(ptr
) + s1
->sym_attrs
[sym_index
].got_offset
);
737 if (s1
->output_format
!= TCC_OUTPUT_FORMAT_BINARY
) {
739 tcc_error("can only produce 16-bit binary files");
741 write16le(ptr
, read16le(ptr
) + val
);
744 if (s1
->output_format
!= TCC_OUTPUT_FORMAT_BINARY
)
746 write16le(ptr
, read16le(ptr
) + val
- addr
);
750 case R_386_RELATIVE
: /* handled in pe_relocate_rva() */
754 /* This reloction must copy initialized data from the library
755 to the program .bss segment. Currently made like for ARM
756 (to remove noise of defaukt case). Is this true?
761 fprintf(stderr
,"FIXME: handle reloc type %d at %x [%p] to %x\n",
762 type
, (unsigned)addr
, ptr
, (unsigned)val
);
764 #elif defined(TCC_TARGET_ARM)
770 int x
, is_thumb
, is_call
, h
, blx_avail
, is_bl
, th_ko
;
771 x
= (*(int *) ptr
) & 0xffffff;
772 if (sym
->st_shndx
== SHN_UNDEF
)
773 val
= s1
->plt
->sh_addr
;
775 printf ("reloc %d: x=0x%x val=0x%x ", type
, x
, val
);
777 (*(int *)ptr
) &= 0xff000000;
781 blx_avail
= (TCC_ARM_VERSION
>= 5);
783 is_bl
= (*(unsigned *) ptr
) >> 24 == 0xeb;
784 is_call
= (type
== R_ARM_CALL
|| (type
== R_ARM_PC24
&& is_bl
));
787 printf (" newx=0x%x name=%s\n", x
,
788 (char *) symtab_section
->link
->data
+ sym
->st_name
);
791 th_ko
= (x
& 3) && (!blx_avail
|| !is_call
);
792 if (th_ko
|| x
>= 0x2000000 || x
< -0x2000000)
793 tcc_error("can't relocate value at %x,%d",addr
, type
);
796 /* Only reached if blx is avail and it is a call */
799 (*(int *)ptr
) = 0xfa << 24; /* bl -> blx */
804 /* Since these relocations only concern Thumb-2 and blx instruction was
805 introduced before Thumb-2, we can assume blx is available and not
808 case R_ARM_THM_JUMP24
:
810 int x
, hi
, lo
, s
, j1
, j2
, i1
, i2
, imm10
, imm11
;
811 int to_thumb
, is_call
, to_plt
, blx_bit
= 1 << 12;
815 if (sym
->st_shndx
== SHN_UNDEF
&&
816 ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
819 /* Get initial offset */
820 hi
= (*(uint16_t *)ptr
);
821 lo
= (*(uint16_t *)(ptr
+2));
829 x
= (s
<< 24) | (i1
<< 23) | (i2
<< 22) |
830 (imm10
<< 12) | (imm11
<< 1);
834 /* Relocation infos */
837 to_plt
= (val
>= plt
->sh_addr
) &&
838 (val
< plt
->sh_addr
+ plt
->data_offset
);
839 is_call
= (type
== R_ARM_THM_PC22
);
841 /* Compute final offset */
842 if (to_plt
&& !is_call
) /* Point to 1st instr of Thumb stub */
845 if (!to_thumb
&& is_call
) {
846 blx_bit
= 0; /* bl -> blx */
847 x
= (x
+ 3) & -4; /* Compute offset from aligned PC */
850 /* Check that relocation is possible
851 * offset must not be out of range
852 * if target is to be entered in arm mode:
854 - instruction must be a call (bl) or a jump to PLT */
855 if (!to_thumb
|| x
>= 0x1000000 || x
< -0x1000000)
856 if (to_thumb
|| (val
& 2) || (!is_call
&& !to_plt
))
857 tcc_error("can't relocate value at %x,%d",addr
, type
);
859 /* Compute and store final offset */
865 imm10
= (x
>> 12) & 0x3ff;
866 imm11
= (x
>> 1) & 0x7ff;
867 (*(uint16_t *)ptr
) = (uint16_t) ((hi
& 0xf800) |
869 (*(uint16_t *)(ptr
+2)) = (uint16_t) ((lo
& 0xc000) |
870 (j1
<< 13) | blx_bit
| (j2
<< 11) |
875 case R_ARM_MOVW_ABS_NC
:
878 if (type
== R_ARM_MOVT_ABS
)
881 imm4
= (val
>> 12) & 0xf;
882 x
= (imm4
<< 16) | imm12
;
883 if (type
== R_ARM_THM_MOVT_ABS
)
889 case R_ARM_THM_MOVT_ABS
:
890 case R_ARM_THM_MOVW_ABS_NC
:
892 int x
, i
, imm4
, imm3
, imm8
;
893 if (type
== R_ARM_THM_MOVT_ABS
)
896 imm3
= (val
>> 8) & 0x7;
898 imm4
= (val
>> 12) & 0xf;
899 x
= (imm3
<< 28) | (imm8
<< 16) | (i
<< 10) | imm4
;
900 if (type
== R_ARM_THM_MOVT_ABS
)
909 x
= (*(int *)ptr
) & 0x7fffffff;
910 (*(int *)ptr
) &= 0x80000000;
913 if((x
^(x
>>1))&0x40000000)
914 tcc_error("can't relocate value at %x,%d",addr
, type
);
915 (*(int *)ptr
) |= x
& 0x7fffffff;
921 *(int *)ptr
+= val
- addr
;
924 *(int *)ptr
+= s1
->got
->sh_addr
- addr
;
927 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
930 /* we load the got offset */
931 *(int *)ptr
+= s1
->sym_attrs
[sym_index
].got_offset
;
936 /* trade Thumb support for ARMv4 support */
937 if ((0x0ffffff0 & *(int*)ptr
) == 0x012FFF10)
938 *(int*)ptr
^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
941 case R_ARM_JUMP_SLOT
:
942 *(addr_t
*)ptr
= val
;
945 /* Nothing to do. Normally used to indicate a dependency
946 on a certain symbol (like for exception handling under EABI). */
949 case R_ARM_RELATIVE
: /* handled in pe_relocate_rva() */
953 fprintf(stderr
,"FIXME: handle reloc type %x at %x [%p] to %x\n",
954 type
, (unsigned)addr
, ptr
, (unsigned)val
);
956 #elif defined(TCC_TARGET_ARM64)
957 case R_AARCH64_ABS64
:
960 case R_AARCH64_ABS32
:
963 case R_AARCH64_PREL32
:
964 write32le(ptr
, val
- addr
);
966 case R_AARCH64_MOVW_UABS_G0_NC
:
967 write32le(ptr
, ((read32le(ptr
) & 0xffe0001f) |
968 (val
& 0xffff) << 5));
970 case R_AARCH64_MOVW_UABS_G1_NC
:
971 write32le(ptr
, ((read32le(ptr
) & 0xffe0001f) |
972 (val
>> 16 & 0xffff) << 5));
974 case R_AARCH64_MOVW_UABS_G2_NC
:
975 write32le(ptr
, ((read32le(ptr
) & 0xffe0001f) |
976 (val
>> 32 & 0xffff) << 5));
978 case R_AARCH64_MOVW_UABS_G3
:
979 write32le(ptr
, ((read32le(ptr
) & 0xffe0001f) |
980 (val
>> 48 & 0xffff) << 5));
982 case R_AARCH64_ADR_PREL_PG_HI21
: {
983 uint64_t off
= (val
>> 12) - (addr
>> 12);
984 if ((off
+ ((uint64_t)1 << 20)) >> 21)
985 tcc_error("R_AARCH64_ADR_PREL_PG_HI21 relocation failed");
986 write32le(ptr
, ((read32le(ptr
) & 0x9f00001f) |
987 (off
& 0x1ffffc) << 3 | (off
& 3) << 29));
990 case R_AARCH64_ADD_ABS_LO12_NC
:
991 write32le(ptr
, ((read32le(ptr
) & 0xffc003ff) |
992 (val
& 0xfff) << 10));
994 case R_AARCH64_JUMP26
:
995 case R_AARCH64_CALL26
:
996 /* This check must match the one in build_got_entries, testing
997 if we really need a PLT slot. */
998 if (sym
->st_shndx
== SHN_UNDEF
||
999 s1
->output_type
== TCC_OUTPUT_MEMORY
)
1000 /* We've put the PLT slot offset into r_addend when generating
1001 it, and that's what we must use as relocation value (adjusted
1002 by section offset of course). */
1003 val
= s1
->plt
->sh_addr
+ rel
->r_addend
;
1005 printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type
, addr
, val
,
1006 (char *) symtab_section
->link
->data
+ sym
->st_name
);
1008 if (((val
- addr
) + ((uint64_t)1 << 27)) & ~(uint64_t)0xffffffc)
1010 tcc_error("R_AARCH64_(JUMP|CALL)26 relocation failed (val=%lx, addr=%lx)", addr
, val
);
1012 write32le(ptr
, (0x14000000 |
1013 (uint32_t)(type
== R_AARCH64_CALL26
) << 31 |
1014 ((val
- addr
) >> 2 & 0x3ffffff)));
1016 case R_AARCH64_ADR_GOT_PAGE
: {
1018 (((s1
->got
->sh_addr
+
1019 s1
->sym_attrs
[sym_index
].got_offset
) >> 12) - (addr
>> 12));
1020 if ((off
+ ((uint64_t)1 << 20)) >> 21)
1021 tcc_error("R_AARCH64_ADR_GOT_PAGE relocation failed");
1022 write32le(ptr
, ((read32le(ptr
) & 0x9f00001f) |
1023 (off
& 0x1ffffc) << 3 | (off
& 3) << 29));
1026 case R_AARCH64_LD64_GOT_LO12_NC
:
1028 ((read32le(ptr
) & 0xfff803ff) |
1029 ((s1
->got
->sh_addr
+
1030 s1
->sym_attrs
[sym_index
].got_offset
) & 0xff8) << 7));
1032 case R_AARCH64_COPY
:
1034 case R_AARCH64_GLOB_DAT
:
1035 case R_AARCH64_JUMP_SLOT
:
1036 /* They don't need addend */
1038 printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type
, addr
,
1039 val
- rel
->r_addend
,
1040 (char *) symtab_section
->link
->data
+ sym
->st_name
);
1042 write64le(ptr
, val
- rel
->r_addend
);
1045 fprintf(stderr
, "FIXME: handle reloc type %x at %x [%p] to %x\n",
1046 type
, (unsigned)addr
, ptr
, (unsigned)val
);
1048 #elif defined(TCC_TARGET_C67)
1056 /* put the low 16 bits of the absolute address
1057 add to what is already there */
1059 orig
= ((*(int *)(ptr
)) >> 7) & 0xffff;
1060 orig
|= (((*(int *)(ptr
+4)) >> 7) & 0xffff) << 16;
1062 /* patch both at once - assumes always in pairs Low - High */
1064 *(int *) ptr
= (*(int *) ptr
& (~(0xffff << 7)) ) | (((val
+orig
) & 0xffff) << 7);
1065 *(int *)(ptr
+4) = (*(int *)(ptr
+4) & (~(0xffff << 7)) ) | ((((val
+orig
)>>16) & 0xffff) << 7);
1071 fprintf(stderr
,"FIXME: handle reloc type %x at %x [%p] to %x\n",
1072 type
, (unsigned)addr
, ptr
, (unsigned)val
);
1074 #elif defined(TCC_TARGET_X86_64)
1076 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
1077 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
1078 qrel
->r_offset
= rel
->r_offset
;
1080 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_X86_64_64
);
1081 qrel
->r_addend
= rel
->r_addend
;
1085 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
1086 qrel
->r_addend
= read64le(ptr
) + val
;
1090 write64le(ptr
, read64le(ptr
) + val
);
1094 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
1095 /* XXX: this logic may depend on TCC's codegen
1096 now TCC uses R_X86_64_32 even for a 64bit pointer */
1097 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
1098 /* Use sign extension! */
1099 qrel
->r_addend
= (int)read32le(ptr
) + val
;
1102 write32le(ptr
, read32le(ptr
) + val
);
1106 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
1107 /* DLL relocation */
1108 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
1110 qrel
->r_offset
= rel
->r_offset
;
1111 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_X86_64_PC32
);
1112 /* Use sign extension! */
1113 qrel
->r_addend
= (int)read32le(ptr
) + rel
->r_addend
;
1120 case R_X86_64_PLT32
:
1121 /* We've put the PLT slot offset into r_addend when generating
1122 it, and that's what we must use as relocation value (adjusted
1123 by section offset of course). */
1124 val
= s1
->plt
->sh_addr
+ rel
->r_addend
;
1130 diff
= (long long)val
- addr
;
1131 if (diff
< -2147483648LL || diff
> 2147483647LL) {
1132 tcc_error("internal error: relocation failed");
1134 write32le(ptr
, read32le(ptr
) + diff
);
1137 case R_X86_64_GLOB_DAT
:
1138 case R_X86_64_JUMP_SLOT
:
1139 /* They don't need addend */
1140 write64le(ptr
, val
- rel
->r_addend
);
1142 case R_X86_64_GOTPCREL
:
1143 case R_X86_64_GOTPCRELX
:
1144 case R_X86_64_REX_GOTPCRELX
:
1145 write32le(ptr
, read32le(ptr
) +
1146 (s1
->got
->sh_addr
- addr
+
1147 s1
->sym_attrs
[sym_index
].got_offset
- 4));
1149 case R_X86_64_GOTTPOFF
:
1150 write32le(ptr
, read32le(ptr
) + val
- s1
->got
->sh_addr
);
1152 case R_X86_64_GOT32
:
1153 /* we load the got offset */
1154 write32le(ptr
, read32le(ptr
) + s1
->sym_attrs
[sym_index
].got_offset
);
1156 #ifdef TCC_TARGET_PE
1157 case R_X86_64_RELATIVE
: /* handled in pe_relocate_rva() */
1162 #error unsupported processor
1166 /* if the relocation is allocated, we change its symbol table */
1167 if (sr
->sh_flags
& SHF_ALLOC
)
1168 sr
->link
= s1
->dynsym
;
1171 /* relocate relocation table in 'sr' */
1172 static void relocate_rel(TCCState
*s1
, Section
*sr
)
1177 s
= s1
->sections
[sr
->sh_info
];
1178 for_each_elem(sr
, 0, rel
, ElfW_Rel
)
1179 rel
->r_offset
+= s
->sh_addr
;
1182 /* count the number of dynamic relocations so that we can reserve
1184 static int prepare_dynamic_rel(TCCState
*s1
, Section
*sr
)
1187 int sym_index
, esym_index
, type
, count
;
1190 for_each_elem(sr
, 0, rel
, ElfW_Rel
) {
1191 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1192 type
= ELFW(R_TYPE
)(rel
->r_info
);
1194 #if defined(TCC_TARGET_I386)
1196 #elif defined(TCC_TARGET_X86_64)
1203 #if defined(TCC_TARGET_I386)
1205 #elif defined(TCC_TARGET_X86_64)
1208 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
1217 /* allocate the section */
1218 sr
->sh_flags
|= SHF_ALLOC
;
1219 sr
->sh_size
= count
* sizeof(ElfW_Rel
);
1224 static struct sym_attr
*alloc_sym_attr(TCCState
*s1
, int index
)
1227 struct sym_attr
*tab
;
1229 if (index
>= s1
->nb_sym_attrs
) {
1230 /* find immediately bigger power of 2 and reallocate array */
1234 tab
= tcc_realloc(s1
->sym_attrs
, n
* sizeof(*s1
->sym_attrs
));
1235 s1
->sym_attrs
= tab
;
1236 memset(s1
->sym_attrs
+ s1
->nb_sym_attrs
, 0,
1237 (n
- s1
->nb_sym_attrs
) * sizeof(*s1
->sym_attrs
));
1238 s1
->nb_sym_attrs
= n
;
1240 return &s1
->sym_attrs
[index
];
1243 static void build_got(TCCState
*s1
)
1247 /* if no got, then create it */
1248 s1
->got
= new_section(s1
, ".got", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
1249 s1
->got
->sh_entsize
= 4;
1250 add_elf_sym(symtab_section
, 0, 4, ELFW(ST_INFO
)(STB_GLOBAL
, STT_OBJECT
),
1251 0, s1
->got
->sh_num
, "_GLOBAL_OFFSET_TABLE_");
1252 ptr
= section_ptr_add(s1
->got
, 3 * PTR_SIZE
);
1254 /* keep space for _DYNAMIC pointer, if present */
1256 /* two dummy got entries */
1257 write32le(ptr
+ 4, 0);
1258 write32le(ptr
+ 8, 0);
1260 /* keep space for _DYNAMIC pointer, if present */
1262 write32le(ptr
+ 4, 0);
1263 /* two dummy got entries */
1264 write32le(ptr
+ 8, 0);
1265 write32le(ptr
+ 12, 0);
1266 write32le(ptr
+ 16, 0);
1267 write32le(ptr
+ 20, 0);
1271 /* put a got or plt entry corresponding to a symbol in symtab_section. 'size'
1272 and 'info' can be modifed if more precise info comes from the DLL.
1273 Returns offset of GOT or PLT slot. */
1274 static unsigned long put_got_entry(TCCState
*s1
,
1275 int reloc_type
, unsigned long size
, int info
,
1278 int index
, need_plt_entry
;
1281 unsigned long offset
;
1283 struct sym_attr
*symattr
;
1289 #ifdef TCC_TARGET_X86_64
1290 (reloc_type
== R_X86_64_JUMP_SLOT
);
1291 #elif defined(TCC_TARGET_I386)
1292 (reloc_type
== R_386_JMP_SLOT
);
1293 #elif defined(TCC_TARGET_ARM)
1294 (reloc_type
== R_ARM_JUMP_SLOT
);
1295 #elif defined(TCC_TARGET_ARM64)
1296 (reloc_type
== R_AARCH64_JUMP_SLOT
);
1301 if (need_plt_entry
&& !s1
->plt
) {
1303 s1
->plt
= new_section(s1
, ".plt", SHT_PROGBITS
,
1304 SHF_ALLOC
| SHF_EXECINSTR
);
1305 s1
->plt
->sh_entsize
= 4;
1308 /* If a got/plt entry already exists for that symbol, no need to add one */
1309 if (sym_index
< s1
->nb_sym_attrs
) {
1310 if (need_plt_entry
&& s1
->sym_attrs
[sym_index
].plt_offset
)
1311 return s1
->sym_attrs
[sym_index
].plt_offset
;
1312 else if (!need_plt_entry
&& s1
->sym_attrs
[sym_index
].got_offset
)
1313 return s1
->sym_attrs
[sym_index
].got_offset
;
1316 symattr
= alloc_sym_attr(s1
, sym_index
);
1318 /* Only store the GOT offset if it's not generated for the PLT entry. */
1319 if (!need_plt_entry
)
1320 symattr
->got_offset
= s1
->got
->data_offset
;
1322 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1323 name
= (char *) symtab_section
->link
->data
+ sym
->st_name
;
1324 offset
= sym
->st_value
;
1325 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1326 if (need_plt_entry
) {
1330 unsigned long relofs
;
1332 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1335 /* if we build a DLL, we add a %ebx offset */
1336 if (s1
->output_type
== TCC_OUTPUT_DLL
)
1342 /* add a PLT entry */
1344 if (plt
->data_offset
== 0) {
1345 /* first plt entry */
1346 p
= section_ptr_add(plt
, 16);
1347 p
[0] = 0xff; /* pushl got + PTR_SIZE */
1348 p
[1] = modrm
+ 0x10;
1349 write32le(p
+ 2, PTR_SIZE
);
1350 p
[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1352 write32le(p
+ 8, PTR_SIZE
* 2);
1355 /* The PLT slot refers to the relocation entry it needs
1356 via offset. The reloc entry is created below, so its
1357 offset is the current data_offset. */
1358 relofs
= s1
->got
->reloc
? s1
->got
->reloc
->data_offset
: 0;
1359 symattr
->plt_offset
= plt
->data_offset
;
1360 p
= section_ptr_add(plt
, 16);
1361 p
[0] = 0xff; /* jmp *(got + x) */
1363 write32le(p
+ 2, s1
->got
->data_offset
);
1364 p
[6] = 0x68; /* push $xxx */
1365 #ifdef TCC_TARGET_X86_64
1366 /* On x86-64, the relocation is referred to by _index_. */
1367 write32le(p
+ 7, relofs
/ sizeof (ElfW_Rel
));
1369 write32le(p
+ 7, relofs
);
1371 p
[11] = 0xe9; /* jmp plt_start */
1372 write32le(p
+ 12, -(plt
->data_offset
));
1374 /* If this was an UNDEF symbol set the offset in the
1375 dynsymtab to the PLT slot, so that PC32 relocs to it
1377 if (sym
->st_shndx
== SHN_UNDEF
)
1378 offset
= plt
->data_offset
- 16;
1380 #elif defined(TCC_TARGET_ARM)
1381 if (need_plt_entry
) {
1385 /* if we build a DLL, we add a %ebx offset */
1386 if (s1
->output_type
== TCC_OUTPUT_DLL
)
1387 tcc_error("DLLs unimplemented!");
1389 /* add a PLT entry */
1391 if (plt
->data_offset
== 0) {
1392 /* first plt entry */
1393 p
= section_ptr_add(plt
, 16);
1394 write32le(p
, 0xe52de004); /* push {lr} */
1395 write32le(p
+4, 0xe59fe010); /* ldr lr, [pc, #16] */
1396 write32le(p
+8, 0xe08fe00e); /* add lr, pc, lr */
1397 write32le(p
+12, 0xe5bef008); /* ldr pc, [lr, #8]! */
1400 symattr
->plt_offset
= plt
->data_offset
;
1401 if (symattr
->plt_thumb_stub
) {
1402 p
= section_ptr_add(plt
, 20);
1403 write32le(p
, 0x4778); /* bx pc */
1404 write32le(p
+2, 0x46c0); /* nop */
1407 p
= section_ptr_add(plt
, 16);
1408 write32le(p
, 0xe59fc004); /* ldr ip, [pc, #4] ; GOT entry offset */
1409 write32le(p
+4, 0xe08fc00c); /* add ip, pc, ip ; addr of GOT entry */
1410 write32le(p
+8, 0xe59cf000); /* ldr pc, [ip] ; jump to GOT entry */
1411 write32le(p
+12, s1
->got
->data_offset
); /* GOT entry off once patched */
1413 /* the symbol is modified so that it will be relocated to
1415 if (sym
->st_shndx
== SHN_UNDEF
)
1416 offset
= plt
->data_offset
- 16;
1418 #elif defined(TCC_TARGET_ARM64)
1419 if (need_plt_entry
) {
1423 if (s1
->output_type
== TCC_OUTPUT_DLL
)
1424 tcc_error("DLLs unimplemented!");
1427 if (plt
->data_offset
== 0)
1428 section_ptr_add(plt
, 32);
1429 symattr
->plt_offset
= plt
->data_offset
;
1430 p
= section_ptr_add(plt
, 16);
1431 write32le(p
, s1
->got
->data_offset
);
1432 write32le(p
+ 4, (uint64_t)s1
->got
->data_offset
>> 32);
1434 if (sym
->st_shndx
== SHN_UNDEF
)
1435 offset
= plt
->data_offset
- 16;
1437 #elif defined(TCC_TARGET_C67)
1439 tcc_error("C67 got not implemented");
1442 #error unsupported CPU
1445 /* XXX This might generate multiple syms for name. */
1446 index
= put_elf_sym(s1
->dynsym
, offset
,
1447 size
, info
, 0, sym
->st_shndx
, name
);
1448 /* Create the relocation (it's against the GOT for PLT
1450 put_elf_reloc(s1
->dynsym
, s1
->got
,
1451 s1
->got
->data_offset
,
1454 /* Without .dynsym (i.e. static link or memory output) we
1455 still need relocs against the generated got, so as to fill
1456 the entries with the symbol values (determined later). */
1457 put_elf_reloc(symtab_section
, s1
->got
,
1458 s1
->got
->data_offset
,
1459 reloc_type
, sym_index
);
1461 /* And now create the GOT slot itself. */
1462 ptr
= section_ptr_add(s1
->got
, PTR_SIZE
);
1465 return symattr
->plt_offset
;
1467 return symattr
->got_offset
;
1470 /* build GOT and PLT entries */
1471 ST_FUNC
void build_got_entries(TCCState
*s1
)
1476 int i
, type
, reloc_type
, sym_index
;
1478 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1479 s
= s1
->sections
[i
];
1480 if (s
->sh_type
!= SHT_RELX
)
1482 /* no need to handle got relocations */
1483 if (s
->link
!= symtab_section
)
1485 for_each_elem(s
, 0, rel
, ElfW_Rel
) {
1486 type
= ELFW(R_TYPE
)(rel
->r_info
);
1488 #if defined(TCC_TARGET_I386)
1496 if (type
== R_386_GOT32
|| type
== R_386_GOT32X
||
1497 type
== R_386_PLT32
) {
1498 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1499 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1500 /* look at the symbol got offset. If none, then add one */
1501 if (type
== R_386_GOT32
|| type
== R_386_GOT32X
)
1502 reloc_type
= R_386_GLOB_DAT
;
1504 reloc_type
= R_386_JMP_SLOT
;
1505 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1509 #elif defined(TCC_TARGET_ARM)
1519 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1520 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1521 if (type
!= R_ARM_GOTOFF
&& type
!= R_ARM_GOTPC
1522 && sym
->st_shndx
== SHN_UNDEF
) {
1524 /* look at the symbol got offset. If none, then add one */
1525 if (type
== R_ARM_GOT32
)
1526 reloc_type
= R_ARM_GLOB_DAT
;
1528 reloc_type
= R_ARM_JUMP_SLOT
;
1529 ofs
= put_got_entry(s1
, reloc_type
, sym
->st_size
,
1530 sym
->st_info
, sym_index
);
1532 printf ("maybegot: %s, %d, %d --> ofs=0x%x\n",
1533 (char *) symtab_section
->link
->data
+ sym
->st_name
,
1534 type
, sym
->st_shndx
, ofs
);
1536 if (type
!= R_ARM_GOT32
) {
1537 addr_t
*ptr
= (addr_t
*)(s1
->sections
[s
->sh_info
]->data
1539 /* x must be signed! */
1540 int x
= *ptr
& 0xffffff;
1546 printf ("insn=0x%x --> 0x%x (x==0x%x)\n", *ptr
,
1547 (*ptr
& 0xff000000) | x
, x
);
1549 *ptr
= (*ptr
& 0xff000000) | x
;
1553 case R_ARM_THM_JUMP24
:
1554 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1555 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1556 /* We are relocating a jump from thumb code to arm code */
1557 if (sym
->st_shndx
!= SHN_UNDEF
&& !(sym
->st_value
& 1)) {
1560 char *name
, buf
[1024];
1561 Section
*text_section
;
1563 name
= (char *) symtab_section
->link
->data
+ sym
->st_name
;
1564 text_section
= s1
->sections
[sym
->st_shndx
];
1565 /* Modify reloc to target a thumb stub to switch to ARM */
1566 snprintf(buf
, sizeof(buf
), "%s_from_thumb", name
);
1567 index
= put_elf_sym(symtab_section
,
1568 text_section
->data_offset
+ 1,
1569 sym
->st_size
, sym
->st_info
, 0,
1570 sym
->st_shndx
, buf
);
1571 rel
->r_info
= ELFW(R_INFO
)(index
, type
);
1572 /* Create a thumb stub fonction to switch to ARM mode */
1573 put_elf_reloc(symtab_section
, text_section
,
1574 text_section
->data_offset
+ 4, R_ARM_JUMP24
,
1576 p
= section_ptr_add(text_section
, 8);
1577 write32le(p
, 0x4778); /* bx pc */
1578 write32le(p
+2, 0x46c0); /* nop */
1579 write32le(p
+4, 0xeafffffe); /* b $sym */
1581 #elif defined(TCC_TARGET_ARM64)
1582 //xx Other cases may be required here:
1583 case R_AARCH64_ADR_GOT_PAGE
:
1584 case R_AARCH64_LD64_GOT_LO12_NC
:
1587 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1588 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1589 reloc_type
= R_AARCH64_GLOB_DAT
;
1590 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1594 case R_AARCH64_JUMP26
:
1595 case R_AARCH64_CALL26
:
1598 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1599 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1600 if (sym
->st_shndx
== SHN_UNDEF
||
1601 s1
->output_type
== TCC_OUTPUT_MEMORY
) {
1603 reloc_type
= R_AARCH64_JUMP_SLOT
;
1604 ofs
= put_got_entry(s1
, reloc_type
, sym
->st_size
,
1605 sym
->st_info
, sym_index
);
1606 /* We store the place of the generated PLT slot
1608 rel
->r_addend
+= ofs
;
1611 #elif defined(TCC_TARGET_C67)
1618 if (type
== R_C60_GOT32
|| type
== R_C60_PLT32
) {
1619 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1620 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1621 /* look at the symbol got offset. If none, then add one */
1622 if (type
== R_C60_GOT32
)
1623 reloc_type
= R_C60_GLOB_DAT
;
1625 reloc_type
= R_C60_JMP_SLOT
;
1626 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1630 #elif defined(TCC_TARGET_X86_64)
1631 case R_X86_64_GOT32
:
1632 case R_X86_64_GOTTPOFF
:
1633 case R_X86_64_GOTPCREL
:
1634 case R_X86_64_GOTPCRELX
:
1635 case R_X86_64_REX_GOTPCRELX
:
1636 case R_X86_64_PLT32
:
1637 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1638 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1639 if (type
== R_X86_64_PLT32
&&
1640 ELFW(ST_VISIBILITY
)(sym
->st_other
) != STV_DEFAULT
)
1642 rel
->r_info
= ELFW(R_INFO
)(sym_index
, R_X86_64_PC32
);
1648 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1650 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
||
1651 type
== R_X86_64_GOTPCRELX
||
1652 type
== R_X86_64_REX_GOTPCRELX
||
1653 type
== R_X86_64_PLT32
) {
1655 /* look at the symbol got offset. If none, then add one */
1656 if (type
== R_X86_64_PLT32
)
1657 reloc_type
= R_X86_64_JUMP_SLOT
;
1659 reloc_type
= R_X86_64_GLOB_DAT
;
1660 ofs
= put_got_entry(s1
, reloc_type
, sym
->st_size
,
1661 sym
->st_info
, sym_index
);
1662 if (type
== R_X86_64_PLT32
)
1663 /* We store the place of the generated PLT slot
1665 rel
->r_addend
+= ofs
;
1669 #error unsupported CPU
1678 ST_FUNC Section
*new_symtab(TCCState
*s1
,
1679 const char *symtab_name
, int sh_type
, int sh_flags
,
1680 const char *strtab_name
,
1681 const char *hash_name
, int hash_sh_flags
)
1683 Section
*symtab
, *strtab
, *hash
;
1684 int *ptr
, nb_buckets
;
1686 symtab
= new_section(s1
, symtab_name
, sh_type
, sh_flags
);
1687 symtab
->sh_entsize
= sizeof(ElfW(Sym
));
1688 strtab
= new_section(s1
, strtab_name
, SHT_STRTAB
, sh_flags
);
1689 put_elf_str(strtab
, "");
1690 symtab
->link
= strtab
;
1691 put_elf_sym(symtab
, 0, 0, 0, 0, 0, NULL
);
1695 hash
= new_section(s1
, hash_name
, SHT_HASH
, hash_sh_flags
);
1696 hash
->sh_entsize
= sizeof(int);
1697 symtab
->hash
= hash
;
1698 hash
->link
= symtab
;
1700 ptr
= section_ptr_add(hash
, (2 + nb_buckets
+ 1) * sizeof(int));
1701 ptr
[0] = nb_buckets
;
1703 memset(ptr
+ 2, 0, (nb_buckets
+ 1) * sizeof(int));
1707 /* put dynamic tag */
1708 static void put_dt(Section
*dynamic
, int dt
, addr_t val
)
1711 dyn
= section_ptr_add(dynamic
, sizeof(ElfW(Dyn
)));
1713 dyn
->d_un
.d_val
= val
;
1716 static void add_init_array_defines(TCCState
*s1
, const char *section_name
)
1720 char sym_start
[1024];
1723 snprintf(sym_start
, sizeof(sym_start
), "__%s_start", section_name
+ 1);
1724 snprintf(sym_end
, sizeof(sym_end
), "__%s_end", section_name
+ 1);
1726 s
= find_section(s1
, section_name
);
1731 end_offset
= s
->data_offset
;
1734 add_elf_sym(symtab_section
,
1736 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1737 s
->sh_num
, sym_start
);
1738 add_elf_sym(symtab_section
,
1740 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1741 s
->sh_num
, sym_end
);
1744 static int tcc_add_support(TCCState
*s1
, const char *filename
)
1747 snprintf(buf
, sizeof(buf
), "%s/"TCC_ARCH_DIR
"%s", s1
->tcc_lib_path
, filename
);
1748 return tcc_add_file(s1
, buf
);
1751 ST_FUNC
void tcc_add_bcheck(TCCState
*s1
)
1753 #ifdef CONFIG_TCC_BCHECK
1757 if (0 == s1
->do_bounds_check
)
1759 /* XXX: add an object file to do that */
1760 ptr
= section_ptr_add(bounds_section
, sizeof(*ptr
));
1762 add_elf_sym(symtab_section
, 0, 0,
1763 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1764 bounds_section
->sh_num
, "__bounds_start");
1765 /* pull bcheck.o from libtcc1.a */
1766 sym_index
= add_elf_sym(symtab_section
, 0, 0,
1767 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1768 SHN_UNDEF
, "__bound_init");
1769 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
) {
1770 /* add 'call __bound_init()' in .init section */
1771 Section
*init_section
= find_section(s1
, ".init");
1772 unsigned char *pinit
= section_ptr_add(init_section
, 5);
1774 write32le(pinit
+ 1, -4);
1775 put_elf_reloc(symtab_section
, init_section
,
1776 init_section
->data_offset
- 4, R_386_PC32
, sym_index
);
1777 /* R_386_PC32 = R_X86_64_PC32 = 2 */
1782 /* add tcc runtime libraries */
1783 ST_FUNC
void tcc_add_runtime(TCCState
*s1
)
1786 tcc_add_pragma_libs(s1
);
1788 if (!s1
->nostdlib
) {
1789 tcc_add_library(s1
, "c");
1790 #ifdef CONFIG_USE_LIBGCC
1791 if (!s1
->static_link
) {
1792 tcc_add_file(s1
, TCC_LIBGCC
);
1795 tcc_add_support(s1
, "libtcc1.a");
1796 /* add crt end if not memory output */
1797 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
)
1798 tcc_add_crt(s1
, "crtn.o");
1802 /* add various standard linker symbols (must be done after the
1803 sections are filled (for example after allocating common
1805 ST_FUNC
void tcc_add_linker_symbols(TCCState
*s1
)
1811 add_elf_sym(symtab_section
,
1812 text_section
->data_offset
, 0,
1813 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1814 text_section
->sh_num
, "_etext");
1815 add_elf_sym(symtab_section
,
1816 data_section
->data_offset
, 0,
1817 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1818 data_section
->sh_num
, "_edata");
1819 add_elf_sym(symtab_section
,
1820 bss_section
->data_offset
, 0,
1821 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1822 bss_section
->sh_num
, "_end");
1823 /* horrible new standard ldscript defines */
1824 add_init_array_defines(s1
, ".preinit_array");
1825 add_init_array_defines(s1
, ".init_array");
1826 add_init_array_defines(s1
, ".fini_array");
1828 /* add start and stop symbols for sections whose name can be
1830 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1831 s
= s1
->sections
[i
];
1832 if (s
->sh_type
== SHT_PROGBITS
&&
1833 (s
->sh_flags
& SHF_ALLOC
)) {
1837 /* check if section name can be expressed in C */
1843 if (!isid(ch
) && !isnum(ch
))
1847 snprintf(buf
, sizeof(buf
), "__start_%s", s
->name
);
1848 add_elf_sym(symtab_section
,
1850 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1852 snprintf(buf
, sizeof(buf
), "__stop_%s", s
->name
);
1853 add_elf_sym(symtab_section
,
1855 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1862 static void tcc_output_binary(TCCState
*s1
, FILE *f
,
1863 const int *sec_order
)
1866 int i
, offset
, size
;
1869 for(i
=1;i
<s1
->nb_sections
;i
++) {
1870 s
= s1
->sections
[sec_order
[i
]];
1871 if (s
->sh_type
!= SHT_NOBITS
&&
1872 (s
->sh_flags
& SHF_ALLOC
)) {
1873 while (offset
< s
->sh_offset
) {
1878 fwrite(s
->data
, 1, size
, f
);
1884 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1886 #define EXTRA_RELITEMS 14
1888 /* move the relocation value from .dynsym to .got */
1889 static void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1891 uint32_t *gotd
= (void *)s1
->got
->data
;
1894 gotd
+= 3; /* dummy entries in .got */
1895 /* relocate symbols in .dynsym */
1896 for_each_elem(s
, 1, sym
, ElfW(Sym
)) {
1897 if (sym
->st_shndx
== SHN_UNDEF
) {
1898 *gotd
++ = sym
->st_value
+ 6; /* XXX 6 is magic ? */
1905 #define EXTRA_RELITEMS 9
1907 /* zero plt offsets of weak symbols in .dynsym */
1908 static void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1912 for_each_elem(s
, 1, sym
, ElfW(Sym
))
1913 if (sym
->st_shndx
== SHN_UNDEF
&& ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
1918 ST_FUNC
void fill_got_entry(TCCState
*s1
, ElfW_Rel
*rel
)
1920 int sym_index
= ELFW(R_SYM
) (rel
->r_info
);
1921 ElfW(Sym
) *sym
= &((ElfW(Sym
) *) symtab_section
->data
)[sym_index
];
1922 unsigned long offset
;
1924 if (sym_index
>= s1
->nb_sym_attrs
)
1926 offset
= s1
->sym_attrs
[sym_index
].got_offset
;
1927 section_reserve(s1
->got
, offset
+ PTR_SIZE
);
1928 #ifdef TCC_TARGET_X86_64
1929 /* only works for x86-64 */
1930 write32le(s1
->got
->data
+ offset
+ 4, sym
->st_value
>> 32);
1932 write32le(s1
->got
->data
+ offset
, sym
->st_value
& 0xffffffff);
1935 /* Perform relocation to GOT or PLT entries */
1936 ST_FUNC
void fill_got(TCCState
*s1
)
1942 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1943 s
= s1
->sections
[i
];
1944 if (s
->sh_type
!= SHT_RELX
)
1946 /* no need to handle got relocations */
1947 if (s
->link
!= symtab_section
)
1949 for_each_elem(s
, 0, rel
, ElfW_Rel
) {
1950 switch (ELFW(R_TYPE
) (rel
->r_info
)) {
1951 case R_X86_64_GOT32
:
1952 case R_X86_64_GOTPCREL
:
1953 case R_X86_64_GOTPCRELX
:
1954 case R_X86_64_REX_GOTPCRELX
:
1955 case R_X86_64_PLT32
:
1956 fill_got_entry(s1
, rel
);
1963 /* Bind symbols of executable: resolve undefined symbols from exported symbols
1964 in shared libraries and export non local defined symbols to shared libraries
1965 if -rdynamic switch was given on command line */
1966 static void bind_exe_dynsyms(TCCState
*s1
)
1969 int sym_index
, index
;
1970 ElfW(Sym
) *sym
, *esym
;
1973 /* Resolve undefined symbols from dynamic symbols. When there is a match:
1974 - if STT_FUNC or STT_GNU_IFUNC symbol -> add it in PLT
1975 - if STT_OBJECT symbol -> add it in .bss section with suitable reloc */
1976 for_each_elem(symtab_section
, 1, sym
, ElfW(Sym
)) {
1977 if (sym
->st_shndx
== SHN_UNDEF
) {
1978 name
= (char *) symtab_section
->link
->data
+ sym
->st_name
;
1979 sym_index
= find_elf_sym(s1
->dynsymtab_section
, name
);
1981 esym
= &((ElfW(Sym
) *)s1
->dynsymtab_section
->data
)[sym_index
];
1982 type
= ELFW(ST_TYPE
)(esym
->st_info
);
1983 if ((type
== STT_FUNC
) || (type
== STT_GNU_IFUNC
)) {
1984 /* Indirect functions shall have STT_FUNC type in executable
1985 * dynsym section. Indeed, a dlsym call following a lazy
1986 * resolution would pick the symbol value from the
1987 * executable dynsym entry which would contain the address
1988 * of the function wanted by the caller of dlsym instead of
1989 * the address of the function that would return that
1991 put_got_entry(s1
, R_JMP_SLOT
, esym
->st_size
,
1992 ELFW(ST_INFO
)(STB_GLOBAL
,STT_FUNC
),
1993 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1994 } else if (type
== STT_OBJECT
) {
1995 unsigned long offset
;
1997 offset
= bss_section
->data_offset
;
1998 /* XXX: which alignment ? */
1999 offset
= (offset
+ 16 - 1) & -16;
2000 index
= put_elf_sym(s1
->dynsym
, offset
, esym
->st_size
,
2001 esym
->st_info
, 0, bss_section
->sh_num
,
2003 /* Ensure R_COPY works for weak symbol aliases */
2004 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
2005 for_each_elem(s1
->dynsymtab_section
, 1, dynsym
, ElfW(Sym
)) {
2006 if ((dynsym
->st_value
== esym
->st_value
)
2007 && (ELFW(ST_BIND
)(dynsym
->st_info
) == STB_GLOBAL
)) {
2008 char *dynname
= (char *) s1
->dynsymtab_section
->link
->data
2010 put_elf_sym(s1
->dynsym
, offset
, dynsym
->st_size
,
2012 bss_section
->sh_num
, dynname
);
2017 put_elf_reloc(s1
->dynsym
, bss_section
,
2018 offset
, R_COPY
, index
);
2019 offset
+= esym
->st_size
;
2020 bss_section
->data_offset
= offset
;
2023 /* STB_WEAK undefined symbols are accepted */
2024 /* XXX: _fp_hw seems to be part of the ABI, so we ignore it */
2025 if (ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
||
2026 !strcmp(name
, "_fp_hw")) {
2028 tcc_error_noabort("undefined symbol '%s'", name
);
2031 } else if (s1
->rdynamic
&& ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
2032 /* if -rdynamic option, then export all non local symbols */
2033 name
= (char *) symtab_section
->link
->data
+ sym
->st_name
;
2034 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
, sym
->st_info
,
2035 0, sym
->st_shndx
, name
);
2040 /* Bind symbols of libraries: export non local symbols of executable that
2041 resolve undefined symbols of shared libraries */
2042 static void bind_libs_dynsyms(TCCState
*s1
)
2046 ElfW(Sym
) *sym
, *esym
;
2048 /* now look at unresolved dynamic symbols and export
2049 corresponding symbol */
2050 for_each_elem(s1
->dynsymtab_section
, 1, esym
, ElfW(Sym
)) {
2051 name
= (char *) s1
->dynsymtab_section
->link
->data
+ esym
->st_name
;
2052 sym_index
= find_elf_sym(symtab_section
, name
);
2054 /* XXX: avoid adding a symbol if already present because of
2056 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
2057 if (sym
->st_shndx
!= SHN_UNDEF
)
2058 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
2059 sym
->st_info
, 0, sym
->st_shndx
, name
);
2060 } else if (esym
->st_shndx
== SHN_UNDEF
) {
2061 /* weak symbols can stay undefined */
2062 if (ELFW(ST_BIND
)(esym
->st_info
) != STB_WEAK
)
2063 tcc_warning("undefined dynamic symbol '%s'", name
);
2068 /* Export all non local symbols (for shared libraries) */
2069 static void export_global_syms(TCCState
*s1
)
2071 int nb_syms
, dynindex
, index
;
2075 nb_syms
= symtab_section
->data_offset
/ sizeof(ElfW(Sym
));
2076 s1
->symtab_to_dynsym
= tcc_mallocz(sizeof(int) * nb_syms
);
2077 for_each_elem(symtab_section
, 1, sym
, ElfW(Sym
)) {
2078 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
2079 name
= (char *) symtab_section
->link
->data
+ sym
->st_name
;
2080 dynindex
= put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
2081 sym
->st_info
, 0, sym
->st_shndx
, name
);
2082 index
= sym
- (ElfW(Sym
) *) symtab_section
->data
;
2083 s1
->symtab_to_dynsym
[index
] = dynindex
;
2088 /* relocate the PLT: compute addresses and offsets in the PLT now that final
2089 address for PLT and GOT are known (see fill_program_header) */
2090 ST_FUNC
void relocate_plt(TCCState
*s1
)
2098 p_end
= p
+ s1
->plt
->data_offset
;
2100 #if defined(TCC_TARGET_I386)
2101 write32le(p
+ 2, read32le(p
+ 2) + s1
->got
->sh_addr
);
2102 write32le(p
+ 8, read32le(p
+ 8) + s1
->got
->sh_addr
);
2105 write32le(p
+ 2, read32le(p
+ 2) + s1
->got
->sh_addr
);
2108 #elif defined(TCC_TARGET_X86_64)
2109 int x
= s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 6;
2110 write32le(p
+ 2, read32le(p
+ 2) + x
);
2111 write32le(p
+ 8, read32le(p
+ 8) + x
- 6);
2114 write32le(p
+ 2, read32le(p
+ 2) + x
+ s1
->plt
->data
- p
);
2117 #elif defined(TCC_TARGET_ARM)
2119 x
=s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 12;
2122 if (read32le(p
) == 0x46c04778) /* PLT Thumb stub present */
2124 write32le(p
+ 12, x
+ read32le(p
+ 12) + s1
->plt
->data
- p
);
2127 #elif defined(TCC_TARGET_ARM64)
2128 uint64_t plt
= s1
->plt
->sh_addr
;
2129 uint64_t got
= s1
->got
->sh_addr
;
2130 uint64_t off
= (got
>> 12) - (plt
>> 12);
2131 if ((off
+ ((uint32_t)1 << 20)) >> 21)
2132 tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", off
, got
, plt
);
2133 write32le(p
, 0xa9bf7bf0); // stp x16,x30,[sp,#-16]!
2134 write32le(p
+ 4, (0x90000010 | // adrp x16,...
2135 (off
& 0x1ffffc) << 3 | (off
& 3) << 29));
2136 write32le(p
+ 8, (0xf9400211 | // ldr x17,[x16,#...]
2137 (got
& 0xff8) << 7));
2138 write32le(p
+ 12, (0x91000210 | // add x16,x16,#...
2139 (got
& 0xfff) << 10));
2140 write32le(p
+ 16, 0xd61f0220); // br x17
2141 write32le(p
+ 20, 0xd503201f); // nop
2142 write32le(p
+ 24, 0xd503201f); // nop
2143 write32le(p
+ 28, 0xd503201f); // nop
2146 uint64_t pc
= plt
+ (p
- s1
->plt
->data
);
2147 uint64_t addr
= got
+ read64le(p
);
2148 uint64_t off
= (addr
>> 12) - (pc
>> 12);
2149 if ((off
+ ((uint32_t)1 << 20)) >> 21)
2150 tcc_error("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", off
, addr
, pc
);
2151 write32le(p
, (0x90000010 | // adrp x16,...
2152 (off
& 0x1ffffc) << 3 | (off
& 3) << 29));
2153 write32le(p
+ 4, (0xf9400211 | // ldr x17,[x16,#...]
2154 (addr
& 0xff8) << 7));
2155 write32le(p
+ 8, (0x91000210 | // add x16,x16,#...
2156 (addr
& 0xfff) << 10));
2157 write32le(p
+ 12, 0xd61f0220); // br x17
2160 #elif defined(TCC_TARGET_C67)
2163 #error unsupported CPU
2168 /* Allocate strings for section names and decide if an unallocated section
2171 NOTE: the strsec section comes last, so its size is also correct ! */
2172 static void alloc_sec_names(TCCState
*s1
, int file_type
, Section
*strsec
)
2177 /* Allocate strings for section names */
2178 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2179 s
= s1
->sections
[i
];
2180 s
->sh_name
= put_elf_str(strsec
, s
->name
);
2181 /* when generating a DLL, we include relocations but we may
2183 if (file_type
== TCC_OUTPUT_DLL
&&
2184 s
->sh_type
== SHT_RELX
&&
2185 !(s
->sh_flags
& SHF_ALLOC
)) {
2186 /* gr: avoid bogus relocs for empty (debug) sections */
2187 if (s1
->sections
[s
->sh_info
]->sh_flags
& SHF_ALLOC
)
2188 prepare_dynamic_rel(s1
, s
);
2189 else if (s1
->do_debug
)
2190 s
->sh_size
= s
->data_offset
;
2191 } else if (s1
->do_debug
||
2192 file_type
== TCC_OUTPUT_OBJ
||
2193 (s
->sh_flags
& SHF_ALLOC
) ||
2194 i
== (s1
->nb_sections
- 1)) {
2195 /* we output all sections if debug or object file */
2196 s
->sh_size
= s
->data_offset
;
2201 /* Info to be copied in dynamic section */
2205 unsigned long dyn_rel_off
;
2208 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2214 /* Assign sections to segments and decide how are sections laid out when loaded
2215 in memory. This function also fills corresponding program headers. */
2216 static int layout_sections(TCCState
*s1
, ElfW(Phdr
) *phdr
, int phnum
,
2217 Section
*interp
, Section
* strsec
,
2218 struct dyn_inf
*dyninf
, int *sec_order
)
2220 int i
, j
, k
, file_type
, sh_order_index
, file_offset
;
2221 unsigned long s_align
;
2227 file_type
= s1
->output_type
;
2230 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
)
2231 file_offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
2232 s_align
= ELF_PAGE_SIZE
;
2233 if (s1
->section_align
)
2234 s_align
= s1
->section_align
;
2237 if (s1
->has_text_addr
) {
2238 int a_offset
, p_offset
;
2239 addr
= s1
->text_addr
;
2240 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
2242 a_offset
= (int) (addr
& (s_align
- 1));
2243 p_offset
= file_offset
& (s_align
- 1);
2244 if (a_offset
< p_offset
)
2245 a_offset
+= s_align
;
2246 file_offset
+= (a_offset
- p_offset
);
2248 if (file_type
== TCC_OUTPUT_DLL
)
2251 addr
= ELF_START_ADDR
;
2252 /* compute address after headers */
2253 addr
+= (file_offset
& (s_align
- 1));
2257 /* Leave one program headers for the program interpreter and one for
2258 the program header table itself if needed. These are done later as
2259 they require section layout to be done first. */
2261 ph
+= 1 + HAVE_PHDR
;
2263 /* dynamic relocation table information, for .dynamic section */
2264 dyninf
->rel_addr
= dyninf
->rel_size
= 0;
2265 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2266 dyninf
->bss_addr
= dyninf
->bss_size
= 0;
2269 for(j
= 0; j
< 2; j
++) {
2270 ph
->p_type
= PT_LOAD
;
2272 ph
->p_flags
= PF_R
| PF_X
;
2274 ph
->p_flags
= PF_R
| PF_W
;
2275 ph
->p_align
= s_align
;
2277 /* Decide the layout of sections loaded in memory. This must
2278 be done before program headers are filled since they contain
2279 info about the layout. We do the following ordering: interp,
2280 symbol tables, relocations, progbits, nobits */
2281 /* XXX: do faster and simpler sorting */
2282 for(k
= 0; k
< 5; k
++) {
2283 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2284 s
= s1
->sections
[i
];
2285 /* compute if section should be included */
2287 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
2291 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
2292 (SHF_ALLOC
| SHF_WRITE
))
2298 } else if (s
->sh_type
== SHT_DYNSYM
||
2299 s
->sh_type
== SHT_STRTAB
||
2300 s
->sh_type
== SHT_HASH
) {
2303 } else if (s
->sh_type
== SHT_RELX
) {
2306 } else if (s
->sh_type
== SHT_NOBITS
) {
2313 sec_order
[sh_order_index
++] = i
;
2315 /* section matches: we align it and add its size */
2317 addr
= (addr
+ s
->sh_addralign
- 1) &
2318 ~(s
->sh_addralign
- 1);
2319 file_offset
+= (int) ( addr
- tmp
);
2320 s
->sh_offset
= file_offset
;
2323 /* update program header infos */
2324 if (ph
->p_offset
== 0) {
2325 ph
->p_offset
= file_offset
;
2327 ph
->p_paddr
= ph
->p_vaddr
;
2329 /* update dynamic relocation infos */
2330 if (s
->sh_type
== SHT_RELX
) {
2331 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2332 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.got")) {
2333 dyninf
->rel_addr
= addr
;
2334 dyninf
->rel_size
+= s
->sh_size
; /* XXX only first rel. */
2336 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.bss")) {
2337 dyninf
->bss_addr
= addr
;
2338 dyninf
->bss_size
= s
->sh_size
; /* XXX only first rel. */
2341 if (dyninf
->rel_size
== 0)
2342 dyninf
->rel_addr
= addr
;
2343 dyninf
->rel_size
+= s
->sh_size
;
2347 if (s
->sh_type
!= SHT_NOBITS
)
2348 file_offset
+= s
->sh_size
;
2352 /* Make the first PT_LOAD segment include the program
2353 headers itself (and the ELF header as well), it'll
2354 come out with same memory use but will make various
2355 tools like binutils strip work better. */
2356 ph
->p_offset
&= ~(ph
->p_align
- 1);
2357 ph
->p_vaddr
&= ~(ph
->p_align
- 1);
2358 ph
->p_paddr
&= ~(ph
->p_align
- 1);
2360 ph
->p_filesz
= file_offset
- ph
->p_offset
;
2361 ph
->p_memsz
= addr
- ph
->p_vaddr
;
2364 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
2365 /* if in the middle of a page, we duplicate the page in
2366 memory so that one copy is RX and the other is RW */
2367 if ((addr
& (s_align
- 1)) != 0)
2370 addr
= (addr
+ s_align
- 1) & ~(s_align
- 1);
2371 file_offset
= (file_offset
+ s_align
- 1) & ~(s_align
- 1);
2377 /* all other sections come after */
2378 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2379 s
= s1
->sections
[i
];
2380 if (phnum
> 0 && (s
->sh_flags
& SHF_ALLOC
))
2382 sec_order
[sh_order_index
++] = i
;
2384 file_offset
= (file_offset
+ s
->sh_addralign
- 1) &
2385 ~(s
->sh_addralign
- 1);
2386 s
->sh_offset
= file_offset
;
2387 if (s
->sh_type
!= SHT_NOBITS
)
2388 file_offset
+= s
->sh_size
;
2394 static void fill_unloadable_phdr(ElfW(Phdr
) *phdr
, int phnum
, Section
*interp
,
2399 /* if interpreter, then add corresponding program header */
2405 int len
= phnum
* sizeof(ElfW(Phdr
));
2407 ph
->p_type
= PT_PHDR
;
2408 ph
->p_offset
= sizeof(ElfW(Ehdr
));
2409 ph
->p_vaddr
= interp
->sh_addr
- len
;
2410 ph
->p_paddr
= ph
->p_vaddr
;
2411 ph
->p_filesz
= ph
->p_memsz
= len
;
2412 ph
->p_flags
= PF_R
| PF_X
;
2413 ph
->p_align
= 4; /* interp->sh_addralign; */
2417 ph
->p_type
= PT_INTERP
;
2418 ph
->p_offset
= interp
->sh_offset
;
2419 ph
->p_vaddr
= interp
->sh_addr
;
2420 ph
->p_paddr
= ph
->p_vaddr
;
2421 ph
->p_filesz
= interp
->sh_size
;
2422 ph
->p_memsz
= interp
->sh_size
;
2424 ph
->p_align
= interp
->sh_addralign
;
2427 /* if dynamic section, then add corresponding program header */
2429 ph
= &phdr
[phnum
- 1];
2431 ph
->p_type
= PT_DYNAMIC
;
2432 ph
->p_offset
= dynamic
->sh_offset
;
2433 ph
->p_vaddr
= dynamic
->sh_addr
;
2434 ph
->p_paddr
= ph
->p_vaddr
;
2435 ph
->p_filesz
= dynamic
->sh_size
;
2436 ph
->p_memsz
= dynamic
->sh_size
;
2437 ph
->p_flags
= PF_R
| PF_W
;
2438 ph
->p_align
= dynamic
->sh_addralign
;
2442 /* Fill the dynamic section with tags describing the address and size of
2444 static void fill_dynamic(TCCState
*s1
, struct dyn_inf
*dyninf
)
2448 dynamic
= dyninf
->dynamic
;
2450 /* put dynamic section entries */
2451 dynamic
->data_offset
= dyninf
->dyn_rel_off
;
2452 put_dt(dynamic
, DT_HASH
, s1
->dynsym
->hash
->sh_addr
);
2453 put_dt(dynamic
, DT_STRTAB
, dyninf
->dynstr
->sh_addr
);
2454 put_dt(dynamic
, DT_SYMTAB
, s1
->dynsym
->sh_addr
);
2455 put_dt(dynamic
, DT_STRSZ
, dyninf
->dynstr
->data_offset
);
2456 put_dt(dynamic
, DT_SYMENT
, sizeof(ElfW(Sym
)));
2457 #if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
2458 put_dt(dynamic
, DT_RELA
, dyninf
->rel_addr
);
2459 put_dt(dynamic
, DT_RELASZ
, dyninf
->rel_size
);
2460 put_dt(dynamic
, DT_RELAENT
, sizeof(ElfW_Rel
));
2462 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2463 put_dt(dynamic
, DT_PLTGOT
, s1
->got
->sh_addr
);
2464 put_dt(dynamic
, DT_PLTRELSZ
, dyninf
->rel_size
);
2465 put_dt(dynamic
, DT_JMPREL
, dyninf
->rel_addr
);
2466 put_dt(dynamic
, DT_PLTREL
, DT_REL
);
2467 put_dt(dynamic
, DT_REL
, dyninf
->bss_addr
);
2468 put_dt(dynamic
, DT_RELSZ
, dyninf
->bss_size
);
2470 put_dt(dynamic
, DT_REL
, dyninf
->rel_addr
);
2471 put_dt(dynamic
, DT_RELSZ
, dyninf
->rel_size
);
2472 put_dt(dynamic
, DT_RELENT
, sizeof(ElfW_Rel
));
2476 put_dt(dynamic
, DT_DEBUG
, 0);
2477 put_dt(dynamic
, DT_NULL
, 0);
2480 /* Relocate remaining sections and symbols (that is those not related to
2482 static int final_sections_reloc(TCCState
*s1
)
2487 relocate_syms(s1
, 0);
2489 if (s1
->nb_errors
!= 0)
2492 /* relocate sections */
2493 /* XXX: ignore sections with allocated relocations ? */
2494 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2495 s
= s1
->sections
[i
];
2496 #ifdef TCC_TARGET_I386
2497 if (s
->reloc
&& s
!= s1
->got
&& (s
->sh_flags
& SHF_ALLOC
)) //gr
2498 /* On X86 gdb 7.3 works in any case but gdb 6.6 will crash if SHF_ALLOC
2499 checking is removed */
2501 if (s
->reloc
&& s
!= s1
->got
)
2502 /* On X86_64 gdb 7.3 will crash if SHF_ALLOC checking is present */
2504 relocate_section(s1
, s
);
2507 /* relocate relocation entries if the relocation tables are
2508 allocated in the executable */
2509 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2510 s
= s1
->sections
[i
];
2511 if ((s
->sh_flags
& SHF_ALLOC
) &&
2512 s
->sh_type
== SHT_RELX
) {
2513 relocate_rel(s1
, s
);
2519 /* Create an ELF file on disk.
2520 This function handle ELF specific layout requirements */
2521 static void tcc_output_elf(TCCState
*s1
, FILE *f
, int phnum
, ElfW(Phdr
) *phdr
,
2522 int file_offset
, int *sec_order
)
2524 int i
, shnum
, offset
, size
, file_type
;
2527 ElfW(Shdr
) shdr
, *sh
;
2529 file_type
= s1
->output_type
;
2530 shnum
= s1
->nb_sections
;
2532 memset(&ehdr
, 0, sizeof(ehdr
));
2535 ehdr
.e_phentsize
= sizeof(ElfW(Phdr
));
2536 ehdr
.e_phnum
= phnum
;
2537 ehdr
.e_phoff
= sizeof(ElfW(Ehdr
));
2541 file_offset
= (file_offset
+ 3) & -4;
2544 ehdr
.e_ident
[0] = ELFMAG0
;
2545 ehdr
.e_ident
[1] = ELFMAG1
;
2546 ehdr
.e_ident
[2] = ELFMAG2
;
2547 ehdr
.e_ident
[3] = ELFMAG3
;
2548 ehdr
.e_ident
[4] = ELFCLASSW
;
2549 ehdr
.e_ident
[5] = ELFDATA2LSB
;
2550 ehdr
.e_ident
[6] = EV_CURRENT
;
2551 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2552 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_FREEBSD
;
2554 #ifdef TCC_TARGET_ARM
2556 ehdr
.e_ident
[EI_OSABI
] = 0;
2557 ehdr
.e_flags
= EF_ARM_EABI_VER4
;
2558 if (file_type
== TCC_OUTPUT_EXE
|| file_type
== TCC_OUTPUT_DLL
)
2559 ehdr
.e_flags
|= EF_ARM_HASENTRY
;
2560 if (s1
->float_abi
== ARM_HARD_FLOAT
)
2561 ehdr
.e_flags
|= EF_ARM_VFP_FLOAT
;
2563 ehdr
.e_flags
|= EF_ARM_SOFT_FLOAT
;
2565 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_ARM
;
2570 case TCC_OUTPUT_EXE
:
2571 ehdr
.e_type
= ET_EXEC
;
2572 ehdr
.e_entry
= get_elf_sym_addr(s1
, "_start", 1);
2574 case TCC_OUTPUT_DLL
:
2575 ehdr
.e_type
= ET_DYN
;
2576 ehdr
.e_entry
= text_section
->sh_addr
; /* XXX: is it correct ? */
2578 case TCC_OUTPUT_OBJ
:
2579 ehdr
.e_type
= ET_REL
;
2582 ehdr
.e_machine
= EM_TCC_TARGET
;
2583 ehdr
.e_version
= EV_CURRENT
;
2584 ehdr
.e_shoff
= file_offset
;
2585 ehdr
.e_ehsize
= sizeof(ElfW(Ehdr
));
2586 ehdr
.e_shentsize
= sizeof(ElfW(Shdr
));
2587 ehdr
.e_shnum
= shnum
;
2588 ehdr
.e_shstrndx
= shnum
- 1;
2590 fwrite(&ehdr
, 1, sizeof(ElfW(Ehdr
)), f
);
2591 fwrite(phdr
, 1, phnum
* sizeof(ElfW(Phdr
)), f
);
2592 offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
2594 sort_syms(s1
, symtab_section
);
2595 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2596 s
= s1
->sections
[sec_order
[i
]];
2597 if (s
->sh_type
!= SHT_NOBITS
) {
2598 if (s
->sh_type
== SHT_DYNSYM
)
2599 patch_dynsym_undef(s1
, s
);
2600 while (offset
< s
->sh_offset
) {
2606 fwrite(s
->data
, 1, size
, f
);
2611 /* output section headers */
2612 while (offset
< ehdr
.e_shoff
) {
2617 for(i
= 0; i
< s1
->nb_sections
; i
++) {
2619 memset(sh
, 0, sizeof(ElfW(Shdr
)));
2620 s
= s1
->sections
[i
];
2622 sh
->sh_name
= s
->sh_name
;
2623 sh
->sh_type
= s
->sh_type
;
2624 sh
->sh_flags
= s
->sh_flags
;
2625 sh
->sh_entsize
= s
->sh_entsize
;
2626 sh
->sh_info
= s
->sh_info
;
2628 sh
->sh_link
= s
->link
->sh_num
;
2629 sh
->sh_addralign
= s
->sh_addralign
;
2630 sh
->sh_addr
= s
->sh_addr
;
2631 sh
->sh_offset
= s
->sh_offset
;
2632 sh
->sh_size
= s
->sh_size
;
2634 fwrite(sh
, 1, sizeof(ElfW(Shdr
)), f
);
2638 /* Write an elf, coff or "binary" file */
2639 static int tcc_write_elf_file(TCCState
*s1
, const char *filename
, int phnum
,
2640 ElfW(Phdr
) *phdr
, int file_offset
, int *sec_order
)
2642 int fd
, mode
, file_type
;
2645 file_type
= s1
->output_type
;
2646 if (file_type
== TCC_OUTPUT_OBJ
)
2651 fd
= open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
, mode
);
2653 tcc_error_noabort("could not write '%s'", filename
);
2656 f
= fdopen(fd
, "wb");
2658 printf("<- %s\n", filename
);
2660 #ifdef TCC_TARGET_COFF
2661 if (s1
->output_format
== TCC_OUTPUT_FORMAT_COFF
)
2662 tcc_output_coff(s1
, f
);
2665 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
)
2666 tcc_output_elf(s1
, f
, phnum
, phdr
, file_offset
, sec_order
);
2668 tcc_output_binary(s1
, f
, sec_order
);
2674 /* Output an elf, coff or binary file */
2675 /* XXX: suppress unneeded sections */
2676 static int elf_output_file(TCCState
*s1
, const char *filename
)
2678 int i
, ret
, phnum
, shnum
, file_type
, file_offset
, *sec_order
;
2679 struct dyn_inf dyninf
;
2682 Section
*strsec
, *interp
, *dynamic
, *dynstr
;
2684 file_type
= s1
->output_type
;
2687 /* if linking, also link in runtime libraries (libc, libgcc, etc.) */
2688 if (file_type
!= TCC_OUTPUT_OBJ
) {
2689 tcc_add_runtime(s1
);
2694 interp
= dynamic
= dynstr
= NULL
; /* avoid warning */
2695 dyninf
.dyn_rel_off
= 0; /* avoid warning */
2697 if (file_type
!= TCC_OUTPUT_OBJ
) {
2698 relocate_common_syms();
2700 tcc_add_linker_symbols(s1
);
2702 if (!s1
->static_link
) {
2703 if (file_type
== TCC_OUTPUT_EXE
) {
2705 /* allow override the dynamic loader */
2706 const char *elfint
= getenv("LD_SO");
2708 elfint
= DEFAULT_ELFINTERP(s1
);
2709 /* add interpreter section only if executable */
2710 interp
= new_section(s1
, ".interp", SHT_PROGBITS
, SHF_ALLOC
);
2711 interp
->sh_addralign
= 1;
2712 ptr
= section_ptr_add(interp
, 1 + strlen(elfint
));
2713 strcpy(ptr
, elfint
);
2716 /* add dynamic symbol table */
2717 s1
->dynsym
= new_symtab(s1
, ".dynsym", SHT_DYNSYM
, SHF_ALLOC
,
2719 ".hash", SHF_ALLOC
);
2720 dynstr
= s1
->dynsym
->link
;
2722 /* add dynamic section */
2723 dynamic
= new_section(s1
, ".dynamic", SHT_DYNAMIC
,
2724 SHF_ALLOC
| SHF_WRITE
);
2725 dynamic
->link
= dynstr
;
2726 dynamic
->sh_entsize
= sizeof(ElfW(Dyn
));
2730 if (file_type
== TCC_OUTPUT_EXE
) {
2731 bind_exe_dynsyms(s1
);
2733 if (s1
->nb_errors
) {
2738 bind_libs_dynsyms(s1
);
2739 } else /* shared library case: simply export all global symbols */
2740 export_global_syms(s1
);
2742 build_got_entries(s1
);
2744 /* add a list of needed dlls */
2745 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
2746 DLLReference
*dllref
= s1
->loaded_dlls
[i
];
2747 if (dllref
->level
== 0)
2748 put_dt(dynamic
, DT_NEEDED
, put_elf_str(dynstr
, dllref
->name
));
2752 put_dt(dynamic
, DT_RPATH
, put_elf_str(dynstr
, s1
->rpath
));
2754 /* XXX: currently, since we do not handle PIC code, we
2755 must relocate the readonly segments */
2756 if (file_type
== TCC_OUTPUT_DLL
) {
2758 put_dt(dynamic
, DT_SONAME
, put_elf_str(dynstr
, s1
->soname
));
2759 put_dt(dynamic
, DT_TEXTREL
, 0);
2763 put_dt(dynamic
, DT_SYMBOLIC
, 0);
2765 /* add necessary space for other entries */
2766 dyninf
.dyn_rel_off
= dynamic
->data_offset
;
2767 dynamic
->data_offset
+= sizeof(ElfW(Dyn
)) * EXTRA_RELITEMS
;
2769 /* still need to build got entries in case of static link */
2770 build_got_entries(s1
);
2774 /* we add a section for symbols */
2775 strsec
= new_section(s1
, ".shstrtab", SHT_STRTAB
, 0);
2776 put_elf_str(strsec
, "");
2778 /* compute number of sections */
2779 shnum
= s1
->nb_sections
;
2781 /* this array is used to reorder sections in the output file */
2782 sec_order
= tcc_malloc(sizeof(int) * shnum
);
2785 /* compute number of program headers */
2788 case TCC_OUTPUT_OBJ
:
2791 case TCC_OUTPUT_EXE
:
2792 if (!s1
->static_link
)
2793 phnum
= 4 + HAVE_PHDR
;
2797 case TCC_OUTPUT_DLL
:
2802 /* Allocate strings for section names */
2803 alloc_sec_names(s1
, file_type
, strsec
);
2805 /* allocate program segment headers */
2806 phdr
= tcc_mallocz(phnum
* sizeof(ElfW(Phdr
)));
2808 /* compute section to program header mapping */
2809 file_offset
= layout_sections(s1
, phdr
, phnum
, interp
, strsec
, &dyninf
,
2812 /* Fill remaining program header and finalize relocation related to dynamic
2815 fill_unloadable_phdr(phdr
, phnum
, interp
, dynamic
);
2817 dyninf
.dynamic
= dynamic
;
2818 dyninf
.dynstr
= dynstr
;
2820 fill_dynamic(s1
, &dyninf
);
2822 /* put in GOT the dynamic section address and relocate PLT */
2823 write32le(s1
->got
->data
, dynamic
->sh_addr
);
2824 if (file_type
== TCC_OUTPUT_EXE
2825 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2826 || file_type
== TCC_OUTPUT_DLL
2831 /* relocate symbols in .dynsym now that final addresses are known */
2832 for_each_elem(s1
->dynsym
, 1, sym
, ElfW(Sym
)) {
2833 if (sym
->st_shndx
== SHN_UNDEF
) {
2834 /* relocate to PLT if symbol corresponds to a PLT entry,
2835 but not if it's a weak symbol */
2836 if (ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
2838 else if (sym
->st_value
)
2839 sym
->st_value
+= s1
->plt
->sh_addr
;
2840 } else if (sym
->st_shndx
< SHN_LORESERVE
) {
2841 /* do symbol relocation */
2842 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
2848 /* if building executable or DLL, then relocate each section
2849 except the GOT which is already relocated */
2850 if (file_type
!= TCC_OUTPUT_OBJ
) {
2851 ret
= final_sections_reloc(s1
);
2856 /* Perform relocation to GOT or PLT entries */
2857 if (file_type
== TCC_OUTPUT_EXE
&& s1
->static_link
)
2860 /* Create the ELF file with name 'filename' */
2861 ret
= tcc_write_elf_file(s1
, filename
, phnum
, phdr
, file_offset
, sec_order
);
2863 tcc_free(s1
->symtab_to_dynsym
);
2864 tcc_free(sec_order
);
2866 tcc_free(s1
->sym_attrs
);
2867 s1
->sym_attrs
= NULL
;
2871 LIBTCCAPI
int tcc_output_file(TCCState
*s
, const char *filename
)
2874 #ifdef TCC_TARGET_PE
2875 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
2876 ret
= pe_output_file(s
, filename
);
2879 ret
= elf_output_file(s
, filename
);
2883 static void *load_data(int fd
, unsigned long file_offset
, unsigned long size
)
2887 data
= tcc_malloc(size
);
2888 lseek(fd
, file_offset
, SEEK_SET
);
2889 read(fd
, data
, size
);
2893 typedef struct SectionMergeInfo
{
2894 Section
*s
; /* corresponding existing section */
2895 unsigned long offset
; /* offset of the new section in the existing section */
2896 uint8_t new_section
; /* true if section 's' was added */
2897 uint8_t link_once
; /* true if link once section */
2900 ST_FUNC
int tcc_object_type(int fd
, ElfW(Ehdr
) *h
)
2902 int size
= read(fd
, h
, sizeof *h
);
2903 if (size
== sizeof *h
&& 0 == memcmp(h
, ELFMAG
, 4)) {
2904 if (h
->e_type
== ET_REL
)
2905 return AFF_BINTYPE_REL
;
2906 if (h
->e_type
== ET_DYN
)
2907 return AFF_BINTYPE_DYN
;
2908 } else if (size
>= 8) {
2909 if (0 == memcmp(h
, ARMAG
, 8))
2910 return AFF_BINTYPE_AR
;
2911 #ifdef TCC_TARGET_COFF
2912 if (((struct filehdr
*)h
)->f_magic
== COFF_C67_MAGIC
)
2913 return AFF_BINTYPE_C67
;
2919 /* load an object file and merge it with current files */
2920 /* XXX: handle correctly stab (debug) info */
2921 ST_FUNC
int tcc_load_object_file(TCCState
*s1
,
2922 int fd
, unsigned long file_offset
)
2925 ElfW(Shdr
) *shdr
, *sh
;
2926 int size
, i
, j
, offset
, offseti
, nb_syms
, sym_index
, ret
;
2927 unsigned char *strsec
, *strtab
;
2928 int *old_to_new_syms
;
2929 char *sh_name
, *name
;
2930 SectionMergeInfo
*sm_table
, *sm
;
2931 ElfW(Sym
) *sym
, *symtab
;
2938 stab_index
= stabstr_index
= 0;
2940 lseek(fd
, file_offset
, SEEK_SET
);
2941 if (tcc_object_type(fd
, &ehdr
) != AFF_BINTYPE_REL
)
2943 /* test CPU specific stuff */
2944 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2945 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2947 tcc_error_noabort("invalid object file");
2951 shdr
= load_data(fd
, file_offset
+ ehdr
.e_shoff
,
2952 sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2953 sm_table
= tcc_mallocz(sizeof(SectionMergeInfo
) * ehdr
.e_shnum
);
2955 /* load section names */
2956 sh
= &shdr
[ehdr
.e_shstrndx
];
2957 strsec
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2959 /* load symtab and strtab */
2960 old_to_new_syms
= NULL
;
2964 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2966 if (sh
->sh_type
== SHT_SYMTAB
) {
2968 tcc_error_noabort("object must contain only one symtab");
2973 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2974 symtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2975 sm_table
[i
].s
= symtab_section
;
2977 /* now load strtab */
2978 sh
= &shdr
[sh
->sh_link
];
2979 strtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2983 /* now examine each section and try to merge its content with the
2985 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2986 /* no need to examine section name strtab */
2987 if (i
== ehdr
.e_shstrndx
)
2990 sh_name
= (char *) strsec
+ sh
->sh_name
;
2991 /* ignore sections types we do not handle */
2992 if (sh
->sh_type
!= SHT_PROGBITS
&&
2993 sh
->sh_type
!= SHT_RELX
&&
2995 sh
->sh_type
!= SHT_ARM_EXIDX
&&
2997 sh
->sh_type
!= SHT_NOBITS
&&
2998 sh
->sh_type
!= SHT_PREINIT_ARRAY
&&
2999 sh
->sh_type
!= SHT_INIT_ARRAY
&&
3000 sh
->sh_type
!= SHT_FINI_ARRAY
&&
3001 strcmp(sh_name
, ".stabstr")
3004 if (sh
->sh_addralign
< 1)
3005 sh
->sh_addralign
= 1;
3006 /* find corresponding section, if any */
3007 for(j
= 1; j
< s1
->nb_sections
;j
++) {
3008 s
= s1
->sections
[j
];
3009 if (!strcmp(s
->name
, sh_name
)) {
3010 if (!strncmp(sh_name
, ".gnu.linkonce",
3011 sizeof(".gnu.linkonce") - 1)) {
3012 /* if a 'linkonce' section is already present, we
3013 do not add it again. It is a little tricky as
3014 symbols can still be defined in
3016 sm_table
[i
].link_once
= 1;
3023 /* not found: create new section */
3024 s
= new_section(s1
, sh_name
, sh
->sh_type
, sh
->sh_flags
);
3025 /* take as much info as possible from the section. sh_link and
3026 sh_info will be updated later */
3027 s
->sh_addralign
= sh
->sh_addralign
;
3028 s
->sh_entsize
= sh
->sh_entsize
;
3029 sm_table
[i
].new_section
= 1;
3031 if (sh
->sh_type
!= s
->sh_type
) {
3032 tcc_error_noabort("invalid section type");
3036 /* align start of section */
3037 offset
= s
->data_offset
;
3039 if (0 == strcmp(sh_name
, ".stab")) {
3043 if (0 == strcmp(sh_name
, ".stabstr")) {
3048 size
= sh
->sh_addralign
- 1;
3049 offset
= (offset
+ size
) & ~size
;
3050 if (sh
->sh_addralign
> s
->sh_addralign
)
3051 s
->sh_addralign
= sh
->sh_addralign
;
3052 s
->data_offset
= offset
;
3054 sm_table
[i
].offset
= offset
;
3056 /* concatenate sections */
3058 if (sh
->sh_type
!= SHT_NOBITS
) {
3060 lseek(fd
, file_offset
+ sh
->sh_offset
, SEEK_SET
);
3061 ptr
= section_ptr_add(s
, size
);
3062 read(fd
, ptr
, size
);
3064 s
->data_offset
+= size
;
3069 /* gr relocate stab strings */
3070 if (stab_index
&& stabstr_index
) {
3073 s
= sm_table
[stab_index
].s
;
3074 a
= (Stab_Sym
*)(s
->data
+ sm_table
[stab_index
].offset
);
3075 b
= (Stab_Sym
*)(s
->data
+ s
->data_offset
);
3076 o
= sm_table
[stabstr_index
].offset
;
3078 a
->n_strx
+= o
, a
++;
3081 /* second short pass to update sh_link and sh_info fields of new
3083 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
3085 if (!s
|| !sm_table
[i
].new_section
)
3088 if (sh
->sh_link
> 0)
3089 s
->link
= sm_table
[sh
->sh_link
].s
;
3090 if (sh
->sh_type
== SHT_RELX
) {
3091 s
->sh_info
= sm_table
[sh
->sh_info
].s
->sh_num
;
3092 /* update backward link */
3093 s1
->sections
[s
->sh_info
]->reloc
= s
;
3098 /* resolve symbols */
3099 old_to_new_syms
= tcc_mallocz(nb_syms
* sizeof(int));
3102 for(i
= 1; i
< nb_syms
; i
++, sym
++) {
3103 if (sym
->st_shndx
!= SHN_UNDEF
&&
3104 sym
->st_shndx
< SHN_LORESERVE
) {
3105 sm
= &sm_table
[sym
->st_shndx
];
3106 if (sm
->link_once
) {
3107 /* if a symbol is in a link once section, we use the
3108 already defined symbol. It is very important to get
3109 correct relocations */
3110 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
3111 name
= (char *) strtab
+ sym
->st_name
;
3112 sym_index
= find_elf_sym(symtab_section
, name
);
3114 old_to_new_syms
[i
] = sym_index
;
3118 /* if no corresponding section added, no need to add symbol */
3121 /* convert section number */
3122 sym
->st_shndx
= sm
->s
->sh_num
;
3124 sym
->st_value
+= sm
->offset
;
3127 name
= (char *) strtab
+ sym
->st_name
;
3128 sym_index
= add_elf_sym(symtab_section
, sym
->st_value
, sym
->st_size
,
3129 sym
->st_info
, sym
->st_other
,
3130 sym
->st_shndx
, name
);
3131 old_to_new_syms
[i
] = sym_index
;
3134 /* third pass to patch relocation entries */
3135 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
3140 offset
= sm_table
[i
].offset
;
3141 switch(s
->sh_type
) {
3143 /* take relocation offset information */
3144 offseti
= sm_table
[sh
->sh_info
].offset
;
3145 for_each_elem(s
, (offset
/ sizeof(*rel
)), rel
, ElfW_Rel
) {
3148 /* convert symbol index */
3149 type
= ELFW(R_TYPE
)(rel
->r_info
);
3150 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
3151 /* NOTE: only one symtab assumed */
3152 if (sym_index
>= nb_syms
)
3154 sym_index
= old_to_new_syms
[sym_index
];
3155 /* ignore link_once in rel section. */
3156 if (!sym_index
&& !sm
->link_once
3157 #ifdef TCC_TARGET_ARM
3158 && type
!= R_ARM_V4BX
3162 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
3163 i
, strsec
+ sh
->sh_name
, rel
->r_offset
);
3166 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
3167 /* offset the relocation offset */
3168 rel
->r_offset
+= offseti
;
3169 #ifdef TCC_TARGET_ARM
3170 /* Jumps and branches from a Thumb code to a PLT entry need
3171 special handling since PLT entries are ARM code.
3172 Unconditional bl instructions referencing PLT entries are
3173 handled by converting these instructions into blx
3174 instructions. Other case of instructions referencing a PLT
3175 entry require to add a Thumb stub before the PLT entry to
3176 switch to ARM mode. We set bit plt_thumb_stub of the
3177 attribute of a symbol to indicate such a case. */
3178 if (type
== R_ARM_THM_JUMP24
)
3179 alloc_sym_attr(s1
, sym_index
)->plt_thumb_stub
= 1;
3192 tcc_free(old_to_new_syms
);
3199 typedef struct ArchiveHeader
{
3200 char ar_name
[16]; /* name of this member */
3201 char ar_date
[12]; /* file mtime */
3202 char ar_uid
[6]; /* owner uid; printed as decimal */
3203 char ar_gid
[6]; /* owner gid; printed as decimal */
3204 char ar_mode
[8]; /* file mode, printed as octal */
3205 char ar_size
[10]; /* file size, printed as decimal */
3206 char ar_fmag
[2]; /* should contain ARFMAG */
3209 static int get_be32(const uint8_t *b
)
3211 return b
[3] | (b
[2] << 8) | (b
[1] << 16) | (b
[0] << 24);
3214 static long get_be64(const uint8_t *b
)
3216 long long ret
= get_be32(b
);
3217 ret
= (ret
<< 32) | (unsigned)get_be32(b
+4);
3221 /* load only the objects which resolve undefined symbols */
3222 static int tcc_load_alacarte(TCCState
*s1
, int fd
, int size
, int entrysize
)
3224 long i
, bound
, nsyms
, sym_index
, off
, ret
;
3226 const char *ar_names
, *p
;
3227 const uint8_t *ar_index
;
3230 data
= tcc_malloc(size
);
3231 if (read(fd
, data
, size
) != size
)
3233 nsyms
= entrysize
== 4 ? get_be32(data
) : get_be64(data
);
3234 ar_index
= data
+ entrysize
;
3235 ar_names
= (char *) ar_index
+ nsyms
* entrysize
;
3239 for(p
= ar_names
, i
= 0; i
< nsyms
; i
++, p
+= strlen(p
)+1) {
3240 sym_index
= find_elf_sym(symtab_section
, p
);
3242 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
3243 if(sym
->st_shndx
== SHN_UNDEF
) {
3244 off
= (entrysize
== 4
3245 ? get_be32(ar_index
+ i
* 4)
3246 : get_be64(ar_index
+ i
* 8))
3247 + sizeof(ArchiveHeader
);
3249 if(tcc_load_object_file(s1
, fd
, off
) < 0) {
3264 /* load a '.a' file */
3265 ST_FUNC
int tcc_load_archive(TCCState
*s1
, int fd
)
3272 unsigned long file_offset
;
3274 /* skip magic which was already checked */
3275 read(fd
, magic
, sizeof(magic
));
3278 len
= read(fd
, &hdr
, sizeof(hdr
));
3281 if (len
!= sizeof(hdr
)) {
3282 tcc_error_noabort("invalid archive");
3285 memcpy(ar_size
, hdr
.ar_size
, sizeof(hdr
.ar_size
));
3286 ar_size
[sizeof(hdr
.ar_size
)] = '\0';
3287 size
= strtol(ar_size
, NULL
, 0);
3288 memcpy(ar_name
, hdr
.ar_name
, sizeof(hdr
.ar_name
));
3289 for(i
= sizeof(hdr
.ar_name
) - 1; i
>= 0; i
--) {
3290 if (ar_name
[i
] != ' ')
3293 ar_name
[i
+ 1] = '\0';
3294 file_offset
= lseek(fd
, 0, SEEK_CUR
);
3296 size
= (size
+ 1) & ~1;
3297 if (!strcmp(ar_name
, "/")) {
3298 /* coff symbol table : we handle it */
3299 if(s1
->alacarte_link
)
3300 return tcc_load_alacarte(s1
, fd
, size
, 4);
3301 } else if (!strcmp(ar_name
, "/SYM64/")) {
3302 if(s1
->alacarte_link
)
3303 return tcc_load_alacarte(s1
, fd
, size
, 8);
3306 if (tcc_object_type(fd
, &ehdr
) == AFF_BINTYPE_REL
) {
3307 if (tcc_load_object_file(s1
, fd
, file_offset
) < 0)
3311 lseek(fd
, file_offset
+ size
, SEEK_SET
);
3316 #ifndef TCC_TARGET_PE
3317 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
3318 is referenced by the user (so it should be added as DT_NEEDED in
3319 the generated ELF file) */
3320 ST_FUNC
int tcc_load_dll(TCCState
*s1
, int fd
, const char *filename
, int level
)
3323 ElfW(Shdr
) *shdr
, *sh
, *sh1
;
3324 int i
, j
, nb_syms
, nb_dts
, sym_bind
, ret
;
3325 ElfW(Sym
) *sym
, *dynsym
;
3326 ElfW(Dyn
) *dt
, *dynamic
;
3327 unsigned char *dynstr
;
3328 const char *name
, *soname
;
3329 DLLReference
*dllref
;
3331 read(fd
, &ehdr
, sizeof(ehdr
));
3333 /* test CPU specific stuff */
3334 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
3335 ehdr
.e_machine
!= EM_TCC_TARGET
) {
3336 tcc_error_noabort("bad architecture");
3341 shdr
= load_data(fd
, ehdr
.e_shoff
, sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
3343 /* load dynamic section and dynamic symbols */
3347 dynsym
= NULL
; /* avoid warning */
3348 dynstr
= NULL
; /* avoid warning */
3349 for(i
= 0, sh
= shdr
; i
< ehdr
.e_shnum
; i
++, sh
++) {
3350 switch(sh
->sh_type
) {
3352 nb_dts
= sh
->sh_size
/ sizeof(ElfW(Dyn
));
3353 dynamic
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
3356 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
3357 dynsym
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
3358 sh1
= &shdr
[sh
->sh_link
];
3359 dynstr
= load_data(fd
, sh1
->sh_offset
, sh1
->sh_size
);
3366 /* compute the real library name */
3367 soname
= tcc_basename(filename
);
3369 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
3370 if (dt
->d_tag
== DT_SONAME
) {
3371 soname
= (char *) dynstr
+ dt
->d_un
.d_val
;
3375 /* if the dll is already loaded, do not load it */
3376 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
3377 dllref
= s1
->loaded_dlls
[i
];
3378 if (!strcmp(soname
, dllref
->name
)) {
3379 /* but update level if needed */
3380 if (level
< dllref
->level
)
3381 dllref
->level
= level
;
3387 /* add the dll and its level */
3388 dllref
= tcc_mallocz(sizeof(DLLReference
) + strlen(soname
));
3389 dllref
->level
= level
;
3390 strcpy(dllref
->name
, soname
);
3391 dynarray_add((void ***)&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
, dllref
);
3393 /* add dynamic symbols in dynsym_section */
3394 for(i
= 1, sym
= dynsym
+ 1; i
< nb_syms
; i
++, sym
++) {
3395 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
3396 if (sym_bind
== STB_LOCAL
)
3398 name
= (char *) dynstr
+ sym
->st_name
;
3399 add_elf_sym(s1
->dynsymtab_section
, sym
->st_value
, sym
->st_size
,
3400 sym
->st_info
, sym
->st_other
, sym
->st_shndx
, name
);
3403 /* load all referenced DLLs */
3404 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
3407 name
= (char *) dynstr
+ dt
->d_un
.d_val
;
3408 for(j
= 0; j
< s1
->nb_loaded_dlls
; j
++) {
3409 dllref
= s1
->loaded_dlls
[j
];
3410 if (!strcmp(name
, dllref
->name
))
3411 goto already_loaded
;
3413 if (tcc_add_dll(s1
, name
, AFF_REFERENCED_DLL
) < 0) {
3414 tcc_error_noabort("referenced dll '%s' not found", name
);
3431 #define LD_TOK_NAME 256
3432 #define LD_TOK_EOF (-1)
3434 /* return next ld script token */
3435 static int ld_next(TCCState
*s1
, char *name
, int name_size
)
3453 file
->buf_ptr
= parse_comment(file
->buf_ptr
);
3454 ch
= file
->buf_ptr
[0];
3467 /* case 'a' ... 'z': */
3494 /* case 'A' ... 'z': */
3528 if (!((ch
>= 'a' && ch
<= 'z') ||
3529 (ch
>= 'A' && ch
<= 'Z') ||
3530 (ch
>= '0' && ch
<= '9') ||
3531 strchr("/.-_+=$:\\,~", ch
)))
3533 if ((q
- name
) < name_size
- 1) {
3552 static int ld_add_file(TCCState
*s1
, const char filename
[])
3556 ret
= tcc_add_file_internal(s1
, filename
, AFF_TYPE_BIN
);
3558 ret
= tcc_add_dll(s1
, filename
, 0);
3562 static inline int new_undef_syms(void)
3565 ret
= new_undef_sym
;
3570 static int ld_add_file_list(TCCState
*s1
, const char *cmd
, int as_needed
)
3572 char filename
[1024], libname
[1024];
3573 int t
, group
, nblibs
= 0, ret
= 0;
3576 group
= !strcmp(cmd
, "GROUP");
3579 t
= ld_next(s1
, filename
, sizeof(filename
));
3582 t
= ld_next(s1
, filename
, sizeof(filename
));
3585 if (t
== LD_TOK_EOF
) {
3586 tcc_error_noabort("unexpected end of file");
3588 goto lib_parse_error
;
3589 } else if (t
== ')') {
3591 } else if (t
== '-') {
3592 t
= ld_next(s1
, filename
, sizeof(filename
));
3593 if ((t
!= LD_TOK_NAME
) || (filename
[0] != 'l')) {
3594 tcc_error_noabort("library name expected");
3596 goto lib_parse_error
;
3598 pstrcpy(libname
, sizeof libname
, &filename
[1]);
3599 if (s1
->static_link
) {
3600 snprintf(filename
, sizeof filename
, "lib%s.a", libname
);
3602 snprintf(filename
, sizeof filename
, "lib%s.so", libname
);
3604 } else if (t
!= LD_TOK_NAME
) {
3605 tcc_error_noabort("filename expected");
3607 goto lib_parse_error
;
3609 if (!strcmp(filename
, "AS_NEEDED")) {
3610 ret
= ld_add_file_list(s1
, cmd
, 1);
3612 goto lib_parse_error
;
3614 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3616 ret
= ld_add_file(s1
, filename
);
3618 goto lib_parse_error
;
3620 /* Add the filename *and* the libname to avoid future conversions */
3621 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(filename
));
3622 if (libname
[0] != '\0')
3623 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(libname
));
3627 t
= ld_next(s1
, filename
, sizeof(filename
));
3629 t
= ld_next(s1
, filename
, sizeof(filename
));
3632 if (group
&& !as_needed
) {
3633 while (new_undef_syms()) {
3636 for (i
= 0; i
< nblibs
; i
++)
3637 ld_add_file(s1
, libs
[i
]);
3641 dynarray_reset(&libs
, &nblibs
);
3645 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3647 ST_FUNC
int tcc_load_ldscript(TCCState
*s1
)
3650 char filename
[1024];
3655 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3656 if (t
== LD_TOK_EOF
)
3658 else if (t
!= LD_TOK_NAME
)
3660 if (!strcmp(cmd
, "INPUT") ||
3661 !strcmp(cmd
, "GROUP")) {
3662 ret
= ld_add_file_list(s1
, cmd
, 0);
3665 } else if (!strcmp(cmd
, "OUTPUT_FORMAT") ||
3666 !strcmp(cmd
, "TARGET")) {
3667 /* ignore some commands */
3668 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3672 t
= ld_next(s1
, filename
, sizeof(filename
));
3673 if (t
== LD_TOK_EOF
) {
3674 tcc_error_noabort("unexpected end of file");
3676 } else if (t
== ')') {
3686 #endif /* !TCC_TARGET_PE */