blob: 2f174932f7a5c83f044b41fa7eca19bab5174a0b [file] [log] [blame]
Greg Clayton59ec5122011-07-15 18:02:58 +00001//===-- ProcessKDP.cpp ------------------------------------------*- C++ -*-===//
Greg Claytonf9765ac2011-07-15 03:27:12 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// C Includes
11#include <errno.h>
12#include <stdlib.h>
13
14// C++ Includes
Benjamin Kramer3f69fa62015-04-03 10:55:00 +000015#include <mutex>
16
Greg Claytonf9765ac2011-07-15 03:27:12 +000017// Other libraries and framework includes
Greg Clayton07e66e32011-07-20 03:41:06 +000018#include "lldb/Core/Debugger.h"
Greg Clayton1f746072012-08-29 21:13:06 +000019#include "lldb/Core/Module.h"
Jason Molenda4bd4e7e2012-09-29 04:02:01 +000020#include "lldb/Core/ModuleSpec.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000021#include "lldb/Core/PluginManager.h"
Zachary Turner93a66fc2014-10-06 21:22:36 +000022#include "lldb/Host/ConnectionFileDescriptor.h"
Greg Claytonf9765ac2011-07-15 03:27:12 +000023#include "lldb/Host/Host.h"
Jason Molenda4bd4e7e2012-09-29 04:02:01 +000024#include "lldb/Host/Symbols.h"
Zachary Turner39de3112014-09-09 20:54:56 +000025#include "lldb/Host/ThreadLauncher.h"
Oleksiy Vyalove98628c2015-10-15 23:54:09 +000026#include "lldb/Host/common/TCPSocket.h"
Greg Clayton1d19a2f2012-10-19 22:22:57 +000027#include "lldb/Interpreter/CommandInterpreter.h"
28#include "lldb/Interpreter/CommandObject.h"
29#include "lldb/Interpreter/CommandObjectMultiword.h"
30#include "lldb/Interpreter/CommandReturnObject.h"
31#include "lldb/Interpreter/OptionGroupString.h"
32#include "lldb/Interpreter/OptionGroupUInt64.h"
Ilia K41204d02015-03-04 12:05:24 +000033#include "lldb/Interpreter/OptionValueProperties.h"
Greg Clayton1f746072012-08-29 21:13:06 +000034#include "lldb/Symbol/ObjectFile.h"
Greg Clayton7925fbb2012-09-21 16:31:20 +000035#include "lldb/Target/RegisterContext.h"
Greg Clayton57508022011-07-15 16:31:38 +000036#include "lldb/Target/Target.h"
Greg Claytona63d08c2011-07-19 03:57:15 +000037#include "lldb/Target/Thread.h"
Pavel Labathd821c992018-08-07 11:07:21 +000038#include "lldb/Utility/State.h"
Bruce Mitchener45788152015-07-07 23:59:01 +000039#include "lldb/Utility/StringExtractor.h"
Pavel Labathd821c992018-08-07 11:07:21 +000040#include "lldb/Utility/UUID.h"
Greg Claytonf9765ac2011-07-15 03:27:12 +000041
Kamil Rytarowskic5f28e22017-02-06 17:55:02 +000042#include "llvm/Support/Threading.h"
43
Charles Davis510938e2013-08-27 05:04:57 +000044#define USEC_PER_SEC 1000000
45
Greg Claytonf9765ac2011-07-15 03:27:12 +000046// Project includes
Kate Stoneb9c1b512016-09-06 20:57:50 +000047#include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h"
48#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"
Greg Claytonf9765ac2011-07-15 03:27:12 +000049#include "ProcessKDP.h"
50#include "ProcessKDPLog.h"
Greg Claytona63d08c2011-07-19 03:57:15 +000051#include "ThreadKDP.h"
Greg Claytonf9765ac2011-07-15 03:27:12 +000052
53using namespace lldb;
54using namespace lldb_private;
55
Greg Clayton7f982402013-07-15 22:54:20 +000056namespace {
57
Tatyana Krasnukhae40db052018-09-27 07:11:58 +000058static constexpr PropertyDefinition g_properties[] = {
Tatyana Krasnukhaf929e2b2018-09-26 20:31:39 +000059 {"packet-timeout", OptionValue::eTypeUInt64, true, 5, NULL, {},
Tatyana Krasnukhae40db052018-09-27 07:11:58 +000060 "Specify the default packet timeout in seconds."}};
Greg Clayton7f982402013-07-15 22:54:20 +000061
Kate Stoneb9c1b512016-09-06 20:57:50 +000062enum { ePropertyPacketTimeout };
Greg Clayton7f982402013-07-15 22:54:20 +000063
Kate Stoneb9c1b512016-09-06 20:57:50 +000064class PluginProperties : public Properties {
65public:
66 static ConstString GetSettingName() {
67 return ProcessKDP::GetPluginNameStatic();
68 }
Greg Clayton7f982402013-07-15 22:54:20 +000069
Kate Stoneb9c1b512016-09-06 20:57:50 +000070 PluginProperties() : Properties() {
71 m_collection_sp.reset(new OptionValueProperties(GetSettingName()));
72 m_collection_sp->Initialize(g_properties);
73 }
Greg Clayton7f982402013-07-15 22:54:20 +000074
Kate Stoneb9c1b512016-09-06 20:57:50 +000075 virtual ~PluginProperties() {}
76
77 uint64_t GetPacketTimeout() {
78 const uint32_t idx = ePropertyPacketTimeout;
79 return m_collection_sp->GetPropertyAtIndexAsUInt64(
80 NULL, idx, g_properties[idx].default_uint_value);
81 }
82};
83
84typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP;
85
86static const ProcessKDPPropertiesSP &GetGlobalPluginProperties() {
87 static ProcessKDPPropertiesSP g_settings_sp;
88 if (!g_settings_sp)
89 g_settings_sp.reset(new PluginProperties());
90 return g_settings_sp;
91}
92
Greg Clayton7f982402013-07-15 22:54:20 +000093} // anonymous namespace end
94
Andrew Kaylorba4e61d2013-05-07 18:35:34 +000095static const lldb::tid_t g_kernel_tid = 1;
96
Kate Stoneb9c1b512016-09-06 20:57:50 +000097ConstString ProcessKDP::GetPluginNameStatic() {
98 static ConstString g_name("kdp-remote");
99 return g_name;
Greg Claytonf9765ac2011-07-15 03:27:12 +0000100}
101
Kate Stoneb9c1b512016-09-06 20:57:50 +0000102const char *ProcessKDP::GetPluginDescriptionStatic() {
103 return "KDP Remote protocol based debugging plug-in for darwin kernel "
104 "debugging.";
Greg Claytonf9765ac2011-07-15 03:27:12 +0000105}
106
Kate Stoneb9c1b512016-09-06 20:57:50 +0000107void ProcessKDP::Terminate() {
108 PluginManager::UnregisterPlugin(ProcessKDP::CreateInstance);
Greg Claytonf9765ac2011-07-15 03:27:12 +0000109}
110
Kate Stoneb9c1b512016-09-06 20:57:50 +0000111lldb::ProcessSP ProcessKDP::CreateInstance(TargetSP target_sp,
112 ListenerSP listener_sp,
113 const FileSpec *crash_file_path) {
114 lldb::ProcessSP process_sp;
115 if (crash_file_path == NULL)
116 process_sp.reset(new ProcessKDP(target_sp, listener_sp));
117 return process_sp;
Greg Claytonf9765ac2011-07-15 03:27:12 +0000118}
119
Kate Stoneb9c1b512016-09-06 20:57:50 +0000120bool ProcessKDP::CanDebug(TargetSP target_sp, bool plugin_specified_by_name) {
121 if (plugin_specified_by_name)
122 return true;
Greg Clayton596ed242011-10-21 21:41:45 +0000123
Kate Stoneb9c1b512016-09-06 20:57:50 +0000124 // For now we are just making sure the file exists for a given module
125 Module *exe_module = target_sp->GetExecutableModulePointer();
126 if (exe_module) {
127 const llvm::Triple &triple_ref = target_sp->GetArchitecture().GetTriple();
128 switch (triple_ref.getOS()) {
129 case llvm::Triple::Darwin: // Should use "macosx" for desktop and "ios" for
130 // iOS, but accept darwin just in case
131 case llvm::Triple::MacOSX: // For desktop targets
132 case llvm::Triple::IOS: // For arm targets
133 case llvm::Triple::TvOS:
134 case llvm::Triple::WatchOS:
135 if (triple_ref.getVendor() == llvm::Triple::Apple) {
136 ObjectFile *exe_objfile = exe_module->GetObjectFile();
137 if (exe_objfile->GetType() == ObjectFile::eTypeExecutable &&
138 exe_objfile->GetStrata() == ObjectFile::eStrataKernel)
139 return true;
140 }
141 break;
Greg Clayton70512312012-05-08 01:45:38 +0000142
Kate Stoneb9c1b512016-09-06 20:57:50 +0000143 default:
144 break;
Greg Claytonf9765ac2011-07-15 03:27:12 +0000145 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000146 }
147 return false;
Greg Claytonf9765ac2011-07-15 03:27:12 +0000148}
149
150//----------------------------------------------------------------------
151// ProcessKDP constructor
152//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000153ProcessKDP::ProcessKDP(TargetSP target_sp, ListenerSP listener_sp)
154 : Process(target_sp, listener_sp),
155 m_comm("lldb.process.kdp-remote.communication"),
156 m_async_broadcaster(NULL, "lldb.process.kdp-remote.async-broadcaster"),
157 m_dyld_plugin_name(), m_kernel_load_addr(LLDB_INVALID_ADDRESS),
158 m_command_sp(), m_kernel_thread_wp() {
159 m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit,
160 "async thread should exit");
161 m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue,
162 "async thread continue");
163 const uint64_t timeout_seconds =
164 GetGlobalPluginProperties()->GetPacketTimeout();
165 if (timeout_seconds > 0)
Pavel Labath5cddd602016-11-02 10:13:54 +0000166 m_comm.SetPacketTimeout(std::chrono::seconds(timeout_seconds));
Greg Claytonf9765ac2011-07-15 03:27:12 +0000167}
168
169//----------------------------------------------------------------------
170// Destructor
171//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000172ProcessKDP::~ProcessKDP() {
173 Clear();
Adrian Prantl05097242018-04-30 16:49:04 +0000174 // We need to call finalize on the process before destroying ourselves to
175 // make sure all of the broadcaster cleanup goes as planned. If we destruct
176 // this class, then Process::~Process() might have problems trying to fully
177 // destroy the broadcaster.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000178 Finalize();
Greg Claytonf9765ac2011-07-15 03:27:12 +0000179}
180
181//----------------------------------------------------------------------
182// PluginInterface
183//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000184lldb_private::ConstString ProcessKDP::GetPluginName() {
185 return GetPluginNameStatic();
Greg Claytonf9765ac2011-07-15 03:27:12 +0000186}
187
Kate Stoneb9c1b512016-09-06 20:57:50 +0000188uint32_t ProcessKDP::GetPluginVersion() { return 1; }
189
Zachary Turner97206d52017-05-12 04:51:55 +0000190Status ProcessKDP::WillLaunch(Module *module) {
191 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000192 error.SetErrorString("launching not supported in kdp-remote plug-in");
193 return error;
Greg Claytonf9765ac2011-07-15 03:27:12 +0000194}
195
Zachary Turner97206d52017-05-12 04:51:55 +0000196Status ProcessKDP::WillAttachToProcessWithID(lldb::pid_t pid) {
197 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000198 error.SetErrorString(
199 "attaching to a by process ID not supported in kdp-remote plug-in");
200 return error;
201}
202
Zachary Turner97206d52017-05-12 04:51:55 +0000203Status ProcessKDP::WillAttachToProcessWithName(const char *process_name,
204 bool wait_for_launch) {
205 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000206 error.SetErrorString(
207 "attaching to a by process name not supported in kdp-remote plug-in");
208 return error;
209}
210
211bool ProcessKDP::GetHostArchitecture(ArchSpec &arch) {
212 uint32_t cpu = m_comm.GetCPUType();
213 if (cpu) {
214 uint32_t sub = m_comm.GetCPUSubtype();
215 arch.SetArchitecture(eArchTypeMachO, cpu, sub);
216 // Leave architecture vendor as unspecified unknown
217 arch.GetTriple().setVendor(llvm::Triple::UnknownVendor);
218 arch.GetTriple().setVendorName(llvm::StringRef());
219 return true;
220 }
221 arch.Clear();
222 return false;
223}
224
Zachary Turner97206d52017-05-12 04:51:55 +0000225Status ProcessKDP::DoConnectRemote(Stream *strm, llvm::StringRef remote_url) {
226 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000227
Adrian Prantl05097242018-04-30 16:49:04 +0000228 // Don't let any JIT happen when doing KDP as we can't allocate memory and we
229 // don't want to be mucking with threads that might already be handling
230 // exceptions
Kate Stoneb9c1b512016-09-06 20:57:50 +0000231 SetCanJIT(false);
232
Greg Clayton3ce7e992016-12-07 23:51:49 +0000233 if (remote_url.empty()) {
234 error.SetErrorStringWithFormat("empty connection URL");
Greg Claytonf9765ac2011-07-15 03:27:12 +0000235 return error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000236 }
Greg Claytonf9765ac2011-07-15 03:27:12 +0000237
Kate Stoneb9c1b512016-09-06 20:57:50 +0000238 std::unique_ptr<ConnectionFileDescriptor> conn_ap(
239 new ConnectionFileDescriptor());
240 if (conn_ap.get()) {
241 // Only try once for now.
242 // TODO: check if we should be retrying?
243 const uint32_t max_retry_count = 1;
244 for (uint32_t retry_count = 0; retry_count < max_retry_count;
245 ++retry_count) {
246 if (conn_ap->Connect(remote_url, &error) == eConnectionStatusSuccess)
247 break;
248 usleep(100000);
Greg Claytona3706882015-10-28 23:26:59 +0000249 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000250 }
Greg Claytona3706882015-10-28 23:26:59 +0000251
Kate Stoneb9c1b512016-09-06 20:57:50 +0000252 if (conn_ap->IsConnected()) {
253 const TCPSocket &socket =
254 static_cast<const TCPSocket &>(*conn_ap->GetReadObject());
255 const uint16_t reply_port = socket.GetLocalPortNumber();
Greg Clayton7925fbb2012-09-21 16:31:20 +0000256
Kate Stoneb9c1b512016-09-06 20:57:50 +0000257 if (reply_port != 0) {
258 m_comm.SetConnection(conn_ap.release());
Greg Clayton7925fbb2012-09-21 16:31:20 +0000259
Kate Stoneb9c1b512016-09-06 20:57:50 +0000260 if (m_comm.SendRequestReattach(reply_port)) {
261 if (m_comm.SendRequestConnect(reply_port, reply_port,
262 "Greetings from LLDB...")) {
263 m_comm.GetVersion();
Greg Clayton3a29bdb2011-07-17 20:36:25 +0000264
Kate Stoneb9c1b512016-09-06 20:57:50 +0000265 Target &target = GetTarget();
266 ArchSpec kernel_arch;
267 // The host architecture
268 GetHostArchitecture(kernel_arch);
269 ArchSpec target_arch = target.GetArchitecture();
270 // Merge in any unspecified stuff into the target architecture in
271 // case the target arch isn't set at all or incompletely.
272 target_arch.MergeFrom(kernel_arch);
273 target.SetArchitecture(target_arch);
Greg Clayton3a29bdb2011-07-17 20:36:25 +0000274
Kate Stoneb9c1b512016-09-06 20:57:50 +0000275 /* Get the kernel's UUID and load address via KDP_KERNELVERSION
276 * packet. */
277 /* An EFI kdp session has neither UUID nor load address. */
Greg Clayton3a29bdb2011-07-17 20:36:25 +0000278
Kate Stoneb9c1b512016-09-06 20:57:50 +0000279 UUID kernel_uuid = m_comm.GetUUID();
280 addr_t kernel_load_addr = m_comm.GetLoadAddress();
Greg Clayton3a29bdb2011-07-17 20:36:25 +0000281
Kate Stoneb9c1b512016-09-06 20:57:50 +0000282 if (m_comm.RemoteIsEFI()) {
283 // Select an invalid plugin name for the dynamic loader so one
Adrian Prantl05097242018-04-30 16:49:04 +0000284 // doesn't get used since EFI does its own manual loading via
285 // python scripting
Kate Stoneb9c1b512016-09-06 20:57:50 +0000286 static ConstString g_none_dynamic_loader("none");
287 m_dyld_plugin_name = g_none_dynamic_loader;
Greg Claytona3706882015-10-28 23:26:59 +0000288
Kate Stoneb9c1b512016-09-06 20:57:50 +0000289 if (kernel_uuid.IsValid()) {
Adrian Prantl05097242018-04-30 16:49:04 +0000290 // If EFI passed in a UUID= try to lookup UUID The slide will not
291 // be provided. But the UUID lookup will be used to launch EFI
292 // debug scripts from the dSYM, that can load all of the symbols.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000293 ModuleSpec module_spec;
294 module_spec.GetUUID() = kernel_uuid;
295 module_spec.GetArchitecture() = target.GetArchitecture();
Jason Molenda4bd4e7e2012-09-29 04:02:01 +0000296
Kate Stoneb9c1b512016-09-06 20:57:50 +0000297 // Lookup UUID locally, before attempting dsymForUUID like action
298 module_spec.GetSymbolFileSpec() =
299 Symbols::LocateExecutableSymbolFile(module_spec);
300 if (module_spec.GetSymbolFileSpec()) {
301 ModuleSpec executable_module_spec =
302 Symbols::LocateExecutableObjectFile(module_spec);
303 if (executable_module_spec.GetFileSpec().Exists()) {
304 module_spec.GetFileSpec() =
305 executable_module_spec.GetFileSpec();
Greg Clayton3a29bdb2011-07-17 20:36:25 +0000306 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000307 }
308 if (!module_spec.GetSymbolFileSpec() ||
309 !module_spec.GetSymbolFileSpec())
310 Symbols::DownloadObjectAndSymbolFile(module_spec, true);
Greg Clayton3a29bdb2011-07-17 20:36:25 +0000311
Kate Stoneb9c1b512016-09-06 20:57:50 +0000312 if (module_spec.GetFileSpec().Exists()) {
313 ModuleSP module_sp(new Module(module_spec));
314 if (module_sp.get() && module_sp->GetObjectFile()) {
315 // Get the current target executable
316 ModuleSP exe_module_sp(target.GetExecutableModule());
317
318 // Make sure you don't already have the right module loaded
319 // and they will be uniqued
320 if (exe_module_sp.get() != module_sp.get())
Jonas Devliegheref9a07e92018-09-20 09:09:05 +0000321 target.SetExecutableModule(module_sp, eLoadDependentsNo);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000322 }
323 }
324 }
325 } else if (m_comm.RemoteIsDarwinKernel()) {
326 m_dyld_plugin_name =
327 DynamicLoaderDarwinKernel::GetPluginNameStatic();
328 if (kernel_load_addr != LLDB_INVALID_ADDRESS) {
329 m_kernel_load_addr = kernel_load_addr;
330 }
331 }
332
333 // Set the thread ID
334 UpdateThreadListIfNeeded();
335 SetID(1);
336 GetThreadList();
337 SetPrivateState(eStateStopped);
338 StreamSP async_strm_sp(target.GetDebugger().GetAsyncOutputStream());
339 if (async_strm_sp) {
340 const char *cstr;
341 if ((cstr = m_comm.GetKernelVersion()) != NULL) {
342 async_strm_sp->Printf("Version: %s\n", cstr);
343 async_strm_sp->Flush();
344 }
345 // if ((cstr = m_comm.GetImagePath ()) != NULL)
346 // {
347 // async_strm_sp->Printf ("Image Path:
348 // %s\n", cstr);
349 // async_strm_sp->Flush();
350 // }
351 }
352 } else {
353 error.SetErrorString("KDP_REATTACH failed");
354 }
355 } else {
356 error.SetErrorString("KDP_REATTACH failed");
357 }
358 } else {
359 error.SetErrorString("invalid reply port from UDP connection");
360 }
361 } else {
362 if (error.Success())
Greg Clayton3ce7e992016-12-07 23:51:49 +0000363 error.SetErrorStringWithFormat("failed to connect to '%s'",
364 remote_url.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000365 }
366 if (error.Fail())
367 m_comm.Disconnect();
368
369 return error;
Greg Claytonf9765ac2011-07-15 03:27:12 +0000370}
371
372//----------------------------------------------------------------------
373// Process Control
374//----------------------------------------------------------------------
Zachary Turner97206d52017-05-12 04:51:55 +0000375Status ProcessKDP::DoLaunch(Module *exe_module,
376 ProcessLaunchInfo &launch_info) {
377 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000378 error.SetErrorString("launching not supported in kdp-remote plug-in");
379 return error;
Greg Claytonf9765ac2011-07-15 03:27:12 +0000380}
381
Zachary Turner97206d52017-05-12 04:51:55 +0000382Status
383ProcessKDP::DoAttachToProcessWithID(lldb::pid_t attach_pid,
384 const ProcessAttachInfo &attach_info) {
385 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000386 error.SetErrorString(
Bruce Mitchener4ebdee02018-05-29 09:10:46 +0000387 "attach to process by ID is not supported in kdp remote debugging");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000388 return error;
Han Ming Ong84647042012-02-25 01:07:38 +0000389}
390
Zachary Turner97206d52017-05-12 04:51:55 +0000391Status
392ProcessKDP::DoAttachToProcessWithName(const char *process_name,
393 const ProcessAttachInfo &attach_info) {
394 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000395 error.SetErrorString(
Bruce Mitchener4ebdee02018-05-29 09:10:46 +0000396 "attach to process by name is not supported in kdp remote debugging");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000397 return error;
Greg Claytonf9765ac2011-07-15 03:27:12 +0000398}
399
Kate Stoneb9c1b512016-09-06 20:57:50 +0000400void ProcessKDP::DidAttach(ArchSpec &process_arch) {
401 Process::DidAttach(process_arch);
Greg Claytonf9765ac2011-07-15 03:27:12 +0000402
Kate Stoneb9c1b512016-09-06 20:57:50 +0000403 Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
404 if (log)
405 log->Printf("ProcessKDP::DidAttach()");
406 if (GetID() != LLDB_INVALID_PROCESS_ID) {
407 GetHostArchitecture(process_arch);
408 }
409}
410
411addr_t ProcessKDP::GetImageInfoAddress() { return m_kernel_load_addr; }
412
413lldb_private::DynamicLoader *ProcessKDP::GetDynamicLoader() {
414 if (m_dyld_ap.get() == NULL)
415 m_dyld_ap.reset(DynamicLoader::FindPlugin(
416 this,
417 m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString()));
418 return m_dyld_ap.get();
419}
420
Zachary Turner97206d52017-05-12 04:51:55 +0000421Status ProcessKDP::WillResume() { return Status(); }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000422
Zachary Turner97206d52017-05-12 04:51:55 +0000423Status ProcessKDP::DoResume() {
424 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000425 Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
426 // Only start the async thread if we try to do any process control
427 if (!m_async_thread.IsJoinable())
428 StartAsyncThread();
429
430 bool resume = false;
431
432 // With KDP there is only one thread we can tell what to do
433 ThreadSP kernel_thread_sp(m_thread_list.FindThreadByProtocolID(g_kernel_tid));
434
435 if (kernel_thread_sp) {
436 const StateType thread_resume_state =
437 kernel_thread_sp->GetTemporaryResumeState();
438
Greg Claytonf9765ac2011-07-15 03:27:12 +0000439 if (log)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000440 log->Printf("ProcessKDP::DoResume() thread_resume_state = %s",
441 StateAsCString(thread_resume_state));
442 switch (thread_resume_state) {
443 case eStateSuspended:
Adrian Prantl05097242018-04-30 16:49:04 +0000444 // Nothing to do here when a thread will stay suspended we just leave the
445 // CPU mask bit set to zero for the thread
Kate Stoneb9c1b512016-09-06 20:57:50 +0000446 if (log)
447 log->Printf("ProcessKDP::DoResume() = suspended???");
448 break;
Greg Claytonf9765ac2011-07-15 03:27:12 +0000449
Kate Stoneb9c1b512016-09-06 20:57:50 +0000450 case eStateStepping: {
451 lldb::RegisterContextSP reg_ctx_sp(
452 kernel_thread_sp->GetRegisterContext());
Jason Molenda5e8534e2012-10-03 01:29:34 +0000453
Kate Stoneb9c1b512016-09-06 20:57:50 +0000454 if (reg_ctx_sp) {
Greg Clayton6e0ff1a2013-05-09 01:55:29 +0000455 if (log)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000456 log->Printf(
457 "ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (true);");
458 reg_ctx_sp->HardwareSingleStep(true);
459 resume = true;
460 } else {
461 error.SetErrorStringWithFormat(
462 "KDP thread 0x%llx has no register context",
463 kernel_thread_sp->GetID());
464 }
465 } break;
Greg Clayton1afa68e2013-04-02 20:32:37 +0000466
Kate Stoneb9c1b512016-09-06 20:57:50 +0000467 case eStateRunning: {
468 lldb::RegisterContextSP reg_ctx_sp(
469 kernel_thread_sp->GetRegisterContext());
Greg Clayton97d5cf02012-09-25 02:40:06 +0000470
Kate Stoneb9c1b512016-09-06 20:57:50 +0000471 if (reg_ctx_sp) {
Greg Clayton97d5cf02012-09-25 02:40:06 +0000472 if (log)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000473 log->Printf("ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep "
474 "(false);");
475 reg_ctx_sp->HardwareSingleStep(false);
476 resume = true;
477 } else {
478 error.SetErrorStringWithFormat(
479 "KDP thread 0x%llx has no register context",
480 kernel_thread_sp->GetID());
481 }
482 } break;
483
484 default:
485 // The only valid thread resume states are listed above
David Blaikiea322f362017-01-06 00:38:06 +0000486 llvm_unreachable("invalid thread resume state");
Greg Clayton7925fbb2012-09-21 16:31:20 +0000487 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000488 }
Greg Claytonf9765ac2011-07-15 03:27:12 +0000489
Kate Stoneb9c1b512016-09-06 20:57:50 +0000490 if (resume) {
Greg Claytonf9765ac2011-07-15 03:27:12 +0000491 if (log)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000492 log->Printf("ProcessKDP::DoResume () sending resume");
493
494 if (m_comm.SendRequestResume()) {
495 m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue);
496 SetPrivateState(eStateRunning);
497 } else
498 error.SetErrorString("KDP resume failed");
499 } else {
500 error.SetErrorString("kernel thread is suspended");
501 }
502
503 return error;
Greg Claytonf9765ac2011-07-15 03:27:12 +0000504}
505
Kate Stoneb9c1b512016-09-06 20:57:50 +0000506lldb::ThreadSP ProcessKDP::GetKernelThread() {
507 // KDP only tells us about one thread/core. Any other threads will usually
508 // be the ones that are read from memory by the OS plug-ins.
509
510 ThreadSP thread_sp(m_kernel_thread_wp.lock());
511 if (!thread_sp) {
512 thread_sp.reset(new ThreadKDP(*this, g_kernel_tid));
513 m_kernel_thread_wp = thread_sp;
514 }
515 return thread_sp;
516}
517
518bool ProcessKDP::UpdateThreadList(ThreadList &old_thread_list,
519 ThreadList &new_thread_list) {
520 // locker will keep a mutex locked until it goes out of scope
521 Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_THREAD));
Pavel Labath250858a2017-02-06 21:46:22 +0000522 LLDB_LOGV(log, "pid = {0}", GetID());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000523
524 // Even though there is a CPU mask, it doesn't mean we can see each CPU
525 // individually, there is really only one. Lets call this thread 1.
526 ThreadSP thread_sp(
527 old_thread_list.FindThreadByProtocolID(g_kernel_tid, false));
528 if (!thread_sp)
529 thread_sp = GetKernelThread();
530 new_thread_list.AddThread(thread_sp);
531
532 return new_thread_list.GetSize(false) > 0;
533}
534
535void ProcessKDP::RefreshStateAfterStop() {
Adrian Prantl05097242018-04-30 16:49:04 +0000536 // Let all threads recover from stopping and do any clean up based on the
537 // previous thread state (if any).
Kate Stoneb9c1b512016-09-06 20:57:50 +0000538 m_thread_list.RefreshStateAfterStop();
539}
540
Zachary Turner97206d52017-05-12 04:51:55 +0000541Status ProcessKDP::DoHalt(bool &caused_stop) {
542 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000543
544 if (m_comm.IsRunning()) {
545 if (m_destroy_in_process) {
Bruce Mitchener4ebdee02018-05-29 09:10:46 +0000546 // If we are attempting to destroy, we need to not return an error to Halt
Adrian Prantl05097242018-04-30 16:49:04 +0000547 // or DoDestroy won't get called. We are also currently running, so send
548 // a process stopped event
Kate Stoneb9c1b512016-09-06 20:57:50 +0000549 SetPrivateState(eStateStopped);
550 } else {
551 error.SetErrorString("KDP cannot interrupt a running kernel");
552 }
553 }
554 return error;
555}
556
Zachary Turner97206d52017-05-12 04:51:55 +0000557Status ProcessKDP::DoDetach(bool keep_stopped) {
558 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000559 Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
560 if (log)
561 log->Printf("ProcessKDP::DoDetach(keep_stopped = %i)", keep_stopped);
562
563 if (m_comm.IsRunning()) {
Adrian Prantl05097242018-04-30 16:49:04 +0000564 // We are running and we can't interrupt a running kernel, so we need to
565 // just close the connection to the kernel and hope for the best
Kate Stoneb9c1b512016-09-06 20:57:50 +0000566 } else {
567 // If we are going to keep the target stopped, then don't send the
568 // disconnect message.
569 if (!keep_stopped && m_comm.IsConnected()) {
570 const bool success = m_comm.SendRequestDisconnect();
571 if (log) {
572 if (success)
573 log->PutCString(
574 "ProcessKDP::DoDetach() detach packet sent successfully");
575 else
576 log->PutCString(
577 "ProcessKDP::DoDetach() connection channel shutdown failed");
578 }
579 m_comm.Disconnect();
580 }
581 }
582 StopAsyncThread();
583 m_comm.Clear();
584
585 SetPrivateState(eStateDetached);
586 ResumePrivateStateThread();
587
588 // KillDebugserverProcess ();
589 return error;
590}
591
Zachary Turner97206d52017-05-12 04:51:55 +0000592Status ProcessKDP::DoDestroy() {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000593 // For KDP there really is no difference between destroy and detach
594 bool keep_stopped = false;
595 return DoDetach(keep_stopped);
Greg Claytonf9765ac2011-07-15 03:27:12 +0000596}
597
598//------------------------------------------------------------------
599// Process Queries
600//------------------------------------------------------------------
601
Kate Stoneb9c1b512016-09-06 20:57:50 +0000602bool ProcessKDP::IsAlive() {
603 return m_comm.IsConnected() && Process::IsAlive();
Greg Claytonf9765ac2011-07-15 03:27:12 +0000604}
605
606//------------------------------------------------------------------
607// Process Memory
608//------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000609size_t ProcessKDP::DoReadMemory(addr_t addr, void *buf, size_t size,
Zachary Turner97206d52017-05-12 04:51:55 +0000610 Status &error) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000611 uint8_t *data_buffer = (uint8_t *)buf;
612 if (m_comm.IsConnected()) {
613 const size_t max_read_size = 512;
614 size_t total_bytes_read = 0;
Jason Molenda8eb32812014-05-21 23:44:02 +0000615
Kate Stoneb9c1b512016-09-06 20:57:50 +0000616 // Read the requested amount of memory in 512 byte chunks
617 while (total_bytes_read < size) {
618 size_t bytes_to_read_this_request = size - total_bytes_read;
619 if (bytes_to_read_this_request > max_read_size) {
620 bytes_to_read_this_request = max_read_size;
621 }
622 size_t bytes_read = m_comm.SendRequestReadMemory(
623 addr + total_bytes_read, data_buffer + total_bytes_read,
624 bytes_to_read_this_request, error);
625 total_bytes_read += bytes_read;
626 if (error.Fail() || bytes_read == 0) {
Jason Molenda8eb32812014-05-21 23:44:02 +0000627 return total_bytes_read;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000628 }
Jason Molenda8eb32812014-05-21 23:44:02 +0000629 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000630
631 return total_bytes_read;
632 }
633 error.SetErrorString("not connected");
634 return 0;
Greg Claytonf9765ac2011-07-15 03:27:12 +0000635}
636
Kate Stoneb9c1b512016-09-06 20:57:50 +0000637size_t ProcessKDP::DoWriteMemory(addr_t addr, const void *buf, size_t size,
Zachary Turner97206d52017-05-12 04:51:55 +0000638 Status &error) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000639 if (m_comm.IsConnected())
640 return m_comm.SendRequestWriteMemory(addr, buf, size, error);
641 error.SetErrorString("not connected");
642 return 0;
Greg Claytonf9765ac2011-07-15 03:27:12 +0000643}
644
Kate Stoneb9c1b512016-09-06 20:57:50 +0000645lldb::addr_t ProcessKDP::DoAllocateMemory(size_t size, uint32_t permissions,
Zachary Turner97206d52017-05-12 04:51:55 +0000646 Status &error) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000647 error.SetErrorString(
Bruce Mitchener4ebdee02018-05-29 09:10:46 +0000648 "memory allocation not supported in kdp remote debugging");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000649 return LLDB_INVALID_ADDRESS;
Greg Claytonf9765ac2011-07-15 03:27:12 +0000650}
651
Zachary Turner97206d52017-05-12 04:51:55 +0000652Status ProcessKDP::DoDeallocateMemory(lldb::addr_t addr) {
653 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000654 error.SetErrorString(
Bruce Mitchener4ebdee02018-05-29 09:10:46 +0000655 "memory deallocation not supported in kdp remote debugging");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000656 return error;
657}
658
Zachary Turner97206d52017-05-12 04:51:55 +0000659Status ProcessKDP::EnableBreakpointSite(BreakpointSite *bp_site) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000660 if (m_comm.LocalBreakpointsAreSupported()) {
Zachary Turner97206d52017-05-12 04:51:55 +0000661 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000662 if (!bp_site->IsEnabled()) {
663 if (m_comm.SendRequestBreakpoint(true, bp_site->GetLoadAddress())) {
664 bp_site->SetEnabled(true);
665 bp_site->SetType(BreakpointSite::eExternal);
666 } else {
667 error.SetErrorString("KDP set breakpoint failed");
668 }
669 }
Greg Claytonf9765ac2011-07-15 03:27:12 +0000670 return error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000671 }
672 return EnableSoftwareBreakpoint(bp_site);
Greg Claytonf9765ac2011-07-15 03:27:12 +0000673}
674
Zachary Turner97206d52017-05-12 04:51:55 +0000675Status ProcessKDP::DisableBreakpointSite(BreakpointSite *bp_site) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000676 if (m_comm.LocalBreakpointsAreSupported()) {
Zachary Turner97206d52017-05-12 04:51:55 +0000677 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000678 if (bp_site->IsEnabled()) {
679 BreakpointSite::Type bp_type = bp_site->GetType();
680 if (bp_type == BreakpointSite::eExternal) {
681 if (m_destroy_in_process && m_comm.IsRunning()) {
682 // We are trying to destroy our connection and we are running
683 bp_site->SetEnabled(false);
684 } else {
685 if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress()))
686 bp_site->SetEnabled(false);
687 else
688 error.SetErrorString("KDP remove breakpoint failed");
Greg Clayton5b882162011-07-21 01:12:01 +0000689 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000690 } else {
691 error = DisableSoftwareBreakpoint(bp_site);
692 }
Greg Clayton07e66e32011-07-20 03:41:06 +0000693 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000694 return error;
695 }
696 return DisableSoftwareBreakpoint(bp_site);
Greg Claytonf9765ac2011-07-15 03:27:12 +0000697}
698
Zachary Turner97206d52017-05-12 04:51:55 +0000699Status ProcessKDP::EnableWatchpoint(Watchpoint *wp, bool notify) {
700 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000701 error.SetErrorString(
Bruce Mitchener4ebdee02018-05-29 09:10:46 +0000702 "watchpoints are not supported in kdp remote debugging");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000703 return error;
704}
705
Zachary Turner97206d52017-05-12 04:51:55 +0000706Status ProcessKDP::DisableWatchpoint(Watchpoint *wp, bool notify) {
707 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000708 error.SetErrorString(
Bruce Mitchener4ebdee02018-05-29 09:10:46 +0000709 "watchpoints are not supported in kdp remote debugging");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000710 return error;
711}
712
713void ProcessKDP::Clear() { m_thread_list.Clear(); }
714
Zachary Turner97206d52017-05-12 04:51:55 +0000715Status ProcessKDP::DoSignal(int signo) {
716 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000717 error.SetErrorString(
Bruce Mitchener4ebdee02018-05-29 09:10:46 +0000718 "sending signals is not supported in kdp remote debugging");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000719 return error;
720}
721
722void ProcessKDP::Initialize() {
Kamil Rytarowskic5f28e22017-02-06 17:55:02 +0000723 static llvm::once_flag g_once_flag;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000724
Kamil Rytarowskic5f28e22017-02-06 17:55:02 +0000725 llvm::call_once(g_once_flag, []() {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000726 PluginManager::RegisterPlugin(GetPluginNameStatic(),
727 GetPluginDescriptionStatic(), CreateInstance,
728 DebuggerInitialize);
729
Pavel Labath7b35b782017-02-17 15:08:08 +0000730 ProcessKDPLog::Initialize();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000731 });
732}
733
734void ProcessKDP::DebuggerInitialize(lldb_private::Debugger &debugger) {
735 if (!PluginManager::GetSettingForProcessPlugin(
736 debugger, PluginProperties::GetSettingName())) {
737 const bool is_global_setting = true;
738 PluginManager::CreateSettingForProcessPlugin(
739 debugger, GetGlobalPluginProperties()->GetValueProperties(),
740 ConstString("Properties for the kdp-remote process plug-in."),
741 is_global_setting);
742 }
743}
744
745bool ProcessKDP::StartAsyncThread() {
746 Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
747
748 if (log)
749 log->Printf("ProcessKDP::StartAsyncThread ()");
750
751 if (m_async_thread.IsJoinable())
752 return true;
753
754 m_async_thread = ThreadLauncher::LaunchThread(
755 "<lldb.process.kdp-remote.async>", ProcessKDP::AsyncThread, this, NULL);
756 return m_async_thread.IsJoinable();
757}
758
759void ProcessKDP::StopAsyncThread() {
760 Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
761
762 if (log)
763 log->Printf("ProcessKDP::StopAsyncThread ()");
764
765 m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit);
766
767 // Stop the stdio thread
768 if (m_async_thread.IsJoinable())
769 m_async_thread.Join(nullptr);
770}
771
772void *ProcessKDP::AsyncThread(void *arg) {
773 ProcessKDP *process = (ProcessKDP *)arg;
774
775 const lldb::pid_t pid = process->GetID();
776
777 Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
778 if (log)
779 log->Printf("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64
780 ") thread starting...",
781 arg, pid);
782
783 ListenerSP listener_sp(Listener::MakeListener("ProcessKDP::AsyncThread"));
784 EventSP event_sp;
785 const uint32_t desired_event_mask =
786 eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit;
787
788 if (listener_sp->StartListeningForEvents(&process->m_async_broadcaster,
789 desired_event_mask) ==
790 desired_event_mask) {
791 bool done = false;
792 while (!done) {
793 if (log)
794 log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64
795 ") listener.WaitForEvent (NULL, event_sp)...",
796 pid);
Pavel Labathfafff0c2016-11-30 11:09:47 +0000797 if (listener_sp->GetEvent(event_sp, llvm::None)) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000798 uint32_t event_type = event_sp->GetType();
799 if (log)
800 log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64
801 ") Got an event of type: %d...",
802 pid, event_type);
803
804 // When we are running, poll for 1 second to try and get an exception
805 // to indicate the process has stopped. If we don't get one, check to
806 // make sure no one asked us to exit
807 bool is_running = false;
808 DataExtractor exc_reply_packet;
809 do {
810 switch (event_type) {
811 case eBroadcastBitAsyncContinue: {
812 is_running = true;
813 if (process->m_comm.WaitForPacketWithTimeoutMicroSeconds(
814 exc_reply_packet, 1 * USEC_PER_SEC)) {
815 ThreadSP thread_sp(process->GetKernelThread());
816 if (thread_sp) {
817 lldb::RegisterContextSP reg_ctx_sp(
818 thread_sp->GetRegisterContext());
819 if (reg_ctx_sp)
820 reg_ctx_sp->InvalidateAllRegisters();
821 static_cast<ThreadKDP *>(thread_sp.get())
822 ->SetStopInfoFrom_KDP_EXCEPTION(exc_reply_packet);
823 }
824
825 // TODO: parse the stop reply packet
826 is_running = false;
827 process->SetPrivateState(eStateStopped);
828 } else {
829 // Check to see if we are supposed to exit. There is no way to
830 // interrupt a running kernel, so all we can do is wait for an
831 // exception or detach...
Pavel Labathfafff0c2016-11-30 11:09:47 +0000832 if (listener_sp->GetEvent(event_sp,
833 std::chrono::microseconds(0))) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000834 // We got an event, go through the loop again
835 event_type = event_sp->GetType();
836 }
Greg Clayton5b882162011-07-21 01:12:01 +0000837 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000838 } break;
Greg Claytonf9765ac2011-07-15 03:27:12 +0000839
Kate Stoneb9c1b512016-09-06 20:57:50 +0000840 case eBroadcastBitAsyncThreadShouldExit:
Greg Claytonf9765ac2011-07-15 03:27:12 +0000841 if (log)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000842 log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64
843 ") got eBroadcastBitAsyncThreadShouldExit...",
844 pid);
845 done = true;
846 is_running = false;
847 break;
Greg Clayton97d5cf02012-09-25 02:40:06 +0000848
Kate Stoneb9c1b512016-09-06 20:57:50 +0000849 default:
850 if (log)
851 log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64
852 ") got unknown event 0x%8.8x",
853 pid, event_type);
854 done = true;
855 is_running = false;
856 break;
857 }
858 } while (is_running);
859 } else {
860 if (log)
861 log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64
862 ") listener.WaitForEvent (NULL, event_sp) => false",
863 pid);
864 done = true;
865 }
Greg Claytonf9765ac2011-07-15 03:27:12 +0000866 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000867 }
Zachary Turner39de3112014-09-09 20:54:56 +0000868
Kate Stoneb9c1b512016-09-06 20:57:50 +0000869 if (log)
870 log->Printf("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64
871 ") thread exiting...",
872 arg, pid);
873
874 process->m_async_thread.Reset();
875 return NULL;
Greg Claytonf9765ac2011-07-15 03:27:12 +0000876}
877
Kate Stoneb9c1b512016-09-06 20:57:50 +0000878class CommandObjectProcessKDPPacketSend : public CommandObjectParsed {
Greg Clayton1d19a2f2012-10-19 22:22:57 +0000879private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000880 OptionGroupOptions m_option_group;
881 OptionGroupUInt64 m_command_byte;
882 OptionGroupString m_packet_data;
883
884 virtual Options *GetOptions() { return &m_option_group; }
Greg Clayton1d19a2f2012-10-19 22:22:57 +0000885
886public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000887 CommandObjectProcessKDPPacketSend(CommandInterpreter &interpreter)
888 : CommandObjectParsed(interpreter, "process plugin packet send",
889 "Send a custom packet through the KDP protocol by "
890 "specifying the command byte and the packet "
891 "payload data. A packet will be sent with a "
892 "correct header and payload, and the raw result "
893 "bytes will be displayed as a string value. ",
894 NULL),
Todd Fialae1cfbc72016-08-11 23:51:28 +0000895 m_option_group(),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000896 m_command_byte(LLDB_OPT_SET_1, true, "command", 'c', 0, eArgTypeNone,
897 "Specify the command byte to use when sending the KDP "
898 "request packet.",
899 0),
900 m_packet_data(LLDB_OPT_SET_1, false, "payload", 'p', 0, eArgTypeNone,
901 "Specify packet payload bytes as a hex ASCII string with "
902 "no spaces or hex prefixes.",
903 NULL) {
904 m_option_group.Append(&m_command_byte, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
905 m_option_group.Append(&m_packet_data, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
906 m_option_group.Finalize();
907 }
908
909 ~CommandObjectProcessKDPPacketSend() {}
910
911 bool DoExecute(Args &command, CommandReturnObject &result) {
912 const size_t argc = command.GetArgumentCount();
913 if (argc == 0) {
914 if (!m_command_byte.GetOptionValue().OptionWasSet()) {
915 result.AppendError(
916 "the --command option must be set to a valid command byte");
917 result.SetStatus(eReturnStatusFailed);
918 } else {
919 const uint64_t command_byte =
920 m_command_byte.GetOptionValue().GetUInt64Value(0);
921 if (command_byte > 0 && command_byte <= UINT8_MAX) {
922 ProcessKDP *process =
923 (ProcessKDP *)m_interpreter.GetExecutionContext().GetProcessPtr();
924 if (process) {
925 const StateType state = process->GetState();
926
927 if (StateIsStoppedState(state, true)) {
928 std::vector<uint8_t> payload_bytes;
929 const char *ascii_hex_bytes_cstr =
930 m_packet_data.GetOptionValue().GetCurrentValue();
931 if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0]) {
932 StringExtractor extractor(ascii_hex_bytes_cstr);
933 const size_t ascii_hex_bytes_cstr_len =
934 extractor.GetStringRef().size();
935 if (ascii_hex_bytes_cstr_len & 1) {
936 result.AppendErrorWithFormat("payload data must contain an "
937 "even number of ASCII hex "
938 "characters: '%s'",
939 ascii_hex_bytes_cstr);
940 result.SetStatus(eReturnStatusFailed);
941 return false;
Greg Clayton1d19a2f2012-10-19 22:22:57 +0000942 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000943 payload_bytes.resize(ascii_hex_bytes_cstr_len / 2);
944 if (extractor.GetHexBytes(payload_bytes, '\xdd') !=
945 payload_bytes.size()) {
946 result.AppendErrorWithFormat("payload data must only contain "
947 "ASCII hex characters (no "
948 "spaces or hex prefixes): '%s'",
949 ascii_hex_bytes_cstr);
950 result.SetStatus(eReturnStatusFailed);
951 return false;
952 }
953 }
Zachary Turner97206d52017-05-12 04:51:55 +0000954 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000955 DataExtractor reply;
956 process->GetCommunication().SendRawRequest(
957 command_byte,
958 payload_bytes.empty() ? NULL : payload_bytes.data(),
959 payload_bytes.size(), reply, error);
960
961 if (error.Success()) {
962 // Copy the binary bytes into a hex ASCII string for the result
963 StreamString packet;
964 packet.PutBytesAsRawHex8(
965 reply.GetDataStart(), reply.GetByteSize(),
966 endian::InlHostByteOrder(), endian::InlHostByteOrder());
Zachary Turnerc1564272016-11-16 21:15:24 +0000967 result.AppendMessage(packet.GetString());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000968 result.SetStatus(eReturnStatusSuccessFinishResult);
969 return true;
970 } else {
971 const char *error_cstr = error.AsCString();
972 if (error_cstr && error_cstr[0])
973 result.AppendError(error_cstr);
Greg Clayton1d19a2f2012-10-19 22:22:57 +0000974 else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000975 result.AppendErrorWithFormat("unknown error 0x%8.8x",
976 error.GetError());
977 result.SetStatus(eReturnStatusFailed);
978 return false;
979 }
980 } else {
981 result.AppendErrorWithFormat("process must be stopped in order "
982 "to send KDP packets, state is %s",
983 StateAsCString(state));
984 result.SetStatus(eReturnStatusFailed);
Greg Clayton1d19a2f2012-10-19 22:22:57 +0000985 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000986 } else {
987 result.AppendError("invalid process");
988 result.SetStatus(eReturnStatusFailed);
989 }
990 } else {
991 result.AppendErrorWithFormat("invalid command byte 0x%" PRIx64
992 ", valid values are 1 - 255",
993 command_byte);
994 result.SetStatus(eReturnStatusFailed);
Greg Clayton1d19a2f2012-10-19 22:22:57 +0000995 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000996 }
997 } else {
998 result.AppendErrorWithFormat("'%s' takes no arguments, only options.",
999 m_cmd_name.c_str());
1000 result.SetStatus(eReturnStatusFailed);
Greg Clayton1d19a2f2012-10-19 22:22:57 +00001001 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001002 return false;
1003 }
Greg Clayton1d19a2f2012-10-19 22:22:57 +00001004};
1005
Kate Stoneb9c1b512016-09-06 20:57:50 +00001006class CommandObjectProcessKDPPacket : public CommandObjectMultiword {
Greg Clayton1d19a2f2012-10-19 22:22:57 +00001007private:
Greg Clayton1d19a2f2012-10-19 22:22:57 +00001008public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001009 CommandObjectProcessKDPPacket(CommandInterpreter &interpreter)
1010 : CommandObjectMultiword(interpreter, "process plugin packet",
1011 "Commands that deal with KDP remote packets.",
1012 NULL) {
1013 LoadSubCommand(
1014 "send",
1015 CommandObjectSP(new CommandObjectProcessKDPPacketSend(interpreter)));
1016 }
1017
1018 ~CommandObjectProcessKDPPacket() {}
Greg Clayton1d19a2f2012-10-19 22:22:57 +00001019};
1020
Kate Stoneb9c1b512016-09-06 20:57:50 +00001021class CommandObjectMultiwordProcessKDP : public CommandObjectMultiword {
Greg Clayton1d19a2f2012-10-19 22:22:57 +00001022public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001023 CommandObjectMultiwordProcessKDP(CommandInterpreter &interpreter)
1024 : CommandObjectMultiword(
1025 interpreter, "process plugin",
1026 "Commands for operating on a ProcessKDP process.",
1027 "process plugin <subcommand> [<subcommand-options>]") {
1028 LoadSubCommand("packet", CommandObjectSP(new CommandObjectProcessKDPPacket(
1029 interpreter)));
1030 }
1031
1032 ~CommandObjectMultiwordProcessKDP() {}
Greg Clayton1d19a2f2012-10-19 22:22:57 +00001033};
1034
Kate Stoneb9c1b512016-09-06 20:57:50 +00001035CommandObject *ProcessKDP::GetPluginCommandObject() {
1036 if (!m_command_sp)
1037 m_command_sp.reset(new CommandObjectMultiwordProcessKDP(
1038 GetTarget().GetDebugger().GetCommandInterpreter()));
1039 return m_command_sp.get();
Greg Clayton1d19a2f2012-10-19 22:22:57 +00001040}