x86-64: Add basic shared lib support
Initial support for shared libraries on x86-64.
This commit is contained in:
parent
5a5fee867a
commit
080ad7e62a
2 changed files with 41 additions and 37 deletions
60
tccelf.c
60
tccelf.c
|
@ -802,10 +802,19 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
|
|||
#elif defined(TCC_TARGET_X86_64)
|
||||
case R_X86_64_64:
|
||||
if (s1->output_type == TCC_OUTPUT_DLL) {
|
||||
esym_index = s1->symtab_to_dynsym[sym_index];
|
||||
qrel->r_offset = rel->r_offset;
|
||||
if (esym_index) {
|
||||
qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_64);
|
||||
qrel->r_addend = rel->r_addend;
|
||||
qrel++;
|
||||
break;
|
||||
} else {
|
||||
qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
|
||||
qrel->r_addend = *(long long *)ptr + val;
|
||||
qrel++;
|
||||
}
|
||||
}
|
||||
*(long long *)ptr += val;
|
||||
break;
|
||||
case R_X86_64_32:
|
||||
|
@ -1013,6 +1022,7 @@ static void put_got_entry(TCCState *s1,
|
|||
ElfW(Sym) *sym;
|
||||
unsigned long offset;
|
||||
int *ptr;
|
||||
struct sym_attr *symattr;
|
||||
|
||||
if (!s1->got)
|
||||
build_got(s1);
|
||||
|
@ -1037,7 +1047,10 @@ static void put_got_entry(TCCState *s1,
|
|||
got_entry_present = 1;
|
||||
}
|
||||
|
||||
alloc_sym_attr(s1, sym_index)->got_offset = s1->got->data_offset;
|
||||
symattr = alloc_sym_attr(s1, sym_index);
|
||||
/* Only store the GOT offset if it's not generated for the PLT entry. */
|
||||
if (!need_plt_entry)
|
||||
symattr->got_offset = s1->got->data_offset;
|
||||
|
||||
if (s1->dynsym) {
|
||||
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||
|
@ -1048,6 +1061,7 @@ static void put_got_entry(TCCState *s1,
|
|||
Section *plt;
|
||||
uint8_t *p;
|
||||
int modrm;
|
||||
unsigned long relofs;
|
||||
|
||||
#if defined(TCC_OUTPUT_DLL_WITH_PLT)
|
||||
modrm = 0x25;
|
||||
|
@ -1072,12 +1086,21 @@ static void put_got_entry(TCCState *s1,
|
|||
put32(p + 8, PTR_SIZE * 2);
|
||||
}
|
||||
|
||||
/* The PLT slot refers to the relocation entry it needs
|
||||
via offset. The reloc entry is created below, so its
|
||||
offset is the current data_offset. */
|
||||
relofs = s1->got->reloc ? s1->got->reloc->data_offset : 0;
|
||||
p = section_ptr_add(plt, 16);
|
||||
p[0] = 0xff; /* jmp *(got + x) */
|
||||
p[1] = modrm;
|
||||
put32(p + 2, s1->got->data_offset);
|
||||
p[6] = 0x68; /* push $xxx */
|
||||
put32(p + 7, (plt->data_offset - 32) >> 1);
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
/* On x86-64, the relocation is referred to by _index_. */
|
||||
put32(p + 7, relofs / sizeof (ElfW_Rel));
|
||||
#else
|
||||
put32(p + 7, relofs);
|
||||
#endif
|
||||
p[11] = 0xe9; /* jmp plt_start */
|
||||
put32(p + 12, -(plt->data_offset));
|
||||
|
||||
|
@ -1087,7 +1110,7 @@ static void put_got_entry(TCCState *s1,
|
|||
if (s1->output_type == TCC_OUTPUT_EXE)
|
||||
#endif
|
||||
offset = plt->data_offset - 16;
|
||||
s1->sym_attrs[sym_index].has_plt_entry = 1;
|
||||
symattr->has_plt_entry = 1;
|
||||
}
|
||||
#elif defined(TCC_TARGET_ARM)
|
||||
if (need_plt_entry) {
|
||||
|
@ -1109,7 +1132,7 @@ static void put_got_entry(TCCState *s1,
|
|||
put32(p+12, 0xe5bef008); /* ldr pc, [lr, #8]! */
|
||||
}
|
||||
|
||||
if (s1->sym_attrs[sym_index].plt_thumb_stub) {
|
||||
if (symattr->plt_thumb_stub) {
|
||||
p = section_ptr_add(plt, 20);
|
||||
put32(p, 0x4778); /* bx pc */
|
||||
put32(p+2, 0x46c0); /* nop */
|
||||
|
@ -1125,27 +1148,23 @@ static void put_got_entry(TCCState *s1,
|
|||
the PLT */
|
||||
if (s1->output_type == TCC_OUTPUT_EXE)
|
||||
offset = plt->data_offset - 16;
|
||||
s1->sym_attrs[sym_index].has_plt_entry = 1;
|
||||
symattr->has_plt_entry = 1;
|
||||
}
|
||||
#elif defined(TCC_TARGET_C67)
|
||||
tcc_error("C67 got not implemented");
|
||||
#else
|
||||
#error unsupported CPU
|
||||
#endif
|
||||
/* XXX This might generate multiple syms for name. */
|
||||
index = put_elf_sym(s1->dynsym, offset,
|
||||
size, info, 0, sym->st_shndx, name);
|
||||
if (got_entry_present) {
|
||||
put_elf_reloc(s1->dynsym, s1->got,
|
||||
s1->sym_attrs[sym_index].got_offset,
|
||||
reloc_type, index);
|
||||
return;
|
||||
}
|
||||
|
||||
/* put a got entry */
|
||||
/* Create the relocation (it's against the GOT for PLT
|
||||
and GOT relocs). */
|
||||
put_elf_reloc(s1->dynsym, s1->got,
|
||||
s1->got->data_offset,
|
||||
reloc_type, index);
|
||||
}
|
||||
/* And now create the GOT slot itself. */
|
||||
ptr = section_ptr_add(s1->got, PTR_SIZE);
|
||||
*ptr = 0;
|
||||
}
|
||||
|
@ -1697,20 +1716,6 @@ static void export_global_syms(TCCState *s1)
|
|||
s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
|
||||
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
|
||||
if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
|
||||
#if defined(TCC_OUTPUT_DLL_WITH_PLT)
|
||||
int type = ELFW(ST_TYPE)(sym->st_info);
|
||||
if ((type == STT_FUNC || type == STT_GNU_IFUNC)
|
||||
&& sym->st_shndx == SHN_UNDEF) {
|
||||
int visibility = ELFW(ST_BIND)(sym->st_info);
|
||||
put_got_entry(s1, R_JMP_SLOT, sym->st_size,
|
||||
ELFW(ST_INFO)(visibility, STT_FUNC),
|
||||
sym - (ElfW(Sym) *) symtab_section->data);
|
||||
} else if (type == STT_OBJECT) {
|
||||
put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size, sym->st_info,
|
||||
sym - (ElfW(Sym) *) symtab_section->data);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
name = (char *) symtab_section->link->data + sym->st_name;
|
||||
dynindex = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
|
||||
sym->st_info, 0, sym->st_shndx, name);
|
||||
|
@ -1719,7 +1724,6 @@ static void export_global_syms(TCCState *s1)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
||||
address for PLT and GOT are known (see fill_program_header) */
|
||||
|
|
|
@ -604,7 +604,7 @@ static void gcall_or_jmp(int is_jmp)
|
|||
if (vtop->r & VT_SYM) {
|
||||
/* relocation case */
|
||||
greloc(cur_text_section, vtop->sym,
|
||||
ind + 1, R_X86_64_PC32);
|
||||
ind + 1, R_X86_64_PLT32);
|
||||
} else {
|
||||
/* put an empty PC32 relocation */
|
||||
put_elf_reloc(symtab_section, cur_text_section,
|
||||
|
|
Loading…
Reference in a new issue