[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
This commit is contained in:
Fangrui Song 2020-08-03 13:35:59 -07:00 committed by Fangrui Song
parent 040e0990b8
commit 6fcac4f990
7 changed files with 52 additions and 9 deletions

View File

@ -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 {

View File

@ -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<MCSectionELF>(&Sym->getSection());
sh_link = SectionIndexMap.lookup(Sec);
if (Sym && Sym->isInSection()) {
const MCSectionELF *Sec = cast<MCSectionELF>(&Sym->getSection());
sh_link = SectionIndexMap.lookup(Sec);
}
}
WriteSecHdrEntry(StrTabBuilder.getOffset(Section.getName()),

View File

@ -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<MCSymbolELF>(getContext().lookupSymbol(Name));
if (!LinkedToSym || !LinkedToSym->isInSection())
return Error(StartLoc, "linked-to symbol is not in a section: " + Name);

View File

@ -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())

View File

@ -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}

View File

@ -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

View File

@ -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