diff options
Diffstat (limited to 'lld/ELF')
| -rw-r--r-- | lld/ELF/Writer.cpp | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index dfb99d4b8b4..4079c761115 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -439,6 +439,12 @@ static bool needsPlt(RelExpr Expr) { return Expr == R_PLT_PC || Expr == R_PPC_PLT_OPD || Expr == R_PLT; } +// True if this expression is of the form Sym - X, where X is a position in the +// file (PC, or GOT for example). +static bool isRelExpr(RelExpr Expr) { + return Expr == R_PC || Expr == R_GOTREL || Expr == R_PAGE_PC; +} + template <class ELFT> static bool isStaticLinkTimeConstant(RelExpr E, uint32_t Type, const SymbolBody &Body) { @@ -460,7 +466,7 @@ static bool isStaticLinkTimeConstant(RelExpr E, uint32_t Type, return true; bool AbsVal = isAbsolute<ELFT>(Body) || Body.isTls(); - bool RelE = E == R_PC || E == R_GOTREL || E == R_PAGE_PC; + bool RelE = isRelExpr(E); if (AbsVal && !RelE) return true; if (!AbsVal && RelE) @@ -520,7 +526,7 @@ RelExpr Writer<ELFT>::adjustExpr(SymbolBody &Body, bool IsWrite, RelExpr Expr, // This relocation would require the dynamic linker to write a value to read // only memory. We can hack around it if we are producing an executable and // the refered symbol can be preemepted to refer to the executable. - if (Config->Shared) { + if (Config->Shared || (Config->Pic && !isRelExpr(Expr))) { StringRef S = getELFRelocationTypeName(Config->EMachine, Type); error("relocation " + S + " cannot be used when making a shared " "object; recompile with -fPIC."); |

