1
1
mirror of https://github.com/rui314/mold.git synced 2024-12-24 00:43:18 +03:00

Fix relocations for i386 PIC

This commit is contained in:
Rui Ueyama 2021-06-07 15:24:03 +09:00
parent a0c3fcb1bb
commit 8833dcbcb0
4 changed files with 65 additions and 20 deletions

View File

@ -47,7 +47,7 @@ void PltSection<I386>::copy_buf(Context<I386> &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<I386>::copy_buf(Context<I386> &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<I386>::apply_reloc_alloc(Context<I386> &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<I386>::apply_reloc_alloc(Context<I386> &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<I386>::apply_reloc_alloc(Context<I386> &ctx, u8 *base) {
#undef A
#undef P
#undef G
#undef GOT
#undef GOTPLT
}
}

45
test/i386-shared.sh Executable file
View File

@ -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 <<EOF | clang -fPIC -c -o $t/a.o -xc - -m32
int foo = 5;
void set_foo(int x) { foo = x; }
int get_foo() { return foo; }
static int bar = 7;
void set_bar(int x) { bar = x; }
int get_bar() { return bar; }
EOF
clang -fuse-ld=`pwd`/../mold -o $t/b.so -shared $t/a.o -m32
cat <<EOF > $t/c.c
#include <stdio.h>
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

View File

@ -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'

View File

@ -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'