summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/MC/ELFObjectWriter.cpp31
1 files changed, 30 insertions, 1 deletions
diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp
index b293afc56a0..e3623997a44 100644
--- a/llvm/lib/MC/ELFObjectWriter.cpp
+++ b/llvm/lib/MC/ELFObjectWriter.cpp
@@ -769,7 +769,36 @@ static const MCSymbol *getWeakRef(const MCSymbolRefExpr &Ref) {
}
static bool isWeak(const MCSymbolData &D) {
- return D.getFlags() & ELF_STB_Weak || MCELF::GetType(D) == ELF::STT_GNU_IFUNC;
+ if (MCELF::GetType(D) == ELF::STT_GNU_IFUNC)
+ return true;
+
+ switch (MCELF::GetBinding(D)) {
+ default:
+ llvm_unreachable("Unknown binding");
+ case ELF::STB_LOCAL:
+ return false;
+ case ELF::STB_GLOBAL:
+ break;
+ case ELF::STB_WEAK:
+ case ELF::STB_GNU_UNIQUE:
+ return true;
+ }
+
+ const MCSymbol &Sym = D.getSymbol();
+ if (!Sym.isInSection())
+ return false;
+
+ const auto &Sec = cast<MCSectionELF>(Sym.getSection());
+ if (!Sec.getGroup())
+ return false;
+
+ // It is invalid to replace a reference to a global in a comdat
+ // with a reference to a local since out of comdat references
+ // to a local are forbidden.
+ // We could try to return false for more cases, like the reference
+ // being in the same comdat or Sym being an alias to another global,
+ // but it is not clear if it is worth the effort.
+ return true;
}
void ELFObjectWriter::RecordRelocation(MCAssembler &Asm,
OpenPOWER on IntegriCloud