llvm.org GIT mirror llvm / 34173de
[pdbutil] Add a command to dump the FPM. Recently problems have been discovered in the way we write the FPM (free page map). In order to fix this, we first need to establish a baseline about what a correct FPM looks like using an MSVC generated PDB, so that we can then make our own generated PDBs match. And in order to do this, the dumper needs a mode where it can dump an FPM so that we can write tests for it. This patch adds a command to dump the FPM, as well as a test against a known-good PDB. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@309894 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 2 years ago
15 changed file(s) with 92 addition(s) and 60 deletion(s). Raw diff Collapse all Expand all
5858 std::vector> StreamMap;
5959 };
6060
61 /// \brief Describes the layout of a stream in an MSF layout. A "stream" here
62 /// is defined as any logical unit of data which may be arranged inside the MSF
63 /// file as a sequence of (possibly discontiguous) blocks. When we want to read
64 /// from a particular MSF Stream, we fill out a stream layout structure and the
65 /// reader uses it to determine which blocks in the underlying MSF file contain
66 /// the data, so that it can be pieced together in the right order.
67 class MSFStreamLayout {
68 public:
69 uint32_t Length;
70 std::vector Blocks;
71 };
72
73 /// \brief Determine the layout of the FPM stream, given the MSF layout. An FPM
74 /// stream spans 1 or more blocks, each at equally spaced intervals throughout
75 /// the file.
76 MSFStreamLayout getFpmStreamLayout(const MSFLayout &Msf);
77
6178 inline bool isValidBlockSize(uint32_t Size) {
6279 switch (Size) {
6380 case 512:
+0
-35
include/llvm/DebugInfo/MSF/MSFStreamLayout.h less more
None //===- MSFStreamLayout.h - Describes the layout of a stream -----*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_DEBUGINFO_MSF_MSFSTREAMLAYOUT_H
10 #define LLVM_DEBUGINFO_MSF_MSFSTREAMLAYOUT_H
11
12 #include "llvm/Support/Endian.h"
13
14 #include
15 #include
16
17 namespace llvm {
18 namespace msf {
19
20 /// \brief Describes the layout of a stream in an MSF layout. A "stream" here
21 /// is defined as any logical unit of data which may be arranged inside the MSF
22 /// file as a sequence of (possibly discontiguous) blocks. When we want to read
23 /// from a particular MSF Stream, we fill out a stream layout structure and the
24 /// reader uses it to determine which blocks in the underlying MSF file contain
25 /// the data, so that it can be pieced together in the right order.
26 class MSFStreamLayout {
27 public:
28 uint32_t Length;
29 std::vector Blocks;
30 };
31 } // namespace msf
32 } // namespace llvm
33
34 #endif // LLVM_DEBUGINFO_MSF_MSFSTREAMLAYOUT_H
1111
1212 #include "llvm/ADT/ArrayRef.h"
1313 #include "llvm/ADT/DenseMap.h"
14 #include "llvm/DebugInfo/MSF/MSFStreamLayout.h"
14 #include "llvm/DebugInfo/MSF/MSFCommon.h"
1515 #include "llvm/Support/Allocator.h"
1616 #include "llvm/Support/BinaryStream.h"
1717 #include "llvm/Support/BinaryStreamRef.h"
1212 #include "llvm/ADT/DenseMap.h"
1313 #include "llvm/DebugInfo/MSF/IMSFFile.h"
1414 #include "llvm/DebugInfo/MSF/MSFCommon.h"
15 #include "llvm/DebugInfo/MSF/MSFStreamLayout.h"
1615 #include "llvm/Support/Allocator.h"
1716 #include "llvm/Support/BinaryStreamRef.h"
1817 #include "llvm/Support/Endian.h"
7170 Error setBlockData(uint32_t BlockIndex, uint32_t Offset,
7271 ArrayRef Data) const override;
7372
74 ArrayRef getFpmPages() const { return FpmPages; }
75
7673 ArrayRef getStreamSizes() const {
7774 return ContainerLayout.StreamSizes;
7875 }
8683 ArrayRef getDirectoryBlockArray() const;
8784
8885 msf::MSFStreamLayout getStreamLayout(uint32_t StreamIdx) const;
86 msf::MSFStreamLayout getFpmStreamLayout() const;
8987
9088 Error parseFileHeaders();
9189 Error parseStreamData();
123121
124122 std::unique_ptr Buffer;
125123
126 std::vector FpmPages;
127124 msf::MSFLayout ContainerLayout;
128125
129126 std::unique_ptr Globals;
5858
5959 return Error::success();
6060 }
61
62 MSFStreamLayout llvm::msf::getFpmStreamLayout(const MSFLayout &Msf) {
63 MSFStreamLayout FL;
64 uint32_t NumFpmIntervals = getNumFpmIntervals(Msf);
65 support::ulittle32_t FpmBlock = Msf.SB->FreeBlockMapBlock;
66 assert(FpmBlock == 1 || FpmBlock == 2);
67 while (NumFpmIntervals > 0) {
68 FL.Blocks.push_back(FpmBlock);
69 FpmBlock += msf::getFpmIntervalLength(Msf);
70 --NumFpmIntervals;
71 }
72 FL.Length = getFullFpmByteSize(Msf);
73
74 return FL;
75 }
1010 #include "llvm/ADT/ArrayRef.h"
1111 #include "llvm/ADT/STLExtras.h"
1212 #include "llvm/DebugInfo/MSF/MSFCommon.h"
13 #include "llvm/DebugInfo/MSF/MSFStreamLayout.h"
1413 #include "llvm/Support/Endian.h"
1514 #include "llvm/Support/Error.h"
1615 #include "llvm/Support/MathExtras.h"
3534
3635 } // end anonymous namespace
3736
38 static void initializeFpmStreamLayout(const MSFLayout &Layout,
39 MSFStreamLayout &FpmLayout) {
40 uint32_t NumFpmIntervals = msf::getNumFpmIntervals(Layout);
41 support::ulittle32_t FpmBlock = Layout.SB->FreeBlockMapBlock;
42 assert(FpmBlock == 1 || FpmBlock == 2);
43 while (NumFpmIntervals > 0) {
44 FpmLayout.Blocks.push_back(FpmBlock);
45 FpmBlock += msf::getFpmIntervalLength(Layout);
46 --NumFpmIntervals;
47 }
48 FpmLayout.Length = msf::getFullFpmByteSize(Layout);
49 }
50
5137 using Interval = std::pair;
5238
5339 static Interval intersect(const Interval &I1, const Interval &I2) {
9480 MappedBlockStream::createFpmStream(const MSFLayout &Layout,
9581 BinaryStreamRef MsfData,
9682 BumpPtrAllocator &Allocator) {
97 MSFStreamLayout SL;
98 initializeFpmStreamLayout(Layout, SL);
83 MSFStreamLayout SL(getFpmStreamLayout(Layout));
9984 return createStream(Layout.SB->BlockSize, SL, MsfData, Allocator);
10085 }
10186
362347 WritableMappedBlockStream::createFpmStream(const MSFLayout &Layout,
363348 WritableBinaryStreamRef MsfData,
364349 BumpPtrAllocator &Allocator) {
365 MSFStreamLayout SL;
366 initializeFpmStreamLayout(Layout, SL);
350 MSFStreamLayout SL(getFpmStreamLayout(Layout));
367351 return createStream(Layout.SB->BlockSize, SL, MsfData, Allocator);
368352 }
369353
237237 return Result;
238238 }
239239
240 msf::MSFStreamLayout PDBFile::getFpmStreamLayout() const {
241 return msf::getFpmStreamLayout(ContainerLayout);
242 }
243
240244 Expected PDBFile::getPDBGlobalsStream() {
241245 if (!Globals) {
242246 auto DbiS = getPDBDbiStream();
0 RUN: llvm-pdbutil bytes -fpm %p/Inputs/empty.pdb | FileCheck %s
1
2 CHECK: Free Page Map
3 CHECK-NEXT: ============================================================
4 CHECK-NEXT: Block 2 (
5 CHECK-NEXT: 2000: 380300FE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |8...............................|
6 CHECK-NEXT: 2020: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................................|
7 CHECK: 2FE0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................................|
8 CHECK-NEXT: )
1414
1515 #include "llvm/DebugInfo/CodeView/Formatters.h"
1616 #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
17 #include "llvm/DebugInfo/MSF/MSFCommon.h"
1718 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
1819 #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
1920 #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
116117 inconvertibleErrorCode());
117118
118119 dumpByteRanges(R.Min, Max);
120 P.NewLine();
121 }
122
123 if (opts::bytes::Fpm) {
124 dumpFpm();
119125 P.NewLine();
120126 }
121127
479485 return *TypeCollection;
480486 }
481487
488 void BytesOutputStyle::dumpFpm() {
489 printHeader(P, "Free Page Map");
490
491 msf::MSFStreamLayout FpmLayout = File.getFpmStreamLayout();
492 P.formatMsfStreamBlocks(File, FpmLayout);
493 }
494
482495 void BytesOutputStyle::dumpStreamBytes() {
483496 if (StreamPurposes.empty())
484497 discoverStreamPurposes(File, StreamPurposes);
3434 void dumpNameMap();
3535 void dumpBlockRanges(uint32_t Min, uint32_t Max);
3636 void dumpByteRanges(uint32_t Min, uint32_t Max);
37 void dumpFpm();
3738 void dumpStreamBytes();
3839
3940 void dumpSectionContributions();
1212
1313 #include "llvm/ADT/STLExtras.h"
1414 #include "llvm/DebugInfo/MSF/MSFCommon.h"
15 #include "llvm/DebugInfo/MSF/MSFStreamLayout.h"
1615 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
1716 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
1817 #include "llvm/DebugInfo/PDB/UDTLayout.h"
245244 OS << ")";
246245 }
247246
247 void LinePrinter::formatMsfStreamBlocks(
248 PDBFile &File, const msf::MSFStreamLayout &StreamLayout) {
249 auto Blocks = makeArrayRef(StreamLayout.Blocks);
250 uint32_t L = StreamLayout.Length;
251
252 while (L > 0) {
253 NewLine();
254 assert(!Blocks.empty());
255 OS << formatv("Block {0} (\n", uint32_t(Blocks.front()));
256 uint32_t UsedBytes = std::min(L, File.getBlockSize());
257 ArrayRef BlockData =
258 cantFail(File.getBlockData(Blocks.front(), File.getBlockSize()));
259 uint64_t BaseOffset = Blocks.front();
260 BaseOffset *= File.getBlockSize();
261 OS << format_bytes_with_ascii(BlockData, BaseOffset, 32, 4,
262 CurrentIndent + IndentSpaces, true);
263 NewLine();
264 OS << ")";
265 NewLine();
266 L -= UsedBytes;
267 Blocks = Blocks.drop_front();
268 }
269 }
270
248271 bool LinePrinter::IsTypeExcluded(llvm::StringRef TypeName, uint32_t Size) {
249272 if (IsItemExcluded(TypeName, IncludeTypeFilters, ExcludeTypeFilters))
250273 return true;
5959 void formatMsfStreamData(StringRef Label, PDBFile &File,
6060 const msf::MSFStreamLayout &Stream,
6161 BinarySubstreamRef Substream);
62 void formatMsfStreamBlocks(PDBFile &File, const msf::MSFStreamLayout &Stream);
6263
6364 bool hasColor() const { return UseColor; }
6465 raw_ostream &getStream() { return OS; }
341341
342342 cl::opt NameMap("name-map", cl::desc("Dump bytes of PDB Name Map"),
343343 cl::sub(BytesSubcommand), cl::cat(PdbBytes));
344 cl::opt Fpm("fpm", cl::desc("Dump free page map"),
345 cl::sub(BytesSubcommand), cl::cat(MsfBytes));
344346
345347 cl::opt SectionContributions("sc", cl::desc("Dump section contributions"),
346348 cl::sub(BytesSubcommand), cl::cat(DbiBytes));
101101 extern llvm::Optional DumpByteRange;
102102 extern llvm::cl::list DumpStreamData;
103103 extern llvm::cl::opt NameMap;
104 extern llvm::cl::opt Fpm;
104105
105106 extern llvm::cl::opt SectionContributions;
106107 extern llvm::cl::opt SectionMap;
122123 namespace dump {
123124
124125 extern llvm::cl::opt DumpSummary;
126 extern llvm::cl::opt DumpFpm;
125127 extern llvm::cl::opt DumpStreams;
126128 extern llvm::cl::opt DumpStreamBlocks;
127129
99 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
1010 #include "llvm/DebugInfo/MSF/IMSFFile.h"
1111 #include "llvm/DebugInfo/MSF/MSFError.h"
12 #include "llvm/DebugInfo/MSF/MSFStreamLayout.h"
1312 #include "llvm/Support/BinaryByteStream.h"
1413 #include "llvm/Support/BinaryStreamReader.h"
1514 #include "llvm/Support/BinaryStreamRef.h"