From: Fangrui Song Date: Mon, 3 Aug 2020 20:35:59 +0000 (-0700) Subject: [MC] Set sh_link to 0 if the associated symbol is undefined X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=11bb7c220ccdff1ffec4780ff92fb5acec8f6f0b;p=platform%2Fupstream%2Fllvm.git [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 --- diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 4859919..8ef9125 100644 --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/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/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp index 5a5692c..b44a36b 100644 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/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/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/llvm/lib/MC/MCParser/ELFAsmParser.cpp index e5ab13b..41779d0 100644 --- a/llvm/lib/MC/MCParser/ELFAsmParser.cpp +++ b/llvm/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/llvm/lib/MC/MCSectionELF.cpp b/llvm/lib/MC/MCSectionELF.cpp index 77c259c..7a15556 100644 --- a/llvm/lib/MC/MCSectionELF.cpp +++ b/llvm/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/llvm/test/CodeGen/X86/elf-associated-discarded.ll b/llvm/test/CodeGen/X86/elf-associated-discarded.ll new file mode 100644 index 0000000..5a4fad4 --- /dev/null +++ b/llvm/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/llvm/test/CodeGen/X86/elf-associated.ll b/llvm/test/CodeGen/X86/elf-associated.ll index e0e9e00..14a4b5b 100644 --- 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,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/llvm/test/MC/ELF/section-linkorder.s b/llvm/test/MC/ELF/section-linkorder.s new file mode 100644 index 0000000..a0f6357 --- /dev/null +++ b/llvm/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