diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index b293afc56a0..e3623997a44 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/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(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, diff --git a/test/MC/ELF/alias-to-local.s b/test/MC/ELF/alias-to-local.s new file mode 100644 index 00000000000..4983833b33a --- /dev/null +++ b/test/MC/ELF/alias-to-local.s @@ -0,0 +1,18 @@ +// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu < %s | llvm-readobj -r | FileCheck %s + +// CHECK: Relocations [ +// CHECK-NEXT: Section {{.*}} .rela.text { +// CHECK-NEXT: 0x1 R_X86_64_32 zed 0x0 +// CHECK-NEXT: } +// CHECK-NEXT: ] + +foo: + movl $zed, %eax + + + .section .data.bar,"aGw",@progbits,zed,comdat +bar: + .byte 42 + + .globl zed +zed = bar