brintos

brintos / llvm-project-archived public Read only

0
0
Text · 34.0 KiB · 3c26afa Raw
985 lines · cpp
1//===-- ProcessKDP.cpp ----------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include <cerrno>10#include <cstdlib>11 12#include <memory>13#include <mutex>14 15#include "lldb/Core/Debugger.h"16#include "lldb/Core/Module.h"17#include "lldb/Core/ModuleSpec.h"18#include "lldb/Core/PluginManager.h"19#include "lldb/Host/ConnectionFileDescriptor.h"20#include "lldb/Host/Host.h"21#include "lldb/Host/ThreadLauncher.h"22#include "lldb/Host/common/TCPSocket.h"23#include "lldb/Interpreter/CommandInterpreter.h"24#include "lldb/Interpreter/CommandObject.h"25#include "lldb/Interpreter/CommandObjectMultiword.h"26#include "lldb/Interpreter/CommandReturnObject.h"27#include "lldb/Interpreter/OptionGroupString.h"28#include "lldb/Interpreter/OptionGroupUInt64.h"29#include "lldb/Interpreter/OptionValueProperties.h"30#include "lldb/Symbol/ObjectFile.h"31#include "lldb/Target/RegisterContext.h"32#include "lldb/Target/Target.h"33#include "lldb/Target/Thread.h"34#include "lldb/Utility/LLDBLog.h"35#include "lldb/Utility/Log.h"36#include "lldb/Utility/State.h"37#include "lldb/Utility/StringExtractor.h"38#include "lldb/Utility/UUID.h"39 40#include "llvm/Support/Threading.h"41 42#define USEC_PER_SEC 100000043 44#include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h"45#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"46#include "ProcessKDP.h"47#include "ProcessKDPLog.h"48#include "ThreadKDP.h"49 50using namespace lldb;51using namespace lldb_private;52 53LLDB_PLUGIN_DEFINE_ADV(ProcessKDP, ProcessMacOSXKernel)54 55namespace {56 57#define LLDB_PROPERTIES_processkdp58#include "ProcessKDPProperties.inc"59 60enum {61#define LLDB_PROPERTIES_processkdp62#include "ProcessKDPPropertiesEnum.inc"63};64 65class PluginProperties : public Properties {66public:67  static llvm::StringRef GetSettingName() {68    return ProcessKDP::GetPluginNameStatic();69  }70 71  PluginProperties() : Properties() {72    m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());73    m_collection_sp->Initialize(g_processkdp_properties);74  }75 76  ~PluginProperties() override = default;77 78  uint64_t GetPacketTimeout() {79    const uint32_t idx = ePropertyKDPPacketTimeout;80    return GetPropertyAtIndexAs<uint64_t>(81        idx, g_processkdp_properties[idx].default_uint_value);82  }83};84 85} // namespace86 87static PluginProperties &GetGlobalPluginProperties() {88  static PluginProperties g_settings;89  return g_settings;90}91 92static const lldb::tid_t g_kernel_tid = 1;93 94llvm::StringRef ProcessKDP::GetPluginDescriptionStatic() {95  return "KDP Remote protocol based debugging plug-in for darwin kernel "96         "debugging.";97}98 99void ProcessKDP::Terminate() {100  PluginManager::UnregisterPlugin(ProcessKDP::CreateInstance);101}102 103lldb::ProcessSP ProcessKDP::CreateInstance(TargetSP target_sp,104                                           ListenerSP listener_sp,105                                           const FileSpec *crash_file_path,106                                           bool can_connect) {107  lldb::ProcessSP process_sp;108  if (crash_file_path == NULL)109    process_sp = std::make_shared<ProcessKDP>(target_sp, listener_sp);110  return process_sp;111}112 113bool ProcessKDP::CanDebug(TargetSP target_sp, bool plugin_specified_by_name) {114  if (plugin_specified_by_name)115    return true;116 117  // For now we are just making sure the file exists for a given module118  Module *exe_module = target_sp->GetExecutableModulePointer();119  if (exe_module) {120    const llvm::Triple &triple_ref = target_sp->GetArchitecture().GetTriple();121    switch (triple_ref.getOS()) {122    case llvm::Triple::Darwin: // Should use "macosx" for desktop and "ios" for123                               // iOS, but accept darwin just in case124    case llvm::Triple::MacOSX: // For desktop targets125    case llvm::Triple::IOS:    // For arm targets126    case llvm::Triple::TvOS:127    case llvm::Triple::WatchOS:128    case llvm::Triple::XROS:129      if (triple_ref.getVendor() == llvm::Triple::Apple) {130        ObjectFile *exe_objfile = exe_module->GetObjectFile();131        if (exe_objfile->GetType() == ObjectFile::eTypeExecutable &&132            exe_objfile->GetStrata() == ObjectFile::eStrataKernel)133          return true;134      }135      break;136 137    default:138      break;139    }140  }141  return false;142}143 144// ProcessKDP constructor145ProcessKDP::ProcessKDP(TargetSP target_sp, ListenerSP listener_sp)146    : Process(target_sp, listener_sp),147      m_comm("lldb.process.kdp-remote.communication"),148      m_async_broadcaster(NULL, "lldb.process.kdp-remote.async-broadcaster"),149      m_kernel_load_addr(LLDB_INVALID_ADDRESS), m_command_sp(),150      m_kernel_thread_wp() {151  m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit,152                                   "async thread should exit");153  m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue,154                                   "async thread continue");155  const uint64_t timeout_seconds =156      GetGlobalPluginProperties().GetPacketTimeout();157  if (timeout_seconds > 0)158    m_comm.SetPacketTimeout(std::chrono::seconds(timeout_seconds));159}160 161// Destructor162ProcessKDP::~ProcessKDP() {163  Clear();164  // We need to call finalize on the process before destroying ourselves to165  // make sure all of the broadcaster cleanup goes as planned. If we destruct166  // this class, then Process::~Process() might have problems trying to fully167  // destroy the broadcaster.168  Finalize(true /* destructing */);169}170 171Status ProcessKDP::DoWillLaunch(Module *module) {172  Status error;173  return Status::FromErrorString(174      "launching not supported in kdp-remote plug-in");175  return error;176}177 178Status ProcessKDP::DoWillAttachToProcessWithID(lldb::pid_t pid) {179  Status error;180  return Status::FromErrorString(181      "attaching to a by process ID not supported in kdp-remote plug-in");182  return error;183}184 185Status ProcessKDP::DoWillAttachToProcessWithName(const char *process_name,186                                                 bool wait_for_launch) {187  Status error;188  return Status::FromErrorString(189      "attaching to a by process name not supported in kdp-remote plug-in");190  return error;191}192 193bool ProcessKDP::GetHostArchitecture(ArchSpec &arch) {194  uint32_t cpu = m_comm.GetCPUType();195  if (cpu) {196    uint32_t sub = m_comm.GetCPUSubtype();197    arch.SetArchitecture(eArchTypeMachO, cpu, sub);198    // Leave architecture vendor as unspecified unknown199    arch.GetTriple().setVendor(llvm::Triple::UnknownVendor);200    arch.GetTriple().setVendorName(llvm::StringRef());201    return true;202  }203  arch.Clear();204  return false;205}206 207Status ProcessKDP::DoConnectRemote(llvm::StringRef remote_url) {208  Status error;209 210  // Don't let any JIT happen when doing KDP as we can't allocate memory and we211  // don't want to be mucking with threads that might already be handling212  // exceptions213  SetCanJIT(false);214 215  if (remote_url.empty())216    return Status::FromErrorString("empty connection URL");217 218  std::unique_ptr<ConnectionFileDescriptor> conn_up(219      new ConnectionFileDescriptor());220  if (conn_up) {221    // Only try once for now.222    // TODO: check if we should be retrying?223    const uint32_t max_retry_count = 1;224    for (uint32_t retry_count = 0; retry_count < max_retry_count;225         ++retry_count) {226      if (conn_up->Connect(remote_url, &error) == eConnectionStatusSuccess)227        break;228      usleep(100000);229    }230  }231 232  if (conn_up->IsConnected()) {233    const TCPSocket &socket =234        static_cast<const TCPSocket &>(*conn_up->GetReadObject());235    const uint16_t reply_port = socket.GetLocalPortNumber();236 237    if (reply_port != 0) {238      m_comm.SetConnection(std::move(conn_up));239 240      if (m_comm.SendRequestReattach(reply_port)) {241        if (m_comm.SendRequestConnect(reply_port, reply_port,242                                      "Greetings from LLDB...")) {243          m_comm.GetVersion();244 245          Target &target = GetTarget();246          ArchSpec kernel_arch;247          // The host architecture248          GetHostArchitecture(kernel_arch);249          ArchSpec target_arch = target.GetArchitecture();250          // Merge in any unspecified stuff into the target architecture in251          // case the target arch isn't set at all or incompletely.252          target_arch.MergeFrom(kernel_arch);253          target.SetArchitecture(target_arch);254 255          /* Get the kernel's UUID and load address via KDP_KERNELVERSION256           * packet.  */257          /* An EFI kdp session has neither UUID nor load address. */258 259          UUID kernel_uuid = m_comm.GetUUID();260          addr_t kernel_load_addr = m_comm.GetLoadAddress();261 262          if (m_comm.RemoteIsEFI()) {263            // Select an invalid plugin name for the dynamic loader so one264            // doesn't get used since EFI does its own manual loading via265            // python scripting266            m_dyld_plugin_name = "none";267 268            if (kernel_uuid.IsValid()) {269              // If EFI passed in a UUID= try to lookup UUID The slide will not270              // be provided. But the UUID lookup will be used to launch EFI271              // debug scripts from the dSYM, that can load all of the symbols.272              ModuleSpec module_spec;273              module_spec.GetUUID() = kernel_uuid;274              module_spec.GetArchitecture() = target.GetArchitecture();275 276              // Lookup UUID locally, before attempting dsymForUUID like action277              FileSpecList search_paths =278                  Target::GetDefaultDebugFileSearchPaths();279 280              StatisticsMap symbol_locator_map;281              module_spec.GetSymbolFileSpec() =282                  PluginManager::LocateExecutableSymbolFile(283                      module_spec, search_paths, symbol_locator_map);284              if (module_spec.GetSymbolFileSpec()) {285                ModuleSpec executable_module_spec =286                    PluginManager::LocateExecutableObjectFile(287                        module_spec, symbol_locator_map);288                if (FileSystem::Instance().Exists(289                        executable_module_spec.GetFileSpec())) {290                  module_spec.GetFileSpec() =291                      executable_module_spec.GetFileSpec();292                }293              }294              if (!module_spec.GetSymbolFileSpec() ||295                  !module_spec.GetSymbolFileSpec()) {296                Status symbl_error;297                PluginManager::DownloadObjectAndSymbolFile(module_spec,298                                                           symbl_error, true);299              }300 301              if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {302                ModuleSP module_sp(new Module(module_spec));303                module_sp->GetSymbolLocatorStatistics().merge(304                    symbol_locator_map);305                if (module_sp.get() && module_sp->GetObjectFile()) {306                  // Get the current target executable307                  ModuleSP exe_module_sp(target.GetExecutableModule());308 309                  // Make sure you don't already have the right module loaded310                  // and they will be uniqued311                  if (exe_module_sp.get() != module_sp.get())312                    target.SetExecutableModule(module_sp, eLoadDependentsNo);313                }314              }315            }316          } else if (m_comm.RemoteIsDarwinKernel()) {317            m_dyld_plugin_name =318                DynamicLoaderDarwinKernel::GetPluginNameStatic();319            if (kernel_load_addr != LLDB_INVALID_ADDRESS) {320              m_kernel_load_addr = kernel_load_addr;321            }322          }323 324          // Set the thread ID325          UpdateThreadListIfNeeded();326          SetID(1);327          GetThreadList();328          SetPrivateState(eStateStopped);329          const char *cstr;330          if ((cstr = m_comm.GetKernelVersion()) != NULL)331            target.GetDebugger().GetAsyncOutputStream()->Printf("Version: %s\n",332                                                                cstr);333        } else {334          return Status::FromErrorString("KDP_REATTACH failed");335        }336      } else {337        return Status::FromErrorString("KDP_REATTACH failed");338      }339    } else {340      return Status::FromErrorString("invalid reply port from UDP connection");341    }342  } else {343    if (error.Success())344      error = Status::FromErrorStringWithFormat("failed to connect to '%s'",345                                                remote_url.str().c_str());346  }347  if (error.Fail())348    m_comm.Disconnect();349 350  return error;351}352 353// Process Control354Status ProcessKDP::DoLaunch(Module *exe_module,355                            ProcessLaunchInfo &launch_info) {356  Status error;357  return Status::FromErrorString(358      "launching not supported in kdp-remote plug-in");359  return error;360}361 362Status363ProcessKDP::DoAttachToProcessWithID(lldb::pid_t attach_pid,364                                    const ProcessAttachInfo &attach_info) {365  Status error;366  return Status::FromErrorString(367      "attach to process by ID is not supported in kdp remote debugging");368  return error;369}370 371Status372ProcessKDP::DoAttachToProcessWithName(const char *process_name,373                                      const ProcessAttachInfo &attach_info) {374  Status error;375  return Status::FromErrorString(376      "attach to process by name is not supported in kdp remote debugging");377  return error;378}379 380void ProcessKDP::DidAttach(ArchSpec &process_arch) {381  Process::DidAttach(process_arch);382 383  Log *log = GetLog(KDPLog::Process);384  LLDB_LOGF(log, "ProcessKDP::DidAttach()");385  if (GetID() != LLDB_INVALID_PROCESS_ID) {386    GetHostArchitecture(process_arch);387  }388}389 390addr_t ProcessKDP::GetImageInfoAddress() { return m_kernel_load_addr; }391 392lldb_private::DynamicLoader *ProcessKDP::GetDynamicLoader() {393  if (m_dyld_up.get() == NULL)394    m_dyld_up.reset(DynamicLoader::FindPlugin(this, m_dyld_plugin_name));395  return m_dyld_up.get();396}397 398Status ProcessKDP::WillResume() { return Status(); }399 400Status ProcessKDP::DoResume(RunDirection direction) {401  Status error;402  Log *log = GetLog(KDPLog::Process);403 404  if (direction == RunDirection::eRunReverse)405    return Status::FromErrorStringWithFormatv(406        "{0} does not support reverse execution of processes", GetPluginName());407 408  // Only start the async thread if we try to do any process control409  if (!m_async_thread.IsJoinable())410    StartAsyncThread();411 412  bool resume = false;413 414  // With KDP there is only one thread we can tell what to do415  ThreadSP kernel_thread_sp(m_thread_list.FindThreadByProtocolID(g_kernel_tid));416 417  if (kernel_thread_sp) {418    const StateType thread_resume_state =419        kernel_thread_sp->GetTemporaryResumeState();420 421    LLDB_LOGF(log, "ProcessKDP::DoResume() thread_resume_state = %s",422              StateAsCString(thread_resume_state));423    switch (thread_resume_state) {424    case eStateSuspended:425      // Nothing to do here when a thread will stay suspended we just leave the426      // CPU mask bit set to zero for the thread427      LLDB_LOGF(log, "ProcessKDP::DoResume() = suspended???");428      break;429 430    case eStateStepping: {431      lldb::RegisterContextSP reg_ctx_sp(432          kernel_thread_sp->GetRegisterContext());433 434      if (reg_ctx_sp) {435        LLDB_LOGF(436            log,437            "ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (true);");438        reg_ctx_sp->HardwareSingleStep(true);439        resume = true;440      } else {441        error = Status::FromErrorStringWithFormat(442            "KDP thread 0x%llx has no register context",443            kernel_thread_sp->GetID());444      }445    } break;446 447    case eStateRunning: {448      lldb::RegisterContextSP reg_ctx_sp(449          kernel_thread_sp->GetRegisterContext());450 451      if (reg_ctx_sp) {452        LLDB_LOGF(log, "ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep "453                       "(false);");454        reg_ctx_sp->HardwareSingleStep(false);455        resume = true;456      } else {457        error = Status::FromErrorStringWithFormat(458            "KDP thread 0x%llx has no register context",459            kernel_thread_sp->GetID());460      }461    } break;462 463    default:464      // The only valid thread resume states are listed above465      llvm_unreachable("invalid thread resume state");466    }467  }468 469  if (resume) {470    LLDB_LOGF(log, "ProcessKDP::DoResume () sending resume");471 472    if (m_comm.SendRequestResume()) {473      m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue);474      SetPrivateState(eStateRunning);475    } else476      return Status::FromErrorString("KDP resume failed");477  } else {478    return Status::FromErrorString("kernel thread is suspended");479  }480 481  return error;482}483 484lldb::ThreadSP ProcessKDP::GetKernelThread() {485  // KDP only tells us about one thread/core. Any other threads will usually486  // be the ones that are read from memory by the OS plug-ins.487 488  ThreadSP thread_sp(m_kernel_thread_wp.lock());489  if (!thread_sp) {490    thread_sp = std::make_shared<ThreadKDP>(*this, g_kernel_tid);491    m_kernel_thread_wp = thread_sp;492  }493  return thread_sp;494}495 496bool ProcessKDP::DoUpdateThreadList(ThreadList &old_thread_list,497                                    ThreadList &new_thread_list) {498  // locker will keep a mutex locked until it goes out of scope499  Log *log = GetLog(KDPLog::Thread);500  LLDB_LOGV(log, "pid = {0}", GetID());501 502  // Even though there is a CPU mask, it doesn't mean we can see each CPU503  // individually, there is really only one. Lets call this thread 1.504  ThreadSP thread_sp(505      old_thread_list.FindThreadByProtocolID(g_kernel_tid, false));506  if (!thread_sp)507    thread_sp = GetKernelThread();508  new_thread_list.AddThread(thread_sp);509 510  return new_thread_list.GetSize(false) > 0;511}512 513void ProcessKDP::RefreshStateAfterStop() {514  // Let all threads recover from stopping and do any clean up based on the515  // previous thread state (if any).516  m_thread_list.RefreshStateAfterStop();517}518 519Status ProcessKDP::DoHalt(bool &caused_stop) {520  Status error;521 522  if (m_comm.IsRunning()) {523    if (m_destroy_in_process) {524      // If we are attempting to destroy, we need to not return an error to Halt525      // or DoDestroy won't get called. We are also currently running, so send526      // a process stopped event527      SetPrivateState(eStateStopped);528    } else {529      return Status::FromErrorString("KDP cannot interrupt a running kernel");530    }531  }532  return error;533}534 535Status ProcessKDP::DoDetach(bool keep_stopped) {536  Status error;537  Log *log = GetLog(KDPLog::Process);538  LLDB_LOGF(log, "ProcessKDP::DoDetach(keep_stopped = %i)", keep_stopped);539 540  if (m_comm.IsRunning()) {541    // We are running and we can't interrupt a running kernel, so we need to542    // just close the connection to the kernel and hope for the best543  } else {544    // If we are going to keep the target stopped, then don't send the545    // disconnect message.546    if (!keep_stopped && m_comm.IsConnected()) {547      const bool success = m_comm.SendRequestDisconnect();548      if (log) {549        if (success)550          log->PutCString(551              "ProcessKDP::DoDetach() detach packet sent successfully");552        else553          log->PutCString(554              "ProcessKDP::DoDetach() connection channel shutdown failed");555      }556      m_comm.Disconnect();557    }558  }559  StopAsyncThread();560  m_comm.Clear();561 562  SetPrivateState(eStateDetached);563  ResumePrivateStateThread();564 565  // KillDebugserverProcess ();566  return error;567}568 569Status ProcessKDP::DoDestroy() {570  // For KDP there really is no difference between destroy and detach571  bool keep_stopped = false;572  return DoDetach(keep_stopped);573}574 575// Process Queries576 577bool ProcessKDP::IsAlive() {578  return m_comm.IsConnected() && Process::IsAlive();579}580 581// Process Memory582size_t ProcessKDP::DoReadMemory(addr_t addr, void *buf, size_t size,583                                Status &error) {584  uint8_t *data_buffer = (uint8_t *)buf;585  if (m_comm.IsConnected()) {586    const size_t max_read_size = 512;587    size_t total_bytes_read = 0;588 589    // Read the requested amount of memory in 512 byte chunks590    while (total_bytes_read < size) {591      size_t bytes_to_read_this_request = size - total_bytes_read;592      if (bytes_to_read_this_request > max_read_size) {593        bytes_to_read_this_request = max_read_size;594      }595      size_t bytes_read = m_comm.SendRequestReadMemory(596          addr + total_bytes_read, data_buffer + total_bytes_read,597          bytes_to_read_this_request, error);598      total_bytes_read += bytes_read;599      if (error.Fail() || bytes_read == 0) {600        return total_bytes_read;601      }602    }603 604    return total_bytes_read;605  }606  error = Status::FromErrorString("not connected");607  return 0;608}609 610size_t ProcessKDP::DoWriteMemory(addr_t addr, const void *buf, size_t size,611                                 Status &error) {612  if (m_comm.IsConnected())613    return m_comm.SendRequestWriteMemory(addr, buf, size, error);614  error = Status::FromErrorString("not connected");615  return 0;616}617 618lldb::addr_t ProcessKDP::DoAllocateMemory(size_t size, uint32_t permissions,619                                          Status &error) {620  error = Status::FromErrorString(621      "memory allocation not supported in kdp remote debugging");622  return LLDB_INVALID_ADDRESS;623}624 625Status ProcessKDP::DoDeallocateMemory(lldb::addr_t addr) {626  Status error;627  return Status::FromErrorString(628      "memory deallocation not supported in kdp remote debugging");629  return error;630}631 632Status ProcessKDP::EnableBreakpointSite(BreakpointSite *bp_site) {633  if (bp_site->HardwareRequired())634    return Status::FromErrorString("Hardware breakpoints are not supported.");635 636  if (m_comm.LocalBreakpointsAreSupported()) {637    Status error;638    if (!bp_site->IsEnabled()) {639      if (m_comm.SendRequestBreakpoint(true, bp_site->GetLoadAddress())) {640        bp_site->SetEnabled(true);641        bp_site->SetType(BreakpointSite::eExternal);642      } else {643        return Status::FromErrorString("KDP set breakpoint failed");644      }645    }646    return error;647  }648  return EnableSoftwareBreakpoint(bp_site);649}650 651Status ProcessKDP::DisableBreakpointSite(BreakpointSite *bp_site) {652  if (m_comm.LocalBreakpointsAreSupported()) {653    Status error;654    if (bp_site->IsEnabled()) {655      BreakpointSite::Type bp_type = bp_site->GetType();656      if (bp_type == BreakpointSite::eExternal) {657        if (m_destroy_in_process && m_comm.IsRunning()) {658          // We are trying to destroy our connection and we are running659          bp_site->SetEnabled(false);660        } else {661          if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress()))662            bp_site->SetEnabled(false);663          else664            return Status::FromErrorString("KDP remove breakpoint failed");665        }666      } else {667        error = DisableSoftwareBreakpoint(bp_site);668      }669    }670    return error;671  }672  return DisableSoftwareBreakpoint(bp_site);673}674 675void ProcessKDP::Clear() { m_thread_list.Clear(); }676 677Status ProcessKDP::DoSignal(int signo) {678  Status error;679  return Status::FromErrorString(680      "sending signals is not supported in kdp remote debugging");681  return error;682}683 684void ProcessKDP::Initialize() {685  static llvm::once_flag g_once_flag;686 687  llvm::call_once(g_once_flag, []() {688    PluginManager::RegisterPlugin(GetPluginNameStatic(),689                                  GetPluginDescriptionStatic(), CreateInstance,690                                  DebuggerInitialize);691 692    ProcessKDPLog::Initialize();693  });694}695 696void ProcessKDP::DebuggerInitialize(lldb_private::Debugger &debugger) {697  if (!PluginManager::GetSettingForProcessPlugin(698          debugger, PluginProperties::GetSettingName())) {699    const bool is_global_setting = true;700    PluginManager::CreateSettingForProcessPlugin(701        debugger, GetGlobalPluginProperties().GetValueProperties(),702        "Properties for the kdp-remote process plug-in.", is_global_setting);703  }704}705 706bool ProcessKDP::StartAsyncThread() {707  Log *log = GetLog(KDPLog::Process);708 709  LLDB_LOGF(log, "ProcessKDP::StartAsyncThread ()");710 711  if (m_async_thread.IsJoinable())712    return true;713 714  llvm::Expected<HostThread> async_thread = ThreadLauncher::LaunchThread(715      "<lldb.process.kdp-remote.async>", [this] { return AsyncThread(); });716  if (!async_thread) {717    LLDB_LOG_ERROR(GetLog(LLDBLog::Host), async_thread.takeError(),718                   "failed to launch host thread: {0}");719    return false;720  }721  m_async_thread = *async_thread;722  return m_async_thread.IsJoinable();723}724 725void ProcessKDP::StopAsyncThread() {726  Log *log = GetLog(KDPLog::Process);727 728  LLDB_LOGF(log, "ProcessKDP::StopAsyncThread ()");729 730  m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit);731 732  // Stop the stdio thread733  if (m_async_thread.IsJoinable())734    m_async_thread.Join(nullptr);735}736 737void *ProcessKDP::AsyncThread() {738  const lldb::pid_t pid = GetID();739 740  Log *log = GetLog(KDPLog::Process);741  LLDB_LOGF(log,742            "ProcessKDP::AsyncThread(pid = %" PRIu64 ") thread starting...",743            pid);744 745  ListenerSP listener_sp(Listener::MakeListener("ProcessKDP::AsyncThread"));746  EventSP event_sp;747  const uint32_t desired_event_mask =748      eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit;749 750  if (listener_sp->StartListeningForEvents(751          &m_async_broadcaster, desired_event_mask) == desired_event_mask) {752    bool done = false;753    while (!done) {754      LLDB_LOGF(log,755                "ProcessKDP::AsyncThread (pid = %" PRIu64756                ") listener.WaitForEvent (NULL, event_sp)...",757                pid);758      if (listener_sp->GetEvent(event_sp, std::nullopt)) {759        uint32_t event_type = event_sp->GetType();760        LLDB_LOGF(log,761                  "ProcessKDP::AsyncThread (pid = %" PRIu64762                  ") Got an event of type: %d...",763                  pid, event_type);764 765        // When we are running, poll for 1 second to try and get an exception766        // to indicate the process has stopped. If we don't get one, check to767        // make sure no one asked us to exit768        bool is_running = false;769        DataExtractor exc_reply_packet;770        do {771          switch (event_type) {772          case eBroadcastBitAsyncContinue: {773            is_running = true;774            if (m_comm.WaitForPacketWithTimeoutMicroSeconds(775                    exc_reply_packet, 1 * USEC_PER_SEC)) {776              ThreadSP thread_sp(GetKernelThread());777              if (thread_sp) {778                lldb::RegisterContextSP reg_ctx_sp(779                    thread_sp->GetRegisterContext());780                if (reg_ctx_sp)781                  reg_ctx_sp->InvalidateAllRegisters();782                static_cast<ThreadKDP *>(thread_sp.get())783                    ->SetStopInfoFrom_KDP_EXCEPTION(exc_reply_packet);784              }785 786              // TODO: parse the stop reply packet787              is_running = false;788              SetPrivateState(eStateStopped);789            } else {790              // Check to see if we are supposed to exit. There is no way to791              // interrupt a running kernel, so all we can do is wait for an792              // exception or detach...793              if (listener_sp->GetEvent(event_sp,794                                        std::chrono::microseconds(0))) {795                // We got an event, go through the loop again796                event_type = event_sp->GetType();797              }798            }799          } break;800 801          case eBroadcastBitAsyncThreadShouldExit:802            LLDB_LOGF(log,803                      "ProcessKDP::AsyncThread (pid = %" PRIu64804                      ") got eBroadcastBitAsyncThreadShouldExit...",805                      pid);806            done = true;807            is_running = false;808            break;809 810          default:811            LLDB_LOGF(log,812                      "ProcessKDP::AsyncThread (pid = %" PRIu64813                      ") got unknown event 0x%8.8x",814                      pid, event_type);815            done = true;816            is_running = false;817            break;818          }819        } while (is_running);820      } else {821        LLDB_LOGF(log,822                  "ProcessKDP::AsyncThread (pid = %" PRIu64823                  ") listener.WaitForEvent (NULL, event_sp) => false",824                  pid);825        done = true;826      }827    }828  }829 830  LLDB_LOGF(log, "ProcessKDP::AsyncThread(pid = %" PRIu64 ") thread exiting...",831            pid);832 833  m_async_thread.Reset();834  return NULL;835}836 837class CommandObjectProcessKDPPacketSend : public CommandObjectParsed {838private:839  OptionGroupOptions m_option_group;840  OptionGroupUInt64 m_command_byte;841  OptionGroupString m_packet_data;842 843  Options *GetOptions() override { return &m_option_group; }844 845public:846  CommandObjectProcessKDPPacketSend(CommandInterpreter &interpreter)847      : CommandObjectParsed(interpreter, "process plugin packet send",848                            "Send a custom packet through the KDP protocol by "849                            "specifying the command byte and the packet "850                            "payload data. A packet will be sent with a "851                            "correct header and payload, and the raw result "852                            "bytes will be displayed as a string value. ",853                            NULL),854        m_option_group(),855        m_command_byte(LLDB_OPT_SET_1, true, "command", 'c', 0, eArgTypeNone,856                       "Specify the command byte to use when sending the KDP "857                       "request packet.",858                       0),859        m_packet_data(LLDB_OPT_SET_1, false, "payload", 'p', 0, eArgTypeNone,860                      "Specify packet payload bytes as a hex ASCII string with "861                      "no spaces or hex prefixes.",862                      NULL) {863    m_option_group.Append(&m_command_byte, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);864    m_option_group.Append(&m_packet_data, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);865    m_option_group.Finalize();866  }867 868  ~CommandObjectProcessKDPPacketSend() override = default;869 870  void DoExecute(Args &command, CommandReturnObject &result) override {871    if (!m_command_byte.GetOptionValue().OptionWasSet()) {872      result.AppendError(873          "the --command option must be set to a valid command byte");874    } else {875      const uint64_t command_byte =876          m_command_byte.GetOptionValue().GetValueAs<uint64_t>().value_or(0);877      if (command_byte > 0 && command_byte <= UINT8_MAX) {878        ProcessKDP *process =879            (ProcessKDP *)m_interpreter.GetExecutionContext().GetProcessPtr();880        if (process) {881          const StateType state = process->GetState();882 883          if (StateIsStoppedState(state, true)) {884            std::vector<uint8_t> payload_bytes;885            const char *ascii_hex_bytes_cstr =886                m_packet_data.GetOptionValue().GetCurrentValue();887            if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0]) {888              StringExtractor extractor(ascii_hex_bytes_cstr);889              const size_t ascii_hex_bytes_cstr_len =890                  extractor.GetStringRef().size();891              if (ascii_hex_bytes_cstr_len & 1) {892                result.AppendErrorWithFormat("payload data must contain an "893                                             "even number of ASCII hex "894                                             "characters: '%s'",895                                             ascii_hex_bytes_cstr);896                return;897              }898              payload_bytes.resize(ascii_hex_bytes_cstr_len / 2);899              if (extractor.GetHexBytes(payload_bytes, '\xdd') !=900                  payload_bytes.size()) {901                result.AppendErrorWithFormat("payload data must only contain "902                                             "ASCII hex characters (no "903                                             "spaces or hex prefixes): '%s'",904                                             ascii_hex_bytes_cstr);905                return;906              }907            }908            Status error;909            DataExtractor reply;910            process->GetCommunication().SendRawRequest(911                command_byte,912                payload_bytes.empty() ? NULL : payload_bytes.data(),913                payload_bytes.size(), reply, error);914 915            if (error.Success()) {916              // Copy the binary bytes into a hex ASCII string for the result917              StreamString packet;918              packet.PutBytesAsRawHex8(919                  reply.GetDataStart(), reply.GetByteSize(),920                  endian::InlHostByteOrder(), endian::InlHostByteOrder());921              result.AppendMessage(packet.GetString());922              result.SetStatus(eReturnStatusSuccessFinishResult);923              return;924            } else {925              const char *error_cstr = error.AsCString();926              if (error_cstr && error_cstr[0])927                result.AppendError(error_cstr);928              else929                result.AppendErrorWithFormat("unknown error 0x%8.8x",930                                             error.GetError());931              return;932            }933          } else {934            result.AppendErrorWithFormat("process must be stopped in order "935                                         "to send KDP packets, state is %s",936                                         StateAsCString(state));937          }938        } else {939          result.AppendError("invalid process");940        }941      } else {942        result.AppendErrorWithFormat("invalid command byte 0x%" PRIx64943                                     ", valid values are 1 - 255",944                                     command_byte);945      }946    }947  }948};949 950class CommandObjectProcessKDPPacket : public CommandObjectMultiword {951private:952public:953  CommandObjectProcessKDPPacket(CommandInterpreter &interpreter)954      : CommandObjectMultiword(interpreter, "process plugin packet",955                               "Commands that deal with KDP remote packets.",956                               NULL) {957    LoadSubCommand(958        "send",959        CommandObjectSP(new CommandObjectProcessKDPPacketSend(interpreter)));960  }961 962  ~CommandObjectProcessKDPPacket() override = default;963};964 965class CommandObjectMultiwordProcessKDP : public CommandObjectMultiword {966public:967  CommandObjectMultiwordProcessKDP(CommandInterpreter &interpreter)968      : CommandObjectMultiword(969            interpreter, "process plugin",970            "Commands for operating on a ProcessKDP process.",971            "process plugin <subcommand> [<subcommand-options>]") {972    LoadSubCommand("packet", CommandObjectSP(new CommandObjectProcessKDPPacket(973                                 interpreter)));974  }975 976  ~CommandObjectMultiwordProcessKDP() override = default;977};978 979CommandObject *ProcessKDP::GetPluginCommandObject() {980  if (!m_command_sp)981    m_command_sp = std::make_shared<CommandObjectMultiwordProcessKDP>(982        GetTarget().GetDebugger().GetCommandInterpreter());983  return m_command_sp.get();984}985