Index: llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiStream.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiStream.h +++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiStream.h @@ -10,6 +10,7 @@ #define LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAM_H #include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" #include "llvm/DebugInfo/PDB/Native/DbiModuleList.h" @@ -79,7 +80,10 @@ FixedStreamArray getSectionHeaders() const; - FixedStreamArray getFpoRecords(); + bool hasOldFpoRecords() const; + FixedStreamArray getOldFpoRecords() const; + bool hasNewFpoRecords() const; + const codeview::DebugFrameDataSubsectionRef &getNewFpoRecords() const; FixedStreamArray getSectionMap() const; void visitSectionContributions(ISectionContribVisitor &Visitor) const; @@ -90,7 +94,11 @@ Error initializeSectionContributionData(); Error initializeSectionHeadersData(PDBFile *Pdb); Error initializeSectionMapData(); - Error initializeFpoRecords(PDBFile *Pdb); + Error initializeOldFpoRecords(PDBFile *Pdb); + Error initializeNewFpoRecords(PDBFile *Pdb); + + Expected> + createIndexedStreamForHeaderType(PDBFile *Pdb, DbgHeaderType Type) const; std::unique_ptr Stream; @@ -116,8 +124,11 @@ std::unique_ptr SectionHeaderStream; FixedStreamArray SectionHeaders; - std::unique_ptr FpoStream; - FixedStreamArray FpoRecords; + std::unique_ptr OldFpoStream; + FixedStreamArray OldFpoRecords; + + std::unique_ptr NewFpoStream; + codeview::DebugFrameDataSubsectionRef NewFpoRecords; const DbiStreamHeader *Header; }; Index: llvm/trunk/lib/DebugInfo/PDB/Native/DbiStream.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/PDB/Native/DbiStream.cpp +++ llvm/trunk/lib/DebugInfo/PDB/Native/DbiStream.cpp @@ -126,8 +126,10 @@ return EC; if (auto EC = initializeSectionMapData()) return EC; - if (auto EC = initializeFpoRecords(Pdb)) + if (auto EC = initializeOldFpoRecords(Pdb)) return EC; + if (auto EC = initializeNewFpoRecords(Pdb)) + return EC; if (Reader.bytesRemaining() > 0) return make_error(raw_error_code::corrupt_file, @@ -200,8 +202,16 @@ return SectionHeaders; } -FixedStreamArray DbiStream::getFpoRecords() { - return FpoRecords; +bool DbiStream::hasOldFpoRecords() const { return OldFpoStream != nullptr; } + +FixedStreamArray DbiStream::getOldFpoRecords() const { + return OldFpoRecords; +} + +bool DbiStream::hasNewFpoRecords() const { return NewFpoStream != nullptr; } + +const DebugFrameDataSubsectionRef &DbiStream::getNewFpoRecords() const { + return NewFpoRecords; } const DbiModuleList &DbiStream::modules() const { return Modules; } @@ -246,22 +256,15 @@ // Initializes this->SectionHeaders. Error DbiStream::initializeSectionHeadersData(PDBFile *Pdb) { - if (!Pdb) - return Error::success(); - - if (DbgStreams.size() == 0) - return Error::success(); + Expected> ExpectedStream = + createIndexedStreamForHeaderType(Pdb, DbgHeaderType::SectionHdr); + if (auto EC = ExpectedStream.takeError()) + return EC; - uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::SectionHdr); - if (StreamNum == kInvalidStreamIndex) + auto &SHS = *ExpectedStream; + if (!SHS) return Error::success(); - if (StreamNum >= Pdb->getNumStreams()) - return make_error(raw_error_code::no_stream); - - auto SHS = MappedBlockStream::createIndexedStream( - Pdb->getMsfLayout(), Pdb->getMsfBuffer(), StreamNum, Pdb->getAllocator()); - size_t StreamLen = SHS->getLength(); if (StreamLen % sizeof(object::coff_section)) return make_error(raw_error_code::corrupt_file, @@ -278,39 +281,69 @@ } // Initializes this->Fpos. -Error DbiStream::initializeFpoRecords(PDBFile *Pdb) { - if (!Pdb) - return Error::success(); - - if (DbgStreams.size() == 0) - return Error::success(); - - uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::NewFPO); +Error DbiStream::initializeOldFpoRecords(PDBFile *Pdb) { + Expected> ExpectedStream = + createIndexedStreamForHeaderType(Pdb, DbgHeaderType::FPO); + if (auto EC = ExpectedStream.takeError()) + return EC; - // This means there is no FPO data. - if (StreamNum == kInvalidStreamIndex) + auto &FS = *ExpectedStream; + if (!FS) return Error::success(); - if (StreamNum >= Pdb->getNumStreams()) - return make_error(raw_error_code::no_stream); - - auto FS = MappedBlockStream::createIndexedStream( - Pdb->getMsfLayout(), Pdb->getMsfBuffer(), StreamNum, Pdb->getAllocator()); - size_t StreamLen = FS->getLength(); if (StreamLen % sizeof(object::FpoData)) return make_error(raw_error_code::corrupt_file, - "Corrupted New FPO stream."); + "Corrupted Old FPO stream."); size_t NumRecords = StreamLen / sizeof(object::FpoData); BinaryStreamReader Reader(*FS); - if (auto EC = Reader.readArray(FpoRecords, NumRecords)) + if (auto EC = Reader.readArray(OldFpoRecords, NumRecords)) return make_error(raw_error_code::corrupt_file, - "Corrupted New FPO stream."); - FpoStream = std::move(FS); + "Corrupted Old FPO stream."); + OldFpoStream = std::move(FS); + return Error::success(); +} + +Error DbiStream::initializeNewFpoRecords(PDBFile *Pdb) { + Expected> ExpectedStream = + createIndexedStreamForHeaderType(Pdb, DbgHeaderType::NewFPO); + if (auto EC = ExpectedStream.takeError()) + return EC; + + auto &FS = *ExpectedStream; + if (!FS) + return Error::success(); + + if (auto EC = NewFpoRecords.initialize(*FS)) + return EC; + + NewFpoStream = std::move(FS); return Error::success(); } +Expected> +DbiStream::createIndexedStreamForHeaderType(PDBFile *Pdb, + DbgHeaderType Type) const { + if (!Pdb) + return nullptr; + + if (DbgStreams.empty()) + return nullptr; + + uint32_t StreamNum = getDebugStreamIndex(Type); + + // This means there is no such stream + if (StreamNum == kInvalidStreamIndex) + return nullptr; + + if (StreamNum >= Pdb->getNumStreams()) + return make_error(raw_error_code::no_stream); + + return MappedBlockStream::createIndexedStream( + Pdb->getMsfLayout(), Pdb->getMsfBuffer(), StreamNum, Pdb->getAllocator()); +} + BinarySubstreamRef DbiStream::getSectionContributionData() const { return SecContrSubstream; } Index: llvm/trunk/test/tools/llvm-pdbdump/fpo-data.test =================================================================== --- llvm/trunk/test/tools/llvm-pdbdump/fpo-data.test +++ llvm/trunk/test/tools/llvm-pdbdump/fpo-data.test @@ -0,0 +1,14 @@ +; RUN: llvm-pdbutil dump -fpo %p/Inputs/FPOTest.pdb \ +; RUN: | FileCheck %s + +CHECK: Old FPO Data +CHECK-NEXT: ============================================================ +CHECK-NEXT: RVA | Code | Locals | Params | Prolog | Saved Regs | Use BP | Has SEH | Frame Type +CHECK-NEXT: 0000004E | 19 | 0 | 0 | 0 | 0 | false | false | FPO + +CHECK: New FPO Data +CHECK-NEXT: ============================================================ +CHECK-NEXT: RVA | Code | Locals | Params | Stack | Prolog | Saved Regs | Has SEH | Has C++EH | Start | Program +CHECK-NEXT: 00001010 | 18 | 0 | 0 | 0 | 4 | 0 | false | false | true | $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = +CHECK-NEXT: 00001011 | 17 | 0 | 0 | 0 | 3 | 4 | false | false | false | $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = +CHECK-NEXT: 00001013 | 15 | 0 | 0 | 0 | 1 | 4 | false | false | false | $T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = \ No newline at end of file Index: llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp =================================================================== --- llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp +++ llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp @@ -1010,17 +1010,12 @@ ExitOnError Err("Error dumping old fpo data:"); auto &Dbi = Err(File.getPDBDbiStream()); - uint32_t Index = Dbi.getDebugStreamIndex(DbgHeaderType::FPO); - if (Index == kInvalidStreamIndex) { + if (!Dbi.hasOldFpoRecords()) { printStreamNotPresent("FPO"); return Error::success(); } - std::unique_ptr OldFpo = File.createIndexedStream(Index); - BinaryStreamReader Reader(*OldFpo); - FixedStreamArray Records; - Err(Reader.readArray(Records, - Reader.bytesRemaining() / sizeof(object::FpoData))); + const FixedStreamArray& Records = Dbi.getOldFpoRecords(); P.printLine(" RVA | Code | Locals | Params | Prolog | Saved Regs | Use " "BP | Has SEH | Frame Type"); @@ -1042,18 +1037,12 @@ ExitOnError Err("Error dumping new fpo data:"); auto &Dbi = Err(File.getPDBDbiStream()); - uint32_t Index = Dbi.getDebugStreamIndex(DbgHeaderType::NewFPO); - if (Index == kInvalidStreamIndex) { + if (!Dbi.hasNewFpoRecords()) { 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"); + const DebugFrameDataSubsectionRef& FDS = Dbi.getNewFpoRecords(); P.printLine(" RVA | Code | Locals | Params | Stack | Prolog | Saved Regs " "| Has SEH | Has C++EH | Start | Program");