From 43a811852d4d37639b2fe42cbf2e6b76bba5fff7 Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Tue, 11 Sep 2018 22:35:01 +0000 Subject: [PATCH] [PDB] Write FPO Data to the PDB. llvm-svn: 342003 --- .../CodeView/DebugFrameDataSubsection.h | 9 ++- .../DebugInfo/PDB/Native/DbiStreamBuilder.h | 10 +++- .../CodeView/DebugFrameDataSubsection.cpp | 30 ++++++++-- lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp | 31 +++++++++- lib/ObjectYAML/CodeViewYAMLDebugSections.cpp | 2 +- tools/llvm-pdbutil/DumpOutputStyle.cpp | 58 +++++++++++++++++++ tools/llvm-pdbutil/DumpOutputStyle.h | 1 + tools/llvm-pdbutil/llvm-pdbutil.cpp | 4 ++ tools/llvm-pdbutil/llvm-pdbutil.h | 1 + 9 files changed, 132 insertions(+), 14 deletions(-) diff --git a/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h b/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h index 1e329c7c3f1..f74120a5360 100644 --- a/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h +++ b/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h @@ -26,11 +26,12 @@ public: } Error initialize(BinaryStreamReader Reader); + Error initialize(BinaryStreamRef Stream); FixedStreamArray::Iterator begin() const { return Frames.begin(); } FixedStreamArray::Iterator end() const { return Frames.end(); } - const void *getRelocPtr() const { return RelocPtr; } + const uint32_t *getRelocPtr() const { return RelocPtr; } private: const uint32_t *RelocPtr = nullptr; @@ -39,8 +40,9 @@ private: class DebugFrameDataSubsection final : public DebugSubsection { public: - DebugFrameDataSubsection() - : DebugSubsection(DebugSubsectionKind::FrameData) {} + DebugFrameDataSubsection(bool IncludeRelocPtr) + : DebugSubsection(DebugSubsectionKind::FrameData), + IncludeRelocPtr(IncludeRelocPtr) {} static bool classof(const DebugSubsection *S) { return S->kind() == DebugSubsectionKind::FrameData; } @@ -52,6 +54,7 @@ public: void setFrames(ArrayRef Frames); private: + bool IncludeRelocPtr = false; std::vector Frames; }; } diff --git a/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h b/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h index 51befcdac77..826e0c179cc 100644 --- a/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h +++ b/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h @@ -15,6 +15,7 @@ #include "llvm/BinaryFormat/COFF.h" #include "llvm/Support/Error.h" +#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h" #include "llvm/DebugInfo/PDB/Native/RawConstants.h" @@ -24,6 +25,9 @@ #include "llvm/Support/Endian.h" namespace llvm { +namespace codeview { +struct FrameData; +} namespace msf { class MSFBuilder; } @@ -65,6 +69,7 @@ public: void setGlobalsStreamIndex(uint32_t Index); void setPublicsStreamIndex(uint32_t Index); void setSymbolRecordStreamIndex(uint32_t Index); + void addFrameData(const codeview::FrameData &FD); Expected addModuleInfo(StringRef ModuleName); Error addModuleSourceFile(DbiModuleDescriptorBuilder &Module, StringRef File); @@ -84,7 +89,8 @@ public: private: struct DebugStream { - ArrayRef Data; + std::function WriteFn; + uint32_t Size = 0; uint16_t StreamNumber = kInvalidStreamIndex; }; @@ -117,6 +123,8 @@ private: std::vector> ModiList; + Optional FrameData; + StringMap SourceFileNames; PDBStringTableBuilder ECNamesBuilder; diff --git a/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp b/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp index fd558aa9cc8..5881bf177a5 100644 --- a/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp +++ b/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp @@ -14,8 +14,11 @@ using namespace llvm; using namespace llvm::codeview; Error DebugFrameDataSubsectionRef::initialize(BinaryStreamReader Reader) { - if (auto EC = Reader.readObject(RelocPtr)) - return EC; + if (Reader.bytesRemaining() % sizeof(FrameData) != 0) { + if (auto EC = Reader.readObject(RelocPtr)) + return EC; + } + if (Reader.bytesRemaining() % sizeof(FrameData) != 0) return make_error(cv_error_code::corrupt_record, "Invalid frame data record format!"); @@ -26,15 +29,30 @@ Error DebugFrameDataSubsectionRef::initialize(BinaryStreamReader Reader) { return Error::success(); } +Error DebugFrameDataSubsectionRef::initialize(BinaryStreamRef Section) { + BinaryStreamReader Reader(Section); + return initialize(Reader); +} + uint32_t DebugFrameDataSubsection::calculateSerializedSize() const { - return 4 + sizeof(FrameData) * Frames.size(); + uint32_t Size = sizeof(FrameData) * Frames.size(); + if (IncludeRelocPtr) + Size += sizeof(uint32_t); + return Size; } Error DebugFrameDataSubsection::commit(BinaryStreamWriter &Writer) const { - if (auto EC = Writer.writeInteger(0)) - return EC; + if (IncludeRelocPtr) { + if (auto EC = Writer.writeInteger(0)) + return EC; + } - if (auto EC = Writer.writeArray(makeArrayRef(Frames))) + std::vector SortedFrames(Frames.begin(), Frames.end()); + std::sort(SortedFrames.begin(), SortedFrames.end(), + [](const FrameData &LHS, const FrameData &RHS) { + return LHS.RvaStart < RHS.RvaStart; + }); + if (auto EC = Writer.writeArray(makeArrayRef(SortedFrames))) return EC; return Error::success(); } diff --git a/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp b/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp index f6043bfd7cf..9b045f916db 100644 --- a/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp @@ -11,6 +11,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/BinaryFormat/COFF.h" +#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h" @@ -74,10 +75,23 @@ void DbiStreamBuilder::setPublicsStreamIndex(uint32_t Index) { PublicsStreamIndex = Index; } +void DbiStreamBuilder::addFrameData(const codeview::FrameData &FD) { + if (!FrameData.hasValue()) + FrameData.emplace(false); + + FrameData->addFrameData(FD); +} + Error DbiStreamBuilder::addDbgStream(pdb::DbgHeaderType Type, ArrayRef Data) { + assert(Type != DbgHeaderType::NewFPO && + "NewFPO data should be written via addFrameData()!"); + DbgStreams[(int)Type].emplace(); - DbgStreams[(int)Type]->Data = Data; + DbgStreams[(int)Type]->Size = Data.size(); + DbgStreams[(int)Type]->WriteFn = [Data](BinaryStreamWriter &Writer) { + return Writer.writeArray(Data); + }; return Error::success(); } @@ -272,10 +286,20 @@ Error DbiStreamBuilder::finalize() { } Error DbiStreamBuilder::finalizeMsfLayout() { + if (FrameData.hasValue()) { + DbgStreams[(int)DbgHeaderType::NewFPO].emplace(); + DbgStreams[(int)DbgHeaderType::NewFPO]->Size = + FrameData->calculateSerializedSize(); + DbgStreams[(int)DbgHeaderType::NewFPO]->WriteFn = + [this](BinaryStreamWriter &Writer) { + return FrameData->commit(Writer); + }; + } + for (auto &S : DbgStreams) { if (!S.hasValue()) continue; - auto ExpectedIndex = Msf.addStream(S->Data.size()); + auto ExpectedIndex = Msf.addStream(S->Size); if (!ExpectedIndex) return ExpectedIndex.takeError(); S->StreamNumber = *ExpectedIndex; @@ -406,7 +430,8 @@ Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout, auto WritableStream = WritableMappedBlockStream::createIndexedStream( Layout, MsfBuffer, Stream->StreamNumber, Allocator); BinaryStreamWriter DbgStreamWriter(*WritableStream); - if (auto EC = DbgStreamWriter.writeArray(Stream->Data)) + + if (auto EC = Stream->WriteFn(DbgStreamWriter)) return EC; } diff --git a/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp b/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp index 6debd8ab0c6..4deeae87801 100644 --- a/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp +++ b/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp @@ -511,7 +511,7 @@ std::shared_ptr YAMLFrameDataSubsection::toCodeViewSubsection( const codeview::StringsAndChecksums &SC) const { assert(SC.hasStrings()); - auto Result = std::make_shared(); + auto Result = std::make_shared(true); for (const auto &YF : Frames) { codeview::FrameData F; F.CodeSize = YF.CodeSize; diff --git a/tools/llvm-pdbutil/DumpOutputStyle.cpp b/tools/llvm-pdbutil/DumpOutputStyle.cpp index c628b148f60..60f79f05e01 100644 --- a/tools/llvm-pdbutil/DumpOutputStyle.cpp +++ b/tools/llvm-pdbutil/DumpOutputStyle.cpp @@ -22,6 +22,7 @@ #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" #include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h" #include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h" #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" @@ -142,6 +143,11 @@ Error DumpOutputStyle::dump() { return EC; } + if (opts::dump::DumpFpo) { + if (auto EC = dumpFpo()) + return EC; + } + if (File.isObj()) { if (opts::dump::DumpTypes || !opts::dump::DumpTypeIndex.empty() || opts::dump::DumpTypeExtras) @@ -985,6 +991,58 @@ Error DumpOutputStyle::dumpXme() { return Error::success(); } +Error DumpOutputStyle::dumpFpo() { + printHeader(P, "New FPO Data"); + + if (!File.isPdb()) { + printStreamNotValidForObj(); + return Error::success(); + } + + PDBFile &File = getPdb(); + if (!File.hasPDBDbiStream()) { + printStreamNotPresent("DBI"); + return Error::success(); + } + + ExitOnError Err("Error dumping fpo data:"); + + auto &Dbi = Err(File.getPDBDbiStream()); + + uint32_t Index = Dbi.getDebugStreamIndex(DbgHeaderType::NewFPO); + if (Index == kInvalidStreamIndex) { + printStreamNotPresent("New FPO"); + return Error::success(); + } + + std::unique_ptr NewFpo = File.createIndexedStream(Index); + + DebugFrameDataSubsectionRef FDS; + if (auto EC = FDS.initialize(*NewFpo)) + return make_error(raw_error_code::corrupt_file, + "Invalid new fpo stream"); + + P.printLine(" RVA | Code | Locals | Params | Stack | Prolog | Saved Regs " + "| Has SEH | Has C++EH | Start | Program"); + for (const FrameData &FD : FDS) { + bool IsFuncStart = FD.Flags & FrameData::IsFunctionStart; + bool HasEH = FD.Flags & FrameData::HasEH; + bool HasSEH = FD.Flags & FrameData::HasSEH; + + auto &StringTable = Err(File.getStringTable()); + + auto Program = Err(StringTable.getStringForID(FD.FrameFunc)); + P.formatLine("{0:X-8} | {1,4} | {2,6} | {3,6} | {4,5} | {5,6} | {6,10} | " + "{7,7} | {8,9} | {9,5} | {10}", + uint32_t(FD.RvaStart), uint32_t(FD.CodeSize), + uint32_t(FD.LocalSize), uint32_t(FD.ParamsSize), + uint32_t(FD.MaxStackSize), uint16_t(FD.PrologSize), + uint16_t(FD.SavedRegsSize), HasSEH, HasEH, IsFuncStart, + Program); + } + return Error::success(); +} + Error DumpOutputStyle::dumpStringTableFromPdb() { AutoIndent Indent(P); auto IS = getPdb().getStringTable(); diff --git a/tools/llvm-pdbutil/DumpOutputStyle.h b/tools/llvm-pdbutil/DumpOutputStyle.h index 5232a07fbf1..946a30539a8 100644 --- a/tools/llvm-pdbutil/DumpOutputStyle.h +++ b/tools/llvm-pdbutil/DumpOutputStyle.h @@ -85,6 +85,7 @@ private: Error dumpInlineeLines(); Error dumpXmi(); Error dumpXme(); + Error dumpFpo(); Error dumpTpiStream(uint32_t StreamIdx); Error dumpTypesFromObjectFile(); Error dumpModules(); diff --git a/tools/llvm-pdbutil/llvm-pdbutil.cpp b/tools/llvm-pdbutil/llvm-pdbutil.cpp index 0a4fb49284d..7c34cc6dc07 100644 --- a/tools/llvm-pdbutil/llvm-pdbutil.cpp +++ b/tools/llvm-pdbutil/llvm-pdbutil.cpp @@ -501,6 +501,9 @@ cl::opt cl::desc("dump CodeView symbol record raw bytes"), cl::cat(SymbolOptions), cl::sub(DumpSubcommand)); +cl::opt DumpFpo("fpo", cl::desc("dump FPO records"), + cl::cat(SymbolOptions), cl::sub(DumpSubcommand)); + // MODULE & FILE OPTIONS cl::opt DumpModules("modules", cl::desc("dump compiland information"), cl::cat(FileOptions), cl::sub(DumpSubcommand)); @@ -1372,6 +1375,7 @@ int main(int Argc, const char **Argv) { if (opts::DumpSubcommand) { if (opts::dump::RawAll) { opts::dump::DumpGlobals = true; + opts::dump::DumpFpo = true; opts::dump::DumpInlineeLines = true; opts::dump::DumpIds = true; opts::dump::DumpIdExtras = true; diff --git a/tools/llvm-pdbutil/llvm-pdbutil.h b/tools/llvm-pdbutil/llvm-pdbutil.h index 7496adaeb62..1524f83560c 100644 --- a/tools/llvm-pdbutil/llvm-pdbutil.h +++ b/tools/llvm-pdbutil/llvm-pdbutil.h @@ -171,6 +171,7 @@ extern llvm::cl::opt DumpSectionContribs; extern llvm::cl::opt DumpSectionMap; extern llvm::cl::opt DumpModules; extern llvm::cl::opt DumpModuleFiles; +extern llvm::cl::opt DumpFpo; extern llvm::cl::opt RawAll; }