1 //===-- LocateModuleCallbackTest.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 "Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h" 10 #include "Plugins/ObjectFile/ELF/ObjectFileELF.h" 11 #include "Plugins/Platform/Android/PlatformAndroid.h" 12 #include "Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h" 13 #include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h" 14 #include "TestingSupport/SubsystemRAII.h" 15 #include "TestingSupport/TestUtilities.h" 16 #include "lldb/Core/Debugger.h" 17 #include "lldb/Core/PluginManager.h" 18 #include "lldb/Host/HostInfo.h" 19 #include "lldb/Target/Target.h" 20 #include "gmock/gmock.h" 21 22 using namespace lldb; 23 using namespace lldb_private; 24 using namespace lldb_private::platform_android; 25 using namespace lldb_private::platform_linux; 26 using namespace lldb_private::breakpad; 27 using namespace testing; 28 29 namespace { 30 31 constexpr llvm::StringLiteral k_process_plugin("mock-process-plugin"); 32 constexpr llvm::StringLiteral k_platform_dir("remote-android"); 33 constexpr llvm::StringLiteral k_cache_dir(".cache"); 34 constexpr llvm::StringLiteral k_module_file("AndroidModule.so"); 35 constexpr llvm::StringLiteral k_symbol_file("AndroidModule.unstripped.so"); 36 constexpr llvm::StringLiteral k_breakpad_symbol_file("AndroidModule.so.sym"); 37 constexpr llvm::StringLiteral k_arch("aarch64-none-linux"); 38 constexpr llvm::StringLiteral 39 k_module_uuid("80008338-82A0-51E5-5922-C905D23890DA-BDDEFECC"); 40 constexpr llvm::StringLiteral k_function_symbol("boom"); 41 constexpr llvm::StringLiteral k_hidden_function_symbol("boom_hidden"); 42 const size_t k_module_size = 3784; 43 44 ModuleSpec GetTestModuleSpec(); 45 46 class MockProcess : public Process { 47 public: 48 MockProcess(TargetSP target_sp, ListenerSP listener_sp) 49 : Process(target_sp, listener_sp) {} 50 51 llvm::StringRef GetPluginName() override { return k_process_plugin; }; 52 53 bool CanDebug(TargetSP target, bool plugin_specified_by_name) override { 54 return true; 55 } 56 57 Status DoDestroy() override { return Status(); } 58 59 void RefreshStateAfterStop() override {} 60 61 bool DoUpdateThreadList(ThreadList &old_thread_list, 62 ThreadList &new_thread_list) override { 63 return false; 64 } 65 66 size_t DoReadMemory(addr_t vm_addr, void *buf, size_t size, 67 Status &error) override { 68 return 0; 69 } 70 71 bool GetModuleSpec(const FileSpec &module_file_spec, const ArchSpec &arch, 72 ModuleSpec &module_spec) override { 73 module_spec = GetTestModuleSpec(); 74 return true; 75 } 76 }; 77 78 FileSpec GetTestDir() { 79 const auto *info = UnitTest::GetInstance()->current_test_info(); 80 FileSpec test_dir = HostInfo::GetProcessTempDir(); 81 test_dir.AppendPathComponent(std::string(info->test_case_name()) + "-" + 82 info->name()); 83 std::error_code ec = llvm::sys::fs::create_directory(test_dir.GetPath()); 84 EXPECT_FALSE(ec); 85 return test_dir; 86 } 87 88 FileSpec GetRemotePath() { 89 FileSpec fs("/", FileSpec::Style::posix); 90 fs.AppendPathComponent("bin"); 91 fs.AppendPathComponent(k_module_file); 92 return fs; 93 } 94 95 FileSpec GetUuidView(FileSpec spec) { 96 spec.AppendPathComponent(k_platform_dir); 97 spec.AppendPathComponent(k_cache_dir); 98 spec.AppendPathComponent(k_module_uuid); 99 spec.AppendPathComponent(k_module_file); 100 return spec; 101 } 102 103 void BuildEmptyCacheDir(const FileSpec &test_dir) { 104 FileSpec cache_dir(test_dir); 105 cache_dir.AppendPathComponent(k_platform_dir); 106 cache_dir.AppendPathComponent(k_cache_dir); 107 std::error_code ec = llvm::sys::fs::create_directories(cache_dir.GetPath()); 108 EXPECT_FALSE(ec); 109 } 110 111 FileSpec BuildCacheDir(const FileSpec &test_dir) { 112 FileSpec uuid_view = GetUuidView(test_dir); 113 std::error_code ec = 114 llvm::sys::fs::create_directories(uuid_view.GetDirectory().GetCString()); 115 EXPECT_FALSE(ec); 116 ec = llvm::sys::fs::copy_file(GetInputFilePath(k_module_file), 117 uuid_view.GetPath().c_str()); 118 EXPECT_FALSE(ec); 119 return uuid_view; 120 } 121 122 FileSpec GetSymFileSpec(const FileSpec &uuid_view) { 123 return FileSpec(uuid_view.GetPath() + ".sym"); 124 } 125 126 FileSpec BuildCacheDirWithSymbol(const FileSpec &test_dir) { 127 FileSpec uuid_view = BuildCacheDir(test_dir); 128 std::error_code ec = 129 llvm::sys::fs::copy_file(GetInputFilePath(k_symbol_file), 130 GetSymFileSpec(uuid_view).GetPath().c_str()); 131 EXPECT_FALSE(ec); 132 return uuid_view; 133 } 134 135 FileSpec BuildCacheDirWithBreakpadSymbol(const FileSpec &test_dir) { 136 FileSpec uuid_view = BuildCacheDir(test_dir); 137 std::error_code ec = 138 llvm::sys::fs::copy_file(GetInputFilePath(k_breakpad_symbol_file), 139 GetSymFileSpec(uuid_view).GetPath().c_str()); 140 EXPECT_FALSE(ec); 141 return uuid_view; 142 } 143 144 ModuleSpec GetTestModuleSpec() { 145 ModuleSpec module_spec(GetRemotePath(), ArchSpec(k_arch)); 146 module_spec.GetUUID().SetFromStringRef(k_module_uuid); 147 module_spec.SetObjectSize(k_module_size); 148 return module_spec; 149 } 150 151 void CheckModule(const ModuleSP &module_sp) { 152 ASSERT_TRUE(module_sp); 153 ASSERT_EQ(module_sp->GetUUID().GetAsString(), k_module_uuid); 154 ASSERT_EQ(module_sp->GetObjectOffset(), 0U); 155 ASSERT_EQ(module_sp->GetPlatformFileSpec(), GetRemotePath()); 156 } 157 158 SymbolContextList FindFunctions(const ModuleSP &module_sp, 159 const llvm::StringRef &name) { 160 SymbolContextList sc_list; 161 ModuleFunctionSearchOptions function_options; 162 function_options.include_symbols = true; 163 function_options.include_inlines = true; 164 FunctionNameType type = static_cast<FunctionNameType>(eSymbolTypeCode); 165 module_sp->FindFunctions(ConstString(name), CompilerDeclContext(), type, 166 function_options, sc_list); 167 return sc_list; 168 } 169 170 void CheckStrippedSymbol(const ModuleSP &module_sp) { 171 SymbolContextList sc_list = FindFunctions(module_sp, k_function_symbol); 172 EXPECT_EQ(1U, sc_list.GetSize()); 173 174 sc_list = FindFunctions(module_sp, k_hidden_function_symbol); 175 EXPECT_EQ(0U, sc_list.GetSize()); 176 } 177 178 void CheckUnstrippedSymbol(const ModuleSP &module_sp) { 179 SymbolContextList sc_list = FindFunctions(module_sp, k_function_symbol); 180 EXPECT_EQ(1U, sc_list.GetSize()); 181 182 sc_list = FindFunctions(module_sp, k_hidden_function_symbol); 183 EXPECT_EQ(1U, sc_list.GetSize()); 184 } 185 186 ProcessSP MockProcessCreateInstance(TargetSP target_sp, ListenerSP listener_sp, 187 const FileSpec *crash_file_path, 188 bool can_connect) { 189 return std::make_shared<MockProcess>(target_sp, listener_sp); 190 } 191 192 class LocateModuleCallbackTest : public testing::Test { 193 SubsystemRAII<FileSystem, HostInfo, ObjectFileBreakpad, ObjectFileELF, 194 PlatformAndroid, PlatformLinux, SymbolFileBreakpad, 195 SymbolFileSymtab> 196 subsystems; 197 198 public: 199 void SetUp() override { 200 m_test_dir = GetTestDir(); 201 202 // Set module cache directory for PlatformAndroid. 203 PlatformAndroid::GetGlobalPlatformProperties().SetModuleCacheDirectory( 204 m_test_dir); 205 206 // Create Debugger. 207 ArchSpec host_arch("i386-pc-linux"); 208 Platform::SetHostPlatform( 209 platform_linux::PlatformLinux::CreateInstance(true, &host_arch)); 210 m_debugger_sp = Debugger::CreateInstance(); 211 EXPECT_TRUE(m_debugger_sp); 212 213 // Create PlatformAndroid. 214 ArchSpec arch(k_arch); 215 m_platform_sp = PlatformAndroid::CreateInstance(true, &arch); 216 EXPECT_TRUE(m_platform_sp); 217 218 // Create Target. 219 m_debugger_sp->GetTargetList().CreateTarget(*m_debugger_sp, "", arch, 220 eLoadDependentsNo, 221 m_platform_sp, m_target_sp); 222 EXPECT_TRUE(m_target_sp); 223 224 // Create MockProcess. 225 PluginManager::RegisterPlugin(k_process_plugin, "", 226 MockProcessCreateInstance); 227 m_process_sp = 228 m_target_sp->CreateProcess(Listener::MakeListener("test-listener"), 229 k_process_plugin, /*crash_file=*/nullptr, 230 /*can_connect=*/true); 231 EXPECT_TRUE(m_process_sp); 232 233 m_module_spec = GetTestModuleSpec(); 234 m_module_spec_without_uuid = ModuleSpec(GetRemotePath(), ArchSpec(k_arch)); 235 } 236 237 void TearDown() override { 238 if (m_module_sp) 239 ModuleList::RemoveSharedModule(m_module_sp); 240 } 241 242 void CheckNoCallback() { 243 EXPECT_FALSE(m_platform_sp->GetLocateModuleCallback()); 244 EXPECT_EQ(m_callback_call_count, 0); 245 } 246 247 void CheckCallbackArgs(const ModuleSpec &module_spec, 248 FileSpec &module_file_spec, FileSpec &symbol_file_spec, 249 const ModuleSpec &expected_module_spec, 250 int expected_callback_call_count) { 251 EXPECT_TRUE(expected_module_spec.Matches(module_spec, 252 /*exact_arch_match=*/true)); 253 EXPECT_FALSE(module_file_spec); 254 EXPECT_FALSE(symbol_file_spec); 255 256 EXPECT_EQ(++m_callback_call_count, expected_callback_call_count); 257 } 258 259 void CheckCallbackArgsWithUUID(const ModuleSpec &module_spec, 260 FileSpec &module_file_spec, 261 FileSpec &symbol_file_spec, 262 int expected_callback_call_count) { 263 CheckCallbackArgs(module_spec, module_file_spec, symbol_file_spec, 264 m_module_spec, expected_callback_call_count); 265 EXPECT_TRUE(module_spec.GetUUID().IsValid()); 266 } 267 268 void CheckCallbackArgsWithoutUUID(const ModuleSpec &module_spec, 269 FileSpec &module_file_spec, 270 FileSpec &symbol_file_spec, 271 int expected_callback_call_count) { 272 CheckCallbackArgs(module_spec, module_file_spec, symbol_file_spec, 273 m_module_spec_without_uuid, expected_callback_call_count); 274 EXPECT_FALSE(module_spec.GetUUID().IsValid()); 275 } 276 277 protected: 278 FileSpec m_test_dir; 279 DebuggerSP m_debugger_sp; 280 PlatformSP m_platform_sp; 281 TargetSP m_target_sp; 282 ProcessSP m_process_sp; 283 ModuleSpec m_module_spec; 284 ModuleSpec m_module_spec_without_uuid; 285 ModuleSP m_module_sp; 286 int m_callback_call_count = 0; 287 }; 288 289 } // namespace 290 291 TEST_F(LocateModuleCallbackTest, GetOrCreateModuleWithCachedModule) { 292 // The module file is cached, and the locate module callback is not set. 293 // GetOrCreateModule should succeed to return the module from the cache. 294 FileSpec uuid_view = BuildCacheDir(m_test_dir); 295 296 CheckNoCallback(); 297 298 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false); 299 CheckModule(m_module_sp); 300 ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view); 301 ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec()); 302 CheckStrippedSymbol(m_module_sp); 303 } 304 305 TEST_F(LocateModuleCallbackTest, GetOrCreateModuleWithCachedModuleAndSymbol) { 306 // The module and symbol files are cached, and the locate module callback is 307 // not set. GetOrCreateModule should succeed to return the module from the 308 // cache with the symbol. 309 FileSpec uuid_view = BuildCacheDirWithSymbol(m_test_dir); 310 311 CheckNoCallback(); 312 313 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false); 314 CheckModule(m_module_sp); 315 ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view); 316 ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(), GetSymFileSpec(uuid_view)); 317 CheckUnstrippedSymbol(m_module_sp); 318 } 319 320 TEST_F(LocateModuleCallbackTest, 321 GetOrCreateModuleWithCachedModuleAndBreakpadSymbol) { 322 // The module file and breakpad symbol file are cached, and the locate module 323 // callback is not set. GetOrCreateModule should succeed to return the module 324 // from the cache with the symbol. 325 FileSpec uuid_view = BuildCacheDirWithBreakpadSymbol(m_test_dir); 326 327 CheckNoCallback(); 328 329 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false); 330 CheckModule(m_module_sp); 331 ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view); 332 ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(), GetSymFileSpec(uuid_view)); 333 CheckUnstrippedSymbol(m_module_sp); 334 } 335 336 TEST_F(LocateModuleCallbackTest, GetOrCreateModuleFailure) { 337 // The cache dir is empty, and the locate module callback is not set. 338 // GetOrCreateModule should fail because PlatformAndroid tries to download the 339 // module and fails. 340 BuildEmptyCacheDir(m_test_dir); 341 342 CheckNoCallback(); 343 344 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false); 345 ASSERT_FALSE(m_module_sp); 346 } 347 348 TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackFailureNoCache) { 349 // The cache dir is empty, also the locate module callback fails for some 350 // reason. GetOrCreateModule should fail because PlatformAndroid tries to 351 // download the module and fails. 352 BuildEmptyCacheDir(m_test_dir); 353 354 int callback_call_count = 0; 355 m_platform_sp->SetLocateModuleCallback( 356 [this, &callback_call_count](const ModuleSpec &module_spec, 357 FileSpec &module_file_spec, 358 FileSpec &symbol_file_spec) { 359 CheckCallbackArgsWithUUID(module_spec, module_file_spec, 360 symbol_file_spec, ++callback_call_count); 361 return Status::FromErrorString("The locate module callback failed"); 362 }); 363 364 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false); 365 ASSERT_EQ(callback_call_count, 2); 366 ASSERT_FALSE(m_module_sp); 367 } 368 369 TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackFailureCached) { 370 // The module file is cached, so GetOrCreateModule should succeed to return 371 // the module from the cache even though the locate module callback fails for 372 // some reason. 373 FileSpec uuid_view = BuildCacheDir(m_test_dir); 374 375 int callback_call_count = 0; 376 m_platform_sp->SetLocateModuleCallback( 377 [this, &callback_call_count](const ModuleSpec &module_spec, 378 FileSpec &module_file_spec, 379 FileSpec &symbol_file_spec) { 380 CheckCallbackArgsWithUUID(module_spec, module_file_spec, 381 symbol_file_spec, ++callback_call_count); 382 return Status::FromErrorString("The locate module callback failed"); 383 }); 384 385 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false); 386 ASSERT_EQ(callback_call_count, 2); 387 CheckModule(m_module_sp); 388 ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view); 389 ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec()); 390 CheckStrippedSymbol(m_module_sp); 391 } 392 393 TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackNoFiles) { 394 // The module file is cached, so GetOrCreateModule should succeed to return 395 // the module from the cache even though the locate module callback returns 396 // no files. 397 FileSpec uuid_view = BuildCacheDir(m_test_dir); 398 399 int callback_call_count = 0; 400 m_platform_sp->SetLocateModuleCallback( 401 [this, &callback_call_count](const ModuleSpec &module_spec, 402 FileSpec &module_file_spec, 403 FileSpec &symbol_file_spec) { 404 CheckCallbackArgsWithUUID(module_spec, module_file_spec, 405 symbol_file_spec, ++callback_call_count); 406 // The locate module callback succeeds but it does not set 407 // module_file_spec nor symbol_file_spec. 408 return Status(); 409 }); 410 411 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false); 412 ASSERT_EQ(callback_call_count, 2); 413 CheckModule(m_module_sp); 414 ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view); 415 ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec()); 416 CheckStrippedSymbol(m_module_sp); 417 ModuleList::RemoveSharedModule(m_module_sp); 418 } 419 420 TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackNonExistentModule) { 421 // The module file is cached, so GetOrCreateModule should succeed to return 422 // the module from the cache even though the locate module callback returns 423 // non-existent module file. 424 FileSpec uuid_view = BuildCacheDir(m_test_dir); 425 426 int callback_call_count = 0; 427 m_platform_sp->SetLocateModuleCallback( 428 [this, &callback_call_count](const ModuleSpec &module_spec, 429 FileSpec &module_file_spec, 430 FileSpec &symbol_file_spec) { 431 CheckCallbackArgsWithUUID(module_spec, module_file_spec, 432 symbol_file_spec, ++callback_call_count); 433 module_file_spec.SetPath("/this path does not exist"); 434 return Status(); 435 }); 436 437 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false); 438 ASSERT_EQ(callback_call_count, 2); 439 CheckModule(m_module_sp); 440 ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view); 441 ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec()); 442 CheckStrippedSymbol(m_module_sp); 443 ModuleList::RemoveSharedModule(m_module_sp); 444 } 445 446 TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackNonExistentSymbol) { 447 // The module file is cached, so GetOrCreateModule should succeed to return 448 // the module from the cache even though the locate module callback returns 449 // non-existent symbol file. 450 FileSpec uuid_view = BuildCacheDir(m_test_dir); 451 452 int callback_call_count = 0; 453 m_platform_sp->SetLocateModuleCallback( 454 [this, &callback_call_count](const ModuleSpec &module_spec, 455 FileSpec &module_file_spec, 456 FileSpec &symbol_file_spec) { 457 CheckCallbackArgsWithUUID(module_spec, module_file_spec, 458 symbol_file_spec, ++callback_call_count); 459 // The locate module callback returns a right module file. 460 module_file_spec.SetPath(GetInputFilePath(k_module_file)); 461 // But it returns non-existent symbols file. 462 symbol_file_spec.SetPath("/this path does not exist"); 463 return Status(); 464 }); 465 466 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false); 467 ASSERT_EQ(callback_call_count, 2); 468 CheckModule(m_module_sp); 469 ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view); 470 ASSERT_TRUE(m_module_sp->GetSymbolFileFileSpec().GetPath().empty()); 471 CheckStrippedSymbol(m_module_sp); 472 ModuleList::RemoveSharedModule(m_module_sp); 473 } 474 475 TEST_F(LocateModuleCallbackTest, GetOrCreateModuleCallbackSuccessWithModule) { 476 // The locate module callback returns a module file, GetOrCreateModule should 477 // succeed to return the module from the Inputs directory. 478 BuildEmptyCacheDir(m_test_dir); 479 480 m_platform_sp->SetLocateModuleCallback([this](const ModuleSpec &module_spec, 481 FileSpec &module_file_spec, 482 FileSpec &symbol_file_spec) { 483 CheckCallbackArgsWithUUID(module_spec, module_file_spec, symbol_file_spec, 484 1); 485 module_file_spec.SetPath(GetInputFilePath(k_module_file)); 486 return Status(); 487 }); 488 489 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false); 490 CheckModule(m_module_sp); 491 ASSERT_EQ(m_module_sp->GetFileSpec(), 492 FileSpec(GetInputFilePath(k_module_file))); 493 ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec()); 494 CheckStrippedSymbol(m_module_sp); 495 ModuleList::RemoveSharedModule(m_module_sp); 496 } 497 498 TEST_F(LocateModuleCallbackTest, 499 GetOrCreateModuleCallbackSuccessWithSymbolAsModule) { 500 // The locate module callback returns the symbol file as a module file. It 501 // should work since the sections and UUID of the symbol file are the exact 502 // same with the module file, GetOrCreateModule should succeed to return the 503 // module with the symbol file from Inputs directory. 504 BuildEmptyCacheDir(m_test_dir); 505 506 m_platform_sp->SetLocateModuleCallback([this](const ModuleSpec &module_spec, 507 FileSpec &module_file_spec, 508 FileSpec &symbol_file_spec) { 509 CheckCallbackArgsWithUUID(module_spec, module_file_spec, symbol_file_spec, 510 1); 511 module_file_spec.SetPath(GetInputFilePath(k_symbol_file)); 512 return Status(); 513 }); 514 515 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false); 516 CheckModule(m_module_sp); 517 ASSERT_EQ(m_module_sp->GetFileSpec(), 518 FileSpec(GetInputFilePath(k_symbol_file))); 519 ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec()); 520 CheckUnstrippedSymbol(m_module_sp); 521 ModuleList::RemoveSharedModule(m_module_sp); 522 } 523 524 TEST_F(LocateModuleCallbackTest, 525 GetOrCreateModuleCallbackSuccessWithSymbolAsModuleAndSymbol) { 526 // The locate module callback returns a symbol file as both a module file and 527 // a symbol file. It should work since the sections and UUID of the symbol 528 // file are the exact same with the module file, GetOrCreateModule should 529 // succeed to return the module with the symbol file from Inputs directory. 530 BuildEmptyCacheDir(m_test_dir); 531 532 m_platform_sp->SetLocateModuleCallback([this](const ModuleSpec &module_spec, 533 FileSpec &module_file_spec, 534 FileSpec &symbol_file_spec) { 535 CheckCallbackArgsWithUUID(module_spec, module_file_spec, symbol_file_spec, 536 1); 537 module_file_spec.SetPath(GetInputFilePath(k_symbol_file)); 538 symbol_file_spec.SetPath(GetInputFilePath(k_symbol_file)); 539 return Status(); 540 }); 541 542 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false); 543 CheckModule(m_module_sp); 544 ASSERT_EQ(m_module_sp->GetFileSpec(), 545 FileSpec(GetInputFilePath(k_symbol_file))); 546 ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(), 547 FileSpec(GetInputFilePath(k_symbol_file))); 548 CheckUnstrippedSymbol(m_module_sp); 549 ModuleList::RemoveSharedModule(m_module_sp); 550 } 551 552 TEST_F(LocateModuleCallbackTest, 553 GetOrCreateModuleCallbackSuccessWithModuleAndSymbol) { 554 // The locate module callback returns a module file and a symbol file, 555 // GetOrCreateModule should succeed to return the module from Inputs 556 // directory, along with the symbol file. 557 BuildEmptyCacheDir(m_test_dir); 558 559 m_platform_sp->SetLocateModuleCallback([this](const ModuleSpec &module_spec, 560 FileSpec &module_file_spec, 561 FileSpec &symbol_file_spec) { 562 CheckCallbackArgsWithUUID(module_spec, module_file_spec, symbol_file_spec, 563 1); 564 module_file_spec.SetPath(GetInputFilePath(k_module_file)); 565 symbol_file_spec.SetPath(GetInputFilePath(k_symbol_file)); 566 return Status(); 567 }); 568 569 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false); 570 CheckModule(m_module_sp); 571 ASSERT_EQ(m_module_sp->GetFileSpec(), 572 FileSpec(GetInputFilePath(k_module_file))); 573 ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(), 574 FileSpec(GetInputFilePath(k_symbol_file))); 575 CheckUnstrippedSymbol(m_module_sp); 576 ModuleList::RemoveSharedModule(m_module_sp); 577 } 578 579 TEST_F(LocateModuleCallbackTest, 580 GetOrCreateModuleCallbackSuccessWithModuleAndBreakpadSymbol) { 581 // The locate module callback returns a module file and a breakpad symbol 582 // file, GetOrCreateModule should succeed to return the module with the symbol 583 // file from Inputs directory. 584 BuildEmptyCacheDir(m_test_dir); 585 586 m_platform_sp->SetLocateModuleCallback([this](const ModuleSpec &module_spec, 587 FileSpec &module_file_spec, 588 FileSpec &symbol_file_spec) { 589 CheckCallbackArgsWithUUID(module_spec, module_file_spec, symbol_file_spec, 590 1); 591 module_file_spec.SetPath(GetInputFilePath(k_module_file)); 592 symbol_file_spec.SetPath(GetInputFilePath(k_breakpad_symbol_file)); 593 return Status(); 594 }); 595 596 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false); 597 CheckModule(m_module_sp); 598 ASSERT_EQ(m_module_sp->GetFileSpec(), 599 FileSpec(GetInputFilePath(k_module_file))); 600 ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(), 601 FileSpec(GetInputFilePath(k_breakpad_symbol_file))); 602 CheckUnstrippedSymbol(m_module_sp); 603 ModuleList::RemoveSharedModule(m_module_sp); 604 } 605 606 TEST_F(LocateModuleCallbackTest, 607 GetOrCreateModuleCallbackSuccessWithOnlySymbol) { 608 // The get callback returns only a symbol file, and the module is cached, 609 // GetOrCreateModule should succeed to return the module from the cache 610 // along with the symbol file from the Inputs directory. 611 FileSpec uuid_view = BuildCacheDir(m_test_dir); 612 613 int callback_call_count = 0; 614 m_platform_sp->SetLocateModuleCallback( 615 [this, &callback_call_count](const ModuleSpec &module_spec, 616 FileSpec &module_file_spec, 617 FileSpec &symbol_file_spec) { 618 CheckCallbackArgsWithUUID(module_spec, module_file_spec, 619 symbol_file_spec, ++callback_call_count); 620 symbol_file_spec.SetPath(GetInputFilePath(k_symbol_file)); 621 return Status(); 622 }); 623 624 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false); 625 ASSERT_EQ(callback_call_count, 2); 626 CheckModule(m_module_sp); 627 ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view); 628 ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(), 629 FileSpec(GetInputFilePath(k_symbol_file))); 630 CheckUnstrippedSymbol(m_module_sp); 631 ModuleList::RemoveSharedModule(m_module_sp); 632 } 633 634 TEST_F(LocateModuleCallbackTest, 635 GetOrCreateModuleCallbackSuccessWithOnlyBreakpadSymbol) { 636 // The get callback returns only a breakpad symbol file, and the module is 637 // cached, GetOrCreateModule should succeed to return the module from the 638 // cache along with the symbol file from the Inputs directory. 639 FileSpec uuid_view = BuildCacheDir(m_test_dir); 640 641 int callback_call_count = 0; 642 m_platform_sp->SetLocateModuleCallback( 643 [this, &callback_call_count](const ModuleSpec &module_spec, 644 FileSpec &module_file_spec, 645 FileSpec &symbol_file_spec) { 646 CheckCallbackArgsWithUUID(module_spec, module_file_spec, 647 symbol_file_spec, ++callback_call_count); 648 symbol_file_spec.SetPath(GetInputFilePath(k_breakpad_symbol_file)); 649 return Status(); 650 }); 651 652 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false); 653 ASSERT_EQ(callback_call_count, 2); 654 CheckModule(m_module_sp); 655 ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view); 656 ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(), 657 FileSpec(GetInputFilePath(k_breakpad_symbol_file))); 658 CheckUnstrippedSymbol(m_module_sp); 659 ModuleList::RemoveSharedModule(m_module_sp); 660 } 661 662 TEST_F(LocateModuleCallbackTest, 663 GetOrCreateModuleCallbackSuccessWithMultipleSymbols) { 664 // The get callback returns only a symbol file. The first call returns 665 // a breakpad symbol file and the second call returns a symbol file. 666 // Also the module is cached, so GetOrCreateModule should succeed to return 667 // the module from the cache along with the breakpad symbol file from the 668 // Inputs directory because GetOrCreateModule will use the first symbol file 669 // from the callback. 670 FileSpec uuid_view = BuildCacheDir(m_test_dir); 671 672 int callback_call_count = 0; 673 m_platform_sp->SetLocateModuleCallback( 674 [this, &callback_call_count](const ModuleSpec &module_spec, 675 FileSpec &module_file_spec, 676 FileSpec &symbol_file_spec) { 677 CheckCallbackArgsWithUUID(module_spec, module_file_spec, 678 symbol_file_spec, ++callback_call_count); 679 symbol_file_spec.SetPath(GetInputFilePath( 680 callback_call_count == 1 ? k_breakpad_symbol_file : k_symbol_file)); 681 return Status(); 682 }); 683 684 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false); 685 ASSERT_EQ(callback_call_count, 2); 686 CheckModule(m_module_sp); 687 ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view); 688 ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(), 689 FileSpec(GetInputFilePath(k_breakpad_symbol_file))); 690 CheckUnstrippedSymbol(m_module_sp); 691 ModuleList::RemoveSharedModule(m_module_sp); 692 } 693 694 TEST_F(LocateModuleCallbackTest, 695 GetOrCreateModuleNoCacheWithCallbackOnlySymbol) { 696 // The get callback returns only a symbol file, but the module is not 697 // cached, GetOrCreateModule should fail because of the missing module. 698 BuildEmptyCacheDir(m_test_dir); 699 700 int callback_call_count = 0; 701 m_platform_sp->SetLocateModuleCallback( 702 [this, &callback_call_count](const ModuleSpec &module_spec, 703 FileSpec &module_file_spec, 704 FileSpec &symbol_file_spec) { 705 CheckCallbackArgsWithUUID(module_spec, module_file_spec, 706 symbol_file_spec, ++callback_call_count); 707 symbol_file_spec.SetPath(GetInputFilePath(k_symbol_file)); 708 return Status(); 709 }); 710 711 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false); 712 ASSERT_EQ(callback_call_count, 2); 713 ASSERT_FALSE(m_module_sp); 714 } 715 716 TEST_F(LocateModuleCallbackTest, 717 GetOrCreateModuleNoCacheWithCallbackOnlyBreakpadSymbol) { 718 // The get callback returns only a breakpad symbol file, but the module is not 719 // cached, GetOrCreateModule should fail because of the missing module. 720 BuildEmptyCacheDir(m_test_dir); 721 722 int callback_call_count = 0; 723 m_platform_sp->SetLocateModuleCallback( 724 [this, &callback_call_count](const ModuleSpec &module_spec, 725 FileSpec &module_file_spec, 726 FileSpec &symbol_file_spec) { 727 CheckCallbackArgsWithUUID(module_spec, module_file_spec, 728 symbol_file_spec, ++callback_call_count); 729 symbol_file_spec.SetPath(GetInputFilePath(k_breakpad_symbol_file)); 730 return Status(); 731 }); 732 733 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec, /*notify=*/false); 734 ASSERT_EQ(callback_call_count, 2); 735 ASSERT_FALSE(m_module_sp); 736 } 737 738 TEST_F(LocateModuleCallbackTest, 739 GetOrCreateModuleCallbackSuccessWithModuleByPlatformUUID) { 740 // This is a simulation for Android remote platform debugging. 741 // The locate module callback first call fails because module_spec does not 742 // have UUID. Then, the callback second call returns a module file because the 743 // platform resolved the module_spec UUID from the target process. 744 // GetOrCreateModule should succeed to return the module from the Inputs 745 // directory. 746 BuildEmptyCacheDir(m_test_dir); 747 748 int callback_call_count = 0; 749 m_platform_sp->SetLocateModuleCallback( 750 [this, &callback_call_count](const ModuleSpec &module_spec, 751 FileSpec &module_file_spec, 752 FileSpec &symbol_file_spec) { 753 callback_call_count++; 754 if (callback_call_count == 1) { 755 // The module_spec does not have UUID on the first call. 756 CheckCallbackArgsWithoutUUID(module_spec, module_file_spec, 757 symbol_file_spec, callback_call_count); 758 return Status::FromErrorString("Ignored empty UUID"); 759 } else { 760 // The module_spec has UUID on the second call. 761 CheckCallbackArgsWithUUID(module_spec, module_file_spec, 762 symbol_file_spec, callback_call_count); 763 module_file_spec.SetPath(GetInputFilePath(k_module_file)); 764 return Status(); 765 } 766 }); 767 768 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec_without_uuid, 769 /*notify=*/false); 770 ASSERT_EQ(callback_call_count, 2); 771 CheckModule(m_module_sp); 772 ASSERT_EQ(m_module_sp->GetFileSpec(), 773 FileSpec(GetInputFilePath(k_module_file))); 774 ASSERT_FALSE(m_module_sp->GetSymbolFileFileSpec()); 775 CheckStrippedSymbol(m_module_sp); 776 ModuleList::RemoveSharedModule(m_module_sp); 777 } 778 779 TEST_F(LocateModuleCallbackTest, 780 GetOrCreateModuleCallbackSuccessWithSymbolByPlatformUUID) { 781 // Same as GetOrCreateModuleCallbackSuccessWithModuleByPlatformUUID, 782 // but with a symbol file. GetOrCreateModule should succeed to return the 783 // module file and the symbol file from the Inputs directory. 784 BuildEmptyCacheDir(m_test_dir); 785 786 int callback_call_count = 0; 787 m_platform_sp->SetLocateModuleCallback( 788 [this, &callback_call_count](const ModuleSpec &module_spec, 789 FileSpec &module_file_spec, 790 FileSpec &symbol_file_spec) { 791 callback_call_count++; 792 if (callback_call_count == 1) { 793 // The module_spec does not have UUID on the first call. 794 CheckCallbackArgsWithoutUUID(module_spec, module_file_spec, 795 symbol_file_spec, callback_call_count); 796 return Status::FromErrorString("Ignored empty UUID"); 797 } else { 798 // The module_spec has UUID on the second call. 799 CheckCallbackArgsWithUUID(module_spec, module_file_spec, 800 symbol_file_spec, callback_call_count); 801 module_file_spec.SetPath(GetInputFilePath(k_module_file)); 802 symbol_file_spec.SetPath(GetInputFilePath(k_symbol_file)); 803 return Status(); 804 } 805 }); 806 807 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec_without_uuid, 808 /*notify=*/false); 809 ASSERT_EQ(callback_call_count, 2); 810 CheckModule(m_module_sp); 811 ASSERT_EQ(m_module_sp->GetFileSpec(), 812 FileSpec(GetInputFilePath(k_module_file))); 813 ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(), 814 FileSpec(GetInputFilePath(k_symbol_file))); 815 CheckUnstrippedSymbol(m_module_sp); 816 ModuleList::RemoveSharedModule(m_module_sp); 817 } 818 819 TEST_F(LocateModuleCallbackTest, 820 GetOrCreateModuleCallbackSuccessWithBreakpadSymbolByPlatformUUID) { 821 // Same as GetOrCreateModuleCallbackSuccessWithModuleByPlatformUUID, 822 // but with a breakpad symbol file. GetOrCreateModule should succeed to return 823 // the module file and the symbol file from the Inputs directory. 824 BuildEmptyCacheDir(m_test_dir); 825 826 int callback_call_count = 0; 827 m_platform_sp->SetLocateModuleCallback( 828 [this, &callback_call_count](const ModuleSpec &module_spec, 829 FileSpec &module_file_spec, 830 FileSpec &symbol_file_spec) { 831 callback_call_count++; 832 if (callback_call_count == 1) { 833 // The module_spec does not have UUID on the first call. 834 CheckCallbackArgsWithoutUUID(module_spec, module_file_spec, 835 symbol_file_spec, callback_call_count); 836 return Status::FromErrorString("Ignored empty UUID"); 837 } else { 838 // The module_spec has UUID on the second call. 839 CheckCallbackArgsWithUUID(module_spec, module_file_spec, 840 symbol_file_spec, callback_call_count); 841 module_file_spec.SetPath(GetInputFilePath(k_module_file)); 842 symbol_file_spec.SetPath(GetInputFilePath(k_breakpad_symbol_file)); 843 return Status(); 844 } 845 }); 846 847 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec_without_uuid, 848 /*notify=*/false); 849 ASSERT_EQ(callback_call_count, 2); 850 CheckModule(m_module_sp); 851 ASSERT_EQ(m_module_sp->GetFileSpec(), 852 FileSpec(GetInputFilePath(k_module_file))); 853 ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(), 854 FileSpec(GetInputFilePath(k_breakpad_symbol_file))); 855 CheckUnstrippedSymbol(m_module_sp); 856 ModuleList::RemoveSharedModule(m_module_sp); 857 } 858 859 TEST_F(LocateModuleCallbackTest, 860 GetOrCreateModuleCallbackSuccessWithOnlyBreakpadSymbolByPlatformUUID) { 861 // This is a simulation for Android remote platform debugging. 862 // The locate module callback first call fails because module_spec does not 863 // have UUID. Then, the callback second call returns a breakpad symbol file 864 // for the UUID from the target process. GetOrCreateModule should succeed to 865 // return the module from the cache along with the symbol file from the Inputs 866 // directory. 867 FileSpec uuid_view = BuildCacheDir(m_test_dir); 868 869 int callback_call_count = 0; 870 m_platform_sp->SetLocateModuleCallback( 871 [this, &callback_call_count](const ModuleSpec &module_spec, 872 FileSpec &module_file_spec, 873 FileSpec &symbol_file_spec) { 874 callback_call_count++; 875 if (callback_call_count == 1) { 876 // The module_spec does not have UUID on the first call. 877 CheckCallbackArgsWithoutUUID(module_spec, module_file_spec, 878 symbol_file_spec, callback_call_count); 879 return Status::FromErrorString("Ignored empty UUID"); 880 } else { 881 // The module_spec has UUID on the second call. 882 CheckCallbackArgsWithUUID(module_spec, module_file_spec, 883 symbol_file_spec, callback_call_count); 884 symbol_file_spec.SetPath(GetInputFilePath(k_breakpad_symbol_file)); 885 return Status(); 886 } 887 }); 888 889 m_module_sp = m_target_sp->GetOrCreateModule(m_module_spec_without_uuid, 890 /*notify=*/false); 891 ASSERT_EQ(callback_call_count, 2); 892 CheckModule(m_module_sp); 893 ASSERT_EQ(m_module_sp->GetFileSpec(), uuid_view); 894 ASSERT_EQ(m_module_sp->GetSymbolFileFileSpec(), 895 FileSpec(GetInputFilePath(k_breakpad_symbol_file))); 896 CheckUnstrippedSymbol(m_module_sp); 897 ModuleList::RemoveSharedModule(m_module_sp); 898 } 899