diff options
-rw-r--r-- | llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h | 1 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp | 28 | ||||
-rw-r--r-- | llvm/test/DebugInfo/PDB/pdbdump-headers.test | 14 | ||||
-rw-r--r-- | llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp | 181 |
5 files changed, 150 insertions, 78 deletions
diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h b/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h index 4d7941ae413..1ff5c3fcfef 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h @@ -34,6 +34,7 @@ public: PdbRaw_DbiVer getDbiVersion() const; uint32_t getAge() const; uint16_t getPublicSymbolStreamIndex() const; + uint16_t getGlobalSymbolStreamIndex() const; bool isIncrementallyLinked() const; bool hasCTypes() const; diff --git a/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp index 7e1811daf09..2cc2a73a0d1 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp @@ -188,6 +188,10 @@ uint16_t DbiStream::getPublicSymbolStreamIndex() const { return Header->PublicSymbolStreamIndex; } +uint16_t DbiStream::getGlobalSymbolStreamIndex() const { + return Header->GlobalSymbolStreamIndex; +} + bool DbiStream::isIncrementallyLinked() const { return (Header->Flags & FlagIncrementalMask) != 0; } diff --git a/llvm/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp index af047f73abd..09d71985031 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp @@ -15,8 +15,12 @@ using namespace llvm; using namespace llvm::pdb; MappedBlockStream::MappedBlockStream(uint32_t StreamIdx, const PDBFile &File) : Pdb(File) { - StreamLength = Pdb.getStreamByteSize(StreamIdx); - BlockList = Pdb.getStreamBlockList(StreamIdx); + if (StreamIdx >= Pdb.getNumStreams()) { + StreamLength = 0; + } else { + StreamLength = Pdb.getStreamByteSize(StreamIdx); + BlockList = Pdb.getStreamBlockList(StreamIdx); + } } Error MappedBlockStream::readBytes(uint32_t Offset, @@ -54,5 +58,23 @@ Error MappedBlockStream::readBytes(uint32_t Offset, Error MappedBlockStream::getArrayRef(uint32_t Offset, ArrayRef<uint8_t> &Buffer, uint32_t Length) const { - return make_error<RawError>(raw_error_code::feature_unsupported); + uint32_t BlockNum = Offset / Pdb.getBlockSize(); + uint32_t OffsetInBlock = Offset % Pdb.getBlockSize(); + uint32_t BytesAvailableInBlock = Pdb.getBlockSize() - OffsetInBlock; + + // If this is the last block in the stream, not all of the data is valid. + if (BlockNum == BlockList.size() - 1) { + uint32_t AllocatedBytesInBlock = StreamLength % Pdb.getBlockSize(); + if (AllocatedBytesInBlock < BytesAvailableInBlock) + BytesAvailableInBlock = AllocatedBytesInBlock; + } + if (BytesAvailableInBlock < Length) + return make_error<RawError>(raw_error_code::feature_unsupported); + + uint32_t StreamBlockAddr = BlockList[BlockNum]; + StringRef Data = Pdb.getBlockData(StreamBlockAddr, Pdb.getBlockSize()); + Data = Data.substr(OffsetInBlock, Length); + + Buffer = ArrayRef<uint8_t>(Data.bytes_begin(), Data.bytes_end()); + return Error::success(); } diff --git a/llvm/test/DebugInfo/PDB/pdbdump-headers.test b/llvm/test/DebugInfo/PDB/pdbdump-headers.test index bb591355a55..8f1ff2de8b7 100644 --- a/llvm/test/DebugInfo/PDB/pdbdump-headers.test +++ b/llvm/test/DebugInfo/PDB/pdbdump-headers.test @@ -1,7 +1,9 @@ -; RUN: llvm-pdbdump --dump-headers -dump-tpi-records -dump-tpi-record-bytes -dump-module-syms \ -; RUN: -dump-sym-record-bytes --dump-publics %p/Inputs/empty.pdb | FileCheck -check-prefix=EMPTY %s -; RUN: llvm-pdbdump --dump-headers %p/Inputs/big-read.pdb | FileCheck -check-prefix=BIG %s -; RUN: llvm-pdbdump --dump-headers %p/Inputs/bad-block-size.pdb | FileCheck -check-prefix=BAD-BLOCK-SIZE %s +; RUN: llvm-pdbdump -raw-headers -raw-tpi-records -raw-tpi-record-bytes -raw-module-syms \ +; RUN: -raw-sym-record-bytes -raw-publics -raw-module-files -raw-stream-name=/names \ +; RUN: %p/Inputs/empty.pdb | FileCheck -check-prefix=EMPTY %s +; RUN: llvm-pdbdump -raw-headers -raw-stream-name=/names -raw-modules -raw-module-files \ +; RUN: %p/Inputs/big-read.pdb | FileCheck -check-prefix=BIG %s +; RUN: llvm-pdbdump -raw-headers %p/Inputs/bad-block-size.pdb | FileCheck -check-prefix=BAD-BLOCK-SIZE %s ; EMPTY: FileHeaders { ; EMPTY-NEXT: BlockSize: 4096 @@ -105,6 +107,8 @@ ; EMPTY-NEXT: Is Stripped: No ; EMPTY-NEXT: Machine Type: x86 ; EMPTY-NEXT: Symbol Record Stream Index: 8 +; EMPTY-NEXT: Public Symbol Stream Index: 7 +; EMPTY-NEXT: Global Symbol Stream Index: 6 ; EMPTY-NEXT: Toolchain Version: 12.0 ; EMPTY-NEXT: mspdb120.dll version: 12.0.31101 ; EMPTY-NEXT: Modules [ @@ -525,6 +529,8 @@ ; BIG-NEXT: Is Stripped: No ; BIG-NEXT: Machine Type: x86 ; BIG-NEXT: Symbol Record Stream Index: 9 +; BIG-NEXT: Public Symbol Stream Index: 8 +; BIG-NEXT: Global Symbol Stream Index: 7 ; BIG-NEXT: Toolchain Version: 14.0 ; BIG-NEXT: mspdb140.dll version: 14.0.23918 ; BIG-NEXT: Modules [ diff --git a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp index d8dcd3d4076..0946873536f 100644 --- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -104,31 +104,38 @@ cl::opt<uint64_t> LoadAddress( cl::desc("Assume the module is loaded at the specified address"), cl::cat(OtherOptions)); -cl::opt<bool> DumpHeaders("dump-headers", cl::desc("dump PDB headers"), +cl::opt<bool> DumpHeaders("raw-headers", cl::desc("dump PDB headers"), cl::cat(NativeOtions)); -cl::opt<bool> DumpStreamSizes("dump-stream-sizes", +cl::opt<bool> DumpStreamSizes("raw-stream-sizes", cl::desc("dump PDB stream sizes"), cl::cat(NativeOtions)); -cl::opt<bool> DumpStreamBlocks("dump-stream-blocks", +cl::opt<bool> DumpStreamBlocks("raw-stream-blocks", cl::desc("dump PDB stream blocks"), cl::cat(NativeOtions)); -cl::opt<bool> DumpTpiRecords("dump-tpi-records", +cl::opt<bool> DumpTpiRecords("raw-tpi-records", cl::desc("dump CodeView type records"), cl::cat(NativeOtions)); cl::opt<bool> - DumpTpiRecordBytes("dump-tpi-record-bytes", + DumpTpiRecordBytes("raw-tpi-record-bytes", cl::desc("dump CodeView type record raw bytes"), cl::cat(NativeOtions)); -cl::opt<std::string> DumpStreamData("dump-stream", cl::desc("dump stream data"), - cl::cat(NativeOtions)); -cl::opt<bool> DumpModuleSyms("dump-module-syms", - cl::desc("dump module symbols"), +cl::opt<std::string> DumpStreamDataIdx("raw-stream", + cl::desc("dump stream data"), + cl::cat(NativeOtions)); +cl::opt<std::string> DumpStreamDataName("raw-stream-name", + cl::desc("dump stream data"), + cl::cat(NativeOtions)); +cl::opt<bool> DumpModules("raw-modules", cl::desc("dump compiland information"), + cl::cat(NativeOtions)); +cl::opt<bool> DumpModuleFiles("raw-module-files", + cl::desc("dump file information"), + cl::cat(NativeOtions)); +cl::opt<bool> DumpModuleSyms("raw-module-syms", cl::desc("dump module symbols"), cl::cat(NativeOtions)); -cl::opt<bool> DumpPublics("dump-publics", - cl::desc("dump Publics stream data"), +cl::opt<bool> DumpPublics("raw-publics", cl::desc("dump Publics stream data"), cl::cat(NativeOtions)); cl::opt<bool> - DumpSymRecordBytes("dump-sym-record-bytes", + DumpSymRecordBytes("raw-sym-record-bytes", cl::desc("dump CodeView symbol record raw bytes"), cl::cat(NativeOtions)); @@ -227,28 +234,22 @@ static Error dumpStreamBlocks(ScopedPrinter &P, PDBFile &File) { static Error dumpStreamData(ScopedPrinter &P, PDBFile &File) { uint32_t StreamCount = File.getNumStreams(); - StringRef DumpStreamStr = opts::DumpStreamData; + StringRef DumpStreamStr = opts::DumpStreamDataIdx; uint32_t DumpStreamNum; if (DumpStreamStr.getAsInteger(/*Radix=*/0U, DumpStreamNum) || DumpStreamNum >= StreamCount) return Error::success(); - uint32_t StreamBytesRead = 0; - uint32_t StreamSize = File.getStreamByteSize(DumpStreamNum); - auto StreamBlocks = File.getStreamBlockList(DumpStreamNum); - - for (uint32_t StreamBlockAddr : StreamBlocks) { - uint32_t BytesLeftToReadInStream = StreamSize - StreamBytesRead; - if (BytesLeftToReadInStream == 0) - break; - + MappedBlockStream S(DumpStreamNum, File); + StreamReader R(S); + while (R.bytesRemaining() > 0) { + ArrayRef<uint8_t> Data; uint32_t BytesToReadInBlock = std::min( - BytesLeftToReadInStream, static_cast<uint32_t>(File.getBlockSize())); - auto StreamBlockData = - File.getBlockData(StreamBlockAddr, BytesToReadInBlock); - - outs() << StreamBlockData; - StreamBytesRead += StreamBlockData.size(); + R.bytesRemaining(), static_cast<uint32_t>(File.getBlockSize())); + if (auto EC = R.getArrayRef(Data, BytesToReadInBlock)) + return EC; + outs() << StringRef(reinterpret_cast<const char *>(Data.begin()), + Data.size()); } return Error::success(); } @@ -268,18 +269,20 @@ static Error dumpInfoStream(ScopedPrinter &P, PDBFile &File) { return Error::success(); } -static Error dumpNamedStream(ScopedPrinter &P, PDBFile &File, - StringRef Stream) { +static Error dumpNamedStream(ScopedPrinter &P, PDBFile &File) { + if (opts::DumpStreamDataName.empty()) + return Error::success(); + auto InfoS = File.getPDBInfoStream(); if (auto EC = InfoS.takeError()) return EC; InfoStream &IS = InfoS.get(); - uint32_t NameStreamIndex = IS.getNamedStreamIndex(Stream); + uint32_t NameStreamIndex = IS.getNamedStreamIndex(opts::DumpStreamDataName); if (NameStreamIndex != 0) { std::string Name("Stream '"); - Name += Stream; + Name += opts::DumpStreamDataName; Name += "'"; DictScope D(P, Name); P.printNumber("Index", NameStreamIndex); @@ -319,6 +322,8 @@ static Error dumpDbiStream(ScopedPrinter &P, PDBFile &File, P.printBoolean("Is Stripped", DS.isStripped()); P.printObject("Machine Type", DS.getMachineType()); P.printNumber("Symbol Record Stream Index", DS.getSymRecordStreamIndex()); + P.printNumber("Public Symbol Stream Index", DS.getPublicSymbolStreamIndex()); + P.printNumber("Global Symbol Stream Index", DS.getGlobalSymbolStreamIndex()); uint16_t Major = DS.getBuildMajorVersion(); uint16_t Minor = DS.getBuildMinorVersion(); @@ -330,42 +335,48 @@ static Error dumpDbiStream(ScopedPrinter &P, PDBFile &File, DllStream.flush(); P.printVersion(DllName, Major, Minor, DS.getPdbDllVersion()); - ListScope L(P, "Modules"); - for (auto &Modi : DS.modules()) { - DictScope DD(P); - P.printString("Name", Modi.Info.getModuleName()); - P.printNumber("Debug Stream Index", Modi.Info.getModuleStreamIndex()); - P.printString("Object File Name", Modi.Info.getObjFileName()); - P.printNumber("Num Files", Modi.Info.getNumberOfFiles()); - P.printNumber("Source File Name Idx", Modi.Info.getSourceFileNameIndex()); - P.printNumber("Pdb File Name Idx", Modi.Info.getPdbFilePathNameIndex()); - P.printNumber("Line Info Byte Size", Modi.Info.getLineInfoByteSize()); - P.printNumber("C13 Line Info Byte Size", - Modi.Info.getC13LineInfoByteSize()); - P.printNumber("Symbol Byte Size", Modi.Info.getSymbolDebugInfoByteSize()); - P.printNumber("Type Server Index", Modi.Info.getTypeServerIndex()); - P.printBoolean("Has EC Info", Modi.Info.hasECInfo()); - { - std::string FileListName = - to_string(Modi.SourceFiles.size()) + " Contributing Source Files"; - ListScope LL(P, FileListName); - for (auto File : Modi.SourceFiles) - P.printString(File); - } - if (opts::DumpModuleSyms || opts::DumpSymRecordBytes) { - ListScope SS(P, "Symbols"); - ModStream ModS(File, Modi.Info); - if (auto EC = ModS.reload()) - return EC; - - codeview::CVSymbolDumper SD(P, TD, nullptr, false); - for (auto &S : ModS.symbols()) { - DictScope DD(P, ""); - - if (opts::DumpModuleSyms) - SD.dump(S); - if (opts::DumpSymRecordBytes) - P.printBinaryBlock("Bytes", S.Data); + if (opts::DumpModules || opts::DumpModuleSyms || opts::DumpModuleFiles) { + ListScope L(P, "Modules"); + for (auto &Modi : DS.modules()) { + DictScope DD(P); + P.printString("Name", Modi.Info.getModuleName()); + P.printNumber("Debug Stream Index", Modi.Info.getModuleStreamIndex()); + P.printString("Object File Name", Modi.Info.getObjFileName()); + P.printNumber("Num Files", Modi.Info.getNumberOfFiles()); + P.printNumber("Source File Name Idx", Modi.Info.getSourceFileNameIndex()); + P.printNumber("Pdb File Name Idx", Modi.Info.getPdbFilePathNameIndex()); + P.printNumber("Line Info Byte Size", Modi.Info.getLineInfoByteSize()); + P.printNumber("C13 Line Info Byte Size", + Modi.Info.getC13LineInfoByteSize()); + P.printNumber("Symbol Byte Size", Modi.Info.getSymbolDebugInfoByteSize()); + P.printNumber("Type Server Index", Modi.Info.getTypeServerIndex()); + P.printBoolean("Has EC Info", Modi.Info.hasECInfo()); + if (opts::DumpModuleFiles) { + std::string FileListName = + to_string(Modi.SourceFiles.size()) + " Contributing Source Files"; + ListScope LL(P, FileListName); + for (auto File : Modi.SourceFiles) + P.printString(File); + } + bool HasModuleDI = + (Modi.Info.getModuleStreamIndex() < File.getNumStreams()); + bool ShouldDumpSymbols = + (opts::DumpModuleSyms || opts::DumpSymRecordBytes); + if (HasModuleDI && ShouldDumpSymbols) { + ListScope SS(P, "Symbols"); + ModStream ModS(File, Modi.Info); + if (auto EC = ModS.reload()) + return EC; + + codeview::CVSymbolDumper SD(P, TD, nullptr, false); + for (auto &S : ModS.symbols()) { + DictScope DD(P, ""); + + if (opts::DumpModuleSyms) + SD.dump(S); + if (opts::DumpSymRecordBytes) + P.printBinaryBlock("Bytes", S.Data); + } } } } @@ -474,7 +485,7 @@ static Error dumpStructure(RawSession &RS) { if (auto EC = dumpInfoStream(P, File)) return EC; - if (auto EC = dumpNamedStream(P, File, "/names")) + if (auto EC = dumpNamedStream(P, File)) return EC; codeview::CVTypeDumper TD(P, false); @@ -486,12 +497,40 @@ static Error dumpStructure(RawSession &RS) { if (auto EC = dumpPublicsStream(P, File, TD)) return EC; -return Error::success(); + return Error::success(); +} + +bool isRawDumpEnabled() { + if (opts::DumpHeaders) + return true; + if (opts::DumpModules) + return true; + if (opts::DumpModuleFiles) + return true; + if (opts::DumpModuleSyms) + return true; + if (!opts::DumpStreamDataIdx.empty()) + return true; + if (!opts::DumpStreamDataName.empty()) + return true; + if (opts::DumpPublics) + return true; + if (opts::DumpStreamBlocks) + return true; + if (opts::DumpStreamSizes) + return true; + if (opts::DumpSymRecordBytes) + return true; + if (opts::DumpTpiRecordBytes) + return true; + if (opts::DumpTpiRecords) + return true; + return false; } static void dumpInput(StringRef Path) { std::unique_ptr<IPDBSession> Session; - if (opts::DumpHeaders || !opts::DumpStreamData.empty()) { + if (isRawDumpEnabled()) { auto E = loadDataForPDB(PDB_ReaderType::Raw, Path, Session); if (!E) { RawSession *RS = static_cast<RawSession *>(Session.get()); |