// 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 {
}
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()),
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);
}
if (Flags & ELF::SHF_LINK_ORDER) {
- assert(LinkedToSym);
OS << ",";
- printName(OS, LinkedToSym->getName());
+ if (LinkedToSym)
+ printName(OS, LinkedToSym->getName());
+ else
+ OS << '0';
}
if (isUnique())
--- /dev/null
+;; 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}
; 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
--- /dev/null
+# 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