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