From 6fcac4f990ed4d393314a01eb6c21ab478f5a9e5 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 3 Aug 2020 13:35:59 -0700 Subject: [PATCH] [MC] Set sh_link to 0 if the associated symbol is undefined Part of https://bugs.llvm.org/show_bug.cgi?id=41734 LTO can drop externally available definitions. Such AssociatedSymbol is not associated with a symbol. ELFWriter::writeSection() will assert. Allow a SHF_LINK_ORDER section to have sh_link=0. We need to give sh_link a syntax, a literal zero in the linked-to symbol position, e.g. `.section name,"ao",@progbits,0` Reviewed By: pcc Differential Revision: https://reviews.llvm.org/D72899 --- lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 2 +- lib/MC/ELFObjectWriter.cpp | 8 +++++-- lib/MC/MCParser/ELFAsmParser.cpp | 8 ++++++- lib/MC/MCSectionELF.cpp | 6 +++-- test/CodeGen/X86/elf-associated-discarded.ll | 23 ++++++++++++++++++++ test/CodeGen/X86/elf-associated.ll | 6 ++--- test/MC/ELF/section-linkorder.s | 8 +++++++ 7 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 test/CodeGen/X86/elf-associated-discarded.ll create mode 100644 test/MC/ELF/section-linkorder.s diff --git a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 48599199626..8ef91250423 100644 --- a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -680,7 +680,7 @@ MCSection *TargetLoweringObjectFileELF::getExplicitSectionGlobal( // MD_associated in a unique section. unsigned UniqueID = MCContext::GenericSectionID; const MCSymbolELF *LinkedToSym = getLinkedToSymbol(GO, TM); - if (LinkedToSym) { + if (GO->getMetadata(LLVMContext::MD_associated)) { UniqueID = NextUniqueID++; Flags |= ELF::SHF_LINK_ORDER; } else { diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 5a5692c0cb6..b44a36b9713 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -1024,9 +1024,13 @@ void ELFWriter::writeSection(const SectionIndexMapTy &SectionIndexMap, } if (Section.getFlags() & ELF::SHF_LINK_ORDER) { + // If the value in the associated metadata is not a definition, Sym will be + // undefined. Represent this with sh_link=0. const MCSymbol *Sym = Section.getLinkedToSymbol(); - 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.getName()), diff --git a/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp index e5ab13bc719..41779d023a5 100644 --- a/lib/MC/MCParser/ELFAsmParser.cpp +++ b/lib/MC/MCParser/ELFAsmParser.cpp @@ -450,8 +450,14 @@ bool ELFAsmParser::parseLinkedToSym(MCSymbolELF *&LinkedToSym) { Lex(); StringRef Name; SMLoc StartLoc = L.getLoc(); - if (getParser().parseIdentifier(Name)) + if (getParser().parseIdentifier(Name)) { + if (getParser().getTok().getString() == "0") { + getParser().Lex(); + LinkedToSym = nullptr; + return false; + } return TokError("invalid linked-to symbol"); + } LinkedToSym = dyn_cast_or_null(getContext().lookupSymbol(Name)); if (!LinkedToSym || !LinkedToSym->isInSection()) return Error(StartLoc, "linked-to symbol is not in a section: " + Name); diff --git a/lib/MC/MCSectionELF.cpp b/lib/MC/MCSectionELF.cpp index 77c259c27a0..7a155561826 100644 --- a/lib/MC/MCSectionELF.cpp +++ b/lib/MC/MCSectionELF.cpp @@ -172,9 +172,11 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, } if (Flags & ELF::SHF_LINK_ORDER) { - assert(LinkedToSym); OS << ","; - printName(OS, LinkedToSym->getName()); + if (LinkedToSym) + printName(OS, LinkedToSym->getName()); + else + OS << '0'; } if (isUnique()) diff --git a/test/CodeGen/X86/elf-associated-discarded.ll b/test/CodeGen/X86/elf-associated-discarded.ll new file mode 100644 index 00000000000..5a4fad4ebb7 --- /dev/null +++ b/test/CodeGen/X86/elf-associated-discarded.ll @@ -0,0 +1,23 @@ +;; Test that we keep SHF_LINK_ORDER but 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/test/CodeGen/X86/elf-associated.ll b/test/CodeGen/X86/elf-associated.ll index e0e9e005828..14a4b5b85b0 100644 --- a/test/CodeGen/X86/elf-associated.ll +++ b/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,0,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,0,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 diff --git a/test/MC/ELF/section-linkorder.s b/test/MC/ELF/section-linkorder.s new file mode 100644 index 00000000000..a0f6357e52c --- /dev/null +++ b/test/MC/ELF/section-linkorder.s @@ -0,0 +1,8 @@ +# RUN: llvm-mc -triple x86_64 %s | FileCheck %s --check-prefix=ASM +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t +# RUN: llvm-readelf -S %t | FileCheck %s + +# ASM: .section .linkorder,"ao",@progbits,0 +# CHECK: Name Type {{.*}} Flg Lk +# CHECK: .linkorder PROGBITS {{.*}} AL 0 +.section .linkorder,"ao",@progbits,0