mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
[MC] Create unique .pdata sections for every .text section
Summary: This adds a unique ID to the COFF section uniquing map, similar to the one we have for ELF. The unique id is not currently exposed via the assembler because we don't have a use case for it yet. Users generally create .pdata with the .seh_* family of directives, and the assembler internally needs to produce .pdata and .xdata sections corresponding to the code section. The association between .text sections and the assembler-created .xdata and .pdata sections is maintained as an ID field of MCSectionCOFF. The CFI-related sections are created with the given unique ID, so if more code is added to the same text section, we can find and reuse the CFI sections that were already created. Reviewers: majnemer, rafael Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D19376 llvm-svn: 268331
This commit is contained in:
parent
b3f499f033
commit
75b594b1e8
@ -140,6 +140,8 @@ public:
|
||||
|
||||
|
||||
class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile {
|
||||
mutable unsigned NextUniqueID = 0;
|
||||
|
||||
public:
|
||||
~TargetLoweringObjectFileCOFF() override {}
|
||||
|
||||
|
@ -200,16 +200,19 @@ namespace llvm {
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
@ -315,6 +318,13 @@ namespace llvm {
|
||||
/// \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,
|
||||
@ -382,6 +392,7 @@ namespace llvm {
|
||||
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,
|
||||
@ -394,8 +405,9 @@ namespace llvm {
|
||||
/// 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);
|
||||
|
@ -32,6 +32,13 @@ class MCSectionCOFF final : public MCSection {
|
||||
/// 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;
|
||||
@ -71,6 +78,12 @@ public:
|
||||
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; }
|
||||
};
|
||||
|
||||
|
@ -183,6 +183,12 @@ class MCStreamer {
|
||||
/// 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);
|
||||
|
||||
@ -720,6 +726,14 @@ public:
|
||||
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.
|
||||
|
@ -13,11 +13,9 @@
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
class MCContext;
|
||||
class MCSection;
|
||||
class MCStreamer;
|
||||
class MCSymbol;
|
||||
class StringRef;
|
||||
|
||||
namespace WinEH {
|
||||
struct Instruction {
|
||||
@ -31,50 +29,35 @@ 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;
|
||||
};
|
||||
|
@ -124,10 +124,9 @@ void WinException::endFunction(const MachineFunction *MF) {
|
||||
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
|
||||
|
@ -316,7 +316,7 @@ selectELFSectionForGlobal(MCContext &Ctx, const GlobalValue *GV,
|
||||
Name.push_back('.');
|
||||
TM.getNameWithPrefix(Name, GV, Mang, true);
|
||||
}
|
||||
unsigned UniqueID = ~0;
|
||||
unsigned UniqueID = MCContext::GenericSectionID;
|
||||
if (EmitUniqueSection && !UniqueSectionNames) {
|
||||
UniqueID = *NextUniqueID;
|
||||
(*NextUniqueID)++;
|
||||
@ -924,10 +924,8 @@ MCSection *TargetLoweringObjectFileCOFF::getExplicitSectionGlobal(
|
||||
Selection = 0;
|
||||
}
|
||||
}
|
||||
return getContext().getCOFFSection(Name,
|
||||
Characteristics,
|
||||
Kind,
|
||||
COMDATSymName,
|
||||
|
||||
return getContext().getCOFFSection(Name, Characteristics, Kind, COMDATSymName,
|
||||
Selection);
|
||||
}
|
||||
|
||||
@ -968,16 +966,20 @@ MCSection *TargetLoweringObjectFileCOFF::SelectSectionForGlobal(
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1031,9 +1033,10 @@ MCSection *TargetLoweringObjectFileCOFF::getSectionForJumpTable(
|
||||
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::
|
||||
@ -1068,13 +1071,13 @@ emitModuleFlags(MCStreamer &Streamer,
|
||||
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(
|
||||
|
@ -1288,8 +1288,8 @@ void MCAsmStreamer::EmitWinEHHandlerData() {
|
||||
// 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";
|
||||
|
@ -372,6 +372,7 @@ MCSectionCOFF *MCContext::getCOFFSection(StringRef Section,
|
||||
unsigned Characteristics,
|
||||
SectionKind Kind,
|
||||
StringRef COMDATSymName, int Selection,
|
||||
unsigned UniqueID,
|
||||
const char *BeginSymName) {
|
||||
MCSymbol *COMDATSymbol = nullptr;
|
||||
if (!COMDATSymName.empty()) {
|
||||
@ -379,8 +380,9 @@ MCSectionCOFF *MCContext::getCOFFSection(StringRef Section,
|
||||
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)
|
||||
@ -402,11 +404,12 @@ MCSectionCOFF *MCContext::getCOFFSection(StringRef Section,
|
||||
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;
|
||||
@ -414,18 +417,24 @@ MCSectionCOFF *MCContext::getCOFFSection(StringRef Section) {
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -19,8 +19,10 @@
|
||||
#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"
|
||||
@ -446,6 +448,7 @@ void MCStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol) {
|
||||
|
||||
WinFrameInfos.push_back(new WinEH::FrameInfo(Symbol, StartProc));
|
||||
CurrentWinFrameInfo = WinFrameInfos.back();
|
||||
CurrentWinFrameInfo->TextSection = getCurrentSectionOnly();
|
||||
}
|
||||
|
||||
void MCStreamer::EmitWinCFIEndProc() {
|
||||
@ -467,6 +470,7 @@ void MCStreamer::EmitWinCFIStartChained() {
|
||||
WinFrameInfos.push_back(new WinEH::FrameInfo(CurrentWinFrameInfo->Function,
|
||||
StartProc, CurrentWinFrameInfo));
|
||||
CurrentWinFrameInfo = WinFrameInfos.back();
|
||||
CurrentWinFrameInfo->TextSection = getCurrentSectionOnly();
|
||||
}
|
||||
|
||||
void MCStreamer::EmitWinCFIEndChained() {
|
||||
@ -502,6 +506,38 @@ void MCStreamer::EmitWinEHHandlerData() {
|
||||
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) {
|
||||
|
@ -17,7 +17,7 @@
|
||||
#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.
|
||||
|
||||
@ -218,35 +218,29 @@ static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
@ -19,60 +19,7 @@
|
||||
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() {}
|
||||
|
||||
}
|
||||
}
|
||||
|
154
test/MC/COFF/seh-section-2.s
Normal file
154
test/MC/COFF/seh-section-2.s
Normal file
@ -0,0 +1,154 @@
|
||||
# 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: ]
|
@ -1,10 +1,8 @@
|
||||
// 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
|
||||
@ -22,7 +20,7 @@
|
||||
// CHECK-NEXT: 0000: 01050200 05500402
|
||||
// CHECK-NEXT: )
|
||||
|
||||
// CHECK: Name: .xdata$.mytext
|
||||
// CHECK: Name: .xdata
|
||||
// CHECK-NEXT: VirtualSize
|
||||
// CHECK-NEXT: VirtualAddress
|
||||
// CHECK-NEXT: RawDataSize: 8
|
||||
|
Loading…
Reference in New Issue
Block a user