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)
605
x = (*(int *)ptr)&0xffffff;
606
(*(int *)ptr) &= 0xff000000;
611
#ifndef TCC_TARGET_PE
612
if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
613
if (s1->output_type == TCC_OUTPUT_MEMORY)
614
x += add_jmp_table(s1, val) - val; /* add veneer */
616
if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
617
tcc_error("can't relocate value at %x",addr);
626
x = (*(int *)ptr) & 0x7fffffff;
627
(*(int *)ptr) &= 0x80000000;
630
if((x^(x>>1))&0x40000000)
631
tcc_error("can't relocate value at %x",addr);
632
(*(int *)ptr) |= x & 0x7fffffff;
638
*(int *)ptr += val - addr;
639
case R_ARM_BASE_PREL:
640
*(int *)ptr += s1->got->sh_addr - addr;
643
*(int *)ptr += val - s1->got->sh_addr;
646
/* we load the got offset */
647
*(int *)ptr += s1->got_offsets[sym_index];
652
/* trade Thumb support for ARMv4 support */
653
if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
654
*(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
657
fprintf(stderr,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
658
type, (unsigned)addr, (unsigned)(uplong)ptr, (unsigned)val);
660
#elif defined(TCC_TARGET_C67)
668
/* put the low 16 bits of the absolute address */
669
// add to what is already there
671
orig = ((*(int *)(ptr )) >> 7) & 0xffff;
672
orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
674
//patch both at once - assumes always in pairs Low - High
676
*(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
677
*(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
683
fprintf(stderr,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
684
type, (unsigned)addr, (unsigned)(uplong)ptr, (unsigned)val);
686
#elif defined(TCC_TARGET_X86_64)
688
if (s1->output_type == TCC_OUTPUT_DLL) {
689
qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
690
qrel->r_addend = *(long long *)ptr + val;
693
*(long long *)ptr += val;
697
if (s1->output_type == TCC_OUTPUT_DLL) {
698
/* XXX: this logic may depend on TCC's codegen
699
now TCC uses R_X86_64_32 even for a 64bit pointer */
700
qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
701
qrel->r_addend = *(int *)ptr + val;
708
if (s1->output_type == TCC_OUTPUT_DLL) {
710
esym_index = s1->symtab_to_dynsym[sym_index];
712
qrel->r_offset = rel->r_offset;
713
qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
714
qrel->r_addend = *(int *)ptr;
720
case R_X86_64_PLT32: {
722
diff = (long long)val - addr;
723
if (diff <= -2147483647 || diff > 2147483647) {
724
#ifndef TCC_TARGET_PE
725
/* XXX: naive support for over 32bit jump */
726
if (s1->output_type == TCC_OUTPUT_MEMORY) {
727
val = (add_jmp_table(s1, val - rel->r_addend) +
732
if (diff <= -2147483647 || diff > 2147483647) {
733
tcc_error("internal error: relocation failed");
739
case R_X86_64_GLOB_DAT:
740
case R_X86_64_JUMP_SLOT:
741
/* They don't need addend */
742
*(int *)ptr = val - rel->r_addend;
744
case R_X86_64_GOTPCREL:
745
#ifndef TCC_TARGET_PE
746
if (s1->output_type == TCC_OUTPUT_MEMORY) {
747
val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
748
*(int *)ptr += val - addr;
752
*(int *)ptr += (s1->got->sh_addr - addr +
753
s1->got_offsets[sym_index] - 4);
755
case R_X86_64_GOTTPOFF:
756
*(int *)ptr += val - s1->got->sh_addr;
759
/* we load the got offset */
760
*(int *)ptr += s1->got_offsets[sym_index];
763
#error unsupported processor
767
/* if the relocation is allocated, we change its symbol table */
768
if (sr->sh_flags & SHF_ALLOC)
769
sr->link = s1->dynsym;
772
/* relocate relocation table in 'sr' */
773
static void relocate_rel(TCCState *s1, Section *sr)
776
ElfW_Rel *rel, *rel_end;
778
s = s1->sections[sr->sh_info];
779
rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
780
for(rel = (ElfW_Rel *)sr->data;
783
rel->r_offset += s->sh_addr;
787
/* count the number of dynamic relocations so that we can reserve
789
static int prepare_dynamic_rel(TCCState *s1, Section *sr)
791
ElfW_Rel *rel, *rel_end;
792
int sym_index, esym_index, type, count;
795
rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
796
for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
797
sym_index = ELFW(R_SYM)(rel->r_info);
798
type = ELFW(R_TYPE)(rel->r_info);
800
#if defined(TCC_TARGET_I386)
802
#elif defined(TCC_TARGET_X86_64)
809
#if defined(TCC_TARGET_I386)
811
#elif defined(TCC_TARGET_X86_64)
814
esym_index = s1->symtab_to_dynsym[sym_index];
823
/* allocate the section */
824
sr->sh_flags |= SHF_ALLOC;
825
sr->sh_size = count * sizeof(ElfW_Rel);
830
static void put_got_offset(TCCState *s1, int index, unsigned long val)
835
if (index >= s1->nb_got_offsets) {
836
/* find immediately bigger power of 2 and reallocate array */
840
tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
841
s1->got_offsets = tab;
842
memset(s1->got_offsets + s1->nb_got_offsets, 0,
843
(n - s1->nb_got_offsets) * sizeof(unsigned long));
844
s1->nb_got_offsets = n;
846
s1->got_offsets[index] = val;
849
/* XXX: suppress that */
850
static void put32(unsigned char *p, uint32_t val)
858
#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
859
defined(TCC_TARGET_X86_64)
860
static uint32_t get32(unsigned char *p)
862
return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
866
static void build_got(TCCState *s1)
870
/* if no got, then create it */
871
s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
872
s1->got->sh_entsize = 4;
873
add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
874
0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
875
ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
877
/* keep space for _DYNAMIC pointer, if present */
879
/* two dummy got entries */
883
/* keep space for _DYNAMIC pointer, if present */
886
/* two dummy got entries */
894
/* put a got entry corresponding to a symbol in symtab_section. 'size'
895
and 'info' can be modifed if more precise info comes from the DLL */
896
static void put_got_entry(TCCState *s1,
897
int reloc_type, unsigned long size, int info,
903
unsigned long offset;
909
/* if a got entry already exists for that symbol, no need to add one */
910
if (sym_index < s1->nb_got_offsets &&
911
s1->got_offsets[sym_index] != 0)
914
put_got_offset(s1, sym_index, s1->got->data_offset);
917
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
918
name = symtab_section->link->data + sym->st_name;
919
offset = sym->st_value;
920
#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
922
#ifdef TCC_TARGET_X86_64
932
#if defined(TCC_OUTPUT_DLL_WITH_PLT)
935
/* if we build a DLL, we add a %ebx offset */
936
if (s1->output_type == TCC_OUTPUT_DLL)
942
/* add a PLT entry */
944
if (plt->data_offset == 0) {
945
/* first plt entry */
946
p = section_ptr_add(plt, 16);
947
p[0] = 0xff; /* pushl got + PTR_SIZE */
949
put32(p + 2, PTR_SIZE);
950
p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
952
put32(p + 8, PTR_SIZE * 2);
955
p = section_ptr_add(plt, 16);
956
p[0] = 0xff; /* jmp *(got + x) */
958
put32(p + 2, s1->got->data_offset);
959
p[6] = 0x68; /* push $xxx */
960
put32(p + 7, (plt->data_offset - 32) >> 1);
961
p[11] = 0xe9; /* jmp plt_start */
962
put32(p + 12, -(plt->data_offset));
964
/* the symbol is modified so that it will be relocated to
966
#if !defined(TCC_OUTPUT_DLL_WITH_PLT)
967
if (s1->output_type == TCC_OUTPUT_EXE)
969
offset = plt->data_offset - 16;
971
#elif defined(TCC_TARGET_ARM)
972
if (reloc_type == R_ARM_JUMP_SLOT) {
976
/* if we build a DLL, we add a %ebx offset */
977
if (s1->output_type == TCC_OUTPUT_DLL)
978
tcc_error("DLLs unimplemented!");
980
/* add a PLT entry */
982
if (plt->data_offset == 0) {
983
/* first plt entry */
984
p = section_ptr_add(plt, 16);
985
put32(p , 0xe52de004);
986
put32(p + 4, 0xe59fe010);
987
put32(p + 8, 0xe08fe00e);
988
put32(p + 12, 0xe5bef008);
991
p = section_ptr_add(plt, 16);
992
put32(p , 0xe59fc004);
993
put32(p+4, 0xe08fc00c);
994
put32(p+8, 0xe59cf000);
995
put32(p+12, s1->got->data_offset);
997
/* the symbol is modified so that it will be relocated to
999
if (s1->output_type == TCC_OUTPUT_EXE)
1000
offset = plt->data_offset - 16;
1002
#elif defined(TCC_TARGET_C67)
1003
tcc_error("C67 got not implemented");
1005
#error unsupported CPU
1007
index = put_elf_sym(s1->dynsym, offset,
1008
size, info, 0, sym->st_shndx, name);
1009
/* put a got entry */
1010
put_elf_reloc(s1->dynsym, s1->got,
1011
s1->got->data_offset,
1014
ptr = section_ptr_add(s1->got, PTR_SIZE);
1018
/* build GOT and PLT entries */
1019
ST_FUNC void build_got_entries(TCCState *s1)
1022
ElfW_Rel *rel, *rel_end;
1024
int i, type, reloc_type, sym_index;
1026
for(i = 1; i < s1->nb_sections; i++) {
1027
s = s1->sections[i];
1028
if (s->sh_type != SHT_RELX)
1030
/* no need to handle got relocations */
1031
if (s->link != symtab_section)
1033
rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1034
for(rel = (ElfW_Rel *)s->data;
1037
type = ELFW(R_TYPE)(rel->r_info);
1039
#if defined(TCC_TARGET_I386)
1046
if (type == R_386_GOT32 || type == R_386_PLT32) {
1047
sym_index = ELFW(R_SYM)(rel->r_info);
1048
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1049
/* look at the symbol got offset. If none, then add one */
1050
if (type == R_386_GOT32)
1051
reloc_type = R_386_GLOB_DAT;
1053
reloc_type = R_386_JMP_SLOT;
1054
put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1058
#elif defined(TCC_TARGET_ARM)
1059
case R_ARM_GOT_BREL:
1060
case R_ARM_GOTOFF32:
1061
case R_ARM_BASE_PREL:
1065
if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1066
sym_index = ELFW(R_SYM)(rel->r_info);
1067
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1068
/* look at the symbol got offset. If none, then add one */
1069
if (type == R_ARM_GOT_BREL)
1070
reloc_type = R_ARM_GLOB_DAT;
1072
reloc_type = R_ARM_JUMP_SLOT;
1073
put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1077
#elif defined(TCC_TARGET_C67)
1084
if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1085
sym_index = ELFW(R_SYM)(rel->r_info);
1086
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1087
/* look at the symbol got offset. If none, then add one */
1088
if (type == R_C60_GOT32)
1089
reloc_type = R_C60_GLOB_DAT;
1091
reloc_type = R_C60_JMP_SLOT;
1092
put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1096
#elif defined(TCC_TARGET_X86_64)
1097
case R_X86_64_GOT32:
1098
case R_X86_64_GOTTPOFF:
1099
case R_X86_64_GOTPCREL:
1100
case R_X86_64_PLT32:
1103
if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1104
type == R_X86_64_PLT32) {
1105
sym_index = ELFW(R_SYM)(rel->r_info);
1106
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1107
/* look at the symbol got offset. If none, then add one */
1108
if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1109
reloc_type = R_X86_64_GLOB_DAT;
1111
reloc_type = R_X86_64_JUMP_SLOT;
1112
put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1117
#error unsupported CPU
1126
ST_FUNC Section *new_symtab(TCCState *s1,
1127
const char *symtab_name, int sh_type, int sh_flags,
1128
const char *strtab_name,
1129
const char *hash_name, int hash_sh_flags)
1131
Section *symtab, *strtab, *hash;
1132
int *ptr, nb_buckets;
1134
symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1135
symtab->sh_entsize = sizeof(ElfW(Sym));
1136
strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1137
put_elf_str(strtab, "");
1138
symtab->link = strtab;
1139
put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1143
hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1144
hash->sh_entsize = sizeof(int);
1145
symtab->hash = hash;
1146
hash->link = symtab;
1148
ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1149
ptr[0] = nb_buckets;
1151
memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1155
/* put dynamic tag */
1156
static void put_dt(Section *dynamic, int dt, uplong val)
1159
dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1161
dyn->d_un.d_val = val;
1164
static void add_init_array_defines(TCCState *s1, const char *section_name)
1168
char sym_start[1024];
1171
snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1172
snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1174
s = find_section(s1, section_name);
1179
end_offset = s->data_offset;
1182
add_elf_sym(symtab_section,
1184
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1185
s->sh_num, sym_start);
1186
add_elf_sym(symtab_section,
1188
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1189
s->sh_num, sym_end);
1192
static int tcc_add_support(TCCState *s1, const char *filename)
1195
snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, filename);
1196
return tcc_add_file(s1, buf);
1199
ST_FUNC void tcc_add_bcheck(TCCState *s1)
1201
#ifdef CONFIG_TCC_BCHECK
1203
Section *init_section;
1204
unsigned char *pinit;
1207
if (0 == s1->do_bounds_check)
1210
/* XXX: add an object file to do that */
1211
ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1213
add_elf_sym(symtab_section, 0, 0,
1214
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1215
bounds_section->sh_num, "__bounds_start");
1216
/* add bound check code */
1217
#ifndef TCC_TARGET_PE
1218
tcc_add_support(s1, "bcheck.o");
1220
#ifdef TCC_TARGET_I386
1221
if (s1->output_type != TCC_OUTPUT_MEMORY) {
1222
/* add 'call __bound_init()' in .init section */
1223
init_section = find_section(s1, ".init");
1224
pinit = section_ptr_add(init_section, 5);
1226
put32(pinit + 1, -4);
1227
sym_index = find_elf_sym(symtab_section, "__bound_init");
1228
put_elf_reloc(symtab_section, init_section,
1229
init_section->data_offset - 4, R_386_PC32, sym_index);
1235
/* add tcc runtime libraries */
1236
ST_FUNC void tcc_add_runtime(TCCState *s1)
1241
if (!s1->nostdlib) {
1242
tcc_add_library(s1, "c");
1243
#ifdef CONFIG_USE_LIBGCC
1244
tcc_add_file(s1, TCC_LIBGCC);
1245
#elif !defined WITHOUT_LIBTCC
1246
tcc_add_support(s1, "libtcc1.a");
1248
/* add crt end if not memory output */
1249
if (s1->output_type != TCC_OUTPUT_MEMORY)
1250
tcc_add_crt(s1, "crtn.o");
1254
/* add various standard linker symbols (must be done after the
1255
sections are filled (for example after allocating common
1257
ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1263
add_elf_sym(symtab_section,
1264
text_section->data_offset, 0,
1265
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1266
text_section->sh_num, "_etext");
1267
add_elf_sym(symtab_section,
1268
data_section->data_offset, 0,
1269
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1270
data_section->sh_num, "_edata");
1271
add_elf_sym(symtab_section,
1272
bss_section->data_offset, 0,
1273
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1274
bss_section->sh_num, "_end");
1275
/* horrible new standard ldscript defines */
1276
add_init_array_defines(s1, ".preinit_array");
1277
add_init_array_defines(s1, ".init_array");
1278
add_init_array_defines(s1, ".fini_array");
1280
/* add start and stop symbols for sections whose name can be
1282
for(i = 1; i < s1->nb_sections; i++) {
1283
s = s1->sections[i];
1284
if (s->sh_type == SHT_PROGBITS &&
1285
(s->sh_flags & SHF_ALLOC)) {
1289
/* check if section name can be expressed in C */
1295
if (!isid(ch) && !isnum(ch))
1299
snprintf(buf, sizeof(buf), "__start_%s", s->name);
1300
add_elf_sym(symtab_section,
1302
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1304
snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1305
add_elf_sym(symtab_section,
1307
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1314
static void tcc_output_binary(TCCState *s1, FILE *f,
1315
const int *section_order)
1318
int i, offset, size;
1321
for(i=1;i<s1->nb_sections;i++) {
1322
s = s1->sections[section_order[i]];
1323
if (s->sh_type != SHT_NOBITS &&
1324
(s->sh_flags & SHF_ALLOC)) {
1325
while (offset < s->sh_offset) {
1330
fwrite(s->data, 1, size, f);
1336
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1338
#define EXTRA_RELITEMS 14
1340
/* move the relocation value from .dynsym to .got */
1341
void patch_dynsym_undef(TCCState *s1, Section *s)
1343
uint32_t *gotd = (void *)s1->got->data;
1344
ElfW(Sym) *sym, *sym_end;
1346
gotd += 3; // dummy entries in .got
1347
/* relocate symbols in .dynsym */
1348
sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1349
for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1350
if (sym->st_shndx == SHN_UNDEF) {
1351
*gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1358
#define EXTRA_RELITEMS 9
1360
/* zero plt offsets of weak symbols in .dynsym */
1361
void patch_dynsym_undef(TCCState *s1, Section *s)
1363
ElfW(Sym) *sym, *sym_end;
1365
sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1366
for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++)
1367
if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
1372
ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1374
int sym_index = ELFW(R_SYM) (rel->r_info);
1375
ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1376
unsigned long offset;
1378
if (sym_index >= s1->nb_got_offsets)
1380
offset = s1->got_offsets[sym_index];
1381
section_reserve(s1->got, offset + PTR_SIZE);
1382
#ifdef TCC_TARGET_X86_64
1383
/* only works for x86-64 */
1384
put32(s1->got->data + offset + 4, sym->st_value >> 32);
1386
put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1389
ST_FUNC void fill_got(TCCState *s1)
1392
ElfW_Rel *rel, *rel_end;
1395
for(i = 1; i < s1->nb_sections; i++) {
1396
s = s1->sections[i];
1397
if (s->sh_type != SHT_RELX)
1399
/* no need to handle got relocations */
1400
if (s->link != symtab_section)
1402
rel_end = (ElfW_Rel *) (s->data + s->data_offset);
1403
for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
1404
switch (ELFW(R_TYPE) (rel->r_info)) {
1405
case R_X86_64_GOT32:
1406
case R_X86_64_GOTPCREL:
1407
case R_X86_64_PLT32:
1408
fill_got_entry(s1, rel);
1416
/* output an ELF file */
1417
/* XXX: suppress unneeded sections */
1418
static int elf_output_file(TCCState *s1, const char *filename)
1424
int shnum, i, phnum, file_offset, offset, size, j, sh_order_index, k;
1427
Section *strsec, *s;
1428
ElfW(Shdr) shdr, *sh;
1429
ElfW(Phdr) *phdr, *ph;
1430
Section *interp, *dynamic, *dynstr;
1431
unsigned long saved_dynamic_data_offset;
1433
int type, file_type;
1434
uplong rel_addr, rel_size;
1435
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1436
uplong bss_addr, bss_size;
1439
file_type = s1->output_type;
1442
if (file_type != TCC_OUTPUT_OBJ) {
1443
tcc_add_runtime(s1);
1447
section_order = NULL;
1450
dynstr = NULL; /* avoid warning */
1451
saved_dynamic_data_offset = 0; /* avoid warning */
1453
if (file_type != TCC_OUTPUT_OBJ) {
1454
relocate_common_syms();
1456
tcc_add_linker_symbols(s1);
1458
if (!s1->static_link) {
1460
int sym_index, index;
1461
ElfW(Sym) *esym, *sym_end;
1463
if (file_type == TCC_OUTPUT_EXE) {
1465
/* allow override the dynamic loader */
1466
const char *elfint = getenv("LD_SO");
1468
elfint = CONFIG_TCC_ELFINTERP;
1469
/* add interpreter section only if executable */
1470
interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1471
interp->sh_addralign = 1;
1472
ptr = section_ptr_add(interp, 1+strlen(elfint));
1473
strcpy(ptr, elfint);
1476
/* add dynamic symbol table */
1477
s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1479
".hash", SHF_ALLOC);
1480
dynstr = s1->dynsym->link;
1482
/* add dynamic section */
1483
dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1484
SHF_ALLOC | SHF_WRITE);
1485
dynamic->link = dynstr;
1486
dynamic->sh_entsize = sizeof(ElfW(Dyn));
1489
s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1490
SHF_ALLOC | SHF_EXECINSTR);
1491
s1->plt->sh_entsize = 4;
1495
/* scan for undefined symbols and see if they are in the
1496
dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1497
is found, then we add it in the PLT. If a symbol
1498
STT_OBJECT is found, we add it in the .bss section with
1499
a suitable relocation */
1500
sym_end = (ElfW(Sym) *)(symtab_section->data +
1501
symtab_section->data_offset);
1502
if (file_type == TCC_OUTPUT_EXE) {
1503
for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1506
if (sym->st_shndx == SHN_UNDEF) {
1507
name = symtab_section->link->data + sym->st_name;
1508
sym_index = find_elf_sym(s1->dynsymtab_section, name);
1510
esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1511
type = ELFW(ST_TYPE)(esym->st_info);
1512
if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1513
put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1514
ELFW(ST_INFO)(STB_GLOBAL,type),
1515
sym - (ElfW(Sym) *)symtab_section->data);
1516
} else if (type == STT_OBJECT) {
1517
unsigned long offset;
1518
ElfW(Sym) *dynsym, *dynsym_end;
1519
offset = bss_section->data_offset;
1520
/* XXX: which alignment ? */
1521
offset = (offset + 16 - 1) & -16;
1522
index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1524
bss_section->sh_num, name);
1525
// Ensure R_COPY works for weak symbol aliases
1526
if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1527
dynsym_end = (ElfW(Sym) *)
1528
(s1->dynsymtab_section->data +
1529
s1->dynsymtab_section->data_offset);
1530
for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1531
dynsym < dynsym_end; dynsym++) {
1532
if ((dynsym->st_value == esym->st_value)
1533
&& (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1535
dynname = s1->dynsymtab_section->link->data
1537
put_elf_sym(s1->dynsym, offset,
1540
bss_section->sh_num,
1546
put_elf_reloc(s1->dynsym, bss_section,
1547
offset, R_COPY, index);
1548
offset += esym->st_size;
1549
bss_section->data_offset = offset;
1552
/* STB_WEAK undefined symbols are accepted */
1553
/* XXX: _fp_hw seems to be part of the ABI, so we ignore
1555
if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1556
!strcmp(name, "_fp_hw")) {
1558
tcc_error_noabort("undefined symbol '%s'", name);
1561
} else if (s1->rdynamic &&
1562
ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1563
/* if -rdynamic option, then export all non
1565
name = symtab_section->link->data + sym->st_name;
1566
put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1568
sym->st_shndx, name);
1575
/* now look at unresolved dynamic symbols and export
1576
corresponding symbol */
1577
sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1578
s1->dynsymtab_section->data_offset);
1579
for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1582
if (esym->st_shndx == SHN_UNDEF) {
1583
name = s1->dynsymtab_section->link->data + esym->st_name;
1584
sym_index = find_elf_sym(symtab_section, name);
1586
/* XXX: avoid adding a symbol if already
1587
present because of -rdynamic ? */
1588
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1589
put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1591
sym->st_shndx, name);
1593
if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1594
/* weak symbols can stay undefined */
1596
tcc_warning("undefined dynamic symbol '%s'", name);
1603
/* shared library case : we simply export all the global symbols */
1604
nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1605
s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1606
for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1609
if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1610
#if defined(TCC_OUTPUT_DLL_WITH_PLT)
1611
if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
1612
ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
1613
&& sym->st_shndx == SHN_UNDEF) {
1614
put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1616
sym - (ElfW(Sym) *)symtab_section->data);
1618
else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1619
put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1621
sym - (ElfW(Sym) *)symtab_section->data);
1626
name = symtab_section->link->data + sym->st_name;
1627
index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1629
sym->st_shndx, name);
1630
s1->symtab_to_dynsym[sym -
1631
(ElfW(Sym) *)symtab_section->data] =
1638
build_got_entries(s1);
1640
/* add a list of needed dlls */
1641
for(i = 0; i < s1->nb_loaded_dlls; i++) {
1642
DLLReference *dllref = s1->loaded_dlls[i];
1643
if (dllref->level == 0)
1644
put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1648
put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1650
/* XXX: currently, since we do not handle PIC code, we
1651
must relocate the readonly segments */
1652
if (file_type == TCC_OUTPUT_DLL) {
1654
put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1655
put_dt(dynamic, DT_TEXTREL, 0);
1659
put_dt(dynamic, DT_SYMBOLIC, 0);
1661
/* add necessary space for other entries */
1662
saved_dynamic_data_offset = dynamic->data_offset;
1663
dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1665
/* still need to build got entries in case of static link */
1666
build_got_entries(s1);
1670
memset(&ehdr, 0, sizeof(ehdr));
1672
/* we add a section for symbols */
1673
strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1674
put_elf_str(strsec, "");
1676
/* compute number of sections */
1677
shnum = s1->nb_sections;
1679
/* this array is used to reorder sections in the output file */
1680
section_order = tcc_malloc(sizeof(int) * shnum);
1681
section_order[0] = 0;
1684
/* compute number of program headers */
1687
case TCC_OUTPUT_OBJ:
1690
case TCC_OUTPUT_EXE:
1691
if (!s1->static_link)
1692
phnum = 4 + HAVE_PHDR;
1696
case TCC_OUTPUT_DLL:
1701
/* allocate strings for section names and decide if an unallocated
1702
section should be output */
1703
/* NOTE: the strsec section comes last, so its size is also
1705
for(i = 1; i < s1->nb_sections; i++) {
1706
s = s1->sections[i];
1707
s->sh_name = put_elf_str(strsec, s->name);
1709
printf("section: f=%08x t=%08x i=%08x %s %s\n",
1714
s->reloc ? s->reloc->name : "n"
1717
/* when generating a DLL, we include relocations but we may
1719
if (file_type == TCC_OUTPUT_DLL &&
1720
s->sh_type == SHT_RELX &&
1721
!(s->sh_flags & SHF_ALLOC)) {
1722
/* //gr: avoid bogus relocs for empty (debug) sections */
1723
if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1724
prepare_dynamic_rel(s1, s);
1725
else if (s1->do_debug)
1726
s->sh_size = s->data_offset;
1727
} else if (s1->do_debug ||
1728
file_type == TCC_OUTPUT_OBJ ||
1729
(s->sh_flags & SHF_ALLOC) ||
1730
i == (s1->nb_sections - 1)) {
1731
/* we output all sections if debug or object file */
1732
s->sh_size = s->data_offset;
1736
/* allocate program segment headers */
1737
phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1739
if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1740
file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1745
/* compute section to program header mapping */
1746
if (s1->has_text_addr) {
1747
int a_offset, p_offset;
1748
addr = s1->text_addr;
1749
/* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1751
a_offset = (int) (addr & (s1->section_align - 1));
1752
p_offset = file_offset & (s1->section_align - 1);
1753
if (a_offset < p_offset)
1754
a_offset += s1->section_align;
1755
file_offset += (a_offset - p_offset);
1757
if (file_type == TCC_OUTPUT_DLL)
1760
addr = ELF_START_ADDR;
1761
/* compute address after headers */
1762
addr += (file_offset & (s1->section_align - 1));
1765
/* dynamic relocation table information, for .dynamic section */
1769
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1770
bss_addr = bss_size = 0;
1772
/* leave one program header for the program interpreter */
1775
ph += 1 + HAVE_PHDR;
1777
for(j = 0; j < 2; j++) {
1778
ph->p_type = PT_LOAD;
1780
ph->p_flags = PF_R | PF_X;
1782
ph->p_flags = PF_R | PF_W;
1783
ph->p_align = s1->section_align;
1785
/* we do the following ordering: interp, symbol tables,
1786
relocations, progbits, nobits */
1787
/* XXX: do faster and simpler sorting */
1788
for(k = 0; k < 5; k++) {
1789
for(i = 1; i < s1->nb_sections; i++) {
1790
s = s1->sections[i];
1791
/* compute if section should be included */
1793
if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1797
if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1798
(SHF_ALLOC | SHF_WRITE))
1804
} else if (s->sh_type == SHT_DYNSYM ||
1805
s->sh_type == SHT_STRTAB ||
1806
s->sh_type == SHT_HASH) {
1809
} else if (s->sh_type == SHT_RELX) {
1812
} else if (s->sh_type == SHT_NOBITS) {
1819
section_order[sh_order_index++] = i;
1821
/* section matches: we align it and add its size */
1823
addr = (addr + s->sh_addralign - 1) &
1824
~(s->sh_addralign - 1);
1825
file_offset += (int) ( addr - tmp );
1826
s->sh_offset = file_offset;
1829
/* update program header infos */
1830
if (ph->p_offset == 0) {
1831
ph->p_offset = file_offset;
1833
ph->p_paddr = ph->p_vaddr;
1835
/* update dynamic relocation infos */
1836
if (s->sh_type == SHT_RELX) {
1837
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1838
if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1840
rel_size += s->sh_size; // XXX only first rel.
1842
if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1844
bss_size = s->sh_size; // XXX only first rel.
1849
rel_size += s->sh_size;
1853
if (s->sh_type != SHT_NOBITS)
1854
file_offset += s->sh_size;
1857
ph->p_filesz = file_offset - ph->p_offset;
1858
ph->p_memsz = addr - ph->p_vaddr;
1861
if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1862
/* if in the middle of a page, we duplicate the page in
1863
memory so that one copy is RX and the other is RW */
1864
if ((addr & (s1->section_align - 1)) != 0)
1865
addr += s1->section_align;
1867
addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1868
file_offset = (file_offset + s1->section_align - 1) &
1869
~(s1->section_align - 1);
1874
/* if interpreter, then add corresponing program header */
1878
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1880
int len = phnum * sizeof(ElfW(Phdr));
1882
ph->p_type = PT_PHDR;
1883
ph->p_offset = sizeof(ElfW(Ehdr));
1884
ph->p_vaddr = interp->sh_addr - len;
1885
ph->p_paddr = ph->p_vaddr;
1886
ph->p_filesz = ph->p_memsz = len;
1887
ph->p_flags = PF_R | PF_X;
1888
ph->p_align = 4; // interp->sh_addralign;
1893
ph->p_type = PT_INTERP;
1894
ph->p_offset = interp->sh_offset;
1895
ph->p_vaddr = interp->sh_addr;
1896
ph->p_paddr = ph->p_vaddr;
1897
ph->p_filesz = interp->sh_size;
1898
ph->p_memsz = interp->sh_size;
1900
ph->p_align = interp->sh_addralign;
1903
/* if dynamic section, then add corresponing program header */
1907
ph = &phdr[phnum - 1];
1909
ph->p_type = PT_DYNAMIC;
1910
ph->p_offset = dynamic->sh_offset;
1911
ph->p_vaddr = dynamic->sh_addr;
1912
ph->p_paddr = ph->p_vaddr;
1913
ph->p_filesz = dynamic->sh_size;
1914
ph->p_memsz = dynamic->sh_size;
1915
ph->p_flags = PF_R | PF_W;
1916
ph->p_align = dynamic->sh_addralign;
1918
/* put GOT dynamic section address */
1919
put32(s1->got->data, dynamic->sh_addr);
1921
/* relocate the PLT */
1922
if (file_type == TCC_OUTPUT_EXE
1923
#if defined(TCC_OUTPUT_DLL_WITH_PLT)
1924
|| file_type == TCC_OUTPUT_DLL
1930
p_end = p + s1->plt->data_offset;
1932
#if defined(TCC_TARGET_I386)
1933
put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1934
put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1937
put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1940
#elif defined(TCC_TARGET_X86_64)
1941
int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1942
put32(p + 2, get32(p + 2) + x);
1943
put32(p + 8, get32(p + 8) + x - 6);
1946
put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1949
#elif defined(TCC_TARGET_ARM)
1951
x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1954
put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1957
#elif defined(TCC_TARGET_C67)
1960
#error unsupported CPU
1965
/* relocate symbols in .dynsym */
1966
sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
1967
for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
1970
if (sym->st_shndx == SHN_UNDEF) {
1971
/* relocate to the PLT if the symbol corresponds
1974
sym->st_value += s1->plt->sh_addr;
1975
} else if (sym->st_shndx < SHN_LORESERVE) {
1976
/* do symbol relocation */
1977
sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
1981
/* put dynamic section entries */
1982
dynamic->data_offset = saved_dynamic_data_offset;
1983
put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
1984
put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
1985
put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
1986
put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
1987
put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
1988
#ifdef TCC_TARGET_X86_64
1989
put_dt(dynamic, DT_RELA, rel_addr);
1990
put_dt(dynamic, DT_RELASZ, rel_size);
1991
put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
1993
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1994
put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
1995
put_dt(dynamic, DT_PLTRELSZ, rel_size);
1996
put_dt(dynamic, DT_JMPREL, rel_addr);
1997
put_dt(dynamic, DT_PLTREL, DT_REL);
1998
put_dt(dynamic, DT_REL, bss_addr);
1999
put_dt(dynamic, DT_RELSZ, bss_size);
2001
put_dt(dynamic, DT_REL, rel_addr);
2002
put_dt(dynamic, DT_RELSZ, rel_size);
2003
put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2007
put_dt(dynamic, DT_DEBUG, 0);
2008
put_dt(dynamic, DT_NULL, 0);
2011
ehdr.e_phentsize = sizeof(ElfW(Phdr));
2012
ehdr.e_phnum = phnum;
2013
ehdr.e_phoff = sizeof(ElfW(Ehdr));
2016
/* all other sections come after */
2017
for(i = 1; i < s1->nb_sections; i++) {
2018
s = s1->sections[i];
2019
if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2021
section_order[sh_order_index++] = i;
2023
file_offset = (file_offset + s->sh_addralign - 1) &
2024
~(s->sh_addralign - 1);
2025
s->sh_offset = file_offset;
2026
if (s->sh_type != SHT_NOBITS)
2027
file_offset += s->sh_size;
2030
/* if building executable or DLL, then relocate each section
2031
except the GOT which is already relocated */
2032
if (file_type != TCC_OUTPUT_OBJ) {
2033
relocate_syms(s1, 0);
2035
if (s1->nb_errors != 0) {
2041
/* relocate sections */
2042
/* XXX: ignore sections with allocated relocations ? */
2043
for(i = 1; i < s1->nb_sections; i++) {
2044
s = s1->sections[i];
2045
if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
2046
relocate_section(s1, s);
2049
/* relocate relocation entries if the relocation tables are
2050
allocated in the executable */
2051
for(i = 1; i < s1->nb_sections; i++) {
2052
s = s1->sections[i];
2053
if ((s->sh_flags & SHF_ALLOC) &&
2054
s->sh_type == SHT_RELX) {
2055
relocate_rel(s1, s);
2059
/* get entry point address */
2060
if (file_type == TCC_OUTPUT_EXE)
2061
ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
2063
ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2065
if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2068
/* write elf file */
2069
if (file_type == TCC_OUTPUT_OBJ)
2074
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2076
tcc_error_noabort("could not write '%s'", filename);
2079
f = fdopen(fd, "wb");
2081
printf("<- %s\n", filename);
2083
#ifdef TCC_TARGET_COFF
2084
if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2085
tcc_output_coff(s1, f);
2088
if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2089
sort_syms(s1, symtab_section);
2092
file_offset = (file_offset + 3) & -4;
2095
ehdr.e_ident[0] = ELFMAG0;
2096
ehdr.e_ident[1] = ELFMAG1;
2097
ehdr.e_ident[2] = ELFMAG2;
2098
ehdr.e_ident[3] = ELFMAG3;
2099
ehdr.e_ident[4] = ELFCLASSW;
2100
ehdr.e_ident[5] = ELFDATA2LSB;
2101
ehdr.e_ident[6] = EV_CURRENT;
2102
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2103
ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2105
#ifdef TCC_TARGET_ARM
2107
ehdr.e_ident[EI_OSABI] = 0;
2108
ehdr.e_flags = 4 << 24;
2110
ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2115
case TCC_OUTPUT_EXE:
2116
ehdr.e_type = ET_EXEC;
2118
case TCC_OUTPUT_DLL:
2119
ehdr.e_type = ET_DYN;
2121
case TCC_OUTPUT_OBJ:
2122
ehdr.e_type = ET_REL;
2125
ehdr.e_machine = EM_TCC_TARGET;
2126
ehdr.e_version = EV_CURRENT;
2127
ehdr.e_shoff = file_offset;
2128
ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2129
ehdr.e_shentsize = sizeof(ElfW(Shdr));
2130
ehdr.e_shnum = shnum;
2131
ehdr.e_shstrndx = shnum - 1;
2133
fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2134
fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2135
offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2137
for(i=1;i<s1->nb_sections;i++) {
2138
s = s1->sections[section_order[i]];
2139
if (s->sh_type != SHT_NOBITS) {
2140
if (s->sh_type == SHT_DYNSYM)
2141
patch_dynsym_undef(s1, s);
2142
while (offset < s->sh_offset) {
2147
fwrite(s->data, 1, size, f);
2152
/* output section headers */
2153
while (offset < ehdr.e_shoff) {
2158
for(i=0;i<s1->nb_sections;i++) {
2160
memset(sh, 0, sizeof(ElfW(Shdr)));
2161
s = s1->sections[i];
2163
sh->sh_name = s->sh_name;
2164
sh->sh_type = s->sh_type;
2165
sh->sh_flags = s->sh_flags;
2166
sh->sh_entsize = s->sh_entsize;
2167
sh->sh_info = s->sh_info;
2169
sh->sh_link = s->link->sh_num;
2170
sh->sh_addralign = s->sh_addralign;
2171
sh->sh_addr = s->sh_addr;
2172
sh->sh_offset = s->sh_offset;
2173
sh->sh_size = s->sh_size;
2175
fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2178
tcc_output_binary(s1, f, section_order);
2184
tcc_free(s1->symtab_to_dynsym);
2185
tcc_free(section_order);
2187
tcc_free(s1->got_offsets);
2191
LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2194
#ifdef TCC_TARGET_PE
2195
if (s->output_type != TCC_OUTPUT_OBJ) {
2196
ret = pe_output_file(s, filename);
2200
ret = elf_output_file(s, filename);
2205
static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2209
data = tcc_malloc(size);
2210
lseek(fd, file_offset, SEEK_SET);
2211
read(fd, data, size);
2215
typedef struct SectionMergeInfo {
2216
Section *s; /* corresponding existing section */
2217
unsigned long offset; /* offset of the new section in the existing section */
2218
uint8_t new_section; /* true if section 's' was added */
2219
uint8_t link_once; /* true if link once section */
2222
/* load an object file and merge it with current files */
2223
/* XXX: handle correctly stab (debug) info */
2224
ST_FUNC int tcc_load_object_file(TCCState *s1,
2225
int fd, unsigned long file_offset)
2228
ElfW(Shdr) *shdr, *sh;
2229
int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2230
unsigned char *strsec, *strtab;
2231
int *old_to_new_syms;
2232
char *sh_name, *name;
2233
SectionMergeInfo *sm_table, *sm;
2234
ElfW(Sym) *sym, *symtab;
2235
ElfW_Rel *rel, *rel_end;
2241
stab_index = stabstr_index = 0;
2243
if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2245
if (ehdr.e_ident[0] != ELFMAG0 ||
2246
ehdr.e_ident[1] != ELFMAG1 ||
2247
ehdr.e_ident[2] != ELFMAG2 ||
2248
ehdr.e_ident[3] != ELFMAG3)
2250
/* test if object file */
2251
if (ehdr.e_type != ET_REL)
2253
/* test CPU specific stuff */
2254
if (ehdr.e_ident[5] != ELFDATA2LSB ||
2255
ehdr.e_machine != EM_TCC_TARGET) {
2257
tcc_error_noabort("invalid object file");
2261
shdr = load_data(fd, file_offset + ehdr.e_shoff,
2262
sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2263
sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2265
/* load section names */
2266
sh = &shdr[ehdr.e_shstrndx];
2267
strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2269
/* load symtab and strtab */
2270
old_to_new_syms = NULL;
2274
for(i = 1; i < ehdr.e_shnum; i++) {
2276
if (sh->sh_type == SHT_SYMTAB) {
2278
tcc_error_noabort("object must contain only one symtab");
2283
nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2284
symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2285
sm_table[i].s = symtab_section;
2287
/* now load strtab */
2288
sh = &shdr[sh->sh_link];
2289
strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2293
/* now examine each section and try to merge its content with the
2295
for(i = 1; i < ehdr.e_shnum; i++) {
2296
/* no need to examine section name strtab */
2297
if (i == ehdr.e_shstrndx)
2300
sh_name = strsec + sh->sh_name;
2301
/* ignore sections types we do not handle */
2302
if (sh->sh_type != SHT_PROGBITS &&
2303
sh->sh_type != SHT_RELX &&
2305
sh->sh_type != SHT_ARM_EXIDX &&
2307
sh->sh_type != SHT_NOBITS &&
2308
sh->sh_type != SHT_PREINIT_ARRAY &&
2309
sh->sh_type != SHT_INIT_ARRAY &&
2310
sh->sh_type != SHT_FINI_ARRAY &&
2311
strcmp(sh_name, ".stabstr")
2314
if (sh->sh_addralign < 1)
2315
sh->sh_addralign = 1;
2316
/* find corresponding section, if any */
2317
for(j = 1; j < s1->nb_sections;j++) {
2318
s = s1->sections[j];
2319
if (!strcmp(s->name, sh_name)) {
2320
if (!strncmp(sh_name, ".gnu.linkonce",
2321
sizeof(".gnu.linkonce") - 1)) {
2322
/* if a 'linkonce' section is already present, we
2323
do not add it again. It is a little tricky as
2324
symbols can still be defined in
2326
sm_table[i].link_once = 1;
2333
/* not found: create new section */
2334
s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2335
/* take as much info as possible from the section. sh_link and
2336
sh_info will be updated later */
2337
s->sh_addralign = sh->sh_addralign;
2338
s->sh_entsize = sh->sh_entsize;
2339
sm_table[i].new_section = 1;
2341
if (sh->sh_type != s->sh_type) {
2342
tcc_error_noabort("invalid section type");
2346
/* align start of section */
2347
offset = s->data_offset;
2349
if (0 == strcmp(sh_name, ".stab")) {
2353
if (0 == strcmp(sh_name, ".stabstr")) {
2358
size = sh->sh_addralign - 1;
2359
offset = (offset + size) & ~size;
2360
if (sh->sh_addralign > s->sh_addralign)
2361
s->sh_addralign = sh->sh_addralign;
2362
s->data_offset = offset;
2364
sm_table[i].offset = offset;
2366
/* concatenate sections */
2368
if (sh->sh_type != SHT_NOBITS) {
2370
lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2371
ptr = section_ptr_add(s, size);
2372
read(fd, ptr, size);
2374
s->data_offset += size;
2379
/* //gr relocate stab strings */
2380
if (stab_index && stabstr_index) {
2383
s = sm_table[stab_index].s;
2384
a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2385
b = (Stab_Sym *)(s->data + s->data_offset);
2386
o = sm_table[stabstr_index].offset;
2388
a->n_strx += o, a++;
2391
/* second short pass to update sh_link and sh_info fields of new
2393
for(i = 1; i < ehdr.e_shnum; i++) {
2395
if (!s || !sm_table[i].new_section)
2398
if (sh->sh_link > 0)
2399
s->link = sm_table[sh->sh_link].s;
2400
if (sh->sh_type == SHT_RELX) {
2401
s->sh_info = sm_table[sh->sh_info].s->sh_num;
2402
/* update backward link */
2403
s1->sections[s->sh_info]->reloc = s;
2408
/* resolve symbols */
2409
old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2412
for(i = 1; i < nb_syms; i++, sym++) {
2413
if (sym->st_shndx != SHN_UNDEF &&
2414
sym->st_shndx < SHN_LORESERVE) {
2415
sm = &sm_table[sym->st_shndx];
2416
if (sm->link_once) {
2417
/* if a symbol is in a link once section, we use the
2418
already defined symbol. It is very important to get
2419
correct relocations */
2420
if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2421
name = strtab + sym->st_name;
2422
sym_index = find_elf_sym(symtab_section, name);
2424
old_to_new_syms[i] = sym_index;
2428
/* if no corresponding section added, no need to add symbol */
2431
/* convert section number */
2432
sym->st_shndx = sm->s->sh_num;
2434
sym->st_value += sm->offset;
2437
name = strtab + sym->st_name;
2438
sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2439
sym->st_info, sym->st_other,
2440
sym->st_shndx, name);
2441
old_to_new_syms[i] = sym_index;
2444
/* third pass to patch relocation entries */
2445
for(i = 1; i < ehdr.e_shnum; i++) {
2450
offset = sm_table[i].offset;
2451
switch(s->sh_type) {
2453
/* take relocation offset information */
2454
offseti = sm_table[sh->sh_info].offset;
2455
rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2456
for(rel = (ElfW_Rel *)(s->data + offset);
2461
/* convert symbol index */
2462
type = ELFW(R_TYPE)(rel->r_info);
2463
sym_index = ELFW(R_SYM)(rel->r_info);
2464
/* NOTE: only one symtab assumed */
2465
if (sym_index >= nb_syms)
2467
sym_index = old_to_new_syms[sym_index];
2468
/* ignore link_once in rel section. */
2469
if (!sym_index && !sm->link_once
2470
#ifdef TCC_TARGET_ARM
2471
&& type != R_ARM_V4BX
2475
tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2476
i, strsec + sh->sh_name, rel->r_offset);
2479
rel->r_info = ELFW(R_INFO)(sym_index, type);
2480
/* offset the relocation offset */
2481
rel->r_offset += offseti;
2493
tcc_free(old_to_new_syms);
2500
typedef struct ArchiveHeader {
2501
char ar_name[16]; /* name of this member */
2502
char ar_date[12]; /* file mtime */
2503
char ar_uid[6]; /* owner uid; printed as decimal */
2504
char ar_gid[6]; /* owner gid; printed as decimal */
2505
char ar_mode[8]; /* file mode, printed as octal */
2506
char ar_size[10]; /* file size, printed as decimal */
2507
char ar_fmag[2]; /* should contain ARFMAG */
2510
static int get_be32(const uint8_t *b)
2512
return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2515
/* load only the objects which resolve undefined symbols */
2516
static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2518
int i, bound, nsyms, sym_index, off, ret;
2520
const char *ar_names, *p;
2521
const uint8_t *ar_index;
2524
data = tcc_malloc(size);
2525
if (read(fd, data, size) != size)
2527
nsyms = get_be32(data);
2528
ar_index = data + 4;
2529
ar_names = ar_index + nsyms * 4;
2533
for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2534
sym_index = find_elf_sym(symtab_section, p);
2536
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2537
if(sym->st_shndx == SHN_UNDEF) {
2538
off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2540
printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2543
lseek(fd, off, SEEK_SET);
2544
if(tcc_load_object_file(s1, fd, off) < 0) {
2559
/* load a '.a' file */
2560
ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2567
unsigned long file_offset;
2569
/* skip magic which was already checked */
2570
read(fd, magic, sizeof(magic));
2573
len = read(fd, &hdr, sizeof(hdr));
2576
if (len != sizeof(hdr)) {
2577
tcc_error_noabort("invalid archive");
2580
memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2581
ar_size[sizeof(hdr.ar_size)] = '\0';
2582
size = strtol(ar_size, NULL, 0);
2583
memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2584
for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2585
if (ar_name[i] != ' ')
2588
ar_name[i + 1] = '\0';
2589
// printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2590
file_offset = lseek(fd, 0, SEEK_CUR);
2592
size = (size + 1) & ~1;
2593
if (!strcmp(ar_name, "/")) {
2594
/* coff symbol table : we handle it */
2595
if(s1->alacarte_link)
2596
return tcc_load_alacarte(s1, fd, size);
2597
} else if (!strcmp(ar_name, "//") ||
2598
!strcmp(ar_name, "__.SYMDEF") ||
2599
!strcmp(ar_name, "__.SYMDEF/") ||
2600
!strcmp(ar_name, "ARFILENAMES/")) {
2601
/* skip symbol table or archive names */
2603
if (tcc_load_object_file(s1, fd, file_offset) < 0)
2606
lseek(fd, file_offset + size, SEEK_SET);
2611
#ifndef TCC_TARGET_PE
2612
/* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2613
is referenced by the user (so it should be added as DT_NEEDED in
2614
the generated ELF file) */
2615
ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2618
ElfW(Shdr) *shdr, *sh, *sh1;
2619
int i, j, nb_syms, nb_dts, sym_bind, ret;
2620
ElfW(Sym) *sym, *dynsym;
2621
ElfW(Dyn) *dt, *dynamic;
2622
unsigned char *dynstr;
2623
const char *name, *soname;
2624
DLLReference *dllref;
2626
read(fd, &ehdr, sizeof(ehdr));
2628
/* test CPU specific stuff */
2629
if (ehdr.e_ident[5] != ELFDATA2LSB ||
2630
ehdr.e_machine != EM_TCC_TARGET) {
2631
tcc_error_noabort("bad architecture");
2636
shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2638
/* load dynamic section and dynamic symbols */
2642
dynsym = NULL; /* avoid warning */
2643
dynstr = NULL; /* avoid warning */
2644
for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2645
switch(sh->sh_type) {
2647
nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2648
dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2651
nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2652
dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2653
sh1 = &shdr[sh->sh_link];
2654
dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2661
/* compute the real library name */
2662
soname = tcc_basename(filename);
2664
for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2665
if (dt->d_tag == DT_SONAME) {
2666
soname = dynstr + dt->d_un.d_val;
2670
/* if the dll is already loaded, do not load it */
2671
for(i = 0; i < s1->nb_loaded_dlls; i++) {
2672
dllref = s1->loaded_dlls[i];
2673
if (!strcmp(soname, dllref->name)) {
2674
/* but update level if needed */
2675
if (level < dllref->level)
2676
dllref->level = level;
2682
// printf("loading dll '%s'\n", soname);
2684
/* add the dll and its level */
2685
dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2686
dllref->level = level;
2687
strcpy(dllref->name, soname);
2688
dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2690
/* add dynamic symbols in dynsym_section */
2691
for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2692
sym_bind = ELFW(ST_BIND)(sym->st_info);
2693
if (sym_bind == STB_LOCAL)
2695
name = dynstr + sym->st_name;
2696
add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2697
sym->st_info, sym->st_other, sym->st_shndx, name);
2700
/* load all referenced DLLs */
2701
for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2704
name = dynstr + dt->d_un.d_val;
2705
for(j = 0; j < s1->nb_loaded_dlls; j++) {
2706
dllref = s1->loaded_dlls[j];
2707
if (!strcmp(name, dllref->name))
2708
goto already_loaded;
2710
if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2711
tcc_error_noabort("referenced dll '%s' not found", name);
2728
#define LD_TOK_NAME 256
2729
#define LD_TOK_EOF (-1)
2731
/* return next ld script token */
2732
static int ld_next(TCCState *s1, char *name, int name_size)
2750
file->buf_ptr = parse_comment(file->buf_ptr);
2751
ch = file->buf_ptr[0];
2759
/* case 'a' ... 'z': */
2786
/* case 'A' ... 'z': */
2821
if (!((ch >= 'a' && ch <= 'z') ||
2822
(ch >= 'A' && ch <= 'Z') ||
2823
(ch >= '0' && ch <= '9') ||
2824
strchr("/.-_+=$:\\,~", ch)))
2826
if ((q - name) < name_size - 1) {
2843
printf("tok=%c %d\n", c, c);
2844
if (c == LD_TOK_NAME)
2845
printf(" name=%s\n", name);
2851
* Extract the file name from the library name
2853
* /!\ No test on filename capacity, be careful
2855
static void libname_to_filename(TCCState *s1, const char libname[], char filename[])
2857
if (!s1->static_link) {
2858
sprintf(filename, "lib%s.so", libname);
2860
sprintf(filename, "lib%s.a", libname);
2864
static int ld_add_file(TCCState *s1, const char filename[])
2868
ret = tcc_add_file_internal(s1, filename, 0);
2870
ret = tcc_add_dll(s1, filename, 0);
2874
static inline int new_undef_syms(void)
2877
ret = new_undef_sym;
2882
static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
2884
char filename[1024], libname[1024];
2885
int t, group, nblibs = 0, ret = 0;
2888
group = !strcmp(cmd, "GROUP");
2891
t = ld_next(s1, filename, sizeof(filename));
2894
t = ld_next(s1, filename, sizeof(filename));
2897
if (t == LD_TOK_EOF) {
2898
tcc_error_noabort("unexpected end of file");
2900
goto lib_parse_error;
2901
} else if (t == ')') {
2903
} else if (t == '-') {
2904
t = ld_next(s1, filename, sizeof(filename));
2905
if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
2906
tcc_error_noabort("library name expected");
2908
goto lib_parse_error;
2910
strcpy(libname, &filename[1]);
2911
libname_to_filename(s1, libname, filename);
2912
} else if (t != LD_TOK_NAME) {
2913
tcc_error_noabort("filename expected");
2915
goto lib_parse_error;
2917
if (!strcmp(filename, "AS_NEEDED")) {
2918
ret = ld_add_file_list(s1, cmd, 1);
2920
goto lib_parse_error;
2922
/* TODO: Implement AS_NEEDED support. Ignore it for now */
2924
ret = ld_add_file(s1, filename);
2926
goto lib_parse_error;
2928
/* Add the filename *and* the libname to avoid future conversions */
2929
dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
2930
if (libname[0] != '\0')
2931
dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
2935
t = ld_next(s1, filename, sizeof(filename));
2937
t = ld_next(s1, filename, sizeof(filename));
2940
if (group && !as_needed) {
2941
while (new_undef_syms()) {
2944
for (i = 0; i < nblibs; i ++)
2945
ld_add_file(s1, libs[i]);
2949
dynarray_reset(&libs, &nblibs);
2953
/* interpret a subset of GNU ldscripts to handle the dummy libc.so
2955
ST_FUNC int tcc_load_ldscript(TCCState *s1)
2958
char filename[1024];
2961
ch = file->buf_ptr[0];
2964
t = ld_next(s1, cmd, sizeof(cmd));
2965
if (t == LD_TOK_EOF)
2967
else if (t != LD_TOK_NAME)
2969
if (!strcmp(cmd, "INPUT") ||
2970
!strcmp(cmd, "GROUP")) {
2971
ret = ld_add_file_list(s1, cmd, 0);
2974
} else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
2975
!strcmp(cmd, "TARGET")) {
2976
/* ignore some commands */
2977
t = ld_next(s1, cmd, sizeof(cmd));
2981
t = ld_next(s1, filename, sizeof(filename));
2982
if (t == LD_TOK_EOF) {
2983
tcc_error_noabort("unexpected end of file");
2985
} else if (t == ')') {
2995
#endif /* ndef TCC_TARGET_PE */