2 * ELF file handling for TCC
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 static int new_undef_sym
= 0; /* Is there a new undefined sym since last new_undef_sym() */
25 ST_FUNC
int put_elf_str(Section
*s
, const char *sym
)
30 len
= strlen(sym
) + 1;
31 offset
= s
->data_offset
;
32 ptr
= section_ptr_add(s
, len
);
33 memcpy(ptr
, sym
, len
);
37 /* elf symbol hashing function */
38 static unsigned long elf_hash(const unsigned char *name
)
40 unsigned long h
= 0, g
;
43 h
= (h
<< 4) + *name
++;
52 /* rebuild hash table of section s */
53 /* NOTE: we do factorize the hash table code to go faster */
54 static void rebuild_hash(Section
*s
, unsigned int nb_buckets
)
57 int *ptr
, *hash
, nb_syms
, sym_index
, h
;
60 strtab
= s
->link
->data
;
61 nb_syms
= s
->data_offset
/ sizeof(ElfW(Sym
));
63 s
->hash
->data_offset
= 0;
64 ptr
= section_ptr_add(s
->hash
, (2 + nb_buckets
+ nb_syms
) * sizeof(int));
69 memset(hash
, 0, (nb_buckets
+ 1) * sizeof(int));
70 ptr
+= nb_buckets
+ 1;
72 sym
= (ElfW(Sym
) *)s
->data
+ 1;
73 for(sym_index
= 1; sym_index
< nb_syms
; sym_index
++) {
74 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
75 h
= elf_hash(strtab
+ sym
->st_name
) % nb_buckets
;
86 /* return the symbol number */
87 ST_FUNC
int put_elf_sym(Section
*s
, addr_t value
, unsigned long size
,
88 int info
, int other
, int shndx
, const char *name
)
90 int name_offset
, sym_index
;
95 sym
= section_ptr_add(s
, sizeof(ElfW(Sym
)));
97 name_offset
= put_elf_str(s
->link
, name
);
100 /* XXX: endianness */
101 sym
->st_name
= name_offset
;
102 sym
->st_value
= value
;
105 sym
->st_other
= other
;
106 sym
->st_shndx
= shndx
;
107 sym_index
= sym
- (ElfW(Sym
) *)s
->data
;
111 ptr
= section_ptr_add(hs
, sizeof(int));
112 base
= (int *)hs
->data
;
113 /* only add global or weak symbols */
114 if (ELFW(ST_BIND
)(info
) != STB_LOCAL
) {
115 /* add another hashing entry */
117 h
= elf_hash(name
) % nbuckets
;
119 base
[2 + h
] = sym_index
;
121 /* we resize the hash table */
122 hs
->nb_hashed_syms
++;
123 if (hs
->nb_hashed_syms
> 2 * nbuckets
) {
124 rebuild_hash(s
, 2 * nbuckets
);
134 /* find global ELF symbol 'name' and return its index. Return 0 if not
136 ST_FUNC
int find_elf_sym(Section
*s
, const char *name
)
140 int nbuckets
, sym_index
, h
;
146 nbuckets
= ((int *)hs
->data
)[0];
147 h
= elf_hash(name
) % nbuckets
;
148 sym_index
= ((int *)hs
->data
)[2 + h
];
149 while (sym_index
!= 0) {
150 sym
= &((ElfW(Sym
) *)s
->data
)[sym_index
];
151 name1
= s
->link
->data
+ sym
->st_name
;
152 if (!strcmp(name
, name1
))
154 sym_index
= ((int *)hs
->data
)[2 + nbuckets
+ sym_index
];
159 /* return elf symbol value, signal error if 'err' is nonzero */
160 ST_FUNC addr_t
get_elf_sym_addr(TCCState
*s
, const char *name
, int err
)
165 sym_index
= find_elf_sym(s
->symtab
, name
);
166 sym
= &((ElfW(Sym
) *)s
->symtab
->data
)[sym_index
];
167 if (!sym_index
|| sym
->st_shndx
== SHN_UNDEF
) {
169 tcc_error("%s not defined", name
);
172 return sym
->st_value
;
175 /* return elf symbol value */
176 LIBTCCAPI
void *tcc_get_symbol(TCCState
*s
, const char *name
)
178 return (void*)(uintptr_t)get_elf_sym_addr(s
, name
, 0);
182 /* return elf symbol value or error */
183 ST_FUNC
void* tcc_get_symbol_err(TCCState
*s
, const char *name
)
185 return (void*)get_elf_sym_addr(s
, name
, 1);
189 /* add an elf symbol : check if it is already defined and patch
190 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
191 ST_FUNC
int add_elf_sym(Section
*s
, addr_t value
, unsigned long size
,
192 int info
, int other
, int sh_num
, const char *name
)
195 int sym_bind
, sym_index
, sym_type
, esym_bind
;
196 unsigned char sym_vis
, esym_vis
, new_vis
;
198 sym_bind
= ELFW(ST_BIND
)(info
);
199 sym_type
= ELFW(ST_TYPE
)(info
);
200 sym_vis
= ELFW(ST_VISIBILITY
)(other
);
202 if (sym_bind
!= STB_LOCAL
) {
203 /* we search global or weak symbols */
204 sym_index
= find_elf_sym(s
, name
);
207 esym
= &((ElfW(Sym
) *)s
->data
)[sym_index
];
208 if (esym
->st_shndx
!= SHN_UNDEF
) {
209 esym_bind
= ELFW(ST_BIND
)(esym
->st_info
);
210 /* propagate the most constraining visibility */
211 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
212 esym_vis
= ELFW(ST_VISIBILITY
)(esym
->st_other
);
213 if (esym_vis
== STV_DEFAULT
) {
215 } else if (sym_vis
== STV_DEFAULT
) {
218 new_vis
= (esym_vis
< sym_vis
) ? esym_vis
: sym_vis
;
220 esym
->st_other
= (esym
->st_other
& ~ELFW(ST_VISIBILITY
)(-1))
222 other
= esym
->st_other
; /* in case we have to patch esym */
223 if (sh_num
== SHN_UNDEF
) {
224 /* ignore adding of undefined symbol if the
225 corresponding symbol is already defined */
226 } else if (sym_bind
== STB_GLOBAL
&& esym_bind
== STB_WEAK
) {
227 /* global overrides weak, so patch */
229 } else if (sym_bind
== STB_WEAK
&& esym_bind
== STB_GLOBAL
) {
230 /* weak is ignored if already global */
231 } else if (sym_bind
== STB_WEAK
&& esym_bind
== STB_WEAK
) {
232 /* keep first-found weak definition, ignore subsequents */
233 } else if (sym_vis
== STV_HIDDEN
|| sym_vis
== STV_INTERNAL
) {
234 /* ignore hidden symbols after */
235 } else if (esym
->st_shndx
== SHN_COMMON
236 && (sh_num
< SHN_LORESERVE
|| sh_num
== SHN_COMMON
)) {
237 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
238 No idea if this is the correct solution ... */
240 } else if (s
== tcc_state
->dynsymtab_section
) {
241 /* we accept that two DLL define the same symbol */
244 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
245 sym_bind
, sh_num
, new_vis
, esym_bind
, esym
->st_shndx
, esym_vis
);
247 tcc_error_noabort("'%s' defined twice", name
);
251 esym
->st_info
= ELFW(ST_INFO
)(sym_bind
, sym_type
);
252 esym
->st_shndx
= sh_num
;
254 esym
->st_value
= value
;
255 esym
->st_size
= size
;
256 esym
->st_other
= other
;
260 sym_index
= put_elf_sym(s
, value
, size
,
261 ELFW(ST_INFO
)(sym_bind
, sym_type
), other
,
268 ST_FUNC
void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
269 int type
, int symbol
)
277 /* if no relocation section, create it */
278 snprintf(buf
, sizeof(buf
), REL_SECTION_FMT
, s
->name
);
279 /* if the symtab is allocated, then we consider the relocation
281 sr
= new_section(tcc_state
, buf
, SHT_RELX
, symtab
->sh_flags
);
282 sr
->sh_entsize
= sizeof(ElfW_Rel
);
284 sr
->sh_info
= s
->sh_num
;
287 rel
= section_ptr_add(sr
, sizeof(ElfW_Rel
));
288 rel
->r_offset
= offset
;
289 rel
->r_info
= ELFW(R_INFO
)(symbol
, type
);
290 #ifdef TCC_TARGET_X86_64
295 /* put stab debug information */
297 ST_FUNC
void put_stabs(const char *str
, int type
, int other
, int desc
,
302 sym
= section_ptr_add(stab_section
, sizeof(Stab_Sym
));
304 sym
->n_strx
= put_elf_str(stabstr_section
, str
);
309 sym
->n_other
= other
;
311 sym
->n_value
= value
;
314 ST_FUNC
void put_stabs_r(const char *str
, int type
, int other
, int desc
,
315 unsigned long value
, Section
*sec
, int sym_index
)
317 put_stabs(str
, type
, other
, desc
, value
);
318 put_elf_reloc(symtab_section
, stab_section
,
319 stab_section
->data_offset
- sizeof(unsigned int),
320 R_DATA_32
, sym_index
);
323 ST_FUNC
void put_stabn(int type
, int other
, int desc
, int value
)
325 put_stabs(NULL
, type
, other
, desc
, value
);
328 ST_FUNC
void put_stabd(int type
, int other
, int desc
)
330 put_stabs(NULL
, type
, other
, desc
, 0);
333 /* In an ELF file symbol table, the local symbols must appear below
334 the global and weak ones. Since TCC cannot sort it while generating
335 the code, we must do it after. All the relocation tables are also
336 modified to take into account the symbol table sorting */
337 static void sort_syms(TCCState
*s1
, Section
*s
)
339 int *old_to_new_syms
;
343 ElfW_Rel
*rel
, *rel_end
;
347 nb_syms
= s
->data_offset
/ sizeof(ElfW(Sym
));
348 new_syms
= tcc_malloc(nb_syms
* sizeof(ElfW(Sym
)));
349 old_to_new_syms
= tcc_malloc(nb_syms
* sizeof(int));
351 /* first pass for local symbols */
352 p
= (ElfW(Sym
) *)s
->data
;
354 for(i
= 0; i
< nb_syms
; i
++) {
355 if (ELFW(ST_BIND
)(p
->st_info
) == STB_LOCAL
) {
356 old_to_new_syms
[i
] = q
- new_syms
;
361 /* save the number of local symbols in section header */
362 s
->sh_info
= q
- new_syms
;
364 /* then second pass for non local symbols */
365 p
= (ElfW(Sym
) *)s
->data
;
366 for(i
= 0; i
< nb_syms
; i
++) {
367 if (ELFW(ST_BIND
)(p
->st_info
) != STB_LOCAL
) {
368 old_to_new_syms
[i
] = q
- new_syms
;
374 /* we copy the new symbols to the old */
375 memcpy(s
->data
, new_syms
, nb_syms
* sizeof(ElfW(Sym
)));
378 /* now we modify all the relocations */
379 for(i
= 1; i
< s1
->nb_sections
; i
++) {
380 sr
= s1
->sections
[i
];
381 if (sr
->sh_type
== SHT_RELX
&& sr
->link
== s
) {
382 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
383 for(rel
= (ElfW_Rel
*)sr
->data
;
386 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
387 type
= ELFW(R_TYPE
)(rel
->r_info
);
388 sym_index
= old_to_new_syms
[sym_index
];
389 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
394 tcc_free(old_to_new_syms
);
397 /* relocate common symbols in the .bss section */
398 ST_FUNC
void relocate_common_syms(void)
400 ElfW(Sym
) *sym
, *sym_end
;
401 unsigned long offset
, align
;
403 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+ symtab_section
->data_offset
);
404 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
407 if (sym
->st_shndx
== SHN_COMMON
) {
409 align
= sym
->st_value
;
410 offset
= bss_section
->data_offset
;
411 offset
= (offset
+ align
- 1) & -align
;
412 sym
->st_value
= offset
;
413 sym
->st_shndx
= bss_section
->sh_num
;
414 offset
+= sym
->st_size
;
415 bss_section
->data_offset
= offset
;
420 /* relocate symbol table, resolve undefined symbols if do_resolve is
421 true and output error if undefined symbol. */
422 ST_FUNC
void relocate_syms(TCCState
*s1
, int do_resolve
)
424 ElfW(Sym
) *sym
, *esym
, *sym_end
;
425 int sym_bind
, sh_num
, sym_index
;
428 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+ symtab_section
->data_offset
);
429 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
432 sh_num
= sym
->st_shndx
;
433 if (sh_num
== SHN_UNDEF
) {
434 name
= strtab_section
->data
+ sym
->st_name
;
436 #if defined TCC_IS_NATIVE && !defined _WIN32
438 name
= symtab_section
->link
->data
+ sym
->st_name
;
439 addr
= resolve_sym(s1
, name
);
441 sym
->st_value
= (addr_t
)addr
;
445 } else if (s1
->dynsym
) {
446 /* if dynamic symbol exist, then use it */
447 sym_index
= find_elf_sym(s1
->dynsym
, name
);
449 esym
= &((ElfW(Sym
) *)s1
->dynsym
->data
)[sym_index
];
450 sym
->st_value
= esym
->st_value
;
454 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
456 if (!strcmp(name
, "_fp_hw"))
458 /* only weak symbols are accepted to be undefined. Their
460 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
461 if (sym_bind
== STB_WEAK
) {
464 tcc_error_noabort("undefined symbol '%s'", name
);
466 } else if (sh_num
< SHN_LORESERVE
) {
467 /* add section base */
468 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
474 #ifdef TCC_HAS_RUNTIME_PLTGOT
475 #ifdef TCC_TARGET_X86_64
476 #define JMP_TABLE_ENTRY_SIZE 14
477 static addr_t
add_jmp_table(TCCState
*s1
, addr_t val
)
479 char *p
= s1
->runtime_plt_and_got
+ s1
->runtime_plt_and_got_offset
;
480 s1
->runtime_plt_and_got_offset
+= JMP_TABLE_ENTRY_SIZE
;
485 *(addr_t
*)(p
+ 6) = val
;
489 static addr_t
add_got_table(TCCState
*s1
, addr_t val
)
491 addr_t
*p
= (addr_t
*)(s1
->runtime_plt_and_got
+ s1
->runtime_plt_and_got_offset
);
492 s1
->runtime_plt_and_got_offset
+= sizeof(addr_t
);
496 #elif defined TCC_TARGET_ARM
497 #define JMP_TABLE_ENTRY_SIZE 8
498 static addr_t
add_jmp_table(TCCState
*s1
, int val
)
500 uint32_t *p
= (uint32_t *)(s1
->runtime_plt_and_got
+ s1
->runtime_plt_and_got_offset
);
501 s1
->runtime_plt_and_got_offset
+= JMP_TABLE_ENTRY_SIZE
;
502 /* ldr pc, [pc, #-4] */
508 #endif /* def TCC_HAS_RUNTIME_PLTGOT */
510 /* relocate a given section (CPU dependent) */
511 ST_FUNC
void relocate_section(TCCState
*s1
, Section
*s
)
514 ElfW_Rel
*rel
, *rel_end
, *qrel
;
519 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
524 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
525 qrel
= (ElfW_Rel
*)sr
->data
;
529 ptr
= s
->data
+ rel
->r_offset
;
531 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
532 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
534 #ifdef TCC_TARGET_X86_64
535 val
+= rel
->r_addend
;
537 type
= ELFW(R_TYPE
)(rel
->r_info
);
538 addr
= s
->sh_addr
+ rel
->r_offset
;
542 #if defined(TCC_TARGET_I386)
544 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
545 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
546 qrel
->r_offset
= rel
->r_offset
;
548 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_386_32
);
552 qrel
->r_info
= ELFW(R_INFO
)(0, R_386_RELATIVE
);
559 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
561 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
563 qrel
->r_offset
= rel
->r_offset
;
564 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_386_PC32
);
569 *(int *)ptr
+= val
- addr
;
572 *(int *)ptr
+= val
- addr
;
579 *(int *)ptr
+= s1
->got
->sh_addr
- addr
;
582 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
585 /* we load the got offset */
586 *(int *)ptr
+= s1
->sym_attrs
[sym_index
].got_offset
;
589 if (s1
->output_format
!= TCC_OUTPUT_FORMAT_BINARY
) {
591 tcc_error("can only produce 16-bit binary files");
593 *(short *)ptr
+= val
;
596 if (s1
->output_format
!= TCC_OUTPUT_FORMAT_BINARY
)
598 *(short *)ptr
+= val
- addr
;
600 #elif defined(TCC_TARGET_ARM)
606 int x
, is_thumb
, is_call
, h
, blx_avail
, is_bl
, th_ko
;
607 x
= (*(int *) ptr
) & 0xffffff;
608 (*(int *)ptr
) &= 0xff000000;
612 blx_avail
= (TCC_ARM_VERSION
>= 5);
614 is_bl
= (*(unsigned *) ptr
) >> 24 == 0xeb;
615 is_call
= (type
== R_ARM_CALL
|| (type
== R_ARM_PC24
&& is_bl
));
618 th_ko
= (x
& 3) && (!blx_avail
|| !is_call
);
619 #ifdef TCC_HAS_RUNTIME_PLTGOT
620 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
621 if (th_ko
|| x
>= 0x2000000 || x
< -0x2000000) {
622 x
+= add_jmp_table(s1
, val
) - val
; /* add veneer */
623 th_ko
= (x
& 3) && (!blx_avail
|| !is_call
);
624 is_thumb
= 0; /* Veneer uses ARM instructions */
628 if (th_ko
|| x
>= 0x2000000 || x
< -0x2000000)
629 tcc_error("can't relocate value at %x",addr
);
632 /* Only reached if blx is avail and it is a call */
635 (*(int *)ptr
) = 0xfa << 24; /* bl -> blx */
640 /* Since these relocations only concern Thumb-2 and blx instruction was
641 introduced before Thumb-2, we can assume blx is available and not
644 case R_ARM_THM_JUMP24
:
646 int x
, hi
, lo
, s
, j1
, j2
, i1
, i2
, imm10
, imm11
;
647 int to_thumb
, is_call
, to_plt
, blx_bit
= 1 << 12;
651 if (sym
->st_shndx
== SHN_UNDEF
&&
652 ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
655 /* Get initial offset */
656 hi
= (*(uint16_t *)ptr
);
657 lo
= (*(uint16_t *)(ptr
+2));
665 x
= (s
<< 24) | (i1
<< 23) | (i2
<< 22) |
666 (imm10
<< 12) | (imm11
<< 1);
670 /* Relocation infos */
673 to_plt
= (val
>= plt
->sh_addr
) &&
674 (val
< plt
->sh_addr
+ plt
->data_offset
);
675 is_call
= (type
== R_ARM_THM_CALL
);
677 /* Compute final offset */
678 if (to_plt
&& !is_call
) /* Point to 1st instr of Thumb stub */
681 if (!to_thumb
&& is_call
) {
682 blx_bit
= 0; /* bl -> blx */
683 x
= (x
+ 3) & -4; /* Compute offset from aligned PC */
686 /* Check that relocation is possible
687 * offset must not be out of range
688 * if target is to be entered in arm mode:
690 - instruction must be a call (bl) or a jump to PLT */
691 if (!to_thumb
|| x
>= 0x1000000 || x
< -0x1000000)
692 if (to_thumb
|| (val
& 2) || (!is_call
&& !to_plt
))
693 tcc_error("can't relocate value at %x",addr
);
695 /* Compute and store final offset */
701 imm10
= (x
>> 12) & 0x3ff;
702 imm11
= (x
>> 1) & 0x7ff;
703 (*(uint16_t *)ptr
) = (uint16_t) ((hi
& 0xf800) |
705 (*(uint16_t *)(ptr
+2)) = (uint16_t) ((lo
& 0xc000) |
706 (j1
<< 13) | blx_bit
| (j2
<< 11) |
711 case R_ARM_MOVW_ABS_NC
:
714 if (type
== R_ARM_MOVT_ABS
)
717 imm4
= (val
>> 12) & 0xf;
718 x
= (imm4
<< 16) | imm12
;
719 if (type
== R_ARM_THM_MOVT_ABS
)
725 case R_ARM_THM_MOVT_ABS
:
726 case R_ARM_THM_MOVW_ABS_NC
:
728 int x
, i
, imm4
, imm3
, imm8
;
729 if (type
== R_ARM_THM_MOVT_ABS
)
732 imm3
= (val
>> 8) & 0x7;
734 imm4
= (val
>> 12) & 0xf;
735 x
= (imm3
<< 28) | (imm8
<< 16) | (i
<< 10) | imm4
;
736 if (type
== R_ARM_THM_MOVT_ABS
)
745 x
= (*(int *)ptr
) & 0x7fffffff;
746 (*(int *)ptr
) &= 0x80000000;
749 if((x
^(x
>>1))&0x40000000)
750 tcc_error("can't relocate value at %x",addr
);
751 (*(int *)ptr
) |= x
& 0x7fffffff;
757 *(int *)ptr
+= val
- addr
;
759 case R_ARM_BASE_PREL
:
760 *(int *)ptr
+= s1
->got
->sh_addr
- addr
;
763 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
766 /* we load the got offset */
767 *(int *)ptr
+= s1
->sym_attrs
[sym_index
].got_offset
;
772 /* trade Thumb support for ARMv4 support */
773 if ((0x0ffffff0 & *(int*)ptr
) == 0x012FFF10)
774 *(int*)ptr
^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
777 fprintf(stderr
,"FIXME: handle reloc type %x at %x [%p] to %x\n",
778 type
, (unsigned)addr
, ptr
, (unsigned)val
);
780 #elif defined(TCC_TARGET_C67)
788 /* put the low 16 bits of the absolute address */
789 // add to what is already there
791 orig
= ((*(int *)(ptr
)) >> 7) & 0xffff;
792 orig
|= (((*(int *)(ptr
+4)) >> 7) & 0xffff) << 16;
794 //patch both at once - assumes always in pairs Low - High
796 *(int *) ptr
= (*(int *) ptr
& (~(0xffff << 7)) ) | (((val
+orig
) & 0xffff) << 7);
797 *(int *)(ptr
+4) = (*(int *)(ptr
+4) & (~(0xffff << 7)) ) | ((((val
+orig
)>>16) & 0xffff) << 7);
803 fprintf(stderr
,"FIXME: handle reloc type %x at %x [%p] to %x\n",
804 type
, (unsigned)addr
, ptr
, (unsigned)val
);
806 #elif defined(TCC_TARGET_X86_64)
808 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
809 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
810 qrel
->r_addend
= *(long long *)ptr
+ val
;
813 *(long long *)ptr
+= val
;
817 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
818 /* XXX: this logic may depend on TCC's codegen
819 now TCC uses R_X86_64_32 even for a 64bit pointer */
820 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
821 qrel
->r_addend
= *(int *)ptr
+ val
;
828 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
830 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
832 qrel
->r_offset
= rel
->r_offset
;
833 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_X86_64_PC32
);
834 qrel
->r_addend
= *(int *)ptr
;
840 case R_X86_64_PLT32
: {
842 diff
= (long long)val
- addr
;
843 if (diff
<= -2147483647 || diff
> 2147483647) {
844 #ifdef TCC_HAS_RUNTIME_PLTGOT
845 /* XXX: naive support for over 32bit jump */
846 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
847 val
= (add_jmp_table(s1
, val
- rel
->r_addend
) +
852 if (diff
<= -2147483647 || diff
> 2147483647) {
853 tcc_error("internal error: relocation failed");
859 case R_X86_64_GLOB_DAT
:
860 case R_X86_64_JUMP_SLOT
:
861 /* They don't need addend */
862 *(int *)ptr
= val
- rel
->r_addend
;
864 case R_X86_64_GOTPCREL
:
865 #ifdef TCC_HAS_RUNTIME_PLTGOT
866 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
867 val
= add_got_table(s1
, val
- rel
->r_addend
) + rel
->r_addend
;
868 *(int *)ptr
+= val
- addr
;
872 *(int *)ptr
+= (s1
->got
->sh_addr
- addr
+
873 s1
->sym_attrs
[sym_index
].got_offset
- 4);
875 case R_X86_64_GOTTPOFF
:
876 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
879 /* we load the got offset */
880 *(int *)ptr
+= s1
->sym_attrs
[sym_index
].got_offset
;
883 #error unsupported processor
887 /* if the relocation is allocated, we change its symbol table */
888 if (sr
->sh_flags
& SHF_ALLOC
)
889 sr
->link
= s1
->dynsym
;
892 /* relocate relocation table in 'sr' */
893 static void relocate_rel(TCCState
*s1
, Section
*sr
)
896 ElfW_Rel
*rel
, *rel_end
;
898 s
= s1
->sections
[sr
->sh_info
];
899 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
900 for(rel
= (ElfW_Rel
*)sr
->data
;
903 rel
->r_offset
+= s
->sh_addr
;
907 /* count the number of dynamic relocations so that we can reserve
909 static int prepare_dynamic_rel(TCCState
*s1
, Section
*sr
)
911 ElfW_Rel
*rel
, *rel_end
;
912 int sym_index
, esym_index
, type
, count
;
915 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
916 for(rel
= (ElfW_Rel
*)sr
->data
; rel
< rel_end
; rel
++) {
917 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
918 type
= ELFW(R_TYPE
)(rel
->r_info
);
920 #if defined(TCC_TARGET_I386)
922 #elif defined(TCC_TARGET_X86_64)
929 #if defined(TCC_TARGET_I386)
931 #elif defined(TCC_TARGET_X86_64)
934 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
943 /* allocate the section */
944 sr
->sh_flags
|= SHF_ALLOC
;
945 sr
->sh_size
= count
* sizeof(ElfW_Rel
);
950 static struct sym_attr
*alloc_sym_attr(TCCState
*s1
, int index
)
953 struct sym_attr
*tab
;
955 if (index
>= s1
->nb_sym_attrs
) {
956 /* find immediately bigger power of 2 and reallocate array */
960 tab
= tcc_realloc(s1
->sym_attrs
, n
* sizeof(*s1
->sym_attrs
));
962 memset(s1
->sym_attrs
+ s1
->nb_sym_attrs
, 0,
963 (n
- s1
->nb_sym_attrs
) * sizeof(*s1
->sym_attrs
));
964 s1
->nb_sym_attrs
= n
;
966 return &s1
->sym_attrs
[index
];
969 /* XXX: suppress that */
970 static void put32(unsigned char *p
, uint32_t val
)
978 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
979 defined(TCC_TARGET_X86_64)
980 static uint32_t get32(unsigned char *p
)
982 return p
[0] | (p
[1] << 8) | (p
[2] << 16) | (p
[3] << 24);
986 static void build_got(TCCState
*s1
)
990 /* if no got, then create it */
991 s1
->got
= new_section(s1
, ".got", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
992 s1
->got
->sh_entsize
= 4;
993 add_elf_sym(symtab_section
, 0, 4, ELFW(ST_INFO
)(STB_GLOBAL
, STT_OBJECT
),
994 0, s1
->got
->sh_num
, "_GLOBAL_OFFSET_TABLE_");
995 ptr
= section_ptr_add(s1
->got
, 3 * PTR_SIZE
);
997 /* keep space for _DYNAMIC pointer, if present */
999 /* two dummy got entries */
1003 /* keep space for _DYNAMIC pointer, if present */
1006 /* two dummy got entries */
1014 /* put a got entry corresponding to a symbol in symtab_section. 'size'
1015 and 'info' can be modifed if more precise info comes from the DLL */
1016 static void put_got_entry(TCCState
*s1
,
1017 int reloc_type
, unsigned long size
, int info
,
1023 unsigned long offset
;
1029 /* if a got entry already exists for that symbol, no need to add one */
1030 if (sym_index
< s1
->nb_sym_attrs
&&
1031 s1
->sym_attrs
[sym_index
].got_offset
)
1034 alloc_sym_attr(s1
, sym_index
)->got_offset
= s1
->got
->data_offset
;
1037 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1038 name
= symtab_section
->link
->data
+ sym
->st_name
;
1039 offset
= sym
->st_value
;
1040 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1042 #ifdef TCC_TARGET_X86_64
1052 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1055 /* if we build a DLL, we add a %ebx offset */
1056 if (s1
->output_type
== TCC_OUTPUT_DLL
)
1062 /* add a PLT entry */
1064 if (plt
->data_offset
== 0) {
1065 /* first plt entry */
1066 p
= section_ptr_add(plt
, 16);
1067 p
[0] = 0xff; /* pushl got + PTR_SIZE */
1068 p
[1] = modrm
+ 0x10;
1069 put32(p
+ 2, PTR_SIZE
);
1070 p
[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1072 put32(p
+ 8, PTR_SIZE
* 2);
1075 p
= section_ptr_add(plt
, 16);
1076 p
[0] = 0xff; /* jmp *(got + x) */
1078 put32(p
+ 2, s1
->got
->data_offset
);
1079 p
[6] = 0x68; /* push $xxx */
1080 put32(p
+ 7, (plt
->data_offset
- 32) >> 1);
1081 p
[11] = 0xe9; /* jmp plt_start */
1082 put32(p
+ 12, -(plt
->data_offset
));
1084 /* the symbol is modified so that it will be relocated to
1086 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
1087 if (s1
->output_type
== TCC_OUTPUT_EXE
)
1089 offset
= plt
->data_offset
- 16;
1091 #elif defined(TCC_TARGET_ARM)
1092 if (reloc_type
== R_ARM_JUMP_SLOT
) {
1096 /* if we build a DLL, we add a %ebx offset */
1097 if (s1
->output_type
== TCC_OUTPUT_DLL
)
1098 tcc_error("DLLs unimplemented!");
1100 /* add a PLT entry */
1102 if (plt
->data_offset
== 0) {
1103 /* first plt entry */
1104 p
= section_ptr_add(plt
, 16);
1105 put32(p
, 0xe52de004);
1106 put32(p
+ 4, 0xe59fe010);
1107 put32(p
+ 8, 0xe08fe00e);
1108 put32(p
+ 12, 0xe5bef008);
1111 if (s1
->sym_attrs
[sym_index
].plt_thumb_stub
) {
1112 p
= section_ptr_add(plt
, 20);
1113 put32(p
, 0x4778); // bx pc
1114 put32(p
+2, 0x46c0); // nop
1117 p
= section_ptr_add(plt
, 16);
1118 put32(p
, 0xe59fc004); // ldr ip, [pc, #4] // offset in GOT
1119 put32(p
+4, 0xe08fc00c); // add ip, pc, ip // absolute address or offset
1120 put32(p
+8, 0xe59cf000); // ldr pc, [ip] // load absolute address or load offset
1121 put32(p
+12, s1
->got
->data_offset
);
1123 /* the symbol is modified so that it will be relocated to
1125 if (s1
->output_type
== TCC_OUTPUT_EXE
)
1126 offset
= plt
->data_offset
- 16;
1128 #elif defined(TCC_TARGET_C67)
1129 tcc_error("C67 got not implemented");
1131 #error unsupported CPU
1133 index
= put_elf_sym(s1
->dynsym
, offset
,
1134 size
, info
, 0, sym
->st_shndx
, name
);
1135 /* put a got entry */
1136 put_elf_reloc(s1
->dynsym
, s1
->got
,
1137 s1
->got
->data_offset
,
1140 ptr
= section_ptr_add(s1
->got
, PTR_SIZE
);
1144 /* build GOT and PLT entries */
1145 ST_FUNC
void build_got_entries(TCCState
*s1
)
1148 ElfW_Rel
*rel
, *rel_end
;
1150 int i
, type
, reloc_type
, sym_index
;
1152 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1153 s
= s1
->sections
[i
];
1154 if (s
->sh_type
!= SHT_RELX
)
1156 /* no need to handle got relocations */
1157 if (s
->link
!= symtab_section
)
1159 rel_end
= (ElfW_Rel
*)(s
->data
+ s
->data_offset
);
1160 for(rel
= (ElfW_Rel
*)s
->data
;
1163 type
= ELFW(R_TYPE
)(rel
->r_info
);
1165 #if defined(TCC_TARGET_I386)
1172 if (type
== R_386_GOT32
|| type
== R_386_PLT32
) {
1173 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1174 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1175 /* look at the symbol got offset. If none, then add one */
1176 if (type
== R_386_GOT32
)
1177 reloc_type
= R_386_GLOB_DAT
;
1179 reloc_type
= R_386_JMP_SLOT
;
1180 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1184 #elif defined(TCC_TARGET_ARM)
1185 case R_ARM_GOT_BREL
:
1186 case R_ARM_GOTOFF32
:
1187 case R_ARM_BASE_PREL
:
1191 if (type
== R_ARM_GOT_BREL
|| type
== R_ARM_PLT32
) {
1192 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1193 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1194 /* look at the symbol got offset. If none, then add one */
1195 if (type
== R_ARM_GOT_BREL
)
1196 reloc_type
= R_ARM_GLOB_DAT
;
1198 reloc_type
= R_ARM_JUMP_SLOT
;
1199 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1203 #elif defined(TCC_TARGET_C67)
1210 if (type
== R_C60_GOT32
|| type
== R_C60_PLT32
) {
1211 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1212 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1213 /* look at the symbol got offset. If none, then add one */
1214 if (type
== R_C60_GOT32
)
1215 reloc_type
= R_C60_GLOB_DAT
;
1217 reloc_type
= R_C60_JMP_SLOT
;
1218 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1222 #elif defined(TCC_TARGET_X86_64)
1223 case R_X86_64_GOT32
:
1224 case R_X86_64_GOTTPOFF
:
1225 case R_X86_64_GOTPCREL
:
1226 case R_X86_64_PLT32
:
1229 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
||
1230 type
== R_X86_64_PLT32
) {
1231 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1232 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1233 /* look at the symbol got offset. If none, then add one */
1234 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
)
1235 reloc_type
= R_X86_64_GLOB_DAT
;
1237 reloc_type
= R_X86_64_JUMP_SLOT
;
1238 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1243 #error unsupported CPU
1252 ST_FUNC Section
*new_symtab(TCCState
*s1
,
1253 const char *symtab_name
, int sh_type
, int sh_flags
,
1254 const char *strtab_name
,
1255 const char *hash_name
, int hash_sh_flags
)
1257 Section
*symtab
, *strtab
, *hash
;
1258 int *ptr
, nb_buckets
;
1260 symtab
= new_section(s1
, symtab_name
, sh_type
, sh_flags
);
1261 symtab
->sh_entsize
= sizeof(ElfW(Sym
));
1262 strtab
= new_section(s1
, strtab_name
, SHT_STRTAB
, sh_flags
);
1263 put_elf_str(strtab
, "");
1264 symtab
->link
= strtab
;
1265 put_elf_sym(symtab
, 0, 0, 0, 0, 0, NULL
);
1269 hash
= new_section(s1
, hash_name
, SHT_HASH
, hash_sh_flags
);
1270 hash
->sh_entsize
= sizeof(int);
1271 symtab
->hash
= hash
;
1272 hash
->link
= symtab
;
1274 ptr
= section_ptr_add(hash
, (2 + nb_buckets
+ 1) * sizeof(int));
1275 ptr
[0] = nb_buckets
;
1277 memset(ptr
+ 2, 0, (nb_buckets
+ 1) * sizeof(int));
1281 /* put dynamic tag */
1282 static void put_dt(Section
*dynamic
, int dt
, addr_t val
)
1285 dyn
= section_ptr_add(dynamic
, sizeof(ElfW(Dyn
)));
1287 dyn
->d_un
.d_val
= val
;
1290 static void add_init_array_defines(TCCState
*s1
, const char *section_name
)
1294 char sym_start
[1024];
1297 snprintf(sym_start
, sizeof(sym_start
), "__%s_start", section_name
+ 1);
1298 snprintf(sym_end
, sizeof(sym_end
), "__%s_end", section_name
+ 1);
1300 s
= find_section(s1
, section_name
);
1305 end_offset
= s
->data_offset
;
1308 add_elf_sym(symtab_section
,
1310 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1311 s
->sh_num
, sym_start
);
1312 add_elf_sym(symtab_section
,
1314 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1315 s
->sh_num
, sym_end
);
1318 ST_FUNC
void tcc_add_bcheck(TCCState
*s1
)
1320 #ifdef CONFIG_TCC_BCHECK
1322 Section
*init_section
;
1323 unsigned char *pinit
;
1326 if (0 == s1
->do_bounds_check
)
1329 /* XXX: add an object file to do that */
1330 ptr
= section_ptr_add(bounds_section
, sizeof(unsigned long));
1332 add_elf_sym(symtab_section
, 0, 0,
1333 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1334 bounds_section
->sh_num
, "__bounds_start");
1335 #ifdef TCC_TARGET_I386
1336 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
) {
1337 /* add 'call __bound_init()' in .init section */
1338 init_section
= find_section(s1
, ".init");
1339 pinit
= section_ptr_add(init_section
, 5);
1341 put32(pinit
+ 1, -4);
1342 sym_index
= find_elf_sym(symtab_section
, "__bound_init");
1343 put_elf_reloc(symtab_section
, init_section
,
1344 init_section
->data_offset
- 4, R_386_PC32
, sym_index
);
1350 static inline int tcc_add_support(TCCState
*s1
, const char *filename
)
1353 snprintf(buf
, sizeof(buf
), "%s/%s", s1
->tcc_lib_path
, filename
);
1354 return tcc_add_file(s1
, buf
);
1357 /* add tcc runtime libraries */
1358 ST_FUNC
void tcc_add_runtime(TCCState
*s1
)
1363 if (!s1
->nostdlib
) {
1364 tcc_add_library(s1
, "c");
1365 #ifdef CONFIG_USE_LIBGCC
1366 tcc_add_file(s1
, TCC_LIBGCC
);
1367 #elif !defined WITHOUT_LIBTCC
1368 tcc_add_support(s1
, "libtcc1.a");
1370 /* add crt end if not memory output */
1371 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
)
1372 tcc_add_crt(s1
, "crtn.o");
1376 /* add various standard linker symbols (must be done after the
1377 sections are filled (for example after allocating common
1379 ST_FUNC
void tcc_add_linker_symbols(TCCState
*s1
)
1385 add_elf_sym(symtab_section
,
1386 text_section
->data_offset
, 0,
1387 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1388 text_section
->sh_num
, "_etext");
1389 add_elf_sym(symtab_section
,
1390 data_section
->data_offset
, 0,
1391 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1392 data_section
->sh_num
, "_edata");
1393 add_elf_sym(symtab_section
,
1394 bss_section
->data_offset
, 0,
1395 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1396 bss_section
->sh_num
, "_end");
1397 /* horrible new standard ldscript defines */
1398 add_init_array_defines(s1
, ".preinit_array");
1399 add_init_array_defines(s1
, ".init_array");
1400 add_init_array_defines(s1
, ".fini_array");
1402 /* add start and stop symbols for sections whose name can be
1404 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1405 s
= s1
->sections
[i
];
1406 if (s
->sh_type
== SHT_PROGBITS
&&
1407 (s
->sh_flags
& SHF_ALLOC
)) {
1411 /* check if section name can be expressed in C */
1417 if (!isid(ch
) && !isnum(ch
))
1421 snprintf(buf
, sizeof(buf
), "__start_%s", s
->name
);
1422 add_elf_sym(symtab_section
,
1424 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1426 snprintf(buf
, sizeof(buf
), "__stop_%s", s
->name
);
1427 add_elf_sym(symtab_section
,
1429 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1436 static void tcc_output_binary(TCCState
*s1
, FILE *f
,
1437 const int *section_order
)
1440 int i
, offset
, size
;
1443 for(i
=1;i
<s1
->nb_sections
;i
++) {
1444 s
= s1
->sections
[section_order
[i
]];
1445 if (s
->sh_type
!= SHT_NOBITS
&&
1446 (s
->sh_flags
& SHF_ALLOC
)) {
1447 while (offset
< s
->sh_offset
) {
1452 fwrite(s
->data
, 1, size
, f
);
1458 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1460 #define EXTRA_RELITEMS 14
1462 /* move the relocation value from .dynsym to .got */
1463 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1465 uint32_t *gotd
= (void *)s1
->got
->data
;
1466 ElfW(Sym
) *sym
, *sym_end
;
1468 gotd
+= 3; // dummy entries in .got
1469 /* relocate symbols in .dynsym */
1470 sym_end
= (ElfW(Sym
) *)(s
->data
+ s
->data_offset
);
1471 for (sym
= (ElfW(Sym
) *)s
->data
+ 1; sym
< sym_end
; sym
++) {
1472 if (sym
->st_shndx
== SHN_UNDEF
) {
1473 *gotd
++ = sym
->st_value
+ 6; // XXX 6 is magic ?
1480 #define EXTRA_RELITEMS 9
1482 /* zero plt offsets of weak symbols in .dynsym */
1483 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1485 ElfW(Sym
) *sym
, *sym_end
;
1487 sym_end
= (ElfW(Sym
) *)(s
->data
+ s
->data_offset
);
1488 for (sym
= (ElfW(Sym
) *)s
->data
+ 1; sym
< sym_end
; sym
++)
1489 if (sym
->st_shndx
== SHN_UNDEF
&& ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
1494 ST_FUNC
void fill_got_entry(TCCState
*s1
, ElfW_Rel
*rel
)
1496 int sym_index
= ELFW(R_SYM
) (rel
->r_info
);
1497 ElfW(Sym
) *sym
= &((ElfW(Sym
) *) symtab_section
->data
)[sym_index
];
1498 unsigned long offset
;
1500 if (sym_index
>= s1
->nb_sym_attrs
)
1502 offset
= s1
->sym_attrs
[sym_index
].got_offset
;
1503 section_reserve(s1
->got
, offset
+ PTR_SIZE
);
1504 #ifdef TCC_TARGET_X86_64
1505 /* only works for x86-64 */
1506 put32(s1
->got
->data
+ offset
+ 4, sym
->st_value
>> 32);
1508 put32(s1
->got
->data
+ offset
, sym
->st_value
& 0xffffffff);
1511 ST_FUNC
void fill_got(TCCState
*s1
)
1514 ElfW_Rel
*rel
, *rel_end
;
1517 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1518 s
= s1
->sections
[i
];
1519 if (s
->sh_type
!= SHT_RELX
)
1521 /* no need to handle got relocations */
1522 if (s
->link
!= symtab_section
)
1524 rel_end
= (ElfW_Rel
*) (s
->data
+ s
->data_offset
);
1525 for(rel
= (ElfW_Rel
*) s
->data
; rel
< rel_end
; rel
++) {
1526 switch (ELFW(R_TYPE
) (rel
->r_info
)) {
1527 case R_X86_64_GOT32
:
1528 case R_X86_64_GOTPCREL
:
1529 case R_X86_64_PLT32
:
1530 fill_got_entry(s1
, rel
);
1538 /* output an ELF file */
1539 /* XXX: suppress unneeded sections */
1540 static int elf_output_file(TCCState
*s1
, const char *filename
)
1546 int shnum
, i
, phnum
, file_offset
, offset
, size
, j
, sh_order_index
, k
;
1549 Section
*strsec
, *s
;
1550 ElfW(Shdr
) shdr
, *sh
;
1551 ElfW(Phdr
) *phdr
, *ph
;
1552 Section
*interp
, *dynamic
, *dynstr
;
1553 unsigned long saved_dynamic_data_offset
;
1555 int type
, file_type
;
1556 addr_t rel_addr
, rel_size
;
1557 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1558 addr_t bss_addr
, bss_size
;
1561 file_type
= s1
->output_type
;
1564 if (file_type
!= TCC_OUTPUT_OBJ
) {
1565 tcc_add_runtime(s1
);
1569 section_order
= NULL
;
1572 dynstr
= NULL
; /* avoid warning */
1573 saved_dynamic_data_offset
= 0; /* avoid warning */
1575 if (file_type
!= TCC_OUTPUT_OBJ
) {
1576 relocate_common_syms();
1578 tcc_add_linker_symbols(s1
);
1580 if (!s1
->static_link
) {
1582 int sym_index
, index
;
1583 ElfW(Sym
) *esym
, *sym_end
;
1585 if (file_type
== TCC_OUTPUT_EXE
) {
1587 /* allow override the dynamic loader */
1588 const char *elfint
= getenv("LD_SO");
1590 elfint
= CONFIG_TCC_ELFINTERP
;
1591 /* add interpreter section only if executable */
1592 interp
= new_section(s1
, ".interp", SHT_PROGBITS
, SHF_ALLOC
);
1593 interp
->sh_addralign
= 1;
1594 ptr
= section_ptr_add(interp
, 1+strlen(elfint
));
1595 strcpy(ptr
, elfint
);
1598 /* add dynamic symbol table */
1599 s1
->dynsym
= new_symtab(s1
, ".dynsym", SHT_DYNSYM
, SHF_ALLOC
,
1601 ".hash", SHF_ALLOC
);
1602 dynstr
= s1
->dynsym
->link
;
1604 /* add dynamic section */
1605 dynamic
= new_section(s1
, ".dynamic", SHT_DYNAMIC
,
1606 SHF_ALLOC
| SHF_WRITE
);
1607 dynamic
->link
= dynstr
;
1608 dynamic
->sh_entsize
= sizeof(ElfW(Dyn
));
1611 s1
->plt
= new_section(s1
, ".plt", SHT_PROGBITS
,
1612 SHF_ALLOC
| SHF_EXECINSTR
);
1613 s1
->plt
->sh_entsize
= 4;
1617 /* scan for undefined symbols and see if they are in the
1618 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1619 is found, then we add it in the PLT. If a symbol
1620 STT_OBJECT is found, we add it in the .bss section with
1621 a suitable relocation */
1622 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+
1623 symtab_section
->data_offset
);
1624 if (file_type
== TCC_OUTPUT_EXE
) {
1625 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
1628 if (sym
->st_shndx
== SHN_UNDEF
) {
1629 name
= symtab_section
->link
->data
+ sym
->st_name
;
1630 sym_index
= find_elf_sym(s1
->dynsymtab_section
, name
);
1632 esym
= &((ElfW(Sym
) *)s1
->dynsymtab_section
->data
)[sym_index
];
1633 type
= ELFW(ST_TYPE
)(esym
->st_info
);
1634 if ((type
== STT_FUNC
) || (type
== STT_GNU_IFUNC
)) {
1635 /* Indirect functions shall have STT_FUNC type
1636 * in executable dynsym section. Indeed, a dlsym
1637 * call following a lazy resolution would pick
1638 * the symbol value from the executable dynsym
1639 * entry which would contain the address of the
1640 * function wanted by the caller of dlsym
1641 * instead of the address of the function that
1642 * would return that address */
1643 put_got_entry(s1
, R_JMP_SLOT
, esym
->st_size
,
1644 ELFW(ST_INFO
)(STB_GLOBAL
,STT_FUNC
),
1645 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1646 } else if (type
== STT_OBJECT
) {
1647 unsigned long offset
;
1648 ElfW(Sym
) *dynsym
, *dynsym_end
;
1649 offset
= bss_section
->data_offset
;
1650 /* XXX: which alignment ? */
1651 offset
= (offset
+ 16 - 1) & -16;
1652 index
= put_elf_sym(s1
->dynsym
, offset
, esym
->st_size
,
1654 bss_section
->sh_num
, name
);
1655 // Ensure R_COPY works for weak symbol aliases
1656 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1657 dynsym_end
= (ElfW(Sym
) *)
1658 (s1
->dynsymtab_section
->data
+
1659 s1
->dynsymtab_section
->data_offset
);
1660 for(dynsym
= (ElfW(Sym
) *)s1
->dynsymtab_section
->data
+ 1;
1661 dynsym
< dynsym_end
; dynsym
++) {
1662 if ((dynsym
->st_value
== esym
->st_value
)
1663 && (ELFW(ST_BIND
)(dynsym
->st_info
) == STB_GLOBAL
)) {
1665 dynname
= s1
->dynsymtab_section
->link
->data
1667 put_elf_sym(s1
->dynsym
, offset
,
1670 bss_section
->sh_num
,
1676 put_elf_reloc(s1
->dynsym
, bss_section
,
1677 offset
, R_COPY
, index
);
1678 offset
+= esym
->st_size
;
1679 bss_section
->data_offset
= offset
;
1682 /* STB_WEAK undefined symbols are accepted */
1683 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1685 if (ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
||
1686 !strcmp(name
, "_fp_hw")) {
1688 tcc_error_noabort("undefined symbol '%s'", name
);
1691 } else if (s1
->rdynamic
&&
1692 ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1693 /* if -rdynamic option, then export all non
1695 name
= symtab_section
->link
->data
+ sym
->st_name
;
1696 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1698 sym
->st_shndx
, name
);
1705 /* now look at unresolved dynamic symbols and export
1706 corresponding symbol */
1707 sym_end
= (ElfW(Sym
) *)(s1
->dynsymtab_section
->data
+
1708 s1
->dynsymtab_section
->data_offset
);
1709 for(esym
= (ElfW(Sym
) *)s1
->dynsymtab_section
->data
+ 1;
1712 if (esym
->st_shndx
== SHN_UNDEF
) {
1713 name
= s1
->dynsymtab_section
->link
->data
+ esym
->st_name
;
1714 sym_index
= find_elf_sym(symtab_section
, name
);
1716 /* XXX: avoid adding a symbol if already
1717 present because of -rdynamic ? */
1718 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1719 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1721 sym
->st_shndx
, name
);
1723 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1724 /* weak symbols can stay undefined */
1726 tcc_warning("undefined dynamic symbol '%s'", name
);
1733 /* shared library case : we simply export all the global symbols */
1734 nb_syms
= symtab_section
->data_offset
/ sizeof(ElfW(Sym
));
1735 s1
->symtab_to_dynsym
= tcc_mallocz(sizeof(int) * nb_syms
);
1736 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
1739 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1740 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1741 if ((ELFW(ST_TYPE
)(sym
->st_info
) == STT_FUNC
||
1742 ELFW(ST_TYPE
)(sym
->st_info
) == STT_GNU_IFUNC
)
1743 && sym
->st_shndx
== SHN_UNDEF
) {
1744 int visibility
= ELFW(ST_BIND
)(sym
->st_info
);
1745 put_got_entry(s1
, R_JMP_SLOT
, sym
->st_size
,
1746 ELFW(ST_INFO
)(visibility
,STT_FUNC
),
1747 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1749 else if (ELFW(ST_TYPE
)(sym
->st_info
) == STT_OBJECT
) {
1750 put_got_entry(s1
, R_X86_64_GLOB_DAT
, sym
->st_size
,
1752 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1757 name
= symtab_section
->link
->data
+ sym
->st_name
;
1758 index
= put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1760 sym
->st_shndx
, name
);
1761 s1
->symtab_to_dynsym
[sym
-
1762 (ElfW(Sym
) *)symtab_section
->data
] =
1769 build_got_entries(s1
);
1771 /* add a list of needed dlls */
1772 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
1773 DLLReference
*dllref
= s1
->loaded_dlls
[i
];
1774 if (dllref
->level
== 0)
1775 put_dt(dynamic
, DT_NEEDED
, put_elf_str(dynstr
, dllref
->name
));
1779 put_dt(dynamic
, DT_RPATH
, put_elf_str(dynstr
, s1
->rpath
));
1781 /* XXX: currently, since we do not handle PIC code, we
1782 must relocate the readonly segments */
1783 if (file_type
== TCC_OUTPUT_DLL
) {
1785 put_dt(dynamic
, DT_SONAME
, put_elf_str(dynstr
, s1
->soname
));
1786 put_dt(dynamic
, DT_TEXTREL
, 0);
1790 put_dt(dynamic
, DT_SYMBOLIC
, 0);
1792 /* add necessary space for other entries */
1793 saved_dynamic_data_offset
= dynamic
->data_offset
;
1794 dynamic
->data_offset
+= sizeof(ElfW(Dyn
)) * EXTRA_RELITEMS
;
1796 /* still need to build got entries in case of static link */
1797 build_got_entries(s1
);
1801 memset(&ehdr
, 0, sizeof(ehdr
));
1803 /* we add a section for symbols */
1804 strsec
= new_section(s1
, ".shstrtab", SHT_STRTAB
, 0);
1805 put_elf_str(strsec
, "");
1807 /* compute number of sections */
1808 shnum
= s1
->nb_sections
;
1810 /* this array is used to reorder sections in the output file */
1811 section_order
= tcc_malloc(sizeof(int) * shnum
);
1812 section_order
[0] = 0;
1815 /* compute number of program headers */
1818 case TCC_OUTPUT_OBJ
:
1821 case TCC_OUTPUT_EXE
:
1822 if (!s1
->static_link
)
1823 phnum
= 4 + HAVE_PHDR
;
1827 case TCC_OUTPUT_DLL
:
1832 /* allocate strings for section names and decide if an unallocated
1833 section should be output */
1834 /* NOTE: the strsec section comes last, so its size is also
1836 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1837 s
= s1
->sections
[i
];
1838 s
->sh_name
= put_elf_str(strsec
, s
->name
);
1840 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1845 s
->reloc
? s
->reloc
->name
: "n"
1848 /* when generating a DLL, we include relocations but we may
1850 if (file_type
== TCC_OUTPUT_DLL
&&
1851 s
->sh_type
== SHT_RELX
&&
1852 !(s
->sh_flags
& SHF_ALLOC
)) {
1853 /* //gr: avoid bogus relocs for empty (debug) sections */
1854 if (s1
->sections
[s
->sh_info
]->sh_flags
& SHF_ALLOC
)
1855 prepare_dynamic_rel(s1
, s
);
1856 else if (s1
->do_debug
)
1857 s
->sh_size
= s
->data_offset
;
1858 } else if (s1
->do_debug
||
1859 file_type
== TCC_OUTPUT_OBJ
||
1860 (s
->sh_flags
& SHF_ALLOC
) ||
1861 i
== (s1
->nb_sections
- 1)) {
1862 /* we output all sections if debug or object file */
1863 s
->sh_size
= s
->data_offset
;
1867 /* allocate program segment headers */
1868 phdr
= tcc_mallocz(phnum
* sizeof(ElfW(Phdr
)));
1870 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1871 file_offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
1876 /* compute section to program header mapping */
1877 if (s1
->has_text_addr
) {
1878 int a_offset
, p_offset
;
1879 addr
= s1
->text_addr
;
1880 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1882 a_offset
= (int) (addr
& (s1
->section_align
- 1));
1883 p_offset
= file_offset
& (s1
->section_align
- 1);
1884 if (a_offset
< p_offset
)
1885 a_offset
+= s1
->section_align
;
1886 file_offset
+= (a_offset
- p_offset
);
1888 if (file_type
== TCC_OUTPUT_DLL
)
1891 addr
= ELF_START_ADDR
;
1892 /* compute address after headers */
1893 addr
+= (file_offset
& (s1
->section_align
- 1));
1896 /* dynamic relocation table information, for .dynamic section */
1900 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1901 bss_addr
= bss_size
= 0;
1903 /* leave one program header for the program interpreter */
1906 ph
+= 1 + HAVE_PHDR
;
1908 for(j
= 0; j
< 2; j
++) {
1909 ph
->p_type
= PT_LOAD
;
1911 ph
->p_flags
= PF_R
| PF_X
;
1913 ph
->p_flags
= PF_R
| PF_W
;
1914 ph
->p_align
= s1
->section_align
;
1916 /* we do the following ordering: interp, symbol tables,
1917 relocations, progbits, nobits */
1918 /* XXX: do faster and simpler sorting */
1919 for(k
= 0; k
< 5; k
++) {
1920 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1921 s
= s1
->sections
[i
];
1922 /* compute if section should be included */
1924 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1928 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1929 (SHF_ALLOC
| SHF_WRITE
))
1935 } else if (s
->sh_type
== SHT_DYNSYM
||
1936 s
->sh_type
== SHT_STRTAB
||
1937 s
->sh_type
== SHT_HASH
) {
1940 } else if (s
->sh_type
== SHT_RELX
) {
1943 } else if (s
->sh_type
== SHT_NOBITS
) {
1950 section_order
[sh_order_index
++] = i
;
1952 /* section matches: we align it and add its size */
1954 addr
= (addr
+ s
->sh_addralign
- 1) &
1955 ~(s
->sh_addralign
- 1);
1956 file_offset
+= (int) ( addr
- tmp
);
1957 s
->sh_offset
= file_offset
;
1960 /* update program header infos */
1961 if (ph
->p_offset
== 0) {
1962 ph
->p_offset
= file_offset
;
1964 ph
->p_paddr
= ph
->p_vaddr
;
1966 /* update dynamic relocation infos */
1967 if (s
->sh_type
== SHT_RELX
) {
1968 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1969 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.got")) { // rel_size == 0) {
1971 rel_size
+= s
->sh_size
; // XXX only first rel.
1973 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.bss")) { // rel_size == 0) {
1975 bss_size
= s
->sh_size
; // XXX only first rel.
1980 rel_size
+= s
->sh_size
;
1984 if (s
->sh_type
!= SHT_NOBITS
)
1985 file_offset
+= s
->sh_size
;
1988 ph
->p_filesz
= file_offset
- ph
->p_offset
;
1989 ph
->p_memsz
= addr
- ph
->p_vaddr
;
1992 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1993 /* if in the middle of a page, we duplicate the page in
1994 memory so that one copy is RX and the other is RW */
1995 if ((addr
& (s1
->section_align
- 1)) != 0)
1996 addr
+= s1
->section_align
;
1998 addr
= (addr
+ s1
->section_align
- 1) & ~(s1
->section_align
- 1);
1999 file_offset
= (file_offset
+ s1
->section_align
- 1) &
2000 ~(s1
->section_align
- 1);
2005 /* if interpreter, then add corresponing program header */
2009 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2011 int len
= phnum
* sizeof(ElfW(Phdr
));
2013 ph
->p_type
= PT_PHDR
;
2014 ph
->p_offset
= sizeof(ElfW(Ehdr
));
2015 ph
->p_vaddr
= interp
->sh_addr
- len
;
2016 ph
->p_paddr
= ph
->p_vaddr
;
2017 ph
->p_filesz
= ph
->p_memsz
= len
;
2018 ph
->p_flags
= PF_R
| PF_X
;
2019 ph
->p_align
= 4; // interp->sh_addralign;
2024 ph
->p_type
= PT_INTERP
;
2025 ph
->p_offset
= interp
->sh_offset
;
2026 ph
->p_vaddr
= interp
->sh_addr
;
2027 ph
->p_paddr
= ph
->p_vaddr
;
2028 ph
->p_filesz
= interp
->sh_size
;
2029 ph
->p_memsz
= interp
->sh_size
;
2031 ph
->p_align
= interp
->sh_addralign
;
2034 /* if dynamic section, then add corresponing program header */
2038 ph
= &phdr
[phnum
- 1];
2040 ph
->p_type
= PT_DYNAMIC
;
2041 ph
->p_offset
= dynamic
->sh_offset
;
2042 ph
->p_vaddr
= dynamic
->sh_addr
;
2043 ph
->p_paddr
= ph
->p_vaddr
;
2044 ph
->p_filesz
= dynamic
->sh_size
;
2045 ph
->p_memsz
= dynamic
->sh_size
;
2046 ph
->p_flags
= PF_R
| PF_W
;
2047 ph
->p_align
= dynamic
->sh_addralign
;
2049 /* put GOT dynamic section address */
2050 put32(s1
->got
->data
, dynamic
->sh_addr
);
2052 /* relocate the PLT */
2053 if (file_type
== TCC_OUTPUT_EXE
2054 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2055 || file_type
== TCC_OUTPUT_DLL
2061 p_end
= p
+ s1
->plt
->data_offset
;
2063 #if defined(TCC_TARGET_I386)
2064 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
2065 put32(p
+ 8, get32(p
+ 8) + s1
->got
->sh_addr
);
2068 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
2071 #elif defined(TCC_TARGET_X86_64)
2072 int x
= s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 6;
2073 put32(p
+ 2, get32(p
+ 2) + x
);
2074 put32(p
+ 8, get32(p
+ 8) + x
- 6);
2077 put32(p
+ 2, get32(p
+ 2) + x
+ s1
->plt
->data
- p
);
2080 #elif defined(TCC_TARGET_ARM)
2082 x
=s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 12;
2085 if (get32(p
) == 0x46c04778) /* PLT Thumb stub present */
2087 put32(p
+ 12, x
+ get32(p
+ 12) + s1
->plt
->data
- p
);
2090 #elif defined(TCC_TARGET_C67)
2093 #error unsupported CPU
2098 /* relocate symbols in .dynsym */
2099 sym_end
= (ElfW(Sym
) *)(s1
->dynsym
->data
+ s1
->dynsym
->data_offset
);
2100 for(sym
= (ElfW(Sym
) *)s1
->dynsym
->data
+ 1;
2103 if (sym
->st_shndx
== SHN_UNDEF
) {
2104 /* relocate to the PLT if the symbol corresponds
2107 sym
->st_value
+= s1
->plt
->sh_addr
;
2108 } else if (sym
->st_shndx
< SHN_LORESERVE
) {
2109 /* do symbol relocation */
2110 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
2114 /* put dynamic section entries */
2115 dynamic
->data_offset
= saved_dynamic_data_offset
;
2116 put_dt(dynamic
, DT_HASH
, s1
->dynsym
->hash
->sh_addr
);
2117 put_dt(dynamic
, DT_STRTAB
, dynstr
->sh_addr
);
2118 put_dt(dynamic
, DT_SYMTAB
, s1
->dynsym
->sh_addr
);
2119 put_dt(dynamic
, DT_STRSZ
, dynstr
->data_offset
);
2120 put_dt(dynamic
, DT_SYMENT
, sizeof(ElfW(Sym
)));
2121 #ifdef TCC_TARGET_X86_64
2122 put_dt(dynamic
, DT_RELA
, rel_addr
);
2123 put_dt(dynamic
, DT_RELASZ
, rel_size
);
2124 put_dt(dynamic
, DT_RELAENT
, sizeof(ElfW_Rel
));
2126 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2127 put_dt(dynamic
, DT_PLTGOT
, s1
->got
->sh_addr
);
2128 put_dt(dynamic
, DT_PLTRELSZ
, rel_size
);
2129 put_dt(dynamic
, DT_JMPREL
, rel_addr
);
2130 put_dt(dynamic
, DT_PLTREL
, DT_REL
);
2131 put_dt(dynamic
, DT_REL
, bss_addr
);
2132 put_dt(dynamic
, DT_RELSZ
, bss_size
);
2134 put_dt(dynamic
, DT_REL
, rel_addr
);
2135 put_dt(dynamic
, DT_RELSZ
, rel_size
);
2136 put_dt(dynamic
, DT_RELENT
, sizeof(ElfW_Rel
));
2140 put_dt(dynamic
, DT_DEBUG
, 0);
2141 put_dt(dynamic
, DT_NULL
, 0);
2144 ehdr
.e_phentsize
= sizeof(ElfW(Phdr
));
2145 ehdr
.e_phnum
= phnum
;
2146 ehdr
.e_phoff
= sizeof(ElfW(Ehdr
));
2149 /* all other sections come after */
2150 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2151 s
= s1
->sections
[i
];
2152 if (phnum
> 0 && (s
->sh_flags
& SHF_ALLOC
))
2154 section_order
[sh_order_index
++] = i
;
2156 file_offset
= (file_offset
+ s
->sh_addralign
- 1) &
2157 ~(s
->sh_addralign
- 1);
2158 s
->sh_offset
= file_offset
;
2159 if (s
->sh_type
!= SHT_NOBITS
)
2160 file_offset
+= s
->sh_size
;
2163 /* if building executable or DLL, then relocate each section
2164 except the GOT which is already relocated */
2165 if (file_type
!= TCC_OUTPUT_OBJ
) {
2166 relocate_syms(s1
, 0);
2168 if (s1
->nb_errors
!= 0) {
2174 /* relocate sections */
2175 /* XXX: ignore sections with allocated relocations ? */
2176 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2177 s
= s1
->sections
[i
];
2178 if (s
->reloc
&& s
!= s1
->got
)
2179 relocate_section(s1
, s
);
2182 /* relocate relocation entries if the relocation tables are
2183 allocated in the executable */
2184 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2185 s
= s1
->sections
[i
];
2186 if ((s
->sh_flags
& SHF_ALLOC
) &&
2187 s
->sh_type
== SHT_RELX
) {
2188 relocate_rel(s1
, s
);
2192 /* get entry point address */
2193 if (file_type
== TCC_OUTPUT_EXE
)
2194 ehdr
.e_entry
= get_elf_sym_addr(s1
, "_start", 1);
2196 ehdr
.e_entry
= text_section
->sh_addr
; /* XXX: is it correct ? */
2198 if (file_type
== TCC_OUTPUT_EXE
&& s1
->static_link
)
2201 /* write elf file */
2202 if (file_type
== TCC_OUTPUT_OBJ
)
2207 fd
= open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
, mode
);
2209 tcc_error_noabort("could not write '%s'", filename
);
2212 f
= fdopen(fd
, "wb");
2214 printf("<- %s\n", filename
);
2216 #ifdef TCC_TARGET_COFF
2217 if (s1
->output_format
== TCC_OUTPUT_FORMAT_COFF
) {
2218 tcc_output_coff(s1
, f
);
2221 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
2222 sort_syms(s1
, symtab_section
);
2225 file_offset
= (file_offset
+ 3) & -4;
2228 ehdr
.e_ident
[0] = ELFMAG0
;
2229 ehdr
.e_ident
[1] = ELFMAG1
;
2230 ehdr
.e_ident
[2] = ELFMAG2
;
2231 ehdr
.e_ident
[3] = ELFMAG3
;
2232 ehdr
.e_ident
[4] = ELFCLASSW
;
2233 ehdr
.e_ident
[5] = ELFDATA2LSB
;
2234 ehdr
.e_ident
[6] = EV_CURRENT
;
2235 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2236 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_FREEBSD
;
2238 #ifdef TCC_TARGET_ARM
2240 ehdr
.e_ident
[EI_OSABI
] = 0;
2241 ehdr
.e_flags
= 4 << 24;
2243 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_ARM
;
2248 case TCC_OUTPUT_EXE
:
2249 ehdr
.e_type
= ET_EXEC
;
2251 case TCC_OUTPUT_DLL
:
2252 ehdr
.e_type
= ET_DYN
;
2254 case TCC_OUTPUT_OBJ
:
2255 ehdr
.e_type
= ET_REL
;
2258 ehdr
.e_machine
= EM_TCC_TARGET
;
2259 ehdr
.e_version
= EV_CURRENT
;
2260 ehdr
.e_shoff
= file_offset
;
2261 ehdr
.e_ehsize
= sizeof(ElfW(Ehdr
));
2262 ehdr
.e_shentsize
= sizeof(ElfW(Shdr
));
2263 ehdr
.e_shnum
= shnum
;
2264 ehdr
.e_shstrndx
= shnum
- 1;
2266 fwrite(&ehdr
, 1, sizeof(ElfW(Ehdr
)), f
);
2267 fwrite(phdr
, 1, phnum
* sizeof(ElfW(Phdr
)), f
);
2268 offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
2270 for(i
=1;i
<s1
->nb_sections
;i
++) {
2271 s
= s1
->sections
[section_order
[i
]];
2272 if (s
->sh_type
!= SHT_NOBITS
) {
2273 if (s
->sh_type
== SHT_DYNSYM
)
2274 patch_dynsym_undef(s1
, s
);
2275 while (offset
< s
->sh_offset
) {
2280 fwrite(s
->data
, 1, size
, f
);
2285 /* output section headers */
2286 while (offset
< ehdr
.e_shoff
) {
2291 for(i
=0;i
<s1
->nb_sections
;i
++) {
2293 memset(sh
, 0, sizeof(ElfW(Shdr
)));
2294 s
= s1
->sections
[i
];
2296 sh
->sh_name
= s
->sh_name
;
2297 sh
->sh_type
= s
->sh_type
;
2298 sh
->sh_flags
= s
->sh_flags
;
2299 sh
->sh_entsize
= s
->sh_entsize
;
2300 sh
->sh_info
= s
->sh_info
;
2302 sh
->sh_link
= s
->link
->sh_num
;
2303 sh
->sh_addralign
= s
->sh_addralign
;
2304 sh
->sh_addr
= s
->sh_addr
;
2305 sh
->sh_offset
= s
->sh_offset
;
2306 sh
->sh_size
= s
->sh_size
;
2308 fwrite(sh
, 1, sizeof(ElfW(Shdr
)), f
);
2311 tcc_output_binary(s1
, f
, section_order
);
2317 tcc_free(s1
->symtab_to_dynsym
);
2318 tcc_free(section_order
);
2320 tcc_free(s1
->sym_attrs
);
2324 LIBTCCAPI
int tcc_output_file(TCCState
*s
, const char *filename
)
2327 #ifdef TCC_TARGET_PE
2328 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
2329 ret
= pe_output_file(s
, filename
);
2333 ret
= elf_output_file(s
, filename
);
2338 static void *load_data(int fd
, unsigned long file_offset
, unsigned long size
)
2342 data
= tcc_malloc(size
);
2343 lseek(fd
, file_offset
, SEEK_SET
);
2344 read(fd
, data
, size
);
2348 typedef struct SectionMergeInfo
{
2349 Section
*s
; /* corresponding existing section */
2350 unsigned long offset
; /* offset of the new section in the existing section */
2351 uint8_t new_section
; /* true if section 's' was added */
2352 uint8_t link_once
; /* true if link once section */
2355 /* load an object file and merge it with current files */
2356 /* XXX: handle correctly stab (debug) info */
2357 ST_FUNC
int tcc_load_object_file(TCCState
*s1
,
2358 int fd
, unsigned long file_offset
)
2361 ElfW(Shdr
) *shdr
, *sh
;
2362 int size
, i
, j
, offset
, offseti
, nb_syms
, sym_index
, ret
;
2363 unsigned char *strsec
, *strtab
;
2364 int *old_to_new_syms
;
2365 char *sh_name
, *name
;
2366 SectionMergeInfo
*sm_table
, *sm
;
2367 ElfW(Sym
) *sym
, *symtab
;
2368 ElfW_Rel
*rel
, *rel_end
;
2374 stab_index
= stabstr_index
= 0;
2376 if (read(fd
, &ehdr
, sizeof(ehdr
)) != sizeof(ehdr
))
2378 if (ehdr
.e_ident
[0] != ELFMAG0
||
2379 ehdr
.e_ident
[1] != ELFMAG1
||
2380 ehdr
.e_ident
[2] != ELFMAG2
||
2381 ehdr
.e_ident
[3] != ELFMAG3
)
2383 /* test if object file */
2384 if (ehdr
.e_type
!= ET_REL
)
2386 /* test CPU specific stuff */
2387 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2388 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2390 tcc_error_noabort("invalid object file");
2394 shdr
= load_data(fd
, file_offset
+ ehdr
.e_shoff
,
2395 sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2396 sm_table
= tcc_mallocz(sizeof(SectionMergeInfo
) * ehdr
.e_shnum
);
2398 /* load section names */
2399 sh
= &shdr
[ehdr
.e_shstrndx
];
2400 strsec
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2402 /* load symtab and strtab */
2403 old_to_new_syms
= NULL
;
2407 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2409 if (sh
->sh_type
== SHT_SYMTAB
) {
2411 tcc_error_noabort("object must contain only one symtab");
2416 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2417 symtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2418 sm_table
[i
].s
= symtab_section
;
2420 /* now load strtab */
2421 sh
= &shdr
[sh
->sh_link
];
2422 strtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2426 /* now examine each section and try to merge its content with the
2428 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2429 /* no need to examine section name strtab */
2430 if (i
== ehdr
.e_shstrndx
)
2433 sh_name
= strsec
+ sh
->sh_name
;
2434 /* ignore sections types we do not handle */
2435 if (sh
->sh_type
!= SHT_PROGBITS
&&
2436 sh
->sh_type
!= SHT_RELX
&&
2438 sh
->sh_type
!= SHT_ARM_EXIDX
&&
2440 sh
->sh_type
!= SHT_NOBITS
&&
2441 sh
->sh_type
!= SHT_PREINIT_ARRAY
&&
2442 sh
->sh_type
!= SHT_INIT_ARRAY
&&
2443 sh
->sh_type
!= SHT_FINI_ARRAY
&&
2444 strcmp(sh_name
, ".stabstr")
2447 if (sh
->sh_addralign
< 1)
2448 sh
->sh_addralign
= 1;
2449 /* find corresponding section, if any */
2450 for(j
= 1; j
< s1
->nb_sections
;j
++) {
2451 s
= s1
->sections
[j
];
2452 if (!strcmp(s
->name
, sh_name
)) {
2453 if (!strncmp(sh_name
, ".gnu.linkonce",
2454 sizeof(".gnu.linkonce") - 1)) {
2455 /* if a 'linkonce' section is already present, we
2456 do not add it again. It is a little tricky as
2457 symbols can still be defined in
2459 sm_table
[i
].link_once
= 1;
2466 /* not found: create new section */
2467 s
= new_section(s1
, sh_name
, sh
->sh_type
, sh
->sh_flags
);
2468 /* take as much info as possible from the section. sh_link and
2469 sh_info will be updated later */
2470 s
->sh_addralign
= sh
->sh_addralign
;
2471 s
->sh_entsize
= sh
->sh_entsize
;
2472 sm_table
[i
].new_section
= 1;
2474 if (sh
->sh_type
!= s
->sh_type
) {
2475 tcc_error_noabort("invalid section type");
2479 /* align start of section */
2480 offset
= s
->data_offset
;
2482 if (0 == strcmp(sh_name
, ".stab")) {
2486 if (0 == strcmp(sh_name
, ".stabstr")) {
2491 size
= sh
->sh_addralign
- 1;
2492 offset
= (offset
+ size
) & ~size
;
2493 if (sh
->sh_addralign
> s
->sh_addralign
)
2494 s
->sh_addralign
= sh
->sh_addralign
;
2495 s
->data_offset
= offset
;
2497 sm_table
[i
].offset
= offset
;
2499 /* concatenate sections */
2501 if (sh
->sh_type
!= SHT_NOBITS
) {
2503 lseek(fd
, file_offset
+ sh
->sh_offset
, SEEK_SET
);
2504 ptr
= section_ptr_add(s
, size
);
2505 read(fd
, ptr
, size
);
2507 s
->data_offset
+= size
;
2512 /* //gr relocate stab strings */
2513 if (stab_index
&& stabstr_index
) {
2516 s
= sm_table
[stab_index
].s
;
2517 a
= (Stab_Sym
*)(s
->data
+ sm_table
[stab_index
].offset
);
2518 b
= (Stab_Sym
*)(s
->data
+ s
->data_offset
);
2519 o
= sm_table
[stabstr_index
].offset
;
2521 a
->n_strx
+= o
, a
++;
2524 /* second short pass to update sh_link and sh_info fields of new
2526 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2528 if (!s
|| !sm_table
[i
].new_section
)
2531 if (sh
->sh_link
> 0)
2532 s
->link
= sm_table
[sh
->sh_link
].s
;
2533 if (sh
->sh_type
== SHT_RELX
) {
2534 s
->sh_info
= sm_table
[sh
->sh_info
].s
->sh_num
;
2535 /* update backward link */
2536 s1
->sections
[s
->sh_info
]->reloc
= s
;
2541 /* resolve symbols */
2542 old_to_new_syms
= tcc_mallocz(nb_syms
* sizeof(int));
2545 for(i
= 1; i
< nb_syms
; i
++, sym
++) {
2546 if (sym
->st_shndx
!= SHN_UNDEF
&&
2547 sym
->st_shndx
< SHN_LORESERVE
) {
2548 sm
= &sm_table
[sym
->st_shndx
];
2549 if (sm
->link_once
) {
2550 /* if a symbol is in a link once section, we use the
2551 already defined symbol. It is very important to get
2552 correct relocations */
2553 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
2554 name
= strtab
+ sym
->st_name
;
2555 sym_index
= find_elf_sym(symtab_section
, name
);
2557 old_to_new_syms
[i
] = sym_index
;
2561 /* if no corresponding section added, no need to add symbol */
2564 /* convert section number */
2565 sym
->st_shndx
= sm
->s
->sh_num
;
2567 sym
->st_value
+= sm
->offset
;
2570 name
= strtab
+ sym
->st_name
;
2571 sym_index
= add_elf_sym(symtab_section
, sym
->st_value
, sym
->st_size
,
2572 sym
->st_info
, sym
->st_other
,
2573 sym
->st_shndx
, name
);
2574 old_to_new_syms
[i
] = sym_index
;
2577 /* third pass to patch relocation entries */
2578 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2583 offset
= sm_table
[i
].offset
;
2584 switch(s
->sh_type
) {
2586 /* take relocation offset information */
2587 offseti
= sm_table
[sh
->sh_info
].offset
;
2588 rel_end
= (ElfW_Rel
*)(s
->data
+ s
->data_offset
);
2589 for(rel
= (ElfW_Rel
*)(s
->data
+ offset
);
2594 /* convert symbol index */
2595 type
= ELFW(R_TYPE
)(rel
->r_info
);
2596 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
2597 /* NOTE: only one symtab assumed */
2598 if (sym_index
>= nb_syms
)
2600 sym_index
= old_to_new_syms
[sym_index
];
2601 /* ignore link_once in rel section. */
2602 if (!sym_index
&& !sm
->link_once
2603 #ifdef TCC_TARGET_ARM
2604 && type
!= R_ARM_V4BX
2608 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2609 i
, strsec
+ sh
->sh_name
, rel
->r_offset
);
2612 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
2613 /* offset the relocation offset */
2614 rel
->r_offset
+= offseti
;
2615 #ifdef TCC_TARGET_ARM
2616 /* Jumps and branches from a Thumb code to a PLT entry need
2617 special handling since PLT entries are ARM code.
2618 Unconditional bl instructions referencing PLT entries are
2619 handled by converting these instructions into blx
2620 instructions. Other case of instructions referencing a PLT
2621 entry require to add a Thumb stub before the PLT entry to
2622 switch to ARM mode. We set bit 0 of the got offset of a
2623 symbol to indicate such a case. */
2624 if (type
== R_ARM_THM_JUMP24
)
2625 alloc_sym_attr(s1
, sym_index
)->plt_thumb_stub
= 1;
2638 tcc_free(old_to_new_syms
);
2645 typedef struct ArchiveHeader
{
2646 char ar_name
[16]; /* name of this member */
2647 char ar_date
[12]; /* file mtime */
2648 char ar_uid
[6]; /* owner uid; printed as decimal */
2649 char ar_gid
[6]; /* owner gid; printed as decimal */
2650 char ar_mode
[8]; /* file mode, printed as octal */
2651 char ar_size
[10]; /* file size, printed as decimal */
2652 char ar_fmag
[2]; /* should contain ARFMAG */
2655 static int get_be32(const uint8_t *b
)
2657 return b
[3] | (b
[2] << 8) | (b
[1] << 16) | (b
[0] << 24);
2660 /* load only the objects which resolve undefined symbols */
2661 static int tcc_load_alacarte(TCCState
*s1
, int fd
, int size
)
2663 int i
, bound
, nsyms
, sym_index
, off
, ret
;
2665 const char *ar_names
, *p
;
2666 const uint8_t *ar_index
;
2669 data
= tcc_malloc(size
);
2670 if (read(fd
, data
, size
) != size
)
2672 nsyms
= get_be32(data
);
2673 ar_index
= data
+ 4;
2674 ar_names
= ar_index
+ nsyms
* 4;
2678 for(p
= ar_names
, i
= 0; i
< nsyms
; i
++, p
+= strlen(p
)+1) {
2679 sym_index
= find_elf_sym(symtab_section
, p
);
2681 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
2682 if(sym
->st_shndx
== SHN_UNDEF
) {
2683 off
= get_be32(ar_index
+ i
* 4) + sizeof(ArchiveHeader
);
2685 printf("%5d\t%s\t%08x\n", i
, p
, sym
->st_shndx
);
2688 lseek(fd
, off
, SEEK_SET
);
2689 if(tcc_load_object_file(s1
, fd
, off
) < 0) {
2704 /* load a '.a' file */
2705 ST_FUNC
int tcc_load_archive(TCCState
*s1
, int fd
)
2712 unsigned long file_offset
;
2714 /* skip magic which was already checked */
2715 read(fd
, magic
, sizeof(magic
));
2718 len
= read(fd
, &hdr
, sizeof(hdr
));
2721 if (len
!= sizeof(hdr
)) {
2722 tcc_error_noabort("invalid archive");
2725 memcpy(ar_size
, hdr
.ar_size
, sizeof(hdr
.ar_size
));
2726 ar_size
[sizeof(hdr
.ar_size
)] = '\0';
2727 size
= strtol(ar_size
, NULL
, 0);
2728 memcpy(ar_name
, hdr
.ar_name
, sizeof(hdr
.ar_name
));
2729 for(i
= sizeof(hdr
.ar_name
) - 1; i
>= 0; i
--) {
2730 if (ar_name
[i
] != ' ')
2733 ar_name
[i
+ 1] = '\0';
2734 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2735 file_offset
= lseek(fd
, 0, SEEK_CUR
);
2737 size
= (size
+ 1) & ~1;
2738 if (!strcmp(ar_name
, "/")) {
2739 /* coff symbol table : we handle it */
2740 if(s1
->alacarte_link
)
2741 return tcc_load_alacarte(s1
, fd
, size
);
2742 } else if (!strcmp(ar_name
, "//") ||
2743 !strcmp(ar_name
, "__.SYMDEF") ||
2744 !strcmp(ar_name
, "__.SYMDEF/") ||
2745 !strcmp(ar_name
, "ARFILENAMES/")) {
2746 /* skip symbol table or archive names */
2748 if (tcc_load_object_file(s1
, fd
, file_offset
) < 0)
2751 lseek(fd
, file_offset
+ size
, SEEK_SET
);
2756 #ifndef TCC_TARGET_PE
2757 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2758 is referenced by the user (so it should be added as DT_NEEDED in
2759 the generated ELF file) */
2760 ST_FUNC
int tcc_load_dll(TCCState
*s1
, int fd
, const char *filename
, int level
)
2763 ElfW(Shdr
) *shdr
, *sh
, *sh1
;
2764 int i
, j
, nb_syms
, nb_dts
, sym_bind
, ret
;
2765 ElfW(Sym
) *sym
, *dynsym
;
2766 ElfW(Dyn
) *dt
, *dynamic
;
2767 unsigned char *dynstr
;
2768 const char *name
, *soname
;
2769 DLLReference
*dllref
;
2771 read(fd
, &ehdr
, sizeof(ehdr
));
2773 /* test CPU specific stuff */
2774 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2775 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2776 tcc_error_noabort("bad architecture");
2781 shdr
= load_data(fd
, ehdr
.e_shoff
, sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2783 /* load dynamic section and dynamic symbols */
2787 dynsym
= NULL
; /* avoid warning */
2788 dynstr
= NULL
; /* avoid warning */
2789 for(i
= 0, sh
= shdr
; i
< ehdr
.e_shnum
; i
++, sh
++) {
2790 switch(sh
->sh_type
) {
2792 nb_dts
= sh
->sh_size
/ sizeof(ElfW(Dyn
));
2793 dynamic
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2796 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2797 dynsym
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2798 sh1
= &shdr
[sh
->sh_link
];
2799 dynstr
= load_data(fd
, sh1
->sh_offset
, sh1
->sh_size
);
2806 /* compute the real library name */
2807 soname
= tcc_basename(filename
);
2809 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2810 if (dt
->d_tag
== DT_SONAME
) {
2811 soname
= dynstr
+ dt
->d_un
.d_val
;
2815 /* if the dll is already loaded, do not load it */
2816 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
2817 dllref
= s1
->loaded_dlls
[i
];
2818 if (!strcmp(soname
, dllref
->name
)) {
2819 /* but update level if needed */
2820 if (level
< dllref
->level
)
2821 dllref
->level
= level
;
2827 // printf("loading dll '%s'\n", soname);
2829 /* add the dll and its level */
2830 dllref
= tcc_mallocz(sizeof(DLLReference
) + strlen(soname
));
2831 dllref
->level
= level
;
2832 strcpy(dllref
->name
, soname
);
2833 dynarray_add((void ***)&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
, dllref
);
2835 /* add dynamic symbols in dynsym_section */
2836 for(i
= 1, sym
= dynsym
+ 1; i
< nb_syms
; i
++, sym
++) {
2837 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
2838 if (sym_bind
== STB_LOCAL
)
2840 name
= dynstr
+ sym
->st_name
;
2841 add_elf_sym(s1
->dynsymtab_section
, sym
->st_value
, sym
->st_size
,
2842 sym
->st_info
, sym
->st_other
, sym
->st_shndx
, name
);
2845 /* load all referenced DLLs */
2846 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2849 name
= dynstr
+ dt
->d_un
.d_val
;
2850 for(j
= 0; j
< s1
->nb_loaded_dlls
; j
++) {
2851 dllref
= s1
->loaded_dlls
[j
];
2852 if (!strcmp(name
, dllref
->name
))
2853 goto already_loaded
;
2855 if (tcc_add_dll(s1
, name
, AFF_REFERENCED_DLL
) < 0) {
2856 tcc_error_noabort("referenced dll '%s' not found", name
);
2873 #define LD_TOK_NAME 256
2874 #define LD_TOK_EOF (-1)
2876 /* return next ld script token */
2877 static int ld_next(TCCState
*s1
, char *name
, int name_size
)
2895 file
->buf_ptr
= parse_comment(file
->buf_ptr
);
2896 ch
= file
->buf_ptr
[0];
2904 /* case 'a' ... 'z': */
2931 /* case 'A' ... 'z': */
2966 if (!((ch
>= 'a' && ch
<= 'z') ||
2967 (ch
>= 'A' && ch
<= 'Z') ||
2968 (ch
>= '0' && ch
<= '9') ||
2969 strchr("/.-_+=$:\\,~", ch
)))
2971 if ((q
- name
) < name_size
- 1) {
2988 printf("tok=%c %d\n", c
, c
);
2989 if (c
== LD_TOK_NAME
)
2990 printf(" name=%s\n", name
);
2995 static int ld_add_file(TCCState
*s1
, const char filename
[])
2999 ret
= tcc_add_file_internal(s1
, filename
, 0);
3001 ret
= tcc_add_dll(s1
, filename
, 0);
3005 static inline int new_undef_syms(void)
3008 ret
= new_undef_sym
;
3013 static int ld_add_file_list(TCCState
*s1
, const char *cmd
, int as_needed
)
3015 char filename
[1024], libname
[1024];
3016 int t
, group
, nblibs
= 0, ret
= 0;
3019 group
= !strcmp(cmd
, "GROUP");
3022 t
= ld_next(s1
, filename
, sizeof(filename
));
3025 t
= ld_next(s1
, filename
, sizeof(filename
));
3028 if (t
== LD_TOK_EOF
) {
3029 tcc_error_noabort("unexpected end of file");
3031 goto lib_parse_error
;
3032 } else if (t
== ')') {
3034 } else if (t
== '-') {
3035 t
= ld_next(s1
, filename
, sizeof(filename
));
3036 if ((t
!= LD_TOK_NAME
) || (filename
[0] != 'l')) {
3037 tcc_error_noabort("library name expected");
3039 goto lib_parse_error
;
3041 pstrcpy(libname
, sizeof libname
, &filename
[1]);
3042 if (s1
->static_link
) {
3043 snprintf(filename
, sizeof filename
, "lib%s.a", libname
);
3045 snprintf(filename
, sizeof filename
, "lib%s.so", libname
);
3047 } else if (t
!= LD_TOK_NAME
) {
3048 tcc_error_noabort("filename expected");
3050 goto lib_parse_error
;
3052 if (!strcmp(filename
, "AS_NEEDED")) {
3053 ret
= ld_add_file_list(s1
, cmd
, 1);
3055 goto lib_parse_error
;
3057 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3059 ret
= ld_add_file(s1
, filename
);
3061 goto lib_parse_error
;
3063 /* Add the filename *and* the libname to avoid future conversions */
3064 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(filename
));
3065 if (libname
[0] != '\0')
3066 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(libname
));
3070 t
= ld_next(s1
, filename
, sizeof(filename
));
3072 t
= ld_next(s1
, filename
, sizeof(filename
));
3075 if (group
&& !as_needed
) {
3076 while (new_undef_syms()) {
3079 for (i
= 0; i
< nblibs
; i
++)
3080 ld_add_file(s1
, libs
[i
]);
3084 dynarray_reset(&libs
, &nblibs
);
3088 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3090 ST_FUNC
int tcc_load_ldscript(TCCState
*s1
)
3093 char filename
[1024];
3096 ch
= file
->buf_ptr
[0];
3099 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3100 if (t
== LD_TOK_EOF
)
3102 else if (t
!= LD_TOK_NAME
)
3104 if (!strcmp(cmd
, "INPUT") ||
3105 !strcmp(cmd
, "GROUP")) {
3106 ret
= ld_add_file_list(s1
, cmd
, 0);
3109 } else if (!strcmp(cmd
, "OUTPUT_FORMAT") ||
3110 !strcmp(cmd
, "TARGET")) {
3111 /* ignore some commands */
3112 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3116 t
= ld_next(s1
, filename
, sizeof(filename
));
3117 if (t
== LD_TOK_EOF
) {
3118 tcc_error_noabort("unexpected end of file");
3120 } else if (t
== ')') {
3130 #endif /* ndef TCC_TARGET_PE */