brintos

brintos / llvm-project-archived public Read only

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