diff options
| author | David Majnemer <david.majnemer@gmail.com> | 2015-05-30 04:56:02 +0000 |
|---|---|---|
| committer | David Majnemer <david.majnemer@gmail.com> | 2015-05-30 04:56:02 +0000 |
| commit | 4eecd30d1910ba784e98a7d628f0e2448712725f (patch) | |
| tree | 94b5f2352aff7eb8f73b7966f22cedc561f4abf3 /llvm/lib/MC | |
| parent | 9cc2516676063f190e04e231284a52cb45fdb273 (diff) | |
| download | bcm5719-llvm-4eecd30d1910ba784e98a7d628f0e2448712725f.tar.gz bcm5719-llvm-4eecd30d1910ba784e98a7d628f0e2448712725f.zip | |
[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.
llvm-svn: 238641
Diffstat (limited to 'llvm/lib/MC')
| -rw-r--r-- | llvm/lib/MC/MCAsmStreamer.cpp | 6 | ||||
| -rw-r--r-- | llvm/lib/MC/MCAssembler.cpp | 18 | ||||
| -rw-r--r-- | llvm/lib/MC/MCObjectFileInfo.cpp | 3 | ||||
| -rw-r--r-- | llvm/lib/MC/MCParser/COFFAsmParser.cpp | 17 | ||||
| -rw-r--r-- | llvm/lib/MC/MCStreamer.cpp | 3 | ||||
| -rw-r--r-- | llvm/lib/MC/WinCOFFObjectWriter.cpp | 44 | ||||
| -rw-r--r-- | llvm/lib/MC/WinCOFFStreamer.cpp | 15 |
7 files changed, 89 insertions, 17 deletions
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index 572634a99ec..8a5624bc333 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -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(); diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index c8e3371c8f3..cd14e33a7aa 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -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() { } diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp index e99f036af16..b6b72e6a798 100644 --- a/llvm/lib/MC/MCObjectFileInfo.cpp +++ b/llvm/lib/MC/MCObjectFileInfo.cpp @@ -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, diff --git a/llvm/lib/MC/MCParser/COFFAsmParser.cpp b/llvm/lib/MC/MCParser/COFFAsmParser.cpp index 82f7f228052..53b527fb9ef 100644 --- a/llvm/lib/MC/MCParser/COFFAsmParser.cpp +++ b/llvm/lib/MC/MCParser/COFFAsmParser.cpp @@ -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)) diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp index 280dbe28816..426bf90afcf 100644 --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -555,6 +555,9 @@ void MCStreamer::EmitWinCFIEndProlog() { CurrentWinFrameInfo->PrologEnd = Label; } +void MCStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) { +} + void MCStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) { } diff --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp index ddec16cd42e..2f6d1805605 100644 --- a/llvm/lib/MC/WinCOFFObjectWriter.cpp +++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp @@ -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()); diff --git a/llvm/lib/MC/WinCOFFStreamer.cpp b/llvm/lib/MC/WinCOFFStreamer.cpp index 72c18788068..abbe4164958 100644 --- a/llvm/lib/MC/WinCOFFStreamer.cpp +++ b/llvm/lib/MC/WinCOFFStreamer.cpp @@ -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()); |

