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