diff options
Diffstat (limited to 'lld/ELF/Symbols.cpp')
-rw-r--r-- | lld/ELF/Symbols.cpp | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index d8c459795b3..9eb222362bb 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -112,10 +112,14 @@ static typename ELFT::uint getSymVA(const SymbolBody &Body, int64_t &Addend) { return 0; return In<ELFT>::Common->OutSec->Addr + In<ELFT>::Common->OutSecOff + cast<DefinedCommon>(Body).Offset; - case SymbolBody::SharedKind: - if (cast<SharedSymbol>(Body).NeedsPltAddr) + case SymbolBody::SharedKind: { + auto &SS = cast<SharedSymbol>(Body); + if (SS.NeedsCopy) + return SS.Section->OutSec->Addr + SS.Section->OutSecOff; + if (SS.NeedsPltAddr) return Body.getPltVA<ELFT>(); return 0; + } case SymbolBody::UndefinedKind: return 0; case SymbolBody::LazyArchiveKind: @@ -128,7 +132,7 @@ static typename ELFT::uint getSymVA(const SymbolBody &Body, int64_t &Addend) { SymbolBody::SymbolBody(Kind K, StringRefZ Name, bool IsLocal, uint8_t StOther, uint8_t Type) - : SymbolKind(K), NeedsPltAddr(false), IsLocal(IsLocal), + : SymbolKind(K), NeedsCopy(false), NeedsPltAddr(false), IsLocal(IsLocal), IsInGlobalMipsGot(false), Is32BitMipsGot(false), IsInIplt(false), IsInIgot(false), Type(Type), StOther(StOther), Name(Name) {} @@ -139,9 +143,10 @@ bool SymbolBody::isPreemptible() const { return false; // Shared symbols resolve to the definition in the DSO. The exceptions are - // symbols that needs plt entries (which resolve to that plt entry). + // symbols with copy relocations (which resolve to .bss) or preempt plt + // entries (which resolve to that plt entry). if (isShared()) - return !NeedsPltAddr; + return !NeedsCopy && !NeedsPltAddr; // That's all that can be preempted in a non-DSO. if (!Config->Shared) @@ -210,8 +215,11 @@ const OutputSection *SymbolBody::getOutputSection() const { return nullptr; } - if (isa<SharedSymbol>(this)) + if (auto *S = dyn_cast<SharedSymbol>(this)) { + if (S->NeedsCopy) + return S->Section->OutSec; return nullptr; + } if (isa<DefinedCommon>(this)) { if (Config->DefineCommon) |