[WinCOFF] Add support for the .safeseh directive

.safeseh adds an entry to the .sxdata section to register all the
appropriate functions which may handle an exception.  This entry is not
a relocation to the symbol but instead the symbol table index of the
function.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238641 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Majnemer 2015-05-30 04:56:02 +00:00
parent 3279f2381b
commit e0d2a2939d
12 changed files with 120 additions and 19 deletions

View File

@ -60,7 +60,8 @@ public:
FT_Org,
FT_Dwarf,
FT_DwarfFrame,
FT_LEB
FT_LEB,
FT_SafeSEH
};
private:
@ -531,6 +532,28 @@ public:
}
};
class MCSafeSEHFragment : public MCFragment {
virtual void anchor();
const MCSymbol *Sym;
public:
MCSafeSEHFragment(const MCSymbol *Sym, MCSection *Sec = nullptr)
: MCFragment(FT_SafeSEH, Sec), Sym(Sym) {}
/// \name Accessors
/// @{
const MCSymbol *getSymbol() { return Sym; }
const MCSymbol *getSymbol() const { return Sym; }
/// @}
static bool classof(const MCFragment *F) {
return F->getKind() == MCFragment::FT_SafeSEH;
}
};
// FIXME: This really doesn't belong here. See comments below.
struct IndirectSymbolData {
MCSymbol *Symbol;

View File

@ -186,6 +186,7 @@ protected:
MCSection *DrectveSection;
MCSection *PDataSection;
MCSection *XDataSection;
MCSection *SXDataSection;
public:
void InitMCObjectFileInfo(StringRef TT, Reloc::Model RM, CodeModel::Model CM,
@ -321,6 +322,7 @@ public:
MCSection *getDrectveSection() const { return DrectveSection; }
MCSection *getPDataSection() const { return PDataSection; }
MCSection *getXDataSection() const { return XDataSection; }
MCSection *getSXDataSection() const { return SXDataSection; }
MCSection *getEHFrameSection() {
if (!EHFrameSection)

View File

@ -434,6 +434,8 @@ public:
/// \brief Marks the end of the symbol definition.
virtual void EndCOFFSymbolDef();
virtual void EmitCOFFSafeSEH(MCSymbol const *Symbol);
/// \brief Emits a COFF section index.
///
/// \param Symbol - Symbol the section number relocation should point to.

View File

@ -50,6 +50,7 @@ public:
void EmitCOFFSymbolStorageClass(int StorageClass) override;
void EmitCOFFSymbolType(int Type) override;
void EndCOFFSymbolDef() override;
void EmitCOFFSafeSEH(MCSymbol const *Symbol) override;
void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
void EmitCOFFSecRel32(MCSymbol const *Symbol) override;
void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;

View File

@ -162,7 +162,8 @@ namespace COFF {
SF_ClassMask = 0x00FF0000,
SF_ClassShift = 16,
SF_WeakExternal = 0x01000000
SF_WeakExternal = 0x01000000,
SF_SafeSEH = 0x02000000,
};
enum SymbolSectionNumber : int32_t {

View File

@ -136,6 +136,7 @@ public:
void EmitCOFFSymbolStorageClass(int StorageClass) override;
void EmitCOFFSymbolType(int Type) override;
void EndCOFFSymbolDef() override;
void EmitCOFFSafeSEH(MCSymbol const *Symbol) override;
void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
void EmitCOFFSecRel32(MCSymbol const *Symbol) override;
void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
@ -486,6 +487,11 @@ void MCAsmStreamer::EndCOFFSymbolDef() {
EmitEOL();
}
void MCAsmStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
OS << "\t.safeseh\t" << *Symbol;
EmitEOL();
}
void MCAsmStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
OS << "\t.secidx\t" << *Symbol;
EmitEOL();

View File

@ -473,6 +473,9 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout,
case MCFragment::FT_LEB:
return cast<MCLEBFragment>(F).getContents().size();
case MCFragment::FT_SafeSEH:
return 4;
case MCFragment::FT_Align: {
const MCAlignFragment &AF = cast<MCAlignFragment>(F);
unsigned Offset = Layout.getFragmentOffset(&AF);
@ -705,6 +708,12 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
break;
}
case MCFragment::FT_SafeSEH: {
const MCSafeSEHFragment &SF = cast<MCSafeSEHFragment>(F);
OW->Write32(SF.getSymbol()->getIndex());
break;
}
case MCFragment::FT_Org: {
++stats::EmittedOrgFragments;
const MCOrgFragment &OF = cast<MCOrgFragment>(F);
@ -1086,6 +1095,7 @@ void MCFragment::dump() {
case MCFragment::FT_Dwarf: OS << "MCDwarfFragment"; break;
case MCFragment::FT_DwarfFrame: OS << "MCDwarfCallFrameFragment"; break;
case MCFragment::FT_LEB: OS << "MCLEBFragment"; break;
case MCFragment::FT_SafeSEH: OS << "MCSafeSEHFragment"; break;
}
OS << "<MCFragment " << (void*) this << " LayoutOrder:" << LayoutOrder
@ -1178,6 +1188,13 @@ void MCFragment::dump() {
OS << " Value:" << LF->getValue() << " Signed:" << LF->isSigned();
break;
}
case MCFragment::FT_SafeSEH: {
const MCSafeSEHFragment *F = cast<MCSafeSEHFragment>(this);
OS << "\n ";
OS << " Sym:";
F->getSymbol()->print(OS);
break;
}
}
OS << ">";
}
@ -1215,5 +1232,6 @@ void MCAlignFragment::anchor() { }
void MCFillFragment::anchor() { }
void MCOrgFragment::anchor() { }
void MCLEBFragment::anchor() { }
void MCSafeSEHFragment::anchor() { }
void MCDwarfLineAddrFragment::anchor() { }
void MCDwarfCallFrameFragment::anchor() { }

View File

@ -714,6 +714,9 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) {
".xdata", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ,
SectionKind::getDataRel());
SXDataSection = Ctx->getCOFFSection(".sxdata", COFF::IMAGE_SCN_LNK_INFO,
SectionKind::getMetadata());
TLSDataSection = Ctx->getCOFFSection(
".tls$", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ |
COFF::IMAGE_SCN_MEM_WRITE,

View File

@ -57,6 +57,7 @@ class COFFAsmParser : public MCAsmParserExtension {
addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh");
addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
// Win64 EH directives.
@ -118,6 +119,7 @@ class COFFAsmParser : public MCAsmParserExtension {
bool ParseDirectiveEndef(StringRef, SMLoc);
bool ParseDirectiveSecRel32(StringRef, SMLoc);
bool ParseDirectiveSecIdx(StringRef, SMLoc);
bool ParseDirectiveSafeSEH(StringRef, SMLoc);
bool parseCOMDATType(COFF::COMDATType &Type);
bool ParseDirectiveLinkOnce(StringRef, SMLoc);
@ -453,6 +455,21 @@ bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
return false;
}
bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {
StringRef SymbolID;
if (getParser().parseIdentifier(SymbolID))
return TokError("expected identifier in directive");
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in directive");
MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
Lex();
getStreamer().EmitCOFFSafeSEH(Symbol);
return false;
}
bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
StringRef SymbolID;
if (getParser().parseIdentifier(SymbolID))

View File

@ -555,6 +555,9 @@ void MCStreamer::EmitWinCFIEndProlog() {
CurrentWinFrameInfo->PrologEnd = Label;
}
void MCStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
}
void MCStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
}

View File

@ -21,6 +21,7 @@
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSectionCOFF.h"
@ -76,6 +77,13 @@ public:
void set_name_offset(uint32_t Offset);
bool should_keep() const;
int64_t getIndex() const { return Index; }
void setIndex(int Value) {
Index = Value;
if (MC)
MC->setIndex(static_cast<uint32_t>(Value));
}
};
// This class contains staging data for a COFF relocation entry.
@ -219,6 +227,10 @@ bool COFFSymbol::should_keep() const {
return true;
}
// if this is a safeseh handler, keep it
if (MC && (MC->getFlags() & COFF::SF_SafeSEH))
return true;
// if the section its in is being droped, drop it
if (Section->Number == -1)
return false;
@ -416,11 +428,13 @@ void WinCOFFObjectWriter::DefineSymbol(const MCSymbol &Symbol,
const MCSymbol *Base = Layout.getBaseSymbol(Symbol);
coff_symbol->Data.Value = getSymbolValue(Symbol, Layout);
coff_symbol->Data.Type = (Symbol.getFlags() & 0x0000FFFF) >> 0;
coff_symbol->Data.StorageClass = (Symbol.getFlags() & 0x00FF0000) >> 16;
coff_symbol->Data.Type =
(Symbol.getFlags() & COFF::SF_TypeMask) >> COFF::SF_TypeShift;
coff_symbol->Data.StorageClass =
(Symbol.getFlags() & COFF::SF_ClassMask) >> COFF::SF_ClassShift;
// If no storage class was specified in the streamer, define it here.
if (coff_symbol->Data.StorageClass == 0) {
if (coff_symbol->Data.StorageClass == COFF::IMAGE_SYM_CLASS_NULL) {
bool IsExternal = Symbol.isExternal() ||
(!Symbol.getFragment() && !Symbol.isVariable());
@ -828,13 +842,9 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,
UseBigObj = NumberOfSections > COFF::MaxNumberOfSections16;
DenseMap<COFFSection *, int32_t> SectionIndices(
NextPowerOf2(NumberOfSections));
// Assign section numbers.
size_t Number = 1;
for (const auto &Section : Sections) {
SectionIndices[Section.get()] = Number;
Section->Number = Number;
Section->Symbol->Data.SectionNumber = Number;
Section->Symbol->Aux[0].Aux.SectionDefinition.Number = Number;
@ -877,12 +887,13 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,
if (Symbol->Section)
Symbol->Data.SectionNumber = Symbol->Section->Number;
if (Symbol->should_keep()) {
Symbol->Index = Header.NumberOfSymbols++;
Symbol->setIndex(Header.NumberOfSymbols++);
// Update auxiliary symbol info.
Symbol->Data.NumberOfAuxSymbols = Symbol->Aux.size();
Header.NumberOfSymbols += Symbol->Data.NumberOfAuxSymbols;
} else
Symbol->Index = -1;
} else {
Symbol->setIndex(-1);
}
}
// Build string table.
@ -904,11 +915,11 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,
// Fixup weak external references.
for (auto &Symbol : Symbols) {
if (Symbol->Other) {
assert(Symbol->Index != -1);
assert(Symbol->getIndex() != -1);
assert(Symbol->Aux.size() == 1 && "Symbol must contain one aux symbol!");
assert(Symbol->Aux[0].AuxType == ATWeakExternal &&
"Symbol's aux symbol must be a Weak External!");
Symbol->Aux[0].Aux.WeakExternal.TagIndex = Symbol->Other->Index;
Symbol->Aux[0].Aux.WeakExternal.TagIndex = Symbol->Other->getIndex();
}
}
@ -934,8 +945,7 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,
if (Assoc->Number == -1)
continue;
Section->Symbol->Aux[0].Aux.SectionDefinition.Number =
SectionIndices[Assoc];
Section->Symbol->Aux[0].Aux.SectionDefinition.Number = Assoc->Number;
}
// Assign file offsets to COFF object file structures.
@ -984,8 +994,8 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,
offset += COFF::RelocationSize * Sec->Relocations.size();
for (auto &Relocation : Sec->Relocations) {
assert(Relocation.Symb->Index != -1);
Relocation.Data.SymbolTableIndex = Relocation.Symb->Index;
assert(Relocation.Symb->getIndex() != -1);
Relocation.Data.SymbolTableIndex = Relocation.Symb->getIndex();
}
}
@ -1067,7 +1077,7 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,
"Header::PointerToSymbolTable is insane!");
for (auto &Symbol : Symbols)
if (Symbol->Index != -1)
if (Symbol->getIndex() != -1)
WriteSymbol(*Symbol);
OS.write(Strings.data().data(), Strings.data().size());

View File

@ -158,6 +158,21 @@ void MCWinCOFFStreamer::EndCOFFSymbolDef() {
CurSymbol = nullptr;
}
void MCWinCOFFStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
if (Symbol->getFlags() & COFF::SF_SafeSEH)
return;
MCSection *SXData = getContext().getObjectFileInfo()->getSXDataSection();
getAssembler().registerSection(*SXData);
if (SXData->getAlignment() < 4)
SXData->setAlignment(4);
new MCSafeSEHFragment(Symbol, SXData);
getAssembler().registerSymbol(*Symbol);
Symbol->modifyFlags(COFF::SF_SafeSEH, COFF::SF_SafeSEH);
}
void MCWinCOFFStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
MCDataFragment *DF = getOrCreateDataFragment();
const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext());