blob: 123c55d207257db104dcc3d625cf83b5e3223ee1 [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"
16#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
17#include "llvm/DebugInfo/PDB/Native/RawError.h"
18#include "llvm/Support/BinaryStreamReader.h"
19#include "llvm/Support/FormatAdapters.h"
20#include "llvm/Support/FormatVariadic.h"
21
22using namespace llvm;
23using namespace llvm::msf;
24using namespace llvm::pdb;
25
26namespace {
27struct StreamSpec {
28 uint32_t SI = 0;
29 uint32_t Begin = 0;
30 uint32_t Size = 0;
31};
32} // namespace
33
34static Expected<StreamSpec> parseStreamSpec(StringRef Str) {
35 StreamSpec Result;
36 if (Str.consumeInteger(0, Result.SI))
37 return make_error<RawError>(raw_error_code::invalid_format,
38 "Invalid Stream Specification");
39 if (Str.consume_front(":")) {
40 if (Str.consumeInteger(0, Result.Begin))
41 return make_error<RawError>(raw_error_code::invalid_format,
42 "Invalid Stream Specification");
43 }
44 if (Str.consume_front("@")) {
45 if (Str.consumeInteger(0, Result.Size))
46 return make_error<RawError>(raw_error_code::invalid_format,
47 "Invalid Stream Specification");
48 }
49
50 if (!Str.empty())
51 return make_error<RawError>(raw_error_code::invalid_format,
52 "Invalid Stream Specification");
53 return Result;
54}
55
56static SmallVector<StreamSpec, 2> parseStreamSpecs(LinePrinter &P) {
57 SmallVector<StreamSpec, 2> Result;
58
59 for (auto &Str : opts::bytes::DumpStreamData) {
60 auto ESS = parseStreamSpec(Str);
61 if (!ESS) {
62 P.formatLine("Error parsing stream spec {0}: {1}", Str,
63 toString(ESS.takeError()));
64 continue;
65 }
66 Result.push_back(*ESS);
67 }
68 return Result;
69}
70
71static void printHeader(LinePrinter &P, const Twine &S) {
72 P.NewLine();
73 P.formatLine("{0,=60}", S);
74 P.formatLine("{0}", fmt_repeat('=', 60));
75}
76
77BytesOutputStyle::BytesOutputStyle(PDBFile &File)
78 : File(File), P(2, false, outs()) {}
79
80Error BytesOutputStyle::dump() {
81
82 if (opts::bytes::DumpBlockRange.hasValue()) {
83 auto &R = *opts::bytes::DumpBlockRange;
84 uint32_t Max = R.Max.getValueOr(R.Min);
85
86 if (Max < R.Min)
87 return make_error<StringError>(
88 "Invalid block range specified. Max < Min",
89 inconvertibleErrorCode());
90 if (Max >= File.getBlockCount())
91 return make_error<StringError>(
92 "Invalid block range specified. Requested block out of bounds",
93 inconvertibleErrorCode());
94
95 dumpBlockRanges(R.Min, Max);
96 P.NewLine();
97 }
98
99 if (!opts::bytes::DumpStreamData.empty()) {
100 dumpStreamBytes();
101 P.NewLine();
102 }
103 return Error::success();
104}
105
106void BytesOutputStyle::dumpBlockRanges(uint32_t Min, uint32_t Max) {
107 printHeader(P, "MSF Blocks");
108
109 AutoIndent Indent(P);
110 for (uint32_t I = Min; I <= Max; ++I) {
111 uint64_t Base = I;
112 Base *= File.getBlockSize();
113
114 auto ExpectedData = File.getBlockData(I, File.getBlockSize());
115 if (!ExpectedData) {
116 P.formatLine("Could not get block {0}. Reason = {1}", I,
117 toString(ExpectedData.takeError()));
118 continue;
119 }
120 std::string Label = formatv("Block {0}", I).str();
121 P.formatBinary(Label, *ExpectedData, Base, 0);
122 }
123}
124
125void BytesOutputStyle::dumpStreamBytes() {
126 if (StreamPurposes.empty())
127 discoverStreamPurposes(File, StreamPurposes);
128
129 printHeader(P, "Stream Data");
130 ExitOnError Err("Unexpected error reading stream data");
131
132 auto Specs = parseStreamSpecs(P);
133
134 for (const auto &Spec : Specs) {
Zachary Turner99402032017-06-22 20:58:11 +0000135 AutoIndent Indent(P);
Zachary Turner0b36c3e2017-06-23 18:52:13 +0000136 if (Spec.SI >= StreamPurposes.size()) {
Zachary Turner99402032017-06-22 20:58:11 +0000137 P.formatLine("Stream {0}: Not present", Spec.SI);
138 continue;
139 }
Zachary Turner0b36c3e2017-06-23 18:52:13 +0000140 P.formatMsfStreamData("Data", File, Spec.SI, StreamPurposes[Spec.SI],
141 Spec.Begin, Spec.Size);
Zachary Turner99402032017-06-22 20:58:11 +0000142 }
143}