mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
[pdb] Print out file names instead of file offsets.
When printing line information and file checksums, we were printing the file offset field from the struct header. This teaches llvm-pdbdump how to turn those numbers into the filename. In the case of file checksums, this is done by looking in the global string table. In the case of line contributions, this is done by indexing into the file names buffer of the DBI stream. Why they use a different technique I don't know. llvm-svn: 271630
This commit is contained in:
parent
7dae6773ea
commit
eace145381
@ -142,9 +142,9 @@ struct InlineeSourceLine {
|
||||
};
|
||||
|
||||
struct FileChecksum {
|
||||
ulittle32_t FileNameOffset; // Offset of filename in string table substream.
|
||||
uint8_t ChecksumSize;
|
||||
uint8_t ChecksumKind; // FileChecksumKind
|
||||
ulittle32_t FileNameOffset; // Byte offset of filename in global string table.
|
||||
uint8_t ChecksumSize; // Number of bytes of checksum.
|
||||
uint8_t ChecksumKind; // FileChecksumKind
|
||||
// Checksum bytes follow.
|
||||
};
|
||||
|
||||
|
@ -35,7 +35,7 @@ struct LineSubstreamHeader {
|
||||
|
||||
// Corresponds to the `CV_DebugSLinesFileBlockHeader_t` structure.
|
||||
struct LineFileBlockHeader {
|
||||
support::ulittle32_t FileOffset;
|
||||
support::ulittle32_t NameIndex; // Index in DBI name buffer of filename.
|
||||
support::ulittle32_t NumLines; // Number of lines
|
||||
support::ulittle32_t BlockSize; // Code size of block, in bytes.
|
||||
// The following two variable length arrays appear immediately after the
|
||||
|
@ -21,7 +21,7 @@ namespace llvm {
|
||||
namespace codeview {
|
||||
|
||||
struct LineColumnEntry {
|
||||
support::ulittle32_t Offset;
|
||||
support::ulittle32_t NameIndex;
|
||||
FixedStreamArray<LineNumberEntry> LineNumbers;
|
||||
FixedStreamArray<ColumnNumberEntry> Columns;
|
||||
};
|
||||
@ -50,7 +50,7 @@ public:
|
||||
// The value recorded in BlockHeader->BlockSize includes the size of
|
||||
// LineFileBlockHeader.
|
||||
Len = BlockHeader->BlockSize;
|
||||
Item.Offset = BlockHeader->FileOffset;
|
||||
Item.NameIndex = BlockHeader->NameIndex;
|
||||
if (auto EC = Reader.readArray(Item.LineNumbers, BlockHeader->NumLines))
|
||||
return EC;
|
||||
if (HasColumn) {
|
||||
@ -65,9 +65,9 @@ private:
|
||||
};
|
||||
|
||||
struct FileChecksumEntry {
|
||||
uint32_t FileNameOffset;
|
||||
FileChecksumKind Kind;
|
||||
ArrayRef<uint8_t> Checksum;
|
||||
uint32_t FileNameOffset; // Byte offset of filename in global stringtable.
|
||||
FileChecksumKind Kind; // The type of checksum.
|
||||
ArrayRef<uint8_t> Checksum; // The bytes of the checksum.
|
||||
};
|
||||
|
||||
template <> class VarStreamArrayExtractor<FileChecksumEntry> {
|
||||
|
@ -61,6 +61,8 @@ public:
|
||||
|
||||
ArrayRef<ModuleInfoEx> modules() const;
|
||||
|
||||
Expected<StringRef> getFileNameForIndex(uint32_t Index) const;
|
||||
|
||||
codeview::FixedStreamArray<object::coff_section> getSectionHeaders();
|
||||
|
||||
codeview::FixedStreamArray<SecMapEntry> getSectionMap() const;
|
||||
@ -85,12 +87,15 @@ private:
|
||||
codeview::StreamRef TypeServerMapSubstream;
|
||||
codeview::StreamRef ECSubstream;
|
||||
|
||||
codeview::StreamRef NamesBuffer;
|
||||
|
||||
codeview::FixedStreamArray<support::ulittle16_t> DbgStreams;
|
||||
|
||||
PdbRaw_DbiSecContribVer SectionContribVersion;
|
||||
codeview::FixedStreamArray<SectionContrib> SectionContribs;
|
||||
codeview::FixedStreamArray<SectionContrib2> SectionContribs2;
|
||||
codeview::FixedStreamArray<SecMapEntry> SectionMap;
|
||||
codeview::FixedStreamArray<support::little32_t> FileNameOffsets;
|
||||
|
||||
std::unique_ptr<MappedBlockStream> SectionHeaderStream;
|
||||
codeview::FixedStreamArray<object::coff_section> SectionHeaders;
|
||||
|
@ -25,6 +25,8 @@ namespace pdb {
|
||||
struct PDBFileContext;
|
||||
class DbiStream;
|
||||
class InfoStream;
|
||||
class MappedBlockStream;
|
||||
class NameHashTable;
|
||||
class PublicsStream;
|
||||
class SymbolStream;
|
||||
class TpiStream;
|
||||
@ -69,6 +71,7 @@ public:
|
||||
Expected<TpiStream &> getPDBIpiStream();
|
||||
Expected<PublicsStream &> getPDBPublicsStream();
|
||||
Expected<SymbolStream &> getPDBSymbolStream();
|
||||
Expected<NameHashTable &> getStringTable();
|
||||
|
||||
private:
|
||||
std::unique_ptr<PDBFileContext> Context;
|
||||
@ -78,6 +81,8 @@ private:
|
||||
std::unique_ptr<TpiStream> Ipi;
|
||||
std::unique_ptr<PublicsStream> Publics;
|
||||
std::unique_ptr<SymbolStream> Symbols;
|
||||
std::unique_ptr<MappedBlockStream> StringTableStream;
|
||||
std::unique_ptr<NameHashTable> StringTable;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,8 @@ enum class raw_error_code {
|
||||
feature_unsupported,
|
||||
corrupt_file,
|
||||
insufficient_buffer,
|
||||
no_stream,
|
||||
index_out_of_bounds
|
||||
};
|
||||
|
||||
/// Base class for errors originating when parsing raw PDB files
|
||||
|
@ -345,7 +345,6 @@ Error DbiStream::initializeFileInfo() {
|
||||
|
||||
FixedStreamArray<ulittle16_t> ModIndexArray;
|
||||
FixedStreamArray<ulittle16_t> ModFileCountArray;
|
||||
FixedStreamArray<little32_t> FileNameOffsets;
|
||||
|
||||
// First is an array of `NumModules` module indices. This is not used for the
|
||||
// same reason that `NumSourceFiles` is not used. It's an array of uint16's,
|
||||
@ -373,10 +372,8 @@ Error DbiStream::initializeFileInfo() {
|
||||
if (auto EC = FISR.readArray(FileNameOffsets, NumSourceFiles))
|
||||
return EC;
|
||||
|
||||
StreamRef NamesBufferRef;
|
||||
if (auto EC = FISR.readStreamRef(NamesBufferRef))
|
||||
if (auto EC = FISR.readStreamRef(NamesBuffer))
|
||||
return EC;
|
||||
StreamReader Names(NamesBufferRef);
|
||||
|
||||
// We go through each ModuleInfo, determine the number N of source files for
|
||||
// that module, and then get the next N offsets from the Offsets array, using
|
||||
@ -387,10 +384,10 @@ Error DbiStream::initializeFileInfo() {
|
||||
uint32_t NumFiles = ModFileCountArray[I];
|
||||
ModuleInfos[I].SourceFiles.resize(NumFiles);
|
||||
for (size_t J = 0; J < NumFiles; ++J, ++NextFileIndex) {
|
||||
uint32_t FileOffset = FileNameOffsets[NextFileIndex];
|
||||
Names.setOffset(FileOffset);
|
||||
if (auto EC = Names.readZeroString(ModuleInfos[I].SourceFiles[J]))
|
||||
return EC;
|
||||
if (auto Name = getFileNameForIndex(NextFileIndex))
|
||||
ModuleInfos[I].SourceFiles[J] = Name.get();
|
||||
else
|
||||
return Name.takeError();
|
||||
}
|
||||
}
|
||||
|
||||
@ -400,3 +397,16 @@ Error DbiStream::initializeFileInfo() {
|
||||
uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const {
|
||||
return DbgStreams[static_cast<uint16_t>(Type)];
|
||||
}
|
||||
|
||||
Expected<StringRef> DbiStream::getFileNameForIndex(uint32_t Index) const {
|
||||
StreamReader Names(NamesBuffer);
|
||||
if (Index >= FileNameOffsets.size())
|
||||
return make_error<RawError>(raw_error_code::index_out_of_bounds);
|
||||
|
||||
uint32_t FileOffset = FileNameOffsets[Index];
|
||||
Names.setOffset(FileOffset);
|
||||
StringRef Name;
|
||||
if (auto EC = Names.readZeroString(Name))
|
||||
return std::move(EC);
|
||||
return Name;
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
|
||||
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
|
||||
#include "llvm/DebugInfo/PDB/Raw/NameHashTable.h"
|
||||
#include "llvm/DebugInfo/PDB/Raw/PublicsStream.h"
|
||||
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
|
||||
#include "llvm/DebugInfo/PDB/Raw/SymbolStream.h"
|
||||
@ -359,3 +360,24 @@ Expected<SymbolStream &> PDBFile::getPDBSymbolStream() {
|
||||
}
|
||||
return *Symbols;
|
||||
}
|
||||
|
||||
Expected<NameHashTable &> PDBFile::getStringTable() {
|
||||
if (!StringTable || !StringTableStream) {
|
||||
auto InfoS = getPDBInfoStream();
|
||||
if (auto EC = InfoS.takeError())
|
||||
return std::move(EC);
|
||||
auto &IS = InfoS.get();
|
||||
uint32_t NameStreamIndex = IS.getNamedStreamIndex("/names");
|
||||
|
||||
if (NameStreamIndex == 0)
|
||||
return make_error<RawError>(raw_error_code::no_stream);
|
||||
auto S = llvm::make_unique<MappedBlockStream>(NameStreamIndex, *this);
|
||||
codeview::StreamReader Reader(*S);
|
||||
auto N = llvm::make_unique<NameHashTable>();
|
||||
if (auto EC = N->load(Reader))
|
||||
return std::move(EC);
|
||||
StringTable = std::move(N);
|
||||
StringTableStream = std::move(S);
|
||||
}
|
||||
return *StringTable;
|
||||
}
|
||||
|
@ -24,6 +24,10 @@ public:
|
||||
case raw_error_code::insufficient_buffer:
|
||||
return "The buffer is not large enough to read the requested number of "
|
||||
"bytes.";
|
||||
case raw_error_code::no_stream:
|
||||
return "The specified stream could not be loaded.";
|
||||
case raw_error_code::index_out_of_bounds:
|
||||
return "The specified item does not exist in the array.";
|
||||
}
|
||||
llvm_unreachable("Unrecognized raw_error_code");
|
||||
}
|
||||
|
@ -332,7 +332,7 @@
|
||||
; EMPTY-NEXT: ]
|
||||
; EMPTY-NEXT: LineInfo [
|
||||
; EMPTY-NEXT: Lines {
|
||||
; EMPTY-NEXT: FileOffset: 0
|
||||
; EMPTY-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
|
||||
; EMPTY-NEXT: Line {
|
||||
; EMPTY-NEXT: Offset: 0
|
||||
; EMPTY-NEXT: LineNumberStart: 5
|
||||
@ -354,7 +354,7 @@
|
||||
; EMPTY-NEXT: }
|
||||
; EMPTY-NEXT: FileChecksums {
|
||||
; EMPTY-NEXT: Checksum {
|
||||
; EMPTY-NEXT: FileNameOffset: 86
|
||||
; EMPTY-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
|
||||
; EMPTY-NEXT: Kind: MD5 (0x1)
|
||||
; EMPTY-NEXT: Checksum (
|
||||
; EMPTY-NEXT: 0000: A0A5BD0D 3ECD93FC 29D19DE8 26FBF4BC |....>...)...&...|
|
||||
|
@ -522,11 +522,19 @@ static Error dumpDbiStream(ScopedPrinter &P, PDBFile &File,
|
||||
// substream types types.
|
||||
class RecordVisitor : public codeview::IModuleSubstreamVisitor {
|
||||
public:
|
||||
RecordVisitor(ScopedPrinter &P) : P(P) {}
|
||||
RecordVisitor(ScopedPrinter &P, PDBFile &F) : P(P), F(F) {}
|
||||
Error visitUnknown(ModuleSubstreamKind Kind,
|
||||
StreamRef Data) override {
|
||||
StreamRef Stream) override {
|
||||
DictScope DD(P, "Unknown");
|
||||
return printBinaryData(Data);
|
||||
ArrayRef<uint8_t> Data;
|
||||
StreamReader R(Stream);
|
||||
if (auto EC = R.readBytes(Data, R.bytesRemaining())) {
|
||||
return make_error<RawError>(
|
||||
raw_error_code::corrupt_file,
|
||||
"DBI stream contained corrupt line info record");
|
||||
}
|
||||
P.printBinaryBlock("Data", Data);
|
||||
return Error::success();
|
||||
}
|
||||
Error
|
||||
visitFileChecksums(StreamRef Data,
|
||||
@ -534,7 +542,11 @@ static Error dumpDbiStream(ScopedPrinter &P, PDBFile &File,
|
||||
DictScope DD(P, "FileChecksums");
|
||||
for (const auto &C : Checksums) {
|
||||
DictScope DDD(P, "Checksum");
|
||||
P.printNumber("FileNameOffset", C.FileNameOffset);
|
||||
if (auto Result = getFileNameForOffset(C.FileNameOffset))
|
||||
P.printString("FileName", Result.get());
|
||||
else
|
||||
return Result.takeError();
|
||||
P.flush();
|
||||
P.printEnum("Kind", uint8_t(C.Kind), getFileChecksumNames());
|
||||
P.printBinaryBlock("Checksum", C.Checksum);
|
||||
}
|
||||
@ -545,7 +557,11 @@ static Error dumpDbiStream(ScopedPrinter &P, PDBFile &File,
|
||||
const LineInfoArray &Lines) override {
|
||||
DictScope DD(P, "Lines");
|
||||
for (const auto &L : Lines) {
|
||||
P.printNumber("FileOffset", L.Offset);
|
||||
if (auto Result = getFileNameForOffset2(L.NameIndex))
|
||||
P.printString("FileName", Result.get());
|
||||
else
|
||||
return Result.takeError();
|
||||
P.flush();
|
||||
for (const auto &N : L.LineNumbers) {
|
||||
DictScope DDD(P, "Line");
|
||||
LineInfo LI(N.Flags);
|
||||
@ -569,21 +585,25 @@ static Error dumpDbiStream(ScopedPrinter &P, PDBFile &File,
|
||||
}
|
||||
|
||||
private:
|
||||
Error printBinaryData(StreamRef Stream) {
|
||||
ArrayRef<uint8_t> Data;
|
||||
StreamReader R(Stream);
|
||||
if (auto EC = R.readBytes(Data, R.bytesRemaining())) {
|
||||
return make_error<RawError>(
|
||||
raw_error_code::corrupt_file,
|
||||
"DBI stream contained corrupt line info record");
|
||||
}
|
||||
P.printBinaryBlock("Data", Data);
|
||||
P.flush();
|
||||
return Error::success();
|
||||
Expected<StringRef> getFileNameForOffset(uint32_t Offset) {
|
||||
auto StringT = F.getStringTable();
|
||||
if (auto EC = StringT.takeError())
|
||||
return std::move(EC);
|
||||
NameHashTable &ST = StringT.get();
|
||||
return ST.getStringForID(Offset);
|
||||
}
|
||||
Expected<StringRef> getFileNameForOffset2(uint32_t Offset) {
|
||||
auto DbiS = F.getPDBDbiStream();
|
||||
if (auto EC = DbiS.takeError())
|
||||
return std::move(EC);
|
||||
auto &DS = DbiS.get();
|
||||
return DS.getFileNameForIndex(Offset);
|
||||
}
|
||||
ScopedPrinter &P;
|
||||
PDBFile &F;
|
||||
};
|
||||
RecordVisitor V(P);
|
||||
|
||||
RecordVisitor V(P, File);
|
||||
for (const auto &L : ModS.lines(&HadError)) {
|
||||
if (auto EC = codeview::visitModuleSubstream(L, V))
|
||||
return EC;
|
||||
|
Loading…
Reference in New Issue
Block a user