xref: /llvm-project/llvm/unittests/DebugInfo/LogicalView/CodeViewReaderTest.cpp (revision 37e48e4a7360a6faf1b157e843160d9e65223890)
1 //===- llvm/unittest/DebugInfo/LogicalView/CodeViewReaderTest.cpp ---------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/DebugInfo/LogicalView/Core/LVCompare.h"
10 #include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
11 #include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
12 #include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
13 #include "llvm/DebugInfo/LogicalView/Core/LVType.h"
14 #include "llvm/DebugInfo/LogicalView/LVReaderHandler.h"
15 #include "llvm/MC/TargetRegistry.h"
16 #include "llvm/Support/COM.h"
17 #include "llvm/Support/InitLLVM.h"
18 #include "llvm/Support/ScopedPrinter.h"
19 #include "llvm/Support/TargetSelect.h"
20 #include "llvm/Support/ToolOutputFile.h"
21 #include "llvm/Testing/Support/Error.h"
22 
23 #include "gtest/gtest.h"
24 
25 using namespace llvm;
26 using namespace llvm::logicalview;
27 
28 extern const char *TestMainArgv0;
29 
30 namespace {
31 
32 const char *CodeViewClang = "test-codeview-clang.o";
33 const char *CodeViewMsvc = "test-codeview-msvc.o";
34 const char *CodeViewMsvcLib = "test-codeview-msvc.lib";
35 const char *CodeViewMsvcLibContentName =
36     "test-codeview-msvc.lib(test-codeview-msvc.o)";
37 const char *CodeViewPdbMsvc = "test-codeview-pdb-msvc.o";
38 
39 // Helper function to get the first scope child from the given parent.
40 LVScope *getFirstScopeChild(LVScope *Parent) {
41   EXPECT_NE(Parent, nullptr);
42   const LVScopes *Scopes = Parent->getScopes();
43   EXPECT_NE(Scopes, nullptr);
44   EXPECT_EQ(Scopes->size(), 1u);
45 
46   LVScopes::const_iterator Iter = Scopes->begin();
47   LVScope *Child = *Iter;
48   EXPECT_NE(Child, nullptr);
49   return Child;
50 }
51 
52 // Helper function to create a reader.
53 std::unique_ptr<LVReader> createReader(LVReaderHandler &ReaderHandler,
54                                        SmallString<128> &InputsDir,
55                                        StringRef Filename) {
56   SmallString<128> ObjectName(InputsDir);
57   llvm::sys::path::append(ObjectName, Filename);
58 
59   Expected<std::unique_ptr<LVReader>> ReaderOrErr =
60       ReaderHandler.createReader(std::string(ObjectName));
61   EXPECT_THAT_EXPECTED(ReaderOrErr, Succeeded());
62   std::unique_ptr<LVReader> Reader = std::move(*ReaderOrErr);
63   EXPECT_NE(Reader, nullptr);
64   return Reader;
65 }
66 
67 // Check the logical elements basic properties (Clang - Codeview).
68 void checkElementPropertiesClangCodeview(LVReader *Reader) {
69   LVScopeRoot *Root = Reader->getScopesRoot();
70   LVScopeCompileUnit *CompileUnit =
71       static_cast<LVScopeCompileUnit *>(getFirstScopeChild(Root));
72   LVScopeFunction *Function =
73       static_cast<LVScopeFunction *>(getFirstScopeChild(CompileUnit));
74 
75   EXPECT_EQ(Root->getFileFormatName(), "COFF-x86-64");
76   EXPECT_EQ(Root->getName(), CodeViewClang);
77 
78   EXPECT_EQ(CompileUnit->getBaseAddress(), 0u);
79   EXPECT_TRUE(CompileUnit->getProducer().starts_with("clang"));
80   EXPECT_EQ(CompileUnit->getName(), "test.cpp");
81 
82   EXPECT_EQ(Function->lineCount(), 16u);
83   EXPECT_EQ(Function->scopeCount(), 1u);
84   EXPECT_EQ(Function->symbolCount(), 3u);
85   EXPECT_EQ(Function->typeCount(), 1u);
86   EXPECT_EQ(Function->rangeCount(), 1u);
87 
88   const LVLocations *Ranges = Function->getRanges();
89   ASSERT_NE(Ranges, nullptr);
90   ASSERT_EQ(Ranges->size(), 1u);
91   LVLocations::const_iterator IterLocation = Ranges->begin();
92   LVLocation *Location = (*IterLocation);
93   EXPECT_STREQ(Location->getIntervalInfo().c_str(),
94                "{Range} Lines 2:9 [0x0000000000:0x0000000046]");
95 
96   LVRange RangeList;
97   Function->getRanges(RangeList);
98 
99   const LVRangeEntries &RangeEntries = RangeList.getEntries();
100   ASSERT_EQ(RangeEntries.size(), 2u);
101   LVRangeEntries::const_iterator IterRanges = RangeEntries.cbegin();
102   LVRangeEntry RangeEntry = *IterRanges;
103   EXPECT_EQ(RangeEntry.lower(), 0u);
104   EXPECT_EQ(RangeEntry.upper(), 0x46u);
105   EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);
106   EXPECT_EQ(RangeEntry.scope()->getName(), "foo");
107   EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);
108 
109   ++IterRanges;
110   RangeEntry = *IterRanges;
111   EXPECT_EQ(RangeEntry.lower(), 0x21u);
112   EXPECT_EQ(RangeEntry.upper(), 0x35u);
113   EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);
114   EXPECT_EQ(RangeEntry.scope()->getName(), "foo::?");
115   EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);
116 
117   const LVPublicNames &PublicNames = CompileUnit->getPublicNames();
118   ASSERT_EQ(PublicNames.size(), 1u);
119   LVPublicNames::const_iterator IterNames = PublicNames.cbegin();
120   LVScope *Foo = (*IterNames).first;
121   EXPECT_EQ(Foo->getName(), "foo");
122   EXPECT_EQ(Foo->getLineNumber(), 0u);
123   LVNameInfo NameInfo = (*IterNames).second;
124   EXPECT_EQ(NameInfo.first, 0u);
125   EXPECT_EQ(NameInfo.second, 0x46u);
126 
127   // Lines (debug and assembler) for 'foo'.
128   const LVLines *Lines = Foo->getLines();
129   ASSERT_NE(Lines, nullptr);
130   EXPECT_EQ(Lines->size(), 0x10u);
131 }
132 
133 // Check the logical elements basic properties (MSVC - Codeview).
134 void checkElementPropertiesMsvcCodeview(LVReader *Reader) {
135   LVScopeRoot *Root = Reader->getScopesRoot();
136   LVScopeCompileUnit *CompileUnit =
137       static_cast<LVScopeCompileUnit *>(getFirstScopeChild(Root));
138   LVScopeFunction *Function =
139       static_cast<LVScopeFunction *>(getFirstScopeChild(CompileUnit));
140 
141   EXPECT_EQ(Root->getFileFormatName(), "COFF-x86-64");
142   EXPECT_EQ(Root->getName(), CodeViewMsvc);
143 
144   EXPECT_EQ(CompileUnit->getBaseAddress(), 0u);
145   EXPECT_TRUE(CompileUnit->getProducer().starts_with("Microsoft"));
146   EXPECT_EQ(CompileUnit->getName(), "test.cpp");
147 
148   EXPECT_EQ(Function->lineCount(), 14u);
149   EXPECT_EQ(Function->scopeCount(), 1u);
150   EXPECT_EQ(Function->symbolCount(), 3u);
151   EXPECT_EQ(Function->typeCount(), 0u);
152   EXPECT_EQ(Function->rangeCount(), 1u);
153 
154   const LVLocations *Ranges = Function->getRanges();
155   ASSERT_NE(Ranges, nullptr);
156   ASSERT_EQ(Ranges->size(), 1u);
157   LVLocations::const_iterator IterLocation = Ranges->begin();
158   LVLocation *Location = (*IterLocation);
159   EXPECT_STREQ(Location->getIntervalInfo().c_str(),
160                "{Range} Lines 2:9 [0x0000000000:0x0000000031]");
161 
162   LVRange RangeList;
163   Function->getRanges(RangeList);
164 
165   const LVRangeEntries &RangeEntries = RangeList.getEntries();
166   ASSERT_EQ(RangeEntries.size(), 2u);
167   LVRangeEntries::const_iterator IterRanges = RangeEntries.cbegin();
168   LVRangeEntry RangeEntry = *IterRanges;
169   EXPECT_EQ(RangeEntry.lower(), 0u);
170   EXPECT_EQ(RangeEntry.upper(), 0x31u);
171   EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);
172   EXPECT_EQ(RangeEntry.scope()->getName(), "foo");
173   EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);
174 
175   ++IterRanges;
176   RangeEntry = *IterRanges;
177   EXPECT_EQ(RangeEntry.lower(), 0x1bu);
178   EXPECT_EQ(RangeEntry.upper(), 0x28u);
179   EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);
180   EXPECT_EQ(RangeEntry.scope()->getName(), "foo::?");
181   EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);
182 
183   const LVPublicNames &PublicNames = CompileUnit->getPublicNames();
184   ASSERT_EQ(PublicNames.size(), 1u);
185   LVPublicNames::const_iterator IterNames = PublicNames.cbegin();
186   LVScope *Foo = (*IterNames).first;
187   EXPECT_EQ(Foo->getName(), "foo");
188   EXPECT_EQ(Foo->getLineNumber(), 0u);
189   LVNameInfo NameInfo = (*IterNames).second;
190   EXPECT_EQ(NameInfo.first, 0u);
191   EXPECT_EQ(NameInfo.second, 0x31u);
192 
193   // Lines (debug and assembler) for 'foo'.
194   const LVLines *Lines = Foo->getLines();
195   ASSERT_NE(Lines, nullptr);
196   EXPECT_EQ(Lines->size(), 0x0eu);
197 }
198 
199 // Check the logical elements basic properties (MSVC library - Codeview).
200 void checkElementPropertiesMsvcLibraryCodeview(LVReader *Reader) {
201   LVScopeRoot *Root = Reader->getScopesRoot();
202   LVScopeCompileUnit *CompileUnit =
203       static_cast<LVScopeCompileUnit *>(getFirstScopeChild(Root));
204   LVScopeFunction *Function =
205       static_cast<LVScopeFunction *>(getFirstScopeChild(CompileUnit));
206 
207   EXPECT_EQ(Root->getFileFormatName(), "COFF-x86-64");
208   EXPECT_EQ(Root->getName(), CodeViewMsvcLibContentName);
209 
210   EXPECT_EQ(CompileUnit->getBaseAddress(), 0u);
211   EXPECT_TRUE(CompileUnit->getProducer().starts_with("Microsoft"));
212   EXPECT_EQ(CompileUnit->getName(), "test.cpp");
213 
214   EXPECT_EQ(Function->lineCount(), 14u);
215   EXPECT_EQ(Function->scopeCount(), 1u);
216   EXPECT_EQ(Function->symbolCount(), 3u);
217   EXPECT_EQ(Function->typeCount(), 0u);
218   EXPECT_EQ(Function->rangeCount(), 1u);
219 
220   const LVLocations *Ranges = Function->getRanges();
221   ASSERT_NE(Ranges, nullptr);
222   ASSERT_EQ(Ranges->size(), 1u);
223   LVLocations::const_iterator IterLocation = Ranges->begin();
224   LVLocation *Location = (*IterLocation);
225   EXPECT_STREQ(Location->getIntervalInfo().c_str(),
226                "{Range} Lines 2:9 [0x0000000000:0x0000000031]");
227 
228   LVRange RangeList;
229   Function->getRanges(RangeList);
230 
231   const LVRangeEntries &RangeEntries = RangeList.getEntries();
232   ASSERT_EQ(RangeEntries.size(), 2u);
233   LVRangeEntries::const_iterator IterRanges = RangeEntries.cbegin();
234   LVRangeEntry RangeEntry = *IterRanges;
235   EXPECT_EQ(RangeEntry.lower(), 0u);
236   EXPECT_EQ(RangeEntry.upper(), 0x31u);
237   EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);
238   EXPECT_EQ(RangeEntry.scope()->getName(), "foo");
239   EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);
240 
241   ++IterRanges;
242   RangeEntry = *IterRanges;
243   EXPECT_EQ(RangeEntry.lower(), 0x1bu);
244   EXPECT_EQ(RangeEntry.upper(), 0x28u);
245   EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);
246   EXPECT_EQ(RangeEntry.scope()->getName(), "foo::?");
247   EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);
248 
249   const LVPublicNames &PublicNames = CompileUnit->getPublicNames();
250   ASSERT_EQ(PublicNames.size(), 1u);
251   LVPublicNames::const_iterator IterNames = PublicNames.cbegin();
252   LVScope *Foo = (*IterNames).first;
253   EXPECT_EQ(Foo->getName(), "foo");
254   EXPECT_EQ(Foo->getLineNumber(), 0u);
255   LVNameInfo NameInfo = (*IterNames).second;
256   EXPECT_EQ(NameInfo.first, 0u);
257   EXPECT_EQ(NameInfo.second, 0x31u);
258 
259   // Lines (debug and assembler) for 'foo'.
260   const LVLines *Lines = Foo->getLines();
261   ASSERT_NE(Lines, nullptr);
262   EXPECT_EQ(Lines->size(), 0x0eu);
263 }
264 
265 // Check the logical elements basic properties (MSVC - PDB).
266 void checkElementPropertiesMsvcCodeviewPdb(LVReader *Reader) {
267   LVScopeRoot *Root = Reader->getScopesRoot();
268   LVScopeCompileUnit *CompileUnit =
269       static_cast<LVScopeCompileUnit *>(getFirstScopeChild(Root));
270   LVScopeFunction *Function =
271       static_cast<LVScopeFunction *>(getFirstScopeChild(CompileUnit));
272 
273   EXPECT_EQ(Root->getFileFormatName(), "COFF-x86-64");
274   EXPECT_EQ(Root->getName(), CodeViewPdbMsvc);
275 
276   EXPECT_EQ(CompileUnit->getBaseAddress(), 0u);
277   EXPECT_TRUE(CompileUnit->getProducer().starts_with("Microsoft"));
278   EXPECT_EQ(CompileUnit->getName(), "test.cpp");
279 
280   EXPECT_EQ(Function->lineCount(), 14u);
281   EXPECT_EQ(Function->scopeCount(), 1u);
282   EXPECT_EQ(Function->symbolCount(), 3u);
283   EXPECT_EQ(Function->typeCount(), 0u);
284   EXPECT_EQ(Function->rangeCount(), 1u);
285 
286   const LVLocations *Ranges = Function->getRanges();
287   ASSERT_NE(Ranges, nullptr);
288   ASSERT_EQ(Ranges->size(), 1u);
289   LVLocations::const_iterator IterLocation = Ranges->begin();
290   LVLocation *Location = (*IterLocation);
291   EXPECT_STREQ(Location->getIntervalInfo().c_str(),
292                "{Range} Lines 2:9 [0x0000000000:0x0000000031]");
293 
294   LVRange RangeList;
295   Function->getRanges(RangeList);
296 
297   const LVRangeEntries &RangeEntries = RangeList.getEntries();
298   ASSERT_EQ(RangeEntries.size(), 2u);
299   LVRangeEntries::const_iterator IterRanges = RangeEntries.cbegin();
300   LVRangeEntry RangeEntry = *IterRanges;
301   EXPECT_EQ(RangeEntry.lower(), 0u);
302   EXPECT_EQ(RangeEntry.upper(), 0x31u);
303   EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);
304   EXPECT_EQ(RangeEntry.scope()->getName(), "foo");
305   EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);
306 
307   ++IterRanges;
308   RangeEntry = *IterRanges;
309   EXPECT_EQ(RangeEntry.lower(), 0x1bu);
310   EXPECT_EQ(RangeEntry.upper(), 0x28u);
311   EXPECT_EQ(RangeEntry.scope()->getLineNumber(), 0u);
312   EXPECT_EQ(RangeEntry.scope()->getName(), "foo::?");
313   EXPECT_EQ(RangeEntry.scope()->getOffset(), 0u);
314 
315   const LVPublicNames &PublicNames = CompileUnit->getPublicNames();
316   ASSERT_EQ(PublicNames.size(), 1u);
317   LVPublicNames::const_iterator IterNames = PublicNames.cbegin();
318   LVScope *Foo = (*IterNames).first;
319   EXPECT_EQ(Foo->getName(), "foo");
320   EXPECT_EQ(Foo->getLineNumber(), 0u);
321   LVNameInfo NameInfo = (*IterNames).second;
322   EXPECT_EQ(NameInfo.first, 0u);
323   EXPECT_EQ(NameInfo.second, 0x31u);
324 
325   // Lines (debug and assembler) for 'foo'.
326   const LVLines *Lines = Foo->getLines();
327   ASSERT_NE(Lines, nullptr);
328   EXPECT_EQ(Lines->size(), 0x0eu);
329 }
330 
331 struct SelectionInfo {
332   const char *Name;
333   LVElementGetFunction Function;
334 };
335 
336 // Check the logical elements selection.
337 void checkElementSelection(LVReader *Reader, std::vector<SelectionInfo> &Data,
338                            size_t Size) {
339   LVScopeRoot *Root = Reader->getScopesRoot();
340   LVScopeCompileUnit *CompileUnit =
341       static_cast<LVScopeCompileUnit *>(getFirstScopeChild(Root));
342 
343   // Get the matched elements.
344   LVElements MatchedElements = CompileUnit->getMatchedElements();
345   std::map<StringRef, LVElement *> MapElements;
346   for (LVElement *Element : MatchedElements)
347     MapElements[Element->getName()] = Element;
348   ASSERT_EQ(MapElements.size(), Size);
349 
350   std::map<StringRef, LVElement *>::iterator Iter = MapElements.begin();
351   for (const SelectionInfo &Entry : Data) {
352     // Get matched element.
353     EXPECT_NE(Iter, MapElements.end());
354     LVElement *Element = Iter->second;
355     ASSERT_NE(Element, nullptr);
356     EXPECT_NE(Element->getName().find(Entry.Name), StringRef::npos);
357     EXPECT_EQ((Element->*Entry.Function)(), 1u);
358     ++Iter;
359   }
360 
361   // Get the parents for the matched elements.
362   LVScopes MatchedScopes = CompileUnit->getMatchedScopes();
363   std::set<StringRef> SetScopes;
364   for (LVScope *Scope : MatchedScopes)
365     SetScopes.insert(Scope->getName());
366   ASSERT_EQ(SetScopes.size(), 3u);
367 
368   // Parents of selected elements.
369   std::set<StringRef>::iterator IterScope;
370   IterScope = SetScopes.find("foo");
371   EXPECT_NE(IterScope, SetScopes.end());
372   IterScope = SetScopes.find("foo::?");
373   EXPECT_NE(IterScope, SetScopes.end());
374   IterScope = SetScopes.find("test.cpp");
375   EXPECT_NE(IterScope, SetScopes.end());
376 }
377 
378 // Check the logical elements comparison.
379 void checkElementComparison(LVReader *Reference, LVReader *Target) {
380   LVCompare Compare(nulls());
381   Error Err = Compare.execute(Reference, Target);
382   ASSERT_THAT_ERROR(std::move(Err), Succeeded());
383 
384   // Get comparison table.
385   LVPassTable PassTable = Compare.getPassTable();
386   ASSERT_EQ(PassTable.size(), 2u);
387 
388   LVReader *Reader;
389   LVElement *Element;
390   LVComparePass Pass;
391 
392   // Reference: Missing TypeDefinition 'INTEGER'
393   std::tie(Reader, Element, Pass) = PassTable[0];
394   ASSERT_NE(Reader, nullptr);
395   ASSERT_NE(Element, nullptr);
396   EXPECT_EQ(Reader, Reference);
397   EXPECT_EQ(Element->getLevel(), 3u);
398   EXPECT_EQ(Element->getLineNumber(), 0u);
399   EXPECT_EQ(Element->getName(), "INTEGER");
400   EXPECT_EQ(Pass, LVComparePass::Missing);
401 
402   // Target: Added TypeDefinition 'INTEGER'
403   std::tie(Reader, Element, Pass) = PassTable[1];
404   ASSERT_NE(Reader, nullptr);
405   ASSERT_NE(Element, nullptr);
406   EXPECT_EQ(Reader, Target);
407   EXPECT_EQ(Element->getLevel(), 4u);
408   EXPECT_EQ(Element->getLineNumber(), 0u);
409   EXPECT_EQ(Element->getName(), "INTEGER");
410   EXPECT_EQ(Pass, LVComparePass::Added);
411 }
412 
413 // Logical elements properties.
414 void elementProperties(SmallString<128> &InputsDir) {
415   // Reader options.
416   LVOptions ReaderOptions;
417   ReaderOptions.setAttributeOffset();
418   ReaderOptions.setAttributeFormat();
419   ReaderOptions.setAttributeFilename();
420   ReaderOptions.setAttributeProducer();
421   ReaderOptions.setAttributePublics();
422   ReaderOptions.setAttributeRange();
423   ReaderOptions.setAttributeLocation();
424   ReaderOptions.setPrintAll();
425   ReaderOptions.resolveDependencies();
426 
427   std::vector<std::string> Objects;
428   ScopedPrinter W(outs());
429   LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);
430 
431   // Check logical elements properties.
432   {
433     std::unique_ptr<LVReader> Reader =
434         createReader(ReaderHandler, InputsDir, CodeViewClang);
435     checkElementPropertiesClangCodeview(Reader.get());
436   }
437   {
438     std::unique_ptr<LVReader> Reader =
439         createReader(ReaderHandler, InputsDir, CodeViewMsvc);
440     checkElementPropertiesMsvcCodeview(Reader.get());
441   }
442   {
443     std::unique_ptr<LVReader> Reader =
444         createReader(ReaderHandler, InputsDir, CodeViewMsvcLib);
445     checkElementPropertiesMsvcLibraryCodeview(Reader.get());
446   }
447   {
448     std::unique_ptr<LVReader> Reader =
449         createReader(ReaderHandler, InputsDir, CodeViewPdbMsvc);
450     checkElementPropertiesMsvcCodeviewPdb(Reader.get());
451   }
452 }
453 
454 // Logical elements selection.
455 void elementSelection(SmallString<128> &InputsDir) {
456   // Reader options.
457   LVOptions ReaderOptions;
458   ReaderOptions.setAttributeOffset();
459   ReaderOptions.setPrintAll();
460 
461   ReaderOptions.setSelectIgnoreCase();
462   ReaderOptions.setSelectUseRegex();
463 
464   ReaderOptions.setReportList(); // Matched elements.
465   ReaderOptions.setReportView(); // Parents for matched elements.
466 
467   // Add patterns.
468   ReaderOptions.Select.Generic.insert("foo");
469   ReaderOptions.Select.Generic.insert("movl[ \t]?%");
470   ReaderOptions.Select.Generic.insert("INT[a-z]*");
471   ReaderOptions.Select.Generic.insert("CONSTANT");
472 
473   ReaderOptions.resolveDependencies();
474 
475   std::vector<std::string> Objects;
476   ScopedPrinter W(outs());
477   LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);
478 
479   // Check logical elements selection.
480   {
481     std::vector<SelectionInfo> DataClang = {
482         {"* const int", &LVElement::getIsType},
483         {"CONSTANT", &LVElement::getIsSymbol},
484         {"INTEGER", &LVElement::getIsType},
485         {"INTPTR", &LVElement::getIsType},
486         {"ParamPtr", &LVElement::getIsSymbol},
487         {"const int", &LVElement::getIsType},
488         {"foo", &LVElement::getIsScope},
489         {"foo::?", &LVElement::getIsScope},
490         {"int", &LVElement::getIsType},
491         {"movl", &LVElement::getIsLine},
492         {"movl", &LVElement::getIsLine}};
493     std::unique_ptr<LVReader> Reader =
494         createReader(ReaderHandler, InputsDir, CodeViewClang);
495     checkElementSelection(Reader.get(), DataClang, DataClang.size());
496   }
497   {
498     std::vector<SelectionInfo> DataMsvc = {
499         {"* const int", &LVElement::getIsType},
500         {"CONSTANT", &LVElement::getIsSymbol},
501         {"INTEGER", &LVElement::getIsType},
502         {"INTPTR", &LVElement::getIsType},
503         {"ParamPtr", &LVElement::getIsSymbol},
504         {"const int", &LVElement::getIsType},
505         {"foo", &LVElement::getIsScope},
506         {"foo::?", &LVElement::getIsScope},
507         {"int", &LVElement::getIsType},
508         {"movl", &LVElement::getIsLine}};
509     std::unique_ptr<LVReader> Reader =
510         createReader(ReaderHandler, InputsDir, CodeViewMsvc);
511     checkElementSelection(Reader.get(), DataMsvc, DataMsvc.size());
512   }
513 }
514 
515 // Compare logical elements.
516 void compareElements(SmallString<128> &InputsDir) {
517   // Reader options.
518   LVOptions ReaderOptions;
519   ReaderOptions.setAttributeOffset();
520   ReaderOptions.setPrintLines();
521   ReaderOptions.setPrintSymbols();
522   ReaderOptions.setPrintTypes();
523   ReaderOptions.setCompareLines();
524   ReaderOptions.setCompareSymbols();
525   ReaderOptions.setCompareTypes();
526 
527   ReaderOptions.resolveDependencies();
528 
529   std::vector<std::string> Objects;
530   ScopedPrinter W(outs());
531   LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);
532 
533   // Check logical comparison.
534   std::unique_ptr<LVReader> Reference =
535       createReader(ReaderHandler, InputsDir, CodeViewClang);
536   std::unique_ptr<LVReader> Target =
537       createReader(ReaderHandler, InputsDir, CodeViewMsvc);
538   checkElementComparison(Reference.get(), Target.get());
539 }
540 
541 TEST(LogicalViewTest, CodeViewReader) {
542   // Initialize targets and assembly printers/parsers.
543   llvm::InitializeAllTargetInfos();
544   llvm::InitializeAllTargetMCs();
545   InitializeAllDisassemblers();
546 
547   llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
548 
549   // This test requires a x86-registered-target.
550   Triple TT;
551   TT.setArch(Triple::x86_64);
552   TT.setVendor(Triple::UnknownVendor);
553   TT.setOS(Triple::UnknownOS);
554 
555   std::string TargetLookupError;
556   if (!TargetRegistry::lookupTarget(std::string(TT.str()), TargetLookupError))
557     return;
558 
559   SmallString<128> InputsDir = unittest::getInputFileDirectory(TestMainArgv0);
560 
561   // Logical elements general properties and selection.
562   elementProperties(InputsDir);
563   elementSelection(InputsDir);
564 
565   // Compare logical elements.
566   compareElements(InputsDir);
567 }
568 
569 } // namespace
570