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
, uplong 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 static void *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 (void*)(uplong
)sym
->st_value
;
175 /* return elf symbol value */
176 LIBTCCAPI
void *tcc_get_symbol(TCCState
*s
, const char *name
)
178 return get_elf_sym_addr(s
, name
, 0);
181 /* return elf symbol value or error */
182 ST_FUNC
void *tcc_get_symbol_err(TCCState
*s
, const char *name
)
184 return get_elf_sym_addr(s
, name
, 1);
187 /* add an elf symbol : check if it is already defined and patch
188 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
189 ST_FUNC
int add_elf_sym(Section
*s
, uplong value
, unsigned long size
,
190 int info
, int other
, int sh_num
, const char *name
)
193 int sym_bind
, sym_index
, sym_type
, esym_bind
;
194 unsigned char sym_vis
, esym_vis
, new_vis
;
196 sym_bind
= ELFW(ST_BIND
)(info
);
197 sym_type
= ELFW(ST_TYPE
)(info
);
198 sym_vis
= ELFW(ST_VISIBILITY
)(other
);
200 if (sym_bind
!= STB_LOCAL
) {
201 /* we search global or weak symbols */
202 sym_index
= find_elf_sym(s
, name
);
205 esym
= &((ElfW(Sym
) *)s
->data
)[sym_index
];
206 if (esym
->st_shndx
!= SHN_UNDEF
) {
207 esym_bind
= ELFW(ST_BIND
)(esym
->st_info
);
208 /* propagate the most constraining visibility */
209 /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
210 esym_vis
= ELFW(ST_VISIBILITY
)(esym
->st_other
);
211 if (esym_vis
== STV_DEFAULT
) {
213 } else if (sym_vis
== STV_DEFAULT
) {
216 new_vis
= (esym_vis
< sym_vis
) ? esym_vis
: sym_vis
;
218 esym
->st_other
= (esym
->st_other
& ~ELFW(ST_VISIBILITY
)(-1))
220 other
= esym
->st_other
; /* in case we have to patch esym */
221 if (sh_num
== SHN_UNDEF
) {
222 /* ignore adding of undefined symbol if the
223 corresponding symbol is already defined */
224 } else if (sym_bind
== STB_GLOBAL
&& esym_bind
== STB_WEAK
) {
225 /* global overrides weak, so patch */
227 } else if (sym_bind
== STB_WEAK
&& esym_bind
== STB_GLOBAL
) {
228 /* weak is ignored if already global */
229 } else if (sym_bind
== STB_WEAK
&& esym_bind
== STB_WEAK
) {
230 /* keep first-found weak definition, ignore subsequents */
231 } else if (sym_vis
== STV_HIDDEN
|| sym_vis
== STV_INTERNAL
) {
232 /* ignore hidden symbols after */
233 } else if (esym
->st_shndx
== SHN_COMMON
234 && (sh_num
< SHN_LORESERVE
|| sh_num
== SHN_COMMON
)) {
235 /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
236 No idea if this is the correct solution ... */
238 } else if (s
== tcc_state
->dynsymtab_section
) {
239 /* we accept that two DLL define the same symbol */
242 printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
243 sym_bind
, sh_num
, new_vis
, esym_bind
, esym
->st_shndx
, esym_vis
);
245 tcc_error_noabort("'%s' defined twice", name
);
249 esym
->st_info
= ELFW(ST_INFO
)(sym_bind
, sym_type
);
250 esym
->st_shndx
= sh_num
;
252 esym
->st_value
= value
;
253 esym
->st_size
= size
;
254 esym
->st_other
= other
;
258 sym_index
= put_elf_sym(s
, value
, size
,
259 ELFW(ST_INFO
)(sym_bind
, sym_type
), other
,
266 ST_FUNC
void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
267 int type
, int symbol
)
275 /* if no relocation section, create it */
276 snprintf(buf
, sizeof(buf
), REL_SECTION_FMT
, s
->name
);
277 /* if the symtab is allocated, then we consider the relocation
279 sr
= new_section(tcc_state
, buf
, SHT_RELX
, symtab
->sh_flags
);
280 sr
->sh_entsize
= sizeof(ElfW_Rel
);
282 sr
->sh_info
= s
->sh_num
;
285 rel
= section_ptr_add(sr
, sizeof(ElfW_Rel
));
286 rel
->r_offset
= offset
;
287 rel
->r_info
= ELFW(R_INFO
)(symbol
, type
);
288 #ifdef TCC_TARGET_X86_64
293 /* put stab debug information */
295 ST_FUNC
void put_stabs(const char *str
, int type
, int other
, int desc
,
300 sym
= section_ptr_add(stab_section
, sizeof(Stab_Sym
));
302 sym
->n_strx
= put_elf_str(stabstr_section
, str
);
307 sym
->n_other
= other
;
309 sym
->n_value
= value
;
312 ST_FUNC
void put_stabs_r(const char *str
, int type
, int other
, int desc
,
313 unsigned long value
, Section
*sec
, int sym_index
)
315 put_stabs(str
, type
, other
, desc
, value
);
316 put_elf_reloc(symtab_section
, stab_section
,
317 stab_section
->data_offset
- sizeof(unsigned int),
318 R_DATA_32
, sym_index
);
321 ST_FUNC
void put_stabn(int type
, int other
, int desc
, int value
)
323 put_stabs(NULL
, type
, other
, desc
, value
);
326 ST_FUNC
void put_stabd(int type
, int other
, int desc
)
328 put_stabs(NULL
, type
, other
, desc
, 0);
331 /* In an ELF file symbol table, the local symbols must appear below
332 the global and weak ones. Since TCC cannot sort it while generating
333 the code, we must do it after. All the relocation tables are also
334 modified to take into account the symbol table sorting */
335 static void sort_syms(TCCState
*s1
, Section
*s
)
337 int *old_to_new_syms
;
341 ElfW_Rel
*rel
, *rel_end
;
345 nb_syms
= s
->data_offset
/ sizeof(ElfW(Sym
));
346 new_syms
= tcc_malloc(nb_syms
* sizeof(ElfW(Sym
)));
347 old_to_new_syms
= tcc_malloc(nb_syms
* sizeof(int));
349 /* first pass for local symbols */
350 p
= (ElfW(Sym
) *)s
->data
;
352 for(i
= 0; i
< nb_syms
; i
++) {
353 if (ELFW(ST_BIND
)(p
->st_info
) == STB_LOCAL
) {
354 old_to_new_syms
[i
] = q
- new_syms
;
359 /* save the number of local symbols in section header */
360 s
->sh_info
= q
- new_syms
;
362 /* then second pass for non local symbols */
363 p
= (ElfW(Sym
) *)s
->data
;
364 for(i
= 0; i
< nb_syms
; i
++) {
365 if (ELFW(ST_BIND
)(p
->st_info
) != STB_LOCAL
) {
366 old_to_new_syms
[i
] = q
- new_syms
;
372 /* we copy the new symbols to the old */
373 memcpy(s
->data
, new_syms
, nb_syms
* sizeof(ElfW(Sym
)));
376 /* now we modify all the relocations */
377 for(i
= 1; i
< s1
->nb_sections
; i
++) {
378 sr
= s1
->sections
[i
];
379 if (sr
->sh_type
== SHT_RELX
&& sr
->link
== s
) {
380 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
381 for(rel
= (ElfW_Rel
*)sr
->data
;
384 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
385 type
= ELFW(R_TYPE
)(rel
->r_info
);
386 sym_index
= old_to_new_syms
[sym_index
];
387 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
392 tcc_free(old_to_new_syms
);
395 /* relocate common symbols in the .bss section */
396 ST_FUNC
void relocate_common_syms(void)
398 ElfW(Sym
) *sym
, *sym_end
;
399 unsigned long offset
, align
;
401 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+ symtab_section
->data_offset
);
402 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
405 if (sym
->st_shndx
== SHN_COMMON
) {
407 align
= sym
->st_value
;
408 offset
= bss_section
->data_offset
;
409 offset
= (offset
+ align
- 1) & -align
;
410 sym
->st_value
= offset
;
411 sym
->st_shndx
= bss_section
->sh_num
;
412 offset
+= sym
->st_size
;
413 bss_section
->data_offset
= offset
;
418 /* relocate symbol table, resolve undefined symbols if do_resolve is
419 true and output error if undefined symbol. */
420 ST_FUNC
void relocate_syms(TCCState
*s1
, int do_resolve
)
422 ElfW(Sym
) *sym
, *esym
, *sym_end
;
423 int sym_bind
, sh_num
, sym_index
;
426 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+ symtab_section
->data_offset
);
427 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
430 sh_num
= sym
->st_shndx
;
431 if (sh_num
== SHN_UNDEF
) {
432 name
= strtab_section
->data
+ sym
->st_name
;
434 #if !defined TCC_TARGET_PE || !defined _WIN32
436 name
= symtab_section
->link
->data
+ sym
->st_name
;
437 addr
= resolve_sym(s1
, name
);
439 sym
->st_value
= (uplong
)addr
;
443 } else if (s1
->dynsym
) {
444 /* if dynamic symbol exist, then use it */
445 sym_index
= find_elf_sym(s1
->dynsym
, name
);
447 esym
= &((ElfW(Sym
) *)s1
->dynsym
->data
)[sym_index
];
448 sym
->st_value
= esym
->st_value
;
452 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
454 if (!strcmp(name
, "_fp_hw"))
456 /* only weak symbols are accepted to be undefined. Their
458 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
459 if (sym_bind
== STB_WEAK
) {
462 tcc_error_noabort("undefined symbol '%s'", name
);
464 } else if (sh_num
< SHN_LORESERVE
) {
465 /* add section base */
466 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
472 #ifndef TCC_TARGET_PE
473 #ifdef TCC_TARGET_X86_64
474 #define JMP_TABLE_ENTRY_SIZE 14
475 static uplong
add_jmp_table(TCCState
*s1
, uplong val
)
477 char *p
= s1
->runtime_plt_and_got
+ s1
->runtime_plt_and_got_offset
;
478 s1
->runtime_plt_and_got_offset
+= JMP_TABLE_ENTRY_SIZE
;
483 *(uplong
*)(p
+ 6) = val
;
487 static uplong
add_got_table(TCCState
*s1
, uplong val
)
489 uplong
*p
= (uplong
*)(s1
->runtime_plt_and_got
+ s1
->runtime_plt_and_got_offset
);
490 s1
->runtime_plt_and_got_offset
+= sizeof(uplong
);
494 #elif defined TCC_TARGET_ARM
495 #define JMP_TABLE_ENTRY_SIZE 8
496 static uplong
add_jmp_table(TCCState
*s1
, int val
)
498 uint32_t *p
= (uint32_t *)(s1
->runtime_plt_and_got
+ s1
->runtime_plt_and_got_offset
);
499 s1
->runtime_plt_and_got_offset
+= JMP_TABLE_ENTRY_SIZE
;
500 /* ldr pc, [pc, #-4] */
508 /* relocate a given section (CPU dependent) */
509 ST_FUNC
void relocate_section(TCCState
*s1
, Section
*s
)
512 ElfW_Rel
*rel
, *rel_end
, *qrel
;
517 #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
522 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
523 qrel
= (ElfW_Rel
*)sr
->data
;
527 ptr
= s
->data
+ rel
->r_offset
;
529 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
530 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
532 #ifdef TCC_TARGET_X86_64
533 val
+= rel
->r_addend
;
535 type
= ELFW(R_TYPE
)(rel
->r_info
);
536 addr
= s
->sh_addr
+ rel
->r_offset
;
540 #if defined(TCC_TARGET_I386)
542 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
543 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
544 qrel
->r_offset
= rel
->r_offset
;
546 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_386_32
);
550 qrel
->r_info
= ELFW(R_INFO
)(0, R_386_RELATIVE
);
557 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
559 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
561 qrel
->r_offset
= rel
->r_offset
;
562 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_386_PC32
);
567 *(int *)ptr
+= val
- addr
;
570 *(int *)ptr
+= val
- addr
;
577 *(int *)ptr
+= s1
->got
->sh_addr
- addr
;
580 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
583 /* we load the got offset */
584 *(int *)ptr
+= s1
->got_offsets
[sym_index
];
587 if (s1
->output_format
!= TCC_OUTPUT_FORMAT_BINARY
) {
589 tcc_error("can only produce 16-bit binary files");
591 *(short *)ptr
+= val
;
594 if (s1
->output_format
!= TCC_OUTPUT_FORMAT_BINARY
)
596 *(short *)ptr
+= val
- addr
;
598 #elif defined(TCC_TARGET_ARM)
604 int x
, is_thumb
, is_call
, h
, blx_avail
;
605 x
= (*(int *)ptr
)&0xffffff;
606 (*(int *)ptr
) &= 0xff000000;
610 blx_avail
= (TCC_ARM_VERSION
>= 5);
612 is_call
= (type
== R_ARM_CALL
);
615 #ifndef TCC_TARGET_PE
616 if ((x
& 3) || x
>= 0x4000000 || x
< -0x4000000)
617 if (!(x
& 3) || !blx_avail
|| !is_call
)
618 if (s1
->output_type
== TCC_OUTPUT_MEMORY
)
619 x
+= add_jmp_table(s1
, val
) - val
; /* add veneer */
621 if ((x
& 3) || x
>= 0x4000000 || x
< -0x4000000)
622 if (!(x
& 3) || !blx_avail
|| !is_call
)
623 tcc_error("can't relocate value at %x",addr
);
626 /* Only reached if blx is avail and it is a call */
629 (*(int *)ptr
) = 0xfa << 24; /* bl -> blx */
634 /* Since these relocations only concern Thumb-2 and blx instruction was
635 introduced before Thumb-2, we can assume blx is available and not
638 case R_ARM_THM_JUMP24
:
640 int x
, hi
, lo
, s
, j1
, j2
, i1
, i2
, imm10
, imm11
;
641 int to_thumb
, is_call
, blx_bit
= 1 << 12;
644 if (sym
->st_shndx
== SHN_UNDEF
&&
645 ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
648 /* Get initial offset */
649 hi
= (*(uint16_t *)ptr
);
650 lo
= (*(uint16_t *)(ptr
+2));
658 x
= (s
<< 24) | (i1
<< 23) | (i2
<< 22) |
659 (imm10
<< 12) | (imm11
<< 1);
663 /* Relocation infos */
665 is_call
= (type
== R_ARM_THM_CALL
);
667 /* Compute final offset */
669 if (!to_thumb
&& is_call
) {
670 blx_bit
= 0; /* bl -> blx */
671 x
= (x
+ 3) & -4; /* Compute offset from aligned PC */
674 /* Check that relocation is possible
675 * offset must not be out of range
676 * if target is to be entered in arm mode:
678 - instruction must be a call (bl) */
679 if (!to_thumb
|| x
>= 0x1000000 || x
< -0x1000000)
680 if (to_thumb
|| (val
& 2) || !is_call
)
681 tcc_error("can't relocate value at %x",addr
);
683 /* Compute and store final offset */
689 imm10
= (x
>> 12) & 0x3ff;
690 imm11
= (x
>> 1) & 0x7ff;
691 (*(uint16_t *)ptr
) = (uint16_t) ((hi
& 0xf800) |
693 (*(uint16_t *)(ptr
+2)) = (uint16_t) ((lo
& 0xc000) |
694 (j1
<< 13) | blx_bit
| (j2
<< 11) |
699 case R_ARM_MOVW_ABS_NC
:
702 if (type
== R_ARM_MOVT_ABS
)
705 imm4
= (val
>> 12) & 0xf;
706 x
= (imm4
<< 16) | imm12
;
707 if (type
== R_ARM_THM_MOVT_ABS
)
713 case R_ARM_THM_MOVT_ABS
:
714 case R_ARM_THM_MOVW_ABS_NC
:
716 int x
, i
, imm4
, imm3
, imm8
;
717 if (type
== R_ARM_THM_MOVT_ABS
)
720 imm3
= (val
>> 8) & 0x7;
722 imm4
= (val
>> 12) & 0xf;
723 x
= (imm3
<< 28) | (imm8
<< 16) | (i
<< 10) | imm4
;
724 if (type
== R_ARM_THM_MOVT_ABS
)
733 x
= (*(int *)ptr
) & 0x7fffffff;
734 (*(int *)ptr
) &= 0x80000000;
737 if((x
^(x
>>1))&0x40000000)
738 tcc_error("can't relocate value at %x",addr
);
739 (*(int *)ptr
) |= x
& 0x7fffffff;
745 *(int *)ptr
+= val
- addr
;
747 case R_ARM_BASE_PREL
:
748 *(int *)ptr
+= s1
->got
->sh_addr
- addr
;
751 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
754 /* we load the got offset */
755 *(int *)ptr
+= s1
->got_offsets
[sym_index
];
760 /* trade Thumb support for ARMv4 support */
761 if ((0x0ffffff0 & *(int*)ptr
) == 0x012FFF10)
762 *(int*)ptr
^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
765 fprintf(stderr
,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
766 type
, (unsigned)addr
, (unsigned)(uplong
)ptr
, (unsigned)val
);
768 #elif defined(TCC_TARGET_C67)
776 /* put the low 16 bits of the absolute address */
777 // add to what is already there
779 orig
= ((*(int *)(ptr
)) >> 7) & 0xffff;
780 orig
|= (((*(int *)(ptr
+4)) >> 7) & 0xffff) << 16;
782 //patch both at once - assumes always in pairs Low - High
784 *(int *) ptr
= (*(int *) ptr
& (~(0xffff << 7)) ) | (((val
+orig
) & 0xffff) << 7);
785 *(int *)(ptr
+4) = (*(int *)(ptr
+4) & (~(0xffff << 7)) ) | ((((val
+orig
)>>16) & 0xffff) << 7);
791 fprintf(stderr
,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
792 type
, (unsigned)addr
, (unsigned)(uplong
)ptr
, (unsigned)val
);
794 #elif defined(TCC_TARGET_X86_64)
796 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
797 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
798 qrel
->r_addend
= *(long long *)ptr
+ val
;
801 *(long long *)ptr
+= val
;
805 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
806 /* XXX: this logic may depend on TCC's codegen
807 now TCC uses R_X86_64_32 even for a 64bit pointer */
808 qrel
->r_info
= ELFW(R_INFO
)(0, R_X86_64_RELATIVE
);
809 qrel
->r_addend
= *(int *)ptr
+ val
;
816 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
818 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
820 qrel
->r_offset
= rel
->r_offset
;
821 qrel
->r_info
= ELFW(R_INFO
)(esym_index
, R_X86_64_PC32
);
822 qrel
->r_addend
= *(int *)ptr
;
828 case R_X86_64_PLT32
: {
830 diff
= (long long)val
- addr
;
831 if (diff
<= -2147483647 || diff
> 2147483647) {
832 #ifndef TCC_TARGET_PE
833 /* XXX: naive support for over 32bit jump */
834 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
835 val
= (add_jmp_table(s1
, val
- rel
->r_addend
) +
840 if (diff
<= -2147483647 || diff
> 2147483647) {
841 tcc_error("internal error: relocation failed");
847 case R_X86_64_GLOB_DAT
:
848 case R_X86_64_JUMP_SLOT
:
849 /* They don't need addend */
850 *(int *)ptr
= val
- rel
->r_addend
;
852 case R_X86_64_GOTPCREL
:
853 #ifndef TCC_TARGET_PE
854 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
855 val
= add_got_table(s1
, val
- rel
->r_addend
) + rel
->r_addend
;
856 *(int *)ptr
+= val
- addr
;
860 *(int *)ptr
+= (s1
->got
->sh_addr
- addr
+
861 s1
->got_offsets
[sym_index
] - 4);
863 case R_X86_64_GOTTPOFF
:
864 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
867 /* we load the got offset */
868 *(int *)ptr
+= s1
->got_offsets
[sym_index
];
871 #error unsupported processor
875 /* if the relocation is allocated, we change its symbol table */
876 if (sr
->sh_flags
& SHF_ALLOC
)
877 sr
->link
= s1
->dynsym
;
880 /* relocate relocation table in 'sr' */
881 static void relocate_rel(TCCState
*s1
, Section
*sr
)
884 ElfW_Rel
*rel
, *rel_end
;
886 s
= s1
->sections
[sr
->sh_info
];
887 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
888 for(rel
= (ElfW_Rel
*)sr
->data
;
891 rel
->r_offset
+= s
->sh_addr
;
895 /* count the number of dynamic relocations so that we can reserve
897 static int prepare_dynamic_rel(TCCState
*s1
, Section
*sr
)
899 ElfW_Rel
*rel
, *rel_end
;
900 int sym_index
, esym_index
, type
, count
;
903 rel_end
= (ElfW_Rel
*)(sr
->data
+ sr
->data_offset
);
904 for(rel
= (ElfW_Rel
*)sr
->data
; rel
< rel_end
; rel
++) {
905 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
906 type
= ELFW(R_TYPE
)(rel
->r_info
);
908 #if defined(TCC_TARGET_I386)
910 #elif defined(TCC_TARGET_X86_64)
917 #if defined(TCC_TARGET_I386)
919 #elif defined(TCC_TARGET_X86_64)
922 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
931 /* allocate the section */
932 sr
->sh_flags
|= SHF_ALLOC
;
933 sr
->sh_size
= count
* sizeof(ElfW_Rel
);
938 static void put_got_offset(TCCState
*s1
, int index
, unsigned long val
)
943 if (index
>= s1
->nb_got_offsets
) {
944 /* find immediately bigger power of 2 and reallocate array */
948 tab
= tcc_realloc(s1
->got_offsets
, n
* sizeof(unsigned long));
949 s1
->got_offsets
= tab
;
950 memset(s1
->got_offsets
+ s1
->nb_got_offsets
, 0,
951 (n
- s1
->nb_got_offsets
) * sizeof(unsigned long));
952 s1
->nb_got_offsets
= n
;
954 s1
->got_offsets
[index
] = val
;
957 /* XXX: suppress that */
958 static void put32(unsigned char *p
, uint32_t val
)
966 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
967 defined(TCC_TARGET_X86_64)
968 static uint32_t get32(unsigned char *p
)
970 return p
[0] | (p
[1] << 8) | (p
[2] << 16) | (p
[3] << 24);
974 static void build_got(TCCState
*s1
)
978 /* if no got, then create it */
979 s1
->got
= new_section(s1
, ".got", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
980 s1
->got
->sh_entsize
= 4;
981 add_elf_sym(symtab_section
, 0, 4, ELFW(ST_INFO
)(STB_GLOBAL
, STT_OBJECT
),
982 0, s1
->got
->sh_num
, "_GLOBAL_OFFSET_TABLE_");
983 ptr
= section_ptr_add(s1
->got
, 3 * PTR_SIZE
);
985 /* keep space for _DYNAMIC pointer, if present */
987 /* two dummy got entries */
991 /* keep space for _DYNAMIC pointer, if present */
994 /* two dummy got entries */
1002 /* put a got entry corresponding to a symbol in symtab_section. 'size'
1003 and 'info' can be modifed if more precise info comes from the DLL */
1004 static void put_got_entry(TCCState
*s1
,
1005 int reloc_type
, unsigned long size
, int info
,
1011 unsigned long offset
;
1017 /* if a got entry already exists for that symbol, no need to add one */
1018 if (sym_index
< s1
->nb_got_offsets
&&
1019 s1
->got_offsets
[sym_index
] != 0)
1022 put_got_offset(s1
, sym_index
, s1
->got
->data_offset
);
1025 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1026 name
= symtab_section
->link
->data
+ sym
->st_name
;
1027 offset
= sym
->st_value
;
1028 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1030 #ifdef TCC_TARGET_X86_64
1040 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1043 /* if we build a DLL, we add a %ebx offset */
1044 if (s1
->output_type
== TCC_OUTPUT_DLL
)
1050 /* add a PLT entry */
1052 if (plt
->data_offset
== 0) {
1053 /* first plt entry */
1054 p
= section_ptr_add(plt
, 16);
1055 p
[0] = 0xff; /* pushl got + PTR_SIZE */
1056 p
[1] = modrm
+ 0x10;
1057 put32(p
+ 2, PTR_SIZE
);
1058 p
[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1060 put32(p
+ 8, PTR_SIZE
* 2);
1063 p
= section_ptr_add(plt
, 16);
1064 p
[0] = 0xff; /* jmp *(got + x) */
1066 put32(p
+ 2, s1
->got
->data_offset
);
1067 p
[6] = 0x68; /* push $xxx */
1068 put32(p
+ 7, (plt
->data_offset
- 32) >> 1);
1069 p
[11] = 0xe9; /* jmp plt_start */
1070 put32(p
+ 12, -(plt
->data_offset
));
1072 /* the symbol is modified so that it will be relocated to
1074 #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
1075 if (s1
->output_type
== TCC_OUTPUT_EXE
)
1077 offset
= plt
->data_offset
- 16;
1079 #elif defined(TCC_TARGET_ARM)
1080 if (reloc_type
== R_ARM_JUMP_SLOT
) {
1084 /* if we build a DLL, we add a %ebx offset */
1085 if (s1
->output_type
== TCC_OUTPUT_DLL
)
1086 tcc_error("DLLs unimplemented!");
1088 /* add a PLT entry */
1090 if (plt
->data_offset
== 0) {
1091 /* first plt entry */
1092 p
= section_ptr_add(plt
, 16);
1093 put32(p
, 0xe52de004);
1094 put32(p
+ 4, 0xe59fe010);
1095 put32(p
+ 8, 0xe08fe00e);
1096 put32(p
+ 12, 0xe5bef008);
1099 p
= section_ptr_add(plt
, 16);
1100 put32(p
, 0xe59fc004);
1101 put32(p
+4, 0xe08fc00c);
1102 put32(p
+8, 0xe59cf000);
1103 put32(p
+12, s1
->got
->data_offset
);
1105 /* the symbol is modified so that it will be relocated to
1107 if (s1
->output_type
== TCC_OUTPUT_EXE
)
1108 offset
= plt
->data_offset
- 16;
1110 #elif defined(TCC_TARGET_C67)
1111 tcc_error("C67 got not implemented");
1113 #error unsupported CPU
1115 index
= put_elf_sym(s1
->dynsym
, offset
,
1116 size
, info
, 0, sym
->st_shndx
, name
);
1117 /* put a got entry */
1118 put_elf_reloc(s1
->dynsym
, s1
->got
,
1119 s1
->got
->data_offset
,
1122 ptr
= section_ptr_add(s1
->got
, PTR_SIZE
);
1126 /* build GOT and PLT entries */
1127 ST_FUNC
void build_got_entries(TCCState
*s1
)
1130 ElfW_Rel
*rel
, *rel_end
;
1132 int i
, type
, reloc_type
, sym_index
;
1134 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1135 s
= s1
->sections
[i
];
1136 if (s
->sh_type
!= SHT_RELX
)
1138 /* no need to handle got relocations */
1139 if (s
->link
!= symtab_section
)
1141 rel_end
= (ElfW_Rel
*)(s
->data
+ s
->data_offset
);
1142 for(rel
= (ElfW_Rel
*)s
->data
;
1145 type
= ELFW(R_TYPE
)(rel
->r_info
);
1147 #if defined(TCC_TARGET_I386)
1154 if (type
== R_386_GOT32
|| type
== R_386_PLT32
) {
1155 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1156 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1157 /* look at the symbol got offset. If none, then add one */
1158 if (type
== R_386_GOT32
)
1159 reloc_type
= R_386_GLOB_DAT
;
1161 reloc_type
= R_386_JMP_SLOT
;
1162 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1166 #elif defined(TCC_TARGET_ARM)
1167 case R_ARM_GOT_BREL
:
1168 case R_ARM_GOTOFF32
:
1169 case R_ARM_BASE_PREL
:
1173 if (type
== R_ARM_GOT_BREL
|| type
== R_ARM_PLT32
) {
1174 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1175 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1176 /* look at the symbol got offset. If none, then add one */
1177 if (type
== R_ARM_GOT_BREL
)
1178 reloc_type
= R_ARM_GLOB_DAT
;
1180 reloc_type
= R_ARM_JUMP_SLOT
;
1181 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1185 #elif defined(TCC_TARGET_C67)
1192 if (type
== R_C60_GOT32
|| type
== R_C60_PLT32
) {
1193 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1194 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1195 /* look at the symbol got offset. If none, then add one */
1196 if (type
== R_C60_GOT32
)
1197 reloc_type
= R_C60_GLOB_DAT
;
1199 reloc_type
= R_C60_JMP_SLOT
;
1200 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1204 #elif defined(TCC_TARGET_X86_64)
1205 case R_X86_64_GOT32
:
1206 case R_X86_64_GOTTPOFF
:
1207 case R_X86_64_GOTPCREL
:
1208 case R_X86_64_PLT32
:
1211 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
||
1212 type
== R_X86_64_PLT32
) {
1213 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
1214 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1215 /* look at the symbol got offset. If none, then add one */
1216 if (type
== R_X86_64_GOT32
|| type
== R_X86_64_GOTPCREL
)
1217 reloc_type
= R_X86_64_GLOB_DAT
;
1219 reloc_type
= R_X86_64_JUMP_SLOT
;
1220 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
1225 #error unsupported CPU
1234 ST_FUNC Section
*new_symtab(TCCState
*s1
,
1235 const char *symtab_name
, int sh_type
, int sh_flags
,
1236 const char *strtab_name
,
1237 const char *hash_name
, int hash_sh_flags
)
1239 Section
*symtab
, *strtab
, *hash
;
1240 int *ptr
, nb_buckets
;
1242 symtab
= new_section(s1
, symtab_name
, sh_type
, sh_flags
);
1243 symtab
->sh_entsize
= sizeof(ElfW(Sym
));
1244 strtab
= new_section(s1
, strtab_name
, SHT_STRTAB
, sh_flags
);
1245 put_elf_str(strtab
, "");
1246 symtab
->link
= strtab
;
1247 put_elf_sym(symtab
, 0, 0, 0, 0, 0, NULL
);
1251 hash
= new_section(s1
, hash_name
, SHT_HASH
, hash_sh_flags
);
1252 hash
->sh_entsize
= sizeof(int);
1253 symtab
->hash
= hash
;
1254 hash
->link
= symtab
;
1256 ptr
= section_ptr_add(hash
, (2 + nb_buckets
+ 1) * sizeof(int));
1257 ptr
[0] = nb_buckets
;
1259 memset(ptr
+ 2, 0, (nb_buckets
+ 1) * sizeof(int));
1263 /* put dynamic tag */
1264 static void put_dt(Section
*dynamic
, int dt
, uplong val
)
1267 dyn
= section_ptr_add(dynamic
, sizeof(ElfW(Dyn
)));
1269 dyn
->d_un
.d_val
= val
;
1272 static void add_init_array_defines(TCCState
*s1
, const char *section_name
)
1276 char sym_start
[1024];
1279 snprintf(sym_start
, sizeof(sym_start
), "__%s_start", section_name
+ 1);
1280 snprintf(sym_end
, sizeof(sym_end
), "__%s_end", section_name
+ 1);
1282 s
= find_section(s1
, section_name
);
1287 end_offset
= s
->data_offset
;
1290 add_elf_sym(symtab_section
,
1292 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1293 s
->sh_num
, sym_start
);
1294 add_elf_sym(symtab_section
,
1296 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1297 s
->sh_num
, sym_end
);
1300 static int tcc_add_support(TCCState
*s1
, const char *filename
)
1303 snprintf(buf
, sizeof(buf
), "%s/%s", s1
->tcc_lib_path
, filename
);
1304 return tcc_add_file(s1
, buf
);
1307 ST_FUNC
void tcc_add_bcheck(TCCState
*s1
)
1309 #ifdef CONFIG_TCC_BCHECK
1311 Section
*init_section
;
1312 unsigned char *pinit
;
1315 if (0 == s1
->do_bounds_check
)
1318 /* XXX: add an object file to do that */
1319 ptr
= section_ptr_add(bounds_section
, sizeof(unsigned long));
1321 add_elf_sym(symtab_section
, 0, 0,
1322 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1323 bounds_section
->sh_num
, "__bounds_start");
1324 /* add bound check code */
1325 #ifndef TCC_TARGET_PE
1326 tcc_add_support(s1
, "bcheck.o");
1328 #ifdef TCC_TARGET_I386
1329 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
) {
1330 /* add 'call __bound_init()' in .init section */
1331 init_section
= find_section(s1
, ".init");
1332 pinit
= section_ptr_add(init_section
, 5);
1334 put32(pinit
+ 1, -4);
1335 sym_index
= find_elf_sym(symtab_section
, "__bound_init");
1336 put_elf_reloc(symtab_section
, init_section
,
1337 init_section
->data_offset
- 4, R_386_PC32
, sym_index
);
1343 /* add tcc runtime libraries */
1344 ST_FUNC
void tcc_add_runtime(TCCState
*s1
)
1349 if (!s1
->nostdlib
) {
1350 tcc_add_library(s1
, "c");
1351 #ifdef CONFIG_USE_LIBGCC
1352 tcc_add_file(s1
, TCC_LIBGCC
);
1353 #elif !defined WITHOUT_LIBTCC
1354 tcc_add_support(s1
, "libtcc1.a");
1356 /* add crt end if not memory output */
1357 if (s1
->output_type
!= TCC_OUTPUT_MEMORY
)
1358 tcc_add_crt(s1
, "crtn.o");
1362 /* add various standard linker symbols (must be done after the
1363 sections are filled (for example after allocating common
1365 ST_FUNC
void tcc_add_linker_symbols(TCCState
*s1
)
1371 add_elf_sym(symtab_section
,
1372 text_section
->data_offset
, 0,
1373 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1374 text_section
->sh_num
, "_etext");
1375 add_elf_sym(symtab_section
,
1376 data_section
->data_offset
, 0,
1377 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1378 data_section
->sh_num
, "_edata");
1379 add_elf_sym(symtab_section
,
1380 bss_section
->data_offset
, 0,
1381 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1382 bss_section
->sh_num
, "_end");
1383 /* horrible new standard ldscript defines */
1384 add_init_array_defines(s1
, ".preinit_array");
1385 add_init_array_defines(s1
, ".init_array");
1386 add_init_array_defines(s1
, ".fini_array");
1388 /* add start and stop symbols for sections whose name can be
1390 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1391 s
= s1
->sections
[i
];
1392 if (s
->sh_type
== SHT_PROGBITS
&&
1393 (s
->sh_flags
& SHF_ALLOC
)) {
1397 /* check if section name can be expressed in C */
1403 if (!isid(ch
) && !isnum(ch
))
1407 snprintf(buf
, sizeof(buf
), "__start_%s", s
->name
);
1408 add_elf_sym(symtab_section
,
1410 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1412 snprintf(buf
, sizeof(buf
), "__stop_%s", s
->name
);
1413 add_elf_sym(symtab_section
,
1415 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
1422 static void tcc_output_binary(TCCState
*s1
, FILE *f
,
1423 const int *section_order
)
1426 int i
, offset
, size
;
1429 for(i
=1;i
<s1
->nb_sections
;i
++) {
1430 s
= s1
->sections
[section_order
[i
]];
1431 if (s
->sh_type
!= SHT_NOBITS
&&
1432 (s
->sh_flags
& SHF_ALLOC
)) {
1433 while (offset
< s
->sh_offset
) {
1438 fwrite(s
->data
, 1, size
, f
);
1444 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1446 #define EXTRA_RELITEMS 14
1448 /* move the relocation value from .dynsym to .got */
1449 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1451 uint32_t *gotd
= (void *)s1
->got
->data
;
1452 ElfW(Sym
) *sym
, *sym_end
;
1454 gotd
+= 3; // dummy entries in .got
1455 /* relocate symbols in .dynsym */
1456 sym_end
= (ElfW(Sym
) *)(s
->data
+ s
->data_offset
);
1457 for (sym
= (ElfW(Sym
) *)s
->data
+ 1; sym
< sym_end
; sym
++) {
1458 if (sym
->st_shndx
== SHN_UNDEF
) {
1459 *gotd
++ = sym
->st_value
+ 6; // XXX 6 is magic ?
1466 #define EXTRA_RELITEMS 9
1468 /* zero plt offsets of weak symbols in .dynsym */
1469 void patch_dynsym_undef(TCCState
*s1
, Section
*s
)
1471 ElfW(Sym
) *sym
, *sym_end
;
1473 sym_end
= (ElfW(Sym
) *)(s
->data
+ s
->data_offset
);
1474 for (sym
= (ElfW(Sym
) *)s
->data
+ 1; sym
< sym_end
; sym
++)
1475 if (sym
->st_shndx
== SHN_UNDEF
&& ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
)
1480 ST_FUNC
void fill_got_entry(TCCState
*s1
, ElfW_Rel
*rel
)
1482 int sym_index
= ELFW(R_SYM
) (rel
->r_info
);
1483 ElfW(Sym
) *sym
= &((ElfW(Sym
) *) symtab_section
->data
)[sym_index
];
1484 unsigned long offset
;
1486 if (sym_index
>= s1
->nb_got_offsets
)
1488 offset
= s1
->got_offsets
[sym_index
];
1489 section_reserve(s1
->got
, offset
+ PTR_SIZE
);
1490 #ifdef TCC_TARGET_X86_64
1491 /* only works for x86-64 */
1492 put32(s1
->got
->data
+ offset
+ 4, sym
->st_value
>> 32);
1494 put32(s1
->got
->data
+ offset
, sym
->st_value
& 0xffffffff);
1497 ST_FUNC
void fill_got(TCCState
*s1
)
1500 ElfW_Rel
*rel
, *rel_end
;
1503 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1504 s
= s1
->sections
[i
];
1505 if (s
->sh_type
!= SHT_RELX
)
1507 /* no need to handle got relocations */
1508 if (s
->link
!= symtab_section
)
1510 rel_end
= (ElfW_Rel
*) (s
->data
+ s
->data_offset
);
1511 for(rel
= (ElfW_Rel
*) s
->data
; rel
< rel_end
; rel
++) {
1512 switch (ELFW(R_TYPE
) (rel
->r_info
)) {
1513 case R_X86_64_GOT32
:
1514 case R_X86_64_GOTPCREL
:
1515 case R_X86_64_PLT32
:
1516 fill_got_entry(s1
, rel
);
1524 /* output an ELF file */
1525 /* XXX: suppress unneeded sections */
1526 static int elf_output_file(TCCState
*s1
, const char *filename
)
1532 int shnum
, i
, phnum
, file_offset
, offset
, size
, j
, sh_order_index
, k
;
1535 Section
*strsec
, *s
;
1536 ElfW(Shdr
) shdr
, *sh
;
1537 ElfW(Phdr
) *phdr
, *ph
;
1538 Section
*interp
, *dynamic
, *dynstr
;
1539 unsigned long saved_dynamic_data_offset
;
1541 int type
, file_type
;
1542 uplong rel_addr
, rel_size
;
1543 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1544 uplong bss_addr
, bss_size
;
1547 file_type
= s1
->output_type
;
1550 if (file_type
!= TCC_OUTPUT_OBJ
) {
1551 tcc_add_runtime(s1
);
1555 section_order
= NULL
;
1558 dynstr
= NULL
; /* avoid warning */
1559 saved_dynamic_data_offset
= 0; /* avoid warning */
1561 if (file_type
!= TCC_OUTPUT_OBJ
) {
1562 relocate_common_syms();
1564 tcc_add_linker_symbols(s1
);
1566 if (!s1
->static_link
) {
1568 int sym_index
, index
;
1569 ElfW(Sym
) *esym
, *sym_end
;
1571 if (file_type
== TCC_OUTPUT_EXE
) {
1573 /* allow override the dynamic loader */
1574 const char *elfint
= getenv("LD_SO");
1576 elfint
= CONFIG_TCC_ELFINTERP
;
1577 /* add interpreter section only if executable */
1578 interp
= new_section(s1
, ".interp", SHT_PROGBITS
, SHF_ALLOC
);
1579 interp
->sh_addralign
= 1;
1580 ptr
= section_ptr_add(interp
, 1+strlen(elfint
));
1581 strcpy(ptr
, elfint
);
1584 /* add dynamic symbol table */
1585 s1
->dynsym
= new_symtab(s1
, ".dynsym", SHT_DYNSYM
, SHF_ALLOC
,
1587 ".hash", SHF_ALLOC
);
1588 dynstr
= s1
->dynsym
->link
;
1590 /* add dynamic section */
1591 dynamic
= new_section(s1
, ".dynamic", SHT_DYNAMIC
,
1592 SHF_ALLOC
| SHF_WRITE
);
1593 dynamic
->link
= dynstr
;
1594 dynamic
->sh_entsize
= sizeof(ElfW(Dyn
));
1597 s1
->plt
= new_section(s1
, ".plt", SHT_PROGBITS
,
1598 SHF_ALLOC
| SHF_EXECINSTR
);
1599 s1
->plt
->sh_entsize
= 4;
1603 /* scan for undefined symbols and see if they are in the
1604 dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1605 is found, then we add it in the PLT. If a symbol
1606 STT_OBJECT is found, we add it in the .bss section with
1607 a suitable relocation */
1608 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+
1609 symtab_section
->data_offset
);
1610 if (file_type
== TCC_OUTPUT_EXE
) {
1611 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
1614 if (sym
->st_shndx
== SHN_UNDEF
) {
1615 name
= symtab_section
->link
->data
+ sym
->st_name
;
1616 sym_index
= find_elf_sym(s1
->dynsymtab_section
, name
);
1618 esym
= &((ElfW(Sym
) *)s1
->dynsymtab_section
->data
)[sym_index
];
1619 type
= ELFW(ST_TYPE
)(esym
->st_info
);
1620 if ((type
== STT_FUNC
) || (type
== STT_GNU_IFUNC
)) {
1621 put_got_entry(s1
, R_JMP_SLOT
, esym
->st_size
,
1622 ELFW(ST_INFO
)(STB_GLOBAL
,type
),
1623 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1624 } else if (type
== STT_OBJECT
) {
1625 unsigned long offset
;
1626 ElfW(Sym
) *dynsym
, *dynsym_end
;
1627 offset
= bss_section
->data_offset
;
1628 /* XXX: which alignment ? */
1629 offset
= (offset
+ 16 - 1) & -16;
1630 index
= put_elf_sym(s1
->dynsym
, offset
, esym
->st_size
,
1632 bss_section
->sh_num
, name
);
1633 // Ensure R_COPY works for weak symbol aliases
1634 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1635 dynsym_end
= (ElfW(Sym
) *)
1636 (s1
->dynsymtab_section
->data
+
1637 s1
->dynsymtab_section
->data_offset
);
1638 for(dynsym
= (ElfW(Sym
) *)s1
->dynsymtab_section
->data
+ 1;
1639 dynsym
< dynsym_end
; dynsym
++) {
1640 if ((dynsym
->st_value
== esym
->st_value
)
1641 && (ELFW(ST_BIND
)(dynsym
->st_info
) == STB_GLOBAL
)) {
1643 dynname
= s1
->dynsymtab_section
->link
->data
1645 put_elf_sym(s1
->dynsym
, offset
,
1648 bss_section
->sh_num
,
1654 put_elf_reloc(s1
->dynsym
, bss_section
,
1655 offset
, R_COPY
, index
);
1656 offset
+= esym
->st_size
;
1657 bss_section
->data_offset
= offset
;
1660 /* STB_WEAK undefined symbols are accepted */
1661 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1663 if (ELFW(ST_BIND
)(sym
->st_info
) == STB_WEAK
||
1664 !strcmp(name
, "_fp_hw")) {
1666 tcc_error_noabort("undefined symbol '%s'", name
);
1669 } else if (s1
->rdynamic
&&
1670 ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1671 /* if -rdynamic option, then export all non
1673 name
= symtab_section
->link
->data
+ sym
->st_name
;
1674 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1676 sym
->st_shndx
, name
);
1683 /* now look at unresolved dynamic symbols and export
1684 corresponding symbol */
1685 sym_end
= (ElfW(Sym
) *)(s1
->dynsymtab_section
->data
+
1686 s1
->dynsymtab_section
->data_offset
);
1687 for(esym
= (ElfW(Sym
) *)s1
->dynsymtab_section
->data
+ 1;
1690 if (esym
->st_shndx
== SHN_UNDEF
) {
1691 name
= s1
->dynsymtab_section
->link
->data
+ esym
->st_name
;
1692 sym_index
= find_elf_sym(symtab_section
, name
);
1694 /* XXX: avoid adding a symbol if already
1695 present because of -rdynamic ? */
1696 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
1697 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1699 sym
->st_shndx
, name
);
1701 if (ELFW(ST_BIND
)(esym
->st_info
) == STB_WEAK
) {
1702 /* weak symbols can stay undefined */
1704 tcc_warning("undefined dynamic symbol '%s'", name
);
1711 /* shared library case : we simply export all the global symbols */
1712 nb_syms
= symtab_section
->data_offset
/ sizeof(ElfW(Sym
));
1713 s1
->symtab_to_dynsym
= tcc_mallocz(sizeof(int) * nb_syms
);
1714 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
1717 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
1718 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1719 if ((ELFW(ST_TYPE
)(sym
->st_info
) == STT_FUNC
||
1720 ELFW(ST_TYPE
)(sym
->st_info
) == STT_GNU_IFUNC
)
1721 && sym
->st_shndx
== SHN_UNDEF
) {
1722 put_got_entry(s1
, R_JMP_SLOT
, sym
->st_size
,
1724 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1726 else if (ELFW(ST_TYPE
)(sym
->st_info
) == STT_OBJECT
) {
1727 put_got_entry(s1
, R_X86_64_GLOB_DAT
, sym
->st_size
,
1729 sym
- (ElfW(Sym
) *)symtab_section
->data
);
1734 name
= symtab_section
->link
->data
+ sym
->st_name
;
1735 index
= put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
1737 sym
->st_shndx
, name
);
1738 s1
->symtab_to_dynsym
[sym
-
1739 (ElfW(Sym
) *)symtab_section
->data
] =
1746 build_got_entries(s1
);
1748 /* add a list of needed dlls */
1749 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
1750 DLLReference
*dllref
= s1
->loaded_dlls
[i
];
1751 if (dllref
->level
== 0)
1752 put_dt(dynamic
, DT_NEEDED
, put_elf_str(dynstr
, dllref
->name
));
1756 put_dt(dynamic
, DT_RPATH
, put_elf_str(dynstr
, s1
->rpath
));
1758 /* XXX: currently, since we do not handle PIC code, we
1759 must relocate the readonly segments */
1760 if (file_type
== TCC_OUTPUT_DLL
) {
1762 put_dt(dynamic
, DT_SONAME
, put_elf_str(dynstr
, s1
->soname
));
1763 put_dt(dynamic
, DT_TEXTREL
, 0);
1767 put_dt(dynamic
, DT_SYMBOLIC
, 0);
1769 /* add necessary space for other entries */
1770 saved_dynamic_data_offset
= dynamic
->data_offset
;
1771 dynamic
->data_offset
+= sizeof(ElfW(Dyn
)) * EXTRA_RELITEMS
;
1773 /* still need to build got entries in case of static link */
1774 build_got_entries(s1
);
1778 memset(&ehdr
, 0, sizeof(ehdr
));
1780 /* we add a section for symbols */
1781 strsec
= new_section(s1
, ".shstrtab", SHT_STRTAB
, 0);
1782 put_elf_str(strsec
, "");
1784 /* compute number of sections */
1785 shnum
= s1
->nb_sections
;
1787 /* this array is used to reorder sections in the output file */
1788 section_order
= tcc_malloc(sizeof(int) * shnum
);
1789 section_order
[0] = 0;
1792 /* compute number of program headers */
1795 case TCC_OUTPUT_OBJ
:
1798 case TCC_OUTPUT_EXE
:
1799 if (!s1
->static_link
)
1800 phnum
= 4 + HAVE_PHDR
;
1804 case TCC_OUTPUT_DLL
:
1809 /* allocate strings for section names and decide if an unallocated
1810 section should be output */
1811 /* NOTE: the strsec section comes last, so its size is also
1813 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1814 s
= s1
->sections
[i
];
1815 s
->sh_name
= put_elf_str(strsec
, s
->name
);
1817 printf("section: f=%08x t=%08x i=%08x %s %s\n",
1822 s
->reloc
? s
->reloc
->name
: "n"
1825 /* when generating a DLL, we include relocations but we may
1827 if (file_type
== TCC_OUTPUT_DLL
&&
1828 s
->sh_type
== SHT_RELX
&&
1829 !(s
->sh_flags
& SHF_ALLOC
)) {
1830 /* //gr: avoid bogus relocs for empty (debug) sections */
1831 if (s1
->sections
[s
->sh_info
]->sh_flags
& SHF_ALLOC
)
1832 prepare_dynamic_rel(s1
, s
);
1833 else if (s1
->do_debug
)
1834 s
->sh_size
= s
->data_offset
;
1835 } else if (s1
->do_debug
||
1836 file_type
== TCC_OUTPUT_OBJ
||
1837 (s
->sh_flags
& SHF_ALLOC
) ||
1838 i
== (s1
->nb_sections
- 1)) {
1839 /* we output all sections if debug or object file */
1840 s
->sh_size
= s
->data_offset
;
1844 /* allocate program segment headers */
1845 phdr
= tcc_mallocz(phnum
* sizeof(ElfW(Phdr
)));
1847 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1848 file_offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
1853 /* compute section to program header mapping */
1854 if (s1
->has_text_addr
) {
1855 int a_offset
, p_offset
;
1856 addr
= s1
->text_addr
;
1857 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1859 a_offset
= (int) (addr
& (s1
->section_align
- 1));
1860 p_offset
= file_offset
& (s1
->section_align
- 1);
1861 if (a_offset
< p_offset
)
1862 a_offset
+= s1
->section_align
;
1863 file_offset
+= (a_offset
- p_offset
);
1865 if (file_type
== TCC_OUTPUT_DLL
)
1868 addr
= ELF_START_ADDR
;
1869 /* compute address after headers */
1870 addr
+= (file_offset
& (s1
->section_align
- 1));
1873 /* dynamic relocation table information, for .dynamic section */
1877 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1878 bss_addr
= bss_size
= 0;
1880 /* leave one program header for the program interpreter */
1883 ph
+= 1 + HAVE_PHDR
;
1885 for(j
= 0; j
< 2; j
++) {
1886 ph
->p_type
= PT_LOAD
;
1888 ph
->p_flags
= PF_R
| PF_X
;
1890 ph
->p_flags
= PF_R
| PF_W
;
1891 ph
->p_align
= s1
->section_align
;
1893 /* we do the following ordering: interp, symbol tables,
1894 relocations, progbits, nobits */
1895 /* XXX: do faster and simpler sorting */
1896 for(k
= 0; k
< 5; k
++) {
1897 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1898 s
= s1
->sections
[i
];
1899 /* compute if section should be included */
1901 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1905 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
1906 (SHF_ALLOC
| SHF_WRITE
))
1912 } else if (s
->sh_type
== SHT_DYNSYM
||
1913 s
->sh_type
== SHT_STRTAB
||
1914 s
->sh_type
== SHT_HASH
) {
1917 } else if (s
->sh_type
== SHT_RELX
) {
1920 } else if (s
->sh_type
== SHT_NOBITS
) {
1927 section_order
[sh_order_index
++] = i
;
1929 /* section matches: we align it and add its size */
1931 addr
= (addr
+ s
->sh_addralign
- 1) &
1932 ~(s
->sh_addralign
- 1);
1933 file_offset
+= (int) ( addr
- tmp
);
1934 s
->sh_offset
= file_offset
;
1937 /* update program header infos */
1938 if (ph
->p_offset
== 0) {
1939 ph
->p_offset
= file_offset
;
1941 ph
->p_paddr
= ph
->p_vaddr
;
1943 /* update dynamic relocation infos */
1944 if (s
->sh_type
== SHT_RELX
) {
1945 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1946 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.got")) { // rel_size == 0) {
1948 rel_size
+= s
->sh_size
; // XXX only first rel.
1950 if (!strcmp(strsec
->data
+ s
->sh_name
, ".rel.bss")) { // rel_size == 0) {
1952 bss_size
= s
->sh_size
; // XXX only first rel.
1957 rel_size
+= s
->sh_size
;
1961 if (s
->sh_type
!= SHT_NOBITS
)
1962 file_offset
+= s
->sh_size
;
1965 ph
->p_filesz
= file_offset
- ph
->p_offset
;
1966 ph
->p_memsz
= addr
- ph
->p_vaddr
;
1969 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
1970 /* if in the middle of a page, we duplicate the page in
1971 memory so that one copy is RX and the other is RW */
1972 if ((addr
& (s1
->section_align
- 1)) != 0)
1973 addr
+= s1
->section_align
;
1975 addr
= (addr
+ s1
->section_align
- 1) & ~(s1
->section_align
- 1);
1976 file_offset
= (file_offset
+ s1
->section_align
- 1) &
1977 ~(s1
->section_align
- 1);
1982 /* if interpreter, then add corresponing program header */
1986 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1988 int len
= phnum
* sizeof(ElfW(Phdr
));
1990 ph
->p_type
= PT_PHDR
;
1991 ph
->p_offset
= sizeof(ElfW(Ehdr
));
1992 ph
->p_vaddr
= interp
->sh_addr
- len
;
1993 ph
->p_paddr
= ph
->p_vaddr
;
1994 ph
->p_filesz
= ph
->p_memsz
= len
;
1995 ph
->p_flags
= PF_R
| PF_X
;
1996 ph
->p_align
= 4; // interp->sh_addralign;
2001 ph
->p_type
= PT_INTERP
;
2002 ph
->p_offset
= interp
->sh_offset
;
2003 ph
->p_vaddr
= interp
->sh_addr
;
2004 ph
->p_paddr
= ph
->p_vaddr
;
2005 ph
->p_filesz
= interp
->sh_size
;
2006 ph
->p_memsz
= interp
->sh_size
;
2008 ph
->p_align
= interp
->sh_addralign
;
2011 /* if dynamic section, then add corresponing program header */
2015 ph
= &phdr
[phnum
- 1];
2017 ph
->p_type
= PT_DYNAMIC
;
2018 ph
->p_offset
= dynamic
->sh_offset
;
2019 ph
->p_vaddr
= dynamic
->sh_addr
;
2020 ph
->p_paddr
= ph
->p_vaddr
;
2021 ph
->p_filesz
= dynamic
->sh_size
;
2022 ph
->p_memsz
= dynamic
->sh_size
;
2023 ph
->p_flags
= PF_R
| PF_W
;
2024 ph
->p_align
= dynamic
->sh_addralign
;
2026 /* put GOT dynamic section address */
2027 put32(s1
->got
->data
, dynamic
->sh_addr
);
2029 /* relocate the PLT */
2030 if (file_type
== TCC_OUTPUT_EXE
2031 #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2032 || file_type
== TCC_OUTPUT_DLL
2038 p_end
= p
+ s1
->plt
->data_offset
;
2040 #if defined(TCC_TARGET_I386)
2041 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
2042 put32(p
+ 8, get32(p
+ 8) + s1
->got
->sh_addr
);
2045 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
2048 #elif defined(TCC_TARGET_X86_64)
2049 int x
= s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 6;
2050 put32(p
+ 2, get32(p
+ 2) + x
);
2051 put32(p
+ 8, get32(p
+ 8) + x
- 6);
2054 put32(p
+ 2, get32(p
+ 2) + x
+ s1
->plt
->data
- p
);
2057 #elif defined(TCC_TARGET_ARM)
2059 x
=s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 12;
2062 put32(p
+ 12, x
+ get32(p
+ 12) + s1
->plt
->data
- p
);
2065 #elif defined(TCC_TARGET_C67)
2068 #error unsupported CPU
2073 /* relocate symbols in .dynsym */
2074 sym_end
= (ElfW(Sym
) *)(s1
->dynsym
->data
+ s1
->dynsym
->data_offset
);
2075 for(sym
= (ElfW(Sym
) *)s1
->dynsym
->data
+ 1;
2078 if (sym
->st_shndx
== SHN_UNDEF
) {
2079 /* relocate to the PLT if the symbol corresponds
2082 sym
->st_value
+= s1
->plt
->sh_addr
;
2083 } else if (sym
->st_shndx
< SHN_LORESERVE
) {
2084 /* do symbol relocation */
2085 sym
->st_value
+= s1
->sections
[sym
->st_shndx
]->sh_addr
;
2089 /* put dynamic section entries */
2090 dynamic
->data_offset
= saved_dynamic_data_offset
;
2091 put_dt(dynamic
, DT_HASH
, s1
->dynsym
->hash
->sh_addr
);
2092 put_dt(dynamic
, DT_STRTAB
, dynstr
->sh_addr
);
2093 put_dt(dynamic
, DT_SYMTAB
, s1
->dynsym
->sh_addr
);
2094 put_dt(dynamic
, DT_STRSZ
, dynstr
->data_offset
);
2095 put_dt(dynamic
, DT_SYMENT
, sizeof(ElfW(Sym
)));
2096 #ifdef TCC_TARGET_X86_64
2097 put_dt(dynamic
, DT_RELA
, rel_addr
);
2098 put_dt(dynamic
, DT_RELASZ
, rel_size
);
2099 put_dt(dynamic
, DT_RELAENT
, sizeof(ElfW_Rel
));
2101 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2102 put_dt(dynamic
, DT_PLTGOT
, s1
->got
->sh_addr
);
2103 put_dt(dynamic
, DT_PLTRELSZ
, rel_size
);
2104 put_dt(dynamic
, DT_JMPREL
, rel_addr
);
2105 put_dt(dynamic
, DT_PLTREL
, DT_REL
);
2106 put_dt(dynamic
, DT_REL
, bss_addr
);
2107 put_dt(dynamic
, DT_RELSZ
, bss_size
);
2109 put_dt(dynamic
, DT_REL
, rel_addr
);
2110 put_dt(dynamic
, DT_RELSZ
, rel_size
);
2111 put_dt(dynamic
, DT_RELENT
, sizeof(ElfW_Rel
));
2115 put_dt(dynamic
, DT_DEBUG
, 0);
2116 put_dt(dynamic
, DT_NULL
, 0);
2119 ehdr
.e_phentsize
= sizeof(ElfW(Phdr
));
2120 ehdr
.e_phnum
= phnum
;
2121 ehdr
.e_phoff
= sizeof(ElfW(Ehdr
));
2124 /* all other sections come after */
2125 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2126 s
= s1
->sections
[i
];
2127 if (phnum
> 0 && (s
->sh_flags
& SHF_ALLOC
))
2129 section_order
[sh_order_index
++] = i
;
2131 file_offset
= (file_offset
+ s
->sh_addralign
- 1) &
2132 ~(s
->sh_addralign
- 1);
2133 s
->sh_offset
= file_offset
;
2134 if (s
->sh_type
!= SHT_NOBITS
)
2135 file_offset
+= s
->sh_size
;
2138 /* if building executable or DLL, then relocate each section
2139 except the GOT which is already relocated */
2140 if (file_type
!= TCC_OUTPUT_OBJ
) {
2141 relocate_syms(s1
, 0);
2143 if (s1
->nb_errors
!= 0) {
2149 /* relocate sections */
2150 /* XXX: ignore sections with allocated relocations ? */
2151 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2152 s
= s1
->sections
[i
];
2153 if (s
->reloc
&& s
!= s1
->got
&& (s
->sh_flags
& SHF_ALLOC
)) //gr
2154 relocate_section(s1
, s
);
2157 /* relocate relocation entries if the relocation tables are
2158 allocated in the executable */
2159 for(i
= 1; i
< s1
->nb_sections
; i
++) {
2160 s
= s1
->sections
[i
];
2161 if ((s
->sh_flags
& SHF_ALLOC
) &&
2162 s
->sh_type
== SHT_RELX
) {
2163 relocate_rel(s1
, s
);
2167 /* get entry point address */
2168 if (file_type
== TCC_OUTPUT_EXE
)
2169 ehdr
.e_entry
= (uplong
)tcc_get_symbol_err(s1
, "_start");
2171 ehdr
.e_entry
= text_section
->sh_addr
; /* XXX: is it correct ? */
2173 if (file_type
== TCC_OUTPUT_EXE
&& s1
->static_link
)
2176 /* write elf file */
2177 if (file_type
== TCC_OUTPUT_OBJ
)
2182 fd
= open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
, mode
);
2184 tcc_error_noabort("could not write '%s'", filename
);
2187 f
= fdopen(fd
, "wb");
2189 printf("<- %s\n", filename
);
2191 #ifdef TCC_TARGET_COFF
2192 if (s1
->output_format
== TCC_OUTPUT_FORMAT_COFF
) {
2193 tcc_output_coff(s1
, f
);
2196 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
2197 sort_syms(s1
, symtab_section
);
2200 file_offset
= (file_offset
+ 3) & -4;
2203 ehdr
.e_ident
[0] = ELFMAG0
;
2204 ehdr
.e_ident
[1] = ELFMAG1
;
2205 ehdr
.e_ident
[2] = ELFMAG2
;
2206 ehdr
.e_ident
[3] = ELFMAG3
;
2207 ehdr
.e_ident
[4] = ELFCLASSW
;
2208 ehdr
.e_ident
[5] = ELFDATA2LSB
;
2209 ehdr
.e_ident
[6] = EV_CURRENT
;
2210 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2211 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_FREEBSD
;
2213 #ifdef TCC_TARGET_ARM
2215 ehdr
.e_ident
[EI_OSABI
] = 0;
2216 ehdr
.e_flags
= 4 << 24;
2218 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_ARM
;
2223 case TCC_OUTPUT_EXE
:
2224 ehdr
.e_type
= ET_EXEC
;
2226 case TCC_OUTPUT_DLL
:
2227 ehdr
.e_type
= ET_DYN
;
2229 case TCC_OUTPUT_OBJ
:
2230 ehdr
.e_type
= ET_REL
;
2233 ehdr
.e_machine
= EM_TCC_TARGET
;
2234 ehdr
.e_version
= EV_CURRENT
;
2235 ehdr
.e_shoff
= file_offset
;
2236 ehdr
.e_ehsize
= sizeof(ElfW(Ehdr
));
2237 ehdr
.e_shentsize
= sizeof(ElfW(Shdr
));
2238 ehdr
.e_shnum
= shnum
;
2239 ehdr
.e_shstrndx
= shnum
- 1;
2241 fwrite(&ehdr
, 1, sizeof(ElfW(Ehdr
)), f
);
2242 fwrite(phdr
, 1, phnum
* sizeof(ElfW(Phdr
)), f
);
2243 offset
= sizeof(ElfW(Ehdr
)) + phnum
* sizeof(ElfW(Phdr
));
2245 for(i
=1;i
<s1
->nb_sections
;i
++) {
2246 s
= s1
->sections
[section_order
[i
]];
2247 if (s
->sh_type
!= SHT_NOBITS
) {
2248 if (s
->sh_type
== SHT_DYNSYM
)
2249 patch_dynsym_undef(s1
, s
);
2250 while (offset
< s
->sh_offset
) {
2255 fwrite(s
->data
, 1, size
, f
);
2260 /* output section headers */
2261 while (offset
< ehdr
.e_shoff
) {
2266 for(i
=0;i
<s1
->nb_sections
;i
++) {
2268 memset(sh
, 0, sizeof(ElfW(Shdr
)));
2269 s
= s1
->sections
[i
];
2271 sh
->sh_name
= s
->sh_name
;
2272 sh
->sh_type
= s
->sh_type
;
2273 sh
->sh_flags
= s
->sh_flags
;
2274 sh
->sh_entsize
= s
->sh_entsize
;
2275 sh
->sh_info
= s
->sh_info
;
2277 sh
->sh_link
= s
->link
->sh_num
;
2278 sh
->sh_addralign
= s
->sh_addralign
;
2279 sh
->sh_addr
= s
->sh_addr
;
2280 sh
->sh_offset
= s
->sh_offset
;
2281 sh
->sh_size
= s
->sh_size
;
2283 fwrite(sh
, 1, sizeof(ElfW(Shdr
)), f
);
2286 tcc_output_binary(s1
, f
, section_order
);
2292 tcc_free(s1
->symtab_to_dynsym
);
2293 tcc_free(section_order
);
2295 tcc_free(s1
->got_offsets
);
2299 LIBTCCAPI
int tcc_output_file(TCCState
*s
, const char *filename
)
2302 #ifdef TCC_TARGET_PE
2303 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
2304 ret
= pe_output_file(s
, filename
);
2308 ret
= elf_output_file(s
, filename
);
2313 static void *load_data(int fd
, unsigned long file_offset
, unsigned long size
)
2317 data
= tcc_malloc(size
);
2318 lseek(fd
, file_offset
, SEEK_SET
);
2319 read(fd
, data
, size
);
2323 typedef struct SectionMergeInfo
{
2324 Section
*s
; /* corresponding existing section */
2325 unsigned long offset
; /* offset of the new section in the existing section */
2326 uint8_t new_section
; /* true if section 's' was added */
2327 uint8_t link_once
; /* true if link once section */
2330 /* load an object file and merge it with current files */
2331 /* XXX: handle correctly stab (debug) info */
2332 ST_FUNC
int tcc_load_object_file(TCCState
*s1
,
2333 int fd
, unsigned long file_offset
)
2336 ElfW(Shdr
) *shdr
, *sh
;
2337 int size
, i
, j
, offset
, offseti
, nb_syms
, sym_index
, ret
;
2338 unsigned char *strsec
, *strtab
;
2339 int *old_to_new_syms
;
2340 char *sh_name
, *name
;
2341 SectionMergeInfo
*sm_table
, *sm
;
2342 ElfW(Sym
) *sym
, *symtab
;
2343 ElfW_Rel
*rel
, *rel_end
;
2349 stab_index
= stabstr_index
= 0;
2351 if (read(fd
, &ehdr
, sizeof(ehdr
)) != sizeof(ehdr
))
2353 if (ehdr
.e_ident
[0] != ELFMAG0
||
2354 ehdr
.e_ident
[1] != ELFMAG1
||
2355 ehdr
.e_ident
[2] != ELFMAG2
||
2356 ehdr
.e_ident
[3] != ELFMAG3
)
2358 /* test if object file */
2359 if (ehdr
.e_type
!= ET_REL
)
2361 /* test CPU specific stuff */
2362 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2363 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2365 tcc_error_noabort("invalid object file");
2369 shdr
= load_data(fd
, file_offset
+ ehdr
.e_shoff
,
2370 sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2371 sm_table
= tcc_mallocz(sizeof(SectionMergeInfo
) * ehdr
.e_shnum
);
2373 /* load section names */
2374 sh
= &shdr
[ehdr
.e_shstrndx
];
2375 strsec
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2377 /* load symtab and strtab */
2378 old_to_new_syms
= NULL
;
2382 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2384 if (sh
->sh_type
== SHT_SYMTAB
) {
2386 tcc_error_noabort("object must contain only one symtab");
2391 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2392 symtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2393 sm_table
[i
].s
= symtab_section
;
2395 /* now load strtab */
2396 sh
= &shdr
[sh
->sh_link
];
2397 strtab
= load_data(fd
, file_offset
+ sh
->sh_offset
, sh
->sh_size
);
2401 /* now examine each section and try to merge its content with the
2403 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2404 /* no need to examine section name strtab */
2405 if (i
== ehdr
.e_shstrndx
)
2408 sh_name
= strsec
+ sh
->sh_name
;
2409 /* ignore sections types we do not handle */
2410 if (sh
->sh_type
!= SHT_PROGBITS
&&
2411 sh
->sh_type
!= SHT_RELX
&&
2413 sh
->sh_type
!= SHT_ARM_EXIDX
&&
2415 sh
->sh_type
!= SHT_NOBITS
&&
2416 sh
->sh_type
!= SHT_PREINIT_ARRAY
&&
2417 sh
->sh_type
!= SHT_INIT_ARRAY
&&
2418 sh
->sh_type
!= SHT_FINI_ARRAY
&&
2419 strcmp(sh_name
, ".stabstr")
2422 if (sh
->sh_addralign
< 1)
2423 sh
->sh_addralign
= 1;
2424 /* find corresponding section, if any */
2425 for(j
= 1; j
< s1
->nb_sections
;j
++) {
2426 s
= s1
->sections
[j
];
2427 if (!strcmp(s
->name
, sh_name
)) {
2428 if (!strncmp(sh_name
, ".gnu.linkonce",
2429 sizeof(".gnu.linkonce") - 1)) {
2430 /* if a 'linkonce' section is already present, we
2431 do not add it again. It is a little tricky as
2432 symbols can still be defined in
2434 sm_table
[i
].link_once
= 1;
2441 /* not found: create new section */
2442 s
= new_section(s1
, sh_name
, sh
->sh_type
, sh
->sh_flags
);
2443 /* take as much info as possible from the section. sh_link and
2444 sh_info will be updated later */
2445 s
->sh_addralign
= sh
->sh_addralign
;
2446 s
->sh_entsize
= sh
->sh_entsize
;
2447 sm_table
[i
].new_section
= 1;
2449 if (sh
->sh_type
!= s
->sh_type
) {
2450 tcc_error_noabort("invalid section type");
2454 /* align start of section */
2455 offset
= s
->data_offset
;
2457 if (0 == strcmp(sh_name
, ".stab")) {
2461 if (0 == strcmp(sh_name
, ".stabstr")) {
2466 size
= sh
->sh_addralign
- 1;
2467 offset
= (offset
+ size
) & ~size
;
2468 if (sh
->sh_addralign
> s
->sh_addralign
)
2469 s
->sh_addralign
= sh
->sh_addralign
;
2470 s
->data_offset
= offset
;
2472 sm_table
[i
].offset
= offset
;
2474 /* concatenate sections */
2476 if (sh
->sh_type
!= SHT_NOBITS
) {
2478 lseek(fd
, file_offset
+ sh
->sh_offset
, SEEK_SET
);
2479 ptr
= section_ptr_add(s
, size
);
2480 read(fd
, ptr
, size
);
2482 s
->data_offset
+= size
;
2487 /* //gr relocate stab strings */
2488 if (stab_index
&& stabstr_index
) {
2491 s
= sm_table
[stab_index
].s
;
2492 a
= (Stab_Sym
*)(s
->data
+ sm_table
[stab_index
].offset
);
2493 b
= (Stab_Sym
*)(s
->data
+ s
->data_offset
);
2494 o
= sm_table
[stabstr_index
].offset
;
2496 a
->n_strx
+= o
, a
++;
2499 /* second short pass to update sh_link and sh_info fields of new
2501 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2503 if (!s
|| !sm_table
[i
].new_section
)
2506 if (sh
->sh_link
> 0)
2507 s
->link
= sm_table
[sh
->sh_link
].s
;
2508 if (sh
->sh_type
== SHT_RELX
) {
2509 s
->sh_info
= sm_table
[sh
->sh_info
].s
->sh_num
;
2510 /* update backward link */
2511 s1
->sections
[s
->sh_info
]->reloc
= s
;
2516 /* resolve symbols */
2517 old_to_new_syms
= tcc_mallocz(nb_syms
* sizeof(int));
2520 for(i
= 1; i
< nb_syms
; i
++, sym
++) {
2521 if (sym
->st_shndx
!= SHN_UNDEF
&&
2522 sym
->st_shndx
< SHN_LORESERVE
) {
2523 sm
= &sm_table
[sym
->st_shndx
];
2524 if (sm
->link_once
) {
2525 /* if a symbol is in a link once section, we use the
2526 already defined symbol. It is very important to get
2527 correct relocations */
2528 if (ELFW(ST_BIND
)(sym
->st_info
) != STB_LOCAL
) {
2529 name
= strtab
+ sym
->st_name
;
2530 sym_index
= find_elf_sym(symtab_section
, name
);
2532 old_to_new_syms
[i
] = sym_index
;
2536 /* if no corresponding section added, no need to add symbol */
2539 /* convert section number */
2540 sym
->st_shndx
= sm
->s
->sh_num
;
2542 sym
->st_value
+= sm
->offset
;
2545 name
= strtab
+ sym
->st_name
;
2546 sym_index
= add_elf_sym(symtab_section
, sym
->st_value
, sym
->st_size
,
2547 sym
->st_info
, sym
->st_other
,
2548 sym
->st_shndx
, name
);
2549 old_to_new_syms
[i
] = sym_index
;
2552 /* third pass to patch relocation entries */
2553 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
2558 offset
= sm_table
[i
].offset
;
2559 switch(s
->sh_type
) {
2561 /* take relocation offset information */
2562 offseti
= sm_table
[sh
->sh_info
].offset
;
2563 rel_end
= (ElfW_Rel
*)(s
->data
+ s
->data_offset
);
2564 for(rel
= (ElfW_Rel
*)(s
->data
+ offset
);
2569 /* convert symbol index */
2570 type
= ELFW(R_TYPE
)(rel
->r_info
);
2571 sym_index
= ELFW(R_SYM
)(rel
->r_info
);
2572 /* NOTE: only one symtab assumed */
2573 if (sym_index
>= nb_syms
)
2575 sym_index
= old_to_new_syms
[sym_index
];
2576 /* ignore link_once in rel section. */
2577 if (!sym_index
&& !sm
->link_once
2578 #ifdef TCC_TARGET_ARM
2579 && type
!= R_ARM_V4BX
2583 tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2584 i
, strsec
+ sh
->sh_name
, rel
->r_offset
);
2587 rel
->r_info
= ELFW(R_INFO
)(sym_index
, type
);
2588 /* offset the relocation offset */
2589 rel
->r_offset
+= offseti
;
2601 tcc_free(old_to_new_syms
);
2608 typedef struct ArchiveHeader
{
2609 char ar_name
[16]; /* name of this member */
2610 char ar_date
[12]; /* file mtime */
2611 char ar_uid
[6]; /* owner uid; printed as decimal */
2612 char ar_gid
[6]; /* owner gid; printed as decimal */
2613 char ar_mode
[8]; /* file mode, printed as octal */
2614 char ar_size
[10]; /* file size, printed as decimal */
2615 char ar_fmag
[2]; /* should contain ARFMAG */
2618 static int get_be32(const uint8_t *b
)
2620 return b
[3] | (b
[2] << 8) | (b
[1] << 16) | (b
[0] << 24);
2623 /* load only the objects which resolve undefined symbols */
2624 static int tcc_load_alacarte(TCCState
*s1
, int fd
, int size
)
2626 int i
, bound
, nsyms
, sym_index
, off
, ret
;
2628 const char *ar_names
, *p
;
2629 const uint8_t *ar_index
;
2632 data
= tcc_malloc(size
);
2633 if (read(fd
, data
, size
) != size
)
2635 nsyms
= get_be32(data
);
2636 ar_index
= data
+ 4;
2637 ar_names
= ar_index
+ nsyms
* 4;
2641 for(p
= ar_names
, i
= 0; i
< nsyms
; i
++, p
+= strlen(p
)+1) {
2642 sym_index
= find_elf_sym(symtab_section
, p
);
2644 sym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym_index
];
2645 if(sym
->st_shndx
== SHN_UNDEF
) {
2646 off
= get_be32(ar_index
+ i
* 4) + sizeof(ArchiveHeader
);
2648 printf("%5d\t%s\t%08x\n", i
, p
, sym
->st_shndx
);
2651 lseek(fd
, off
, SEEK_SET
);
2652 if(tcc_load_object_file(s1
, fd
, off
) < 0) {
2667 /* load a '.a' file */
2668 ST_FUNC
int tcc_load_archive(TCCState
*s1
, int fd
)
2675 unsigned long file_offset
;
2677 /* skip magic which was already checked */
2678 read(fd
, magic
, sizeof(magic
));
2681 len
= read(fd
, &hdr
, sizeof(hdr
));
2684 if (len
!= sizeof(hdr
)) {
2685 tcc_error_noabort("invalid archive");
2688 memcpy(ar_size
, hdr
.ar_size
, sizeof(hdr
.ar_size
));
2689 ar_size
[sizeof(hdr
.ar_size
)] = '\0';
2690 size
= strtol(ar_size
, NULL
, 0);
2691 memcpy(ar_name
, hdr
.ar_name
, sizeof(hdr
.ar_name
));
2692 for(i
= sizeof(hdr
.ar_name
) - 1; i
>= 0; i
--) {
2693 if (ar_name
[i
] != ' ')
2696 ar_name
[i
+ 1] = '\0';
2697 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2698 file_offset
= lseek(fd
, 0, SEEK_CUR
);
2700 size
= (size
+ 1) & ~1;
2701 if (!strcmp(ar_name
, "/")) {
2702 /* coff symbol table : we handle it */
2703 if(s1
->alacarte_link
)
2704 return tcc_load_alacarte(s1
, fd
, size
);
2705 } else if (!strcmp(ar_name
, "//") ||
2706 !strcmp(ar_name
, "__.SYMDEF") ||
2707 !strcmp(ar_name
, "__.SYMDEF/") ||
2708 !strcmp(ar_name
, "ARFILENAMES/")) {
2709 /* skip symbol table or archive names */
2711 if (tcc_load_object_file(s1
, fd
, file_offset
) < 0)
2714 lseek(fd
, file_offset
+ size
, SEEK_SET
);
2719 #ifndef TCC_TARGET_PE
2720 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2721 is referenced by the user (so it should be added as DT_NEEDED in
2722 the generated ELF file) */
2723 ST_FUNC
int tcc_load_dll(TCCState
*s1
, int fd
, const char *filename
, int level
)
2726 ElfW(Shdr
) *shdr
, *sh
, *sh1
;
2727 int i
, j
, nb_syms
, nb_dts
, sym_bind
, ret
;
2728 ElfW(Sym
) *sym
, *dynsym
;
2729 ElfW(Dyn
) *dt
, *dynamic
;
2730 unsigned char *dynstr
;
2731 const char *name
, *soname
;
2732 DLLReference
*dllref
;
2734 read(fd
, &ehdr
, sizeof(ehdr
));
2736 /* test CPU specific stuff */
2737 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
2738 ehdr
.e_machine
!= EM_TCC_TARGET
) {
2739 tcc_error_noabort("bad architecture");
2744 shdr
= load_data(fd
, ehdr
.e_shoff
, sizeof(ElfW(Shdr
)) * ehdr
.e_shnum
);
2746 /* load dynamic section and dynamic symbols */
2750 dynsym
= NULL
; /* avoid warning */
2751 dynstr
= NULL
; /* avoid warning */
2752 for(i
= 0, sh
= shdr
; i
< ehdr
.e_shnum
; i
++, sh
++) {
2753 switch(sh
->sh_type
) {
2755 nb_dts
= sh
->sh_size
/ sizeof(ElfW(Dyn
));
2756 dynamic
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2759 nb_syms
= sh
->sh_size
/ sizeof(ElfW(Sym
));
2760 dynsym
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
2761 sh1
= &shdr
[sh
->sh_link
];
2762 dynstr
= load_data(fd
, sh1
->sh_offset
, sh1
->sh_size
);
2769 /* compute the real library name */
2770 soname
= tcc_basename(filename
);
2772 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2773 if (dt
->d_tag
== DT_SONAME
) {
2774 soname
= dynstr
+ dt
->d_un
.d_val
;
2778 /* if the dll is already loaded, do not load it */
2779 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
2780 dllref
= s1
->loaded_dlls
[i
];
2781 if (!strcmp(soname
, dllref
->name
)) {
2782 /* but update level if needed */
2783 if (level
< dllref
->level
)
2784 dllref
->level
= level
;
2790 // printf("loading dll '%s'\n", soname);
2792 /* add the dll and its level */
2793 dllref
= tcc_mallocz(sizeof(DLLReference
) + strlen(soname
));
2794 dllref
->level
= level
;
2795 strcpy(dllref
->name
, soname
);
2796 dynarray_add((void ***)&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
, dllref
);
2798 /* add dynamic symbols in dynsym_section */
2799 for(i
= 1, sym
= dynsym
+ 1; i
< nb_syms
; i
++, sym
++) {
2800 sym_bind
= ELFW(ST_BIND
)(sym
->st_info
);
2801 if (sym_bind
== STB_LOCAL
)
2803 name
= dynstr
+ sym
->st_name
;
2804 add_elf_sym(s1
->dynsymtab_section
, sym
->st_value
, sym
->st_size
,
2805 sym
->st_info
, sym
->st_other
, sym
->st_shndx
, name
);
2808 /* load all referenced DLLs */
2809 for(i
= 0, dt
= dynamic
; i
< nb_dts
; i
++, dt
++) {
2812 name
= dynstr
+ dt
->d_un
.d_val
;
2813 for(j
= 0; j
< s1
->nb_loaded_dlls
; j
++) {
2814 dllref
= s1
->loaded_dlls
[j
];
2815 if (!strcmp(name
, dllref
->name
))
2816 goto already_loaded
;
2818 if (tcc_add_dll(s1
, name
, AFF_REFERENCED_DLL
) < 0) {
2819 tcc_error_noabort("referenced dll '%s' not found", name
);
2836 #define LD_TOK_NAME 256
2837 #define LD_TOK_EOF (-1)
2839 /* return next ld script token */
2840 static int ld_next(TCCState
*s1
, char *name
, int name_size
)
2858 file
->buf_ptr
= parse_comment(file
->buf_ptr
);
2859 ch
= file
->buf_ptr
[0];
2867 /* case 'a' ... 'z': */
2894 /* case 'A' ... 'z': */
2929 if (!((ch
>= 'a' && ch
<= 'z') ||
2930 (ch
>= 'A' && ch
<= 'Z') ||
2931 (ch
>= '0' && ch
<= '9') ||
2932 strchr("/.-_+=$:\\,~", ch
)))
2934 if ((q
- name
) < name_size
- 1) {
2951 printf("tok=%c %d\n", c
, c
);
2952 if (c
== LD_TOK_NAME
)
2953 printf(" name=%s\n", name
);
2959 * Extract the file name from the library name
2961 * /!\ No test on filename capacity, be careful
2963 static void libname_to_filename(TCCState
*s1
, const char libname
[], char filename
[])
2965 if (!s1
->static_link
) {
2966 sprintf(filename
, "lib%s.so", libname
);
2968 sprintf(filename
, "lib%s.a", libname
);
2972 static int ld_add_file(TCCState
*s1
, const char filename
[])
2976 ret
= tcc_add_file_internal(s1
, filename
, 0);
2978 ret
= tcc_add_dll(s1
, filename
, 0);
2982 static inline int new_undef_syms(void)
2985 ret
= new_undef_sym
;
2990 static int ld_add_file_list(TCCState
*s1
, const char *cmd
, int as_needed
)
2992 char filename
[1024], libname
[1024];
2993 int t
, group
, nblibs
= 0, ret
= 0;
2996 group
= !strcmp(cmd
, "GROUP");
2999 t
= ld_next(s1
, filename
, sizeof(filename
));
3002 t
= ld_next(s1
, filename
, sizeof(filename
));
3005 if (t
== LD_TOK_EOF
) {
3006 tcc_error_noabort("unexpected end of file");
3008 goto lib_parse_error
;
3009 } else if (t
== ')') {
3011 } else if (t
== '-') {
3012 t
= ld_next(s1
, filename
, sizeof(filename
));
3013 if ((t
!= LD_TOK_NAME
) || (filename
[0] != 'l')) {
3014 tcc_error_noabort("library name expected");
3016 goto lib_parse_error
;
3018 strcpy(libname
, &filename
[1]);
3019 libname_to_filename(s1
, libname
, filename
);
3020 } else if (t
!= LD_TOK_NAME
) {
3021 tcc_error_noabort("filename expected");
3023 goto lib_parse_error
;
3025 if (!strcmp(filename
, "AS_NEEDED")) {
3026 ret
= ld_add_file_list(s1
, cmd
, 1);
3028 goto lib_parse_error
;
3030 /* TODO: Implement AS_NEEDED support. Ignore it for now */
3032 ret
= ld_add_file(s1
, filename
);
3034 goto lib_parse_error
;
3036 /* Add the filename *and* the libname to avoid future conversions */
3037 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(filename
));
3038 if (libname
[0] != '\0')
3039 dynarray_add((void ***) &libs
, &nblibs
, tcc_strdup(libname
));
3043 t
= ld_next(s1
, filename
, sizeof(filename
));
3045 t
= ld_next(s1
, filename
, sizeof(filename
));
3048 if (group
&& !as_needed
) {
3049 while (new_undef_syms()) {
3052 for (i
= 0; i
< nblibs
; i
++)
3053 ld_add_file(s1
, libs
[i
]);
3057 dynarray_reset(&libs
, &nblibs
);
3061 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3063 ST_FUNC
int tcc_load_ldscript(TCCState
*s1
)
3066 char filename
[1024];
3069 ch
= file
->buf_ptr
[0];
3072 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3073 if (t
== LD_TOK_EOF
)
3075 else if (t
!= LD_TOK_NAME
)
3077 if (!strcmp(cmd
, "INPUT") ||
3078 !strcmp(cmd
, "GROUP")) {
3079 ret
= ld_add_file_list(s1
, cmd
, 0);
3082 } else if (!strcmp(cmd
, "OUTPUT_FORMAT") ||
3083 !strcmp(cmd
, "TARGET")) {
3084 /* ignore some commands */
3085 t
= ld_next(s1
, cmd
, sizeof(cmd
));
3089 t
= ld_next(s1
, filename
, sizeof(filename
));
3090 if (t
== LD_TOK_EOF
) {
3091 tcc_error_noabort("unexpected end of file");
3093 } else if (t
== ')') {
3103 #endif /* ndef TCC_TARGET_PE */