diff options
Diffstat (limited to 'ELF/Relocations.cpp')
| -rw-r--r-- | ELF/Relocations.cpp | 43 |
1 files changed, 21 insertions, 22 deletions
diff --git a/ELF/Relocations.cpp b/ELF/Relocations.cpp index 94ea3e1557c4..1aa0957b1d01 100644 --- a/ELF/Relocations.cpp +++ b/ELF/Relocations.cpp @@ -581,44 +581,38 @@ static RelExpr getPltExpr(Symbol &Sym, RelExpr Expr, bool &IsConstant) { return toPlt(Expr); } +// This modifies the expression if we can use a copy relocation or point the +// symbol to the PLT. template <class ELFT> static RelExpr adjustExpr(Symbol &Sym, RelExpr Expr, RelType Type, InputSectionBase &S, uint64_t RelOff, bool &IsConstant) { - // We can create any dynamic relocation if a section is simply writable. - if (S.Flags & SHF_WRITE) - return Expr; - - // Or, if we are allowed to create dynamic relocations against - // read-only sections (i.e. when "-z notext" is given), - // we can create a dynamic relocation as we want, too. - if (!Config->ZText) { - // We use PLT for relocations that may overflow in runtime, - // see comment for getPltExpr(). - if (Sym.isFunc() && !Target->isPicRel(Type)) - return getPltExpr(Sym, Expr, IsConstant); - return Expr; - } - // If a relocation can be applied at link-time, we don't need to // create a dynamic relocation in the first place. if (IsConstant) return Expr; - // If we got here we know that this relocation would require the dynamic - // linker to write a value to read only memory. - - // If the relocation is to a weak undef, give up on it and produce a - // non preemptible 0. - if (Sym.isUndefWeak()) { + // If the relocation is to a weak undef, and we are producing + // executable, give up on it and produce a non preemptible 0. + if (!Config->Shared && Sym.isUndefWeak()) { Sym.IsPreemptible = false; IsConstant = true; return Expr; } + // We can create any dynamic relocation supported by the dynamic linker if a + // section is writable or we are passed -z notext. + bool CanWrite = (S.Flags & SHF_WRITE) || !Config->ZText; + if (CanWrite && Target->isPicRel(Type)) + return Expr; + + // If we got here we know that this relocation would require the dynamic + // linker to write a value to read only memory or use an unsupported + // relocation. + // 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 || (Config->Pic && !isRelExpr(Expr))) { + if (!CanWrite && (Config->Shared || (Config->Pic && !isRelExpr(Expr)))) { error( "can't create dynamic relocation " + toString(Type) + " against " + (Sym.getName().empty() ? "local symbol" : "symbol: " + toString(Sym)) + @@ -627,6 +621,11 @@ static RelExpr adjustExpr(Symbol &Sym, RelExpr Expr, RelType Type, return Expr; } + // Copy relocations are only possible if we are creating an executable and the + // symbol is shared. + if (!Sym.isShared() || Config->Shared) + return Expr; + if (Sym.getVisibility() != STV_DEFAULT) { error("cannot preempt symbol: " + toString(Sym) + getLocation(S, Sym, RelOff)); |
