Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit 5515858

Browse files
author
Zachary Turner
committed
Read the rest of the DBI substreams, and parse source info.
We now read out the rest of the substreams from the DBI streams. One of these substreams, the FileInfo substream, contains information about which source files contribute to each module (aka compiland). This patch additionally parses out the file information from that substream, and dumps it in llvm-pdbdump. Differential Revision: http://reviews.llvm.org/D19634 Reviewed by: ruiu git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@267928 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 956cf76 commit 5515858

File tree

5 files changed

+166
-27
lines changed

5 files changed

+166
-27
lines changed

include/llvm/DebugInfo/PDB/Raw/ModInfo.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "llvm/ADT/StringRef.h"
1414

1515
#include <stdint.h>
16+
#include <vector>
1617

1718
namespace llvm {
1819
class PDBFile;
@@ -42,6 +43,13 @@ class ModInfo {
4243
const FileLayout *Layout;
4344
};
4445

46+
struct ModuleInfoEx {
47+
ModuleInfoEx(ModInfo Module) : Info(Module) {}
48+
49+
ModInfo Info;
50+
std::vector<StringRef> SourceFiles;
51+
};
52+
4553
class ModInfoIterator {
4654
public:
4755
ModInfoIterator(const uint8_t *Stream);

include/llvm/DebugInfo/PDB/Raw/PDBDbiStream.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,23 @@ class PDBDbiStream {
4343

4444
PDB_Machine getMachineType() const;
4545

46-
llvm::iterator_range<ModInfoIterator> modules() const;
46+
ArrayRef<ModuleInfoEx> modules() const;
4747

4848
private:
49+
std::error_code readSubstream(std::vector<uint8_t> &Bytes, uint32_t Size);
50+
std::error_code initializeFileInfo();
51+
4952
PDBFile &Pdb;
5053
PDBStream Stream;
5154

55+
std::vector<ModuleInfoEx> ModuleInfos;
56+
5257
std::vector<uint8_t> ModInfoSubstream;
58+
std::vector<uint8_t> SecContrSubstream;
59+
std::vector<uint8_t> SecMapSubstream;
60+
std::vector<uint8_t> FileInfoSubstream;
61+
std::vector<uint8_t> TypeServerMapSubstream;
62+
std::vector<uint8_t> ECSubstream;
5363
std::unique_ptr<HeaderInfo> Header;
5464
};
5565
}

lib/DebugInfo/PDB/Raw/PDBDbiStream.cpp

Lines changed: 124 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,16 @@ struct PDBDbiStream::HeaderInfo {
4848
little32_t VersionSignature;
4949
ulittle32_t VersionHeader;
5050
ulittle32_t Age; // Should match PDBInfoStream.
51-
ulittle16_t GSSyms;
52-
ulittle16_t BuildNumber; // See DbiBuildNo structure.
53-
ulittle16_t PSSyms;
51+
ulittle16_t GSSyms; // Number of global symbols
52+
ulittle16_t BuildNumber; // See DbiBuildNo structure.
53+
ulittle16_t PSSyms; // Number of public symbols
5454
ulittle16_t PdbDllVersion; // version of mspdbNNN.dll
5555
ulittle16_t SymRecords; // Number of symbols
5656
ulittle16_t PdbDllRbld; // rbld number of mspdbNNN.dll
5757
little32_t ModiSubstreamSize; // Size of module info stream
5858
little32_t SecContrSubstreamSize; // Size of sec. contribution stream
59-
little32_t SectionMapSize;
60-
little32_t FileInfoSize;
59+
little32_t SectionMapSize; // Size of sec. map substream
60+
little32_t FileInfoSize; // Size of file info substream
6161
little32_t TypeServerSize; // Size of type server map
6262
ulittle32_t MFCTypeServerIndex; // Index of MFC Type Server
6363
little32_t OptionalDbgHdrSize; // Size of DbgHeader info
@@ -101,12 +101,42 @@ std::error_code PDBDbiStream::reload() {
101101
Header->OptionalDbgHdrSize + Header->ECSubstreamSize)
102102
return std::make_error_code(std::errc::illegal_byte_sequence);
103103

104+
// Only certain substreams are guaranteed to be aligned. Validate
105+
// them here.
104106
if (Header->ModiSubstreamSize % sizeof(uint32_t) != 0)
105107
return std::make_error_code(std::errc::illegal_byte_sequence);
108+
if (Header->SecContrSubstreamSize % sizeof(uint32_t) != 0)
109+
return std::make_error_code(std::errc::illegal_byte_sequence);
110+
if (Header->SectionMapSize % sizeof(uint32_t) != 0)
111+
return std::make_error_code(std::errc::illegal_byte_sequence);
112+
if (Header->FileInfoSize % sizeof(uint32_t) != 0)
113+
return std::make_error_code(std::errc::illegal_byte_sequence);
114+
if (Header->TypeServerSize % sizeof(uint32_t) != 0)
115+
return std::make_error_code(std::errc::illegal_byte_sequence);
116+
117+
std::error_code EC;
118+
if (EC = readSubstream(ModInfoSubstream, Header->ModiSubstreamSize))
119+
return EC;
120+
121+
// Since each ModInfo in the stream is a variable length, we have to iterate
122+
// them to know how many there actually are.
123+
auto Range = llvm::make_range(ModInfoIterator(&ModInfoSubstream.front()),
124+
ModInfoIterator(&ModInfoSubstream.back() + 1));
125+
for (auto Info : Range)
126+
ModuleInfos.push_back(ModuleInfoEx(Info));
106127

107-
ModInfoSubstream.resize(Header->ModiSubstreamSize);
108-
if (auto EC =
109-
Stream.readBytes(&ModInfoSubstream[0], Header->ModiSubstreamSize))
128+
if (EC = readSubstream(SecContrSubstream, Header->SecContrSubstreamSize))
129+
return EC;
130+
if (EC = readSubstream(SecMapSubstream, Header->SectionMapSize))
131+
return EC;
132+
if (EC = readSubstream(FileInfoSubstream, Header->FileInfoSize))
133+
return EC;
134+
if (EC = readSubstream(TypeServerMapSubstream, Header->TypeServerSize))
135+
return EC;
136+
if (EC = readSubstream(ECSubstream, Header->ECSubstreamSize))
137+
return EC;
138+
139+
if (EC = initializeFileInfo())
110140
return EC;
111141

112142
return std::error_code();
@@ -150,7 +180,90 @@ PDB_Machine PDBDbiStream::getMachineType() const {
150180
return static_cast<PDB_Machine>(Machine);
151181
}
152182

153-
llvm::iterator_range<ModInfoIterator> PDBDbiStream::modules() const {
154-
return llvm::make_range(ModInfoIterator(&ModInfoSubstream.front()),
155-
ModInfoIterator(&ModInfoSubstream.back() + 1));
183+
ArrayRef<ModuleInfoEx> PDBDbiStream::modules() const { return ModuleInfos; }
184+
185+
std::error_code PDBDbiStream::readSubstream(std::vector<uint8_t> &Bytes, uint32_t Size) {
186+
Bytes.clear();
187+
if (Size == 0)
188+
return std::error_code();
189+
190+
Bytes.resize(Size);
191+
return Stream.readBytes(&Bytes[0], Size);
192+
}
193+
194+
std::error_code PDBDbiStream::initializeFileInfo() {
195+
struct FileInfoSubstreamHeader {
196+
ulittle16_t NumModules; // Total # of modules, should match number of
197+
// records in the ModuleInfo substream.
198+
ulittle16_t NumSourceFiles; // Total # of source files. This value is not
199+
// accurate because PDB actually supports more
200+
// than 64k source files, so we ignore it and
201+
// compute the value from other stream fields.
202+
};
203+
204+
// The layout of the FileInfoSubstream is like this:
205+
// struct {
206+
// ulittle16_t NumModules;
207+
// ulittle16_t NumSourceFiles;
208+
// ulittle16_t ModIndices[NumModules];
209+
// ulittle16_t ModFileCounts[NumModules];
210+
// ulittle32_t FileNameOffsets[NumSourceFiles];
211+
// char Names[][NumSourceFiles];
212+
// };
213+
// with the caveat that `NumSourceFiles` cannot be trusted, so
214+
// it is computed by summing `ModFileCounts`.
215+
//
216+
const uint8_t *Buf = &FileInfoSubstream[0];
217+
auto FI = reinterpret_cast<const FileInfoSubstreamHeader *>(Buf);
218+
Buf += sizeof(FileInfoSubstreamHeader);
219+
// The number of modules in the stream should be the same as reported by
220+
// the FileInfoSubstreamHeader.
221+
if (FI->NumModules != ModuleInfos.size())
222+
return std::make_error_code(std::errc::illegal_byte_sequence);
223+
224+
// First is an array of `NumModules` module indices. This is not used for the
225+
// same reason that `NumSourceFiles` is not used. It's an array of uint16's,
226+
// but it's possible there are more than 64k source files, which would imply
227+
// more than 64k modules (e.g. object files) as well. So we ignore this
228+
// field.
229+
llvm::ArrayRef<ulittle16_t> ModIndexArray(
230+
reinterpret_cast<const ulittle16_t *>(Buf), ModuleInfos.size());
231+
232+
llvm::ArrayRef<ulittle16_t> ModFileCountArray(ModIndexArray.end(),
233+
ModuleInfos.size());
234+
235+
// Compute the real number of source files.
236+
uint32_t NumSourceFiles = 0;
237+
for (auto Count : ModFileCountArray)
238+
NumSourceFiles += Count;
239+
240+
// This is the array that in the reference implementation corresponds to
241+
// `ModInfo::FileLayout::FileNameOffs`, which is commented there as being a
242+
// pointer. Due to the mentioned problems of pointers causing difficulty
243+
// when reading from the file on 64-bit systems, we continue to ignore that
244+
// field in `ModInfo`, and instead build a vector of StringRefs and stores
245+
// them in `ModuleInfoEx`. The value written to and read from the file is
246+
// not used anyway, it is only there as a way to store the offsets for the
247+
// purposes of later accessing the names at runtime.
248+
llvm::ArrayRef<little32_t> FileNameOffsets(
249+
reinterpret_cast<const little32_t *>(ModFileCountArray.end()),
250+
NumSourceFiles);
251+
252+
const char *Names = reinterpret_cast<const char *>(FileNameOffsets.end());
253+
254+
// We go through each ModuleInfo, determine the number N of source files for
255+
// that module, and then get the next N offsets from the Offsets array, using
256+
// them to get the corresponding N names from the Names buffer and associating
257+
// each one with the corresponding module.
258+
uint32_t NextFileIndex = 0;
259+
for (size_t I = 0; I < ModuleInfos.size(); ++I) {
260+
uint32_t NumFiles = ModFileCountArray[I];
261+
ModuleInfos[I].SourceFiles.resize(NumFiles);
262+
for (size_t J = 0; J < NumFiles; ++J, ++NextFileIndex) {
263+
uint32_t FileIndex = FileNameOffsets[NextFileIndex];
264+
ModuleInfos[I].SourceFiles[J] = StringRef(Names + FileIndex);
265+
}
266+
}
267+
268+
return std::error_code();
156269
}

test/DebugInfo/PDB/pdbdump-headers.test

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
; CHECK-NEXT: Symbol Byte Size: 208
4242
; CHECK-NEXT: Type Server Index: 0
4343
; CHECK-NEXT: Has EC Info: 0
44+
; CHECK-NEXT: 1 Contributing Source Files:
45+
; CHECK-NEXT: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
4446
; CHECK-NEXT: * Linker *
4547
; CHECK-NEXT: Debug Stream Index: 14
4648
; CHECK-NEXT: Object File:
@@ -52,3 +54,4 @@
5254
; CHECK-NEXT: Symbol Byte Size: 516
5355
; CHECK-NEXT: Type Server Index: 0
5456
; CHECK-NEXT: Has EC Info: 0
57+
; CHECK-NEXT: 0 Contributing Source Files:

tools/llvm-pdbdump/llvm-pdbdump.cpp

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -281,25 +281,30 @@ static void dumpStructure(RawSession &RS) {
281281
<< Minor << "." << DbiStream.getPdbDllVersion() << '\n';
282282

283283
outs() << "Modules: \n";
284-
for (auto Modi : DbiStream.modules()) {
285-
outs() << Modi.getModuleName() << '\n';
286-
outs().indent(4) << "Debug Stream Index: " << Modi.getModuleStreamIndex()
287-
<< '\n';
288-
outs().indent(4) << "Object File: " << Modi.getObjFileName() << '\n';
289-
outs().indent(4) << "Num Files: " << Modi.getNumberOfFiles() << '\n';
284+
for (auto &Modi : DbiStream.modules()) {
285+
outs() << Modi.Info.getModuleName() << '\n';
286+
outs().indent(4) << "Debug Stream Index: "
287+
<< Modi.Info.getModuleStreamIndex() << '\n';
288+
outs().indent(4) << "Object File: " << Modi.Info.getObjFileName() << '\n';
289+
outs().indent(4) << "Num Files: " << Modi.Info.getNumberOfFiles() << '\n';
290290
outs().indent(4) << "Source File Name Idx: "
291-
<< Modi.getSourceFileNameIndex() << '\n';
292-
outs().indent(4) << "Pdb File Name Idx: " << Modi.getPdbFilePathNameIndex()
293-
<< '\n';
294-
outs().indent(4) << "Line Info Byte Size: " << Modi.getLineInfoByteSize()
295-
<< '\n';
291+
<< Modi.Info.getSourceFileNameIndex() << '\n';
292+
outs().indent(4) << "Pdb File Name Idx: "
293+
<< Modi.Info.getPdbFilePathNameIndex() << '\n';
294+
outs().indent(4) << "Line Info Byte Size: "
295+
<< Modi.Info.getLineInfoByteSize() << '\n';
296296
outs().indent(4) << "C13 Line Info Byte Size: "
297-
<< Modi.getC13LineInfoByteSize() << '\n';
297+
<< Modi.Info.getC13LineInfoByteSize() << '\n';
298298
outs().indent(4) << "Symbol Byte Size: "
299-
<< Modi.getSymbolDebugInfoByteSize() << '\n';
300-
outs().indent(4) << "Type Server Index: " << Modi.getTypeServerIndex()
299+
<< Modi.Info.getSymbolDebugInfoByteSize() << '\n';
300+
outs().indent(4) << "Type Server Index: " << Modi.Info.getTypeServerIndex()
301301
<< '\n';
302-
outs().indent(4) << "Has EC Info: " << Modi.hasECInfo() << '\n';
302+
outs().indent(4) << "Has EC Info: " << Modi.Info.hasECInfo() << '\n';
303+
outs().indent(4) << Modi.SourceFiles.size()
304+
<< " Contributing Source Files: \n";
305+
for (auto File : Modi.SourceFiles) {
306+
outs().indent(8) << File << '\n';
307+
}
303308
}
304309
}
305310

0 commit comments

Comments
 (0)