blob: 5cf15685fe328f8bb0ba66fbf2e3ad6517a33c68 [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 Turner6c3e41b2017-06-23 20:18:38 +000016#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
Zachary Turner99402032017-06-22 20:58:11 +000017#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
18#include "llvm/DebugInfo/PDB/Native/RawError.h"
19#include "llvm/Support/BinaryStreamReader.h"
20#include "llvm/Support/FormatAdapters.h"
21#include "llvm/Support/FormatVariadic.h"
22
23using namespace llvm;
24using namespace llvm::msf;
25using namespace llvm::pdb;
26
27namespace {
28struct StreamSpec {
29 uint32_t SI = 0;
30 uint32_t Begin = 0;
31 uint32_t Size = 0;
32};
33} // namespace
34
35static Expected<StreamSpec> parseStreamSpec(StringRef Str) {
36 StreamSpec Result;
37 if (Str.consumeInteger(0, Result.SI))
38 return make_error<RawError>(raw_error_code::invalid_format,
39 "Invalid Stream Specification");
40 if (Str.consume_front(":")) {
41 if (Str.consumeInteger(0, Result.Begin))
42 return make_error<RawError>(raw_error_code::invalid_format,
43 "Invalid Stream Specification");
44 }
45 if (Str.consume_front("@")) {
46 if (Str.consumeInteger(0, Result.Size))
47 return make_error<RawError>(raw_error_code::invalid_format,
48 "Invalid Stream Specification");
49 }
50
51 if (!Str.empty())
52 return make_error<RawError>(raw_error_code::invalid_format,
53 "Invalid Stream Specification");
54 return Result;
55}
56
57static SmallVector<StreamSpec, 2> parseStreamSpecs(LinePrinter &P) {
58 SmallVector<StreamSpec, 2> Result;
59
60 for (auto &Str : opts::bytes::DumpStreamData) {
61 auto ESS = parseStreamSpec(Str);
62 if (!ESS) {
63 P.formatLine("Error parsing stream spec {0}: {1}", Str,
64 toString(ESS.takeError()));
65 continue;
66 }
67 Result.push_back(*ESS);
68 }
69 return Result;
70}
71
72static void printHeader(LinePrinter &P, const Twine &S) {
73 P.NewLine();
74 P.formatLine("{0,=60}", S);
75 P.formatLine("{0}", fmt_repeat('=', 60));
76}
77
78BytesOutputStyle::BytesOutputStyle(PDBFile &File)
79 : File(File), P(2, false, outs()) {}
80
81Error BytesOutputStyle::dump() {
82
83 if (opts::bytes::DumpBlockRange.hasValue()) {
84 auto &R = *opts::bytes::DumpBlockRange;
85 uint32_t Max = R.Max.getValueOr(R.Min);
86
87 if (Max < R.Min)
88 return make_error<StringError>(
89 "Invalid block range specified. Max < Min",
90 inconvertibleErrorCode());
91 if (Max >= File.getBlockCount())
92 return make_error<StringError>(
93 "Invalid block range specified. Requested block out of bounds",
94 inconvertibleErrorCode());
95
96 dumpBlockRanges(R.Min, Max);
97 P.NewLine();
98 }
99
Zachary Turner6b124f22017-06-23 19:54:44 +0000100 if (opts::bytes::DumpByteRange.hasValue()) {
101 auto &R = *opts::bytes::DumpByteRange;
102 uint32_t Max = R.Max.getValueOr(File.getFileSize());
103
104 if (Max < R.Min)
105 return make_error<StringError>("Invalid byte range specified. Max < Min",
106 inconvertibleErrorCode());
107 if (Max >= File.getFileSize())
108 return make_error<StringError>(
109 "Invalid byte range specified. Requested byte larger than file size",
110 inconvertibleErrorCode());
111
112 dumpByteRanges(R.Min, Max);
113 P.NewLine();
114 }
115
Zachary Turner99402032017-06-22 20:58:11 +0000116 if (!opts::bytes::DumpStreamData.empty()) {
117 dumpStreamBytes();
118 P.NewLine();
119 }
Zachary Turner6c3e41b2017-06-23 20:18:38 +0000120
121 if (opts::bytes::NameMap) {
122 dumpNameMap();
123 P.NewLine();
124 }
Zachary Turner99402032017-06-22 20:58:11 +0000125 return Error::success();
126}
127
Zachary Turner6c3e41b2017-06-23 20:18:38 +0000128void BytesOutputStyle::dumpNameMap() {
129 printHeader(P, "Named Stream Map");
130
131 AutoIndent Indent(P);
132
133 auto &InfoS = Err(File.getPDBInfoStream());
134 BinarySubstreamRef NS = InfoS.getNamedStreamsBuffer();
135 auto Layout = File.getStreamLayout(StreamPDB);
136 P.formatMsfStreamData("Named Stream Map", File, Layout, NS);
137}
138
Zachary Turner99402032017-06-22 20:58:11 +0000139void BytesOutputStyle::dumpBlockRanges(uint32_t Min, uint32_t Max) {
140 printHeader(P, "MSF Blocks");
141
142 AutoIndent Indent(P);
143 for (uint32_t I = Min; I <= Max; ++I) {
144 uint64_t Base = I;
145 Base *= File.getBlockSize();
146
147 auto ExpectedData = File.getBlockData(I, File.getBlockSize());
148 if (!ExpectedData) {
149 P.formatLine("Could not get block {0}. Reason = {1}", I,
150 toString(ExpectedData.takeError()));
151 continue;
152 }
153 std::string Label = formatv("Block {0}", I).str();
154 P.formatBinary(Label, *ExpectedData, Base, 0);
155 }
156}
157
Zachary Turner6b124f22017-06-23 19:54:44 +0000158void BytesOutputStyle::dumpByteRanges(uint32_t Min, uint32_t Max) {
159 printHeader(P, "MSF Bytes");
160
161 AutoIndent Indent(P);
162
163 BinaryStreamReader Reader(File.getMsfBuffer());
164 ArrayRef<uint8_t> Data;
165 consumeError(Reader.skip(Min));
166 uint32_t Size = Max - Min + 1;
167 auto EC = Reader.readBytes(Data, Size);
168 assert(!EC);
169 consumeError(std::move(EC));
170 P.formatBinary("Bytes", Data, Min);
171}
172
Zachary Turner99402032017-06-22 20:58:11 +0000173void BytesOutputStyle::dumpStreamBytes() {
174 if (StreamPurposes.empty())
175 discoverStreamPurposes(File, StreamPurposes);
176
177 printHeader(P, "Stream Data");
178 ExitOnError Err("Unexpected error reading stream data");
179
180 auto Specs = parseStreamSpecs(P);
181
182 for (const auto &Spec : Specs) {
Zachary Turner99402032017-06-22 20:58:11 +0000183 AutoIndent Indent(P);
Zachary Turner0b36c3e2017-06-23 18:52:13 +0000184 if (Spec.SI >= StreamPurposes.size()) {
Zachary Turner99402032017-06-22 20:58:11 +0000185 P.formatLine("Stream {0}: Not present", Spec.SI);
186 continue;
187 }
Zachary Turner0b36c3e2017-06-23 18:52:13 +0000188 P.formatMsfStreamData("Data", File, Spec.SI, StreamPurposes[Spec.SI],
189 Spec.Begin, Spec.Size);
Zachary Turner99402032017-06-22 20:58:11 +0000190 }
191}