diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 875871b0ca638eac59faf7b8533c47c9666e99c7..e5dc0c4d0f29a8d2f5a0189ca18c40f69a13bece 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -286,6 +286,10 @@ template static bool isAbsolute(const SymbolBody &Body) { return false; } +template static bool isAbsoluteValue(const SymbolBody &Body) { + return isAbsolute(Body) || Body.isTls(); +} + static bool needsPlt(RelExpr Expr) { return Expr == R_PLT_PC || Expr == R_PPC_PLT_OPD || Expr == R_PLT || Expr == R_PLT_PAGE_PC || Expr == R_THUNK_PLT_PC; @@ -322,7 +326,7 @@ static bool isStaticLinkTimeConstant(RelExpr E, uint32_t Type, if (!Config->Pic) return true; - bool AbsVal = isAbsolute(Body) || Body.isTls(); + bool AbsVal = isAbsoluteValue(Body); bool RelE = isRelExpr(E); if (AbsVal && !RelE) return true; @@ -433,7 +437,7 @@ static RelExpr adjustExpr(const elf::ObjectFile &File, SymbolBody &Body, } else if (!Preemptible) { if (needsPlt(Expr)) Expr = fromPlt(Expr); - if (Expr == R_GOT_PC) + if (Expr == R_GOT_PC && !isAbsoluteValue(Body)) Expr = Target->adjustRelaxExpr(Type, Data, Expr); } Expr = Target->getThunkExpr(Expr, Type, File, Body); diff --git a/lld/test/ELF/x86-64-relax-got-abs.s b/lld/test/ELF/x86-64-relax-got-abs.s new file mode 100644 index 0000000000000000000000000000000000000000..c4291202f0351d82ccd94d202a06588eef657b5c --- /dev/null +++ b/lld/test/ELF/x86-64-relax-got-abs.s @@ -0,0 +1,16 @@ +// REQUIRES: x86 +// RUN: llvm-mc -filetype=obj -relax-relocations -triple=x86_64-pc-linux %s \ +// RUN: -o %t.o +// RUN: ld.lld %t.o -o %t.so -shared +// RUN: llvm-objdump -d %t.so | FileCheck %s + +// We used to fail trying to relax this into a pc relocation to an absolute +// value. + +// CHECK: movq 4185(%rip), %rax + + movq bar@GOTPCREL(%rip), %rax + .data + .global bar + .hidden bar + bar = 42