1//===-- SBPlatform.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 "lldb/API/SBPlatform.h" 10#include "lldb/API/SBDebugger.h" 11#include "lldb/API/SBEnvironment.h" 12#include "lldb/API/SBError.h" 13#include "lldb/API/SBFileSpec.h" 14#include "lldb/API/SBLaunchInfo.h" 15#include "lldb/API/SBModuleSpec.h" 16#include "lldb/API/SBPlatform.h" 17#include "lldb/API/SBProcessInfoList.h" 18#include "lldb/API/SBTarget.h" 19#include "lldb/API/SBUnixSignals.h" 20#include "lldb/Host/File.h" 21#include "lldb/Target/Platform.h" 22#include "lldb/Target/Target.h" 23#include "lldb/Utility/ArchSpec.h" 24#include "lldb/Utility/Args.h" 25#include "lldb/Utility/Instrumentation.h" 26#include "lldb/Utility/Status.h" 27 28#include "llvm/Support/FileSystem.h" 29 30#include <functional> 31 32using namespace lldb; 33using namespace lldb_private; 34 35// PlatformConnectOptions 36struct PlatformConnectOptions { 37 PlatformConnectOptions(const char *url = nullptr) { 38 if (url && url[0]) 39 m_url = url; 40 } 41 42 ~PlatformConnectOptions() = default; 43 44 std::string m_url; 45 std::string m_rsync_options; 46 std::string m_rsync_remote_path_prefix; 47 bool m_rsync_enabled = false; 48 bool m_rsync_omit_hostname_from_remote_path = false; 49 ConstString m_local_cache_directory; 50}; 51 52// PlatformShellCommand 53struct PlatformShellCommand { 54 PlatformShellCommand(llvm::StringRef shell_interpreter, 55 llvm::StringRef shell_command) { 56 if (!shell_interpreter.empty()) 57 m_shell = shell_interpreter.str(); 58 59 if (!m_shell.empty() && !shell_command.empty()) 60 m_command = shell_command.str(); 61 } 62 63 PlatformShellCommand(llvm::StringRef shell_command = llvm::StringRef()) { 64 if (!shell_command.empty()) 65 m_command = shell_command.str(); 66 } 67 68 ~PlatformShellCommand() = default; 69 70 std::string m_shell; 71 std::string m_command; 72 std::string m_working_dir; 73 std::string m_output; 74 int m_status = 0; 75 int m_signo = 0; 76 Timeout<std::ratio<1>> m_timeout = std::nullopt; 77}; 78// SBPlatformConnectOptions 79SBPlatformConnectOptions::SBPlatformConnectOptions(const char *url) 80 : m_opaque_ptr(new PlatformConnectOptions(url)) { 81 LLDB_INSTRUMENT_VA(this, url); 82} 83 84SBPlatformConnectOptions::SBPlatformConnectOptions( 85 const SBPlatformConnectOptions &rhs) 86 : m_opaque_ptr(new PlatformConnectOptions()) { 87 LLDB_INSTRUMENT_VA(this, rhs); 88 89 *m_opaque_ptr = *rhs.m_opaque_ptr; 90} 91 92SBPlatformConnectOptions::~SBPlatformConnectOptions() { delete m_opaque_ptr; } 93 94SBPlatformConnectOptions & 95SBPlatformConnectOptions::operator=(const SBPlatformConnectOptions &rhs) { 96 LLDB_INSTRUMENT_VA(this, rhs); 97 98 *m_opaque_ptr = *rhs.m_opaque_ptr; 99 return *this; 100} 101 102const char *SBPlatformConnectOptions::GetURL() { 103 LLDB_INSTRUMENT_VA(this); 104 105 if (m_opaque_ptr->m_url.empty()) 106 return nullptr; 107 return ConstString(m_opaque_ptr->m_url.c_str()).GetCString(); 108} 109 110void SBPlatformConnectOptions::SetURL(const char *url) { 111 LLDB_INSTRUMENT_VA(this, url); 112 113 if (url && url[0]) 114 m_opaque_ptr->m_url = url; 115 else 116 m_opaque_ptr->m_url.clear(); 117} 118 119bool SBPlatformConnectOptions::GetRsyncEnabled() { 120 LLDB_INSTRUMENT_VA(this); 121 122 return m_opaque_ptr->m_rsync_enabled; 123} 124 125void SBPlatformConnectOptions::EnableRsync( 126 const char *options, const char *remote_path_prefix, 127 bool omit_hostname_from_remote_path) { 128 LLDB_INSTRUMENT_VA(this, options, remote_path_prefix, 129 omit_hostname_from_remote_path); 130 131 m_opaque_ptr->m_rsync_enabled = true; 132 m_opaque_ptr->m_rsync_omit_hostname_from_remote_path = 133 omit_hostname_from_remote_path; 134 if (remote_path_prefix && remote_path_prefix[0]) 135 m_opaque_ptr->m_rsync_remote_path_prefix = remote_path_prefix; 136 else 137 m_opaque_ptr->m_rsync_remote_path_prefix.clear(); 138 139 if (options && options[0]) 140 m_opaque_ptr->m_rsync_options = options; 141 else 142 m_opaque_ptr->m_rsync_options.clear(); 143} 144 145void SBPlatformConnectOptions::DisableRsync() { 146 LLDB_INSTRUMENT_VA(this); 147 148 m_opaque_ptr->m_rsync_enabled = false; 149} 150 151const char *SBPlatformConnectOptions::GetLocalCacheDirectory() { 152 LLDB_INSTRUMENT_VA(this); 153 154 return m_opaque_ptr->m_local_cache_directory.GetCString(); 155} 156 157void SBPlatformConnectOptions::SetLocalCacheDirectory(const char *path) { 158 LLDB_INSTRUMENT_VA(this, path); 159 160 if (path && path[0]) 161 m_opaque_ptr->m_local_cache_directory.SetCString(path); 162 else 163 m_opaque_ptr->m_local_cache_directory = ConstString(); 164} 165 166// SBPlatformShellCommand 167SBPlatformShellCommand::SBPlatformShellCommand(const char *shell_interpreter, 168 const char *shell_command) 169 : m_opaque_ptr(new PlatformShellCommand(shell_interpreter, shell_command)) { 170 LLDB_INSTRUMENT_VA(this, shell_interpreter, shell_command); 171} 172 173SBPlatformShellCommand::SBPlatformShellCommand(const char *shell_command) 174 : m_opaque_ptr(new PlatformShellCommand(shell_command)) { 175 LLDB_INSTRUMENT_VA(this, shell_command); 176} 177 178SBPlatformShellCommand::SBPlatformShellCommand( 179 const SBPlatformShellCommand &rhs) 180 : m_opaque_ptr(new PlatformShellCommand()) { 181 LLDB_INSTRUMENT_VA(this, rhs); 182 183 *m_opaque_ptr = *rhs.m_opaque_ptr; 184} 185 186SBPlatformShellCommand & 187SBPlatformShellCommand::operator=(const SBPlatformShellCommand &rhs) { 188 189 LLDB_INSTRUMENT_VA(this, rhs); 190 191 *m_opaque_ptr = *rhs.m_opaque_ptr; 192 return *this; 193} 194 195SBPlatformShellCommand::~SBPlatformShellCommand() { delete m_opaque_ptr; } 196 197void SBPlatformShellCommand::Clear() { 198 LLDB_INSTRUMENT_VA(this); 199 200 m_opaque_ptr->m_output = std::string(); 201 m_opaque_ptr->m_status = 0; 202 m_opaque_ptr->m_signo = 0; 203} 204 205const char *SBPlatformShellCommand::GetShell() { 206 LLDB_INSTRUMENT_VA(this); 207 208 if (m_opaque_ptr->m_shell.empty()) 209 return nullptr; 210 return ConstString(m_opaque_ptr->m_shell.c_str()).GetCString(); 211} 212 213void SBPlatformShellCommand::SetShell(const char *shell_interpreter) { 214 LLDB_INSTRUMENT_VA(this, shell_interpreter); 215 216 if (shell_interpreter && shell_interpreter[0]) 217 m_opaque_ptr->m_shell = shell_interpreter; 218 else 219 m_opaque_ptr->m_shell.clear(); 220} 221 222const char *SBPlatformShellCommand::GetCommand() { 223 LLDB_INSTRUMENT_VA(this); 224 225 if (m_opaque_ptr->m_command.empty()) 226 return nullptr; 227 return ConstString(m_opaque_ptr->m_command.c_str()).GetCString(); 228} 229 230void SBPlatformShellCommand::SetCommand(const char *shell_command) { 231 LLDB_INSTRUMENT_VA(this, shell_command); 232 233 if (shell_command && shell_command[0]) 234 m_opaque_ptr->m_command = shell_command; 235 else 236 m_opaque_ptr->m_command.clear(); 237} 238 239const char *SBPlatformShellCommand::GetWorkingDirectory() { 240 LLDB_INSTRUMENT_VA(this); 241 242 if (m_opaque_ptr->m_working_dir.empty()) 243 return nullptr; 244 return ConstString(m_opaque_ptr->m_working_dir.c_str()).GetCString(); 245} 246 247void SBPlatformShellCommand::SetWorkingDirectory(const char *path) { 248 LLDB_INSTRUMENT_VA(this, path); 249 250 if (path && path[0]) 251 m_opaque_ptr->m_working_dir = path; 252 else 253 m_opaque_ptr->m_working_dir.clear(); 254} 255 256uint32_t SBPlatformShellCommand::GetTimeoutSeconds() { 257 LLDB_INSTRUMENT_VA(this); 258 259 if (m_opaque_ptr->m_timeout) 260 return m_opaque_ptr->m_timeout->count(); 261 return UINT32_MAX; 262} 263 264void SBPlatformShellCommand::SetTimeoutSeconds(uint32_t sec) { 265 LLDB_INSTRUMENT_VA(this, sec); 266 267 if (sec == UINT32_MAX) 268 m_opaque_ptr->m_timeout = std::nullopt; 269 else 270 m_opaque_ptr->m_timeout = std::chrono::seconds(sec); 271} 272 273int SBPlatformShellCommand::GetSignal() { 274 LLDB_INSTRUMENT_VA(this); 275 276 return m_opaque_ptr->m_signo; 277} 278 279int SBPlatformShellCommand::GetStatus() { 280 LLDB_INSTRUMENT_VA(this); 281 282 return m_opaque_ptr->m_status; 283} 284 285const char *SBPlatformShellCommand::GetOutput() { 286 LLDB_INSTRUMENT_VA(this); 287 288 if (m_opaque_ptr->m_output.empty()) 289 return nullptr; 290 return ConstString(m_opaque_ptr->m_output.c_str()).GetCString(); 291} 292 293// SBPlatform 294SBPlatform::SBPlatform() { LLDB_INSTRUMENT_VA(this); } 295 296SBPlatform::SBPlatform(const char *platform_name) { 297 LLDB_INSTRUMENT_VA(this, platform_name); 298 299 m_opaque_sp = Platform::Create(platform_name); 300} 301 302SBPlatform::SBPlatform(const SBPlatform &rhs) { 303 LLDB_INSTRUMENT_VA(this, rhs); 304 305 m_opaque_sp = rhs.m_opaque_sp; 306} 307 308SBPlatform &SBPlatform::operator=(const SBPlatform &rhs) { 309 LLDB_INSTRUMENT_VA(this, rhs); 310 311 m_opaque_sp = rhs.m_opaque_sp; 312 return *this; 313} 314 315SBPlatform::~SBPlatform() = default; 316 317SBPlatform SBPlatform::GetHostPlatform() { 318 LLDB_INSTRUMENT(); 319 320 SBPlatform host_platform; 321 host_platform.m_opaque_sp = Platform::GetHostPlatform(); 322 return host_platform; 323} 324 325bool SBPlatform::IsValid() const { 326 LLDB_INSTRUMENT_VA(this); 327 return this->operator bool(); 328} 329SBPlatform::operator bool() const { 330 LLDB_INSTRUMENT_VA(this); 331 332 return m_opaque_sp.get() != nullptr; 333} 334 335void SBPlatform::Clear() { 336 LLDB_INSTRUMENT_VA(this); 337 338 m_opaque_sp.reset(); 339} 340 341const char *SBPlatform::GetName() { 342 LLDB_INSTRUMENT_VA(this); 343 344 PlatformSP platform_sp(GetSP()); 345 if (platform_sp) 346 return ConstString(platform_sp->GetName()).AsCString(); 347 return nullptr; 348} 349 350lldb::PlatformSP SBPlatform::GetSP() const { return m_opaque_sp; } 351 352void SBPlatform::SetSP(const lldb::PlatformSP &platform_sp) { 353 m_opaque_sp = platform_sp; 354} 355 356const char *SBPlatform::GetWorkingDirectory() { 357 LLDB_INSTRUMENT_VA(this); 358 359 PlatformSP platform_sp(GetSP()); 360 if (platform_sp) 361 return platform_sp->GetWorkingDirectory().GetPathAsConstString().AsCString(); 362 return nullptr; 363} 364 365bool SBPlatform::SetWorkingDirectory(const char *path) { 366 LLDB_INSTRUMENT_VA(this, path); 367 368 PlatformSP platform_sp(GetSP()); 369 if (platform_sp) { 370 if (path) 371 platform_sp->SetWorkingDirectory(FileSpec(path)); 372 else 373 platform_sp->SetWorkingDirectory(FileSpec()); 374 return true; 375 } 376 return false; 377} 378 379SBError SBPlatform::ConnectRemote(SBPlatformConnectOptions &connect_options) { 380 LLDB_INSTRUMENT_VA(this, connect_options); 381 382 SBError sb_error; 383 PlatformSP platform_sp(GetSP()); 384 if (platform_sp && connect_options.GetURL()) { 385 Args args; 386 args.AppendArgument(connect_options.GetURL()); 387 sb_error.ref() = platform_sp->ConnectRemote(args); 388 } else { 389 sb_error.SetErrorString("invalid platform"); 390 } 391 return sb_error; 392} 393 394void SBPlatform::DisconnectRemote() { 395 LLDB_INSTRUMENT_VA(this); 396 397 PlatformSP platform_sp(GetSP()); 398 if (platform_sp) 399 platform_sp->DisconnectRemote(); 400} 401 402bool SBPlatform::IsConnected() { 403 LLDB_INSTRUMENT_VA(this); 404 405 PlatformSP platform_sp(GetSP()); 406 if (platform_sp) 407 return platform_sp->IsConnected(); 408 return false; 409} 410 411const char *SBPlatform::GetTriple() { 412 LLDB_INSTRUMENT_VA(this); 413 414 PlatformSP platform_sp(GetSP()); 415 if (platform_sp) { 416 ArchSpec arch(platform_sp->GetSystemArchitecture()); 417 if (arch.IsValid()) { 418 // Const-ify the string so we don't need to worry about the lifetime of 419 // the string 420 return ConstString(arch.GetTriple().getTriple().c_str()).GetCString(); 421 } 422 } 423 return nullptr; 424} 425 426const char *SBPlatform::GetOSBuild() { 427 LLDB_INSTRUMENT_VA(this); 428 429 PlatformSP platform_sp(GetSP()); 430 if (platform_sp) { 431 std::string s = platform_sp->GetOSBuildString().value_or(""); 432 if (!s.empty()) { 433 // Const-ify the string so we don't need to worry about the lifetime of 434 // the string 435 return ConstString(s).GetCString(); 436 } 437 } 438 return nullptr; 439} 440 441const char *SBPlatform::GetOSDescription() { 442 LLDB_INSTRUMENT_VA(this); 443 444 PlatformSP platform_sp(GetSP()); 445 if (platform_sp) { 446 std::string s = platform_sp->GetOSKernelDescription().value_or(""); 447 if (!s.empty()) { 448 // Const-ify the string so we don't need to worry about the lifetime of 449 // the string 450 return ConstString(s.c_str()).GetCString(); 451 } 452 } 453 return nullptr; 454} 455 456const char *SBPlatform::GetHostname() { 457 LLDB_INSTRUMENT_VA(this); 458 459 PlatformSP platform_sp(GetSP()); 460 if (platform_sp) 461 return ConstString(platform_sp->GetHostname()).GetCString(); 462 return nullptr; 463} 464 465uint32_t SBPlatform::GetOSMajorVersion() { 466 LLDB_INSTRUMENT_VA(this); 467 468 llvm::VersionTuple version; 469 if (PlatformSP platform_sp = GetSP()) 470 version = platform_sp->GetOSVersion(); 471 return version.empty() ? UINT32_MAX : version.getMajor(); 472} 473 474uint32_t SBPlatform::GetOSMinorVersion() { 475 LLDB_INSTRUMENT_VA(this); 476 477 llvm::VersionTuple version; 478 if (PlatformSP platform_sp = GetSP()) 479 version = platform_sp->GetOSVersion(); 480 return version.getMinor().value_or(UINT32_MAX); 481} 482 483uint32_t SBPlatform::GetOSUpdateVersion() { 484 LLDB_INSTRUMENT_VA(this); 485 486 llvm::VersionTuple version; 487 if (PlatformSP platform_sp = GetSP()) 488 version = platform_sp->GetOSVersion(); 489 return version.getSubminor().value_or(UINT32_MAX); 490} 491 492void SBPlatform::SetSDKRoot(const char *sysroot) { 493 LLDB_INSTRUMENT_VA(this, sysroot); 494 if (PlatformSP platform_sp = GetSP()) 495 platform_sp->SetSDKRootDirectory(llvm::StringRef(sysroot).str()); 496} 497 498SBError SBPlatform::Get(SBFileSpec &src, SBFileSpec &dst) { 499 LLDB_INSTRUMENT_VA(this, src, dst); 500 501 SBError sb_error; 502 PlatformSP platform_sp(GetSP()); 503 if (platform_sp) { 504 sb_error.ref() = platform_sp->GetFile(src.ref(), dst.ref()); 505 } else { 506 sb_error.SetErrorString("invalid platform"); 507 } 508 return sb_error; 509} 510 511SBError SBPlatform::Put(SBFileSpec &src, SBFileSpec &dst) { 512 LLDB_INSTRUMENT_VA(this, src, dst); 513 return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) { 514 if (src.Exists()) { 515 uint32_t permissions = FileSystem::Instance().GetPermissions(src.ref()); 516 if (permissions == 0) { 517 if (FileSystem::Instance().IsDirectory(src.ref())) 518 permissions = eFilePermissionsDirectoryDefault; 519 else 520 permissions = eFilePermissionsFileDefault; 521 } 522 523 return platform_sp->PutFile(src.ref(), dst.ref(), permissions); 524 } 525 526 Status error; 527 error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", 528 src.ref().GetPath().c_str()); 529 return error; 530 }); 531} 532 533SBError SBPlatform::Install(SBFileSpec &src, SBFileSpec &dst) { 534 LLDB_INSTRUMENT_VA(this, src, dst); 535 return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) { 536 if (src.Exists()) 537 return platform_sp->Install(src.ref(), dst.ref()); 538 539 Status error; 540 error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", 541 src.ref().GetPath().c_str()); 542 return error; 543 }); 544} 545 546SBError SBPlatform::Run(SBPlatformShellCommand &shell_command) { 547 LLDB_INSTRUMENT_VA(this, shell_command); 548 return ExecuteConnected( 549 [&](const lldb::PlatformSP &platform_sp) { 550 const char *command = shell_command.GetCommand(); 551 if (!command) 552 return Status("invalid shell command (empty)"); 553 554 if (shell_command.GetWorkingDirectory() == nullptr) { 555 std::string platform_working_dir = 556 platform_sp->GetWorkingDirectory().GetPath(); 557 if (!platform_working_dir.empty()) 558 shell_command.SetWorkingDirectory(platform_working_dir.c_str()); 559 } 560 return platform_sp->RunShellCommand( 561 shell_command.m_opaque_ptr->m_shell, command, 562 FileSpec(shell_command.GetWorkingDirectory()), 563 &shell_command.m_opaque_ptr->m_status, 564 &shell_command.m_opaque_ptr->m_signo, 565 &shell_command.m_opaque_ptr->m_output, 566 shell_command.m_opaque_ptr->m_timeout); 567 }); 568} 569 570SBError SBPlatform::Launch(SBLaunchInfo &launch_info) { 571 LLDB_INSTRUMENT_VA(this, launch_info); 572 return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) { 573 ProcessLaunchInfo info = launch_info.ref(); 574 Status error = platform_sp->LaunchProcess(info); 575 launch_info.set_ref(info); 576 return error; 577 }); 578} 579 580SBProcess SBPlatform::Attach(SBAttachInfo &attach_info, 581 const SBDebugger &debugger, SBTarget &target, 582 SBError &error) { 583 LLDB_INSTRUMENT_VA(this, attach_info, debugger, target, error); 584 585 if (PlatformSP platform_sp = GetSP()) { 586 if (platform_sp->IsConnected()) { 587 ProcessAttachInfo &info = attach_info.ref(); 588 Status status; 589 ProcessSP process_sp = platform_sp->Attach(info, debugger.ref(), 590 target.GetSP().get(), status); 591 error.SetError(status); 592 return SBProcess(process_sp); 593 } 594 595 error.SetErrorString("not connected"); 596 return {}; 597 } 598 599 error.SetErrorString("invalid platform"); 600 return {}; 601} 602 603SBProcessInfoList SBPlatform::GetAllProcesses(SBError &error) { 604 if (PlatformSP platform_sp = GetSP()) { 605 if (platform_sp->IsConnected()) { 606 ProcessInstanceInfoList list = platform_sp->GetAllProcesses(); 607 return SBProcessInfoList(list); 608 } 609 error.SetErrorString("not connected"); 610 return {}; 611 } 612 613 error.SetErrorString("invalid platform"); 614 return {}; 615} 616 617SBError SBPlatform::Kill(const lldb::pid_t pid) { 618 LLDB_INSTRUMENT_VA(this, pid); 619 return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) { 620 return platform_sp->KillProcess(pid); 621 }); 622} 623 624SBError SBPlatform::ExecuteConnected( 625 const std::function<Status(const lldb::PlatformSP &)> &func) { 626 SBError sb_error; 627 const auto platform_sp(GetSP()); 628 if (platform_sp) { 629 if (platform_sp->IsConnected()) 630 sb_error.ref() = func(platform_sp); 631 else 632 sb_error.SetErrorString("not connected"); 633 } else 634 sb_error.SetErrorString("invalid platform"); 635 636 return sb_error; 637} 638 639SBError SBPlatform::MakeDirectory(const char *path, uint32_t file_permissions) { 640 LLDB_INSTRUMENT_VA(this, path, file_permissions); 641 642 SBError sb_error; 643 PlatformSP platform_sp(GetSP()); 644 if (platform_sp) { 645 sb_error.ref() = 646 platform_sp->MakeDirectory(FileSpec(path), file_permissions); 647 } else { 648 sb_error.SetErrorString("invalid platform"); 649 } 650 return sb_error; 651} 652 653uint32_t SBPlatform::GetFilePermissions(const char *path) { 654 LLDB_INSTRUMENT_VA(this, path); 655 656 PlatformSP platform_sp(GetSP()); 657 if (platform_sp) { 658 uint32_t file_permissions = 0; 659 platform_sp->GetFilePermissions(FileSpec(path), file_permissions); 660 return file_permissions; 661 } 662 return 0; 663} 664 665SBError SBPlatform::SetFilePermissions(const char *path, 666 uint32_t file_permissions) { 667 LLDB_INSTRUMENT_VA(this, path, file_permissions); 668 669 SBError sb_error; 670 PlatformSP platform_sp(GetSP()); 671 if (platform_sp) { 672 sb_error.ref() = 673 platform_sp->SetFilePermissions(FileSpec(path), file_permissions); 674 } else { 675 sb_error.SetErrorString("invalid platform"); 676 } 677 return sb_error; 678} 679 680SBUnixSignals SBPlatform::GetUnixSignals() const { 681 LLDB_INSTRUMENT_VA(this); 682 683 if (auto platform_sp = GetSP()) 684 return SBUnixSignals{platform_sp}; 685 686 return SBUnixSignals(); 687} 688 689SBEnvironment SBPlatform::GetEnvironment() { 690 LLDB_INSTRUMENT_VA(this); 691 PlatformSP platform_sp(GetSP()); 692 693 if (platform_sp) { 694 return SBEnvironment(platform_sp->GetEnvironment()); 695 } 696 697 return SBEnvironment(); 698} 699 700SBError SBPlatform::SetLocateModuleCallback( 701 lldb::SBPlatformLocateModuleCallback callback, void *callback_baton) { 702 LLDB_INSTRUMENT_VA(this, callback, callback_baton); 703 PlatformSP platform_sp(GetSP()); 704 if (!platform_sp) 705 return SBError("invalid platform"); 706 707 if (!callback) { 708 // Clear the callback. 709 platform_sp->SetLocateModuleCallback(nullptr); 710 return SBError(); 711 } 712 713 // Platform.h does not accept lldb::SBPlatformLocateModuleCallback directly 714 // because of the SBModuleSpec and SBFileSpec dependencies. Use a lambda to 715 // convert ModuleSpec/FileSpec <--> SBModuleSpec/SBFileSpec for the callback 716 // arguments. 717 platform_sp->SetLocateModuleCallback( 718 [callback, callback_baton](const ModuleSpec &module_spec, 719 FileSpec &module_file_spec, 720 FileSpec &symbol_file_spec) { 721 SBModuleSpec module_spec_sb(module_spec); 722 SBFileSpec module_file_spec_sb; 723 SBFileSpec symbol_file_spec_sb; 724 725 SBError error = callback(callback_baton, module_spec_sb, 726 module_file_spec_sb, symbol_file_spec_sb); 727 728 if (error.Success()) { 729 module_file_spec = module_file_spec_sb.ref(); 730 symbol_file_spec = symbol_file_spec_sb.ref(); 731 } 732 733 return error.ref(); 734 }); 735 return SBError(); 736} 737