From de17d28a321c48d87cdb15ca784624bfae17f374 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Wed, 4 May 2016 21:40:07 +0000 Subject: [PATCH] Don't produce relative relocs to ro segments. We were already checking for non relative relocations. If we ever decide to add support for rw text segments this means we will have a single spot to add the flag. llvm-svn: 268558 --- lld/ELF/Target.cpp | 1 + lld/ELF/Writer.cpp | 34 ++++++++++++++++++------------ lld/test/ELF/dynamic-reloc-in-ro.s | 8 +++++++ 3 files changed, 30 insertions(+), 13 deletions(-) create mode 100644 lld/test/ELF/dynamic-reloc-in-ro.s diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index df41fcde9992..72544103db6d 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -976,6 +976,7 @@ bool AArch64TargetInfo::usesOnlyLowPageBits(uint32_t Type) const { case R_AARCH64_LDST64_ABS_LO12_NC: case R_AARCH64_LDST128_ABS_LO12_NC: case R_AARCH64_LD64_GOT_LO12_NC: + case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: return true; } } diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 4b8849fb6fcb..63ed12a64e10 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -442,14 +442,25 @@ static bool needsPlt(RelExpr Expr) { template static bool isStaticLinkTimeConstant(RelExpr E, uint32_t Type, const SymbolBody &Body) { - if (E == R_SIZE) + // These expressions always compute a constant + if (E == R_SIZE || E == R_GOT_FROM_END || E == R_GOT_OFF || E == R_MIPS_GOT || + E == R_MIPS_GOT_LOCAL || E == R_GOT_PAGE_PC || E == R_GOT_PC || + E == R_PLT_PC || E == R_TLSGD_PC || E == R_TLSGD || E == R_PPC_PLT_OPD) return true; - bool AbsVal = (isAbsolute(Body) || Body.isTls()) && - !refersToGotEntry(E) && !needsPlt(E); + // These never do, except if the entire file is position dependent or if + // only the low bits are used. + if (E == R_GOT || E == R_PLT) + return Target->usesOnlyLowPageBits(Type) || !Config->Pic; - bool RelE = E == R_PC || E == R_PLT_PC || E == R_GOT_PC || E == R_GOTREL || - E == R_PAGE_PC; + if (Body.isPreemptible()) + return false; + + if (!Config->Pic) + return true; + + bool AbsVal = isAbsolute(Body) || Body.isTls(); + bool RelE = E == R_PC || E == R_GOTREL || E == R_PAGE_PC; if (AbsVal && !RelE) return true; if (!AbsVal && RelE) @@ -497,16 +508,13 @@ static RelExpr fromPlt(RelExpr Expr) { template RelExpr Writer::adjustExpr(SymbolBody &Body, bool IsWrite, RelExpr Expr, uint32_t Type) { - if (Body.isGnuIFunc()) - return toPlt(Expr); bool Preemptible = Body.isPreemptible(); - if (needsPlt(Expr)) { - if (Preemptible) - return Expr; - return fromPlt(Expr); - } + if (Body.isGnuIFunc()) + Expr = toPlt(Expr); + else if (needsPlt(Expr) && !Preemptible) + Expr = fromPlt(Expr); - if (IsWrite || refersToGotEntry(Expr) || needsPlt(Expr) || !Preemptible) + if (IsWrite || isStaticLinkTimeConstant(Expr, Type, Body)) return Expr; // This relocation would require the dynamic linker to write a value to read diff --git a/lld/test/ELF/dynamic-reloc-in-ro.s b/lld/test/ELF/dynamic-reloc-in-ro.s new file mode 100644 index 000000000000..00a83b6ad656 --- /dev/null +++ b/lld/test/ELF/dynamic-reloc-in-ro.s @@ -0,0 +1,8 @@ +// REQUIRES: x86 +// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +// RUN: not ld.lld %t.o -o %t.so -shared 2>&1 | FileCheck %s + +foo: +.quad foo + +// CHECK: relocation R_X86_64_64 cannot be used when making a shared object; recompile with -fPIC.