diff options
Diffstat (limited to 'tools/llvm-pdbdump/llvm-pdbdump.cpp')
| -rw-r--r-- | tools/llvm-pdbdump/llvm-pdbdump.cpp | 100 |
1 files changed, 97 insertions, 3 deletions
diff --git a/tools/llvm-pdbdump/llvm-pdbdump.cpp b/tools/llvm-pdbdump/llvm-pdbdump.cpp index 7337b1d28747..642e169613ba 100644 --- a/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ b/tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -28,18 +28,22 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Config/config.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" #include "llvm/DebugInfo/PDB/GenericError.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" #include "llvm/DebugInfo/PDB/IPDBSession.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h" #include "llvm/DebugInfo/PDB/Native/InfoStream.h" #include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h" -#include "llvm/DebugInfo/PDB/Native/ModInfoBuilder.h" #include "llvm/DebugInfo/PDB/Native/NativeSession.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h" @@ -261,9 +265,10 @@ cl::opt<std::string> cl::cat(MsfOptions), cl::sub(RawSubcommand)); llvm::Optional<BlockRange> DumpBlockRange; -cl::list<uint32_t> +cl::list<std::string> DumpStreamData("stream-data", cl::CommaSeparated, cl::ZeroOrMore, - cl::desc("Dump binary data from specified streams."), + cl::desc("Dump binary data from specified streams. Format " + "is SN[:Start][@Size]"), cl::cat(MsfOptions), cl::sub(RawSubcommand)); // TYPE OPTIONS @@ -419,6 +424,21 @@ cl::list<std::string> InputFilename(cl::Positional, static ExitOnError ExitOnErr; +static uint32_t +getFileChecksumOffset(StringRef FileName, + ModuleDebugFileChecksumFragment &Checksums, + StringTableBuilder &Strings) { + // The offset in the line info record is the offset of the checksum + // entry for the corresponding file. That entry then contains an + // offset into the global string table of the file name. So to + // compute the proper offset to write into the line info record, we + // must first get its offset in the global string table, then ask the + // checksum builder to find the offset in its serialized buffer that + // it mapped that filename string table offset to. + uint32_t StringOffset = Strings.insert(FileName); + return Checksums.mapChecksumOffset(StringOffset); +} + static void yamlToPdb(StringRef Path) { BumpPtrAllocator Allocator; ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer = @@ -490,6 +510,80 @@ static void yamlToPdb(StringRef Path) { for (auto Symbol : ModiStream.Symbols) ModiBuilder.addSymbol(Symbol.Record); } + if (MI.FileLineInfo.hasValue()) { + const auto &FLI = *MI.FileLineInfo; + + // File Checksums must be emitted before line information, because line + // info records use offsets into the checksum buffer to reference a file's + // source file name. + auto Checksums = llvm::make_unique<ModuleDebugFileChecksumFragment>(); + auto &ChecksumRef = *Checksums; + if (!FLI.FileChecksums.empty()) { + auto &Strings = Builder.getStringTableBuilder(); + for (auto &FC : FLI.FileChecksums) { + uint32_t STOffset = Strings.insert(FC.FileName); + Checksums->addChecksum(STOffset, FC.Kind, FC.ChecksumBytes.Bytes); + } + } + ModiBuilder.setC13FileChecksums(std::move(Checksums)); + + // FIXME: StringTable / StringTableBuilder should really be in + // DebugInfoCodeView. This would allow us to construct the + // ModuleDebugLineFragment with a reference to the string table, + // and we could just pass strings around rather than having to + // remember how to calculate the right offset. + auto &Strings = Builder.getStringTableBuilder(); + + for (const auto &Fragment : FLI.LineFragments) { + auto Lines = llvm::make_unique<ModuleDebugLineFragment>(); + Lines->setCodeSize(Fragment.CodeSize); + Lines->setRelocationAddress(Fragment.RelocSegment, + Fragment.RelocOffset); + Lines->setFlags(Fragment.Flags); + for (const auto &LC : Fragment.Blocks) { + uint32_t ChecksumOffset = + getFileChecksumOffset(LC.FileName, ChecksumRef, Strings); + + Lines->createBlock(ChecksumOffset); + if (Lines->hasColumnInfo()) { + for (const auto &Item : zip(LC.Lines, LC.Columns)) { + auto &L = std::get<0>(Item); + auto &C = std::get<1>(Item); + uint32_t LE = L.LineStart + L.EndDelta; + Lines->addLineAndColumnInfo( + L.Offset, LineInfo(L.LineStart, LE, L.IsStatement), + C.StartColumn, C.EndColumn); + } + } else { + for (const auto &L : LC.Lines) { + uint32_t LE = L.LineStart + L.EndDelta; + Lines->addLineInfo(L.Offset, + LineInfo(L.LineStart, LE, L.IsStatement)); + } + } + } + ModiBuilder.addC13Fragment(std::move(Lines)); + } + + for (const auto &Inlinee : FLI.Inlinees) { + auto Inlinees = llvm::make_unique<ModuleDebugInlineeLineFragment>( + Inlinee.HasExtraFiles); + for (const auto &Site : Inlinee.Sites) { + uint32_t FileOff = + getFileChecksumOffset(Site.FileName, ChecksumRef, Strings); + + Inlinees->addInlineSite(Site.Inlinee, FileOff, Site.SourceLineNum); + if (!Inlinee.HasExtraFiles) + continue; + + for (auto EF : Site.ExtraFiles) { + FileOff = getFileChecksumOffset(EF, ChecksumRef, Strings); + Inlinees->addExtraFile(FileOff); + } + } + ModiBuilder.addC13Fragment(std::move(Inlinees)); + } + } } auto &TpiBuilder = Builder.getTpiBuilder(); |
