diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:26:05 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:26:05 +0000 | 
| commit | 14f1b3e8826ce43b978db93a62d1166055db5394 (patch) | |
| tree | 0a00ad8d3498783fe0193f3b656bca17c4c8697d /source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp | |
| parent | 4ee8c119c71a06dcad1e0fecc8c675e480e59337 (diff) | |
Notes
Diffstat (limited to 'source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp')
| -rw-r--r-- | source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp | 1834 | 
1 files changed, 834 insertions, 1000 deletions
diff --git a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp index 898677df616b..dae33f6257d1 100644 --- a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp +++ b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp @@ -16,9 +16,9 @@  // Other libraries and framework includes  #include "lldb/Core/Debugger.h" -#include "lldb/Core/PluginManager.h"  #include "lldb/Core/Module.h"  #include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h"  #include "lldb/Core/State.h"  #include "lldb/Core/UUID.h"  #include "lldb/Host/ConnectionFileDescriptor.h" @@ -42,1168 +42,1002 @@  #define USEC_PER_SEC 1000000  // Project includes +#include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h" +#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"  #include "ProcessKDP.h"  #include "ProcessKDPLog.h"  #include "ThreadKDP.h" -#include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h" -#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"  using namespace lldb;  using namespace lldb_private;  namespace { -    static PropertyDefinition -    g_properties[] = -    { -        { "packet-timeout" , OptionValue::eTypeUInt64 , true , 5, NULL, NULL, "Specify the default packet timeout in seconds." }, -        {  NULL            , OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL  } -    }; -     -    enum -    { -        ePropertyPacketTimeout -    }; - -    class PluginProperties : public Properties -    { -    public: -         -        static ConstString -        GetSettingName () -        { -            return ProcessKDP::GetPluginNameStatic(); -        } +static PropertyDefinition g_properties[] = { +    {"packet-timeout", OptionValue::eTypeUInt64, true, 5, NULL, NULL, +     "Specify the default packet timeout in seconds."}, +    {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}}; -        PluginProperties() : -            Properties () -        { -            m_collection_sp.reset (new OptionValueProperties(GetSettingName())); -            m_collection_sp->Initialize(g_properties); -        } -         -        virtual -        ~PluginProperties() -        { -        } -         -        uint64_t -        GetPacketTimeout() -        { -            const uint32_t idx = ePropertyPacketTimeout; -            return m_collection_sp->GetPropertyAtIndexAsUInt64(NULL, idx, g_properties[idx].default_uint_value); -        } -    }; +enum { ePropertyPacketTimeout }; -    typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP; +class PluginProperties : public Properties { +public: +  static ConstString GetSettingName() { +    return ProcessKDP::GetPluginNameStatic(); +  } + +  PluginProperties() : Properties() { +    m_collection_sp.reset(new OptionValueProperties(GetSettingName())); +    m_collection_sp->Initialize(g_properties); +  } + +  virtual ~PluginProperties() {} + +  uint64_t GetPacketTimeout() { +    const uint32_t idx = ePropertyPacketTimeout; +    return m_collection_sp->GetPropertyAtIndexAsUInt64( +        NULL, idx, g_properties[idx].default_uint_value); +  } +}; + +typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP; + +static const ProcessKDPPropertiesSP &GetGlobalPluginProperties() { +  static ProcessKDPPropertiesSP g_settings_sp; +  if (!g_settings_sp) +    g_settings_sp.reset(new PluginProperties()); +  return g_settings_sp; +} -    static const ProcessKDPPropertiesSP & -    GetGlobalPluginProperties() -    { -        static ProcessKDPPropertiesSP g_settings_sp; -        if (!g_settings_sp) -            g_settings_sp.reset (new PluginProperties ()); -        return g_settings_sp; -    } -      } // anonymous namespace end  static const lldb::tid_t g_kernel_tid = 1; -ConstString -ProcessKDP::GetPluginNameStatic() -{ -    static ConstString g_name("kdp-remote"); -    return g_name; +ConstString ProcessKDP::GetPluginNameStatic() { +  static ConstString g_name("kdp-remote"); +  return g_name;  } -const char * -ProcessKDP::GetPluginDescriptionStatic() -{ -    return "KDP Remote protocol based debugging plug-in for darwin kernel debugging."; +const char *ProcessKDP::GetPluginDescriptionStatic() { +  return "KDP Remote protocol based debugging plug-in for darwin kernel " +         "debugging.";  } -void -ProcessKDP::Terminate() -{ -    PluginManager::UnregisterPlugin (ProcessKDP::CreateInstance); +void ProcessKDP::Terminate() { +  PluginManager::UnregisterPlugin(ProcessKDP::CreateInstance);  } - -lldb::ProcessSP -ProcessKDP::CreateInstance (TargetSP target_sp, -                            ListenerSP listener_sp, -                            const FileSpec *crash_file_path) -{ -    lldb::ProcessSP process_sp; -    if (crash_file_path == NULL) -        process_sp.reset(new ProcessKDP (target_sp, listener_sp)); -    return process_sp; +lldb::ProcessSP ProcessKDP::CreateInstance(TargetSP target_sp, +                                           ListenerSP listener_sp, +                                           const FileSpec *crash_file_path) { +  lldb::ProcessSP process_sp; +  if (crash_file_path == NULL) +    process_sp.reset(new ProcessKDP(target_sp, listener_sp)); +  return process_sp;  } -bool -ProcessKDP::CanDebug(TargetSP target_sp, bool plugin_specified_by_name) -{ -    if (plugin_specified_by_name) -        return true; - -    // For now we are just making sure the file exists for a given module -    Module *exe_module = target_sp->GetExecutableModulePointer(); -    if (exe_module) -    { -        const llvm::Triple &triple_ref = target_sp->GetArchitecture().GetTriple(); -        switch (triple_ref.getOS()) -        { -            case llvm::Triple::Darwin:  // Should use "macosx" for desktop and "ios" for iOS, but accept darwin just in case -            case llvm::Triple::MacOSX:  // For desktop targets -            case llvm::Triple::IOS:     // For arm targets -            case llvm::Triple::TvOS: -            case llvm::Triple::WatchOS: -                if (triple_ref.getVendor() == llvm::Triple::Apple) -                { -                    ObjectFile *exe_objfile = exe_module->GetObjectFile(); -                    if (exe_objfile->GetType() == ObjectFile::eTypeExecutable &&  -                        exe_objfile->GetStrata() == ObjectFile::eStrataKernel) -                        return true; -                } -                break; - -            default: -                break; -        } +bool ProcessKDP::CanDebug(TargetSP target_sp, bool plugin_specified_by_name) { +  if (plugin_specified_by_name) +    return true; + +  // For now we are just making sure the file exists for a given module +  Module *exe_module = target_sp->GetExecutableModulePointer(); +  if (exe_module) { +    const llvm::Triple &triple_ref = target_sp->GetArchitecture().GetTriple(); +    switch (triple_ref.getOS()) { +    case llvm::Triple::Darwin: // Should use "macosx" for desktop and "ios" for +                               // iOS, but accept darwin just in case +    case llvm::Triple::MacOSX: // For desktop targets +    case llvm::Triple::IOS:    // For arm targets +    case llvm::Triple::TvOS: +    case llvm::Triple::WatchOS: +      if (triple_ref.getVendor() == llvm::Triple::Apple) { +        ObjectFile *exe_objfile = exe_module->GetObjectFile(); +        if (exe_objfile->GetType() == ObjectFile::eTypeExecutable && +            exe_objfile->GetStrata() == ObjectFile::eStrataKernel) +          return true; +      } +      break; + +    default: +      break;      } -    return false; +  } +  return false;  }  //----------------------------------------------------------------------  // ProcessKDP constructor  //---------------------------------------------------------------------- -ProcessKDP::ProcessKDP(TargetSP target_sp, ListenerSP listener_sp) : -    Process (target_sp, listener_sp), -    m_comm("lldb.process.kdp-remote.communication"), -    m_async_broadcaster (NULL, "lldb.process.kdp-remote.async-broadcaster"), -    m_dyld_plugin_name (), -    m_kernel_load_addr (LLDB_INVALID_ADDRESS), -    m_command_sp(), -    m_kernel_thread_wp() -{ -    m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit,   "async thread should exit"); -    m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue,           "async thread continue"); -    const uint64_t timeout_seconds = GetGlobalPluginProperties()->GetPacketTimeout(); -    if (timeout_seconds > 0) -        m_comm.SetPacketTimeout(timeout_seconds); +ProcessKDP::ProcessKDP(TargetSP target_sp, ListenerSP listener_sp) +    : Process(target_sp, listener_sp), +      m_comm("lldb.process.kdp-remote.communication"), +      m_async_broadcaster(NULL, "lldb.process.kdp-remote.async-broadcaster"), +      m_dyld_plugin_name(), m_kernel_load_addr(LLDB_INVALID_ADDRESS), +      m_command_sp(), m_kernel_thread_wp() { +  m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, +                                   "async thread should exit"); +  m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, +                                   "async thread continue"); +  const uint64_t timeout_seconds = +      GetGlobalPluginProperties()->GetPacketTimeout(); +  if (timeout_seconds > 0) +    m_comm.SetPacketTimeout(std::chrono::seconds(timeout_seconds));  }  //----------------------------------------------------------------------  // Destructor  //---------------------------------------------------------------------- -ProcessKDP::~ProcessKDP() -{ -    Clear(); -    // We need to call finalize on the process before destroying ourselves -    // to make sure all of the broadcaster cleanup goes as planned. If we -    // destruct this class, then Process::~Process() might have problems -    // trying to fully destroy the broadcaster. -    Finalize(); +ProcessKDP::~ProcessKDP() { +  Clear(); +  // We need to call finalize on the process before destroying ourselves +  // to make sure all of the broadcaster cleanup goes as planned. If we +  // destruct this class, then Process::~Process() might have problems +  // trying to fully destroy the broadcaster. +  Finalize();  }  //----------------------------------------------------------------------  // PluginInterface  //---------------------------------------------------------------------- -lldb_private::ConstString -ProcessKDP::GetPluginName() -{ -    return GetPluginNameStatic(); +lldb_private::ConstString ProcessKDP::GetPluginName() { +  return GetPluginNameStatic();  } -uint32_t -ProcessKDP::GetPluginVersion() -{ -    return 1; -} +uint32_t ProcessKDP::GetPluginVersion() { return 1; } -Error -ProcessKDP::WillLaunch (Module* module) -{ -    Error error; -    error.SetErrorString ("launching not supported in kdp-remote plug-in"); -    return error; +Error ProcessKDP::WillLaunch(Module *module) { +  Error error; +  error.SetErrorString("launching not supported in kdp-remote plug-in"); +  return error;  } -Error -ProcessKDP::WillAttachToProcessWithID (lldb::pid_t pid) -{ -    Error error; -    error.SetErrorString ("attaching to a by process ID not supported in kdp-remote plug-in"); -    return error; +Error ProcessKDP::WillAttachToProcessWithID(lldb::pid_t pid) { +  Error error; +  error.SetErrorString( +      "attaching to a by process ID not supported in kdp-remote plug-in"); +  return error;  } -Error -ProcessKDP::WillAttachToProcessWithName (const char *process_name, bool wait_for_launch) -{ -    Error error; -    error.SetErrorString ("attaching to a by process name not supported in kdp-remote plug-in"); -    return error; +Error ProcessKDP::WillAttachToProcessWithName(const char *process_name, +                                              bool wait_for_launch) { +  Error error; +  error.SetErrorString( +      "attaching to a by process name not supported in kdp-remote plug-in"); +  return error;  } -bool -ProcessKDP::GetHostArchitecture(ArchSpec &arch) -{ -    uint32_t cpu = m_comm.GetCPUType(); -    if (cpu) -    { -        uint32_t sub = m_comm.GetCPUSubtype(); -        arch.SetArchitecture(eArchTypeMachO, cpu, sub); -        // Leave architecture vendor as unspecified unknown -        arch.GetTriple().setVendor(llvm::Triple::UnknownVendor); -        arch.GetTriple().setVendorName(llvm::StringRef()); -        return true; -    } -    arch.Clear(); -    return false; +bool ProcessKDP::GetHostArchitecture(ArchSpec &arch) { +  uint32_t cpu = m_comm.GetCPUType(); +  if (cpu) { +    uint32_t sub = m_comm.GetCPUSubtype(); +    arch.SetArchitecture(eArchTypeMachO, cpu, sub); +    // Leave architecture vendor as unspecified unknown +    arch.GetTriple().setVendor(llvm::Triple::UnknownVendor); +    arch.GetTriple().setVendorName(llvm::StringRef()); +    return true; +  } +  arch.Clear(); +  return false;  } -Error -ProcessKDP::DoConnectRemote (Stream *strm, const char *remote_url) -{ -    Error error; - -    // Don't let any JIT happen when doing KDP as we can't allocate -    // memory and we don't want to be mucking with threads that might -    // already be handling exceptions -    SetCanJIT(false); +Error ProcessKDP::DoConnectRemote(Stream *strm, llvm::StringRef remote_url) { +  Error error; -    if (remote_url == NULL || remote_url[0] == '\0') -    { -        error.SetErrorStringWithFormat ("invalid connection URL '%s'", remote_url); -        return error; -    } +  // Don't let any JIT happen when doing KDP as we can't allocate +  // memory and we don't want to be mucking with threads that might +  // already be handling exceptions +  SetCanJIT(false); -    std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor()); -    if (conn_ap.get()) -    { -        // Only try once for now. -        // TODO: check if we should be retrying? -        const uint32_t max_retry_count = 1; -        for (uint32_t retry_count = 0; retry_count < max_retry_count; ++retry_count) -        { -            if (conn_ap->Connect(remote_url, &error) == eConnectionStatusSuccess) -                break; -            usleep (100000); -        } +  if (remote_url.empty()) { +    error.SetErrorStringWithFormat("empty connection URL"); +    return error; +  } + +  std::unique_ptr<ConnectionFileDescriptor> conn_ap( +      new ConnectionFileDescriptor()); +  if (conn_ap.get()) { +    // Only try once for now. +    // TODO: check if we should be retrying? +    const uint32_t max_retry_count = 1; +    for (uint32_t retry_count = 0; retry_count < max_retry_count; +         ++retry_count) { +      if (conn_ap->Connect(remote_url, &error) == eConnectionStatusSuccess) +        break; +      usleep(100000);      } - -    if (conn_ap->IsConnected()) -    { -        const TCPSocket& socket = static_cast<const TCPSocket&>(*conn_ap->GetReadObject()); -        const uint16_t reply_port = socket.GetLocalPortNumber(); - -        if (reply_port != 0) -        { -            m_comm.SetConnection(conn_ap.release()); - -            if (m_comm.SendRequestReattach(reply_port)) -            { -                if (m_comm.SendRequestConnect(reply_port, reply_port, "Greetings from LLDB...")) -                { -                    m_comm.GetVersion(); - -                    Target &target = GetTarget(); -                    ArchSpec kernel_arch; -                    // The host architecture -                    GetHostArchitecture(kernel_arch); -                    ArchSpec target_arch = target.GetArchitecture(); -                    // Merge in any unspecified stuff into the target architecture in -                    // case the target arch isn't set at all or incompletely. -                    target_arch.MergeFrom(kernel_arch); -                    target.SetArchitecture(target_arch); - -                    /* Get the kernel's UUID and load address via KDP_KERNELVERSION packet.  */ -                    /* An EFI kdp session has neither UUID nor load address. */ - -                    UUID kernel_uuid = m_comm.GetUUID (); -                    addr_t kernel_load_addr = m_comm.GetLoadAddress (); - -                    if (m_comm.RemoteIsEFI ()) -                    { -                        // Select an invalid plugin name for the dynamic loader so one doesn't get used -                        // since EFI does its own manual loading via python scripting -                        static ConstString g_none_dynamic_loader("none"); -                        m_dyld_plugin_name = g_none_dynamic_loader; - -                        if (kernel_uuid.IsValid()) { -                            // If EFI passed in a UUID= try to lookup UUID -                            // The slide will not be provided. But the UUID -                            // lookup will be used to launch EFI debug scripts -                            // from the dSYM, that can load all of the symbols. -                            ModuleSpec module_spec; -                            module_spec.GetUUID() = kernel_uuid; -                            module_spec.GetArchitecture() = target.GetArchitecture(); - -                            // Lookup UUID locally, before attempting dsymForUUID like action -                            module_spec.GetSymbolFileSpec() = Symbols::LocateExecutableSymbolFile(module_spec); -                            if (module_spec.GetSymbolFileSpec()) -                            { -                                ModuleSpec executable_module_spec = Symbols::LocateExecutableObjectFile (module_spec); -                                if (executable_module_spec.GetFileSpec().Exists()) -                                { -                                    module_spec.GetFileSpec() = executable_module_spec.GetFileSpec(); -                                } -                            } -                            if (!module_spec.GetSymbolFileSpec() || !module_spec.GetSymbolFileSpec()) -                                 Symbols::DownloadObjectAndSymbolFile (module_spec, true); - -                            if (module_spec.GetFileSpec().Exists()) -                            { -                                ModuleSP module_sp(new Module (module_spec)); -                                if (module_sp.get() && module_sp->GetObjectFile()) -                                { -                                    // Get the current target executable -                                    ModuleSP exe_module_sp (target.GetExecutableModule ()); - -                                    // Make sure you don't already have the right module loaded and they will be uniqued -                                    if (exe_module_sp.get() != module_sp.get()) -                                        target.SetExecutableModule (module_sp, false); -                                } -                            } -                        } -                    } -                    else if (m_comm.RemoteIsDarwinKernel ()) -                    { -                        m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic(); -                        if (kernel_load_addr != LLDB_INVALID_ADDRESS) -                        { -                            m_kernel_load_addr = kernel_load_addr; -                        } -                    } - -                    // Set the thread ID -                    UpdateThreadListIfNeeded (); -                    SetID (1); -                    GetThreadList (); -                    SetPrivateState (eStateStopped); -                    StreamSP async_strm_sp(target.GetDebugger().GetAsyncOutputStream()); -                    if (async_strm_sp) -                    { -                        const char *cstr; -                        if ((cstr = m_comm.GetKernelVersion ()) != NULL) -                        { -                            async_strm_sp->Printf ("Version: %s\n", cstr); -                            async_strm_sp->Flush(); -                        } -//                      if ((cstr = m_comm.GetImagePath ()) != NULL) -//                      { -//                          async_strm_sp->Printf ("Image Path: %s\n", cstr); -//                          async_strm_sp->Flush(); -//                      }             -                    } +  } + +  if (conn_ap->IsConnected()) { +    const TCPSocket &socket = +        static_cast<const TCPSocket &>(*conn_ap->GetReadObject()); +    const uint16_t reply_port = socket.GetLocalPortNumber(); + +    if (reply_port != 0) { +      m_comm.SetConnection(conn_ap.release()); + +      if (m_comm.SendRequestReattach(reply_port)) { +        if (m_comm.SendRequestConnect(reply_port, reply_port, +                                      "Greetings from LLDB...")) { +          m_comm.GetVersion(); + +          Target &target = GetTarget(); +          ArchSpec kernel_arch; +          // The host architecture +          GetHostArchitecture(kernel_arch); +          ArchSpec target_arch = target.GetArchitecture(); +          // Merge in any unspecified stuff into the target architecture in +          // case the target arch isn't set at all or incompletely. +          target_arch.MergeFrom(kernel_arch); +          target.SetArchitecture(target_arch); + +          /* Get the kernel's UUID and load address via KDP_KERNELVERSION +           * packet.  */ +          /* An EFI kdp session has neither UUID nor load address. */ + +          UUID kernel_uuid = m_comm.GetUUID(); +          addr_t kernel_load_addr = m_comm.GetLoadAddress(); + +          if (m_comm.RemoteIsEFI()) { +            // Select an invalid plugin name for the dynamic loader so one +            // doesn't get used +            // since EFI does its own manual loading via python scripting +            static ConstString g_none_dynamic_loader("none"); +            m_dyld_plugin_name = g_none_dynamic_loader; + +            if (kernel_uuid.IsValid()) { +              // If EFI passed in a UUID= try to lookup UUID +              // The slide will not be provided. But the UUID +              // lookup will be used to launch EFI debug scripts +              // from the dSYM, that can load all of the symbols. +              ModuleSpec module_spec; +              module_spec.GetUUID() = kernel_uuid; +              module_spec.GetArchitecture() = target.GetArchitecture(); + +              // Lookup UUID locally, before attempting dsymForUUID like action +              module_spec.GetSymbolFileSpec() = +                  Symbols::LocateExecutableSymbolFile(module_spec); +              if (module_spec.GetSymbolFileSpec()) { +                ModuleSpec executable_module_spec = +                    Symbols::LocateExecutableObjectFile(module_spec); +                if (executable_module_spec.GetFileSpec().Exists()) { +                  module_spec.GetFileSpec() = +                      executable_module_spec.GetFileSpec();                  } -                else -                { -                    error.SetErrorString("KDP_REATTACH failed"); +              } +              if (!module_spec.GetSymbolFileSpec() || +                  !module_spec.GetSymbolFileSpec()) +                Symbols::DownloadObjectAndSymbolFile(module_spec, true); + +              if (module_spec.GetFileSpec().Exists()) { +                ModuleSP module_sp(new Module(module_spec)); +                if (module_sp.get() && module_sp->GetObjectFile()) { +                  // Get the current target executable +                  ModuleSP exe_module_sp(target.GetExecutableModule()); + +                  // Make sure you don't already have the right module loaded +                  // and they will be uniqued +                  if (exe_module_sp.get() != module_sp.get()) +                    target.SetExecutableModule(module_sp, false);                  } +              }              } -            else -            { -                error.SetErrorString("KDP_REATTACH failed"); +          } else if (m_comm.RemoteIsDarwinKernel()) { +            m_dyld_plugin_name = +                DynamicLoaderDarwinKernel::GetPluginNameStatic(); +            if (kernel_load_addr != LLDB_INVALID_ADDRESS) { +              m_kernel_load_addr = kernel_load_addr;              } +          } + +          // Set the thread ID +          UpdateThreadListIfNeeded(); +          SetID(1); +          GetThreadList(); +          SetPrivateState(eStateStopped); +          StreamSP async_strm_sp(target.GetDebugger().GetAsyncOutputStream()); +          if (async_strm_sp) { +            const char *cstr; +            if ((cstr = m_comm.GetKernelVersion()) != NULL) { +              async_strm_sp->Printf("Version: %s\n", cstr); +              async_strm_sp->Flush(); +            } +            //                      if ((cstr = m_comm.GetImagePath ()) != NULL) +            //                      { +            //                          async_strm_sp->Printf ("Image Path: +            //                          %s\n", cstr); +            //                          async_strm_sp->Flush(); +            //                      } +          } +        } else { +          error.SetErrorString("KDP_REATTACH failed");          } -        else -        { -            error.SetErrorString("invalid reply port from UDP connection"); -        } -    } -    else -    { -        if (error.Success()) -            error.SetErrorStringWithFormat ("failed to connect to '%s'", remote_url); +      } else { +        error.SetErrorString("KDP_REATTACH failed"); +      } +    } else { +      error.SetErrorString("invalid reply port from UDP connection");      } -    if (error.Fail()) -        m_comm.Disconnect(); - -    return error; +  } else { +    if (error.Success()) +      error.SetErrorStringWithFormat("failed to connect to '%s'", +                                     remote_url.str().c_str()); +  } +  if (error.Fail()) +    m_comm.Disconnect(); + +  return error;  }  //----------------------------------------------------------------------  // Process Control  //---------------------------------------------------------------------- -Error -ProcessKDP::DoLaunch (Module *exe_module,  -                      ProcessLaunchInfo &launch_info) -{ -    Error error; -    error.SetErrorString ("launching not supported in kdp-remote plug-in"); -    return error; +Error ProcessKDP::DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) { +  Error error; +  error.SetErrorString("launching not supported in kdp-remote plug-in"); +  return error;  } -Error -ProcessKDP::DoAttachToProcessWithID (lldb::pid_t attach_pid, const ProcessAttachInfo &attach_info) -{ -    Error error; -    error.SetErrorString ("attach to process by ID is not suppported in kdp remote debugging"); -    return error; +Error ProcessKDP::DoAttachToProcessWithID( +    lldb::pid_t attach_pid, const ProcessAttachInfo &attach_info) { +  Error error; +  error.SetErrorString( +      "attach to process by ID is not suppported in kdp remote debugging"); +  return error;  } -Error -ProcessKDP::DoAttachToProcessWithName (const char *process_name, const ProcessAttachInfo &attach_info) -{ -    Error error; -    error.SetErrorString ("attach to process by name is not suppported in kdp remote debugging"); -    return error; +Error ProcessKDP::DoAttachToProcessWithName( +    const char *process_name, const ProcessAttachInfo &attach_info) { +  Error error; +  error.SetErrorString( +      "attach to process by name is not suppported in kdp remote debugging"); +  return error;  } +void ProcessKDP::DidAttach(ArchSpec &process_arch) { +  Process::DidAttach(process_arch); -void -ProcessKDP::DidAttach (ArchSpec &process_arch) -{ -    Process::DidAttach(process_arch); -     -    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS)); -    if (log) -        log->Printf ("ProcessKDP::DidAttach()"); -    if (GetID() != LLDB_INVALID_PROCESS_ID) -    { -        GetHostArchitecture(process_arch); -    } +  Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); +  if (log) +    log->Printf("ProcessKDP::DidAttach()"); +  if (GetID() != LLDB_INVALID_PROCESS_ID) { +    GetHostArchitecture(process_arch); +  }  } -addr_t -ProcessKDP::GetImageInfoAddress() -{ -    return m_kernel_load_addr; -} +addr_t ProcessKDP::GetImageInfoAddress() { return m_kernel_load_addr; } -lldb_private::DynamicLoader * -ProcessKDP::GetDynamicLoader () -{ -    if (m_dyld_ap.get() == NULL) -        m_dyld_ap.reset (DynamicLoader::FindPlugin(this, m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString())); -    return m_dyld_ap.get(); +lldb_private::DynamicLoader *ProcessKDP::GetDynamicLoader() { +  if (m_dyld_ap.get() == NULL) +    m_dyld_ap.reset(DynamicLoader::FindPlugin( +        this, +        m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString())); +  return m_dyld_ap.get();  } -Error -ProcessKDP::WillResume () -{ -    return Error(); -} +Error ProcessKDP::WillResume() { return Error(); } -Error -ProcessKDP::DoResume () -{ -    Error error; -    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS)); -    // Only start the async thread if we try to do any process control -    if (!m_async_thread.IsJoinable()) -        StartAsyncThread(); - -    bool resume = false; -     -    // With KDP there is only one thread we can tell what to do -    ThreadSP kernel_thread_sp (m_thread_list.FindThreadByProtocolID(g_kernel_tid)); -                             -    if (kernel_thread_sp) -    { -        const StateType thread_resume_state = kernel_thread_sp->GetTemporaryResumeState(); -         -        if (log) -            log->Printf ("ProcessKDP::DoResume() thread_resume_state = %s", StateAsCString(thread_resume_state)); -        switch (thread_resume_state) -        { -            case eStateSuspended: -                // Nothing to do here when a thread will stay suspended -                // we just leave the CPU mask bit set to zero for the thread -                if (log) -                    log->Printf ("ProcessKDP::DoResume() = suspended???"); -                break; -                 -            case eStateStepping: -                { -                    lldb::RegisterContextSP reg_ctx_sp (kernel_thread_sp->GetRegisterContext()); - -                    if (reg_ctx_sp) -                    { -                        if (log) -                            log->Printf ("ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (true);"); -                        reg_ctx_sp->HardwareSingleStep (true); -                        resume = true; -                    } -                    else -                    { -                        error.SetErrorStringWithFormat("KDP thread 0x%llx has no register context", kernel_thread_sp->GetID()); -                    } -                } -                break; -     -            case eStateRunning: -                { -                    lldb::RegisterContextSP reg_ctx_sp (kernel_thread_sp->GetRegisterContext()); -                     -                    if (reg_ctx_sp) -                    { -                        if (log) -                            log->Printf ("ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (false);"); -                        reg_ctx_sp->HardwareSingleStep (false); -                        resume = true; -                    } -                    else -                    { -                        error.SetErrorStringWithFormat("KDP thread 0x%llx has no register context", kernel_thread_sp->GetID()); -                    } -                } -                break; +Error ProcessKDP::DoResume() { +  Error error; +  Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); +  // Only start the async thread if we try to do any process control +  if (!m_async_thread.IsJoinable()) +    StartAsyncThread(); -            default: -                // The only valid thread resume states are listed above -                assert (!"invalid thread resume state"); -                break; -        } -    } +  bool resume = false; + +  // With KDP there is only one thread we can tell what to do +  ThreadSP kernel_thread_sp(m_thread_list.FindThreadByProtocolID(g_kernel_tid)); + +  if (kernel_thread_sp) { +    const StateType thread_resume_state = +        kernel_thread_sp->GetTemporaryResumeState(); -    if (resume) -    { +    if (log) +      log->Printf("ProcessKDP::DoResume() thread_resume_state = %s", +                  StateAsCString(thread_resume_state)); +    switch (thread_resume_state) { +    case eStateSuspended: +      // Nothing to do here when a thread will stay suspended +      // we just leave the CPU mask bit set to zero for the thread +      if (log) +        log->Printf("ProcessKDP::DoResume() = suspended???"); +      break; + +    case eStateStepping: { +      lldb::RegisterContextSP reg_ctx_sp( +          kernel_thread_sp->GetRegisterContext()); + +      if (reg_ctx_sp) {          if (log) -            log->Printf ("ProcessKDP::DoResume () sending resume"); -         -        if (m_comm.SendRequestResume ()) -        { -            m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue); -            SetPrivateState(eStateRunning); -        } -        else -            error.SetErrorString ("KDP resume failed"); -    } -    else -    { -        error.SetErrorString ("kernel thread is suspended");         +          log->Printf( +              "ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (true);"); +        reg_ctx_sp->HardwareSingleStep(true); +        resume = true; +      } else { +        error.SetErrorStringWithFormat( +            "KDP thread 0x%llx has no register context", +            kernel_thread_sp->GetID()); +      } +    } break; + +    case eStateRunning: { +      lldb::RegisterContextSP reg_ctx_sp( +          kernel_thread_sp->GetRegisterContext()); + +      if (reg_ctx_sp) { +        if (log) +          log->Printf("ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep " +                      "(false);"); +        reg_ctx_sp->HardwareSingleStep(false); +        resume = true; +      } else { +        error.SetErrorStringWithFormat( +            "KDP thread 0x%llx has no register context", +            kernel_thread_sp->GetID()); +      } +    } break; + +    default: +      // The only valid thread resume states are listed above +      assert(!"invalid thread resume state"); +      break;      } -     -    return error; -} +  } -lldb::ThreadSP -ProcessKDP::GetKernelThread() -{ -    // KDP only tells us about one thread/core. Any other threads will usually -    // be the ones that are read from memory by the OS plug-ins. -     -    ThreadSP thread_sp (m_kernel_thread_wp.lock()); -    if (!thread_sp) -    { -        thread_sp.reset(new ThreadKDP (*this, g_kernel_tid)); -        m_kernel_thread_wp = thread_sp; -    } -    return thread_sp; +  if (resume) { +    if (log) +      log->Printf("ProcessKDP::DoResume () sending resume"); + +    if (m_comm.SendRequestResume()) { +      m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue); +      SetPrivateState(eStateRunning); +    } else +      error.SetErrorString("KDP resume failed"); +  } else { +    error.SetErrorString("kernel thread is suspended"); +  } + +  return error;  } +lldb::ThreadSP ProcessKDP::GetKernelThread() { +  // KDP only tells us about one thread/core. Any other threads will usually +  // be the ones that are read from memory by the OS plug-ins. +  ThreadSP thread_sp(m_kernel_thread_wp.lock()); +  if (!thread_sp) { +    thread_sp.reset(new ThreadKDP(*this, g_kernel_tid)); +    m_kernel_thread_wp = thread_sp; +  } +  return thread_sp; +} - -bool -ProcessKDP::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list) -{ -    // locker will keep a mutex locked until it goes out of scope -    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_THREAD)); -    if (log && log->GetMask().Test(KDP_LOG_VERBOSE)) -        log->Printf ("ProcessKDP::%s (pid = %" PRIu64 ")", __FUNCTION__, GetID()); -     -    // Even though there is a CPU mask, it doesn't mean we can see each CPU -    // individually, there is really only one. Lets call this thread 1. -    ThreadSP thread_sp (old_thread_list.FindThreadByProtocolID(g_kernel_tid, false)); -    if (!thread_sp) -        thread_sp = GetKernelThread (); -    new_thread_list.AddThread(thread_sp); - -    return new_thread_list.GetSize(false) > 0; +bool ProcessKDP::UpdateThreadList(ThreadList &old_thread_list, +                                  ThreadList &new_thread_list) { +  // locker will keep a mutex locked until it goes out of scope +  Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_THREAD)); +  if (log && log->GetMask().Test(KDP_LOG_VERBOSE)) +    log->Printf("ProcessKDP::%s (pid = %" PRIu64 ")", __FUNCTION__, GetID()); + +  // Even though there is a CPU mask, it doesn't mean we can see each CPU +  // individually, there is really only one. Lets call this thread 1. +  ThreadSP thread_sp( +      old_thread_list.FindThreadByProtocolID(g_kernel_tid, false)); +  if (!thread_sp) +    thread_sp = GetKernelThread(); +  new_thread_list.AddThread(thread_sp); + +  return new_thread_list.GetSize(false) > 0;  } -void -ProcessKDP::RefreshStateAfterStop () -{ -    // Let all threads recover from stopping and do any clean up based -    // on the previous thread state (if any). -    m_thread_list.RefreshStateAfterStop(); +void ProcessKDP::RefreshStateAfterStop() { +  // Let all threads recover from stopping and do any clean up based +  // on the previous thread state (if any). +  m_thread_list.RefreshStateAfterStop();  } -Error -ProcessKDP::DoHalt (bool &caused_stop) -{ -    Error error; -     -    if (m_comm.IsRunning()) -    { -        if (m_destroy_in_process) -        { -            // If we are attemping to destroy, we need to not return an error to -            // Halt or DoDestroy won't get called. -            // We are also currently running, so send a process stopped event -            SetPrivateState (eStateStopped); -        } -        else -        { -            error.SetErrorString ("KDP cannot interrupt a running kernel"); -        } +Error ProcessKDP::DoHalt(bool &caused_stop) { +  Error error; + +  if (m_comm.IsRunning()) { +    if (m_destroy_in_process) { +      // If we are attemping to destroy, we need to not return an error to +      // Halt or DoDestroy won't get called. +      // We are also currently running, so send a process stopped event +      SetPrivateState(eStateStopped); +    } else { +      error.SetErrorString("KDP cannot interrupt a running kernel");      } -    return error; +  } +  return error;  } -Error -ProcessKDP::DoDetach(bool keep_stopped) -{ -    Error error; -    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); -    if (log) -        log->Printf ("ProcessKDP::DoDetach(keep_stopped = %i)", keep_stopped); -     -    if (m_comm.IsRunning()) -    { -        // We are running and we can't interrupt a running kernel, so we need -        // to just close the connection to the kernel and hope for the best -    } -    else -    { -        // If we are going to keep the target stopped, then don't send the disconnect message. -        if (!keep_stopped && m_comm.IsConnected()) -        { -            const bool success = m_comm.SendRequestDisconnect(); -            if (log) -            { -                if (success) -                    log->PutCString ("ProcessKDP::DoDetach() detach packet sent successfully"); -                else -                    log->PutCString ("ProcessKDP::DoDetach() connection channel shutdown failed"); -            } -            m_comm.Disconnect (); -        } +Error ProcessKDP::DoDetach(bool keep_stopped) { +  Error error; +  Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); +  if (log) +    log->Printf("ProcessKDP::DoDetach(keep_stopped = %i)", keep_stopped); + +  if (m_comm.IsRunning()) { +    // We are running and we can't interrupt a running kernel, so we need +    // to just close the connection to the kernel and hope for the best +  } else { +    // If we are going to keep the target stopped, then don't send the +    // disconnect message. +    if (!keep_stopped && m_comm.IsConnected()) { +      const bool success = m_comm.SendRequestDisconnect(); +      if (log) { +        if (success) +          log->PutCString( +              "ProcessKDP::DoDetach() detach packet sent successfully"); +        else +          log->PutCString( +              "ProcessKDP::DoDetach() connection channel shutdown failed"); +      } +      m_comm.Disconnect();      } -    StopAsyncThread ();     -    m_comm.Clear(); -     -    SetPrivateState (eStateDetached); -    ResumePrivateStateThread(); -     -    //KillDebugserverProcess (); -    return error; +  } +  StopAsyncThread(); +  m_comm.Clear(); + +  SetPrivateState(eStateDetached); +  ResumePrivateStateThread(); + +  // KillDebugserverProcess (); +  return error;  } -Error -ProcessKDP::DoDestroy () -{ -    // For KDP there really is no difference between destroy and detach -    bool keep_stopped = false; -    return DoDetach(keep_stopped); +Error ProcessKDP::DoDestroy() { +  // For KDP there really is no difference between destroy and detach +  bool keep_stopped = false; +  return DoDetach(keep_stopped);  }  //------------------------------------------------------------------  // Process Queries  //------------------------------------------------------------------ -bool -ProcessKDP::IsAlive () -{ -    return m_comm.IsConnected() && Process::IsAlive(); +bool ProcessKDP::IsAlive() { +  return m_comm.IsConnected() && Process::IsAlive();  }  //------------------------------------------------------------------  // Process Memory  //------------------------------------------------------------------ -size_t -ProcessKDP::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error) -{ -    uint8_t *data_buffer = (uint8_t *) buf; -    if (m_comm.IsConnected()) -    { -        const size_t max_read_size = 512; -        size_t total_bytes_read = 0; - -        // Read the requested amount of memory in 512 byte chunks -        while (total_bytes_read < size) -        { -            size_t bytes_to_read_this_request = size - total_bytes_read; -            if (bytes_to_read_this_request > max_read_size) -            { -                bytes_to_read_this_request = max_read_size; -            } -            size_t bytes_read = m_comm.SendRequestReadMemory (addr + total_bytes_read,  -                                                              data_buffer + total_bytes_read,  -                                                              bytes_to_read_this_request, error); -            total_bytes_read += bytes_read; -            if (error.Fail() || bytes_read == 0) -            { -                return total_bytes_read; -            } -        } - +size_t ProcessKDP::DoReadMemory(addr_t addr, void *buf, size_t size, +                                Error &error) { +  uint8_t *data_buffer = (uint8_t *)buf; +  if (m_comm.IsConnected()) { +    const size_t max_read_size = 512; +    size_t total_bytes_read = 0; + +    // Read the requested amount of memory in 512 byte chunks +    while (total_bytes_read < size) { +      size_t bytes_to_read_this_request = size - total_bytes_read; +      if (bytes_to_read_this_request > max_read_size) { +        bytes_to_read_this_request = max_read_size; +      } +      size_t bytes_read = m_comm.SendRequestReadMemory( +          addr + total_bytes_read, data_buffer + total_bytes_read, +          bytes_to_read_this_request, error); +      total_bytes_read += bytes_read; +      if (error.Fail() || bytes_read == 0) {          return total_bytes_read; +      }      } -    error.SetErrorString ("not connected"); -    return 0; -} -size_t -ProcessKDP::DoWriteMemory (addr_t addr, const void *buf, size_t size, Error &error) -{ -    if (m_comm.IsConnected()) -        return m_comm.SendRequestWriteMemory (addr, buf, size, error); -    error.SetErrorString ("not connected"); -    return 0; +    return total_bytes_read; +  } +  error.SetErrorString("not connected"); +  return 0;  } -lldb::addr_t -ProcessKDP::DoAllocateMemory (size_t size, uint32_t permissions, Error &error) -{ -    error.SetErrorString ("memory allocation not suppported in kdp remote debugging"); -    return LLDB_INVALID_ADDRESS; +size_t ProcessKDP::DoWriteMemory(addr_t addr, const void *buf, size_t size, +                                 Error &error) { +  if (m_comm.IsConnected()) +    return m_comm.SendRequestWriteMemory(addr, buf, size, error); +  error.SetErrorString("not connected"); +  return 0;  } -Error -ProcessKDP::DoDeallocateMemory (lldb::addr_t addr) -{ -    Error error; -    error.SetErrorString ("memory deallocation not suppported in kdp remote debugging"); -    return error; +lldb::addr_t ProcessKDP::DoAllocateMemory(size_t size, uint32_t permissions, +                                          Error &error) { +  error.SetErrorString( +      "memory allocation not suppported in kdp remote debugging"); +  return LLDB_INVALID_ADDRESS;  } -Error -ProcessKDP::EnableBreakpointSite (BreakpointSite *bp_site) -{ -    if (m_comm.LocalBreakpointsAreSupported ()) -    { -        Error error; -        if (!bp_site->IsEnabled()) -        { -            if (m_comm.SendRequestBreakpoint(true, bp_site->GetLoadAddress())) -            { -                bp_site->SetEnabled(true); -                bp_site->SetType (BreakpointSite::eExternal); -            } -            else -            { -                error.SetErrorString ("KDP set breakpoint failed"); -            } -        } -        return error; -    } -    return EnableSoftwareBreakpoint (bp_site); +Error ProcessKDP::DoDeallocateMemory(lldb::addr_t addr) { +  Error error; +  error.SetErrorString( +      "memory deallocation not suppported in kdp remote debugging"); +  return error;  } -Error -ProcessKDP::DisableBreakpointSite (BreakpointSite *bp_site) -{ -    if (m_comm.LocalBreakpointsAreSupported ()) -    { -        Error error; -        if (bp_site->IsEnabled()) -        { -            BreakpointSite::Type bp_type = bp_site->GetType(); -            if (bp_type == BreakpointSite::eExternal) -            { -                if (m_destroy_in_process && m_comm.IsRunning()) -                { -                    // We are trying to destroy our connection and we are running -                    bp_site->SetEnabled(false); -                } -                else -                { -                    if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress())) -                        bp_site->SetEnabled(false); -                    else -                        error.SetErrorString ("KDP remove breakpoint failed"); -                } -            } -            else -            { -                error = DisableSoftwareBreakpoint (bp_site); -            } -        } -        return error; +Error ProcessKDP::EnableBreakpointSite(BreakpointSite *bp_site) { +  if (m_comm.LocalBreakpointsAreSupported()) { +    Error error; +    if (!bp_site->IsEnabled()) { +      if (m_comm.SendRequestBreakpoint(true, bp_site->GetLoadAddress())) { +        bp_site->SetEnabled(true); +        bp_site->SetType(BreakpointSite::eExternal); +      } else { +        error.SetErrorString("KDP set breakpoint failed"); +      }      } -    return DisableSoftwareBreakpoint (bp_site); +    return error; +  } +  return EnableSoftwareBreakpoint(bp_site);  } -Error -ProcessKDP::EnableWatchpoint (Watchpoint *wp, bool notify) -{ +Error ProcessKDP::DisableBreakpointSite(BreakpointSite *bp_site) { +  if (m_comm.LocalBreakpointsAreSupported()) {      Error error; -    error.SetErrorString ("watchpoints are not suppported in kdp remote debugging"); +    if (bp_site->IsEnabled()) { +      BreakpointSite::Type bp_type = bp_site->GetType(); +      if (bp_type == BreakpointSite::eExternal) { +        if (m_destroy_in_process && m_comm.IsRunning()) { +          // We are trying to destroy our connection and we are running +          bp_site->SetEnabled(false); +        } else { +          if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress())) +            bp_site->SetEnabled(false); +          else +            error.SetErrorString("KDP remove breakpoint failed"); +        } +      } else { +        error = DisableSoftwareBreakpoint(bp_site); +      } +    }      return error; +  } +  return DisableSoftwareBreakpoint(bp_site);  } -Error -ProcessKDP::DisableWatchpoint (Watchpoint *wp, bool notify) -{ -    Error error; -    error.SetErrorString ("watchpoints are not suppported in kdp remote debugging"); -    return error; +Error ProcessKDP::EnableWatchpoint(Watchpoint *wp, bool notify) { +  Error error; +  error.SetErrorString( +      "watchpoints are not suppported in kdp remote debugging"); +  return error;  } -void -ProcessKDP::Clear() -{ -    m_thread_list.Clear(); +Error ProcessKDP::DisableWatchpoint(Watchpoint *wp, bool notify) { +  Error error; +  error.SetErrorString( +      "watchpoints are not suppported in kdp remote debugging"); +  return error;  } -Error -ProcessKDP::DoSignal (int signo) -{ -    Error error; -    error.SetErrorString ("sending signals is not suppported in kdp remote debugging"); -    return error; +void ProcessKDP::Clear() { m_thread_list.Clear(); } + +Error ProcessKDP::DoSignal(int signo) { +  Error error; +  error.SetErrorString( +      "sending signals is not suppported in kdp remote debugging"); +  return error;  } -void -ProcessKDP::Initialize() -{ -    static std::once_flag g_once_flag; - -    std::call_once(g_once_flag, []() -    { -        PluginManager::RegisterPlugin (GetPluginNameStatic(), -                                       GetPluginDescriptionStatic(), -                                       CreateInstance, -                                       DebuggerInitialize); - -        Log::Callbacks log_callbacks = { -            ProcessKDPLog::DisableLog, -            ProcessKDPLog::EnableLog, -            ProcessKDPLog::ListLogCategories -        }; - -        Log::RegisterLogChannel (ProcessKDP::GetPluginNameStatic(), log_callbacks); -    }); +void ProcessKDP::Initialize() { +  static std::once_flag g_once_flag; + +  std::call_once(g_once_flag, []() { +    PluginManager::RegisterPlugin(GetPluginNameStatic(), +                                  GetPluginDescriptionStatic(), CreateInstance, +                                  DebuggerInitialize); + +    Log::Callbacks log_callbacks = {ProcessKDPLog::DisableLog, +                                    ProcessKDPLog::EnableLog, +                                    ProcessKDPLog::ListLogCategories}; + +    Log::RegisterLogChannel(ProcessKDP::GetPluginNameStatic(), log_callbacks); +  });  } -void -ProcessKDP::DebuggerInitialize (lldb_private::Debugger &debugger) -{ -    if (!PluginManager::GetSettingForProcessPlugin(debugger, PluginProperties::GetSettingName())) -    { -        const bool is_global_setting = true; -        PluginManager::CreateSettingForProcessPlugin (debugger, -                                                      GetGlobalPluginProperties()->GetValueProperties(), -                                                      ConstString ("Properties for the kdp-remote process plug-in."), -                                                      is_global_setting); -    } +void ProcessKDP::DebuggerInitialize(lldb_private::Debugger &debugger) { +  if (!PluginManager::GetSettingForProcessPlugin( +          debugger, PluginProperties::GetSettingName())) { +    const bool is_global_setting = true; +    PluginManager::CreateSettingForProcessPlugin( +        debugger, GetGlobalPluginProperties()->GetValueProperties(), +        ConstString("Properties for the kdp-remote process plug-in."), +        is_global_setting); +  }  } -bool -ProcessKDP::StartAsyncThread () -{ -    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); -     -    if (log) -        log->Printf ("ProcessKDP::StartAsyncThread ()"); +bool ProcessKDP::StartAsyncThread() { +  Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); -    if (m_async_thread.IsJoinable()) -        return true; +  if (log) +    log->Printf("ProcessKDP::StartAsyncThread ()"); -    m_async_thread = ThreadLauncher::LaunchThread("<lldb.process.kdp-remote.async>", ProcessKDP::AsyncThread, this, NULL); -    return m_async_thread.IsJoinable(); -} +  if (m_async_thread.IsJoinable()) +    return true; -void -ProcessKDP::StopAsyncThread () -{ -    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); -     -    if (log) -        log->Printf ("ProcessKDP::StopAsyncThread ()"); -     -    m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit); -     -    // Stop the stdio thread -    if (m_async_thread.IsJoinable()) -        m_async_thread.Join(nullptr); +  m_async_thread = ThreadLauncher::LaunchThread( +      "<lldb.process.kdp-remote.async>", ProcessKDP::AsyncThread, this, NULL); +  return m_async_thread.IsJoinable();  } +void ProcessKDP::StopAsyncThread() { +  Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); -void * -ProcessKDP::AsyncThread (void *arg) -{ -    ProcessKDP *process = (ProcessKDP*) arg; -     -    const lldb::pid_t pid = process->GetID(); +  if (log) +    log->Printf("ProcessKDP::StopAsyncThread ()"); -    Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS)); -    if (log) -        log->Printf ("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 ") thread starting...", arg, pid); -     -    ListenerSP listener_sp (Listener::MakeListener("ProcessKDP::AsyncThread")); -    EventSP event_sp; -    const uint32_t desired_event_mask = eBroadcastBitAsyncContinue | -                                        eBroadcastBitAsyncThreadShouldExit; -     -     -    if (listener_sp->StartListeningForEvents (&process->m_async_broadcaster, desired_event_mask) == desired_event_mask) -    { -        bool done = false; -        while (!done) -        { -            if (log) -                log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp)...", -                             pid); -            if (listener_sp->WaitForEvent (NULL, event_sp)) -            { -                uint32_t event_type = event_sp->GetType(); -                if (log) -                    log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") Got an event of type: %d...", -                                 pid, -                                 event_type); -                 -                // When we are running, poll for 1 second to try and get an exception -                // to indicate the process has stopped. If we don't get one, check to -                // make sure no one asked us to exit -                bool is_running = false; -                DataExtractor exc_reply_packet; -                do -                { -                    switch (event_type) -                    { -                    case eBroadcastBitAsyncContinue: -                        { -                            is_running = true; -                            if (process->m_comm.WaitForPacketWithTimeoutMicroSeconds (exc_reply_packet, 1 * USEC_PER_SEC)) -                            { -                                ThreadSP thread_sp (process->GetKernelThread()); -                                if (thread_sp) -                                { -                                    lldb::RegisterContextSP reg_ctx_sp (thread_sp->GetRegisterContext()); -                                    if (reg_ctx_sp) -                                        reg_ctx_sp->InvalidateAllRegisters(); -                                    static_cast<ThreadKDP *>(thread_sp.get())->SetStopInfoFrom_KDP_EXCEPTION (exc_reply_packet); -                                } - -                                // TODO: parse the stop reply packet -                                is_running = false;                                 -                                process->SetPrivateState(eStateStopped); -                            } -                            else -                            { -                                // Check to see if we are supposed to exit. There is no way to -                                // interrupt a running kernel, so all we can do is wait for an -                                // exception or detach... -                                if (listener_sp->GetNextEvent(event_sp)) -                                { -                                    // We got an event, go through the loop again -                                    event_type = event_sp->GetType(); -                                } -                            } -                        } -                        break; -                             -                    case eBroadcastBitAsyncThreadShouldExit: -                        if (log) -                            log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") got eBroadcastBitAsyncThreadShouldExit...", -                                         pid); -                        done = true; -                        is_running = false; -                        break; -                             -                    default: -                        if (log) -                            log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") got unknown event 0x%8.8x", -                                         pid, -                                         event_type); -                        done = true; -                        is_running = false; -                        break; -                    } -                } while (is_running); -            } -            else -            { -                if (log) -                    log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp) => false", -                                 pid); -                done = true; +  m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit); + +  // Stop the stdio thread +  if (m_async_thread.IsJoinable()) +    m_async_thread.Join(nullptr); +} + +void *ProcessKDP::AsyncThread(void *arg) { +  ProcessKDP *process = (ProcessKDP *)arg; + +  const lldb::pid_t pid = process->GetID(); + +  Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); +  if (log) +    log->Printf("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 +                ") thread starting...", +                arg, pid); + +  ListenerSP listener_sp(Listener::MakeListener("ProcessKDP::AsyncThread")); +  EventSP event_sp; +  const uint32_t desired_event_mask = +      eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit; + +  if (listener_sp->StartListeningForEvents(&process->m_async_broadcaster, +                                           desired_event_mask) == +      desired_event_mask) { +    bool done = false; +    while (!done) { +      if (log) +        log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 +                    ") listener.WaitForEvent (NULL, event_sp)...", +                    pid); +      if (listener_sp->GetEvent(event_sp, llvm::None)) { +        uint32_t event_type = event_sp->GetType(); +        if (log) +          log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 +                      ") Got an event of type: %d...", +                      pid, event_type); + +        // When we are running, poll for 1 second to try and get an exception +        // to indicate the process has stopped. If we don't get one, check to +        // make sure no one asked us to exit +        bool is_running = false; +        DataExtractor exc_reply_packet; +        do { +          switch (event_type) { +          case eBroadcastBitAsyncContinue: { +            is_running = true; +            if (process->m_comm.WaitForPacketWithTimeoutMicroSeconds( +                    exc_reply_packet, 1 * USEC_PER_SEC)) { +              ThreadSP thread_sp(process->GetKernelThread()); +              if (thread_sp) { +                lldb::RegisterContextSP reg_ctx_sp( +                    thread_sp->GetRegisterContext()); +                if (reg_ctx_sp) +                  reg_ctx_sp->InvalidateAllRegisters(); +                static_cast<ThreadKDP *>(thread_sp.get()) +                    ->SetStopInfoFrom_KDP_EXCEPTION(exc_reply_packet); +              } + +              // TODO: parse the stop reply packet +              is_running = false; +              process->SetPrivateState(eStateStopped); +            } else { +              // Check to see if we are supposed to exit. There is no way to +              // interrupt a running kernel, so all we can do is wait for an +              // exception or detach... +              if (listener_sp->GetEvent(event_sp, +                                        std::chrono::microseconds(0))) { +                // We got an event, go through the loop again +                event_type = event_sp->GetType(); +              }              } -        } +          } break; + +          case eBroadcastBitAsyncThreadShouldExit: +            if (log) +              log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 +                          ") got eBroadcastBitAsyncThreadShouldExit...", +                          pid); +            done = true; +            is_running = false; +            break; + +          default: +            if (log) +              log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 +                          ") got unknown event 0x%8.8x", +                          pid, event_type); +            done = true; +            is_running = false; +            break; +          } +        } while (is_running); +      } else { +        if (log) +          log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 +                      ") listener.WaitForEvent (NULL, event_sp) => false", +                      pid); +        done = true; +      }      } -     -    if (log) -        log->Printf ("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 ") thread exiting...", -                     arg, -                     pid); +  } -    process->m_async_thread.Reset(); -    return NULL; -} +  if (log) +    log->Printf("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 +                ") thread exiting...", +                arg, pid); +  process->m_async_thread.Reset(); +  return NULL; +} -class CommandObjectProcessKDPPacketSend : public CommandObjectParsed -{ +class CommandObjectProcessKDPPacketSend : public CommandObjectParsed {  private: -     -    OptionGroupOptions m_option_group; -    OptionGroupUInt64 m_command_byte; -    OptionGroupString m_packet_data; -     -    virtual Options * -    GetOptions () -    { -        return &m_option_group; -    } -     +  OptionGroupOptions m_option_group; +  OptionGroupUInt64 m_command_byte; +  OptionGroupString m_packet_data; + +  virtual Options *GetOptions() { return &m_option_group; }  public: -    CommandObjectProcessKDPPacketSend(CommandInterpreter &interpreter) : -        CommandObjectParsed (interpreter, -                             "process plugin packet send", -                             "Send a custom packet through the KDP protocol by specifying the command byte and the packet payload data. A packet will be sent with a correct header and payload, and the raw result bytes will be displayed as a string value. ", -                             NULL), -        m_option_group (interpreter), -        m_command_byte(LLDB_OPT_SET_1, true , "command", 'c', 0, eArgTypeNone, "Specify the command byte to use when sending the KDP request packet.", 0), -        m_packet_data (LLDB_OPT_SET_1, false, "payload", 'p', 0, eArgTypeNone, "Specify packet payload bytes as a hex ASCII string with no spaces or hex prefixes.", NULL) -    { -        m_option_group.Append (&m_command_byte, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); -        m_option_group.Append (&m_packet_data , LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); -        m_option_group.Finalize(); -    } -     -    ~CommandObjectProcessKDPPacketSend () -    { -    } -     -    bool -    DoExecute (Args& command, CommandReturnObject &result) -    { -        const size_t argc = command.GetArgumentCount(); -        if (argc == 0) -        { -            if (!m_command_byte.GetOptionValue().OptionWasSet()) -            { -                result.AppendError ("the --command option must be set to a valid command byte"); -                result.SetStatus (eReturnStatusFailed); -            } -            else -            { -                const uint64_t command_byte = m_command_byte.GetOptionValue().GetUInt64Value(0); -                if (command_byte > 0 && command_byte <= UINT8_MAX) -                { -                    ProcessKDP *process = (ProcessKDP *)m_interpreter.GetExecutionContext().GetProcessPtr(); -                    if (process) -                    { -                        const StateType state = process->GetState(); -                         -                        if (StateIsStoppedState (state, true)) -                        { -                            std::vector<uint8_t> payload_bytes; -                            const char *ascii_hex_bytes_cstr = m_packet_data.GetOptionValue().GetCurrentValue(); -                            if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0]) -                            { -                                StringExtractor extractor(ascii_hex_bytes_cstr); -                                const size_t ascii_hex_bytes_cstr_len = extractor.GetStringRef().size(); -                                if (ascii_hex_bytes_cstr_len & 1) -                                { -                                    result.AppendErrorWithFormat ("payload data must contain an even number of ASCII hex characters: '%s'", ascii_hex_bytes_cstr); -                                    result.SetStatus (eReturnStatusFailed); -                                    return false; -                                } -                                payload_bytes.resize(ascii_hex_bytes_cstr_len/2); -                                if (extractor.GetHexBytes(&payload_bytes[0], payload_bytes.size(), '\xdd') != payload_bytes.size()) -                                { -                                    result.AppendErrorWithFormat ("payload data must only contain ASCII hex characters (no spaces or hex prefixes): '%s'", ascii_hex_bytes_cstr); -                                    result.SetStatus (eReturnStatusFailed); -                                    return false; -                                } -                            } -                            Error error; -                            DataExtractor reply; -                            process->GetCommunication().SendRawRequest (command_byte, -                                                                        payload_bytes.empty() ? NULL : payload_bytes.data(), -                                                                        payload_bytes.size(), -                                                                        reply, -                                                                        error); -                             -                            if (error.Success()) -                            { -                                // Copy the binary bytes into a hex ASCII string for the result -                                StreamString packet; -                                packet.PutBytesAsRawHex8(reply.GetDataStart(), -                                                         reply.GetByteSize(), -                                                         endian::InlHostByteOrder(), -                                                         endian::InlHostByteOrder()); -                                result.AppendMessage(packet.GetString().c_str()); -                                result.SetStatus (eReturnStatusSuccessFinishResult); -                                return true; -                            } -                            else -                            { -                                const char *error_cstr = error.AsCString(); -                                if (error_cstr && error_cstr[0]) -                                    result.AppendError (error_cstr); -                                else -                                    result.AppendErrorWithFormat ("unknown error 0x%8.8x", error.GetError()); -                                result.SetStatus (eReturnStatusFailed); -                                return false; -                            } -                        } -                        else -                        { -                            result.AppendErrorWithFormat ("process must be stopped in order to send KDP packets, state is %s", StateAsCString (state)); -                            result.SetStatus (eReturnStatusFailed); -                        } -                    } -                    else -                    { -                        result.AppendError ("invalid process"); -                        result.SetStatus (eReturnStatusFailed); -                    } +  CommandObjectProcessKDPPacketSend(CommandInterpreter &interpreter) +      : CommandObjectParsed(interpreter, "process plugin packet send", +                            "Send a custom packet through the KDP protocol by " +                            "specifying the command byte and the packet " +                            "payload data. A packet will be sent with a " +                            "correct header and payload, and the raw result " +                            "bytes will be displayed as a string value. ", +                            NULL), +        m_option_group(), +        m_command_byte(LLDB_OPT_SET_1, true, "command", 'c', 0, eArgTypeNone, +                       "Specify the command byte to use when sending the KDP " +                       "request packet.", +                       0), +        m_packet_data(LLDB_OPT_SET_1, false, "payload", 'p', 0, eArgTypeNone, +                      "Specify packet payload bytes as a hex ASCII string with " +                      "no spaces or hex prefixes.", +                      NULL) { +    m_option_group.Append(&m_command_byte, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); +    m_option_group.Append(&m_packet_data, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); +    m_option_group.Finalize(); +  } + +  ~CommandObjectProcessKDPPacketSend() {} + +  bool DoExecute(Args &command, CommandReturnObject &result) { +    const size_t argc = command.GetArgumentCount(); +    if (argc == 0) { +      if (!m_command_byte.GetOptionValue().OptionWasSet()) { +        result.AppendError( +            "the --command option must be set to a valid command byte"); +        result.SetStatus(eReturnStatusFailed); +      } else { +        const uint64_t command_byte = +            m_command_byte.GetOptionValue().GetUInt64Value(0); +        if (command_byte > 0 && command_byte <= UINT8_MAX) { +          ProcessKDP *process = +              (ProcessKDP *)m_interpreter.GetExecutionContext().GetProcessPtr(); +          if (process) { +            const StateType state = process->GetState(); + +            if (StateIsStoppedState(state, true)) { +              std::vector<uint8_t> payload_bytes; +              const char *ascii_hex_bytes_cstr = +                  m_packet_data.GetOptionValue().GetCurrentValue(); +              if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0]) { +                StringExtractor extractor(ascii_hex_bytes_cstr); +                const size_t ascii_hex_bytes_cstr_len = +                    extractor.GetStringRef().size(); +                if (ascii_hex_bytes_cstr_len & 1) { +                  result.AppendErrorWithFormat("payload data must contain an " +                                               "even number of ASCII hex " +                                               "characters: '%s'", +                                               ascii_hex_bytes_cstr); +                  result.SetStatus(eReturnStatusFailed); +                  return false;                  } -                else -                { -                    result.AppendErrorWithFormat ("invalid command byte 0x%" PRIx64 ", valid values are 1 - 255", command_byte); -                    result.SetStatus (eReturnStatusFailed); +                payload_bytes.resize(ascii_hex_bytes_cstr_len / 2); +                if (extractor.GetHexBytes(payload_bytes, '\xdd') != +                    payload_bytes.size()) { +                  result.AppendErrorWithFormat("payload data must only contain " +                                               "ASCII hex characters (no " +                                               "spaces or hex prefixes): '%s'", +                                               ascii_hex_bytes_cstr); +                  result.SetStatus(eReturnStatusFailed); +                  return false;                  } +              } +              Error error; +              DataExtractor reply; +              process->GetCommunication().SendRawRequest( +                  command_byte, +                  payload_bytes.empty() ? NULL : payload_bytes.data(), +                  payload_bytes.size(), reply, error); + +              if (error.Success()) { +                // Copy the binary bytes into a hex ASCII string for the result +                StreamString packet; +                packet.PutBytesAsRawHex8( +                    reply.GetDataStart(), reply.GetByteSize(), +                    endian::InlHostByteOrder(), endian::InlHostByteOrder()); +                result.AppendMessage(packet.GetString()); +                result.SetStatus(eReturnStatusSuccessFinishResult); +                return true; +              } else { +                const char *error_cstr = error.AsCString(); +                if (error_cstr && error_cstr[0]) +                  result.AppendError(error_cstr); +                else +                  result.AppendErrorWithFormat("unknown error 0x%8.8x", +                                               error.GetError()); +                result.SetStatus(eReturnStatusFailed); +                return false; +              } +            } else { +              result.AppendErrorWithFormat("process must be stopped in order " +                                           "to send KDP packets, state is %s", +                                           StateAsCString(state)); +              result.SetStatus(eReturnStatusFailed);              } +          } else { +            result.AppendError("invalid process"); +            result.SetStatus(eReturnStatusFailed); +          } +        } else { +          result.AppendErrorWithFormat("invalid command byte 0x%" PRIx64 +                                       ", valid values are 1 - 255", +                                       command_byte); +          result.SetStatus(eReturnStatusFailed);          } -        else -        { -            result.AppendErrorWithFormat ("'%s' takes no arguments, only options.", m_cmd_name.c_str()); -            result.SetStatus (eReturnStatusFailed); -        } -        return false; +      } +    } else { +      result.AppendErrorWithFormat("'%s' takes no arguments, only options.", +                                   m_cmd_name.c_str()); +      result.SetStatus(eReturnStatusFailed);      } +    return false; +  }  }; -class CommandObjectProcessKDPPacket : public CommandObjectMultiword -{ +class CommandObjectProcessKDPPacket : public CommandObjectMultiword {  private: -  public: -    CommandObjectProcessKDPPacket(CommandInterpreter &interpreter) : -    CommandObjectMultiword (interpreter, -                            "process plugin packet", -                            "Commands that deal with KDP remote packets.", -                            NULL) -    { -        LoadSubCommand ("send", CommandObjectSP (new CommandObjectProcessKDPPacketSend (interpreter))); -    } -     -    ~CommandObjectProcessKDPPacket () -    { -    } +  CommandObjectProcessKDPPacket(CommandInterpreter &interpreter) +      : CommandObjectMultiword(interpreter, "process plugin packet", +                               "Commands that deal with KDP remote packets.", +                               NULL) { +    LoadSubCommand( +        "send", +        CommandObjectSP(new CommandObjectProcessKDPPacketSend(interpreter))); +  } + +  ~CommandObjectProcessKDPPacket() {}  }; -class CommandObjectMultiwordProcessKDP : public CommandObjectMultiword -{ +class CommandObjectMultiwordProcessKDP : public CommandObjectMultiword {  public: -    CommandObjectMultiwordProcessKDP(CommandInterpreter &interpreter) -        : CommandObjectMultiword(interpreter, "process plugin", "Commands for operating on a ProcessKDP process.", -                                 "process plugin <subcommand> [<subcommand-options>]") -    { -        LoadSubCommand ("packet", CommandObjectSP (new CommandObjectProcessKDPPacket    (interpreter))); -    } -     -    ~CommandObjectMultiwordProcessKDP () -    { -    } +  CommandObjectMultiwordProcessKDP(CommandInterpreter &interpreter) +      : CommandObjectMultiword( +            interpreter, "process plugin", +            "Commands for operating on a ProcessKDP process.", +            "process plugin <subcommand> [<subcommand-options>]") { +    LoadSubCommand("packet", CommandObjectSP(new CommandObjectProcessKDPPacket( +                                 interpreter))); +  } + +  ~CommandObjectMultiwordProcessKDP() {}  }; -CommandObject * -ProcessKDP::GetPluginCommandObject() -{ -    if (!m_command_sp) -        m_command_sp.reset (new CommandObjectMultiwordProcessKDP (GetTarget().GetDebugger().GetCommandInterpreter())); -    return m_command_sp.get(); +CommandObject *ProcessKDP::GetPluginCommandObject() { +  if (!m_command_sp) +    m_command_sp.reset(new CommandObjectMultiwordProcessKDP( +        GetTarget().GetDebugger().GetCommandInterpreter())); +  return m_command_sp.get();  } -  | 
