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:
parent
a0c3fcb1bb
commit
8833dcbcb0
32
arch_i386.cc
32
arch_i386.cc
@ -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
45
test/i386-shared.sh
Executable 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
|
@ -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'
|
||||
|
@ -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'
|
||||
|
Loading…
Reference in New Issue
Block a user