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