From d79caa9ff6d42e11a8f21e9c22aefbfa4c25d7ed Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Mon, 2 Jul 2018 01:54:45 +0200 Subject: [PATCH] x86-64: Fix calls via absolute function pointers linkers don't treat relocations using symindex 0 (undefined) very well, it can't be misused as indicator for an absolute number. Just don't bother with special casing this, rather emit an indirect call/jump right away. ARM64 needs the same (and didn't handle calls via constant absolute func pointers before). The testcase as is doesn't fail without the patch, it actually needs separate compilation (to -fPIC .o file, then to shared lib) to fail. --- arm64-gen.c | 4 ++-- tests/tests2/07_function.c | 5 +++++ x86_64-gen.c | 15 ++++----------- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/arm64-gen.c b/arm64-gen.c index 26cf5d1..efe4246 100644 --- a/arm64-gen.c +++ b/arm64-gen.c @@ -580,8 +580,8 @@ ST_FUNC void store(int r, SValue *sv) static void arm64_gen_bl_or_b(int b) { - if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { - assert(!b && (vtop->r & VT_SYM)); + if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (vtop->r & VT_SYM)) { + assert(!b); greloca(cur_text_section, vtop->sym, ind, R_AARCH64_CALL26, 0); o(0x94000000); // bl . } diff --git a/tests/tests2/07_function.c b/tests/tests2/07_function.c index 0477ce1..bfb0974 100644 --- a/tests/tests2/07_function.c +++ b/tests/tests2/07_function.c @@ -15,6 +15,11 @@ void qfunc() printf("qfunc()\n"); } +void zfunc() +{ + ((void (*)(void))0) (); +} + int main() { printf("%d\n", myfunc(3)); diff --git a/x86_64-gen.c b/x86_64-gen.c index 2672e13..045dd2c 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -623,20 +623,13 @@ static void gcall_or_jmp(int is_jmp) { int r; if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && - ((vtop->r & VT_SYM) || (vtop->c.i-4) == (int)(vtop->c.i-4))) { - /* constant case */ - if (vtop->r & VT_SYM) { - /* relocation case */ + ((vtop->r & VT_SYM) && (vtop->c.i-4) == (int)(vtop->c.i-4))) { + /* constant symbolic case -> simple relocation */ #ifdef TCC_TARGET_PE - greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PC32, (int)(vtop->c.i-4)); + greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PC32, (int)(vtop->c.i-4)); #else - greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PLT32, (int)(vtop->c.i-4)); + greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PLT32, (int)(vtop->c.i-4)); #endif - } else { - /* put an empty PC32 relocation */ - put_elf_reloca(symtab_section, cur_text_section, - ind + 1, R_X86_64_PC32, 0, (int)(vtop->c.i-4)); - } oad(0xe8 + is_jmp, 0); /* call/jmp im */ } else { /* otherwise, indirect call */