class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile {
+ mutable unsigned NextUniqueID = 0;
+
public:
~TargetLoweringObjectFileCOFF() override {}
std::string SectionName;
StringRef GroupName;
int SelectionKey;
+ unsigned UniqueID;
COFFSectionKey(StringRef SectionName, StringRef GroupName,
- int SelectionKey)
+ int SelectionKey, unsigned UniqueID)
: SectionName(SectionName), GroupName(GroupName),
- SelectionKey(SelectionKey) {}
+ SelectionKey(SelectionKey), UniqueID(UniqueID) {}
bool operator<(const COFFSectionKey &Other) const {
if (SectionName != Other.SectionName)
return SectionName < Other.SectionName;
if (GroupName != Other.GroupName)
return GroupName < Other.GroupName;
- return SelectionKey < Other.SelectionKey;
+ if (SelectionKey != Other.SelectionKey)
+ return SelectionKey < Other.SelectionKey;
+ return UniqueID < Other.UniqueID;
}
};
/// \name Section Management
/// @{
+ enum : unsigned {
+ /// Pass this value as the UniqueID during section creation to get the
+ /// generic section with the given name and characteristics. The usual
+ /// sections such as .text use this ID.
+ GenericSectionID = ~0U
+ };
+
/// Return the MCSection for the specified mach-o section. This requires
/// the operands to be valid.
MCSectionMachO *getMachOSection(StringRef Segment, StringRef Section,
MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics,
SectionKind Kind, StringRef COMDATSymName,
int Selection,
+ unsigned UniqueID = GenericSectionID,
const char *BeginSymName = nullptr);
MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics,
/// section containing KeySym. For example, to create a debug info section
/// associated with an inline function, pass the normal debug info section
/// as Sec and the function symbol as KeySym.
- MCSectionCOFF *getAssociativeCOFFSection(MCSectionCOFF *Sec,
- const MCSymbol *KeySym);
+ MCSectionCOFF *
+ getAssociativeCOFFSection(MCSectionCOFF *Sec, const MCSymbol *KeySym,
+ unsigned UniqueID = GenericSectionID);
// Create and save a copy of STI and return a reference to the copy.
MCSubtargetInfo &getSubtargetCopy(const MCSubtargetInfo &STI);
/// below.
mutable unsigned Characteristics;
+ /// The unique IDs used with the .pdata and .xdata sections created internally
+ /// by the assembler. This ID is used to ensure that for every .text section,
+ /// there is exactly one .pdata and one .xdata section, which is required by
+ /// the Microsoft incremental linker. This data is mutable because this ID is
+ /// not notionally part of the section.
+ mutable unsigned WinCFISectionID = ~0U;
+
/// The COMDAT symbol of this section. Only valid if this is a COMDAT section.
/// Two COMDAT sections are merged if they have the same COMDAT symbol.
MCSymbol *COMDATSymbol;
bool UseCodeAlign() const override;
bool isVirtualSection() const override;
+ unsigned getOrAssignWinCFISectionID(unsigned *NextID) const {
+ if (WinCFISectionID == ~0U)
+ WinCFISectionID = (*NextID)++;
+ return WinCFISectionID;
+ }
+
static bool classof(const MCSection *S) { return S->getVariant() == SV_COFF; }
};
/// PushSection.
SmallVector<std::pair<MCSectionSubPair, MCSectionSubPair>, 4> SectionStack;
+ /// The next unique ID to use when creating a WinCFI-related section (.pdata
+ /// or .xdata). This ID ensures that we have a one-to-one mapping from
+ /// code section to unwind info section, which MSVC's incremental linker
+ /// requires.
+ unsigned NextWinCFIID = 0;
+
protected:
MCStreamer(MCContext &Ctx);
virtual void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except);
virtual void EmitWinEHHandlerData();
+ /// Get the .pdata section used for the given section. Typically the given
+ /// section is either the main .text section or some other COMDAT .text
+ /// section, but it may be any section containing code.
+ MCSection *getAssociatedPDataSection(const MCSection *TextSec);
+
+ /// Get the .xdata section used for the given section.
+ MCSection *getAssociatedXDataSection(const MCSection *TextSec);
+
virtual void EmitSyntaxDirective();
/// \brief Emit a .reloc directive.
#include <vector>
namespace llvm {
-class MCContext;
class MCSection;
class MCStreamer;
class MCSymbol;
-class StringRef;
namespace WinEH {
struct Instruction {
};
struct FrameInfo {
- const MCSymbol *Begin;
- const MCSymbol *End;
- const MCSymbol *ExceptionHandler;
- const MCSymbol *Function;
- const MCSymbol *PrologEnd;
- const MCSymbol *Symbol;
+ const MCSymbol *Begin = nullptr;
+ const MCSymbol *End = nullptr;
+ const MCSymbol *ExceptionHandler = nullptr;
+ const MCSymbol *Function = nullptr;
+ const MCSymbol *PrologEnd = nullptr;
+ const MCSymbol *Symbol = nullptr;
+ const MCSection *TextSection = nullptr;
- bool HandlesUnwind;
- bool HandlesExceptions;
+ bool HandlesUnwind = false;
+ bool HandlesExceptions = false;
- int LastFrameInst;
- const FrameInfo *ChainedParent;
+ int LastFrameInst = -1;
+ const FrameInfo *ChainedParent = nullptr;
std::vector<Instruction> Instructions;
- FrameInfo()
- : Begin(nullptr), End(nullptr), ExceptionHandler(nullptr),
- Function(nullptr), PrologEnd(nullptr), Symbol(nullptr),
- HandlesUnwind(false), HandlesExceptions(false), LastFrameInst(-1),
- ChainedParent(nullptr), Instructions() {}
+ FrameInfo() = default;
FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel)
- : Begin(BeginFuncEHLabel), End(nullptr), ExceptionHandler(nullptr),
- Function(Function), PrologEnd(nullptr), Symbol(nullptr),
- HandlesUnwind(false), HandlesExceptions(false), LastFrameInst(-1),
- ChainedParent(nullptr), Instructions() {}
+ : Begin(BeginFuncEHLabel), Function(Function) {}
FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel,
const FrameInfo *ChainedParent)
- : Begin(BeginFuncEHLabel), End(nullptr), ExceptionHandler(nullptr),
- Function(Function), PrologEnd(nullptr), Symbol(nullptr),
- HandlesUnwind(false), HandlesExceptions(false), LastFrameInst(-1),
- ChainedParent(ChainedParent), Instructions() {}
+ : Begin(BeginFuncEHLabel), Function(Function),
+ ChainedParent(ChainedParent) {}
};
class UnwindEmitter {
public:
- static MCSection *getPDataSection(const MCSymbol *Function,
- MCContext &Context);
- static MCSection *getXDataSection(const MCSymbol *Function,
- MCContext &Context);
+ virtual ~UnwindEmitter();
- virtual ~UnwindEmitter() { }
-
- //
- // This emits the unwind info sections (.pdata and .xdata in PE/COFF).
- //
+ /// This emits the unwind info sections (.pdata and .xdata in PE/COFF).
virtual void Emit(MCStreamer &Streamer) const = 0;
virtual void EmitUnwindInfo(MCStreamer &Streamer, FrameInfo *FI) const = 0;
};
if (shouldEmitPersonality || shouldEmitLSDA) {
Asm->OutStreamer->PushSection();
- // Just switch sections to the right xdata section. This use of CurrentFnSym
- // assumes that we only emit the LSDA when ending the parent function.
- MCSection *XData = WinEH::UnwindEmitter::getXDataSection(Asm->CurrentFnSym,
- Asm->OutContext);
+ // Just switch sections to the right xdata section.
+ MCSection *XData = Asm->OutStreamer->getAssociatedXDataSection(
+ Asm->OutStreamer->getCurrentSectionOnly());
Asm->OutStreamer->SwitchSection(XData);
// Emit the tables appropriate to the personality function in use. If we
Name.push_back('.');
TM.getNameWithPrefix(Name, GV, Mang, true);
}
- unsigned UniqueID = ~0;
+ unsigned UniqueID = MCContext::GenericSectionID;
if (EmitUniqueSection && !UniqueSectionNames) {
UniqueID = *NextUniqueID;
(*NextUniqueID)++;
Selection = 0;
}
}
- return getContext().getCOFFSection(Name,
- Characteristics,
- Kind,
- COMDATSymName,
+
+ return getContext().getCOFFSection(Name, Characteristics, Kind, COMDATSymName,
Selection);
}
else
ComdatGV = GV;
+ unsigned UniqueID = MCContext::GenericSectionID;
+ if (EmitUniquedSection)
+ UniqueID = NextUniqueID++;
+
if (!ComdatGV->hasPrivateLinkage()) {
MCSymbol *Sym = TM.getSymbol(ComdatGV, Mang);
StringRef COMDATSymName = Sym->getName();
return getContext().getCOFFSection(Name, Characteristics, Kind,
- COMDATSymName, Selection);
+ COMDATSymName, Selection, UniqueID);
} else {
SmallString<256> TmpData;
Mang.getNameWithPrefix(TmpData, GV, /*CannotUsePrivateLabel=*/true);
return getContext().getCOFFSection(Name, Characteristics, Kind, TmpData,
- Selection);
+ Selection, UniqueID);
}
}
const char *Name = getCOFFSectionNameForUniqueGlobal(Kind);
unsigned Characteristics = getCOFFSectionFlags(Kind);
Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
+ unsigned UniqueID = NextUniqueID++;
return getContext().getCOFFSection(Name, Characteristics, Kind, COMDATSymName,
- COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE);
+ COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE, UniqueID);
}
void TargetLoweringObjectFileCOFF::
MCSection *TargetLoweringObjectFileCOFF::getStaticCtorSection(
unsigned Priority, const MCSymbol *KeySym) const {
return getContext().getAssociativeCOFFSection(
- cast<MCSectionCOFF>(StaticCtorSection), KeySym);
+ cast<MCSectionCOFF>(StaticCtorSection), KeySym, 0);
}
MCSection *TargetLoweringObjectFileCOFF::getStaticDtorSection(
unsigned Priority, const MCSymbol *KeySym) const {
return getContext().getAssociativeCOFFSection(
- cast<MCSectionCOFF>(StaticDtorSection), KeySym);
+ cast<MCSectionCOFF>(StaticDtorSection), KeySym, 0);
}
void TargetLoweringObjectFileCOFF::emitLinkerFlagsForGlobal(
// We only do this so the section switch that terminates the handler
// data block is visible.
WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo();
- MCSection *XData =
- WinEH::UnwindEmitter::getXDataSection(CurFrame->Function, getContext());
+ MCSection *TextSec = &CurFrame->Function->getSection();
+ MCSection *XData = getAssociatedXDataSection(TextSec);
SwitchSectionNoChange(XData);
OS << "\t.seh_handlerdata";
unsigned Characteristics,
SectionKind Kind,
StringRef COMDATSymName, int Selection,
+ unsigned UniqueID,
const char *BeginSymName) {
MCSymbol *COMDATSymbol = nullptr;
if (!COMDATSymName.empty()) {
COMDATSymName = COMDATSymbol->getName();
}
+
// Do the lookup, if we have a hit, return it.
- COFFSectionKey T{Section, COMDATSymName, Selection};
+ COFFSectionKey T{Section, COMDATSymName, Selection, UniqueID};
auto IterBool = COFFUniquingMap.insert(std::make_pair(T, nullptr));
auto Iter = IterBool.first;
if (!IterBool.second)
unsigned Characteristics,
SectionKind Kind,
const char *BeginSymName) {
- return getCOFFSection(Section, Characteristics, Kind, "", 0, BeginSymName);
+ return getCOFFSection(Section, Characteristics, Kind, "", 0, GenericSectionID,
+ BeginSymName);
}
MCSectionCOFF *MCContext::getCOFFSection(StringRef Section) {
- COFFSectionKey T{Section, "", 0};
+ COFFSectionKey T{Section, "", 0, GenericSectionID};
auto Iter = COFFUniquingMap.find(T);
if (Iter == COFFUniquingMap.end())
return nullptr;
}
MCSectionCOFF *MCContext::getAssociativeCOFFSection(MCSectionCOFF *Sec,
- const MCSymbol *KeySym) {
- // Return the normal section if we don't have to be associative.
- if (!KeySym)
+ const MCSymbol *KeySym,
+ unsigned UniqueID) {
+ // Return the normal section if we don't have to be associative or unique.
+ if (!KeySym && UniqueID == GenericSectionID)
return Sec;
- // Make an associative section with the same name and kind as the normal
- // section.
- unsigned Characteristics =
- Sec->getCharacteristics() | COFF::IMAGE_SCN_LNK_COMDAT;
+ // If we have a key symbol, make an associative section with the same name and
+ // kind as the normal section.
+ unsigned Characteristics = Sec->getCharacteristics();
+ if (KeySym) {
+ Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
+ return getCOFFSection(Sec->getSectionName(), Characteristics,
+ Sec->getKind(), KeySym->getName(),
+ COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE, UniqueID);
+ }
+
return getCOFFSection(Sec->getSectionName(), Characteristics, Sec->getKind(),
- KeySym->getName(),
- COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE);
+ "", 0, UniqueID);
}
MCSubtargetInfo &MCContext::getSubtargetCopy(const MCSubtargetInfo &STI) {
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCWin64EH.h"
+#include "llvm/Support/COFF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/raw_ostream.h"
WinFrameInfos.push_back(new WinEH::FrameInfo(Symbol, StartProc));
CurrentWinFrameInfo = WinFrameInfos.back();
+ CurrentWinFrameInfo->TextSection = getCurrentSectionOnly();
}
void MCStreamer::EmitWinCFIEndProc() {
WinFrameInfos.push_back(new WinEH::FrameInfo(CurrentWinFrameInfo->Function,
StartProc, CurrentWinFrameInfo));
CurrentWinFrameInfo = WinFrameInfos.back();
+ CurrentWinFrameInfo->TextSection = getCurrentSectionOnly();
}
void MCStreamer::EmitWinCFIEndChained() {
report_fatal_error("Chained unwind areas can't have handlers!");
}
+static MCSection *getWinCFISection(MCContext &Context, unsigned *NextWinCFIID,
+ MCSection *MainCFISec,
+ const MCSection *TextSec) {
+ // If this is the main .text section, use the main unwind info section.
+ if (TextSec == Context.getObjectFileInfo()->getTextSection())
+ return MainCFISec;
+
+ const auto *TextSecCOFF = cast<MCSectionCOFF>(TextSec);
+ unsigned UniqueID = TextSecCOFF->getOrAssignWinCFISectionID(NextWinCFIID);
+
+ // If this section is COMDAT, this unwind section should be COMDAT associative
+ // with its group.
+ const MCSymbol *KeySym = nullptr;
+ if (TextSecCOFF->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
+ KeySym = TextSecCOFF->getCOMDATSymbol();
+
+ return Context.getAssociativeCOFFSection(cast<MCSectionCOFF>(MainCFISec),
+ KeySym, UniqueID);
+}
+
+MCSection *MCStreamer::getAssociatedPDataSection(const MCSection *TextSec) {
+ return getWinCFISection(getContext(), &NextWinCFIID,
+ getContext().getObjectFileInfo()->getPDataSection(),
+ TextSec);
+}
+
+MCSection *MCStreamer::getAssociatedXDataSection(const MCSection *TextSec) {
+ return getWinCFISection(getContext(), &NextWinCFIID,
+ getContext().getObjectFileInfo()->getXDataSection(),
+ TextSec);
+}
+
void MCStreamer::EmitSyntaxDirective() {}
void MCStreamer::EmitWinCFIPushReg(unsigned Register) {
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Win64EH.h"
-namespace llvm {
+using namespace llvm;
// NOTE: All relocations generated here are 4-byte image-relative.
}
}
-namespace Win64EH {
-void UnwindEmitter::Emit(MCStreamer &Streamer) const {
- MCContext &Context = Streamer.getContext();
-
+void llvm::Win64EH::UnwindEmitter::Emit(MCStreamer &Streamer) const {
// Emit the unwind info structs first.
- for (const auto &CFI : Streamer.getWinFrameInfos()) {
- MCSection *XData = getXDataSection(CFI->Function, Context);
+ for (WinEH::FrameInfo *CFI : Streamer.getWinFrameInfos()) {
+ MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
Streamer.SwitchSection(XData);
- EmitUnwindInfo(Streamer, CFI);
+ ::EmitUnwindInfo(Streamer, CFI);
}
// Now emit RUNTIME_FUNCTION entries.
- for (const auto &CFI : Streamer.getWinFrameInfos()) {
- MCSection *PData = getPDataSection(CFI->Function, Context);
+ for (WinEH::FrameInfo *CFI : Streamer.getWinFrameInfos()) {
+ MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
Streamer.SwitchSection(PData);
EmitRuntimeFunction(Streamer, CFI);
}
}
-void UnwindEmitter::EmitUnwindInfo(MCStreamer &Streamer,
- WinEH::FrameInfo *info) const {
+void llvm::Win64EH::UnwindEmitter::EmitUnwindInfo(
+ MCStreamer &Streamer, WinEH::FrameInfo *info) const {
// Switch sections (the static function above is meant to be called from
// here and from Emit().
- MCContext &context = Streamer.getContext();
- MCSection *xdataSect = getXDataSection(info->Function, context);
- Streamer.SwitchSection(xdataSect);
+ MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
+ Streamer.SwitchSection(XData);
- llvm::EmitUnwindInfo(Streamer, info);
-}
+ ::EmitUnwindInfo(Streamer, info);
}
-} // End of namespace llvm
namespace llvm {
namespace WinEH {
-/// We can't have one section for all .pdata or .xdata because the Microsoft
-/// linker seems to want all code relocations to refer to the same object file
-/// section. If the code described is comdat, create a new comdat section
-/// associated with that comdat. If the code described is not in the main .text
-/// section, make a new section for it. Otherwise use the main unwind info
-/// section.
-static MCSection *getUnwindInfoSection(StringRef SecName,
- MCSectionCOFF *UnwindSec,
- const MCSymbol *Function,
- MCContext &Context) {
- if (Function && Function->isInSection()) {
- // If Function is in a COMDAT, get or create an unwind info section in that
- // COMDAT group.
- const MCSectionCOFF *FunctionSection =
- cast<MCSectionCOFF>(&Function->getSection());
- if (FunctionSection->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) {
- return Context.getAssociativeCOFFSection(
- UnwindSec, FunctionSection->getCOMDATSymbol());
- }
-
- // If Function is in a section other than .text, create a new .pdata section.
- // Otherwise use the plain .pdata section.
- if (const auto *Section = dyn_cast<MCSectionCOFF>(FunctionSection)) {
- StringRef CodeSecName = Section->getSectionName();
- if (CodeSecName == ".text")
- return UnwindSec;
-
- if (CodeSecName.startswith(".text$"))
- CodeSecName = CodeSecName.substr(6);
-
- return Context.getCOFFSection((SecName + Twine('$') + CodeSecName).str(),
- COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
- SectionKind::getData());
- }
- }
-
- return UnwindSec;
-
-}
-
-MCSection *UnwindEmitter::getPDataSection(const MCSymbol *Function,
- MCContext &Context) {
- MCSectionCOFF *PData =
- cast<MCSectionCOFF>(Context.getObjectFileInfo()->getPDataSection());
- return getUnwindInfoSection(".pdata", PData, Function, Context);
-}
-
-MCSection *UnwindEmitter::getXDataSection(const MCSymbol *Function,
- MCContext &Context) {
- MCSectionCOFF *XData =
- cast<MCSectionCOFF>(Context.getObjectFileInfo()->getXDataSection());
- return getUnwindInfoSection(".xdata", XData, Function, Context);
-}
+UnwindEmitter::~UnwindEmitter() {}
}
}
--- /dev/null
+# RUN: llvm-mc -filetype=obj -triple x86_64-pc-win32 %s | llvm-readobj -symbols | FileCheck %s
+
+# This assembly should make an object with two .text sections, two .xdata
+# sections, and two .pdata sections.
+
+ .def f;
+ .scl 2;
+ .type 32;
+ .endef
+ .section .text,"xr",discard,f
+ .globl f
+ .p2align 4, 0x90
+f: # @f
+.Ltmp0:
+.seh_proc f
+# BB#0:
+ subq $40, %rsp
+.Ltmp1:
+ .seh_stackalloc 40
+.Ltmp2:
+ .seh_endprologue
+ callq g
+ nop
+ addq $40, %rsp
+ retq
+ .seh_handlerdata
+ .section .text,"xr",discard,f
+.Ltmp3:
+ .seh_endproc
+
+ .def g;
+ .scl 3;
+ .type 32;
+ .endef
+ .section .text,"xr",associative,f
+ .p2align 4, 0x90
+g: # @g
+.Ltmp4:
+.seh_proc g
+# BB#0:
+.Ltmp5:
+ .seh_endprologue
+ retq
+ .seh_handlerdata
+ .section .text,"xr",associative,f
+.Ltmp6:
+ .seh_endproc
+
+
+# CHECK: Symbols [
+# CHECK: Symbol {
+# CHECK: Name: .text
+# CHECK: Section: .text (4)
+# CHECK: AuxSymbolCount: 1
+# CHECK: AuxSectionDef {
+# CHECK: Length: 15
+# CHECK: RelocationCount: 1
+# CHECK: LineNumberCount: 0
+# CHECK: Checksum: 0xE17CBB7
+# CHECK: Number: 4
+# CHECK: Selection: Any (0x2)
+# CHECK: }
+# CHECK: }
+# CHECK: Symbol {
+# CHECK: Name: .xdata
+# CHECK: Value: 0
+# CHECK: Section: .xdata (5)
+# CHECK: BaseType: Null (0x0)
+# CHECK: ComplexType: Null (0x0)
+# CHECK: StorageClass: Static (0x3)
+# CHECK: AuxSymbolCount: 1
+# CHECK: AuxSectionDef {
+# CHECK: Length: 8
+# CHECK: RelocationCount: 0
+# CHECK: LineNumberCount: 0
+# CHECK: Checksum: 0xFC539D1
+# CHECK: Number: 4
+# CHECK: Selection: Associative (0x5)
+# CHECK: AssocSection: .text (4)
+# CHECK: }
+# CHECK: }
+# CHECK: Symbol {
+# CHECK: Name: .text
+# CHECK: Value: 0
+# CHECK: Section: .text (6)
+# CHECK: BaseType: Null (0x0)
+# CHECK: ComplexType: Null (0x0)
+# CHECK: StorageClass: Static (0x3)
+# CHECK: AuxSymbolCount: 1
+# CHECK: AuxSectionDef {
+# CHECK: Length: 1
+# CHECK: RelocationCount: 0
+# CHECK: LineNumberCount: 0
+# CHECK: Checksum: 0x26D930A
+# CHECK: Number: 4
+# CHECK: Selection: Associative (0x5)
+# CHECK: AssocSection: .text (4)
+# CHECK: }
+# CHECK: }
+# CHECK: Symbol {
+# CHECK: Name: .xdata
+# CHECK: Value: 0
+# CHECK: Section: .xdata (7)
+# CHECK: BaseType: Null (0x0)
+# CHECK: ComplexType: Null (0x0)
+# CHECK: StorageClass: Static (0x3)
+# CHECK: AuxSymbolCount: 1
+# CHECK: AuxSectionDef {
+# CHECK: Length: 8
+# CHECK: RelocationCount: 0
+# CHECK: LineNumberCount: 0
+# CHECK: Checksum: 0xCCAA009E
+# CHECK: Number: 4
+# CHECK: Selection: Associative (0x5)
+# CHECK: AssocSection: .text (4)
+# CHECK: }
+# CHECK: }
+# CHECK: Symbol {
+# CHECK: Name: .pdata
+# CHECK: Value: 0
+# CHECK: Section: .pdata (8)
+# CHECK: BaseType: Null (0x0)
+# CHECK: ComplexType: Null (0x0)
+# CHECK: StorageClass: Static (0x3)
+# CHECK: AuxSymbolCount: 1
+# CHECK: AuxSectionDef {
+# CHECK: Length: 12
+# CHECK: RelocationCount: 3
+# CHECK: LineNumberCount: 0
+# CHECK: Checksum: 0xD92012AC
+# CHECK: Number: 4
+# CHECK: Selection: Associative (0x5)
+# CHECK: AssocSection: .text (4)
+# CHECK: }
+# CHECK: }
+# CHECK: Symbol {
+# CHECK: Name: .pdata
+# CHECK: Value: 0
+# CHECK: Section: .pdata (9)
+# CHECK: BaseType: Null (0x0)
+# CHECK: ComplexType: Null (0x0)
+# CHECK: StorageClass: Static (0x3)
+# CHECK: AuxSymbolCount: 1
+# CHECK: AuxSectionDef {
+# CHECK: Length: 12
+# CHECK: RelocationCount: 3
+# CHECK: LineNumberCount: 0
+# CHECK: Checksum: 0xCCAA009E
+# CHECK: Number: 4
+# CHECK: Selection: Associative (0x5)
+# CHECK: AssocSection: .text (4)
+# CHECK: }
+# CHECK: }
+# CHECK: ]
// This test ensures functions in custom sections get unwind info emitted in a
-// distinct .xdata section. Ideally we'd just emit a second .xdata section with
-// the same name and characteristics, but MC uniques sections by name and
-// characteristics, so that is not possible.
+// distinct .xdata section.
// RUN: llvm-mc -filetype=obj -triple x86_64-pc-win32 %s | llvm-readobj -s -sd | FileCheck %s
-// CHECK: Name: .xdata$foo
+// CHECK: Name: .xdata
// CHECK-NEXT: VirtualSize
// CHECK-NEXT: VirtualAddress
// CHECK-NEXT: RawDataSize: 8
// CHECK-NEXT: 0000: 01050200 05500402
// CHECK-NEXT: )
-// CHECK: Name: .xdata$.mytext
+// CHECK: Name: .xdata
// CHECK-NEXT: VirtualSize
// CHECK-NEXT: VirtualAddress
// CHECK-NEXT: RawDataSize: 8