diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -593,7 +593,7 @@ // MD_associated in a unique section. unsigned UniqueID = MCContext::GenericSectionID; const MCSymbolELF *AssociatedSymbol = getAssociatedSymbol(GO, TM); - if (AssociatedSymbol) { + if (GO->getMetadata(LLVMContext::MD_associated)) { UniqueID = NextUniqueID++; Flags |= ELF::SHF_LINK_ORDER; } diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -1023,16 +1023,18 @@ break; } - if (Section.getFlags() & ELF::SHF_LINK_ORDER) { + unsigned Flags = Section.getFlags(); + if (Flags & ELF::SHF_LINK_ORDER) { const MCSymbol *Sym = Section.getAssociatedSymbol(); - const MCSectionELF *Sec = cast(&Sym->getSection()); - sh_link = SectionIndexMap.lookup(Sec); + if (Sym && Sym->isInSection()) { + const MCSectionELF *Sec = cast(&Sym->getSection()); + sh_link = SectionIndexMap.lookup(Sec); + } } WriteSecHdrEntry(StrTabBuilder.getOffset(Section.getSectionName()), - Section.getType(), Section.getFlags(), 0, Offset, Size, - sh_link, sh_info, Section.getAlignment(), - Section.getEntrySize()); + Section.getType(), Flags, 0, Offset, Size, sh_link, sh_info, + Section.getAlignment(), Section.getEntrySize()); } void ELFWriter::writeSectionHeader( diff --git a/llvm/lib/MC/MCSectionELF.cpp b/llvm/lib/MC/MCSectionELF.cpp --- a/llvm/lib/MC/MCSectionELF.cpp +++ b/llvm/lib/MC/MCSectionELF.cpp @@ -172,9 +172,11 @@ } if (Flags & ELF::SHF_LINK_ORDER) { - assert(AssociatedSymbol); OS << ","; - printName(OS, AssociatedSymbol->getName()); + if (AssociatedSymbol) + printName(OS, AssociatedSymbol->getName()); + else + printName(OS, ""); } if (isUnique()) diff --git a/llvm/test/CodeGen/X86/elf-associated-discarded.ll b/llvm/test/CodeGen/X86/elf-associated-discarded.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/elf-associated-discarded.ll @@ -0,0 +1,23 @@ +;; Test that we drop SHF_LINK_ORDER and reset sh_link to 0 if the associated +;; symbol is not defined. +; RUN: llc -mtriple=x86_64 -data-sections=1 < %s | FileCheck %s +; RUN: llc -filetype=obj -mtriple=x86_64 -data-sections=1 < %s | llvm-readelf -S | FileCheck --check-prefix=SEC %s + +;; FIXME The assembly output cannot be assembled because foo is not defined. +;; This is difficult to fix because we allow loops (see elf-associated.ll +;; .data.c and .data.d). +; CHECK: .section .data.a,"awo",@progbits,foo +; CHECK: .section .data.b,"awo",@progbits,foo + +;; No 'L' (SHF_LINK_ORDER). sh_link=0. +; SEC; Name {{.*}} Flg Lk Inf +; SEC: .data.a {{.*}} WAL 0 0 +; SEC: .data.b {{.*}} WAL 0 0 + +;; The definition may be discarded by LTO. +declare void @foo() + +@a = global i32 1, !associated !0 +@b = global i32 1, !associated !0 + +!0 = !{void ()* @foo} diff --git a/llvm/test/CodeGen/X86/elf-associated.ll b/llvm/test/CodeGen/X86/elf-associated.ll --- a/llvm/test/CodeGen/X86/elf-associated.ll +++ b/llvm/test/CodeGen/X86/elf-associated.ll @@ -36,15 +36,15 @@ ; Non-GlobalValue metadata. @l = global i32 1, section "ccc", !associated !5 !5 = !{i32* null} -; CHECK-DAG: .section ccc,"aw",@progbits +; CHECK-DAG: .section ccc,"awo",@progbits,,unique,3 ; Null metadata. @m = global i32 1, section "ddd", !associated !6 !6 = distinct !{null} -; CHECK-DAG: .section ddd,"aw",@progbits +; CHECK-DAG: .section ddd,"awo",@progbits,,unique,4 ; Aliases are OK. @n = alias i32, i32* inttoptr (i64 add (i64 ptrtoint (i32* @a to i64), i64 1297036692682702848) to i32*) @o = global i32 1, section "eee", !associated !7 !7 = !{i32* @n} -; CHECK-DAG: .section eee,"awo",@progbits,n,unique,3 +; CHECK-DAG: .section eee,"awo",@progbits,n,unique,5