Skip to content

Commit

Permalink
[ELF] Allow relative relocs against absolute symbols
Browse files Browse the repository at this point in the history
In the previous commit (c325cc0),
I argued that PC-relative relocations are not representable if they
refer absolute symbols, and I made a change so that such relocations
are handled as errors.

Even though what I did is technically correct, that results in a failure
of an important use case of the weak undefined symbol. Here is why.

If you have an weak undefined symbol `foo`, you would use it as follows:

  if (foo)
    foo();

If `foo` is defined (i.e. has an address other than 0), `foo` is called.

If `foo` is undefined (i.e. has the address 0), the subsequent CALL
instruction will have an offset from the CALL instruction to address 0.
That displacement is computed at link-time. If the output is position-
independent, the call instruction may not have a correct displacement
from address 0 to the instruction at runtime due to base relocation.

However, that's not a problem in practice, because the function call
is guarded by `if (foo)`, and that will always evaluated to false
if `foo` is undefined. Therefore, the faulty `CALL` instruction will
never be executed.

So, that means we need to relocate PC-relative relocations against
absolute symbols even if doing so results in an incorrect result.
This patch implement that.
  • Loading branch information
rui314 committed Feb 17, 2022
1 parent c325cc0 commit b5db63f
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 30 deletions.
4 changes: 2 additions & 2 deletions elf/arch-i386.cc
Original file line number Diff line number Diff line change
Expand Up @@ -425,8 +425,8 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
case R_386_PLT32: {
Action table[][4] = {
// Absolute Local Imported data Imported code
{ ERROR, NONE, PLT, PLT }, // DSO
{ ERROR, NONE, PLT, PLT }, // PIE
{ NONE, NONE, PLT, PLT }, // DSO
{ NONE, NONE, PLT, PLT }, // PIE
{ NONE, NONE, PLT, PLT }, // PDE
};
dispatch(ctx, table, i, rel, sym);
Expand Down
4 changes: 2 additions & 2 deletions elf/arch-x86-64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -668,8 +668,8 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
case R_X86_64_PLTOFF64: {
Action table[][4] = {
// Absolute Local Imported data Imported code
{ ERROR, NONE, PLT, PLT }, // DSO
{ ERROR, NONE, PLT, PLT }, // PIE
{ NONE, NONE, PLT, PLT }, // DSO
{ NONE, NONE, PLT, PLT }, // PIE
{ NONE, NONE, PLT, PLT }, // PDE
};
dispatch(ctx, table, i, rel, sym);
Expand Down
26 changes: 0 additions & 26 deletions test/elf/reloc-abs-error.sh

This file was deleted.

43 changes: 43 additions & 0 deletions test/elf/weak-undef.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/bin/bash
export LANG=
set -e
CC="${CC:-cc}"
CXX="${CXX:-c++}"
testname=$(basename "$0" .sh)
echo -n "Testing $testname ... "
cd "$(dirname "$0")"/../..
mold="$(pwd)/mold"
t=out/test/elf/$testname
mkdir -p $t

cat <<EOF | $CC -c -o $t/a.o -fPIC -xc -
#include <stdio.h>
__attribute__((weak)) int foo();
int main() {
printf("%d\n", foo ? foo() : -1);
}
EOF

cat <<EOF | $CC -c -o $t/b.o -fno-PIC -xc -
#include <stdio.h>
__attribute__((weak)) int foo();
int main() {
printf("%d\n", foo ? foo() : -1);
}
EOF

cat <<EOF | $CC -fcommon -xc -c -o $t/c.o -
int foo() { return 2; }
EOF

$CC -B. -o $t/exe1 $t/a.o -pie
$CC -B. -o $t/exe2 $t/b.o -no-pie
$CC -B. -o $t/exe3 $t/a.o $t/c.o -pie
$CC -B. -o $t/exe4 $t/b.o $t/c.o -no-pie

$t/exe1 | grep -q '^-1$'
$t/exe2 | grep -q '^-1$'
$t/exe3 | grep -q '^2$'
$t/exe4 | grep -q '^2$'

echo OK

0 comments on commit b5db63f

Please sign in to comment.