1
1
mirror of https://github.com/rui314/mold.git synced 2024-12-25 17:34:02 +03:00

Fix function pointer equality

Previously, a GOT relocation (e.g. R_X86_64_REX_GOTPCRELX) and a
R_X86_64_64 relocation referring the same imported symbols were
resolved to different addresses. Here is why:

 - When we saw a R_X86_64_64 relocation against an imported symbol,
   we created a PLT and resolve the relocation there.

 - GOT relocation is resolved to a GOT entry, which has a true
   address of an imported function at runtime, which is different
   from PLT entries that redirect calls to the real function.

With this patch, we no longer create a PLT entry for R_X86_64_64.
Instead, we emit a dynamic relocation so that it is always resolved
to a real function address.

Fixes GNU MP's `make check` failure, which was reported at
https://github.com/rui314/mold/issues/81
This commit is contained in:
Rui Ueyama 2021-07-10 17:18:35 +09:00
parent faac31f217
commit 3204bb01d9
4 changed files with 29 additions and 3 deletions

View File

@ -294,7 +294,7 @@ void InputSection<AARCH64>::scan_relocations(Context<AARCH64> &ctx) {
// Absolute Local Imported data Imported code
{ NONE, BASEREL, DYNREL, DYNREL }, // DSO
{ NONE, BASEREL, DYNREL, DYNREL }, // PIE
{ NONE, NONE, DYNREL, PLT }, // PDE
{ NONE, NONE, DYNREL, DYNREL }, // PDE
};
dispatch(ctx, table, i);
break;

View File

@ -349,7 +349,7 @@ void InputSection<I386>::scan_relocations(Context<I386> &ctx) {
// Absolute Local Imported data Imported code
{ NONE, BASEREL, DYNREL, DYNREL }, // DSO
{ NONE, BASEREL, DYNREL, DYNREL }, // PIE
{ NONE, NONE, DYNREL, PLT }, // PDE
{ NONE, NONE, DYNREL, DYNREL }, // PDE
};
dispatch(ctx, table, i);
break;

View File

@ -535,7 +535,7 @@ void InputSection<X86_64>::scan_relocations(Context<X86_64> &ctx) {
// Absolute Local Imported data Imported code
{ NONE, BASEREL, DYNREL, DYNREL }, // DSO
{ NONE, BASEREL, DYNREL, DYNREL }, // PIE
{ NONE, NONE, DYNREL, PLT }, // PDE
{ NONE, NONE, DYNREL, DYNREL }, // PDE
};
dispatch(ctx, table, i);
break;

26
test/func-addr.sh Executable file
View File

@ -0,0 +1,26 @@
#!/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 | cc -shared -o $t/a.so -xc -
void fn() {}
EOF
cat <<EOF | cc -o $t/b.o -c -xc -
#include <stdio.h>
void fn();
void (*ptr)() = fn;
int main() {
printf("%d\n", fn == ptr);
}
EOF
clang -fuse-ld=`pwd`/../mold -o $t/exe $t/b.o $t/a.so
$t/exe | grep -q 1
echo OK