From 8833dcbcb071f44dcb06871b0b0a0640028eb58e Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Mon, 7 Jun 2021 15:24:03 +0900 Subject: [PATCH] Fix relocations for i386 PIC --- arch_i386.cc | 32 ++++++++++++++++---------------- test/i386-shared.sh | 45 +++++++++++++++++++++++++++++++++++++++++++++ test/i386-tls-gd.sh | 4 ++-- test/tls-gd.sh | 4 ++-- 4 files changed, 65 insertions(+), 20 deletions(-) create mode 100755 test/i386-shared.sh diff --git a/arch_i386.cc b/arch_i386.cc index 608d9586..b3743681 100644 --- a/arch_i386.cc +++ b/arch_i386.cc @@ -47,7 +47,7 @@ void PltSection::copy_buf(Context &ctx) { 0xe9, 0, 0, 0, 0, // jmp .PLT0@PC }; memcpy(ent, data, sizeof(data)); - *(u32 *)(ent + 2) = sym->get_gotplt_addr(ctx) - ctx.got->shdr.sh_addr; + *(u32 *)(ent + 2) = sym->get_gotplt_addr(ctx) - ctx.gotplt->shdr.sh_addr; } else { static const u8 data[] = { 0xff, 0x25, 0, 0, 0, 0, // jmp *foo@GOT @@ -76,7 +76,7 @@ void PltGotSection::copy_buf(Context &ctx) { for (i64 i = 0; i < symbols.size(); i++) { u8 *ent = buf + i * sizeof(data); memcpy(ent, data, sizeof(data)); - *(u32 *)(ent + 2) = symbols[i]->get_got_addr(ctx) - ctx.got->shdr.sh_addr; + *(u32 *)(ent + 2) = symbols[i]->get_got_addr(ctx) - ctx.gotplt->shdr.sh_addr; } } else { static const u8 data[] = { @@ -164,11 +164,11 @@ void InputSection::apply_reloc_alloc(Context &ctx, u8 *base) { write_val(ctx, rel.r_type, loc, val); }; -#define S (ref ? ref->frag->get_addr(ctx) : sym.get_addr(ctx)) -#define A (ref ? ref->addend : 0) -#define P (output_section->shdr.sh_addr + offset + rel.r_offset) -#define G (sym.get_got_addr(ctx) - ctx.got->shdr.sh_addr) -#define GOT ctx.got->shdr.sh_addr +#define S (ref ? ref->frag->get_addr(ctx) : sym.get_addr(ctx)) +#define A (ref ? ref->addend : 0) +#define P (output_section->shdr.sh_addr + offset + rel.r_offset) +#define G (sym.get_got_addr(ctx) - ctx.got->shdr.sh_addr) +#define GOTPLT ctx.gotplt->shdr.sh_addr switch (rel_types[i]) { case R_NONE: @@ -188,34 +188,34 @@ void InputSection::apply_reloc_alloc(Context &ctx, u8 *base) { write(S + A - P); break; case R_GOT: - write(G + A); + write(sym.get_got_addr(ctx) + A - GOTPLT); break; case R_GOTOFF: - write(S + A - GOT); + write(S + A - GOTPLT); break; case R_GOTPC: - write(GOT + A - P); + write(GOTPLT + A - P); break; case R_GOTPCREL: - write(G + GOT + A - P); + write(G + GOTPLT + A - P); break; case R_TLS_GOTIE: - write(sym.get_gottp_addr(ctx) + A - GOT); + write(sym.get_gottp_addr(ctx) + A - GOTPLT); break; case R_TLS_LE: write(S + A - ctx.tls_end); break; case R_TLS_GD: - write(sym.get_tlsgd_addr(ctx) + A - GOT); + write(sym.get_tlsgd_addr(ctx) + A - GOTPLT); break; case R_TLS_LD: - write(ctx.got->get_tlsld_addr(ctx) + A - GOT); + write(ctx.got->get_tlsld_addr(ctx) + A - GOTPLT); break; case R_TPOFF: write(S + A - ctx.tls_begin); break; case R_TLS_GOTDESC: - write(sym.get_tlsdesc_addr(ctx) + A - GOT); + write(sym.get_tlsdesc_addr(ctx) + A - GOTPLT); break; case R_TLS_GOTDESC_RELAX: { static const u8 insn[] = { @@ -241,7 +241,7 @@ void InputSection::apply_reloc_alloc(Context &ctx, u8 *base) { #undef A #undef P #undef G -#undef GOT +#undef GOTPLT } } diff --git a/test/i386-shared.sh b/test/i386-shared.sh new file mode 100755 index 00000000..663f4819 --- /dev/null +++ b/test/i386-shared.sh @@ -0,0 +1,45 @@ +#!/bin/bash +set -e +cd $(dirname $0) +echo -n "Testing $(basename -s .sh $0) ... " +t=$(pwd)/tmp/$(basename -s .sh $0) +mkdir -p $t + +cat < $t/c.c +#include + +int get_foo(); +int get_bar(); + +int baz = 2; + +int main() { + printf("%d %d %d\n", get_foo(), get_bar(), baz); +} +EOF + +clang -c -o $t/d.o $t/c.c -fno-PIC -m32 +clang -fuse-ld=`pwd`/../mold -o $t/exe $t/d.o $t/b.so -m32 +$t/exe | grep -q '5 7 2' + +clang -c -o $t/e.o $t/c.c -fPIE -m32 +clang -fuse-ld=`pwd`/../mold -o $t/exe $t/e.o $t/b.so -m32 +$t/exe | grep -q '5 7 2' + +clang -c -o $t/f.o $t/c.c -fPIC -m32 +clang -fuse-ld=`pwd`/../mold -o $t/exe $t/f.o $t/b.so -m32 +$t/exe | grep -q '5 7 2' + +echo OK diff --git a/test/i386-tls-gd.sh b/test/i386-tls-gd.sh index 22210ecf..47780cc3 100755 --- a/test/i386-tls-gd.sh +++ b/test/i386-tls-gd.sh @@ -36,8 +36,8 @@ static _Thread_local int x6 = 6; int get_x6() { return x6; } EOF -clang -shared -o $t/d.so $t/b.o -m32 -clang -shared -o $t/e.so $t/c.o -Wl,--no-relax -m32 +clang -fuse-ld=`pwd`/../mold -shared -o $t/d.so $t/b.o -m32 +clang -fuse-ld=`pwd`/../mold -shared -o $t/e.so $t/c.o -Wl,--no-relax -m32 clang -fuse-ld=`pwd`/../mold -o $t/exe $t/a.o $t/d.so $t/e.so -m32 $t/exe | grep -q '1 2 3 4 5 6' diff --git a/test/tls-gd.sh b/test/tls-gd.sh index a3e442be..8665392a 100755 --- a/test/tls-gd.sh +++ b/test/tls-gd.sh @@ -36,8 +36,8 @@ static _Thread_local int x6 = 6; int get_x6() { return x6; } EOF -clang -shared -o $t/d.so $t/b.o -clang -shared -o $t/e.so $t/c.o -Wl,--no-relax +clang -fuse-ld=`pwd`/../mold -shared -o $t/d.so $t/b.o +clang -fuse-ld=`pwd`/../mold -shared -o $t/e.so $t/c.o -Wl,--no-relax clang -fuse-ld=`pwd`/../mold -o $t/exe $t/a.o $t/d.so $t/e.so $t/exe | grep -q '1 2 3 4 5 6'