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::pdb::IPDBSession &session, llvm::StringRef var) const 138 { 139 auto global = session.getGlobalScope(); 140 auto results = 141 global->findChildren(llvm::pdb::PDB_SymType::Data, var, llvm::pdb::PDB_NameSearchFlags::NS_Default); 142 uint32_t count = results->getChildCount(); 143 if (count == 0) 144 return -1; 145 146 auto item = results->getChildAtIndex(0); 147 auto symbol = llvm::dyn_cast<llvm::pdb::PDBSymbolData>(item.get()); 148 if (!symbol) 149 return -1; 150 llvm::pdb::Variant value = symbol->getValue(); 151 switch (value.Type) 152 { 153 case llvm::pdb::PDB_VariantType::Int16: 154 return value.Value.Int16; 155 case llvm::pdb::PDB_VariantType::Int32: 156 return value.Value.Int32; 157 case llvm::pdb::PDB_VariantType::UInt16: 158 return value.Value.UInt16; 159 case llvm::pdb::PDB_VariantType::UInt32: 160 return value.Value.UInt32; 161 default: 162 return 0; 163 } 164 } 165 }; 166 167 #if defined(HAVE_DIA_SDK) 168 #define REQUIRES_DIA_SDK(TestName) TestName 169 #else 170 #define REQUIRES_DIA_SDK(TestName) DISABLED_##TestName 171 #endif 172 173 TEST_F(SymbolFilePDBTests, TestAbilitiesForDWARF) 174 { 175 // Test that when we have Dwarf debug info, SymbolFileDWARF is used. 176 FileSpec fspec(m_dwarf_test_exe.c_str(), false); 177 ArchSpec aspec("i686-pc-windows"); 178 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 179 180 SymbolVendor *plugin = module->GetSymbolVendor(); 181 EXPECT_NE(nullptr, plugin); 182 SymbolFile *symfile = plugin->GetSymbolFile(); 183 EXPECT_NE(nullptr, symfile); 184 EXPECT_EQ(symfile->GetPluginName(), SymbolFileDWARF::GetPluginNameStatic()); 185 186 uint32_t expected_abilities = SymbolFile::kAllAbilities; 187 EXPECT_EQ(expected_abilities, symfile->CalculateAbilities()); 188 } 189 190 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestAbilitiesForPDB)) 191 { 192 // Test that when we have PDB debug info, SymbolFilePDB is used. 193 FileSpec fspec(m_pdb_test_exe.c_str(), false); 194 ArchSpec aspec("i686-pc-windows"); 195 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 196 197 SymbolVendor *plugin = module->GetSymbolVendor(); 198 EXPECT_NE(nullptr, plugin); 199 SymbolFile *symfile = plugin->GetSymbolFile(); 200 EXPECT_NE(nullptr, symfile); 201 EXPECT_EQ(symfile->GetPluginName(), SymbolFilePDB::GetPluginNameStatic()); 202 203 uint32_t expected_abilities = SymbolFile::CompileUnits | SymbolFile::LineTables; 204 EXPECT_EQ(expected_abilities, symfile->CalculateAbilities()); 205 } 206 207 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestResolveSymbolContextBasename)) 208 { 209 // Test that attempting to call ResolveSymbolContext with only a basename finds all full paths 210 // with the same basename 211 FileSpec fspec(m_pdb_test_exe.c_str(), false); 212 ArchSpec aspec("i686-pc-windows"); 213 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 214 215 SymbolVendor *plugin = module->GetSymbolVendor(); 216 EXPECT_NE(nullptr, plugin); 217 SymbolFile *symfile = plugin->GetSymbolFile(); 218 219 FileSpec header_spec("test-pdb.cpp", false); 220 SymbolContextList sc_list; 221 uint32_t result_count = symfile->ResolveSymbolContext(header_spec, 0, false, lldb::eSymbolContextCompUnit, sc_list); 222 EXPECT_EQ(1u, result_count); 223 EXPECT_TRUE(ContainsCompileUnit(sc_list, header_spec)); 224 } 225 226 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestResolveSymbolContextFullPath)) 227 { 228 // Test that attempting to call ResolveSymbolContext with a full path only finds the one source 229 // file that matches the full path. 230 FileSpec fspec(m_pdb_test_exe.c_str(), false); 231 ArchSpec aspec("i686-pc-windows"); 232 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 233 234 SymbolVendor *plugin = module->GetSymbolVendor(); 235 EXPECT_NE(nullptr, plugin); 236 SymbolFile *symfile = plugin->GetSymbolFile(); 237 238 FileSpec header_spec(R"spec(D:\src\llvm\tools\lldb\unittests\SymbolFile\PDB\Inputs\test-pdb.cpp)spec", false); 239 SymbolContextList sc_list; 240 uint32_t result_count = symfile->ResolveSymbolContext(header_spec, 0, false, lldb::eSymbolContextCompUnit, sc_list); 241 EXPECT_GE(1u, result_count); 242 EXPECT_TRUE(ContainsCompileUnit(sc_list, header_spec)); 243 } 244 245 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestLookupOfHeaderFileWithInlines)) 246 { 247 // Test that when looking up a header file via ResolveSymbolContext (i.e. a file that was not by itself 248 // compiled, but only contributes to the combined code of other source files), a SymbolContext is returned 249 // for each compiland which has line contributions from the requested header. 250 FileSpec fspec(m_pdb_test_exe.c_str(), false); 251 ArchSpec aspec("i686-pc-windows"); 252 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 253 254 SymbolVendor *plugin = module->GetSymbolVendor(); 255 EXPECT_NE(nullptr, plugin); 256 SymbolFile *symfile = plugin->GetSymbolFile(); 257 258 FileSpec header_specs[] = {FileSpec("test-pdb.h", false), FileSpec("test-pdb-nested.h", false)}; 259 FileSpec main_cpp_spec("test-pdb.cpp", false); 260 FileSpec alt_cpp_spec("test-pdb-alt.cpp", false); 261 for (const auto &hspec : header_specs) 262 { 263 SymbolContextList sc_list; 264 uint32_t result_count = symfile->ResolveSymbolContext(hspec, 0, true, lldb::eSymbolContextCompUnit, sc_list); 265 EXPECT_EQ(2u, result_count); 266 EXPECT_TRUE(ContainsCompileUnit(sc_list, main_cpp_spec)); 267 EXPECT_TRUE(ContainsCompileUnit(sc_list, alt_cpp_spec)); 268 } 269 } 270 271 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestLookupOfHeaderFileWithNoInlines)) 272 { 273 // Test that when looking up a header file via ResolveSymbolContext (i.e. a file that was not by itself 274 // compiled, but only contributes to the combined code of other source files), that if check_inlines 275 // is false, no SymbolContexts are returned. 276 FileSpec fspec(m_pdb_test_exe.c_str(), false); 277 ArchSpec aspec("i686-pc-windows"); 278 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 279 280 SymbolVendor *plugin = module->GetSymbolVendor(); 281 EXPECT_NE(nullptr, plugin); 282 SymbolFile *symfile = plugin->GetSymbolFile(); 283 284 FileSpec header_specs[] = {FileSpec("test-pdb.h", false), FileSpec("test-pdb-nested.h", false)}; 285 for (const auto &hspec : header_specs) 286 { 287 SymbolContextList sc_list; 288 uint32_t result_count = symfile->ResolveSymbolContext(hspec, 0, false, lldb::eSymbolContextCompUnit, sc_list); 289 EXPECT_EQ(0u, result_count); 290 } 291 } 292 293 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestLineTablesMatchAll)) 294 { 295 // Test that when calling ResolveSymbolContext with a line number of 0, all line entries from 296 // the specified files are returned. 297 FileSpec fspec(m_pdb_test_exe.c_str(), false); 298 ArchSpec aspec("i686-pc-windows"); 299 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 300 301 SymbolVendor *plugin = module->GetSymbolVendor(); 302 SymbolFile *symfile = plugin->GetSymbolFile(); 303 304 FileSpec source_file("test-pdb.cpp", false); 305 FileSpec header1("test-pdb.h", false); 306 FileSpec header2("test-pdb-nested.h", false); 307 uint32_t cus = symfile->GetNumCompileUnits(); 308 EXPECT_EQ(2u, cus); 309 310 SymbolContextList sc_list; 311 uint32_t scope = lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry; 312 313 uint32_t count = symfile->ResolveSymbolContext(source_file, 0, true, scope, sc_list); 314 EXPECT_EQ(1u, count); 315 SymbolContext sc; 316 EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc)); 317 318 LineTable *lt = sc.comp_unit->GetLineTable(); 319 EXPECT_NE(nullptr, lt); 320 count = lt->GetSize(); 321 // We expect one extra entry for termination (per function) 322 EXPECT_EQ(16u, count); 323 324 VerifyLineEntry(module, sc, source_file, *lt, 7, 0x401040); 325 VerifyLineEntry(module, sc, source_file, *lt, 8, 0x401043); 326 VerifyLineEntry(module, sc, source_file, *lt, 9, 0x401045); 327 328 VerifyLineEntry(module, sc, source_file, *lt, 13, 0x401050); 329 VerifyLineEntry(module, sc, source_file, *lt, 14, 0x401054); 330 VerifyLineEntry(module, sc, source_file, *lt, 15, 0x401070); 331 332 VerifyLineEntry(module, sc, header1, *lt, 9, 0x401090); 333 VerifyLineEntry(module, sc, header1, *lt, 10, 0x401093); 334 VerifyLineEntry(module, sc, header1, *lt, 11, 0x4010a2); 335 336 VerifyLineEntry(module, sc, header2, *lt, 5, 0x401080); 337 VerifyLineEntry(module, sc, header2, *lt, 6, 0x401083); 338 VerifyLineEntry(module, sc, header2, *lt, 7, 0x401089); 339 } 340 341 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestLineTablesMatchSpecific)) 342 { 343 // Test that when calling ResolveSymbolContext with a specific line number, only line entries 344 // which match the requested line are returned. 345 FileSpec fspec(m_pdb_test_exe.c_str(), false); 346 ArchSpec aspec("i686-pc-windows"); 347 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 348 349 SymbolVendor *plugin = module->GetSymbolVendor(); 350 SymbolFile *symfile = plugin->GetSymbolFile(); 351 352 FileSpec source_file("test-pdb.cpp", false); 353 FileSpec header1("test-pdb.h", false); 354 FileSpec header2("test-pdb-nested.h", false); 355 uint32_t cus = symfile->GetNumCompileUnits(); 356 EXPECT_EQ(2u, cus); 357 358 SymbolContextList sc_list; 359 uint32_t scope = lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry; 360 361 // First test with line 7, and verify that only line 7 entries are added. 362 uint32_t count = symfile->ResolveSymbolContext(source_file, 7, true, scope, sc_list); 363 EXPECT_EQ(1u, count); 364 SymbolContext sc; 365 EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc)); 366 367 LineTable *lt = sc.comp_unit->GetLineTable(); 368 EXPECT_NE(nullptr, lt); 369 count = lt->GetSize(); 370 // We expect one extra entry for termination 371 EXPECT_EQ(3u, count); 372 373 VerifyLineEntry(module, sc, source_file, *lt, 7, 0x401040); 374 VerifyLineEntry(module, sc, header2, *lt, 7, 0x401089); 375 376 sc_list.Clear(); 377 // Then test with line 9, and verify that only line 9 entries are added. 378 count = symfile->ResolveSymbolContext(source_file, 9, true, scope, sc_list); 379 EXPECT_EQ(1u, count); 380 EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc)); 381 382 lt = sc.comp_unit->GetLineTable(); 383 EXPECT_NE(nullptr, lt); 384 count = lt->GetSize(); 385 // We expect one extra entry for termination 386 EXPECT_EQ(3u, count); 387 388 VerifyLineEntry(module, sc, source_file, *lt, 9, 0x401045); 389 VerifyLineEntry(module, sc, header1, *lt, 9, 0x401090); 390 } 391 392 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestSimpleClassTypes)) 393 { 394 FileSpec fspec(m_types_test_exe.c_str(), false); 395 ArchSpec aspec("i686-pc-windows"); 396 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 397 398 SymbolVendor *plugin = module->GetSymbolVendor(); 399 SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile()); 400 const llvm::pdb::IPDBSession &session = symfile->GetPDBSession(); 401 SymbolContext sc; 402 llvm::DenseSet<SymbolFile *> searched_files; 403 TypeMap results; 404 EXPECT_EQ(1u, symfile->FindTypes(sc, ConstString("Class"), nullptr, false, 0, searched_files, results)); 405 EXPECT_EQ(1u, results.GetSize()); 406 lldb::TypeSP udt_type = results.GetTypeAtIndex(0); 407 EXPECT_EQ(ConstString("Class"), udt_type->GetName()); 408 CompilerType compiler_type = udt_type->GetForwardCompilerType(); 409 EXPECT_TRUE(ClangASTContext::IsClassType(compiler_type.GetOpaqueQualType())); 410 EXPECT_EQ(uint64_t(GetGlobalConstantInteger(session, "sizeof_Class")), udt_type->GetByteSize()); 411 } 412 413 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestNestedClassTypes)) 414 { 415 FileSpec fspec(m_types_test_exe.c_str(), false); 416 ArchSpec aspec("i686-pc-windows"); 417 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 418 419 SymbolVendor *plugin = module->GetSymbolVendor(); 420 SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile()); 421 const llvm::pdb::IPDBSession &session = symfile->GetPDBSession(); 422 SymbolContext sc; 423 llvm::DenseSet<SymbolFile *> searched_files; 424 TypeMap results; 425 EXPECT_EQ(1u, symfile->FindTypes(sc, ConstString("Class::NestedClass"), nullptr, false, 0, searched_files, results)); 426 EXPECT_EQ(1u, results.GetSize()); 427 lldb::TypeSP udt_type = results.GetTypeAtIndex(0); 428 EXPECT_EQ(ConstString("Class::NestedClass"), udt_type->GetName()); 429 CompilerType compiler_type = udt_type->GetForwardCompilerType(); 430 EXPECT_TRUE(ClangASTContext::IsClassType(compiler_type.GetOpaqueQualType())); 431 EXPECT_EQ(uint64_t(GetGlobalConstantInteger(session, "sizeof_NestedClass")), udt_type->GetByteSize()); 432 } 433 434 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestClassInNamespace)) 435 { 436 FileSpec fspec(m_types_test_exe.c_str(), false); 437 ArchSpec aspec("i686-pc-windows"); 438 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 439 440 SymbolVendor *plugin = module->GetSymbolVendor(); 441 SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile()); 442 const llvm::pdb::IPDBSession &session = symfile->GetPDBSession(); 443 SymbolContext sc; 444 llvm::DenseSet<SymbolFile *> searched_files; 445 TypeMap results; 446 EXPECT_EQ(1u, symfile->FindTypes(sc, ConstString("NS::NSClass"), nullptr, false, 0, searched_files, results)); 447 EXPECT_EQ(1u, results.GetSize()); 448 lldb::TypeSP udt_type = results.GetTypeAtIndex(0); 449 EXPECT_EQ(ConstString("NS::NSClass"), udt_type->GetName()); 450 CompilerType compiler_type = udt_type->GetForwardCompilerType(); 451 EXPECT_TRUE(ClangASTContext::IsClassType(compiler_type.GetOpaqueQualType())); 452 EXPECT_EQ(GetGlobalConstantInteger(session, "sizeof_NSClass"), udt_type->GetByteSize()); 453 } 454 455 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestEnumTypes)) 456 { 457 FileSpec fspec(m_types_test_exe.c_str(), false); 458 ArchSpec aspec("i686-pc-windows"); 459 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 460 461 SymbolVendor *plugin = module->GetSymbolVendor(); 462 SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile()); 463 const llvm::pdb::IPDBSession &session = symfile->GetPDBSession(); 464 SymbolContext sc; 465 llvm::DenseSet<SymbolFile *> searched_files; 466 const char *EnumsToCheck[] = {"Enum", "ShortEnum"}; 467 for (auto Enum : EnumsToCheck) 468 { 469 TypeMap results; 470 EXPECT_EQ(1u, symfile->FindTypes(sc, ConstString(Enum), nullptr, false, 0, searched_files, results)); 471 EXPECT_EQ(1u, results.GetSize()); 472 lldb::TypeSP enum_type = results.GetTypeAtIndex(0); 473 EXPECT_EQ(ConstString(Enum), enum_type->GetName()); 474 CompilerType compiler_type = enum_type->GetFullCompilerType(); 475 EXPECT_TRUE(ClangASTContext::IsEnumType(compiler_type.GetOpaqueQualType())); 476 clang::EnumDecl *enum_decl = ClangASTContext::GetAsEnumDecl(compiler_type); 477 EXPECT_NE(nullptr, enum_decl); 478 EXPECT_EQ(2, std::distance(enum_decl->enumerator_begin(), enum_decl->enumerator_end())); 479 480 std::string sizeof_var = "sizeof_"; 481 sizeof_var.append(Enum); 482 EXPECT_EQ(GetGlobalConstantInteger(session, sizeof_var.c_str()), enum_type->GetByteSize()); 483 } 484 } 485 486 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestArrayTypes)) 487 { 488 // In order to get this test working, we need to support lookup by symbol name. Because array 489 // types themselves do not have names, only the symbols have names (i.e. the name of the array). 490 } 491 492 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestFunctionTypes)) 493 { 494 // In order to get this test working, we need to support lookup by symbol name. Because array 495 // types themselves do not have names, only the symbols have names (i.e. the name of the array). 496 } 497 498 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestTypedefs)) 499 { 500 FileSpec fspec(m_types_test_exe.c_str(), false); 501 ArchSpec aspec("i686-pc-windows"); 502 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 503 504 SymbolVendor *plugin = module->GetSymbolVendor(); 505 SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile()); 506 const llvm::pdb::IPDBSession &session = symfile->GetPDBSession(); 507 SymbolContext sc; 508 llvm::DenseSet<SymbolFile *> searched_files; 509 TypeMap results; 510 511 const char *TypedefsToCheck[] = {"ClassTypedef", "NSClassTypedef"}; 512 for (auto Typedef : TypedefsToCheck) 513 { 514 TypeMap results; 515 EXPECT_EQ(1u, symfile->FindTypes(sc, ConstString(Typedef), nullptr, false, 0, searched_files, results)); 516 EXPECT_EQ(1u, results.GetSize()); 517 lldb::TypeSP typedef_type = results.GetTypeAtIndex(0); 518 EXPECT_EQ(ConstString(Typedef), typedef_type->GetName()); 519 CompilerType compiler_type = typedef_type->GetFullCompilerType(); 520 ClangASTContext *clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(compiler_type.GetTypeSystem()); 521 EXPECT_TRUE(clang_type_system->IsTypedefType(compiler_type.GetOpaqueQualType())); 522 523 std::string sizeof_var = "sizeof_"; 524 sizeof_var.append(Typedef); 525 EXPECT_EQ(GetGlobalConstantInteger(session, sizeof_var.c_str()), typedef_type->GetByteSize()); 526 } 527 } 528 529 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestRegexNameMatch)) 530 { 531 FileSpec fspec(m_types_test_exe.c_str(), false); 532 ArchSpec aspec("i686-pc-windows"); 533 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 534 535 SymbolVendor *plugin = module->GetSymbolVendor(); 536 SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile()); 537 SymbolContext sc; 538 llvm::DenseSet<SymbolFile *> searched_files; 539 TypeMap results; 540 uint32_t num_results = symfile->FindTypes(sc, ConstString(".*"), nullptr, false, 0, searched_files, results); 541 EXPECT_GT(num_results, 1u); 542 EXPECT_EQ(num_results, results.GetSize()); 543 } 544 545 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestMaxMatches)) 546 { 547 FileSpec fspec(m_types_test_exe.c_str(), false); 548 ArchSpec aspec("i686-pc-windows"); 549 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 550 551 SymbolVendor *plugin = module->GetSymbolVendor(); 552 SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile()); 553 SymbolContext sc; 554 llvm::DenseSet<SymbolFile *> searched_files; 555 TypeMap results; 556 uint32_t num_results = symfile->FindTypes(sc, ConstString(".*"), nullptr, false, 0, searched_files, results); 557 // Try to limit ourselves from 1 to 10 results, otherwise we could be doing this thousands of times. 558 // The idea is just to make sure that for a variety of values, the number of limited results always 559 // comes out to the number we are expecting. 560 uint32_t iterations = std::min(num_results, 10u); 561 for (uint32_t i = 1; i <= iterations; ++i) 562 { 563 uint32_t num_limited_results = symfile->FindTypes(sc, ConstString(".*"), nullptr, false, i, searched_files, results); 564 EXPECT_EQ(i, num_limited_results); 565 EXPECT_EQ(num_limited_results, results.GetSize()); 566 } 567 } 568 569 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestNullName)) 570 { 571 FileSpec fspec(m_types_test_exe.c_str(), false); 572 ArchSpec aspec("i686-pc-windows"); 573 lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); 574 575 SymbolVendor *plugin = module->GetSymbolVendor(); 576 SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile()); 577 SymbolContext sc; 578 llvm::DenseSet<SymbolFile *> searched_files; 579 TypeMap results; 580 uint32_t num_results = symfile->FindTypes(sc, ConstString(), nullptr, false, 0, searched_files, results); 581 EXPECT_EQ(0u, num_results); 582 EXPECT_EQ(0u, results.GetSize()); 583 } 584