summaryrefslogtreecommitdiff
path: root/ELF/Relocations.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ELF/Relocations.cpp')
-rw-r--r--ELF/Relocations.cpp43
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));