llvm.org GIT mirror llvm / 18a8461
Revert "Build fixes for pdb-diff test." This reverts commit 180af3fdbdb17ec35b45ec1f925fd743b28d37e1. This is still breaking due to linux-specific path differences. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@307559 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 3 years ago
7 changed file(s) with 149 addition(s) and 291 deletion(s). Raw diff Collapse all Expand all
2222 #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
2323 #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
2424
25 #include "llvm/Support/FileSystem.h"
2625 #include "llvm/Support/FormatAdapters.h"
2726 #include "llvm/Support/FormatProviders.h"
2827 #include "llvm/Support/FormatVariadic.h"
29 #include "llvm/Support/Path.h"
3028
3129 using namespace llvm;
3230 using namespace llvm::pdb;
33
34 namespace {
35 // Compare and format two stream numbers. Stream numbers are considered
36 // identical if they contain the same value, equivalent if they are both
37 // the invalid stream or neither is the invalid stream, and different if
38 // one is the invalid stream and another isn't.
39 struct StreamNumberProvider {
40 static DiffResult compare(uint16_t L, uint16_t R) {
41 if (L == R)
42 return DiffResult::IDENTICAL;
43 bool LP = L != kInvalidStreamIndex;
44 bool RP = R != kInvalidStreamIndex;
45 if (LP != RP)
46 return DiffResult::DIFFERENT;
47 return DiffResult::EQUIVALENT;
48 }
49
50 static std::string format(uint16_t SN, bool Right) {
51 if (SN == kInvalidStreamIndex)
52 return "(not present)";
53 return formatv("{0}", SN).str();
54 }
55 };
56
57 // Compares and formats two module indices. Modis are considered identical
58 // if they are identical, equivalent if they either both contain a value or
59 // both don't contain a value, and different if one contains a value and the
60 // other doesn't.
61 struct ModiProvider {
62 DiffResult compare(Optional L, Optional R) {
63 if (L == R)
64 return DiffResult::IDENTICAL;
65 if (L.hasValue() != R.hasValue())
66 return DiffResult::DIFFERENT;
67 return DiffResult::EQUIVALENT;
68 }
69
70 std::string format(Optional Modi, bool Right) {
71 if (!Modi.hasValue())
72 return "(not present)";
73 return formatv("{0}", *Modi).str();
74 }
75 };
76
77 // Compares and formats two paths embedded in the PDB, ignoring the beginning
78 // of the path if the user specified it as a "root path" on the command line.
79 struct BinaryPathProvider {
80 explicit BinaryPathProvider(uint32_t MaxLen) : MaxLen(MaxLen) {}
81
82 DiffResult compare(StringRef L, StringRef R) {
83 if (L == R)
84 return DiffResult::IDENTICAL;
85
86 SmallString<64> LN = removeRoot(L, false);
87 SmallString<64> RN = removeRoot(R, true);
88
89 return (LN.equals_lower(RN)) ? DiffResult::EQUIVALENT
90 : DiffResult::DIFFERENT;
91 }
92
93 std::string format(StringRef S, bool Right) {
94 if (S.empty())
95 return "(empty)";
96
97 SmallString<64> Native = removeRoot(S, Right);
98 return truncateStringFront(Native.str(), MaxLen);
99 }
100
101 SmallString<64> removeRoot(StringRef Path, bool IsRight) const {
102 SmallString<64> Native(Path);
103 auto &RootOpt = IsRight ? opts::diff::RightRoot : opts::diff::LeftRoot;
104 SmallString<64> Root(static_cast(RootOpt));
105 // pdb paths always use windows syntax, convert slashes to backslashes.
106 sys::path::native(Root, sys::path::Style::windows);
107 if (sys::path::has_stem(Root, sys::path::Style::windows))
108 sys::path::append(Root,
109 sys::path::get_separator(sys::path::Style::windows));
110
111 sys::path::replace_path_prefix(Native, Root, "");
112 return Native;
113 }
114 uint32_t MaxLen;
115 };
116
117 // Compare and format two stream purposes. For general streams, this just
118 // compares the description. For module streams it uses the path comparison
119 // algorithm taking into consideration the binary root, described above.
120 // Formatting stream purposes just prints the stream purpose, except for
121 // module streams and named streams, where it prefixes the name / module
122 // with an identifier. Example:
123 //
124 // Named Stream "\names"
125 // Module Stream "foo.obj"
126 //
127 // If a named stream is too long to fit in a column, it is truncated at the
128 // end, and if a module is too long to fit in a column, it is truncated at the
129 // beginning. Example:
130 //
131 // Named Stream "\Really Long Str..."
132 // Module Stream "...puts\foo.obj"
133 //
134 struct StreamPurposeProvider {
135 explicit StreamPurposeProvider(uint32_t MaxLen) : MaxLen(MaxLen) {}
136
137 DiffResult compare(const std::pair &L,
138 const std::pair &R) {
139 if (L.first != R.first)
140 return DiffResult::DIFFERENT;
141 if (L.first == StreamPurpose::ModuleStream) {
142 BinaryPathProvider PathProvider(MaxLen);
143 return PathProvider.compare(L.second, R.second);
144 }
145 return (L.second == R.second) ? DiffResult::IDENTICAL
146 : DiffResult::DIFFERENT;
147 }
148
149 std::string format(const std::pair &P,
150 bool Right) {
151 if (P.first == StreamPurpose::Other)
152 return truncateStringBack(P.second, MaxLen);
153 if (P.first == StreamPurpose::NamedStream)
154 return truncateQuotedNameBack("Named Stream", P.second, MaxLen);
155
156 assert(P.first == StreamPurpose::ModuleStream);
157 uint32_t ExtraChars = strlen("Module \"\"");
158 BinaryPathProvider PathProvider(MaxLen - ExtraChars);
159 std::string Result = PathProvider.format(P.second, Right);
160 return formatv("Module \"{0}\"", Result);
161 }
162
163 uint32_t MaxLen;
164 };
165 }
16631
16732 namespace llvm {
16833 template <> struct format_provider {
23499 return Error::success();
235100 }
236101
102 static std::string shortFilePath(StringRef Path, uint32_t Width) {
103 if (Path.size() <= Width)
104 return Path;
105 Path = Path.take_back(Width - 3);
106 return std::string("...") + Path.str();
107 }
108
237109 Error DiffStyle::diffSuperBlock() {
238110 DiffPrinter D(2, "MSF Super Block", 16, 20, opts::diff::PrintResultColumn,
239111 opts::diff::PrintValueColumns, outs());
240112 D.printExplicit("File", DiffResult::UNSPECIFIED,
241 truncateStringFront(File1.getFilePath(), 18),
242 truncateStringFront(File2.getFilePath(), 18));
113 shortFilePath(File1.getFilePath(), 18),
114 shortFilePath(File2.getFilePath(), 18));
243115 D.print("Block Size", File1.getBlockSize(), File2.getBlockSize());
244116 D.print("Block Count", File1.getBlockCount(), File2.getBlockCount());
245117 D.print("Unknown 1", File1.getUnknown1(), File2.getUnknown1());
252124 DiffPrinter D(2, "Stream Directory", 30, 20, opts::diff::PrintResultColumn,
253125 opts::diff::PrintValueColumns, outs());
254126 D.printExplicit("File", DiffResult::UNSPECIFIED,
255 truncateStringFront(File1.getFilePath(), 18),
256 truncateStringFront(File2.getFilePath(), 18));
257
258 SmallVector, 32> P;
259 SmallVector, 32> Q;
260 discoverStreamPurposes(File1, P);
261 discoverStreamPurposes(File2, Q);
127 shortFilePath(File1.getFilePath(), 18),
128 shortFilePath(File2.getFilePath(), 18));
129
130 SmallVector P;
131 SmallVector Q;
132 discoverStreamPurposes(File1, P, 28);
133 discoverStreamPurposes(File2, Q, 28);
262134 D.print("Stream Count", File1.getNumStreams(), File2.getNumStreams());
263135 auto PI = to_vector<32>(enumerate(P));
264136 auto QI = to_vector<32>(enumerate(Q));
266138 // Scan all streams in the left hand side, looking for ones that are also
267139 // in the right. Each time we find one, remove it. When we're done, Q
268140 // should contain all the streams that are in the right but not in the left.
269 StreamPurposeProvider StreamProvider(28);
270141 for (const auto &P : PI) {
271142 typedef decltype(PI) ContainerType;
272143 typedef typename ContainerType::value_type value_type;
273144
274 auto Iter = llvm::find_if(QI, [P, &StreamProvider](const value_type &V) {
275 DiffResult Result = StreamProvider.compare(P.value(), V.value());
276 return Result == DiffResult::EQUIVALENT ||
277 Result == DiffResult::IDENTICAL;
278 });
145 auto Iter = llvm::find_if(
146 QI, [P](const value_type &V) { return V.value() == P.value(); });
279147
280148 if (Iter == QI.end()) {
281 D.printExplicit(StreamProvider.format(P.value(), false),
282 DiffResult::DIFFERENT, P.index(), "(not present)");
149 D.printExplicit(P.value(), DiffResult::DIFFERENT, P.index(),
150 "(not present)");
283151 continue;
284152 }
285153
286 D.print(StreamProvider.format(P.value(), false),
287 P.index(), Iter->index());
154 D.print(P.value(), P.index(), Iter->index());
288155 QI.erase(Iter);
289156 }
290157
291158 for (const auto &Q : QI) {
292 D.printExplicit(StreamProvider.format(Q.value(), true),
293 DiffResult::DIFFERENT, "(not present)", Q.index());
159 D.printExplicit(Q.value(), DiffResult::DIFFERENT, "(not present)",
160 Q.index());
294161 }
295162
296163 return Error::success();
300167 DiffPrinter D(2, "String Table", 30, 20, opts::diff::PrintResultColumn,
301168 opts::diff::PrintValueColumns, outs());
302169 D.printExplicit("File", DiffResult::UNSPECIFIED,
303 truncateStringFront(File1.getFilePath(), 18),
304 truncateStringFront(File2.getFilePath(), 18));
170 shortFilePath(File1.getFilePath(), 18),
171 shortFilePath(File2.getFilePath(), 18));
305172
306173 auto ExpectedST1 = File1.getStringTable();
307174 auto ExpectedST2 = File2.getStringTable();
389256 DiffPrinter D(2, "PDB Stream", 22, 40, opts::diff::PrintResultColumn,
390257 opts::diff::PrintValueColumns, outs());
391258 D.printExplicit("File", DiffResult::UNSPECIFIED,
392 truncateStringFront(File1.getFilePath(), 38),
393 truncateStringFront(File2.getFilePath(), 38));
259 shortFilePath(File1.getFilePath(), 38),
260 shortFilePath(File2.getFilePath(), 38));
394261
395262 auto ExpectedInfo1 = File1.getPDBInfoStream();
396263 auto ExpectedInfo2 = File2.getPDBInfoStream();
424291 return Error::success();
425292 }
426293
294 struct StreamNumberProvider {
295 static DiffResult compare(uint16_t L, uint16_t R) {
296 if (L == R)
297 return DiffResult::IDENTICAL;
298 bool LP = L != kInvalidStreamIndex;
299 bool RP = R != kInvalidStreamIndex;
300 if (LP != RP)
301 return DiffResult::DIFFERENT;
302 return DiffResult::EQUIVALENT;
303 }
304
305 static std::string format(uint16_t SN) {
306 if (SN == kInvalidStreamIndex)
307 return "(not present)";
308 return formatv("{0}", SN).str();
309 }
310 };
311
312 struct ModiProvider {
313 DiffResult compare(Optional L, Optional R) {
314 if (L == R)
315 return DiffResult::IDENTICAL;
316 if (L.hasValue() != R.hasValue())
317 return DiffResult::DIFFERENT;
318 return DiffResult::EQUIVALENT;
319 }
320
321 std::string format(Optional Modi) {
322 if (!Modi.hasValue())
323 return "(not present)";
324 return formatv("{0}", *Modi).str();
325 }
326 };
327
328 struct StringProvider {
329 DiffResult compare(StringRef L, StringRef R) {
330 IdenticalDiffProvider I;
331 return I.compare(L, R);
332 }
333
334 std::string format(StringRef S) {
335 if (S.empty())
336 return "(empty)";
337 return S;
338 }
339 };
340
427341 static std::vector>
428342 getModuleDescriptors(const DbiModuleList &ML) {
429343 std::vector> List;
433347 return List;
434348 }
435349
436 static void
437 diffOneModule(DiffPrinter &D,
438 const std::pair Item,
439 std::vector> &Other,
440 bool ItemIsRight) {
441 StreamPurposeProvider HeaderProvider(70);
442 std::pair Header;
443 Header.first = StreamPurpose::ModuleStream;
444 Header.second = Item.second.getModuleName();
445 D.printFullRow(HeaderProvider.format(Header, ItemIsRight));
446
447 const auto *L = &Item;
448
449 BinaryPathProvider PathProvider(28);
350 static void diffOneModule(
351 DiffPrinter &D, const std::pair Item,
352 std::vector> &Other, bool Invert) {
353 D.printFullRow(
354 truncateQuotedNameFront("Module", Item.second.getModuleName(), 70));
355
450356 auto Iter = llvm::find_if(
451 Other, [&PathProvider, ItemIsRight,
452 L](const std::pair &Other) {
453 const auto *Left = L;
454 const auto *Right = &Other;
455 if (ItemIsRight)
456 std::swap(Left, Right);
457 DiffResult Result = PathProvider.compare(Left->second.getModuleName(),
458 Right->second.getModuleName());
459 return Result == DiffResult::EQUIVALENT ||
460 Result == DiffResult::IDENTICAL;
357 Other, [&Item](const std::pair &Other) {
358 return Other.second.getModuleName().equals_lower(
359 Item.second.getModuleName());
461360 });
462361 if (Iter == Other.end()) {
463362 // We didn't find this module at all on the other side. Just print one row
467366 }
468367
469368 // We did find this module. Go through and compare each field.
369 const auto *L = &Item;
470370 const auto *R = &*Iter;
471 if (ItemIsRight)
371 if (Invert)
472372 std::swap(L, R);
473373
474374 D.print("- Modi", L->first, R->first);
475 D.print("- Obj File Name", L->second.getObjFileName(),
476 R->second.getObjFileName(), PathProvider);
375 D.print("- Obj File Name",
376 shortFilePath(L->second.getObjFileName(), 28),
377 shortFilePath(R->second.getObjFileName(), 28));
477378 D.print("- Debug Stream",
478379 L->second.getModuleStreamIndex(),
479380 R->second.getModuleStreamIndex());
496397 DiffPrinter D(2, "DBI Stream", 40, 30, opts::diff::PrintResultColumn,
497398 opts::diff::PrintValueColumns, outs());
498399 D.printExplicit("File", DiffResult::UNSPECIFIED,
499 truncateStringFront(File1.getFilePath(), 28),
500 truncateStringFront(File2.getFilePath(), 28));
400 shortFilePath(File1.getFilePath(), 28),
401 shortFilePath(File2.getFilePath(), 28));
501402
502403 auto ExpectedDbi1 = File1.getPDBDbiStream();
503404 auto ExpectedDbi2 = File2.getPDBDbiStream();
55 using namespace llvm;
66 using namespace llvm::pdb;
77
8 namespace {
9 struct Colorize {
10 Colorize(raw_ostream &OS, DiffResult Result) : OS(OS) {
11 if (!OS.has_colors())
12 return;
13 switch (Result) {
14 case DiffResult::IDENTICAL:
15 OS.changeColor(raw_ostream::Colors::GREEN, false);
16 break;
17 case DiffResult::EQUIVALENT:
18 OS.changeColor(raw_ostream::Colors::YELLOW, true);
19 break;
20 default:
21 OS.changeColor(raw_ostream::Colors::RED, false);
22 break;
23 }
8 static void setColor(llvm::raw_ostream &OS, DiffResult Result) {
9 switch (Result) {
10 case DiffResult::IDENTICAL:
11 OS.changeColor(raw_ostream::Colors::GREEN, false);
12 break;
13 case DiffResult::EQUIVALENT:
14 OS.changeColor(raw_ostream::Colors::YELLOW, true);
15 break;
16 default:
17 OS.changeColor(raw_ostream::Colors::RED, false);
18 break;
2419 }
25
26 ~Colorize() {
27 if (OS.has_colors())
28 OS.resetColor();
29 }
30
31 raw_ostream &OS;
32 };
3320 }
3421
3522 DiffPrinter::DiffPrinter(uint32_t Indent, StringRef Header,
136123 std::string FormattedItem =
137124 formatv("{0}", fmt_align(Value, Style, Width)).str();
138125 if (C != DiffResult::UNSPECIFIED) {
139 Colorize Color(OS, C);
126 setColor(OS, C);
140127 OS << FormattedItem;
128 OS.resetColor();
141129 } else
142130 OS << FormattedItem;
143131 if (Style == AlignStyle::Right)
4242 return (Left == Right) ? DiffResult::IDENTICAL : DiffResult::DIFFERENT;
4343 }
4444
45 template std::string format(const T &Item, bool Right) {
45 template std::string format(const T &Item) {
4646 return formatv("{0}", Item).str();
4747 }
4848 };
5353 return (Left == Right) ? DiffResult::IDENTICAL : DiffResult::EQUIVALENT;
5454 }
5555
56 template std::string format(const T &Item, bool Right) {
56 template std::string format(const T &Item) {
5757 return formatv("{0}", Item).str();
5858 }
5959 };
7070 template
7171 void print(StringRef Property, const T &Left, const U &Right,
7272 Provider P = Provider()) {
73 std::string L = P.format(Left, false);
74 std::string R = P.format(Right, true);
73 std::string L = P.format(Left);
74 std::string R = P.format(Right);
7575
7676 DiffResult Result = P.compare(Left, Right);
7777 printExplicit(Property, Result, L, R);
2121 using namespace llvm;
2222 using namespace llvm::pdb;
2323
24 void llvm::pdb::discoverStreamPurposes(
25 PDBFile &File,
26 SmallVectorImpl> &Purposes) {
24 void llvm::pdb::discoverStreamPurposes(PDBFile &File,
25 SmallVectorImpl &Purposes,
26 uint32_t MaxLen) {
27
2728 // It's OK if we fail to load some of these streams, we still attempt to print
2829 // what we can.
2930 auto Dbi = File.getPDBDbiStream();
5354
5455 Purposes.resize(StreamCount);
5556 for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
56 std::pair Value;
57 std::string Value;
5758 if (StreamIdx == OldMSFDirectory)
58 Value = std::make_pair(StreamPurpose::Other, "Old MSF Directory");
59 Value = truncateStringBack("Old MSF Directory", MaxLen);
5960 else if (StreamIdx == StreamPDB)
60 Value = std::make_pair(StreamPurpose::Other, "PDB Stream");
61 Value = truncateStringBack("PDB Stream", MaxLen);
6162 else if (StreamIdx == StreamDBI)
62 Value = std::make_pair(StreamPurpose::Other, "DBI Stream");
63 Value = truncateStringBack("DBI Stream", MaxLen);
6364 else if (StreamIdx == StreamTPI)
64 Value = std::make_pair(StreamPurpose::Other, "TPI Stream");
65 Value = truncateStringBack("TPI Stream", MaxLen);
6566 else if (StreamIdx == StreamIPI)
66 Value = std::make_pair(StreamPurpose::Other, "IPI Stream");
67 Value = truncateStringBack("IPI Stream", MaxLen);
6768 else if (Dbi && StreamIdx == Dbi->getGlobalSymbolStreamIndex())
68 Value = std::make_pair(StreamPurpose::Other, "Global Symbol Hash");
69 Value = truncateStringBack("Global Symbol Hash", MaxLen);
6970 else if (Dbi && StreamIdx == Dbi->getPublicSymbolStreamIndex())
70 Value = std::make_pair(StreamPurpose::Other, "Public Symbol Hash");
71 Value = truncateStringBack("Public Symbol Hash", MaxLen);
7172 else if (Dbi && StreamIdx == Dbi->getSymRecordStreamIndex())
72 Value = std::make_pair(StreamPurpose::Other, "Public Symbol Records");
73 Value = truncateStringBack("Public Symbol Records", MaxLen);
7374 else if (Tpi && StreamIdx == Tpi->getTypeHashStreamIndex())
74 Value = std::make_pair(StreamPurpose::Other, "TPI Hash");
75 Value = truncateStringBack("TPI Hash", MaxLen);
7576 else if (Tpi && StreamIdx == Tpi->getTypeHashStreamAuxIndex())
76 Value = std::make_pair(StreamPurpose::Other, "TPI Aux Hash");
77 Value = truncateStringBack("TPI Aux Hash", MaxLen);
7778 else if (Ipi && StreamIdx == Ipi->getTypeHashStreamIndex())
78 Value = std::make_pair(StreamPurpose::Other, "IPI Hash");
79 Value = truncateStringBack("IPI Hash", MaxLen);
7980 else if (Ipi && StreamIdx == Ipi->getTypeHashStreamAuxIndex())
80 Value = std::make_pair(StreamPurpose::Other, "IPI Aux Hash");
81 Value = truncateStringBack("IPI Aux Hash", MaxLen);
8182 else if (Dbi &&
8283 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Exception))
83 Value = std::make_pair(StreamPurpose::Other, "Exception Data");
84 Value = truncateStringBack("Exception Data", MaxLen);
8485 else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Fixup))
85 Value = std::make_pair(StreamPurpose::Other, "Fixup Data");
86 Value = truncateStringBack("Fixup Data", MaxLen);
8687 else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::FPO))
87 Value = std::make_pair(StreamPurpose::Other, "FPO Data");
88 Value = truncateStringBack("FPO Data", MaxLen);
8889 else if (Dbi &&
8990 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::NewFPO))
90 Value = std::make_pair(StreamPurpose::Other, "New FPO Data");
91 Value = truncateStringBack("New FPO Data", MaxLen);
9192 else if (Dbi &&
9293 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapFromSrc))
93 Value = std::make_pair(StreamPurpose::Other, "Omap From Source Data");
94 Value = truncateStringBack("Omap From Source Data", MaxLen);
9495 else if (Dbi &&
9596 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapToSrc))
96 Value = std::make_pair(StreamPurpose::Other, "Omap To Source Data");
97 Value = truncateStringBack("Omap To Source Data", MaxLen);
9798 else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Pdata))
98 Value = std::make_pair(StreamPurpose::Other, "Pdata");
99 Value = truncateStringBack("Pdata", MaxLen);
99100 else if (Dbi &&
100101 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdr))
101 Value = std::make_pair(StreamPurpose::Other, "Section Header Data");
102 Value = truncateStringBack("Section Header Data", MaxLen);
102103 else if (Dbi &&
103104 StreamIdx ==
104105 Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdrOrig))
105 Value =
106 std::make_pair(StreamPurpose::Other, "Section Header Original Data");
106 Value = truncateStringBack("Section Header Original Data", MaxLen);
107107 else if (Dbi &&
108108 StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::TokenRidMap))
109 Value = std::make_pair(StreamPurpose::Other, "Token Rid Data");
109 Value = truncateStringBack("Token Rid Data", MaxLen);
110110 else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Xdata))
111 Value = std::make_pair(StreamPurpose::Other, "Xdata");
111 Value = truncateStringBack("Xdata", MaxLen);
112112 else {
113113 auto ModIter = ModStreams.find(StreamIdx);
114114 auto NSIter = NamedStreams.find(StreamIdx);
115115 if (ModIter != ModStreams.end()) {
116 Value = std::make_pair(StreamPurpose::ModuleStream,
117 ModIter->second.getModuleName());
116 Value = truncateQuotedNameFront(
117 "Module", ModIter->second.getModuleName(), MaxLen);
118118 } else if (NSIter != NamedStreams.end()) {
119 Value = std::make_pair(StreamPurpose::NamedStream, NSIter->second);
119 Value = truncateQuotedNameBack("Named Stream", NSIter->second, MaxLen);
120120 } else {
121 Value = std::make_pair(StreamPurpose::Other, "???");
121 Value = "???";
122122 }
123123 }
124124 Purposes[StreamIdx] = Value;
134134 if (!Info)
135135 consumeError(Info.takeError());
136136 }
137
138 void llvm::pdb::discoverStreamPurposes(PDBFile &File,
139 SmallVectorImpl &Purposes) {
140 SmallVector, 24> SP;
141 discoverStreamPurposes(File, SP);
142 Purposes.reserve(SP.size());
143 for (const auto &P : SP) {
144 if (P.first == StreamPurpose::NamedStream)
145 Purposes.push_back(formatv("Named Stream \"{0}\"", P.second));
146 else if (P.first == StreamPurpose::ModuleStream)
147 Purposes.push_back(formatv("Module \"{0}\"", P.second));
148 else
149 Purposes.push_back(P.second);
150 }
151 }
1616 namespace llvm {
1717 namespace pdb {
1818 class PDBFile;
19 enum class StreamPurpose { NamedStream, ModuleStream, Other };
20
2119 void discoverStreamPurposes(PDBFile &File,
22 SmallVectorImpl &Purposes);
23 void discoverStreamPurposes(
24 PDBFile &File,
25 SmallVectorImpl> &Purposes);
20 SmallVectorImpl &Purposes,
21 uint32_t MaxLen = 0);
2622 }
2723 }
2824
292292 cl::desc("Print a column with the result status"),
293293 cl::Optional, cl::sub(DiffSubcommand));
294294
295 cl::opt LeftRoot(
296 "left-bin-root", cl::Optional,
297 cl::desc("Treats the specified path as the root of the tree containing "
298 "binaries referenced by the left PDB. The root is stripped from "
299 "embedded paths when doing equality comparisons."),
300 cl::sub(DiffSubcommand));
301 cl::opt RightRoot(
302 "right-bin-root", cl::Optional,
303 cl::desc("Treats the specified path as the root of the tree containing "
304 "binaries referenced by the right PDB. The root is stripped from "
305 "embedded paths when doing equality comparisons"),
306 cl::sub(DiffSubcommand));
307
308 cl::opt Left(cl::Positional, cl::desc(""),
309 cl::sub(DiffSubcommand));
310 cl::opt Right(cl::Positional, cl::desc(""),
311 cl::sub(DiffSubcommand));
295 cl::list InputFilenames(cl::Positional,
296 cl::desc(" "),
297 cl::OneOrMore, cl::sub(DiffSubcommand));
312298 }
313299
314300 cl::OptionCategory FileOptions("Module & File Options");
11641150 std::for_each(opts::bytes::InputFilenames.begin(),
11651151 opts::bytes::InputFilenames.end(), dumpBytes);
11661152 } else if (opts::DiffSubcommand) {
1167 diff(opts::diff::Left, opts::diff::Right);
1153 if (opts::diff::InputFilenames.size() != 2) {
1154 errs() << "diff subcommand expects exactly 2 arguments.\n";
1155 exit(1);
1156 }
1157 diff(opts::diff::InputFilenames[0], opts::diff::InputFilenames[1]);
11681158 } else if (opts::MergeSubcommand) {
11691159 if (opts::merge::InputFilenames.size() < 2) {
11701160 errs() << "merge subcommand requires at least 2 input files.\n";
171171 namespace diff {
172172 extern llvm::cl::opt PrintValueColumns;
173173 extern llvm::cl::opt PrintResultColumn;
174 extern llvm::cl::opt LeftRoot;
175 extern llvm::cl::opt RightRoot;
176174 } // namespace diff
177175 }
178176