Skip to content

Commit

Permalink
[ELF] Report an error for an unrepresentable reloc against abs symbol
Browse files Browse the repository at this point in the history
PC-relative relocations against absolute symbols are not representable
in position-independent code. In order to support such relocations,
someone has to compute `S + A - P` or subtract `B` as a base relocation,
but such dynamic relocations don't exist.

This is contrary to non-PC-relative relocations against non-absolute
symbols. In this case, we can simply use the base relocation (e.g.
R_X86_64_RELATIVE).

#348
  • Loading branch information
rui314 committed Feb 17, 2022
1 parent 0b7edc0 commit c325cc0
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 19 deletions.
16 changes: 11 additions & 5 deletions elf/arch-i386.cc
Original file line number Diff line number Diff line change
Expand Up @@ -410,8 +410,8 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
case R_386_PC32: {
Action table[][4] = {
// Absolute Local Imported data Imported code
{ BASEREL, NONE, DYNREL, DYNREL }, // DSO
{ BASEREL, NONE, COPYREL, PLT }, // PIE
{ ERROR, NONE, DYNREL, DYNREL }, // DSO
{ ERROR, NONE, COPYREL, PLT }, // PIE
{ NONE, NONE, COPYREL, PLT }, // PDE
};
dispatch(ctx, table, i, rel, sym);
Expand All @@ -422,10 +422,16 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
case R_386_GOTPC:
sym.flags |= NEEDS_GOT;
break;
case R_386_PLT32:
if (sym.is_imported)
sym.flags |= NEEDS_PLT;
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 }, // PDE
};
dispatch(ctx, table, i, rel, sym);
break;
}
case R_386_TLS_GOTIE:
case R_386_TLS_LE:
case R_386_TLS_IE:
Expand Down
16 changes: 11 additions & 5 deletions elf/arch-x86-64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -629,8 +629,8 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
case R_X86_64_PC64: {
Action table[][4] = {
// Absolute Local Imported data Imported code
{ BASEREL, NONE, DYNREL, DYNREL }, // DSO
{ BASEREL, NONE, COPYREL, PLT }, // PIE
{ ERROR, NONE, DYNREL, DYNREL }, // DSO
{ ERROR, NONE, COPYREL, PLT }, // PIE
{ NONE, NONE, COPYREL, PLT }, // PDE
};
dispatch(ctx, table, i, rel, sym);
Expand Down Expand Up @@ -665,10 +665,16 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
break;
}
case R_X86_64_PLT32:
case R_X86_64_PLTOFF64:
if (sym.is_imported)
sym.flags |= NEEDS_PLT;
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 }, // PDE
};
dispatch(ctx, table, i, rel, sym);
break;
}
case R_X86_64_TLSGD:
if (i + 1 == rels.size())
Fatal(ctx) << *this
Expand Down
8 changes: 6 additions & 2 deletions elf/input-sections.cc
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,12 @@ void InputSection<E>::dispatch(Context<E> &ctx, Action table[3][4], i64 i,
bool is_writable = (shdr().sh_flags & SHF_WRITE);

auto error = [&] {
Error(ctx) << *this << ": " << rel << " relocation against symbol `"
<< sym << "' can not be used; recompile with -fPIC";
if (sym.is_absolute())
Error(ctx) << *this << ": " << rel << " relocation against symbol `"
<< sym << "' can not be used; recompile with -fno-PIC";
else
Error(ctx) << *this << ": " << rel << " relocation against symbol `"
<< sym << "' can not be used; recompile with -fPIC";
};

auto warn_textrel = [&] {
Expand Down
37 changes: 30 additions & 7 deletions test/elf/absolute-symbols.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,37 @@ mkdir -p $t

[ "$(uname -m)" = x86_64 ] || { echo skipped; exit; }

cat <<EOF | $CC -o $t/a.o -c -fno-PIC -x assembler -
.globl foo, main
foo = 0x8080
main:
call foo
cat <<EOF | $CC -o $t/a.o -c -x assembler -
.globl foo
foo = 0x800000
EOF

$CC -B. -o $t/exe -no-pie $t/a.o
objdump -d $t/exe | grep -qE 'callq\s+8080'
cat <<EOF | $CC -o $t/b.o -c -fno-PIC -xc -
#define _GNU_SOURCE 1
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <ucontext.h>
void handler(int signum, siginfo_t *info, void *ptr) {
ucontext_t *u = (ucontext_t *)ptr;
printf("ip=0x%llx\n", u->uc_mcontext.gregs[REG_RIP]);
exit(0);
}
void foo();
int main() {
struct sigaction act;
act.sa_flags = SA_SIGINFO | SA_RESETHAND;
act.sa_sigaction = handler;
sigemptyset(&act.sa_mask);
sigaction(SIGSEGV, &act, 0);
foo();
}
EOF

$CC -B. -o $t/exe -no-pie $t/a.o $t/b.o
$t/exe | grep -q '^ip=0x800000$'

echo OK
26 changes: 26 additions & 0 deletions test/elf/reloc-abs-error.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/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 -o $t/a.o -c -x assembler -
.globl foo
foo = 0x800000
EOF

cat <<EOF | $CC -o $t/b.o -c -fPIC -xc -
void foo();
int main() { foo(); }
EOF

! $CC -B. -o $t/exe -pie $t/a.o $t/b.o >& $t/log
grep -q 'recompile with -fno-PIC' $t/log

echo OK

0 comments on commit c325cc0

Please sign in to comment.