1 //===-- PythonDataObjectsTests.cpp ------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "gtest/gtest.h" 11 12 #include "llvm/ADT/STLExtras.h" 13 #include "llvm/Config/config.h" 14 #include "llvm/DebugInfo/PDB/PDBSymbolData.h" 15 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h" 16 #include "llvm/Support/FileSystem.h" 17 #include "llvm/Support/Path.h" 18 19 #include "lldb/Core/Address.h" 20 #include "lldb/Core/ArchSpec.h" 21 #include "lldb/Core/Module.h" 22 #include "lldb/Core/ModuleSpec.h" 23 #include "lldb/Host/FileSpec.h" 24 #include "lldb/Host/HostInfo.h" 25 #include "lldb/Symbol/ClangASTContext.h" 26 #include "lldb/Symbol/CompileUnit.h" 27 #include "lldb/Symbol/LineTable.h" 28 #include "lldb/Symbol/SymbolVendor.h" 29 30 #include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h" 31 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h" 32 #include "Plugins/SymbolFile/PDB/SymbolFilePDB.h" 33 34 #if defined(_MSC_VER) 35 #include "lldb/Host/windows/windows.h" 36 #include <objbase.h> 37 #endif 38 39 #include <algorithm> 40 41 extern const char *TestMainArgv0; 42 43 using namespace lldb_private; 44 45 class SymbolFilePDBTests : public testing::Test 46 { 47 public: 48 void 49 SetUp() override 50 { 51 // Initialize and TearDown the plugin every time, so we get a brand new 52 // AST every time so that modifications to the AST from each test don't 53 // leak into the next test. 54 #if defined(_MSC_VER) 55 ::CoInitializeEx(nullptr, COINIT_MULTITHREADED); 56 #endif 57 58 HostInfo::Initialize(); 59 ObjectFilePECOFF::Initialize(); 60 SymbolFileDWARF::Initialize(); 61 ClangASTContext::Initialize(); 62 SymbolFilePDB::Initialize(); 63 64 llvm::StringRef exe_folder = llvm::sys::path::parent_path(TestMainArgv0); 65 llvm::SmallString<128> inputs_folder = exe_folder; 66 llvm::sys::path::append(inputs_folder, "Inputs"); 67 68 m_pdb_test_exe = inputs_folder; 69 m_dwarf_test_exe = inputs_folder; 70 m_types_test_exe = inputs_folder; 71 llvm::sys::path::append(m_pdb_test_exe, "test-pdb.exe"); 72 llvm::sys::path::append(m_dwarf_test_exe, "test-dwarf.exe"); 73 llvm::sys::path::append(m_types_test_exe, "test-pdb-types.exe"); 74 } 75 76 void 77 TearDown() override 78 { 79 SymbolFilePDB::Terminate(); 80 ClangASTContext::Initialize(); 81 SymbolFileDWARF::Terminate(); 82 ObjectFilePECOFF::Terminate(); 83 HostInfo::Terminate(); 84 85 #if defined(_MSC_VER) 86 ::CoUninitialize(); 87 #endif 88 } 89 90 protected: 91 llvm::SmallString<128> m_pdb_test_exe; 92 llvm::SmallString<128> m_dwarf_test_exe; 93 llvm::SmallString<128> m_types_test_exe; 94 95 bool 96 FileSpecMatchesAsBaseOrFull(const FileSpec &left, const FileSpec &right) const 97 { 98 // If the filenames don't match, the paths can't be equal 99 if (!left.FileEquals(right)) 100 return false; 101 // If BOTH have a directory, also compare the directories. 102 if (left.GetDirectory() && right.GetDirectory()) 103 return left.DirectoryEquals(right); 104 105 // If one has a directory but not the other, they match. 106 return true; 107 } 108 109 void 110 VerifyLineEntry(lldb::ModuleSP module, const SymbolContext &sc, const FileSpec &spec, LineTable <, uint32_t line, 111 lldb::addr_t addr) 112 { 113 LineEntry entry; 114 Address address; 115 EXPECT_TRUE(module->ResolveFileAddress(addr, address)); 116 117 EXPECT_TRUE(lt.FindLineEntryByAddress(address, entry)); 118 EXPECT_EQ(line, entry.line); 119 EXPECT_EQ(address, entry.range.GetBaseAddress()); 120 121 EXPECT_TRUE(FileSpecMatchesAsBaseOrFull(spec, entry.file)); 122 } 123 124 bool 125 ContainsCompileUnit(const SymbolContextList &sc_list, const FileSpec &spec) const 126 { 127 for (size_t i = 0; i < sc_list.GetSize(); ++i) 128 { 129 const SymbolContext &sc = sc_list[i]; 130 if (FileSpecMatchesAsBaseOrFull(*sc.comp_unit, spec)) 131 return true; 132 } 133 return false; 134 } 135 136 int 137 GetGlobalConstantInteger(const llvm::IPDBSession &session, llvm::StringRef var) const 138 { 139 auto global = session.getGlobalScope(); 140 auto results = global->findChildren(llvm::PDB_SymType::Data, var, llvm::PDB_NameSearchFlags::NS_Default); 141 uint32_t count = results->getChildCount(); 142 if (count == 0) 143 return -1; 144 145 auto item = results->getChildAtIndex(0); 146 auto symbol = llvm::dyn_cast<llvm::PDBSymbolData>(item.get()); 147 if (!symbol) 148 return -1; 149 llvm::Variant value = symbol->getValue(); 150 switch (value.Type) 151 { 152 case llvm::PDB_VariantType::Int16: 153 return value.Value.Int16; 154 case llvm::PDB_VariantType::Int32: 155 return value.Value.Int32; 156 case llvm::PDB_VariantType::UInt16: 157 return value.Value.UInt16; 158 case llvm::PDB_VariantType::UInt32: 159 return value.Value.UInt32; 160 default: 161 return 0; 162 } 163 } 164 }; 165 166 #if defined(HAVE_DIA_SDK) 167 #define REQUIRES_DIA_SDK(TestName) TestName 168 #else 169 #define REQUIRES_DIA_SDK(TestName) DISABLED_##TestName 170 #endif 171 172 TEST_F(SymbolFilePDBTests, TestAbilitiesForDWARF) 173 { 174 // Test that when we have Dwarf debug info, SymbolFileDWARF is used. 175 FileSpec fspec(m_dwarf_test_exe.c_str(), false); 176 ArchSpec aspec("i686-pc-windows"); 177 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 178 179 SymbolVendor *plugin = module->GetSymbolVendor(); 180 EXPECT_NE(nullptr, plugin); 181 SymbolFile *symfile = plugin->GetSymbolFile(); 182 EXPECT_NE(nullptr, symfile); 183 EXPECT_EQ(symfile->GetPluginName(), SymbolFileDWARF::GetPluginNameStatic()); 184 185 uint32_t expected_abilities = SymbolFile::kAllAbilities; 186 EXPECT_EQ(expected_abilities, symfile->CalculateAbilities()); 187 } 188 189 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestAbilitiesForPDB)) 190 { 191 // Test that when we have PDB debug info, SymbolFilePDB is used. 192 FileSpec fspec(m_pdb_test_exe.c_str(), false); 193 ArchSpec aspec("i686-pc-windows"); 194 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 195 196 SymbolVendor *plugin = module->GetSymbolVendor(); 197 EXPECT_NE(nullptr, plugin); 198 SymbolFile *symfile = plugin->GetSymbolFile(); 199 EXPECT_NE(nullptr, symfile); 200 EXPECT_EQ(symfile->GetPluginName(), SymbolFilePDB::GetPluginNameStatic()); 201 202 uint32_t expected_abilities = SymbolFile::CompileUnits | SymbolFile::LineTables; 203 EXPECT_EQ(expected_abilities, symfile->CalculateAbilities()); 204 } 205 206 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestResolveSymbolContextBasename)) 207 { 208 // Test that attempting to call ResolveSymbolContext with only a basename finds all full paths 209 // with the same basename 210 FileSpec fspec(m_pdb_test_exe.c_str(), false); 211 ArchSpec aspec("i686-pc-windows"); 212 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 213 214 SymbolVendor *plugin = module->GetSymbolVendor(); 215 EXPECT_NE(nullptr, plugin); 216 SymbolFile *symfile = plugin->GetSymbolFile(); 217 218 FileSpec header_spec("test-pdb.cpp", false); 219 SymbolContextList sc_list; 220 uint32_t result_count = symfile->ResolveSymbolContext(header_spec, 0, false, lldb::eSymbolContextCompUnit, sc_list); 221 EXPECT_EQ(1u, result_count); 222 EXPECT_TRUE(ContainsCompileUnit(sc_list, header_spec)); 223 } 224 225 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestResolveSymbolContextFullPath)) 226 { 227 // Test that attempting to call ResolveSymbolContext with a full path only finds the one source 228 // file that matches the full path. 229 FileSpec fspec(m_pdb_test_exe.c_str(), false); 230 ArchSpec aspec("i686-pc-windows"); 231 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 232 233 SymbolVendor *plugin = module->GetSymbolVendor(); 234 EXPECT_NE(nullptr, plugin); 235 SymbolFile *symfile = plugin->GetSymbolFile(); 236 237 FileSpec header_spec(R"spec(D:\src\llvm\tools\lldb\unittests\SymbolFile\PDB\Inputs\test-pdb.cpp)spec", false); 238 SymbolContextList sc_list; 239 uint32_t result_count = symfile->ResolveSymbolContext(header_spec, 0, false, lldb::eSymbolContextCompUnit, sc_list); 240 EXPECT_GE(1u, result_count); 241 EXPECT_TRUE(ContainsCompileUnit(sc_list, header_spec)); 242 } 243 244 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestLookupOfHeaderFileWithInlines)) 245 { 246 // Test that when looking up a header file via ResolveSymbolContext (i.e. a file that was not by itself 247 // compiled, but only contributes to the combined code of other source files), a SymbolContext is returned 248 // for each compiland which has line contributions from the requested header. 249 FileSpec fspec(m_pdb_test_exe.c_str(), false); 250 ArchSpec aspec("i686-pc-windows"); 251 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 252 253 SymbolVendor *plugin = module->GetSymbolVendor(); 254 EXPECT_NE(nullptr, plugin); 255 SymbolFile *symfile = plugin->GetSymbolFile(); 256 257 FileSpec header_specs[] = {FileSpec("test-pdb.h", false), FileSpec("test-pdb-nested.h", false)}; 258 FileSpec main_cpp_spec("test-pdb.cpp", false); 259 FileSpec alt_cpp_spec("test-pdb-alt.cpp", false); 260 for (const auto &hspec : header_specs) 261 { 262 SymbolContextList sc_list; 263 uint32_t result_count = symfile->ResolveSymbolContext(hspec, 0, true, lldb::eSymbolContextCompUnit, sc_list); 264 EXPECT_EQ(2u, result_count); 265 EXPECT_TRUE(ContainsCompileUnit(sc_list, main_cpp_spec)); 266 EXPECT_TRUE(ContainsCompileUnit(sc_list, alt_cpp_spec)); 267 } 268 } 269 270 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestLookupOfHeaderFileWithNoInlines)) 271 { 272 // Test that when looking up a header file via ResolveSymbolContext (i.e. a file that was not by itself 273 // compiled, but only contributes to the combined code of other source files), that if check_inlines 274 // is false, no SymbolContexts are returned. 275 FileSpec fspec(m_pdb_test_exe.c_str(), false); 276 ArchSpec aspec("i686-pc-windows"); 277 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 278 279 SymbolVendor *plugin = module->GetSymbolVendor(); 280 EXPECT_NE(nullptr, plugin); 281 SymbolFile *symfile = plugin->GetSymbolFile(); 282 283 FileSpec header_specs[] = {FileSpec("test-pdb.h", false), FileSpec("test-pdb-nested.h", false)}; 284 for (const auto &hspec : header_specs) 285 { 286 SymbolContextList sc_list; 287 uint32_t result_count = symfile->ResolveSymbolContext(hspec, 0, false, lldb::eSymbolContextCompUnit, sc_list); 288 EXPECT_EQ(0u, result_count); 289 } 290 } 291 292 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestLineTablesMatchAll)) 293 { 294 // Test that when calling ResolveSymbolContext with a line number of 0, all line entries from 295 // the specified files are returned. 296 FileSpec fspec(m_pdb_test_exe.c_str(), false); 297 ArchSpec aspec("i686-pc-windows"); 298 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 299 300 SymbolVendor *plugin = module->GetSymbolVendor(); 301 SymbolFile *symfile = plugin->GetSymbolFile(); 302 303 FileSpec source_file("test-pdb.cpp", false); 304 FileSpec header1("test-pdb.h", false); 305 FileSpec header2("test-pdb-nested.h", false); 306 uint32_t cus = symfile->GetNumCompileUnits(); 307 EXPECT_EQ(2u, cus); 308 309 SymbolContextList sc_list; 310 uint32_t scope = lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry; 311 312 uint32_t count = symfile->ResolveSymbolContext(source_file, 0, true, scope, sc_list); 313 EXPECT_EQ(1u, count); 314 SymbolContext sc; 315 EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc)); 316 317 LineTable *lt = sc.comp_unit->GetLineTable(); 318 EXPECT_NE(nullptr, lt); 319 count = lt->GetSize(); 320 // We expect one extra entry for termination (per function) 321 EXPECT_EQ(16u, count); 322 323 VerifyLineEntry(module, sc, source_file, *lt, 7, 0x401040); 324 VerifyLineEntry(module, sc, source_file, *lt, 8, 0x401043); 325 VerifyLineEntry(module, sc, source_file, *lt, 9, 0x401045); 326 327 VerifyLineEntry(module, sc, source_file, *lt, 13, 0x401050); 328 VerifyLineEntry(module, sc, source_file, *lt, 14, 0x401054); 329 VerifyLineEntry(module, sc, source_file, *lt, 15, 0x401070); 330 331 VerifyLineEntry(module, sc, header1, *lt, 9, 0x401090); 332 VerifyLineEntry(module, sc, header1, *lt, 10, 0x401093); 333 VerifyLineEntry(module, sc, header1, *lt, 11, 0x4010a2); 334 335 VerifyLineEntry(module, sc, header2, *lt, 5, 0x401080); 336 VerifyLineEntry(module, sc, header2, *lt, 6, 0x401083); 337 VerifyLineEntry(module, sc, header2, *lt, 7, 0x401089); 338 } 339 340 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestLineTablesMatchSpecific)) 341 { 342 // Test that when calling ResolveSymbolContext with a specific line number, only line entries 343 // which match the requested line are returned. 344 FileSpec fspec(m_pdb_test_exe.c_str(), false); 345 ArchSpec aspec("i686-pc-windows"); 346 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 347 348 SymbolVendor *plugin = module->GetSymbolVendor(); 349 SymbolFile *symfile = plugin->GetSymbolFile(); 350 351 FileSpec source_file("test-pdb.cpp", false); 352 FileSpec header1("test-pdb.h", false); 353 FileSpec header2("test-pdb-nested.h", false); 354 uint32_t cus = symfile->GetNumCompileUnits(); 355 EXPECT_EQ(2u, cus); 356 357 SymbolContextList sc_list; 358 uint32_t scope = lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry; 359 360 // First test with line 7, and verify that only line 7 entries are added. 361 uint32_t count = symfile->ResolveSymbolContext(source_file, 7, true, scope, sc_list); 362 EXPECT_EQ(1u, count); 363 SymbolContext sc; 364 EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc)); 365 366 LineTable *lt = sc.comp_unit->GetLineTable(); 367 EXPECT_NE(nullptr, lt); 368 count = lt->GetSize(); 369 // We expect one extra entry for termination 370 EXPECT_EQ(3u, count); 371 372 VerifyLineEntry(module, sc, source_file, *lt, 7, 0x401040); 373 VerifyLineEntry(module, sc, header2, *lt, 7, 0x401089); 374 375 sc_list.Clear(); 376 // Then test with line 9, and verify that only line 9 entries are added. 377 count = symfile->ResolveSymbolContext(source_file, 9, true, scope, sc_list); 378 EXPECT_EQ(1u, count); 379 EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc)); 380 381 lt = sc.comp_unit->GetLineTable(); 382 EXPECT_NE(nullptr, lt); 383 count = lt->GetSize(); 384 // We expect one extra entry for termination 385 EXPECT_EQ(3u, count); 386 387 VerifyLineEntry(module, sc, source_file, *lt, 9, 0x401045); 388 VerifyLineEntry(module, sc, header1, *lt, 9, 0x401090); 389 } 390 391 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestSimpleClassTypes)) 392 { 393 FileSpec fspec(m_types_test_exe.c_str(), false); 394 ArchSpec aspec("i686-pc-windows"); 395 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 396 397 SymbolVendor *plugin = module->GetSymbolVendor(); 398 SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile()); 399 const llvm::IPDBSession &session = symfile->GetPDBSession(); 400 SymbolContext sc; 401 llvm::DenseSet<SymbolFile *> searched_files; 402 TypeMap results; 403 EXPECT_EQ(1, symfile->FindTypes(sc, ConstString("Class"), nullptr, false, 0, searched_files, results)); 404 EXPECT_EQ(1, results.GetSize()); 405 lldb::TypeSP udt_type = results.GetTypeAtIndex(0); 406 EXPECT_EQ(ConstString("Class"), udt_type->GetName()); 407 CompilerType compiler_type = udt_type->GetForwardCompilerType(); 408 EXPECT_TRUE(ClangASTContext::IsClassType(compiler_type.GetOpaqueQualType())); 409 EXPECT_EQ(GetGlobalConstantInteger(session, "sizeof_Class"), udt_type->GetByteSize()); 410 } 411 412 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestNestedClassTypes)) 413 { 414 FileSpec fspec(m_types_test_exe.c_str(), false); 415 ArchSpec aspec("i686-pc-windows"); 416 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 417 418 SymbolVendor *plugin = module->GetSymbolVendor(); 419 SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile()); 420 const llvm::IPDBSession &session = symfile->GetPDBSession(); 421 SymbolContext sc; 422 llvm::DenseSet<SymbolFile *> searched_files; 423 TypeMap results; 424 EXPECT_EQ(1, symfile->FindTypes(sc, ConstString("Class::NestedClass"), nullptr, false, 0, searched_files, results)); 425 EXPECT_EQ(1, results.GetSize()); 426 lldb::TypeSP udt_type = results.GetTypeAtIndex(0); 427 EXPECT_EQ(ConstString("Class::NestedClass"), udt_type->GetName()); 428 CompilerType compiler_type = udt_type->GetForwardCompilerType(); 429 EXPECT_TRUE(ClangASTContext::IsClassType(compiler_type.GetOpaqueQualType())); 430 EXPECT_EQ(GetGlobalConstantInteger(session, "sizeof_NestedClass"), udt_type->GetByteSize()); 431 } 432 433 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestClassInNamespace)) 434 { 435 FileSpec fspec(m_types_test_exe.c_str(), false); 436 ArchSpec aspec("i686-pc-windows"); 437 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 438 439 SymbolVendor *plugin = module->GetSymbolVendor(); 440 SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile()); 441 const llvm::IPDBSession &session = symfile->GetPDBSession(); 442 SymbolContext sc; 443 llvm::DenseSet<SymbolFile *> searched_files; 444 TypeMap results; 445 EXPECT_EQ(1, symfile->FindTypes(sc, ConstString("NS::NSClass"), nullptr, false, 0, searched_files, results)); 446 EXPECT_EQ(1, results.GetSize()); 447 lldb::TypeSP udt_type = results.GetTypeAtIndex(0); 448 EXPECT_EQ(ConstString("NS::NSClass"), udt_type->GetName()); 449 CompilerType compiler_type = udt_type->GetForwardCompilerType(); 450 EXPECT_TRUE(ClangASTContext::IsClassType(compiler_type.GetOpaqueQualType())); 451 EXPECT_EQ(GetGlobalConstantInteger(session, "sizeof_NSClass"), udt_type->GetByteSize()); 452 } 453 454 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestEnumTypes)) 455 { 456 FileSpec fspec(m_types_test_exe.c_str(), false); 457 ArchSpec aspec("i686-pc-windows"); 458 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 459 460 SymbolVendor *plugin = module->GetSymbolVendor(); 461 SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile()); 462 const llvm::IPDBSession &session = symfile->GetPDBSession(); 463 SymbolContext sc; 464 llvm::DenseSet<SymbolFile *> searched_files; 465 const char *EnumsToCheck[] = {"Enum", "ShortEnum"}; 466 for (auto Enum : EnumsToCheck) 467 { 468 TypeMap results; 469 EXPECT_EQ(1, symfile->FindTypes(sc, ConstString(Enum), nullptr, false, 0, searched_files, results)); 470 EXPECT_EQ(1, results.GetSize()); 471 lldb::TypeSP enum_type = results.GetTypeAtIndex(0); 472 EXPECT_EQ(ConstString(Enum), enum_type->GetName()); 473 CompilerType compiler_type = enum_type->GetFullCompilerType(); 474 EXPECT_TRUE(ClangASTContext::IsEnumType(compiler_type.GetOpaqueQualType())); 475 clang::EnumDecl *enum_decl = ClangASTContext::GetAsEnumDecl(compiler_type); 476 EXPECT_NE(nullptr, enum_decl); 477 EXPECT_EQ(2, std::distance(enum_decl->enumerator_begin(), enum_decl->enumerator_end())); 478 479 std::string sizeof_var = "sizeof_"; 480 sizeof_var.append(Enum); 481 EXPECT_EQ(GetGlobalConstantInteger(session, sizeof_var.c_str()), enum_type->GetByteSize()); 482 } 483 } 484 485 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestArrayTypes)) 486 { 487 // In order to get this test working, we need to support lookup by symbol name. Because array 488 // types themselves do not have names, only the symbols have names (i.e. the name of the array). 489 } 490 491 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestFunctionTypes)) 492 { 493 // In order to get this test working, we need to support lookup by symbol name. Because array 494 // types themselves do not have names, only the symbols have names (i.e. the name of the array). 495 } 496 497 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestTypedefs)) 498 { 499 FileSpec fspec(m_types_test_exe.c_str(), false); 500 ArchSpec aspec("i686-pc-windows"); 501 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 502 503 SymbolVendor *plugin = module->GetSymbolVendor(); 504 SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile()); 505 const llvm::IPDBSession &session = symfile->GetPDBSession(); 506 SymbolContext sc; 507 llvm::DenseSet<SymbolFile *> searched_files; 508 TypeMap results; 509 510 const char *TypedefsToCheck[] = {"ClassTypedef", "NSClassTypedef"}; 511 for (auto Typedef : TypedefsToCheck) 512 { 513 TypeMap results; 514 EXPECT_EQ(1, symfile->FindTypes(sc, ConstString(Typedef), nullptr, false, 0, searched_files, results)); 515 EXPECT_EQ(1, results.GetSize()); 516 lldb::TypeSP typedef_type = results.GetTypeAtIndex(0); 517 EXPECT_EQ(ConstString(Typedef), typedef_type->GetName()); 518 CompilerType compiler_type = typedef_type->GetFullCompilerType(); 519 ClangASTContext *clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(compiler_type.GetTypeSystem()); 520 EXPECT_TRUE(clang_type_system->IsTypedefType(compiler_type.GetOpaqueQualType())); 521 522 std::string sizeof_var = "sizeof_"; 523 sizeof_var.append(Typedef); 524 EXPECT_EQ(GetGlobalConstantInteger(session, sizeof_var.c_str()), typedef_type->GetByteSize()); 525 } 526 } 527 528 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestRegexNameMatch)) 529 { 530 FileSpec fspec(m_types_test_exe.c_str(), false); 531 ArchSpec aspec("i686-pc-windows"); 532 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 533 534 SymbolVendor *plugin = module->GetSymbolVendor(); 535 SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile()); 536 SymbolContext sc; 537 llvm::DenseSet<SymbolFile *> searched_files; 538 TypeMap results; 539 int num_results = symfile->FindTypes(sc, ConstString(".*"), nullptr, false, 0, searched_files, results); 540 EXPECT_GT(num_results, 1); 541 EXPECT_EQ(num_results, results.GetSize()); 542 } 543 544 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestMaxMatches)) 545 { 546 FileSpec fspec(m_types_test_exe.c_str(), false); 547 ArchSpec aspec("i686-pc-windows"); 548 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 549 550 SymbolVendor *plugin = module->GetSymbolVendor(); 551 SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile()); 552 SymbolContext sc; 553 llvm::DenseSet<SymbolFile *> searched_files; 554 TypeMap results; 555 int num_results = symfile->FindTypes(sc, ConstString(".*"), nullptr, false, 0, searched_files, results); 556 // Try to limit ourselves from 1 to 10 results, otherwise we could be doing this thousands of times. 557 // The idea is just to make sure that for a variety of values, the number of limited results always 558 // comes out to the number we are expecting. 559 int iterations = std::min(num_results, 10); 560 for (int i = 1; i <= iterations; ++i) 561 { 562 int num_limited_results = symfile->FindTypes(sc, ConstString(".*"), nullptr, false, i, searched_files, results); 563 EXPECT_EQ(i, num_limited_results); 564 EXPECT_EQ(num_limited_results, results.GetSize()); 565 } 566 } 567 568 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestNullName)) 569 { 570 FileSpec fspec(m_types_test_exe.c_str(), false); 571 ArchSpec aspec("i686-pc-windows"); 572 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 573 574 SymbolVendor *plugin = module->GetSymbolVendor(); 575 SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile()); 576 SymbolContext sc; 577 llvm::DenseSet<SymbolFile *> searched_files; 578 TypeMap results; 579 int num_results = symfile->FindTypes(sc, ConstString(), nullptr, false, 0, searched_files, results); 580 EXPECT_EQ(0, num_results); 581 EXPECT_EQ(0, results.GetSize()); 582 } 583