blob: 166136affed19e37946c6fb81050dfa9f4e716b1 [file] [log] [blame]
Zachary Turner99402032017-06-22 20:58:11 +00001//===- BytesOutputStyle.cpp ----------------------------------- *- C++ --*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "BytesOutputStyle.h"
11
12#include "StreamUtil.h"
13#include "llvm-pdbutil.h"
14
15#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
Zachary Turnerdd739682017-06-23 21:11:54 +000016#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
Zachary Turner6c3e41b2017-06-23 20:18:38 +000017#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
Zachary Turner99402032017-06-22 20:58:11 +000018#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
19#include "llvm/DebugInfo/PDB/Native/RawError.h"
20#include "llvm/Support/BinaryStreamReader.h"
21#include "llvm/Support/FormatAdapters.h"
22#include "llvm/Support/FormatVariadic.h"
23
24using namespace llvm;
25using namespace llvm::msf;
26using namespace llvm::pdb;
27
28namespace {
29struct StreamSpec {
30 uint32_t SI = 0;
31 uint32_t Begin = 0;
32 uint32_t Size = 0;
33};
34} // namespace
35
36static Expected<StreamSpec> parseStreamSpec(StringRef Str) {
37 StreamSpec Result;
38 if (Str.consumeInteger(0, Result.SI))
39 return make_error<RawError>(raw_error_code::invalid_format,
40 "Invalid Stream Specification");
41 if (Str.consume_front(":")) {
42 if (Str.consumeInteger(0, Result.Begin))
43 return make_error<RawError>(raw_error_code::invalid_format,
44 "Invalid Stream Specification");
45 }
46 if (Str.consume_front("@")) {
47 if (Str.consumeInteger(0, Result.Size))
48 return make_error<RawError>(raw_error_code::invalid_format,
49 "Invalid Stream Specification");
50 }
51
52 if (!Str.empty())
53 return make_error<RawError>(raw_error_code::invalid_format,
54 "Invalid Stream Specification");
55 return Result;
56}
57
58static SmallVector<StreamSpec, 2> parseStreamSpecs(LinePrinter &P) {
59 SmallVector<StreamSpec, 2> Result;
60
61 for (auto &Str : opts::bytes::DumpStreamData) {
62 auto ESS = parseStreamSpec(Str);
63 if (!ESS) {
64 P.formatLine("Error parsing stream spec {0}: {1}", Str,
65 toString(ESS.takeError()));
66 continue;
67 }
68 Result.push_back(*ESS);
69 }
70 return Result;
71}
72
73static void printHeader(LinePrinter &P, const Twine &S) {
74 P.NewLine();
75 P.formatLine("{0,=60}", S);
76 P.formatLine("{0}", fmt_repeat('=', 60));
77}
78
79BytesOutputStyle::BytesOutputStyle(PDBFile &File)
80 : File(File), P(2, false, outs()) {}
81
82Error BytesOutputStyle::dump() {
83
84 if (opts::bytes::DumpBlockRange.hasValue()) {
85 auto &R = *opts::bytes::DumpBlockRange;
86 uint32_t Max = R.Max.getValueOr(R.Min);
87
88 if (Max < R.Min)
89 return make_error<StringError>(
90 "Invalid block range specified. Max < Min",
91 inconvertibleErrorCode());
92 if (Max >= File.getBlockCount())
93 return make_error<StringError>(
94 "Invalid block range specified. Requested block out of bounds",
95 inconvertibleErrorCode());
96
97 dumpBlockRanges(R.Min, Max);
98 P.NewLine();
99 }
100
Zachary Turner6b124f22017-06-23 19:54:44 +0000101 if (opts::bytes::DumpByteRange.hasValue()) {
102 auto &R = *opts::bytes::DumpByteRange;
103 uint32_t Max = R.Max.getValueOr(File.getFileSize());
104
105 if (Max < R.Min)
106 return make_error<StringError>("Invalid byte range specified. Max < Min",
107 inconvertibleErrorCode());
108 if (Max >= File.getFileSize())
109 return make_error<StringError>(
110 "Invalid byte range specified. Requested byte larger than file size",
111 inconvertibleErrorCode());
112
113 dumpByteRanges(R.Min, Max);
114 P.NewLine();
115 }
116
Zachary Turner99402032017-06-22 20:58:11 +0000117 if (!opts::bytes::DumpStreamData.empty()) {
118 dumpStreamBytes();
119 P.NewLine();
120 }
Zachary Turner6c3e41b2017-06-23 20:18:38 +0000121
122 if (opts::bytes::NameMap) {
123 dumpNameMap();
124 P.NewLine();
125 }
Zachary Turnerdd739682017-06-23 21:11:54 +0000126
127 if (opts::bytes::SectionContributions) {
128 dumpSectionContributions();
129 P.NewLine();
130 }
131
132 if (opts::bytes::SectionMap) {
133 dumpSectionMap();
134 P.NewLine();
135 }
136
137 if (opts::bytes::ModuleInfos) {
138 dumpModuleInfos();
139 P.NewLine();
140 }
141
142 if (opts::bytes::FileInfo) {
143 dumpFileInfo();
144 P.NewLine();
145 }
146
147 if (opts::bytes::TypeServerMap) {
148 dumpTypeServerMap();
149 P.NewLine();
150 }
151
152 if (opts::bytes::ECData) {
153 dumpECData();
154 P.NewLine();
155 }
156
Zachary Turner99402032017-06-22 20:58:11 +0000157 return Error::success();
158}
159
Zachary Turner6c3e41b2017-06-23 20:18:38 +0000160void BytesOutputStyle::dumpNameMap() {
161 printHeader(P, "Named Stream Map");
162
163 AutoIndent Indent(P);
164
165 auto &InfoS = Err(File.getPDBInfoStream());
166 BinarySubstreamRef NS = InfoS.getNamedStreamsBuffer();
167 auto Layout = File.getStreamLayout(StreamPDB);
168 P.formatMsfStreamData("Named Stream Map", File, Layout, NS);
169}
170
Zachary Turner99402032017-06-22 20:58:11 +0000171void BytesOutputStyle::dumpBlockRanges(uint32_t Min, uint32_t Max) {
172 printHeader(P, "MSF Blocks");
173
174 AutoIndent Indent(P);
175 for (uint32_t I = Min; I <= Max; ++I) {
176 uint64_t Base = I;
177 Base *= File.getBlockSize();
178
179 auto ExpectedData = File.getBlockData(I, File.getBlockSize());
180 if (!ExpectedData) {
181 P.formatLine("Could not get block {0}. Reason = {1}", I,
182 toString(ExpectedData.takeError()));
183 continue;
184 }
185 std::string Label = formatv("Block {0}", I).str();
186 P.formatBinary(Label, *ExpectedData, Base, 0);
187 }
188}
189
Zachary Turnerdd739682017-06-23 21:11:54 +0000190void BytesOutputStyle::dumpSectionContributions() {
191 printHeader(P, "Section Contributions");
192
193 AutoIndent Indent(P);
194
195 auto &DbiS = Err(File.getPDBDbiStream());
196 BinarySubstreamRef NS = DbiS.getSectionContributionData();
197 auto Layout = File.getStreamLayout(StreamDBI);
198 P.formatMsfStreamData("Section Contributions", File, Layout, NS);
199}
200
201void BytesOutputStyle::dumpSectionMap() {
202 printHeader(P, "Section Map");
203
204 AutoIndent Indent(P);
205
206 auto &DbiS = Err(File.getPDBDbiStream());
207 BinarySubstreamRef NS = DbiS.getSecMapSubstreamData();
208 auto Layout = File.getStreamLayout(StreamDBI);
209 P.formatMsfStreamData("Section Map", File, Layout, NS);
210}
211
212void BytesOutputStyle::dumpModuleInfos() {
213 printHeader(P, "Module Infos");
214
215 AutoIndent Indent(P);
216
217 auto &DbiS = Err(File.getPDBDbiStream());
218 BinarySubstreamRef NS = DbiS.getModiSubstreamData();
219 auto Layout = File.getStreamLayout(StreamDBI);
220 P.formatMsfStreamData("Module Infos", File, Layout, NS);
221}
222
223void BytesOutputStyle::dumpFileInfo() {
224 printHeader(P, "File Info");
225
226 AutoIndent Indent(P);
227
228 auto &DbiS = Err(File.getPDBDbiStream());
229 BinarySubstreamRef NS = DbiS.getFileInfoSubstreamData();
230 auto Layout = File.getStreamLayout(StreamDBI);
231 P.formatMsfStreamData("File Info", File, Layout, NS);
232}
233
234void BytesOutputStyle::dumpTypeServerMap() {
235 printHeader(P, "Type Server Map");
236
237 AutoIndent Indent(P);
238
239 auto &DbiS = Err(File.getPDBDbiStream());
240 BinarySubstreamRef NS = DbiS.getTypeServerMapSubstreamData();
241 auto Layout = File.getStreamLayout(StreamDBI);
242 P.formatMsfStreamData("Type Server Map", File, Layout, NS);
243}
244
245void BytesOutputStyle::dumpECData() {
246 printHeader(P, "Edit and Continue Data");
247
248 AutoIndent Indent(P);
249
250 auto &DbiS = Err(File.getPDBDbiStream());
251 BinarySubstreamRef NS = DbiS.getECSubstreamData();
252 auto Layout = File.getStreamLayout(StreamDBI);
253 P.formatMsfStreamData("Edit and Continue Data", File, Layout, NS);
254}
255
Zachary Turner6b124f22017-06-23 19:54:44 +0000256void BytesOutputStyle::dumpByteRanges(uint32_t Min, uint32_t Max) {
257 printHeader(P, "MSF Bytes");
258
259 AutoIndent Indent(P);
260
261 BinaryStreamReader Reader(File.getMsfBuffer());
262 ArrayRef<uint8_t> Data;
263 consumeError(Reader.skip(Min));
264 uint32_t Size = Max - Min + 1;
265 auto EC = Reader.readBytes(Data, Size);
266 assert(!EC);
267 consumeError(std::move(EC));
268 P.formatBinary("Bytes", Data, Min);
269}
270
Zachary Turner99402032017-06-22 20:58:11 +0000271void BytesOutputStyle::dumpStreamBytes() {
272 if (StreamPurposes.empty())
273 discoverStreamPurposes(File, StreamPurposes);
274
275 printHeader(P, "Stream Data");
276 ExitOnError Err("Unexpected error reading stream data");
277
278 auto Specs = parseStreamSpecs(P);
279
280 for (const auto &Spec : Specs) {
Zachary Turner99402032017-06-22 20:58:11 +0000281 AutoIndent Indent(P);
Zachary Turner0b36c3e2017-06-23 18:52:13 +0000282 if (Spec.SI >= StreamPurposes.size()) {
Zachary Turner99402032017-06-22 20:58:11 +0000283 P.formatLine("Stream {0}: Not present", Spec.SI);
284 continue;
285 }
Zachary Turner0b36c3e2017-06-23 18:52:13 +0000286 P.formatMsfStreamData("Data", File, Spec.SI, StreamPurposes[Spec.SI],
287 Spec.Begin, Spec.Size);
Zachary Turner99402032017-06-22 20:58:11 +0000288 }
289}