Example #1
0
void
handle_attach_to_pid (GDBRemoteCommunicationServerLLGS &gdb_server, lldb::pid_t pid)
{
    Error error = gdb_server.AttachToProcess (pid);
    if (error.Fail ())
    {
        fprintf (stderr, "error: failed to attach to pid %" PRIu64 ": %s\n", pid, error.AsCString());
        exit(1);
    }
}
Error
PlatformRemoteGDBServer::MakeDirectory(const FileSpec &file_spec, uint32_t mode)
{
    Error error = m_gdb_client.MakeDirectory(file_spec, mode);
    Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
    if (log)
        log->Printf ("PlatformRemoteGDBServer::MakeDirectory(path='%s', mode=%o) error = %u (%s)",
                file_spec.GetCString(), mode, error.GetError(), error.AsCString());
    return error;
}
Error
PlatformRemoteGDBServer::Unlink(const FileSpec &file_spec)
{
    Error error = m_gdb_client.Unlink(file_spec);
    Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
    if (log)
        log->Printf ("PlatformRemoteGDBServer::Unlink(path='%s') error = %u (%s)",
                file_spec.GetCString(), error.GetError(), error.AsCString());
    return error;
}
Error
PlatformRemoteGDBServer::SetFilePermissions(const FileSpec &file_spec,
                                            uint32_t file_permissions)
{
    Error error = m_gdb_client.SetFilePermissions(file_spec, file_permissions);
    Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
    if (log)
        log->Printf ("PlatformRemoteGDBServer::SetFilePermissions(path='%s', file_permissions=%o) error = %u (%s)",
                file_spec.GetCString(), file_permissions, error.GetError(), error.AsCString());
    return error;
}
Example #5
0
lldb::ExpressionResults
GoUserExpression::DoExecute(DiagnosticManager &diagnostic_manager,
                            ExecutionContext &exe_ctx,
                            const EvaluateExpressionOptions &options,
                            lldb::UserExpressionSP &shared_ptr_to_me,
                            lldb::ExpressionVariableSP &result) {
  Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS |
                                                  LIBLLDB_LOG_STEP));

  lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
  lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;

  Process *process = exe_ctx.GetProcessPtr();
  Target *target = exe_ctx.GetTargetPtr();

  if (target == nullptr || process == nullptr ||
      process->GetState() != lldb::eStateStopped) {
    if (execution_policy == eExecutionPolicyAlways) {
      if (log)
        log->Printf("== [GoUserExpression::Evaluate] Expression may not run, "
                    "but is not constant ==");

      diagnostic_manager.PutCString(eDiagnosticSeverityError,
                                    "expression needed to run but couldn't");

      return execution_results;
    }
  }

  m_interpreter->set_use_dynamic(options.GetUseDynamic());
  ValueObjectSP result_val_sp = m_interpreter->Evaluate(exe_ctx);
  Error err = m_interpreter->error();
  m_interpreter.reset();

  if (!result_val_sp) {
    const char *error_cstr = err.AsCString();
    if (error_cstr && error_cstr[0])
      diagnostic_manager.PutCString(eDiagnosticSeverityError, error_cstr);
    else
      diagnostic_manager.PutCString(eDiagnosticSeverityError,
                                    "expression can't be interpreted or run");
    return lldb::eExpressionDiscarded;
  }
  result.reset(new ExpressionVariable(ExpressionVariable::eKindGo));
  result->m_live_sp = result->m_frozen_sp = result_val_sp;
  result->m_flags |= ExpressionVariable::EVIsProgramReference;
  PersistentExpressionState *pv =
      target->GetPersistentExpressionStateForLanguage(eLanguageTypeGo);
  if (pv != nullptr) {
    result->SetName(pv->GetNextPersistentVariableName());
    pv->AddVariable(result);
  }
  return lldb::eExpressionCompleted;
}
size_t
GDBRemoteCommunication::WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractorGDBRemote &packet, uint32_t timeout_usec)
{
    uint8_t buffer[8192];
    Error error;

    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE));

    // Check for a packet from our cache first without trying any reading...
    if (CheckForPacket (NULL, 0, packet))
        return packet.GetStringRef().size();

    bool timed_out = false;
    while (IsConnected() && !timed_out)
    {
        lldb::ConnectionStatus status = eConnectionStatusNoConnection;
        size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error);
        
        if (log)
            log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %" PRIu64,
                         __PRETTY_FUNCTION__,
                         timeout_usec, 
                         Communication::ConnectionStatusAsCString (status),
                         error.AsCString(), 
                         (uint64_t)bytes_read);

        if (bytes_read > 0)
        {
            if (CheckForPacket (buffer, bytes_read, packet))
                return packet.GetStringRef().size();
        }
        else
        {
            switch (status)
            {
            case eConnectionStatusTimedOut:
                timed_out = true;
                break;
            case eConnectionStatusSuccess:
                //printf ("status = success but error = %s\n", error.AsCString("<invalid>"));
                break;
                
            case eConnectionStatusEndOfFile:
            case eConnectionStatusNoConnection:
            case eConnectionStatusLostConnection:
            case eConnectionStatusError:
                Disconnect();
                break;
            }
        }
    }
    packet.Clear ();    
    return 0;
}
Error
PlatformRemoteGDBServer::CreateSymlink(const FileSpec &src,    // The name of the link is in src
                                       const FileSpec &dst)    // The symlink points to dst
{
    Error error = m_gdb_client.CreateSymlink(src, dst);
    Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
    if (log)
        log->Printf ("PlatformRemoteGDBServer::CreateSymlink(src='%s', dst='%s') error = %u (%s)",
                src.GetCString(), dst.GetCString(), error.GetError(), error.AsCString());
    return error;
}
Example #8
0
Error
ProcessWindows::DoAttachToProcessWithID(lldb::pid_t pid, const ProcessAttachInfo &attach_info)
{
    m_session_data.reset(new ProcessWindowsData(!attach_info.GetContinueOnceAttached()));

    DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this()));
    DebuggerThreadSP debugger(new DebuggerThread(delegate));

    m_session_data->m_debugger = debugger;

    DWORD process_id = static_cast<DWORD>(pid);
    Error error = debugger->DebugAttach(process_id, attach_info);
    if (error.Fail())
    {
        WINLOG_IFALL(WINDOWS_LOG_PROCESS,
                     "DoAttachToProcessWithID encountered an error occurred initiating the asynchronous attach.  %s",
                     error.AsCString());
        return error;
    }

    HostProcess process;
    error = WaitForDebuggerConnection(debugger, process);
    if (error.Fail())
    {
        WINLOG_IFALL(WINDOWS_LOG_PROCESS,
                     "DoAttachToProcessWithID encountered an error waiting for the debugger to connect.  %s",
                     error.AsCString());
        return error;
    }

    WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoAttachToProcessWithID successfully attached to process with pid=%u",
                 process_id);

    // We've hit the initial stop.  If eLaunchFlagsStopAtEntry was specified, the private state
    // should already be set to eStateStopped as a result of hitting the initial breakpoint.  If
    // it was not set, the breakpoint should have already been resumed from and the private state
    // should already be eStateRunning.
    SetID(process.GetProcessId());
    return error;
}
lldb::ProcessSP PlatformRemoteGDBServer::DebugProcess(
    ProcessLaunchInfo &launch_info, Debugger &debugger,
    Target *target, // Can be NULL, if NULL create a new target, else use
                    // existing one
    Error &error) {
  lldb::ProcessSP process_sp;
  if (IsRemote()) {
    if (IsConnected()) {
      lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
      std::string connect_url;
      if (!LaunchGDBServer(debugserver_pid, connect_url)) {
        error.SetErrorStringWithFormat("unable to launch a GDB server on '%s'",
                                       GetHostname());
      } else {
        if (target == NULL) {
          TargetSP new_target_sp;

          error = debugger.GetTargetList().CreateTarget(
              debugger, NULL, NULL, false, NULL, new_target_sp);
          target = new_target_sp.get();
        } else
          error.Clear();

        if (target && error.Success()) {
          debugger.GetTargetList().SetSelectedTarget(target);

          // The darwin always currently uses the GDB remote debugger plug-in
          // so even when debugging locally we are debugging remotely!
          process_sp = target->CreateProcess(
              launch_info.GetListenerForProcess(debugger), "gdb-remote", NULL);

          if (process_sp) {
            error = process_sp->ConnectRemote(nullptr, connect_url.c_str());
            // Retry the connect remote one time...
            if (error.Fail())
              error = process_sp->ConnectRemote(nullptr, connect_url.c_str());
            if (error.Success())
              error = process_sp->Launch(launch_info);
            else if (debugserver_pid != LLDB_INVALID_PROCESS_ID) {
              printf("error: connect remote failed (%s)\n", error.AsCString());
              KillSpawnedProcess(debugserver_pid);
            }
          }
        }
      }
    } else {
      error.SetErrorString("not connected to remote gdb server");
    }
  }
  return process_sp;
}
Error OptionValueProperties::SetSubValue(const ExecutionContext *exe_ctx,
                                         VarSetOperationType op,
                                         llvm::StringRef name, llvm::StringRef value) {
  Error error;
  const bool will_modify = true;
  lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, name, will_modify, error));
  if (value_sp)
    error = value_sp->SetValueFromString(value, op);
  else {
    if (error.AsCString() == nullptr)
      error.SetErrorStringWithFormat("invalid value path '%s'", name.str().c_str());
  }
  return error;
}
Example #11
0
Error
ProcessWindows::EnableBreakpointSite(BreakpointSite *bp_site)
{
    WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS, "EnableBreakpointSite called with bp_site 0x%p "
                                          "(id=%d, addr=0x%x)",
                 bp_site->GetID(), bp_site->GetLoadAddress());

    Error error = EnableSoftwareBreakpoint(bp_site);
    if (!error.Success())
    {
        WINERR_IFALL(WINDOWS_LOG_BREAKPOINTS, "EnableBreakpointSite failed.  %s", error.AsCString());
    }
    return error;
}
Example #12
0
size_t
Disassembler::ParseInstructions (const ExecutionContext *exe_ctx,
                                 const AddressRange &range,
                                 Stream *error_strm_ptr,
                                 bool prefer_file_cache)
{
    if (exe_ctx)
    {
        Target *target = exe_ctx->GetTargetPtr();
        const addr_t byte_size = range.GetByteSize();
        if (target == NULL || byte_size == 0 || !range.GetBaseAddress().IsValid())
            return 0;

        DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
        DataBufferSP data_sp(heap_buffer);

        Error error;
        lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
        const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(),
                                                      prefer_file_cache, 
                                                      heap_buffer->GetBytes(), 
                                                      heap_buffer->GetByteSize(), 
                                                      error,
                                                      &load_addr);
        
        if (bytes_read > 0)
        {
            if (bytes_read != heap_buffer->GetByteSize())
                heap_buffer->SetByteSize (bytes_read);
            DataExtractor data (data_sp, 
                                m_arch.GetByteOrder(),
                                m_arch.GetAddressByteSize());
            const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
            return DecodeInstructions (range.GetBaseAddress(), data, 0, UINT32_MAX, false, data_from_file);
        }
        else if (error_strm_ptr)
        {
            const char *error_cstr = error.AsCString();
            if (error_cstr)
            {
                error_strm_ptr->Printf("error: %s\n", error_cstr);
            }
        }
    }
    else if (error_strm_ptr)
    {
        error_strm_ptr->PutCString("error: invalid execution context\n");
    }
    return 0;
}
Example #13
0
Error MachException::Message::Receive(mach_port_t port,
                                      mach_msg_option_t options,
                                      mach_msg_timeout_t timeout,
                                      mach_port_t notify_port) {
  Error error;
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));

  mach_msg_timeout_t mach_msg_timeout =
      options & MACH_RCV_TIMEOUT ? timeout : 0;
  if (log && ((options & MACH_RCV_TIMEOUT) == 0)) {
    // Dump this log message if we have no timeout in case it never returns
    log->Printf("::mach_msg(msg->{bits = %#x, size = %u remote_port = %#x, "
                "local_port = %#x, reserved = 0x%x, id = 0x%x}, "
                "option = %#x, send_size = 0, rcv_size = %llu, "
                "rcv_name = %#x, timeout = %u, notify = %#x)",
                exc_msg.hdr.msgh_bits, exc_msg.hdr.msgh_size,
                exc_msg.hdr.msgh_remote_port, exc_msg.hdr.msgh_local_port,
                exc_msg.hdr.msgh_reserved, exc_msg.hdr.msgh_id, options,
                (uint64_t)sizeof(exc_msg.data), port, mach_msg_timeout,
                notify_port);
  }

  mach_msg_return_t mach_err =
      ::mach_msg(&exc_msg.hdr,
                 options,              // options
                 0,                    // Send size
                 sizeof(exc_msg.data), // Receive size
                 port,                 // exception port to watch for
                                       // exception on
                 mach_msg_timeout,     // timeout in msec (obeyed only
                                       // if MACH_RCV_TIMEOUT is ORed
                                       // into the options parameter)
                 notify_port);
  error.SetError(mach_err, eErrorTypeMachKernel);

  // Dump any errors we get
  if (error.Fail() && log) {
    log->Printf("::mach_msg(msg->{bits = %#x, size = %u remote_port = %#x, "
                "local_port = %#x, reserved = 0x%x, id = 0x%x}, "
                "option = %#x, send_size = %u, rcv_size = %lu, rcv_name "
                "= %#x, timeout = %u, notify = %#x) failed: %s",
                exc_msg.hdr.msgh_bits, exc_msg.hdr.msgh_size,
                exc_msg.hdr.msgh_remote_port, exc_msg.hdr.msgh_local_port,
                exc_msg.hdr.msgh_reserved, exc_msg.hdr.msgh_id, options, 0,
                sizeof(exc_msg.data), port, mach_msg_timeout, notify_port,
                error.AsCString());
  }
  return error;
}
Example #14
0
bool
CommandObject::ParseOptions
(
    Args& args,
    CommandReturnObject &result
)
{
    // See if the subclass has options?
    Options *options = GetOptions();
    if (options != NULL)
    {
        Error error;
        options->NotifyOptionParsingStarting();

        // ParseOptions calls getopt_long, which always skips the zero'th item in the array and starts at position 1,
        // so we need to push a dummy value into position zero.
        args.Unshift("dummy_string");
        error = args.ParseOptions (*options);

        // The "dummy_string" will have already been removed by ParseOptions,
        // so no need to remove it.

        if (error.Success())
            error = options->NotifyOptionParsingFinished();

        if (error.Success())
        {
            if (options->VerifyOptions (result))
                return true;
        }
        else
        {
            const char *error_cstr = error.AsCString();
            if (error_cstr)
            {
                // We got an error string, lets use that
                result.AppendError(error_cstr);
            }
            else
            {
                // No error string, output the usage information into result
                options->GenerateOptionUsage (result.GetErrorStream(), this);
            }
        }
        result.SetStatus (eReturnStatusFailed);
        return false;
    }
    return true;
}
Example #15
0
void
ProcessWindows::OnDebuggerError(const Error &error, uint32_t type)
{
    llvm::sys::ScopedLock lock(m_mutex);

    if (m_session_data->m_initial_stop_received)
    {
        // This happened while debugging.  Do we shutdown the debugging session, try to continue,
        // or do something else?
        WINERR_IFALL(WINDOWS_LOG_PROCESS, "Error %u occurred during debugging.  Unexpected behavior may result.  %s",
                     error.GetError(), error.AsCString());
    }
    else
    {
        // If we haven't actually launched the process yet, this was an error launching the
        // process.  Set the internal error and signal the initial stop event so that the DoLaunch
        // method wakes up and returns a failure.
        m_session_data->m_launch_error = error;
        ::SetEvent(m_session_data->m_initial_stop_event);
        WINERR_IFALL(WINDOWS_LOG_PROCESS, "Error %u occurred launching the process before the initial stop.  %s",
                     error.GetError(), error.AsCString());
        return;
    }
}
Example #16
0
Error
OptionValueDictionary::SetSubValue (const ExecutionContext *exe_ctx, VarSetOperationType op, const char *name, const char *value)
{
    Error error;
    const bool will_modify = true;
    lldb::OptionValueSP value_sp (GetSubValue (exe_ctx, name, will_modify, error));
    if (value_sp)
        error = value_sp->SetValueFromString(value, op);
    else
    {
        if (error.AsCString() == nullptr)
            error.SetErrorStringWithFormat("invalid value path '%s'", name);
    }
    return error;
}
Example #17
0
Error
DebuggerThread::DebugAttach(lldb::pid_t pid, const ProcessAttachInfo &attach_info)
{
    WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DebuggerThread::DebugAttach attaching to '%u'", (DWORD)pid);

    Error error;
    DebugAttachContext *context = new DebugAttachContext(this, pid, attach_info);
    HostThread slave_thread(ThreadLauncher::LaunchThread("lldb.plugin.process-windows.slave[?]",
                                                         DebuggerThreadAttachRoutine, context, &error));

    if (!error.Success())
    {
        WINERR_IFALL(WINDOWS_LOG_PROCESS, "DebugAttach couldn't attach to process '%u'.  %s", (DWORD)pid,
                     error.AsCString());
    }

    return error;
}
Example #18
0
Error
DebuggerThread::DebugLaunch(const ProcessLaunchInfo &launch_info)
{
    WINLOG_IFALL(WINDOWS_LOG_PROCESS,
        "DebuggerThread::DebugLaunch launching '%s'", launch_info.GetExecutableFile().GetPath().c_str());

    Error error;
    DebugLaunchContext *context = new DebugLaunchContext(this, launch_info);
    HostThread slave_thread(ThreadLauncher::LaunchThread("lldb.plugin.process-windows.slave[?]",
                                                         DebuggerThreadLaunchRoutine, context, &error));

    if (!error.Success())
    {
        WINERR_IFALL(WINDOWS_LOG_PROCESS,
            "DebugLaunch couldn't launch debugger thread.  %s", error.AsCString());
    }

    return error;
}
Example #19
0
Error Socket::Write (const void *buf, size_t &num_bytes)
{
    Error error;
    int bytes_sent = 0;
    do
    {
        if (m_protocol == ProtocolUdp)
        {
            bytes_sent = ::sendto (m_socket, 
                                    static_cast<const char*>(buf), 
                                    num_bytes, 
                                    0, 
                                    m_udp_send_sockaddr,
                                    m_udp_send_sockaddr.GetLength());
        }
        else
            bytes_sent = ::send (m_socket, static_cast<const char *>(buf), num_bytes, 0);
    } while (bytes_sent < 0 && IsInterrupted ());

    if (bytes_sent < 0)
    {
        SetLastError (error);
        num_bytes = 0;
    }
    else
        num_bytes = bytes_sent;

    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION));
    if (log)
    {
        log->Printf ("%p Socket::Write() (socket = %" PRIu64 ", src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 " (error = %s)",
                        static_cast<void*>(this), 
                        static_cast<uint64_t>(m_socket),
                        buf,
                        static_cast<uint64_t>(num_bytes),
                        static_cast<int64_t>(bytes_sent),
                        error.AsCString());
    }

    return error;
}
Example #20
0
void
ConnectionFileDescriptor::OpenCommandPipe()
{
    CloseCommandPipe();

    Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
    // Make the command file descriptor here:
    Error result = m_pipe.CreateNew(m_child_processes_inherit);
    if (!result.Success())
    {
        if (log)
            log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe () - could not make pipe: %s", static_cast<void *>(this),
                        result.AsCString());
    }
    else
    {
        if (log)
            log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe() - success readfd=%d writefd=%d", static_cast<void *>(this),
                        m_pipe.GetReadFileDescriptor(), m_pipe.GetWriteFileDescriptor());
    }
}
Example #21
0
Error MachException::PortInfo::Restore(task_t task) {
  Error error;

  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));

  if (log)
    log->Printf("MachException::PortInfo::Restore(task = 0x%4.4x)", task);

  uint32_t i = 0;
  if (count > 0) {
    for (i = 0; i < count; i++) {
      auto mach_err = ::task_set_exception_ports(task, masks[i], ports[i],
                                                 behaviors[i], flavors[i]);
      if (mach_err)
        error.SetError(mach_err, eErrorTypeMachKernel);
      if (log) {
        if (error.Success()) {
          log->Printf("::task_set_exception_ports(task = 0x%4.4x, "
                      "exception_mask = 0x%8.8x, new_port = 0x%4.4x, "
                      "behavior = 0x%8.8x, new_flavor = 0x%8.8x)",
                      task, masks[i], ports[i], behaviors[i], flavors[i]);
        } else {
          log->Printf("::task_set_exception_ports(task = 0x%4.4x, "
                      "exception_mask = 0x%8.8x, new_port = 0x%4.4x, "
                      "behavior = 0x%8.8x, new_flavor = 0x%8.8x): "
                      "error %u (%s)",
                      task, masks[i], ports[i], behaviors[i], flavors[i],
                      error.GetError(), error.AsCString());
        }
      }

      // Bail if we encounter any errors
      if (error.Fail())
        break;
    }
  }

  count = 0;
  return error;
}
Example #22
0
ModuleLock::ModuleLock(const FileSpec &root_dir_spec, const UUID &uuid,
                       Error &error) {
  const auto lock_dir_spec = JoinPath(root_dir_spec, kLockDirName);
  error = MakeDirectory(lock_dir_spec);
  if (error.Fail())
    return;

  m_file_spec = JoinPath(lock_dir_spec, uuid.GetAsString().c_str());
  m_file.Open(m_file_spec.GetCString(), File::eOpenOptionWrite |
                                            File::eOpenOptionCanCreate |
                                            File::eOpenOptionCloseOnExec);
  if (!m_file) {
    error.SetErrorToErrno();
    return;
  }

  m_lock.reset(new lldb_private::LockFile(m_file.GetDescriptor()));
  error = m_lock->WriteLock(0, 1);
  if (error.Fail())
    error.SetErrorStringWithFormat("Failed to lock file: %s",
                                   error.AsCString());
}
    virtual bool
    DoExecute (const char *raw_command_line, CommandReturnObject &result)
    {
        // TODO: Implement "Platform::RunShellCommand()" and switch over to using
        // the current platform when it is in the interface. 
        const char *working_dir = NULL;
        std::string output;
        int status = -1;
        int signo = -1;
        Error error (Host::RunShellCommand (raw_command_line, working_dir, &status, &signo, &output, 10));
        if (!output.empty())
            result.GetOutputStream().PutCString(output.c_str());
        if (status > 0)
        {
            if (signo > 0)
            {
                const char *signo_cstr = Host::GetSignalAsCString(signo);
                if (signo_cstr)
                    result.GetOutputStream().Printf("error: command returned with status %i and signal %s\n", status, signo_cstr);
                else
                    result.GetOutputStream().Printf("error: command returned with status %i and signal %i\n", status, signo);
            }
            else
                result.GetOutputStream().Printf("error: command returned with status %i\n", status);
        }

        if (error.Fail())
        {
            result.AppendError(error.AsCString());
            result.SetStatus (eReturnStatusFailed);
        }
        else
        {
            result.SetStatus (eReturnStatusSuccessFinishResult);
        }
        return true;
    }
 virtual bool
 DoExecute (Args& args, CommandReturnObject &result)
 {
     if (args.GetArgumentCount() == 1)
     {
         const char *platform_name = args.GetArgumentAtIndex (0);
         if (platform_name && platform_name[0])
         {
             const bool select = true;
             m_platform_options.SetPlatformName (platform_name);
             Error error;
             ArchSpec platform_arch;
             PlatformSP platform_sp (m_platform_options.CreatePlatformWithOptions (m_interpreter, ArchSpec(), select, error, platform_arch));
             if (platform_sp)
             {
                 platform_sp->GetStatus (result.GetOutputStream());
                 result.SetStatus (eReturnStatusSuccessFinishResult);
             }
             else
             {
                 result.AppendError(error.AsCString());
                 result.SetStatus (eReturnStatusFailed);
             }
         }
         else
         {
             result.AppendError ("invalid platform name");
             result.SetStatus (eReturnStatusFailed);
         }
     }
     else
     {
         result.AppendError ("platform create takes a platform name as an argument\n");
         result.SetStatus (eReturnStatusFailed);
     }
     return result.Succeeded();
 }
Example #25
0
SBStringList
SBDebugger::GetInternalVariableValue (const char *var_name, const char *debugger_instance_name)
{
    SBStringList ret_value;
    SettableVariableType var_type;
    Error err;

    UserSettingsControllerSP root_settings_controller = Debugger::GetSettingsController();

    StringList value = root_settings_controller->GetVariable (var_name, var_type, debugger_instance_name, err);
    
    if (err.Success())
    {
        for (unsigned i = 0; i != value.GetSize(); ++i)
            ret_value.AppendString (value.GetStringAtIndex(i));
    }
    else
    {
        ret_value.AppendString (err.AsCString());
    }


    return ret_value;
}
Example #26
0
bool
ClangUserExpression::Parse (Stream &error_stream,
                            ExecutionContext &exe_ctx,
                            lldb_private::ExecutionPolicy execution_policy,
                            bool keep_result_in_memory,
                            bool generate_debug_info)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    Error err;

    InstallContext(exe_ctx);

    ScanContext(exe_ctx, err);

    if (!err.Success())
    {
        error_stream.Printf("warning: %s\n", err.AsCString());
    }

    StreamString m_transformed_stream;

    ////////////////////////////////////
    // Generate the expression
    //

    ApplyObjcCastHack(m_expr_text);
    //ApplyUnicharHack(m_expr_text);

    std::unique_ptr<ExpressionSourceCode> source_code (ExpressionSourceCode::CreateWrapped(m_expr_prefix.c_str(), m_expr_text.c_str()));

    lldb::LanguageType lang_type;

    if (m_cplusplus)
        lang_type = lldb::eLanguageTypeC_plus_plus;
    else if(m_objectivec)
        lang_type = lldb::eLanguageTypeObjC;
    else
        lang_type = lldb::eLanguageTypeC;

    if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_static_method, exe_ctx))
    {
        error_stream.PutCString ("error: couldn't construct expression body");
        return false;
    }

    if (log)
        log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());

    ////////////////////////////////////
    // Set up the target and compiler
    //

    Target *target = exe_ctx.GetTargetPtr();

    if (!target)
    {
        error_stream.PutCString ("error: invalid target\n");
        return false;
    }

    //////////////////////////
    // Parse the expression
    //

    m_materializer_ap.reset(new Materializer());

    m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));

    class OnExit
    {
    public:
        typedef std::function <void (void)> Callback;

        OnExit (Callback const &callback) :
            m_callback(callback)
        {
        }

        ~OnExit ()
        {
            m_callback();
        }
    private:
        Callback m_callback;
    };

    OnExit on_exit([this]() { m_expr_decl_map.reset(); });

    if (!m_expr_decl_map->WillParse(exe_ctx, m_materializer_ap.get()))
    {
        error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");

        m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions.

        return false;
    }

    Process *process = exe_ctx.GetProcessPtr();
    ExecutionContextScope *exe_scope = process;

    if (!exe_scope)
        exe_scope = exe_ctx.GetTargetPtr();

    ClangExpressionParser parser(exe_scope, *this, generate_debug_info);

    unsigned num_errors = parser.Parse (error_stream);

    if (num_errors)
    {
        error_stream.Printf ("error: %d errors parsing expression\n", num_errors);

        m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions.

        return false;
    }

    //////////////////////////////////////////////////////////////////////////////////////////
    // Prepare the output of the parser for execution, evaluating it statically if possible
    //

    Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
                                                  m_jit_end_addr,
                                                  m_execution_unit_sp,
                                                  exe_ctx,
                                                  m_can_interpret,
                                                  execution_policy);

    if (generate_debug_info)
    {
        lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule());

        if (jit_module_sp)
        {
            ConstString const_func_name(FunctionName());
            FileSpec jit_file;
            jit_file.GetFilename() = const_func_name;
            jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString());
            m_jit_module_wp = jit_module_sp;
            target->GetImages().Append(jit_module_sp);
        }
//        lldb_private::ObjectFile *jit_obj_file = jit_module_sp->GetObjectFile();
//        StreamFile strm (stdout, false);
//        if (jit_obj_file)
//        {
//            jit_obj_file->GetSectionList();
//            jit_obj_file->GetSymtab();
//            jit_obj_file->Dump(&strm);
//        }
//        lldb_private::SymbolVendor *jit_sym_vendor = jit_module_sp->GetSymbolVendor();
//        if (jit_sym_vendor)
//        {
//            lldb_private::SymbolContextList sc_list;
//            jit_sym_vendor->FindFunctions(const_func_name, NULL, lldb::eFunctionNameTypeFull, true, false, sc_list);
//            sc_list.Dump(&strm, target);
//            jit_sym_vendor->Dump(&strm);
//        }
    }

    m_expr_decl_map.reset(); // Make this go away since we don't need any of its state after parsing.  This also gets rid of any ClangASTImporter::Minions.

    if (jit_error.Success())
    {
        if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
            m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
        return true;
    }
    else
    {
        const char *error_cstr = jit_error.AsCString();
        if (error_cstr && error_cstr[0])
            error_stream.Printf ("error: %s\n", error_cstr);
        else
            error_stream.Printf ("error: expression can't be interpreted or run\n");
        return false;
    }
}
/// Locates the address of the rendezvous structure.  Returns the address on
/// success and LLDB_INVALID_ADDRESS on failure.
static addr_t
ResolveRendezvousAddress(Process *process)
{
    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
    addr_t info_location;
    addr_t info_addr;
    Error error;

    if (!process)
    {
        if (log)
            log->Printf ("%s null process provided", __FUNCTION__);
        return LLDB_INVALID_ADDRESS;
    }

    // Try to get it from our process.  This might be a remote process and might
    // grab it via some remote-specific mechanism.
    info_location = process->GetImageInfoAddress();
    if (log)
        log->Printf ("%s info_location = 0x%" PRIx64, __FUNCTION__, info_location);

    // If the process fails to return an address, fall back to seeing if the local object file can help us find it.
    if (info_location == LLDB_INVALID_ADDRESS)
    {
        Target *target = &process->GetTarget();
        if (target)
        {
            ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
            Address addr = obj_file->GetImageInfoAddress(target);

            if (addr.IsValid())
            {
                info_location = addr.GetLoadAddress(target);
                if (log)
                    log->Printf ("%s resolved via direct object file approach to 0x%" PRIx64, __FUNCTION__, info_location);
            }
            else
            {
                if (log)
                    log->Printf ("%s FAILED - direct object file approach did not yield a valid address", __FUNCTION__);
            }
        }
    }

    if (info_location == LLDB_INVALID_ADDRESS)
    {
        if (log)
            log->Printf ("%s FAILED - invalid info address", __FUNCTION__);
        return LLDB_INVALID_ADDRESS;
    }

    if (log)
        log->Printf ("%s reading pointer (%" PRIu32 " bytes) from 0x%" PRIx64, __FUNCTION__, process->GetAddressByteSize(), info_location);

    info_addr = process->ReadPointerFromMemory(info_location, error);
    if (error.Fail())
    {
        if (log)
            log->Printf ("%s FAILED - could not read from the info location: %s", __FUNCTION__, error.AsCString ());
        return LLDB_INVALID_ADDRESS;
    }

    if (info_addr == 0)
    {
        if (log)
            log->Printf ("%s FAILED - the rendezvous address contained at 0x%" PRIx64 " returned a null value", __FUNCTION__, info_location);
        return LLDB_INVALID_ADDRESS;
    }

    return info_addr;
}
Error
IRExecutionUnit::DisassembleFunction (Stream &stream,
                                      lldb::ProcessSP &process_wp)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    ExecutionContext exe_ctx(process_wp);

    Error ret;

    ret.Clear();

    lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS;
    lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS;

    for (JittedFunction &function : m_jitted_functions)
    {
        if (strstr(function.m_name.c_str(), m_name.AsCString()))
        {
            func_local_addr = function.m_local_addr;
            func_remote_addr = function.m_remote_addr;
        }
    }

    if (func_local_addr == LLDB_INVALID_ADDRESS)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", m_name.AsCString());
        return ret;
    }

    if (log)
        log->Printf("Found function, has local address 0x%" PRIx64 " and remote address 0x%" PRIx64, (uint64_t)func_local_addr, (uint64_t)func_remote_addr);

    std::pair <lldb::addr_t, lldb::addr_t> func_range;

    func_range = GetRemoteRangeForLocal(func_local_addr);

    if (func_range.first == 0 && func_range.second == 0)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't find code range for function %s", m_name.AsCString());
        return ret;
    }

    if (log)
        log->Printf("Function's code range is [0x%" PRIx64 "+0x%" PRIx64 "]", func_range.first, func_range.second);

    Target *target = exe_ctx.GetTargetPtr();
    if (!target)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorString("Couldn't find the target");
        return ret;
    }

    lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0));

    Process *process = exe_ctx.GetProcessPtr();
    Error err;
    process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err);

    if (!err.Success())
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error"));
        return ret;
    }

    ArchSpec arch(target->GetArchitecture());

    const char *plugin_name = NULL;
    const char *flavor_string = NULL;
    lldb::DisassemblerSP disassembler_sp = Disassembler::FindPlugin(arch, flavor_string, plugin_name);

    if (!disassembler_sp)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.GetArchitectureName());
        return ret;
    }

    if (!process)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorString("Couldn't find the process");
        return ret;
    }

    DataExtractor extractor(buffer_sp,
                            process->GetByteOrder(),
                            target->GetArchitecture().GetAddressByteSize());

    if (log)
    {
        log->Printf("Function data has contents:");
        extractor.PutToLog (log,
                            0,
                            extractor.GetByteSize(),
                            func_remote_addr,
                            16,
                            DataExtractor::TypeUInt8);
    }

    disassembler_sp->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false, false);

    InstructionList &instruction_list = disassembler_sp->GetInstructionList();
    const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();
    const char *disassemble_format = "${addr-file-or-load}: ";
    if (exe_ctx.HasTargetScope())
    {
        disassemble_format = exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat();
    }

    for (size_t instruction_index = 0, num_instructions = instruction_list.GetSize();
         instruction_index < num_instructions;
         ++instruction_index)
    {
        Instruction *instruction = instruction_list.GetInstructionAtIndex(instruction_index).get();
        instruction->Dump (&stream,
                           max_opcode_byte_size,
                           true,
                           true,
                           &exe_ctx,
                           NULL,
                           NULL,
                           disassemble_format);
        stream.PutChar('\n');
    }
    // FIXME: The DisassemblerLLVMC has a reference cycle and won't go away if it has any active instructions.
    // I'll fix that but for now, just clear the list and it will go away nicely.
    disassembler_sp->GetInstructionList().Clear();
    return ret;
}
void
IRExecutionUnit::GetRunnableInfo(Error &error,
                                 lldb::addr_t &func_addr,
                                 lldb::addr_t &func_end)
{
    lldb::ProcessSP process_sp(GetProcessWP().lock());

    static Mutex s_runnable_info_mutex(Mutex::Type::eMutexTypeRecursive);

    func_addr = LLDB_INVALID_ADDRESS;
    func_end = LLDB_INVALID_ADDRESS;

    if (!process_sp)
    {
        error.SetErrorToGenericError();
        error.SetErrorString("Couldn't write the JIT compiled code into the process because the process is invalid");
        return;
    }

    if (m_did_jit)
    {
        func_addr = m_function_load_addr;
        func_end = m_function_end_load_addr;

        return;
    };

    Mutex::Locker runnable_info_mutex_locker(s_runnable_info_mutex);

    m_did_jit = true;

    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    std::string error_string;

    if (log)
    {
        std::string s;
        llvm::raw_string_ostream oss(s);

        m_module->print(oss, NULL);

        oss.flush();

        log->Printf ("Module being sent to JIT: \n%s", s.c_str());
    }

    llvm::Triple triple(m_module->getTargetTriple());
    llvm::Function *function = m_module->getFunction (m_name.AsCString());
    llvm::Reloc::Model relocModel;
    llvm::CodeModel::Model codeModel;

    if (triple.isOSBinFormatELF())
    {
        relocModel = llvm::Reloc::Static;
        // This will be small for 32-bit and large for 64-bit.
        codeModel = llvm::CodeModel::JITDefault;
    }
    else
    {
        relocModel = llvm::Reloc::PIC_;
        codeModel = llvm::CodeModel::Small;
    }

    m_module_ap->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, &error);

    llvm::EngineBuilder builder(std::move(m_module_ap));

    builder.setEngineKind(llvm::EngineKind::JIT)
    .setErrorStr(&error_string)
    .setRelocationModel(relocModel)
    .setMCJITMemoryManager(std::unique_ptr<MemoryManager>(new MemoryManager(*this)))
    .setCodeModel(codeModel)
    .setOptLevel(llvm::CodeGenOpt::Less);

    llvm::StringRef mArch;
    llvm::StringRef mCPU;
    llvm::SmallVector<std::string, 0> mAttrs;

    for (std::string &feature : m_cpu_features)
        mAttrs.push_back(feature);

    llvm::TargetMachine *target_machine = builder.selectTarget(triple,
                                                               mArch,
                                                               mCPU,
                                                               mAttrs);

    m_execution_engine_ap.reset(builder.create(target_machine));

    if (!m_execution_engine_ap.get())
    {
        error.SetErrorToGenericError();
        error.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str());
        return;
    }

    // Make sure we see all sections, including ones that don't have relocations...
    m_execution_engine_ap->setProcessAllSections(true);

    m_execution_engine_ap->DisableLazyCompilation();

    // We don't actually need the function pointer here, this just forces it to get resolved.

    void *fun_ptr = m_execution_engine_ap->getPointerToFunction(function);

    if (!error.Success())
    {
        // We got an error through our callback!
        return;
    }

    if (!function)
    {
        error.SetErrorToGenericError();
        error.SetErrorStringWithFormat("Couldn't find '%s' in the JITted module", m_name.AsCString());
        return;
    }

    if (!fun_ptr)
    {
        error.SetErrorToGenericError();
        error.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", m_name.AsCString());
        return;
    }

    m_jitted_functions.push_back (JittedFunction(m_name.AsCString(), (lldb::addr_t)fun_ptr));

    CommitAllocations(process_sp);
    ReportAllocations(*m_execution_engine_ap);
    WriteData(process_sp);

    for (JittedFunction &jitted_function : m_jitted_functions)
    {
        jitted_function.m_remote_addr = GetRemoteAddressForLocal (jitted_function.m_local_addr);

        if (!jitted_function.m_name.compare(m_name.AsCString()))
        {
            AddrRange func_range = GetRemoteRangeForLocal(jitted_function.m_local_addr);
            m_function_end_load_addr = func_range.first + func_range.second;
            m_function_load_addr = jitted_function.m_remote_addr;
        }
    }

    if (log)
    {
        log->Printf("Code can be run in the target.");

        StreamString disassembly_stream;

        Error err = DisassembleFunction(disassembly_stream, process_sp);

        if (!err.Success())
        {
            log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
        }
        else
        {
            log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
        }

        log->Printf("Sections: ");
        for (AllocationRecord &record : m_records)
        {
            if (record.m_process_address != LLDB_INVALID_ADDRESS)
            {
                record.dump(log);

                DataBufferHeap my_buffer(record.m_size, 0);
                Error err;
                ReadMemory(my_buffer.GetBytes(), record.m_process_address, record.m_size, err);

                if (err.Success())
                {
                    DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(), lldb::eByteOrderBig, 8);
                    my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(), record.m_process_address, 16, DataExtractor::TypeUInt8);
                }
            }
        }
    }

    func_addr = m_function_load_addr;
    func_end = m_function_end_load_addr;

    return;
}
lldb::REPLSP
SwiftREPL::CreateInstance (Error &err, lldb::LanguageType language, Debugger *debugger, Target *target, const char *repl_options)
{
    if (language != eLanguageTypeSwift)
    {
        return lldb::REPLSP();
    }
    
    if (target)
    {
        // Sanity check the target to make sure a REPL would work here.
        if (!target->GetProcessSP() ||
            !target->GetProcessSP()->IsAlive())
        {
            err.SetErrorString ("can't launch a Swift REPL without a running process");
            return lldb::REPLSP();
        }
        
        SymbolContextList sc_list;
        target->GetImages().FindSymbolsWithNameAndType(ConstString("_swift_release"), eSymbolTypeAny, sc_list);
        
        if (!sc_list.GetSize())
        {
            err.SetErrorString ("can't launch a Swift REPL in a process that doesn't have the Swift standard library");
            return lldb::REPLSP();
        }
        
        // Sanity checks succeeded.  Go ahead.
        SwiftREPL *repl = new SwiftREPL(*target);
        REPLSP repl_sp(repl);
        repl->SetCompilerOptions(repl_options);
        return repl_sp;
    }
    else if (debugger)
    {
        const char *bp_name = "repl_main";
        
        FileSpec repl_executable;

        if (HostInfo::GetLLDBPath (ePathTypeSupportExecutableDir, repl_executable))
        {
            repl_executable.GetFilename().SetCString("repl_swift");
            std::string repl_exe_path(repl_executable.GetPath());
            if (repl_executable.Exists())
            {
                const char *target_triple = NULL;
                bool add_dependent_modules = true;
                TargetSP target_sp;
                err = debugger->GetTargetList().CreateTarget (*debugger,
                                                              repl_exe_path.c_str(),
                                                              target_triple,
                                                              add_dependent_modules,
                                                              NULL,
                                                              target_sp);
                if (err.Success())
                {
                    // Limit the breakpoint to our executable module
                    FileSpecList containingModules;
                    ModuleSP exe_module_sp (target_sp->GetExecutableModule());
                    if (exe_module_sp)
                    {
                        FileSpec exe_spec(exe_module_sp->GetFileSpec());
                        containingModules.Append(exe_spec);
                        BreakpointSP main_bp_sp = target_sp->CreateBreakpoint (&containingModules,      // Limit to these modules
                                                                               NULL,                    // Don't limit the breakpoint to any source files
                                                                               bp_name,                 // Function name
                                                                               eFunctionNameTypeAuto,   // Name type
                                                                               eLanguageTypeUnknown,    // Language
                                                                               0,                       // offset
                                                                               eLazyBoolYes,            // skip_prologue,
                                                                               true,                    // internal
                                                                               false);                  // request_hardware
                        
                        if (main_bp_sp->GetNumLocations() > 0)
                        {
                            main_bp_sp->SetBreakpointKind("REPL");
                            
                            assert (main_bp_sp->IsInternal()); // We made an internal breakpoint above, it better say it is internal
                            
                            lldb_private::ProcessLaunchInfo launch_info;
                            const char *target_settings_argv0 = target_sp->GetArg0();
                            
                            if (target_sp->GetDisableASLR())
                                launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
                                
                            if (target_sp->GetDisableSTDIO())
                                launch_info.GetFlags().Set (eLaunchFlagDisableSTDIO);
                                    
                            if (target_settings_argv0)
                            {
                                launch_info.GetArguments().AppendArgument (target_settings_argv0);
                                launch_info.SetExecutableFile(exe_module_sp->GetPlatformFileSpec(), false);
                            }
                            else
                            {
                                launch_info.SetExecutableFile(exe_module_sp->GetPlatformFileSpec(), true);
                            }
                            
                            debugger->SetAsyncExecution(false);
                            err = target_sp->Launch(launch_info, nullptr);
                            debugger->SetAsyncExecution(true);
                            
                            if (err.Success())
                            {
                                ProcessSP process_sp (target_sp->GetProcessSP());
                                if (process_sp)
                                {
                                    // Start handling process events automatically
                                    debugger->StartEventHandlerThread();
                                    
                                    StateType state = process_sp->GetState();
                                    
                                    if (state == eStateStopped)
                                    {
                                        ThreadList &thread_list = process_sp->GetThreadList();
                                        const uint32_t num_threads = thread_list.GetSize();
                                        if (num_threads > 0)
                                        {
                                            ThreadSP thread_sp = thread_list.GetSelectedThread();
                                            if (!thread_sp)
                                            {
                                                thread_sp = thread_list.GetThreadAtIndex(0);
                                                thread_list.SetSelectedThreadByID(thread_sp->GetID());
                                            }
                                            if (thread_sp)
                                            {
                                                thread_sp->SetSelectedFrameByIndex(0);
                                                
                                                std::string swift_full_version(swift::version::getSwiftFullVersion());
                                                printf ("Welcome to %s. Type :help for assistance.\n",
                                                        swift_full_version.c_str());
                                                
                                                REPLSP repl_sp(new SwiftREPL(*target_sp));
                                                ((SwiftREPL*)repl_sp.get())->SetCompilerOptions(repl_options);
                                                target_sp->SetREPL(lldb::eLanguageTypeSwift, repl_sp);
                                                return repl_sp;
                                            }
                                        }
                                        else
                                        {
                                            err.SetErrorString ("process is not in valid state (no threads)");
                                        }
                                    }
                                    else
                                    {
                                        err.SetErrorString ("failed to stop process at REPL breakpoint");
                                    }
                                    
                                    process_sp->Destroy(false);
                                    
                                    debugger->StopEventHandlerThread();
                                }
                                else
                                {
                                    err.SetErrorString ("failed to launch REPL process");
                                }
                            }
                            else
                            {
                                err.SetErrorStringWithFormat ("failed to launch REPL process: %s", err.AsCString());
                            }
                        }
                        else
                        {
                            err.SetErrorStringWithFormat ("failed to resolve REPL breakpoint for '%s'", bp_name);
                        }
                    }
                    else
                    {
                        err.SetErrorString ("unable to resolve REPL executable module");
                        
                        target_sp->Destroy();
                    }
                }
                else
                {
                    err.SetErrorStringWithFormat ("failed to create REPL target: %s", err.AsCString());
                }
            }
            else
            {
                err.SetErrorStringWithFormat ("REPL executable does not exist: '%s'", repl_exe_path.c_str());
            }
        }
        else
        {
            err.SetErrorString ("unable to locate REPL executable");
        }
        
        return lldb::REPLSP();
    }
    else
    {
        err.SetErrorString ("must have a debugger or a target to create a REPL");
        return lldb::REPLSP();
    }
}