xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- ProcessKDP.cpp ----------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9be691f3bSpatrick #include <cerrno>
10be691f3bSpatrick #include <cstdlib>
11061da546Spatrick 
12061da546Spatrick #include <memory>
13061da546Spatrick #include <mutex>
14061da546Spatrick 
15061da546Spatrick #include "lldb/Core/Debugger.h"
16061da546Spatrick #include "lldb/Core/Module.h"
17061da546Spatrick #include "lldb/Core/ModuleSpec.h"
18061da546Spatrick #include "lldb/Core/PluginManager.h"
19061da546Spatrick #include "lldb/Host/ConnectionFileDescriptor.h"
20061da546Spatrick #include "lldb/Host/Host.h"
21061da546Spatrick #include "lldb/Host/ThreadLauncher.h"
22061da546Spatrick #include "lldb/Host/common/TCPSocket.h"
23061da546Spatrick #include "lldb/Interpreter/CommandInterpreter.h"
24061da546Spatrick #include "lldb/Interpreter/CommandObject.h"
25061da546Spatrick #include "lldb/Interpreter/CommandObjectMultiword.h"
26061da546Spatrick #include "lldb/Interpreter/CommandReturnObject.h"
27061da546Spatrick #include "lldb/Interpreter/OptionGroupString.h"
28061da546Spatrick #include "lldb/Interpreter/OptionGroupUInt64.h"
29061da546Spatrick #include "lldb/Interpreter/OptionValueProperties.h"
30061da546Spatrick #include "lldb/Symbol/LocateSymbolFile.h"
31061da546Spatrick #include "lldb/Symbol/ObjectFile.h"
32061da546Spatrick #include "lldb/Target/RegisterContext.h"
33061da546Spatrick #include "lldb/Target/Target.h"
34061da546Spatrick #include "lldb/Target/Thread.h"
35*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
36061da546Spatrick #include "lldb/Utility/Log.h"
37061da546Spatrick #include "lldb/Utility/State.h"
38061da546Spatrick #include "lldb/Utility/StringExtractor.h"
39061da546Spatrick #include "lldb/Utility/UUID.h"
40061da546Spatrick 
41061da546Spatrick #include "llvm/Support/Threading.h"
42061da546Spatrick 
43061da546Spatrick #define USEC_PER_SEC 1000000
44061da546Spatrick 
45061da546Spatrick #include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h"
46061da546Spatrick #include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"
47061da546Spatrick #include "ProcessKDP.h"
48061da546Spatrick #include "ProcessKDPLog.h"
49061da546Spatrick #include "ThreadKDP.h"
50061da546Spatrick 
51061da546Spatrick using namespace lldb;
52061da546Spatrick using namespace lldb_private;
53061da546Spatrick 
54dda28197Spatrick LLDB_PLUGIN_DEFINE_ADV(ProcessKDP, ProcessMacOSXKernel)
55dda28197Spatrick 
56061da546Spatrick namespace {
57061da546Spatrick 
58061da546Spatrick #define LLDB_PROPERTIES_processkdp
59061da546Spatrick #include "ProcessKDPProperties.inc"
60061da546Spatrick 
61061da546Spatrick enum {
62061da546Spatrick #define LLDB_PROPERTIES_processkdp
63061da546Spatrick #include "ProcessKDPPropertiesEnum.inc"
64061da546Spatrick };
65061da546Spatrick 
66061da546Spatrick class PluginProperties : public Properties {
67061da546Spatrick public:
GetSettingName()68061da546Spatrick   static ConstString GetSettingName() {
69*f6aab3d8Srobert     return ConstString(ProcessKDP::GetPluginNameStatic());
70061da546Spatrick   }
71061da546Spatrick 
PluginProperties()72061da546Spatrick   PluginProperties() : Properties() {
73061da546Spatrick     m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
74061da546Spatrick     m_collection_sp->Initialize(g_processkdp_properties);
75061da546Spatrick   }
76061da546Spatrick 
77*f6aab3d8Srobert   ~PluginProperties() override = default;
78061da546Spatrick 
GetPacketTimeout()79061da546Spatrick   uint64_t GetPacketTimeout() {
80061da546Spatrick     const uint32_t idx = ePropertyKDPPacketTimeout;
81061da546Spatrick     return m_collection_sp->GetPropertyAtIndexAsUInt64(
82061da546Spatrick         NULL, idx, g_processkdp_properties[idx].default_uint_value);
83061da546Spatrick   }
84061da546Spatrick };
85061da546Spatrick 
86*f6aab3d8Srobert } // namespace
87061da546Spatrick 
GetGlobalPluginProperties()88*f6aab3d8Srobert static PluginProperties &GetGlobalPluginProperties() {
89*f6aab3d8Srobert   static PluginProperties g_settings;
90*f6aab3d8Srobert   return g_settings;
91061da546Spatrick }
92061da546Spatrick 
93061da546Spatrick static const lldb::tid_t g_kernel_tid = 1;
94061da546Spatrick 
GetPluginDescriptionStatic()95*f6aab3d8Srobert llvm::StringRef ProcessKDP::GetPluginDescriptionStatic() {
96061da546Spatrick   return "KDP Remote protocol based debugging plug-in for darwin kernel "
97061da546Spatrick          "debugging.";
98061da546Spatrick }
99061da546Spatrick 
Terminate()100061da546Spatrick void ProcessKDP::Terminate() {
101061da546Spatrick   PluginManager::UnregisterPlugin(ProcessKDP::CreateInstance);
102061da546Spatrick }
103061da546Spatrick 
CreateInstance(TargetSP target_sp,ListenerSP listener_sp,const FileSpec * crash_file_path,bool can_connect)104061da546Spatrick lldb::ProcessSP ProcessKDP::CreateInstance(TargetSP target_sp,
105061da546Spatrick                                            ListenerSP listener_sp,
106be691f3bSpatrick                                            const FileSpec *crash_file_path,
107be691f3bSpatrick                                            bool can_connect) {
108061da546Spatrick   lldb::ProcessSP process_sp;
109061da546Spatrick   if (crash_file_path == NULL)
110061da546Spatrick     process_sp = std::make_shared<ProcessKDP>(target_sp, listener_sp);
111061da546Spatrick   return process_sp;
112061da546Spatrick }
113061da546Spatrick 
CanDebug(TargetSP target_sp,bool plugin_specified_by_name)114061da546Spatrick bool ProcessKDP::CanDebug(TargetSP target_sp, bool plugin_specified_by_name) {
115061da546Spatrick   if (plugin_specified_by_name)
116061da546Spatrick     return true;
117061da546Spatrick 
118061da546Spatrick   // For now we are just making sure the file exists for a given module
119061da546Spatrick   Module *exe_module = target_sp->GetExecutableModulePointer();
120061da546Spatrick   if (exe_module) {
121061da546Spatrick     const llvm::Triple &triple_ref = target_sp->GetArchitecture().GetTriple();
122061da546Spatrick     switch (triple_ref.getOS()) {
123061da546Spatrick     case llvm::Triple::Darwin: // Should use "macosx" for desktop and "ios" for
124061da546Spatrick                                // iOS, but accept darwin just in case
125061da546Spatrick     case llvm::Triple::MacOSX: // For desktop targets
126061da546Spatrick     case llvm::Triple::IOS:    // For arm targets
127061da546Spatrick     case llvm::Triple::TvOS:
128061da546Spatrick     case llvm::Triple::WatchOS:
129061da546Spatrick       if (triple_ref.getVendor() == llvm::Triple::Apple) {
130061da546Spatrick         ObjectFile *exe_objfile = exe_module->GetObjectFile();
131061da546Spatrick         if (exe_objfile->GetType() == ObjectFile::eTypeExecutable &&
132061da546Spatrick             exe_objfile->GetStrata() == ObjectFile::eStrataKernel)
133061da546Spatrick           return true;
134061da546Spatrick       }
135061da546Spatrick       break;
136061da546Spatrick 
137061da546Spatrick     default:
138061da546Spatrick       break;
139061da546Spatrick     }
140061da546Spatrick   }
141061da546Spatrick   return false;
142061da546Spatrick }
143061da546Spatrick 
144061da546Spatrick // ProcessKDP constructor
ProcessKDP(TargetSP target_sp,ListenerSP listener_sp)145061da546Spatrick ProcessKDP::ProcessKDP(TargetSP target_sp, ListenerSP listener_sp)
146061da546Spatrick     : Process(target_sp, listener_sp),
147061da546Spatrick       m_comm("lldb.process.kdp-remote.communication"),
148061da546Spatrick       m_async_broadcaster(NULL, "lldb.process.kdp-remote.async-broadcaster"),
149*f6aab3d8Srobert       m_kernel_load_addr(LLDB_INVALID_ADDRESS), m_command_sp(),
150*f6aab3d8Srobert       m_kernel_thread_wp() {
151061da546Spatrick   m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit,
152061da546Spatrick                                    "async thread should exit");
153061da546Spatrick   m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue,
154061da546Spatrick                                    "async thread continue");
155061da546Spatrick   const uint64_t timeout_seconds =
156*f6aab3d8Srobert       GetGlobalPluginProperties().GetPacketTimeout();
157061da546Spatrick   if (timeout_seconds > 0)
158061da546Spatrick     m_comm.SetPacketTimeout(std::chrono::seconds(timeout_seconds));
159061da546Spatrick }
160061da546Spatrick 
161061da546Spatrick // Destructor
~ProcessKDP()162061da546Spatrick ProcessKDP::~ProcessKDP() {
163061da546Spatrick   Clear();
164061da546Spatrick   // We need to call finalize on the process before destroying ourselves to
165061da546Spatrick   // make sure all of the broadcaster cleanup goes as planned. If we destruct
166061da546Spatrick   // this class, then Process::~Process() might have problems trying to fully
167061da546Spatrick   // destroy the broadcaster.
168061da546Spatrick   Finalize();
169061da546Spatrick }
170061da546Spatrick 
DoWillLaunch(Module * module)171*f6aab3d8Srobert Status ProcessKDP::DoWillLaunch(Module *module) {
172061da546Spatrick   Status error;
173061da546Spatrick   error.SetErrorString("launching not supported in kdp-remote plug-in");
174061da546Spatrick   return error;
175061da546Spatrick }
176061da546Spatrick 
DoWillAttachToProcessWithID(lldb::pid_t pid)177*f6aab3d8Srobert Status ProcessKDP::DoWillAttachToProcessWithID(lldb::pid_t pid) {
178061da546Spatrick   Status error;
179061da546Spatrick   error.SetErrorString(
180061da546Spatrick       "attaching to a by process ID not supported in kdp-remote plug-in");
181061da546Spatrick   return error;
182061da546Spatrick }
183061da546Spatrick 
DoWillAttachToProcessWithName(const char * process_name,bool wait_for_launch)184*f6aab3d8Srobert Status ProcessKDP::DoWillAttachToProcessWithName(const char *process_name,
185061da546Spatrick                                                  bool wait_for_launch) {
186061da546Spatrick   Status error;
187061da546Spatrick   error.SetErrorString(
188061da546Spatrick       "attaching to a by process name not supported in kdp-remote plug-in");
189061da546Spatrick   return error;
190061da546Spatrick }
191061da546Spatrick 
GetHostArchitecture(ArchSpec & arch)192061da546Spatrick bool ProcessKDP::GetHostArchitecture(ArchSpec &arch) {
193061da546Spatrick   uint32_t cpu = m_comm.GetCPUType();
194061da546Spatrick   if (cpu) {
195061da546Spatrick     uint32_t sub = m_comm.GetCPUSubtype();
196061da546Spatrick     arch.SetArchitecture(eArchTypeMachO, cpu, sub);
197061da546Spatrick     // Leave architecture vendor as unspecified unknown
198061da546Spatrick     arch.GetTriple().setVendor(llvm::Triple::UnknownVendor);
199061da546Spatrick     arch.GetTriple().setVendorName(llvm::StringRef());
200061da546Spatrick     return true;
201061da546Spatrick   }
202061da546Spatrick   arch.Clear();
203061da546Spatrick   return false;
204061da546Spatrick }
205061da546Spatrick 
DoConnectRemote(llvm::StringRef remote_url)206dda28197Spatrick Status ProcessKDP::DoConnectRemote(llvm::StringRef remote_url) {
207061da546Spatrick   Status error;
208061da546Spatrick 
209061da546Spatrick   // Don't let any JIT happen when doing KDP as we can't allocate memory and we
210061da546Spatrick   // don't want to be mucking with threads that might already be handling
211061da546Spatrick   // exceptions
212061da546Spatrick   SetCanJIT(false);
213061da546Spatrick 
214061da546Spatrick   if (remote_url.empty()) {
215061da546Spatrick     error.SetErrorStringWithFormat("empty connection URL");
216061da546Spatrick     return error;
217061da546Spatrick   }
218061da546Spatrick 
219061da546Spatrick   std::unique_ptr<ConnectionFileDescriptor> conn_up(
220061da546Spatrick       new ConnectionFileDescriptor());
221061da546Spatrick   if (conn_up) {
222061da546Spatrick     // Only try once for now.
223061da546Spatrick     // TODO: check if we should be retrying?
224061da546Spatrick     const uint32_t max_retry_count = 1;
225061da546Spatrick     for (uint32_t retry_count = 0; retry_count < max_retry_count;
226061da546Spatrick          ++retry_count) {
227061da546Spatrick       if (conn_up->Connect(remote_url, &error) == eConnectionStatusSuccess)
228061da546Spatrick         break;
229061da546Spatrick       usleep(100000);
230061da546Spatrick     }
231061da546Spatrick   }
232061da546Spatrick 
233061da546Spatrick   if (conn_up->IsConnected()) {
234061da546Spatrick     const TCPSocket &socket =
235061da546Spatrick         static_cast<const TCPSocket &>(*conn_up->GetReadObject());
236061da546Spatrick     const uint16_t reply_port = socket.GetLocalPortNumber();
237061da546Spatrick 
238061da546Spatrick     if (reply_port != 0) {
239dda28197Spatrick       m_comm.SetConnection(std::move(conn_up));
240061da546Spatrick 
241061da546Spatrick       if (m_comm.SendRequestReattach(reply_port)) {
242061da546Spatrick         if (m_comm.SendRequestConnect(reply_port, reply_port,
243061da546Spatrick                                       "Greetings from LLDB...")) {
244061da546Spatrick           m_comm.GetVersion();
245061da546Spatrick 
246061da546Spatrick           Target &target = GetTarget();
247061da546Spatrick           ArchSpec kernel_arch;
248061da546Spatrick           // The host architecture
249061da546Spatrick           GetHostArchitecture(kernel_arch);
250061da546Spatrick           ArchSpec target_arch = target.GetArchitecture();
251061da546Spatrick           // Merge in any unspecified stuff into the target architecture in
252061da546Spatrick           // case the target arch isn't set at all or incompletely.
253061da546Spatrick           target_arch.MergeFrom(kernel_arch);
254061da546Spatrick           target.SetArchitecture(target_arch);
255061da546Spatrick 
256061da546Spatrick           /* Get the kernel's UUID and load address via KDP_KERNELVERSION
257061da546Spatrick            * packet.  */
258061da546Spatrick           /* An EFI kdp session has neither UUID nor load address. */
259061da546Spatrick 
260061da546Spatrick           UUID kernel_uuid = m_comm.GetUUID();
261061da546Spatrick           addr_t kernel_load_addr = m_comm.GetLoadAddress();
262061da546Spatrick 
263061da546Spatrick           if (m_comm.RemoteIsEFI()) {
264061da546Spatrick             // Select an invalid plugin name for the dynamic loader so one
265061da546Spatrick             // doesn't get used since EFI does its own manual loading via
266061da546Spatrick             // python scripting
267*f6aab3d8Srobert             m_dyld_plugin_name = "none";
268061da546Spatrick 
269061da546Spatrick             if (kernel_uuid.IsValid()) {
270061da546Spatrick               // If EFI passed in a UUID= try to lookup UUID The slide will not
271061da546Spatrick               // be provided. But the UUID lookup will be used to launch EFI
272061da546Spatrick               // debug scripts from the dSYM, that can load all of the symbols.
273061da546Spatrick               ModuleSpec module_spec;
274061da546Spatrick               module_spec.GetUUID() = kernel_uuid;
275061da546Spatrick               module_spec.GetArchitecture() = target.GetArchitecture();
276061da546Spatrick 
277061da546Spatrick               // Lookup UUID locally, before attempting dsymForUUID like action
278061da546Spatrick               FileSpecList search_paths =
279061da546Spatrick                   Target::GetDefaultDebugFileSearchPaths();
280061da546Spatrick               module_spec.GetSymbolFileSpec() =
281061da546Spatrick                   Symbols::LocateExecutableSymbolFile(module_spec,
282061da546Spatrick                                                       search_paths);
283061da546Spatrick               if (module_spec.GetSymbolFileSpec()) {
284061da546Spatrick                 ModuleSpec executable_module_spec =
285061da546Spatrick                     Symbols::LocateExecutableObjectFile(module_spec);
286061da546Spatrick                 if (FileSystem::Instance().Exists(
287061da546Spatrick                         executable_module_spec.GetFileSpec())) {
288061da546Spatrick                   module_spec.GetFileSpec() =
289061da546Spatrick                       executable_module_spec.GetFileSpec();
290061da546Spatrick                 }
291061da546Spatrick               }
292061da546Spatrick               if (!module_spec.GetSymbolFileSpec() ||
293*f6aab3d8Srobert                   !module_spec.GetSymbolFileSpec()) {
294*f6aab3d8Srobert                 Status symbl_error;
295*f6aab3d8Srobert                 Symbols::DownloadObjectAndSymbolFile(module_spec, symbl_error,
296*f6aab3d8Srobert                                                      true);
297*f6aab3d8Srobert               }
298061da546Spatrick 
299061da546Spatrick               if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
300061da546Spatrick                 ModuleSP module_sp(new Module(module_spec));
301061da546Spatrick                 if (module_sp.get() && module_sp->GetObjectFile()) {
302061da546Spatrick                   // Get the current target executable
303061da546Spatrick                   ModuleSP exe_module_sp(target.GetExecutableModule());
304061da546Spatrick 
305061da546Spatrick                   // Make sure you don't already have the right module loaded
306061da546Spatrick                   // and they will be uniqued
307061da546Spatrick                   if (exe_module_sp.get() != module_sp.get())
308061da546Spatrick                     target.SetExecutableModule(module_sp, eLoadDependentsNo);
309061da546Spatrick                 }
310061da546Spatrick               }
311061da546Spatrick             }
312061da546Spatrick           } else if (m_comm.RemoteIsDarwinKernel()) {
313061da546Spatrick             m_dyld_plugin_name =
314061da546Spatrick                 DynamicLoaderDarwinKernel::GetPluginNameStatic();
315061da546Spatrick             if (kernel_load_addr != LLDB_INVALID_ADDRESS) {
316061da546Spatrick               m_kernel_load_addr = kernel_load_addr;
317061da546Spatrick             }
318061da546Spatrick           }
319061da546Spatrick 
320061da546Spatrick           // Set the thread ID
321061da546Spatrick           UpdateThreadListIfNeeded();
322061da546Spatrick           SetID(1);
323061da546Spatrick           GetThreadList();
324061da546Spatrick           SetPrivateState(eStateStopped);
325061da546Spatrick           StreamSP async_strm_sp(target.GetDebugger().GetAsyncOutputStream());
326061da546Spatrick           if (async_strm_sp) {
327061da546Spatrick             const char *cstr;
328061da546Spatrick             if ((cstr = m_comm.GetKernelVersion()) != NULL) {
329061da546Spatrick               async_strm_sp->Printf("Version: %s\n", cstr);
330061da546Spatrick               async_strm_sp->Flush();
331061da546Spatrick             }
332061da546Spatrick             //                      if ((cstr = m_comm.GetImagePath ()) != NULL)
333061da546Spatrick             //                      {
334061da546Spatrick             //                          async_strm_sp->Printf ("Image Path:
335061da546Spatrick             //                          %s\n", cstr);
336061da546Spatrick             //                          async_strm_sp->Flush();
337061da546Spatrick             //                      }
338061da546Spatrick           }
339061da546Spatrick         } else {
340061da546Spatrick           error.SetErrorString("KDP_REATTACH failed");
341061da546Spatrick         }
342061da546Spatrick       } else {
343061da546Spatrick         error.SetErrorString("KDP_REATTACH failed");
344061da546Spatrick       }
345061da546Spatrick     } else {
346061da546Spatrick       error.SetErrorString("invalid reply port from UDP connection");
347061da546Spatrick     }
348061da546Spatrick   } else {
349061da546Spatrick     if (error.Success())
350061da546Spatrick       error.SetErrorStringWithFormat("failed to connect to '%s'",
351061da546Spatrick                                      remote_url.str().c_str());
352061da546Spatrick   }
353061da546Spatrick   if (error.Fail())
354061da546Spatrick     m_comm.Disconnect();
355061da546Spatrick 
356061da546Spatrick   return error;
357061da546Spatrick }
358061da546Spatrick 
359061da546Spatrick // Process Control
DoLaunch(Module * exe_module,ProcessLaunchInfo & launch_info)360061da546Spatrick Status ProcessKDP::DoLaunch(Module *exe_module,
361061da546Spatrick                             ProcessLaunchInfo &launch_info) {
362061da546Spatrick   Status error;
363061da546Spatrick   error.SetErrorString("launching not supported in kdp-remote plug-in");
364061da546Spatrick   return error;
365061da546Spatrick }
366061da546Spatrick 
367061da546Spatrick Status
DoAttachToProcessWithID(lldb::pid_t attach_pid,const ProcessAttachInfo & attach_info)368061da546Spatrick ProcessKDP::DoAttachToProcessWithID(lldb::pid_t attach_pid,
369061da546Spatrick                                     const ProcessAttachInfo &attach_info) {
370061da546Spatrick   Status error;
371061da546Spatrick   error.SetErrorString(
372061da546Spatrick       "attach to process by ID is not supported in kdp remote debugging");
373061da546Spatrick   return error;
374061da546Spatrick }
375061da546Spatrick 
376061da546Spatrick Status
DoAttachToProcessWithName(const char * process_name,const ProcessAttachInfo & attach_info)377061da546Spatrick ProcessKDP::DoAttachToProcessWithName(const char *process_name,
378061da546Spatrick                                       const ProcessAttachInfo &attach_info) {
379061da546Spatrick   Status error;
380061da546Spatrick   error.SetErrorString(
381061da546Spatrick       "attach to process by name is not supported in kdp remote debugging");
382061da546Spatrick   return error;
383061da546Spatrick }
384061da546Spatrick 
DidAttach(ArchSpec & process_arch)385061da546Spatrick void ProcessKDP::DidAttach(ArchSpec &process_arch) {
386061da546Spatrick   Process::DidAttach(process_arch);
387061da546Spatrick 
388*f6aab3d8Srobert   Log *log = GetLog(KDPLog::Process);
389061da546Spatrick   LLDB_LOGF(log, "ProcessKDP::DidAttach()");
390061da546Spatrick   if (GetID() != LLDB_INVALID_PROCESS_ID) {
391061da546Spatrick     GetHostArchitecture(process_arch);
392061da546Spatrick   }
393061da546Spatrick }
394061da546Spatrick 
GetImageInfoAddress()395061da546Spatrick addr_t ProcessKDP::GetImageInfoAddress() { return m_kernel_load_addr; }
396061da546Spatrick 
GetDynamicLoader()397061da546Spatrick lldb_private::DynamicLoader *ProcessKDP::GetDynamicLoader() {
398061da546Spatrick   if (m_dyld_up.get() == NULL)
399*f6aab3d8Srobert     m_dyld_up.reset(DynamicLoader::FindPlugin(this, m_dyld_plugin_name));
400061da546Spatrick   return m_dyld_up.get();
401061da546Spatrick }
402061da546Spatrick 
WillResume()403061da546Spatrick Status ProcessKDP::WillResume() { return Status(); }
404061da546Spatrick 
DoResume()405061da546Spatrick Status ProcessKDP::DoResume() {
406061da546Spatrick   Status error;
407*f6aab3d8Srobert   Log *log = GetLog(KDPLog::Process);
408061da546Spatrick   // Only start the async thread if we try to do any process control
409061da546Spatrick   if (!m_async_thread.IsJoinable())
410061da546Spatrick     StartAsyncThread();
411061da546Spatrick 
412061da546Spatrick   bool resume = false;
413061da546Spatrick 
414061da546Spatrick   // With KDP there is only one thread we can tell what to do
415061da546Spatrick   ThreadSP kernel_thread_sp(m_thread_list.FindThreadByProtocolID(g_kernel_tid));
416061da546Spatrick 
417061da546Spatrick   if (kernel_thread_sp) {
418061da546Spatrick     const StateType thread_resume_state =
419061da546Spatrick         kernel_thread_sp->GetTemporaryResumeState();
420061da546Spatrick 
421061da546Spatrick     LLDB_LOGF(log, "ProcessKDP::DoResume() thread_resume_state = %s",
422061da546Spatrick               StateAsCString(thread_resume_state));
423061da546Spatrick     switch (thread_resume_state) {
424061da546Spatrick     case eStateSuspended:
425061da546Spatrick       // Nothing to do here when a thread will stay suspended we just leave the
426061da546Spatrick       // CPU mask bit set to zero for the thread
427061da546Spatrick       LLDB_LOGF(log, "ProcessKDP::DoResume() = suspended???");
428061da546Spatrick       break;
429061da546Spatrick 
430061da546Spatrick     case eStateStepping: {
431061da546Spatrick       lldb::RegisterContextSP reg_ctx_sp(
432061da546Spatrick           kernel_thread_sp->GetRegisterContext());
433061da546Spatrick 
434061da546Spatrick       if (reg_ctx_sp) {
435061da546Spatrick         LLDB_LOGF(
436061da546Spatrick             log,
437061da546Spatrick             "ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (true);");
438061da546Spatrick         reg_ctx_sp->HardwareSingleStep(true);
439061da546Spatrick         resume = true;
440061da546Spatrick       } else {
441061da546Spatrick         error.SetErrorStringWithFormat(
442061da546Spatrick             "KDP thread 0x%llx has no register context",
443061da546Spatrick             kernel_thread_sp->GetID());
444061da546Spatrick       }
445061da546Spatrick     } break;
446061da546Spatrick 
447061da546Spatrick     case eStateRunning: {
448061da546Spatrick       lldb::RegisterContextSP reg_ctx_sp(
449061da546Spatrick           kernel_thread_sp->GetRegisterContext());
450061da546Spatrick 
451061da546Spatrick       if (reg_ctx_sp) {
452061da546Spatrick         LLDB_LOGF(log, "ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep "
453061da546Spatrick                        "(false);");
454061da546Spatrick         reg_ctx_sp->HardwareSingleStep(false);
455061da546Spatrick         resume = true;
456061da546Spatrick       } else {
457061da546Spatrick         error.SetErrorStringWithFormat(
458061da546Spatrick             "KDP thread 0x%llx has no register context",
459061da546Spatrick             kernel_thread_sp->GetID());
460061da546Spatrick       }
461061da546Spatrick     } break;
462061da546Spatrick 
463061da546Spatrick     default:
464061da546Spatrick       // The only valid thread resume states are listed above
465061da546Spatrick       llvm_unreachable("invalid thread resume state");
466061da546Spatrick     }
467061da546Spatrick   }
468061da546Spatrick 
469061da546Spatrick   if (resume) {
470061da546Spatrick     LLDB_LOGF(log, "ProcessKDP::DoResume () sending resume");
471061da546Spatrick 
472061da546Spatrick     if (m_comm.SendRequestResume()) {
473061da546Spatrick       m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue);
474061da546Spatrick       SetPrivateState(eStateRunning);
475061da546Spatrick     } else
476061da546Spatrick       error.SetErrorString("KDP resume failed");
477061da546Spatrick   } else {
478061da546Spatrick     error.SetErrorString("kernel thread is suspended");
479061da546Spatrick   }
480061da546Spatrick 
481061da546Spatrick   return error;
482061da546Spatrick }
483061da546Spatrick 
GetKernelThread()484061da546Spatrick lldb::ThreadSP ProcessKDP::GetKernelThread() {
485061da546Spatrick   // KDP only tells us about one thread/core. Any other threads will usually
486061da546Spatrick   // be the ones that are read from memory by the OS plug-ins.
487061da546Spatrick 
488061da546Spatrick   ThreadSP thread_sp(m_kernel_thread_wp.lock());
489061da546Spatrick   if (!thread_sp) {
490061da546Spatrick     thread_sp = std::make_shared<ThreadKDP>(*this, g_kernel_tid);
491061da546Spatrick     m_kernel_thread_wp = thread_sp;
492061da546Spatrick   }
493061da546Spatrick   return thread_sp;
494061da546Spatrick }
495061da546Spatrick 
DoUpdateThreadList(ThreadList & old_thread_list,ThreadList & new_thread_list)496be691f3bSpatrick bool ProcessKDP::DoUpdateThreadList(ThreadList &old_thread_list,
497061da546Spatrick                                     ThreadList &new_thread_list) {
498061da546Spatrick   // locker will keep a mutex locked until it goes out of scope
499*f6aab3d8Srobert   Log *log = GetLog(KDPLog::Thread);
500061da546Spatrick   LLDB_LOGV(log, "pid = {0}", GetID());
501061da546Spatrick 
502061da546Spatrick   // Even though there is a CPU mask, it doesn't mean we can see each CPU
503061da546Spatrick   // individually, there is really only one. Lets call this thread 1.
504061da546Spatrick   ThreadSP thread_sp(
505061da546Spatrick       old_thread_list.FindThreadByProtocolID(g_kernel_tid, false));
506061da546Spatrick   if (!thread_sp)
507061da546Spatrick     thread_sp = GetKernelThread();
508061da546Spatrick   new_thread_list.AddThread(thread_sp);
509061da546Spatrick 
510061da546Spatrick   return new_thread_list.GetSize(false) > 0;
511061da546Spatrick }
512061da546Spatrick 
RefreshStateAfterStop()513061da546Spatrick void ProcessKDP::RefreshStateAfterStop() {
514061da546Spatrick   // Let all threads recover from stopping and do any clean up based on the
515061da546Spatrick   // previous thread state (if any).
516061da546Spatrick   m_thread_list.RefreshStateAfterStop();
517061da546Spatrick }
518061da546Spatrick 
DoHalt(bool & caused_stop)519061da546Spatrick Status ProcessKDP::DoHalt(bool &caused_stop) {
520061da546Spatrick   Status error;
521061da546Spatrick 
522061da546Spatrick   if (m_comm.IsRunning()) {
523061da546Spatrick     if (m_destroy_in_process) {
524061da546Spatrick       // If we are attempting to destroy, we need to not return an error to Halt
525061da546Spatrick       // or DoDestroy won't get called. We are also currently running, so send
526061da546Spatrick       // a process stopped event
527061da546Spatrick       SetPrivateState(eStateStopped);
528061da546Spatrick     } else {
529061da546Spatrick       error.SetErrorString("KDP cannot interrupt a running kernel");
530061da546Spatrick     }
531061da546Spatrick   }
532061da546Spatrick   return error;
533061da546Spatrick }
534061da546Spatrick 
DoDetach(bool keep_stopped)535061da546Spatrick Status ProcessKDP::DoDetach(bool keep_stopped) {
536061da546Spatrick   Status error;
537*f6aab3d8Srobert   Log *log = GetLog(KDPLog::Process);
538061da546Spatrick   LLDB_LOGF(log, "ProcessKDP::DoDetach(keep_stopped = %i)", keep_stopped);
539061da546Spatrick 
540061da546Spatrick   if (m_comm.IsRunning()) {
541061da546Spatrick     // We are running and we can't interrupt a running kernel, so we need to
542061da546Spatrick     // just close the connection to the kernel and hope for the best
543061da546Spatrick   } else {
544061da546Spatrick     // If we are going to keep the target stopped, then don't send the
545061da546Spatrick     // disconnect message.
546061da546Spatrick     if (!keep_stopped && m_comm.IsConnected()) {
547061da546Spatrick       const bool success = m_comm.SendRequestDisconnect();
548061da546Spatrick       if (log) {
549061da546Spatrick         if (success)
550061da546Spatrick           log->PutCString(
551061da546Spatrick               "ProcessKDP::DoDetach() detach packet sent successfully");
552061da546Spatrick         else
553061da546Spatrick           log->PutCString(
554061da546Spatrick               "ProcessKDP::DoDetach() connection channel shutdown failed");
555061da546Spatrick       }
556061da546Spatrick       m_comm.Disconnect();
557061da546Spatrick     }
558061da546Spatrick   }
559061da546Spatrick   StopAsyncThread();
560061da546Spatrick   m_comm.Clear();
561061da546Spatrick 
562061da546Spatrick   SetPrivateState(eStateDetached);
563061da546Spatrick   ResumePrivateStateThread();
564061da546Spatrick 
565061da546Spatrick   // KillDebugserverProcess ();
566061da546Spatrick   return error;
567061da546Spatrick }
568061da546Spatrick 
DoDestroy()569061da546Spatrick Status ProcessKDP::DoDestroy() {
570061da546Spatrick   // For KDP there really is no difference between destroy and detach
571061da546Spatrick   bool keep_stopped = false;
572061da546Spatrick   return DoDetach(keep_stopped);
573061da546Spatrick }
574061da546Spatrick 
575061da546Spatrick // Process Queries
576061da546Spatrick 
IsAlive()577061da546Spatrick bool ProcessKDP::IsAlive() {
578061da546Spatrick   return m_comm.IsConnected() && Process::IsAlive();
579061da546Spatrick }
580061da546Spatrick 
581061da546Spatrick // Process Memory
DoReadMemory(addr_t addr,void * buf,size_t size,Status & error)582061da546Spatrick size_t ProcessKDP::DoReadMemory(addr_t addr, void *buf, size_t size,
583061da546Spatrick                                 Status &error) {
584061da546Spatrick   uint8_t *data_buffer = (uint8_t *)buf;
585061da546Spatrick   if (m_comm.IsConnected()) {
586061da546Spatrick     const size_t max_read_size = 512;
587061da546Spatrick     size_t total_bytes_read = 0;
588061da546Spatrick 
589061da546Spatrick     // Read the requested amount of memory in 512 byte chunks
590061da546Spatrick     while (total_bytes_read < size) {
591061da546Spatrick       size_t bytes_to_read_this_request = size - total_bytes_read;
592061da546Spatrick       if (bytes_to_read_this_request > max_read_size) {
593061da546Spatrick         bytes_to_read_this_request = max_read_size;
594061da546Spatrick       }
595061da546Spatrick       size_t bytes_read = m_comm.SendRequestReadMemory(
596061da546Spatrick           addr + total_bytes_read, data_buffer + total_bytes_read,
597061da546Spatrick           bytes_to_read_this_request, error);
598061da546Spatrick       total_bytes_read += bytes_read;
599061da546Spatrick       if (error.Fail() || bytes_read == 0) {
600061da546Spatrick         return total_bytes_read;
601061da546Spatrick       }
602061da546Spatrick     }
603061da546Spatrick 
604061da546Spatrick     return total_bytes_read;
605061da546Spatrick   }
606061da546Spatrick   error.SetErrorString("not connected");
607061da546Spatrick   return 0;
608061da546Spatrick }
609061da546Spatrick 
DoWriteMemory(addr_t addr,const void * buf,size_t size,Status & error)610061da546Spatrick size_t ProcessKDP::DoWriteMemory(addr_t addr, const void *buf, size_t size,
611061da546Spatrick                                  Status &error) {
612061da546Spatrick   if (m_comm.IsConnected())
613061da546Spatrick     return m_comm.SendRequestWriteMemory(addr, buf, size, error);
614061da546Spatrick   error.SetErrorString("not connected");
615061da546Spatrick   return 0;
616061da546Spatrick }
617061da546Spatrick 
DoAllocateMemory(size_t size,uint32_t permissions,Status & error)618061da546Spatrick lldb::addr_t ProcessKDP::DoAllocateMemory(size_t size, uint32_t permissions,
619061da546Spatrick                                           Status &error) {
620061da546Spatrick   error.SetErrorString(
621061da546Spatrick       "memory allocation not supported in kdp remote debugging");
622061da546Spatrick   return LLDB_INVALID_ADDRESS;
623061da546Spatrick }
624061da546Spatrick 
DoDeallocateMemory(lldb::addr_t addr)625061da546Spatrick Status ProcessKDP::DoDeallocateMemory(lldb::addr_t addr) {
626061da546Spatrick   Status error;
627061da546Spatrick   error.SetErrorString(
628061da546Spatrick       "memory deallocation not supported in kdp remote debugging");
629061da546Spatrick   return error;
630061da546Spatrick }
631061da546Spatrick 
EnableBreakpointSite(BreakpointSite * bp_site)632061da546Spatrick Status ProcessKDP::EnableBreakpointSite(BreakpointSite *bp_site) {
633be691f3bSpatrick   if (bp_site->HardwareRequired())
634be691f3bSpatrick     return Status("Hardware breakpoints are not supported.");
635be691f3bSpatrick 
636061da546Spatrick   if (m_comm.LocalBreakpointsAreSupported()) {
637061da546Spatrick     Status error;
638061da546Spatrick     if (!bp_site->IsEnabled()) {
639061da546Spatrick       if (m_comm.SendRequestBreakpoint(true, bp_site->GetLoadAddress())) {
640061da546Spatrick         bp_site->SetEnabled(true);
641061da546Spatrick         bp_site->SetType(BreakpointSite::eExternal);
642061da546Spatrick       } else {
643061da546Spatrick         error.SetErrorString("KDP set breakpoint failed");
644061da546Spatrick       }
645061da546Spatrick     }
646061da546Spatrick     return error;
647061da546Spatrick   }
648061da546Spatrick   return EnableSoftwareBreakpoint(bp_site);
649061da546Spatrick }
650061da546Spatrick 
DisableBreakpointSite(BreakpointSite * bp_site)651061da546Spatrick Status ProcessKDP::DisableBreakpointSite(BreakpointSite *bp_site) {
652061da546Spatrick   if (m_comm.LocalBreakpointsAreSupported()) {
653061da546Spatrick     Status error;
654061da546Spatrick     if (bp_site->IsEnabled()) {
655061da546Spatrick       BreakpointSite::Type bp_type = bp_site->GetType();
656061da546Spatrick       if (bp_type == BreakpointSite::eExternal) {
657061da546Spatrick         if (m_destroy_in_process && m_comm.IsRunning()) {
658061da546Spatrick           // We are trying to destroy our connection and we are running
659061da546Spatrick           bp_site->SetEnabled(false);
660061da546Spatrick         } else {
661061da546Spatrick           if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress()))
662061da546Spatrick             bp_site->SetEnabled(false);
663061da546Spatrick           else
664061da546Spatrick             error.SetErrorString("KDP remove breakpoint failed");
665061da546Spatrick         }
666061da546Spatrick       } else {
667061da546Spatrick         error = DisableSoftwareBreakpoint(bp_site);
668061da546Spatrick       }
669061da546Spatrick     }
670061da546Spatrick     return error;
671061da546Spatrick   }
672061da546Spatrick   return DisableSoftwareBreakpoint(bp_site);
673061da546Spatrick }
674061da546Spatrick 
EnableWatchpoint(Watchpoint * wp,bool notify)675061da546Spatrick Status ProcessKDP::EnableWatchpoint(Watchpoint *wp, bool notify) {
676061da546Spatrick   Status error;
677061da546Spatrick   error.SetErrorString(
678061da546Spatrick       "watchpoints are not supported in kdp remote debugging");
679061da546Spatrick   return error;
680061da546Spatrick }
681061da546Spatrick 
DisableWatchpoint(Watchpoint * wp,bool notify)682061da546Spatrick Status ProcessKDP::DisableWatchpoint(Watchpoint *wp, bool notify) {
683061da546Spatrick   Status error;
684061da546Spatrick   error.SetErrorString(
685061da546Spatrick       "watchpoints are not supported in kdp remote debugging");
686061da546Spatrick   return error;
687061da546Spatrick }
688061da546Spatrick 
Clear()689061da546Spatrick void ProcessKDP::Clear() { m_thread_list.Clear(); }
690061da546Spatrick 
DoSignal(int signo)691061da546Spatrick Status ProcessKDP::DoSignal(int signo) {
692061da546Spatrick   Status error;
693061da546Spatrick   error.SetErrorString(
694061da546Spatrick       "sending signals is not supported in kdp remote debugging");
695061da546Spatrick   return error;
696061da546Spatrick }
697061da546Spatrick 
Initialize()698061da546Spatrick void ProcessKDP::Initialize() {
699061da546Spatrick   static llvm::once_flag g_once_flag;
700061da546Spatrick 
701061da546Spatrick   llvm::call_once(g_once_flag, []() {
702061da546Spatrick     PluginManager::RegisterPlugin(GetPluginNameStatic(),
703061da546Spatrick                                   GetPluginDescriptionStatic(), CreateInstance,
704061da546Spatrick                                   DebuggerInitialize);
705061da546Spatrick 
706061da546Spatrick     ProcessKDPLog::Initialize();
707061da546Spatrick   });
708061da546Spatrick }
709061da546Spatrick 
DebuggerInitialize(lldb_private::Debugger & debugger)710061da546Spatrick void ProcessKDP::DebuggerInitialize(lldb_private::Debugger &debugger) {
711061da546Spatrick   if (!PluginManager::GetSettingForProcessPlugin(
712061da546Spatrick           debugger, PluginProperties::GetSettingName())) {
713061da546Spatrick     const bool is_global_setting = true;
714061da546Spatrick     PluginManager::CreateSettingForProcessPlugin(
715*f6aab3d8Srobert         debugger, GetGlobalPluginProperties().GetValueProperties(),
716061da546Spatrick         ConstString("Properties for the kdp-remote process plug-in."),
717061da546Spatrick         is_global_setting);
718061da546Spatrick   }
719061da546Spatrick }
720061da546Spatrick 
StartAsyncThread()721061da546Spatrick bool ProcessKDP::StartAsyncThread() {
722*f6aab3d8Srobert   Log *log = GetLog(KDPLog::Process);
723061da546Spatrick 
724061da546Spatrick   LLDB_LOGF(log, "ProcessKDP::StartAsyncThread ()");
725061da546Spatrick 
726061da546Spatrick   if (m_async_thread.IsJoinable())
727061da546Spatrick     return true;
728061da546Spatrick 
729061da546Spatrick   llvm::Expected<HostThread> async_thread = ThreadLauncher::LaunchThread(
730*f6aab3d8Srobert       "<lldb.process.kdp-remote.async>", [this] { return AsyncThread(); });
731061da546Spatrick   if (!async_thread) {
732*f6aab3d8Srobert     LLDB_LOG_ERROR(GetLog(LLDBLog::Host), async_thread.takeError(),
733*f6aab3d8Srobert                    "failed to launch host thread: {}");
734061da546Spatrick     return false;
735061da546Spatrick   }
736061da546Spatrick   m_async_thread = *async_thread;
737061da546Spatrick   return m_async_thread.IsJoinable();
738061da546Spatrick }
739061da546Spatrick 
StopAsyncThread()740061da546Spatrick void ProcessKDP::StopAsyncThread() {
741*f6aab3d8Srobert   Log *log = GetLog(KDPLog::Process);
742061da546Spatrick 
743061da546Spatrick   LLDB_LOGF(log, "ProcessKDP::StopAsyncThread ()");
744061da546Spatrick 
745061da546Spatrick   m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit);
746061da546Spatrick 
747061da546Spatrick   // Stop the stdio thread
748061da546Spatrick   if (m_async_thread.IsJoinable())
749061da546Spatrick     m_async_thread.Join(nullptr);
750061da546Spatrick }
751061da546Spatrick 
AsyncThread()752*f6aab3d8Srobert void *ProcessKDP::AsyncThread() {
753*f6aab3d8Srobert   const lldb::pid_t pid = GetID();
754061da546Spatrick 
755*f6aab3d8Srobert   Log *log = GetLog(KDPLog::Process);
756061da546Spatrick   LLDB_LOGF(log,
757*f6aab3d8Srobert             "ProcessKDP::AsyncThread(pid = %" PRIu64 ") thread starting...",
758*f6aab3d8Srobert             pid);
759061da546Spatrick 
760061da546Spatrick   ListenerSP listener_sp(Listener::MakeListener("ProcessKDP::AsyncThread"));
761061da546Spatrick   EventSP event_sp;
762061da546Spatrick   const uint32_t desired_event_mask =
763061da546Spatrick       eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit;
764061da546Spatrick 
765*f6aab3d8Srobert   if (listener_sp->StartListeningForEvents(
766*f6aab3d8Srobert           &m_async_broadcaster, desired_event_mask) == desired_event_mask) {
767061da546Spatrick     bool done = false;
768061da546Spatrick     while (!done) {
769061da546Spatrick       LLDB_LOGF(log,
770061da546Spatrick                 "ProcessKDP::AsyncThread (pid = %" PRIu64
771061da546Spatrick                 ") listener.WaitForEvent (NULL, event_sp)...",
772061da546Spatrick                 pid);
773*f6aab3d8Srobert       if (listener_sp->GetEvent(event_sp, std::nullopt)) {
774061da546Spatrick         uint32_t event_type = event_sp->GetType();
775061da546Spatrick         LLDB_LOGF(log,
776061da546Spatrick                   "ProcessKDP::AsyncThread (pid = %" PRIu64
777061da546Spatrick                   ") Got an event of type: %d...",
778061da546Spatrick                   pid, event_type);
779061da546Spatrick 
780061da546Spatrick         // When we are running, poll for 1 second to try and get an exception
781061da546Spatrick         // to indicate the process has stopped. If we don't get one, check to
782061da546Spatrick         // make sure no one asked us to exit
783061da546Spatrick         bool is_running = false;
784061da546Spatrick         DataExtractor exc_reply_packet;
785061da546Spatrick         do {
786061da546Spatrick           switch (event_type) {
787061da546Spatrick           case eBroadcastBitAsyncContinue: {
788061da546Spatrick             is_running = true;
789*f6aab3d8Srobert             if (m_comm.WaitForPacketWithTimeoutMicroSeconds(
790061da546Spatrick                     exc_reply_packet, 1 * USEC_PER_SEC)) {
791*f6aab3d8Srobert               ThreadSP thread_sp(GetKernelThread());
792061da546Spatrick               if (thread_sp) {
793061da546Spatrick                 lldb::RegisterContextSP reg_ctx_sp(
794061da546Spatrick                     thread_sp->GetRegisterContext());
795061da546Spatrick                 if (reg_ctx_sp)
796061da546Spatrick                   reg_ctx_sp->InvalidateAllRegisters();
797061da546Spatrick                 static_cast<ThreadKDP *>(thread_sp.get())
798061da546Spatrick                     ->SetStopInfoFrom_KDP_EXCEPTION(exc_reply_packet);
799061da546Spatrick               }
800061da546Spatrick 
801061da546Spatrick               // TODO: parse the stop reply packet
802061da546Spatrick               is_running = false;
803*f6aab3d8Srobert               SetPrivateState(eStateStopped);
804061da546Spatrick             } else {
805061da546Spatrick               // Check to see if we are supposed to exit. There is no way to
806061da546Spatrick               // interrupt a running kernel, so all we can do is wait for an
807061da546Spatrick               // exception or detach...
808061da546Spatrick               if (listener_sp->GetEvent(event_sp,
809061da546Spatrick                                         std::chrono::microseconds(0))) {
810061da546Spatrick                 // We got an event, go through the loop again
811061da546Spatrick                 event_type = event_sp->GetType();
812061da546Spatrick               }
813061da546Spatrick             }
814061da546Spatrick           } break;
815061da546Spatrick 
816061da546Spatrick           case eBroadcastBitAsyncThreadShouldExit:
817061da546Spatrick             LLDB_LOGF(log,
818061da546Spatrick                       "ProcessKDP::AsyncThread (pid = %" PRIu64
819061da546Spatrick                       ") got eBroadcastBitAsyncThreadShouldExit...",
820061da546Spatrick                       pid);
821061da546Spatrick             done = true;
822061da546Spatrick             is_running = false;
823061da546Spatrick             break;
824061da546Spatrick 
825061da546Spatrick           default:
826061da546Spatrick             LLDB_LOGF(log,
827061da546Spatrick                       "ProcessKDP::AsyncThread (pid = %" PRIu64
828061da546Spatrick                       ") got unknown event 0x%8.8x",
829061da546Spatrick                       pid, event_type);
830061da546Spatrick             done = true;
831061da546Spatrick             is_running = false;
832061da546Spatrick             break;
833061da546Spatrick           }
834061da546Spatrick         } while (is_running);
835061da546Spatrick       } else {
836061da546Spatrick         LLDB_LOGF(log,
837061da546Spatrick                   "ProcessKDP::AsyncThread (pid = %" PRIu64
838061da546Spatrick                   ") listener.WaitForEvent (NULL, event_sp) => false",
839061da546Spatrick                   pid);
840061da546Spatrick         done = true;
841061da546Spatrick       }
842061da546Spatrick     }
843061da546Spatrick   }
844061da546Spatrick 
845*f6aab3d8Srobert   LLDB_LOGF(log, "ProcessKDP::AsyncThread(pid = %" PRIu64 ") thread exiting...",
846*f6aab3d8Srobert             pid);
847061da546Spatrick 
848*f6aab3d8Srobert   m_async_thread.Reset();
849061da546Spatrick   return NULL;
850061da546Spatrick }
851061da546Spatrick 
852061da546Spatrick class CommandObjectProcessKDPPacketSend : public CommandObjectParsed {
853061da546Spatrick private:
854061da546Spatrick   OptionGroupOptions m_option_group;
855061da546Spatrick   OptionGroupUInt64 m_command_byte;
856061da546Spatrick   OptionGroupString m_packet_data;
857061da546Spatrick 
GetOptions()858be691f3bSpatrick   Options *GetOptions() override { return &m_option_group; }
859061da546Spatrick 
860061da546Spatrick public:
CommandObjectProcessKDPPacketSend(CommandInterpreter & interpreter)861061da546Spatrick   CommandObjectProcessKDPPacketSend(CommandInterpreter &interpreter)
862061da546Spatrick       : CommandObjectParsed(interpreter, "process plugin packet send",
863061da546Spatrick                             "Send a custom packet through the KDP protocol by "
864061da546Spatrick                             "specifying the command byte and the packet "
865061da546Spatrick                             "payload data. A packet will be sent with a "
866061da546Spatrick                             "correct header and payload, and the raw result "
867061da546Spatrick                             "bytes will be displayed as a string value. ",
868061da546Spatrick                             NULL),
869061da546Spatrick         m_option_group(),
870061da546Spatrick         m_command_byte(LLDB_OPT_SET_1, true, "command", 'c', 0, eArgTypeNone,
871061da546Spatrick                        "Specify the command byte to use when sending the KDP "
872061da546Spatrick                        "request packet.",
873061da546Spatrick                        0),
874061da546Spatrick         m_packet_data(LLDB_OPT_SET_1, false, "payload", 'p', 0, eArgTypeNone,
875061da546Spatrick                       "Specify packet payload bytes as a hex ASCII string with "
876061da546Spatrick                       "no spaces or hex prefixes.",
877061da546Spatrick                       NULL) {
878061da546Spatrick     m_option_group.Append(&m_command_byte, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
879061da546Spatrick     m_option_group.Append(&m_packet_data, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
880061da546Spatrick     m_option_group.Finalize();
881061da546Spatrick   }
882061da546Spatrick 
883*f6aab3d8Srobert   ~CommandObjectProcessKDPPacketSend() override = default;
884061da546Spatrick 
DoExecute(Args & command,CommandReturnObject & result)885be691f3bSpatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
886061da546Spatrick     if (!m_command_byte.GetOptionValue().OptionWasSet()) {
887061da546Spatrick       result.AppendError(
888061da546Spatrick           "the --command option must be set to a valid command byte");
889061da546Spatrick     } else {
890061da546Spatrick       const uint64_t command_byte =
891061da546Spatrick           m_command_byte.GetOptionValue().GetUInt64Value(0);
892061da546Spatrick       if (command_byte > 0 && command_byte <= UINT8_MAX) {
893061da546Spatrick         ProcessKDP *process =
894061da546Spatrick             (ProcessKDP *)m_interpreter.GetExecutionContext().GetProcessPtr();
895061da546Spatrick         if (process) {
896061da546Spatrick           const StateType state = process->GetState();
897061da546Spatrick 
898061da546Spatrick           if (StateIsStoppedState(state, true)) {
899061da546Spatrick             std::vector<uint8_t> payload_bytes;
900061da546Spatrick             const char *ascii_hex_bytes_cstr =
901061da546Spatrick                 m_packet_data.GetOptionValue().GetCurrentValue();
902061da546Spatrick             if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0]) {
903061da546Spatrick               StringExtractor extractor(ascii_hex_bytes_cstr);
904061da546Spatrick               const size_t ascii_hex_bytes_cstr_len =
905061da546Spatrick                   extractor.GetStringRef().size();
906061da546Spatrick               if (ascii_hex_bytes_cstr_len & 1) {
907061da546Spatrick                 result.AppendErrorWithFormat("payload data must contain an "
908061da546Spatrick                                              "even number of ASCII hex "
909061da546Spatrick                                              "characters: '%s'",
910061da546Spatrick                                              ascii_hex_bytes_cstr);
911061da546Spatrick                 return false;
912061da546Spatrick               }
913061da546Spatrick               payload_bytes.resize(ascii_hex_bytes_cstr_len / 2);
914061da546Spatrick               if (extractor.GetHexBytes(payload_bytes, '\xdd') !=
915061da546Spatrick                   payload_bytes.size()) {
916061da546Spatrick                 result.AppendErrorWithFormat("payload data must only contain "
917061da546Spatrick                                              "ASCII hex characters (no "
918061da546Spatrick                                              "spaces or hex prefixes): '%s'",
919061da546Spatrick                                              ascii_hex_bytes_cstr);
920061da546Spatrick                 return false;
921061da546Spatrick               }
922061da546Spatrick             }
923061da546Spatrick             Status error;
924061da546Spatrick             DataExtractor reply;
925061da546Spatrick             process->GetCommunication().SendRawRequest(
926061da546Spatrick                 command_byte,
927061da546Spatrick                 payload_bytes.empty() ? NULL : payload_bytes.data(),
928061da546Spatrick                 payload_bytes.size(), reply, error);
929061da546Spatrick 
930061da546Spatrick             if (error.Success()) {
931061da546Spatrick               // Copy the binary bytes into a hex ASCII string for the result
932061da546Spatrick               StreamString packet;
933061da546Spatrick               packet.PutBytesAsRawHex8(
934061da546Spatrick                   reply.GetDataStart(), reply.GetByteSize(),
935061da546Spatrick                   endian::InlHostByteOrder(), endian::InlHostByteOrder());
936061da546Spatrick               result.AppendMessage(packet.GetString());
937061da546Spatrick               result.SetStatus(eReturnStatusSuccessFinishResult);
938061da546Spatrick               return true;
939061da546Spatrick             } else {
940061da546Spatrick               const char *error_cstr = error.AsCString();
941061da546Spatrick               if (error_cstr && error_cstr[0])
942061da546Spatrick                 result.AppendError(error_cstr);
943061da546Spatrick               else
944061da546Spatrick                 result.AppendErrorWithFormat("unknown error 0x%8.8x",
945061da546Spatrick                                              error.GetError());
946061da546Spatrick               return false;
947061da546Spatrick             }
948061da546Spatrick           } else {
949061da546Spatrick             result.AppendErrorWithFormat("process must be stopped in order "
950061da546Spatrick                                          "to send KDP packets, state is %s",
951061da546Spatrick                                          StateAsCString(state));
952061da546Spatrick           }
953061da546Spatrick         } else {
954061da546Spatrick           result.AppendError("invalid process");
955061da546Spatrick         }
956061da546Spatrick       } else {
957061da546Spatrick         result.AppendErrorWithFormat("invalid command byte 0x%" PRIx64
958061da546Spatrick                                      ", valid values are 1 - 255",
959061da546Spatrick                                      command_byte);
960061da546Spatrick       }
961061da546Spatrick     }
962061da546Spatrick     return false;
963061da546Spatrick   }
964061da546Spatrick };
965061da546Spatrick 
966061da546Spatrick class CommandObjectProcessKDPPacket : public CommandObjectMultiword {
967061da546Spatrick private:
968061da546Spatrick public:
CommandObjectProcessKDPPacket(CommandInterpreter & interpreter)969061da546Spatrick   CommandObjectProcessKDPPacket(CommandInterpreter &interpreter)
970061da546Spatrick       : CommandObjectMultiword(interpreter, "process plugin packet",
971061da546Spatrick                                "Commands that deal with KDP remote packets.",
972061da546Spatrick                                NULL) {
973061da546Spatrick     LoadSubCommand(
974061da546Spatrick         "send",
975061da546Spatrick         CommandObjectSP(new CommandObjectProcessKDPPacketSend(interpreter)));
976061da546Spatrick   }
977061da546Spatrick 
978*f6aab3d8Srobert   ~CommandObjectProcessKDPPacket() override = default;
979061da546Spatrick };
980061da546Spatrick 
981061da546Spatrick class CommandObjectMultiwordProcessKDP : public CommandObjectMultiword {
982061da546Spatrick public:
CommandObjectMultiwordProcessKDP(CommandInterpreter & interpreter)983061da546Spatrick   CommandObjectMultiwordProcessKDP(CommandInterpreter &interpreter)
984061da546Spatrick       : CommandObjectMultiword(
985061da546Spatrick             interpreter, "process plugin",
986061da546Spatrick             "Commands for operating on a ProcessKDP process.",
987061da546Spatrick             "process plugin <subcommand> [<subcommand-options>]") {
988061da546Spatrick     LoadSubCommand("packet", CommandObjectSP(new CommandObjectProcessKDPPacket(
989061da546Spatrick                                  interpreter)));
990061da546Spatrick   }
991061da546Spatrick 
992*f6aab3d8Srobert   ~CommandObjectMultiwordProcessKDP() override = default;
993061da546Spatrick };
994061da546Spatrick 
GetPluginCommandObject()995061da546Spatrick CommandObject *ProcessKDP::GetPluginCommandObject() {
996061da546Spatrick   if (!m_command_sp)
997061da546Spatrick     m_command_sp = std::make_shared<CommandObjectMultiwordProcessKDP>(
998061da546Spatrick         GetTarget().GetDebugger().GetCommandInterpreter());
999061da546Spatrick   return m_command_sp.get();
1000061da546Spatrick }
1001