mirror of
https://github.com/frida/tinycc
synced 2025-01-12 14:49:18 +03:00
x86_64: Create proper PLT and GOT also for -run
This makes us use the normal PLT/GOT codepaths also for -run, which formerly used an on-the-side blob for the jump tables. For x86_64 only for now, arm coming up.
This commit is contained in:
parent
c4427747e6
commit
9750d0b725
3
tcc.h
3
tcc.h
@ -712,7 +712,7 @@ struct TCCState {
|
|||||||
void *write_mem;
|
void *write_mem;
|
||||||
unsigned long mem_size;
|
unsigned long mem_size;
|
||||||
# endif
|
# endif
|
||||||
# if !defined TCC_TARGET_PE && (defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM)
|
# if !defined TCC_TARGET_PE && (defined TCC_TARGET_ARM)
|
||||||
/* write PLT and GOT here */
|
/* write PLT and GOT here */
|
||||||
char *runtime_plt_and_got;
|
char *runtime_plt_and_got;
|
||||||
unsigned runtime_plt_and_got_offset;
|
unsigned runtime_plt_and_got_offset;
|
||||||
@ -1265,6 +1265,7 @@ ST_FUNC void put_stabd(int type, int other, int desc);
|
|||||||
ST_FUNC void relocate_common_syms(void);
|
ST_FUNC void relocate_common_syms(void);
|
||||||
ST_FUNC void relocate_syms(TCCState *s1, int do_resolve);
|
ST_FUNC void relocate_syms(TCCState *s1, int do_resolve);
|
||||||
ST_FUNC void relocate_section(TCCState *s1, Section *s);
|
ST_FUNC void relocate_section(TCCState *s1, Section *s);
|
||||||
|
ST_FUNC void relocate_plt(TCCState *s1);
|
||||||
|
|
||||||
ST_FUNC void tcc_add_linker_symbols(TCCState *s1);
|
ST_FUNC void tcc_add_linker_symbols(TCCState *s1);
|
||||||
ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset);
|
ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset);
|
||||||
|
37
tccelf.c
37
tccelf.c
@ -851,8 +851,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
|
|||||||
/* We've put the PLT slot offset into r_addend when generating
|
/* We've put the PLT slot offset into r_addend when generating
|
||||||
it, and that's what we must use as relocation value (adjusted
|
it, and that's what we must use as relocation value (adjusted
|
||||||
by section offset of course). */
|
by section offset of course). */
|
||||||
if (s1->output_type != TCC_OUTPUT_MEMORY)
|
val = s1->plt->sh_addr + rel->r_addend;
|
||||||
val = s1->plt->sh_addr + rel->r_addend;
|
|
||||||
/* fallthrough. */
|
/* fallthrough. */
|
||||||
|
|
||||||
plt32pc32:
|
plt32pc32:
|
||||||
@ -878,7 +877,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
|
|||||||
case R_X86_64_GLOB_DAT:
|
case R_X86_64_GLOB_DAT:
|
||||||
case R_X86_64_JUMP_SLOT:
|
case R_X86_64_JUMP_SLOT:
|
||||||
/* They don't need addend */
|
/* They don't need addend */
|
||||||
*(int *)ptr = val - rel->r_addend;
|
*(addr_t *)ptr = val - rel->r_addend;
|
||||||
break;
|
break;
|
||||||
case R_X86_64_GOTPCREL:
|
case R_X86_64_GOTPCREL:
|
||||||
#ifdef TCC_HAS_RUNTIME_PLTGOT
|
#ifdef TCC_HAS_RUNTIME_PLTGOT
|
||||||
@ -1042,7 +1041,7 @@ static unsigned long put_got_entry(TCCState *s1,
|
|||||||
if (!s1->got)
|
if (!s1->got)
|
||||||
build_got(s1);
|
build_got(s1);
|
||||||
|
|
||||||
need_plt_entry = s1->dynsym &&
|
need_plt_entry =
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
(reloc_type == R_X86_64_JUMP_SLOT);
|
(reloc_type == R_X86_64_JUMP_SLOT);
|
||||||
#elif defined(TCC_TARGET_I386)
|
#elif defined(TCC_TARGET_I386)
|
||||||
@ -1053,6 +1052,13 @@ static unsigned long put_got_entry(TCCState *s1,
|
|||||||
0;
|
0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (need_plt_entry && !s1->plt) {
|
||||||
|
/* add PLT */
|
||||||
|
s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
|
||||||
|
SHF_ALLOC | SHF_EXECINSTR);
|
||||||
|
s1->plt->sh_entsize = 4;
|
||||||
|
}
|
||||||
|
|
||||||
/* If a got/plt entry already exists for that symbol, no need to add one */
|
/* If a got/plt entry already exists for that symbol, no need to add one */
|
||||||
if (sym_index < s1->nb_sym_attrs) {
|
if (sym_index < s1->nb_sym_attrs) {
|
||||||
if (need_plt_entry && s1->sym_attrs[sym_index].plt_offset)
|
if (need_plt_entry && s1->sym_attrs[sym_index].plt_offset)
|
||||||
@ -1067,10 +1073,9 @@ static unsigned long put_got_entry(TCCState *s1,
|
|||||||
if (!need_plt_entry)
|
if (!need_plt_entry)
|
||||||
symattr->got_offset = s1->got->data_offset;
|
symattr->got_offset = s1->got->data_offset;
|
||||||
|
|
||||||
if (s1->dynsym) {
|
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||||
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
name = (char *) symtab_section->link->data + sym->st_name;
|
||||||
name = (char *) symtab_section->link->data + sym->st_name;
|
offset = sym->st_value;
|
||||||
offset = sym->st_value;
|
|
||||||
#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
|
#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
|
||||||
if (need_plt_entry) {
|
if (need_plt_entry) {
|
||||||
Section *plt;
|
Section *plt;
|
||||||
@ -1165,10 +1170,13 @@ static unsigned long put_got_entry(TCCState *s1,
|
|||||||
offset = plt->data_offset - 16;
|
offset = plt->data_offset - 16;
|
||||||
}
|
}
|
||||||
#elif defined(TCC_TARGET_C67)
|
#elif defined(TCC_TARGET_C67)
|
||||||
|
if (s1->dynsym) {
|
||||||
tcc_error("C67 got not implemented");
|
tcc_error("C67 got not implemented");
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
#error unsupported CPU
|
#error unsupported CPU
|
||||||
#endif
|
#endif
|
||||||
|
if (s1->dynsym) {
|
||||||
/* XXX This might generate multiple syms for name. */
|
/* XXX This might generate multiple syms for name. */
|
||||||
index = put_elf_sym(s1->dynsym, offset,
|
index = put_elf_sym(s1->dynsym, offset,
|
||||||
size, info, 0, sym->st_shndx, name);
|
size, info, 0, sym->st_shndx, name);
|
||||||
@ -1316,8 +1324,7 @@ ST_FUNC void build_got_entries(TCCState *s1)
|
|||||||
reloc_type = R_X86_64_JUMP_SLOT;
|
reloc_type = R_X86_64_JUMP_SLOT;
|
||||||
ofs = put_got_entry(s1, reloc_type, sym->st_size,
|
ofs = put_got_entry(s1, reloc_type, sym->st_size,
|
||||||
sym->st_info, sym_index);
|
sym->st_info, sym_index);
|
||||||
if (type == R_X86_64_PLT32
|
if (type == R_X86_64_PLT32)
|
||||||
&& s1->output_type != TCC_OUTPUT_MEMORY)
|
|
||||||
/* We store the place of the generated PLT slot
|
/* We store the place of the generated PLT slot
|
||||||
in our addend. */
|
in our addend. */
|
||||||
rel->r_addend += ofs;
|
rel->r_addend += ofs;
|
||||||
@ -1754,10 +1761,13 @@ static void export_global_syms(TCCState *s1)
|
|||||||
|
|
||||||
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
||||||
address for PLT and GOT are known (see fill_program_header) */
|
address for PLT and GOT are known (see fill_program_header) */
|
||||||
static void relocate_plt(TCCState *s1)
|
ST_FUNC void relocate_plt(TCCState *s1)
|
||||||
{
|
{
|
||||||
uint8_t *p, *p_end;
|
uint8_t *p, *p_end;
|
||||||
|
|
||||||
|
if (!s1->plt)
|
||||||
|
return;
|
||||||
|
|
||||||
p = s1->plt->data;
|
p = s1->plt->data;
|
||||||
p_end = p + s1->plt->data_offset;
|
p_end = p + s1->plt->data_offset;
|
||||||
if (p < p_end) {
|
if (p < p_end) {
|
||||||
@ -2346,11 +2356,6 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
|||||||
dynamic->link = dynstr;
|
dynamic->link = dynstr;
|
||||||
dynamic->sh_entsize = sizeof(ElfW(Dyn));
|
dynamic->sh_entsize = sizeof(ElfW(Dyn));
|
||||||
|
|
||||||
/* add PLT */
|
|
||||||
s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
|
|
||||||
SHF_ALLOC | SHF_EXECINSTR);
|
|
||||||
s1->plt->sh_entsize = 4;
|
|
||||||
|
|
||||||
build_got(s1);
|
build_got(s1);
|
||||||
|
|
||||||
if (file_type == TCC_OUTPUT_EXE) {
|
if (file_type == TCC_OUTPUT_EXE) {
|
||||||
|
1
tccrun.c
1
tccrun.c
@ -197,6 +197,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr)
|
|||||||
if (s->reloc)
|
if (s->reloc)
|
||||||
relocate_section(s1, s);
|
relocate_section(s1, s);
|
||||||
}
|
}
|
||||||
|
relocate_plt(s1);
|
||||||
|
|
||||||
for(i = 1; i < s1->nb_sections; i++) {
|
for(i = 1; i < s1->nb_sections; i++) {
|
||||||
s = s1->sections[i];
|
s = s1->sections[i];
|
||||||
|
Loading…
Reference in New Issue
Block a user