Mercurial > hg > CbC > CbC_llvm
comparison tools/llvm-pdbutil/Diff.cpp @ 121:803732b1fca8
LLVM 5.0
author | kono |
---|---|
date | Fri, 27 Oct 2017 17:07:41 +0900 |
parents | |
children | 3a76565eade5 |
comparison
equal
deleted
inserted
replaced
120:1172e4bd9c6f | 121:803732b1fca8 |
---|---|
1 //===- Diff.cpp - PDB diff utility ------------------------------*- 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 "Diff.h" | |
11 | |
12 #include "DiffPrinter.h" | |
13 #include "FormatUtil.h" | |
14 #include "StreamUtil.h" | |
15 #include "llvm-pdbutil.h" | |
16 | |
17 #include "llvm/ADT/StringSet.h" | |
18 | |
19 #include "llvm/DebugInfo/PDB/Native/DbiStream.h" | |
20 #include "llvm/DebugInfo/PDB/Native/Formatters.h" | |
21 #include "llvm/DebugInfo/PDB/Native/InfoStream.h" | |
22 #include "llvm/DebugInfo/PDB/Native/PDBFile.h" | |
23 #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" | |
24 #include "llvm/DebugInfo/PDB/Native/RawConstants.h" | |
25 | |
26 #include "llvm/Support/FileSystem.h" | |
27 #include "llvm/Support/FormatAdapters.h" | |
28 #include "llvm/Support/FormatProviders.h" | |
29 #include "llvm/Support/FormatVariadic.h" | |
30 #include "llvm/Support/Path.h" | |
31 | |
32 using namespace llvm; | |
33 using namespace llvm::pdb; | |
34 | |
35 namespace { | |
36 // Compare and format two stream numbers. Stream numbers are considered | |
37 // identical if they contain the same value, equivalent if they are both | |
38 // the invalid stream or neither is the invalid stream, and different if | |
39 // one is the invalid stream and another isn't. | |
40 struct StreamNumberProvider { | |
41 static DiffResult compare(uint16_t L, uint16_t R) { | |
42 if (L == R) | |
43 return DiffResult::IDENTICAL; | |
44 bool LP = L != kInvalidStreamIndex; | |
45 bool RP = R != kInvalidStreamIndex; | |
46 if (LP != RP) | |
47 return DiffResult::DIFFERENT; | |
48 return DiffResult::EQUIVALENT; | |
49 } | |
50 | |
51 static std::string format(uint16_t SN, bool Right) { | |
52 if (SN == kInvalidStreamIndex) | |
53 return "(not present)"; | |
54 return formatv("{0}", SN).str(); | |
55 } | |
56 }; | |
57 | |
58 // Compares and formats two module indices. Modis are considered identical | |
59 // if they are identical, equivalent if they either both contain a value or | |
60 // both don't contain a value, and different if one contains a value and the | |
61 // other doesn't. | |
62 struct ModiProvider { | |
63 DiffResult compare(Optional<uint32_t> L, Optional<uint32_t> R) { | |
64 if (L == R) | |
65 return DiffResult::IDENTICAL; | |
66 if (L.hasValue() != R.hasValue()) | |
67 return DiffResult::DIFFERENT; | |
68 return DiffResult::EQUIVALENT; | |
69 } | |
70 | |
71 std::string format(Optional<uint32_t> Modi, bool Right) { | |
72 if (!Modi.hasValue()) | |
73 return "(not present)"; | |
74 return formatv("{0}", *Modi).str(); | |
75 } | |
76 }; | |
77 | |
78 // Compares and formats two paths embedded in the PDB, ignoring the beginning | |
79 // of the path if the user specified it as a "root path" on the command line. | |
80 struct BinaryPathProvider { | |
81 explicit BinaryPathProvider(uint32_t MaxLen) : MaxLen(MaxLen) {} | |
82 | |
83 DiffResult compare(StringRef L, StringRef R) { | |
84 if (L == R) | |
85 return DiffResult::IDENTICAL; | |
86 | |
87 SmallString<64> LN = removeRoot(L, false); | |
88 SmallString<64> RN = removeRoot(R, true); | |
89 | |
90 return (LN.equals_lower(RN)) ? DiffResult::EQUIVALENT | |
91 : DiffResult::DIFFERENT; | |
92 } | |
93 | |
94 std::string format(StringRef S, bool Right) { | |
95 if (S.empty()) | |
96 return "(empty)"; | |
97 | |
98 SmallString<64> Native = removeRoot(S, Right); | |
99 return truncateStringFront(Native.str(), MaxLen); | |
100 } | |
101 | |
102 SmallString<64> removeRoot(StringRef Path, bool IsRight) const { | |
103 SmallString<64> Native(Path); | |
104 auto &RootOpt = IsRight ? opts::diff::RightRoot : opts::diff::LeftRoot; | |
105 SmallString<64> Root(static_cast<std::string>(RootOpt)); | |
106 // pdb paths always use windows syntax, convert slashes to backslashes. | |
107 sys::path::native(Root, sys::path::Style::windows); | |
108 if (sys::path::has_stem(Root, sys::path::Style::windows)) | |
109 sys::path::append(Root, sys::path::Style::windows, | |
110 sys::path::get_separator(sys::path::Style::windows)); | |
111 | |
112 sys::path::replace_path_prefix(Native, Root, "", sys::path::Style::windows); | |
113 return Native; | |
114 } | |
115 uint32_t MaxLen; | |
116 }; | |
117 | |
118 // Compare and format two stream purposes. For general streams, this just | |
119 // compares the description. For module streams it uses the path comparison | |
120 // algorithm taking into consideration the binary root, described above. | |
121 // Formatting stream purposes just prints the stream purpose, except for | |
122 // module streams and named streams, where it prefixes the name / module | |
123 // with an identifier. Example: | |
124 // | |
125 // Named Stream "\names" | |
126 // Module Stream "foo.obj" | |
127 // | |
128 // If a named stream is too long to fit in a column, it is truncated at the | |
129 // end, and if a module is too long to fit in a column, it is truncated at the | |
130 // beginning. Example: | |
131 // | |
132 // Named Stream "\Really Long Str..." | |
133 // Module Stream "...puts\foo.obj" | |
134 // | |
135 struct StreamPurposeProvider { | |
136 explicit StreamPurposeProvider(uint32_t MaxLen) : MaxLen(MaxLen) {} | |
137 | |
138 DiffResult compare(const StreamInfo &L, const StreamInfo &R) { | |
139 if (L.getPurpose() != R.getPurpose()) | |
140 return DiffResult::DIFFERENT; | |
141 if (L.getPurpose() == StreamPurpose::ModuleStream) { | |
142 BinaryPathProvider PathProvider(MaxLen); | |
143 return PathProvider.compare(L.getShortName(), R.getShortName()); | |
144 } | |
145 return (L.getShortName() == R.getShortName()) ? DiffResult::IDENTICAL | |
146 : DiffResult::DIFFERENT; | |
147 } | |
148 | |
149 std::string format(const StreamInfo &P, bool Right) { | |
150 if (P.getPurpose() == StreamPurpose::Other || | |
151 P.getPurpose() == StreamPurpose::Symbols) | |
152 return truncateStringBack(P.getShortName(), MaxLen); | |
153 if (P.getPurpose() == StreamPurpose::NamedStream) | |
154 return truncateQuotedNameBack("Named Stream", P.getShortName(), MaxLen); | |
155 | |
156 assert(P.getPurpose() == StreamPurpose::ModuleStream); | |
157 uint32_t ExtraChars = strlen("Module \"\""); | |
158 BinaryPathProvider PathProvider(MaxLen - ExtraChars); | |
159 std::string Result = PathProvider.format(P.getShortName(), Right); | |
160 return formatv("Module \"{0}\"", Result); | |
161 } | |
162 | |
163 uint32_t MaxLen; | |
164 }; | |
165 } // namespace | |
166 | |
167 namespace llvm { | |
168 template <> struct format_provider<PdbRaw_FeatureSig> { | |
169 static void format(const PdbRaw_FeatureSig &Sig, raw_ostream &Stream, | |
170 StringRef Style) { | |
171 switch (Sig) { | |
172 case PdbRaw_FeatureSig::MinimalDebugInfo: | |
173 Stream << "MinimalDebugInfo"; | |
174 break; | |
175 case PdbRaw_FeatureSig::NoTypeMerge: | |
176 Stream << "NoTypeMerge"; | |
177 break; | |
178 case PdbRaw_FeatureSig::VC110: | |
179 Stream << "VC110"; | |
180 break; | |
181 case PdbRaw_FeatureSig::VC140: | |
182 Stream << "VC140"; | |
183 break; | |
184 } | |
185 } | |
186 }; | |
187 } | |
188 | |
189 template <typename R> using ValueOfRange = llvm::detail::ValueOfRange<R>; | |
190 | |
191 DiffStyle::DiffStyle(PDBFile &File1, PDBFile &File2) | |
192 : File1(File1), File2(File2) {} | |
193 | |
194 Error DiffStyle::dump() { | |
195 if (auto EC = diffSuperBlock()) | |
196 return EC; | |
197 | |
198 if (auto EC = diffFreePageMap()) | |
199 return EC; | |
200 | |
201 if (auto EC = diffStreamDirectory()) | |
202 return EC; | |
203 | |
204 if (auto EC = diffStringTable()) | |
205 return EC; | |
206 | |
207 if (auto EC = diffInfoStream()) | |
208 return EC; | |
209 | |
210 if (auto EC = diffDbiStream()) | |
211 return EC; | |
212 | |
213 if (auto EC = diffSectionContribs()) | |
214 return EC; | |
215 | |
216 if (auto EC = diffSectionMap()) | |
217 return EC; | |
218 | |
219 if (auto EC = diffFpoStream()) | |
220 return EC; | |
221 | |
222 if (auto EC = diffTpiStream(StreamTPI)) | |
223 return EC; | |
224 | |
225 if (auto EC = diffTpiStream(StreamIPI)) | |
226 return EC; | |
227 | |
228 if (auto EC = diffPublics()) | |
229 return EC; | |
230 | |
231 if (auto EC = diffGlobals()) | |
232 return EC; | |
233 | |
234 return Error::success(); | |
235 } | |
236 | |
237 Error DiffStyle::diffSuperBlock() { | |
238 DiffPrinter D(2, "MSF Super Block", 16, 20, opts::diff::PrintResultColumn, | |
239 opts::diff::PrintValueColumns, outs()); | |
240 D.printExplicit("File", DiffResult::UNSPECIFIED, | |
241 truncateStringFront(File1.getFilePath(), 18), | |
242 truncateStringFront(File2.getFilePath(), 18)); | |
243 D.print("Block Size", File1.getBlockSize(), File2.getBlockSize()); | |
244 D.print("Block Count", File1.getBlockCount(), File2.getBlockCount()); | |
245 D.print("Unknown 1", File1.getUnknown1(), File2.getUnknown1()); | |
246 D.print("Directory Size", File1.getNumDirectoryBytes(), | |
247 File2.getNumDirectoryBytes()); | |
248 return Error::success(); | |
249 } | |
250 | |
251 Error DiffStyle::diffStreamDirectory() { | |
252 DiffPrinter D(2, "Stream Directory", 30, 20, opts::diff::PrintResultColumn, | |
253 opts::diff::PrintValueColumns, outs()); | |
254 D.printExplicit("File", DiffResult::UNSPECIFIED, | |
255 truncateStringFront(File1.getFilePath(), 18), | |
256 truncateStringFront(File2.getFilePath(), 18)); | |
257 | |
258 SmallVector<StreamInfo, 32> P; | |
259 SmallVector<StreamInfo, 32> Q; | |
260 discoverStreamPurposes(File1, P); | |
261 discoverStreamPurposes(File2, Q); | |
262 D.print("Stream Count", File1.getNumStreams(), File2.getNumStreams()); | |
263 auto PI = to_vector<32>(enumerate(P)); | |
264 auto QI = to_vector<32>(enumerate(Q)); | |
265 | |
266 // Scan all streams in the left hand side, looking for ones that are also | |
267 // in the right. Each time we find one, remove it. When we're done, Q | |
268 // should contain all the streams that are in the right but not in the left. | |
269 StreamPurposeProvider StreamProvider(28); | |
270 for (const auto &P : PI) { | |
271 typedef decltype(PI) ContainerType; | |
272 typedef typename ContainerType::value_type value_type; | |
273 | |
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 }); | |
279 | |
280 if (Iter == QI.end()) { | |
281 D.printExplicit(StreamProvider.format(P.value(), false), | |
282 DiffResult::DIFFERENT, P.index(), "(not present)"); | |
283 continue; | |
284 } | |
285 | |
286 D.print<EquivalentDiffProvider>(StreamProvider.format(P.value(), false), | |
287 P.index(), Iter->index()); | |
288 QI.erase(Iter); | |
289 } | |
290 | |
291 for (const auto &Q : QI) { | |
292 D.printExplicit(StreamProvider.format(Q.value(), true), | |
293 DiffResult::DIFFERENT, "(not present)", Q.index()); | |
294 } | |
295 | |
296 return Error::success(); | |
297 } | |
298 | |
299 Error DiffStyle::diffStringTable() { | |
300 DiffPrinter D(2, "String Table", 30, 20, opts::diff::PrintResultColumn, | |
301 opts::diff::PrintValueColumns, outs()); | |
302 D.printExplicit("File", DiffResult::UNSPECIFIED, | |
303 truncateStringFront(File1.getFilePath(), 18), | |
304 truncateStringFront(File2.getFilePath(), 18)); | |
305 | |
306 auto ExpectedST1 = File1.getStringTable(); | |
307 auto ExpectedST2 = File2.getStringTable(); | |
308 bool Has1 = !!ExpectedST1; | |
309 bool Has2 = !!ExpectedST2; | |
310 std::string Count1 = Has1 ? llvm::utostr(ExpectedST1->getNameCount()) | |
311 : "(string table not present)"; | |
312 std::string Count2 = Has2 ? llvm::utostr(ExpectedST2->getNameCount()) | |
313 : "(string table not present)"; | |
314 D.print("Number of Strings", Count1, Count2); | |
315 | |
316 if (!Has1 || !Has2) { | |
317 consumeError(ExpectedST1.takeError()); | |
318 consumeError(ExpectedST2.takeError()); | |
319 return Error::success(); | |
320 } | |
321 | |
322 auto &ST1 = *ExpectedST1; | |
323 auto &ST2 = *ExpectedST2; | |
324 | |
325 D.print("Hash Version", ST1.getHashVersion(), ST2.getHashVersion()); | |
326 D.print("Byte Size", ST1.getByteSize(), ST2.getByteSize()); | |
327 D.print("Signature", ST1.getSignature(), ST2.getSignature()); | |
328 | |
329 // Both have a valid string table, dive in and compare individual strings. | |
330 | |
331 auto IdList1 = ST1.name_ids(); | |
332 auto IdList2 = ST2.name_ids(); | |
333 StringSet<> LS; | |
334 StringSet<> RS; | |
335 uint32_t Empty1 = 0; | |
336 uint32_t Empty2 = 0; | |
337 for (auto ID : IdList1) { | |
338 auto S = ST1.getStringForID(ID); | |
339 if (!S) | |
340 return S.takeError(); | |
341 if (S->empty()) | |
342 ++Empty1; | |
343 else | |
344 LS.insert(*S); | |
345 } | |
346 for (auto ID : IdList2) { | |
347 auto S = ST2.getStringForID(ID); | |
348 if (!S) | |
349 return S.takeError(); | |
350 if (S->empty()) | |
351 ++Empty2; | |
352 else | |
353 RS.insert(*S); | |
354 } | |
355 D.print("Empty Strings", Empty1, Empty2); | |
356 | |
357 for (const auto &S : LS) { | |
358 auto R = RS.find(S.getKey()); | |
359 std::string Truncated = truncateStringMiddle(S.getKey(), 28); | |
360 uint32_t I = cantFail(ST1.getIDForString(S.getKey())); | |
361 if (R == RS.end()) { | |
362 D.printExplicit(Truncated, DiffResult::DIFFERENT, I, "(not present)"); | |
363 continue; | |
364 } | |
365 | |
366 uint32_t J = cantFail(ST2.getIDForString(R->getKey())); | |
367 D.print<EquivalentDiffProvider>(Truncated, I, J); | |
368 RS.erase(R); | |
369 } | |
370 | |
371 for (const auto &S : RS) { | |
372 auto L = LS.find(S.getKey()); | |
373 std::string Truncated = truncateStringMiddle(S.getKey(), 28); | |
374 uint32_t J = cantFail(ST2.getIDForString(S.getKey())); | |
375 if (L == LS.end()) { | |
376 D.printExplicit(Truncated, DiffResult::DIFFERENT, "(not present)", J); | |
377 continue; | |
378 } | |
379 | |
380 uint32_t I = cantFail(ST1.getIDForString(L->getKey())); | |
381 D.print<EquivalentDiffProvider>(Truncated, I, J); | |
382 } | |
383 return Error::success(); | |
384 } | |
385 | |
386 Error DiffStyle::diffFreePageMap() { return Error::success(); } | |
387 | |
388 Error DiffStyle::diffInfoStream() { | |
389 DiffPrinter D(2, "PDB Stream", 22, 40, opts::diff::PrintResultColumn, | |
390 opts::diff::PrintValueColumns, outs()); | |
391 D.printExplicit("File", DiffResult::UNSPECIFIED, | |
392 truncateStringFront(File1.getFilePath(), 38), | |
393 truncateStringFront(File2.getFilePath(), 38)); | |
394 | |
395 auto ExpectedInfo1 = File1.getPDBInfoStream(); | |
396 auto ExpectedInfo2 = File2.getPDBInfoStream(); | |
397 | |
398 bool Has1 = !!ExpectedInfo1; | |
399 bool Has2 = !!ExpectedInfo2; | |
400 if (!(Has1 && Has2)) { | |
401 std::string L = Has1 ? "(present)" : "(not present)"; | |
402 std::string R = Has2 ? "(present)" : "(not present)"; | |
403 D.print("Stream", L, R); | |
404 | |
405 consumeError(ExpectedInfo1.takeError()); | |
406 consumeError(ExpectedInfo2.takeError()); | |
407 return Error::success(); | |
408 } | |
409 | |
410 auto &IS1 = *ExpectedInfo1; | |
411 auto &IS2 = *ExpectedInfo2; | |
412 D.print("Stream Size", IS1.getStreamSize(), IS2.getStreamSize()); | |
413 D.print("Age", IS1.getAge(), IS2.getAge()); | |
414 D.print("Guid", IS1.getGuid(), IS2.getGuid()); | |
415 D.print("Signature", IS1.getSignature(), IS2.getSignature()); | |
416 D.print("Version", IS1.getVersion(), IS2.getVersion()); | |
417 D.diffUnorderedArray("Feature", IS1.getFeatureSignatures(), | |
418 IS2.getFeatureSignatures()); | |
419 D.print("Named Stream Size", IS1.getNamedStreamMapByteSize(), | |
420 IS2.getNamedStreamMapByteSize()); | |
421 StringMap<uint32_t> NSL = IS1.getNamedStreams().getStringMap(); | |
422 StringMap<uint32_t> NSR = IS2.getNamedStreams().getStringMap(); | |
423 D.diffUnorderedMap<EquivalentDiffProvider>("Named Stream", NSL, NSR); | |
424 return Error::success(); | |
425 } | |
426 | |
427 typedef std::pair<uint32_t, DbiModuleDescriptor> IndexedModuleDescriptor; | |
428 typedef std::vector<IndexedModuleDescriptor> IndexedModuleDescriptorList; | |
429 | |
430 static IndexedModuleDescriptorList | |
431 getModuleDescriptors(const DbiModuleList &ML) { | |
432 IndexedModuleDescriptorList List; | |
433 List.reserve(ML.getModuleCount()); | |
434 for (uint32_t I = 0; I < ML.getModuleCount(); ++I) | |
435 List.emplace_back(I, ML.getModuleDescriptor(I)); | |
436 return List; | |
437 } | |
438 | |
439 static IndexedModuleDescriptorList::iterator | |
440 findOverrideEquivalentModule(uint32_t Modi, | |
441 IndexedModuleDescriptorList &OtherList) { | |
442 auto &EqMap = opts::diff::Equivalences; | |
443 | |
444 auto Iter = EqMap.find(Modi); | |
445 if (Iter == EqMap.end()) | |
446 return OtherList.end(); | |
447 | |
448 uint32_t EqValue = Iter->second; | |
449 | |
450 return llvm::find_if(OtherList, | |
451 [EqValue](const IndexedModuleDescriptor &Desc) { | |
452 return Desc.first == EqValue; | |
453 }); | |
454 } | |
455 | |
456 static IndexedModuleDescriptorList::iterator | |
457 findEquivalentModule(const IndexedModuleDescriptor &Item, | |
458 IndexedModuleDescriptorList &OtherList, bool ItemIsRight) { | |
459 | |
460 if (!ItemIsRight) { | |
461 uint32_t Modi = Item.first; | |
462 auto OverrideIter = findOverrideEquivalentModule(Modi, OtherList); | |
463 if (OverrideIter != OtherList.end()) | |
464 return OverrideIter; | |
465 } | |
466 | |
467 BinaryPathProvider PathProvider(28); | |
468 | |
469 auto Iter = OtherList.begin(); | |
470 auto End = OtherList.end(); | |
471 for (; Iter != End; ++Iter) { | |
472 const IndexedModuleDescriptor *Left = &Item; | |
473 const IndexedModuleDescriptor *Right = &*Iter; | |
474 if (ItemIsRight) | |
475 std::swap(Left, Right); | |
476 DiffResult Result = PathProvider.compare(Left->second.getModuleName(), | |
477 Right->second.getModuleName()); | |
478 if (Result == DiffResult::EQUIVALENT || Result == DiffResult::IDENTICAL) | |
479 return Iter; | |
480 } | |
481 return OtherList.end(); | |
482 } | |
483 | |
484 static void diffOneModule(DiffPrinter &D, const IndexedModuleDescriptor &Item, | |
485 IndexedModuleDescriptorList &Other, | |
486 bool ItemIsRight) { | |
487 StreamPurposeProvider HeaderProvider(70); | |
488 StreamInfo Info = StreamInfo::createModuleStream( | |
489 Item.second.getModuleName(), Item.second.getModuleStreamIndex(), | |
490 Item.first); | |
491 D.printFullRow(HeaderProvider.format(Info, ItemIsRight)); | |
492 | |
493 const auto *L = &Item; | |
494 | |
495 auto Iter = findEquivalentModule(Item, Other, ItemIsRight); | |
496 if (Iter == Other.end()) { | |
497 // We didn't find this module at all on the other side. Just print one row | |
498 // and continue. | |
499 if (ItemIsRight) | |
500 D.print<ModiProvider>("- Modi", None, Item.first); | |
501 else | |
502 D.print<ModiProvider>("- Modi", Item.first, None); | |
503 return; | |
504 } | |
505 | |
506 // We did find this module. Go through and compare each field. | |
507 const auto *R = &*Iter; | |
508 if (ItemIsRight) | |
509 std::swap(L, R); | |
510 | |
511 BinaryPathProvider PathProvider(28); | |
512 D.print<ModiProvider>("- Modi", L->first, R->first); | |
513 D.print<BinaryPathProvider>("- Obj File Name", L->second.getObjFileName(), | |
514 R->second.getObjFileName(), PathProvider); | |
515 D.print<StreamNumberProvider>("- Debug Stream", | |
516 L->second.getModuleStreamIndex(), | |
517 R->second.getModuleStreamIndex()); | |
518 D.print("- C11 Byte Size", L->second.getC11LineInfoByteSize(), | |
519 R->second.getC11LineInfoByteSize()); | |
520 D.print("- C13 Byte Size", L->second.getC13LineInfoByteSize(), | |
521 R->second.getC13LineInfoByteSize()); | |
522 D.print("- # of files", L->second.getNumberOfFiles(), | |
523 R->second.getNumberOfFiles()); | |
524 D.print("- Pdb File Path Index", L->second.getPdbFilePathNameIndex(), | |
525 R->second.getPdbFilePathNameIndex()); | |
526 D.print("- Source File Name Index", L->second.getSourceFileNameIndex(), | |
527 R->second.getSourceFileNameIndex()); | |
528 D.print("- Symbol Byte Size", L->second.getSymbolDebugInfoByteSize(), | |
529 R->second.getSymbolDebugInfoByteSize()); | |
530 Other.erase(Iter); | |
531 } | |
532 | |
533 Error DiffStyle::diffDbiStream() { | |
534 DiffPrinter D(2, "DBI Stream", 40, 30, opts::diff::PrintResultColumn, | |
535 opts::diff::PrintValueColumns, outs()); | |
536 D.printExplicit("File", DiffResult::UNSPECIFIED, | |
537 truncateStringFront(File1.getFilePath(), 28), | |
538 truncateStringFront(File2.getFilePath(), 28)); | |
539 | |
540 auto ExpectedDbi1 = File1.getPDBDbiStream(); | |
541 auto ExpectedDbi2 = File2.getPDBDbiStream(); | |
542 | |
543 bool Has1 = !!ExpectedDbi1; | |
544 bool Has2 = !!ExpectedDbi2; | |
545 if (!(Has1 && Has2)) { | |
546 std::string L = Has1 ? "(present)" : "(not present)"; | |
547 std::string R = Has2 ? "(present)" : "(not present)"; | |
548 D.print("Stream", L, R); | |
549 | |
550 consumeError(ExpectedDbi1.takeError()); | |
551 consumeError(ExpectedDbi2.takeError()); | |
552 return Error::success(); | |
553 } | |
554 | |
555 auto &DL = *ExpectedDbi1; | |
556 auto &DR = *ExpectedDbi2; | |
557 | |
558 D.print("Dbi Version", (uint32_t)DL.getDbiVersion(), | |
559 (uint32_t)DR.getDbiVersion()); | |
560 D.print("Age", DL.getAge(), DR.getAge()); | |
561 D.print("Machine", (uint16_t)DL.getMachineType(), | |
562 (uint16_t)DR.getMachineType()); | |
563 D.print("Flags", DL.getFlags(), DR.getFlags()); | |
564 D.print("Build Major", DL.getBuildMajorVersion(), DR.getBuildMajorVersion()); | |
565 D.print("Build Minor", DL.getBuildMinorVersion(), DR.getBuildMinorVersion()); | |
566 D.print("Build Number", DL.getBuildNumber(), DR.getBuildNumber()); | |
567 D.print("PDB DLL Version", DL.getPdbDllVersion(), DR.getPdbDllVersion()); | |
568 D.print("PDB DLL RBLD", DL.getPdbDllRbld(), DR.getPdbDllRbld()); | |
569 D.print<StreamNumberProvider>("DBG (FPO)", | |
570 DL.getDebugStreamIndex(DbgHeaderType::FPO), | |
571 DR.getDebugStreamIndex(DbgHeaderType::FPO)); | |
572 D.print<StreamNumberProvider>( | |
573 "DBG (Exception)", DL.getDebugStreamIndex(DbgHeaderType::Exception), | |
574 DR.getDebugStreamIndex(DbgHeaderType::Exception)); | |
575 D.print<StreamNumberProvider>("DBG (Fixup)", | |
576 DL.getDebugStreamIndex(DbgHeaderType::Fixup), | |
577 DR.getDebugStreamIndex(DbgHeaderType::Fixup)); | |
578 D.print<StreamNumberProvider>( | |
579 "DBG (OmapToSrc)", DL.getDebugStreamIndex(DbgHeaderType::OmapToSrc), | |
580 DR.getDebugStreamIndex(DbgHeaderType::OmapToSrc)); | |
581 D.print<StreamNumberProvider>( | |
582 "DBG (OmapFromSrc)", DL.getDebugStreamIndex(DbgHeaderType::OmapFromSrc), | |
583 DR.getDebugStreamIndex(DbgHeaderType::OmapFromSrc)); | |
584 D.print<StreamNumberProvider>( | |
585 "DBG (SectionHdr)", DL.getDebugStreamIndex(DbgHeaderType::SectionHdr), | |
586 DR.getDebugStreamIndex(DbgHeaderType::SectionHdr)); | |
587 D.print<StreamNumberProvider>( | |
588 "DBG (TokenRidMap)", DL.getDebugStreamIndex(DbgHeaderType::TokenRidMap), | |
589 DR.getDebugStreamIndex(DbgHeaderType::TokenRidMap)); | |
590 D.print<StreamNumberProvider>("DBG (Xdata)", | |
591 DL.getDebugStreamIndex(DbgHeaderType::Xdata), | |
592 DR.getDebugStreamIndex(DbgHeaderType::Xdata)); | |
593 D.print<StreamNumberProvider>("DBG (Pdata)", | |
594 DL.getDebugStreamIndex(DbgHeaderType::Pdata), | |
595 DR.getDebugStreamIndex(DbgHeaderType::Pdata)); | |
596 D.print<StreamNumberProvider>("DBG (NewFPO)", | |
597 DL.getDebugStreamIndex(DbgHeaderType::NewFPO), | |
598 DR.getDebugStreamIndex(DbgHeaderType::NewFPO)); | |
599 D.print<StreamNumberProvider>( | |
600 "DBG (SectionHdrOrig)", | |
601 DL.getDebugStreamIndex(DbgHeaderType::SectionHdrOrig), | |
602 DR.getDebugStreamIndex(DbgHeaderType::SectionHdrOrig)); | |
603 D.print<StreamNumberProvider>("Globals Stream", | |
604 DL.getGlobalSymbolStreamIndex(), | |
605 DR.getGlobalSymbolStreamIndex()); | |
606 D.print<StreamNumberProvider>("Publics Stream", | |
607 DL.getPublicSymbolStreamIndex(), | |
608 DR.getPublicSymbolStreamIndex()); | |
609 D.print<StreamNumberProvider>("Symbol Records", DL.getSymRecordStreamIndex(), | |
610 DR.getSymRecordStreamIndex()); | |
611 D.print("Has CTypes", DL.hasCTypes(), DR.hasCTypes()); | |
612 D.print("Is Incrementally Linked", DL.isIncrementallyLinked(), | |
613 DR.isIncrementallyLinked()); | |
614 D.print("Is Stripped", DL.isStripped(), DR.isStripped()); | |
615 const DbiModuleList &ML = DL.modules(); | |
616 const DbiModuleList &MR = DR.modules(); | |
617 D.print("Module Count", ML.getModuleCount(), MR.getModuleCount()); | |
618 D.print("Source File Count", ML.getSourceFileCount(), | |
619 MR.getSourceFileCount()); | |
620 auto MDL = getModuleDescriptors(ML); | |
621 auto MDR = getModuleDescriptors(MR); | |
622 // Scan all module descriptors from the left, and look for corresponding | |
623 // module descriptors on the right. | |
624 for (const auto &L : MDL) | |
625 diffOneModule(D, L, MDR, false); | |
626 | |
627 for (const auto &R : MDR) | |
628 diffOneModule(D, R, MDL, true); | |
629 | |
630 return Error::success(); | |
631 } | |
632 | |
633 Error DiffStyle::diffSectionContribs() { return Error::success(); } | |
634 | |
635 Error DiffStyle::diffSectionMap() { return Error::success(); } | |
636 | |
637 Error DiffStyle::diffFpoStream() { return Error::success(); } | |
638 | |
639 Error DiffStyle::diffTpiStream(int Index) { return Error::success(); } | |
640 | |
641 Error DiffStyle::diffModuleInfoStream(int Index) { return Error::success(); } | |
642 | |
643 Error DiffStyle::diffPublics() { return Error::success(); } | |
644 | |
645 Error DiffStyle::diffGlobals() { return Error::success(); } |