159ec512cSGreg Clayton //===-- ProcessKDP.cpp ------------------------------------------*- C++ -*-===// 2f9765acdSGreg Clayton // 3f9765acdSGreg Clayton // The LLVM Compiler Infrastructure 4f9765acdSGreg Clayton // 5f9765acdSGreg Clayton // This file is distributed under the University of Illinois Open Source 6f9765acdSGreg Clayton // License. See LICENSE.TXT for details. 7f9765acdSGreg Clayton // 8f9765acdSGreg Clayton //===----------------------------------------------------------------------===// 9f9765acdSGreg Clayton 10f9765acdSGreg Clayton // C Includes 11f9765acdSGreg Clayton #include <errno.h> 12f9765acdSGreg Clayton #include <stdlib.h> 13f9765acdSGreg Clayton 14f9765acdSGreg Clayton // C++ Includes 153f69fa6fSBenjamin Kramer #include <mutex> 163f69fa6fSBenjamin Kramer 17f9765acdSGreg Clayton // Other libraries and framework includes 1807e66e3eSGreg Clayton #include "lldb/Core/Debugger.h" 191f746071SGreg Clayton #include "lldb/Core/Module.h" 204bd4e7e3SJason Molenda #include "lldb/Core/ModuleSpec.h" 21b9c1b51eSKate Stone #include "lldb/Core/PluginManager.h" 2293a66fc1SZachary Turner #include "lldb/Host/ConnectionFileDescriptor.h" 23f9765acdSGreg Clayton #include "lldb/Host/Host.h" 244bd4e7e3SJason Molenda #include "lldb/Host/Symbols.h" 2539de3110SZachary Turner #include "lldb/Host/ThreadLauncher.h" 26e98628ceSOleksiy Vyalov #include "lldb/Host/common/TCPSocket.h" 271d19a2f2SGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 281d19a2f2SGreg Clayton #include "lldb/Interpreter/CommandObject.h" 291d19a2f2SGreg Clayton #include "lldb/Interpreter/CommandObjectMultiword.h" 301d19a2f2SGreg Clayton #include "lldb/Interpreter/CommandReturnObject.h" 311d19a2f2SGreg Clayton #include "lldb/Interpreter/OptionGroupString.h" 321d19a2f2SGreg Clayton #include "lldb/Interpreter/OptionGroupUInt64.h" 3341204d09SIlia K #include "lldb/Interpreter/OptionValueProperties.h" 341f746071SGreg Clayton #include "lldb/Symbol/ObjectFile.h" 357925fbbaSGreg Clayton #include "lldb/Target/RegisterContext.h" 3657508026SGreg Clayton #include "lldb/Target/Target.h" 37a63d08c9SGreg Clayton #include "lldb/Target/Thread.h" 38d821c997SPavel Labath #include "lldb/Utility/State.h" 3945788152SBruce Mitchener #include "lldb/Utility/StringExtractor.h" 40d821c997SPavel Labath #include "lldb/Utility/UUID.h" 41f9765acdSGreg Clayton 42c5f28e2aSKamil Rytarowski #include "llvm/Support/Threading.h" 43c5f28e2aSKamil Rytarowski 44510938e5SCharles Davis #define USEC_PER_SEC 1000000 45510938e5SCharles Davis 46f9765acdSGreg Clayton // Project includes 47b9c1b51eSKate Stone #include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h" 48b9c1b51eSKate Stone #include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h" 49f9765acdSGreg Clayton #include "ProcessKDP.h" 50f9765acdSGreg Clayton #include "ProcessKDPLog.h" 51a63d08c9SGreg Clayton #include "ThreadKDP.h" 52f9765acdSGreg Clayton 53f9765acdSGreg Clayton using namespace lldb; 54f9765acdSGreg Clayton using namespace lldb_private; 55f9765acdSGreg Clayton 567f98240dSGreg Clayton namespace { 577f98240dSGreg Clayton 58*e40db05bSTatyana Krasnukha static constexpr PropertyDefinition g_properties[] = { 59f929e2b0STatyana Krasnukha {"packet-timeout", OptionValue::eTypeUInt64, true, 5, NULL, {}, 60*e40db05bSTatyana Krasnukha "Specify the default packet timeout in seconds."}}; 617f98240dSGreg Clayton 62b9c1b51eSKate Stone enum { ePropertyPacketTimeout }; 637f98240dSGreg Clayton 64b9c1b51eSKate Stone class PluginProperties : public Properties { 657f98240dSGreg Clayton public: 66b9c1b51eSKate Stone static ConstString GetSettingName() { 677f98240dSGreg Clayton return ProcessKDP::GetPluginNameStatic(); 687f98240dSGreg Clayton } 697f98240dSGreg Clayton 70b9c1b51eSKate Stone PluginProperties() : Properties() { 717f98240dSGreg Clayton m_collection_sp.reset(new OptionValueProperties(GetSettingName())); 727f98240dSGreg Clayton m_collection_sp->Initialize(g_properties); 737f98240dSGreg Clayton } 747f98240dSGreg Clayton 75b9c1b51eSKate Stone virtual ~PluginProperties() {} 767f98240dSGreg Clayton 77b9c1b51eSKate Stone uint64_t GetPacketTimeout() { 787f98240dSGreg Clayton const uint32_t idx = ePropertyPacketTimeout; 79b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsUInt64( 80b9c1b51eSKate Stone NULL, idx, g_properties[idx].default_uint_value); 817f98240dSGreg Clayton } 827f98240dSGreg Clayton }; 837f98240dSGreg Clayton 847f98240dSGreg Clayton typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP; 857f98240dSGreg Clayton 86b9c1b51eSKate Stone static const ProcessKDPPropertiesSP &GetGlobalPluginProperties() { 877f98240dSGreg Clayton static ProcessKDPPropertiesSP g_settings_sp; 887f98240dSGreg Clayton if (!g_settings_sp) 897f98240dSGreg Clayton g_settings_sp.reset(new PluginProperties()); 907f98240dSGreg Clayton return g_settings_sp; 917f98240dSGreg Clayton } 927f98240dSGreg Clayton 937f98240dSGreg Clayton } // anonymous namespace end 947f98240dSGreg Clayton 95ba4e61d3SAndrew Kaylor static const lldb::tid_t g_kernel_tid = 1; 96ba4e61d3SAndrew Kaylor 97b9c1b51eSKate Stone ConstString ProcessKDP::GetPluginNameStatic() { 9857abc5d6SGreg Clayton static ConstString g_name("kdp-remote"); 9957abc5d6SGreg Clayton return g_name; 100f9765acdSGreg Clayton } 101f9765acdSGreg Clayton 102b9c1b51eSKate Stone const char *ProcessKDP::GetPluginDescriptionStatic() { 103b9c1b51eSKate Stone return "KDP Remote protocol based debugging plug-in for darwin kernel " 104b9c1b51eSKate Stone "debugging."; 105f9765acdSGreg Clayton } 106f9765acdSGreg Clayton 107b9c1b51eSKate Stone void ProcessKDP::Terminate() { 108f9765acdSGreg Clayton PluginManager::UnregisterPlugin(ProcessKDP::CreateInstance); 109f9765acdSGreg Clayton } 110f9765acdSGreg Clayton 111b9c1b51eSKate Stone lldb::ProcessSP ProcessKDP::CreateInstance(TargetSP target_sp, 112583bbb1dSJim Ingham ListenerSP listener_sp, 113b9c1b51eSKate Stone const FileSpec *crash_file_path) { 114c3776bf2SGreg Clayton lldb::ProcessSP process_sp; 115c3776bf2SGreg Clayton if (crash_file_path == NULL) 116583bbb1dSJim Ingham process_sp.reset(new ProcessKDP(target_sp, listener_sp)); 117c3776bf2SGreg Clayton return process_sp; 118f9765acdSGreg Clayton } 119f9765acdSGreg Clayton 120b9c1b51eSKate Stone bool ProcessKDP::CanDebug(TargetSP target_sp, bool plugin_specified_by_name) { 121596ed24eSGreg Clayton if (plugin_specified_by_name) 122596ed24eSGreg Clayton return true; 123596ed24eSGreg Clayton 124f9765acdSGreg Clayton // For now we are just making sure the file exists for a given module 1255a3bb64fSJim Ingham Module *exe_module = target_sp->GetExecutableModulePointer(); 126b9c1b51eSKate Stone if (exe_module) { 1275a3bb64fSJim Ingham const llvm::Triple &triple_ref = target_sp->GetArchitecture().GetTriple(); 128b9c1b51eSKate Stone switch (triple_ref.getOS()) { 129b9c1b51eSKate Stone case llvm::Triple::Darwin: // Should use "macosx" for desktop and "ios" for 130b9c1b51eSKate Stone // iOS, but accept darwin just in case 13170512317SGreg Clayton case llvm::Triple::MacOSX: // For desktop targets 13270512317SGreg Clayton case llvm::Triple::IOS: // For arm targets 133a814f704SJason Molenda case llvm::Triple::TvOS: 134a814f704SJason Molenda case llvm::Triple::WatchOS: 135b9c1b51eSKate Stone if (triple_ref.getVendor() == llvm::Triple::Apple) { 136aa149cbdSGreg Clayton ObjectFile *exe_objfile = exe_module->GetObjectFile(); 137f9765acdSGreg Clayton if (exe_objfile->GetType() == ObjectFile::eTypeExecutable && 138f9765acdSGreg Clayton exe_objfile->GetStrata() == ObjectFile::eStrataKernel) 139f9765acdSGreg Clayton return true; 140f9765acdSGreg Clayton } 14170512317SGreg Clayton break; 14270512317SGreg Clayton 14370512317SGreg Clayton default: 14470512317SGreg Clayton break; 14570512317SGreg Clayton } 146f9765acdSGreg Clayton } 147596ed24eSGreg Clayton return false; 1483a29bdbeSGreg Clayton } 149f9765acdSGreg Clayton 150f9765acdSGreg Clayton //---------------------------------------------------------------------- 151f9765acdSGreg Clayton // ProcessKDP constructor 152f9765acdSGreg Clayton //---------------------------------------------------------------------- 153b9c1b51eSKate Stone ProcessKDP::ProcessKDP(TargetSP target_sp, ListenerSP listener_sp) 154b9c1b51eSKate Stone : Process(target_sp, listener_sp), 155f9765acdSGreg Clayton m_comm("lldb.process.kdp-remote.communication"), 1564bddaeb5SJim Ingham m_async_broadcaster(NULL, "lldb.process.kdp-remote.async-broadcaster"), 157b9c1b51eSKate Stone m_dyld_plugin_name(), m_kernel_load_addr(LLDB_INVALID_ADDRESS), 158b9c1b51eSKate Stone m_command_sp(), m_kernel_thread_wp() { 159b9c1b51eSKate Stone m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, 160b9c1b51eSKate Stone "async thread should exit"); 161b9c1b51eSKate Stone m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, 162b9c1b51eSKate Stone "async thread continue"); 163b9c1b51eSKate Stone const uint64_t timeout_seconds = 164b9c1b51eSKate Stone GetGlobalPluginProperties()->GetPacketTimeout(); 1657f98240dSGreg Clayton if (timeout_seconds > 0) 1665cddd608SPavel Labath m_comm.SetPacketTimeout(std::chrono::seconds(timeout_seconds)); 167f9765acdSGreg Clayton } 168f9765acdSGreg Clayton 169f9765acdSGreg Clayton //---------------------------------------------------------------------- 170f9765acdSGreg Clayton // Destructor 171f9765acdSGreg Clayton //---------------------------------------------------------------------- 172b9c1b51eSKate Stone ProcessKDP::~ProcessKDP() { 173f9765acdSGreg Clayton Clear(); 17405097246SAdrian Prantl // We need to call finalize on the process before destroying ourselves to 17505097246SAdrian Prantl // make sure all of the broadcaster cleanup goes as planned. If we destruct 17605097246SAdrian Prantl // this class, then Process::~Process() might have problems trying to fully 17705097246SAdrian Prantl // destroy the broadcaster. 178e24c4acfSGreg Clayton Finalize(); 179f9765acdSGreg Clayton } 180f9765acdSGreg Clayton 181f9765acdSGreg Clayton //---------------------------------------------------------------------- 182f9765acdSGreg Clayton // PluginInterface 183f9765acdSGreg Clayton //---------------------------------------------------------------------- 184b9c1b51eSKate Stone lldb_private::ConstString ProcessKDP::GetPluginName() { 185f9765acdSGreg Clayton return GetPluginNameStatic(); 186f9765acdSGreg Clayton } 187f9765acdSGreg Clayton 188b9c1b51eSKate Stone uint32_t ProcessKDP::GetPluginVersion() { return 1; } 189f9765acdSGreg Clayton 19097206d57SZachary Turner Status ProcessKDP::WillLaunch(Module *module) { 19197206d57SZachary Turner Status error; 192f9765acdSGreg Clayton error.SetErrorString("launching not supported in kdp-remote plug-in"); 193f9765acdSGreg Clayton return error; 194f9765acdSGreg Clayton } 195f9765acdSGreg Clayton 19697206d57SZachary Turner Status ProcessKDP::WillAttachToProcessWithID(lldb::pid_t pid) { 19797206d57SZachary Turner Status error; 198b9c1b51eSKate Stone error.SetErrorString( 199b9c1b51eSKate Stone "attaching to a by process ID not supported in kdp-remote plug-in"); 200f9765acdSGreg Clayton return error; 201f9765acdSGreg Clayton } 202f9765acdSGreg Clayton 20397206d57SZachary Turner Status ProcessKDP::WillAttachToProcessWithName(const char *process_name, 204b9c1b51eSKate Stone bool wait_for_launch) { 20597206d57SZachary Turner Status error; 206b9c1b51eSKate Stone error.SetErrorString( 207b9c1b51eSKate Stone "attaching to a by process name not supported in kdp-remote plug-in"); 208f9765acdSGreg Clayton return error; 209f9765acdSGreg Clayton } 210f9765acdSGreg Clayton 211b9c1b51eSKate Stone bool ProcessKDP::GetHostArchitecture(ArchSpec &arch) { 212a3706888SGreg Clayton uint32_t cpu = m_comm.GetCPUType(); 213b9c1b51eSKate Stone if (cpu) { 214a3706888SGreg Clayton uint32_t sub = m_comm.GetCPUSubtype(); 215a3706888SGreg Clayton arch.SetArchitecture(eArchTypeMachO, cpu, sub); 216a3706888SGreg Clayton // Leave architecture vendor as unspecified unknown 217a3706888SGreg Clayton arch.GetTriple().setVendor(llvm::Triple::UnknownVendor); 218a3706888SGreg Clayton arch.GetTriple().setVendorName(llvm::StringRef()); 219a3706888SGreg Clayton return true; 220a3706888SGreg Clayton } 221a3706888SGreg Clayton arch.Clear(); 222a3706888SGreg Clayton return false; 223a3706888SGreg Clayton } 224a3706888SGreg Clayton 22597206d57SZachary Turner Status ProcessKDP::DoConnectRemote(Stream *strm, llvm::StringRef remote_url) { 22697206d57SZachary Turner Status error; 2273a29bdbeSGreg Clayton 22805097246SAdrian Prantl // Don't let any JIT happen when doing KDP as we can't allocate memory and we 22905097246SAdrian Prantl // don't want to be mucking with threads that might already be handling 23005097246SAdrian Prantl // exceptions 2317925fbbaSGreg Clayton SetCanJIT(false); 2327925fbbaSGreg Clayton 2333ce7e996SGreg Clayton if (remote_url.empty()) { 2343ce7e996SGreg Clayton error.SetErrorStringWithFormat("empty connection URL"); 2357925fbbaSGreg Clayton return error; 2367925fbbaSGreg Clayton } 2373a29bdbeSGreg Clayton 238b9c1b51eSKate Stone std::unique_ptr<ConnectionFileDescriptor> conn_ap( 239b9c1b51eSKate Stone new ConnectionFileDescriptor()); 240b9c1b51eSKate Stone if (conn_ap.get()) { 2413a29bdbeSGreg Clayton // Only try once for now. 2423a29bdbeSGreg Clayton // TODO: check if we should be retrying? 2433a29bdbeSGreg Clayton const uint32_t max_retry_count = 1; 244b9c1b51eSKate Stone for (uint32_t retry_count = 0; retry_count < max_retry_count; 245b9c1b51eSKate Stone ++retry_count) { 2463a29bdbeSGreg Clayton if (conn_ap->Connect(remote_url, &error) == eConnectionStatusSuccess) 2473a29bdbeSGreg Clayton break; 2483a29bdbeSGreg Clayton usleep(100000); 2493a29bdbeSGreg Clayton } 2503a29bdbeSGreg Clayton } 2513a29bdbeSGreg Clayton 252b9c1b51eSKate Stone if (conn_ap->IsConnected()) { 253b9c1b51eSKate Stone const TCPSocket &socket = 254b9c1b51eSKate Stone static_cast<const TCPSocket &>(*conn_ap->GetReadObject()); 255014bb7daSVince Harron const uint16_t reply_port = socket.GetLocalPortNumber(); 2563a29bdbeSGreg Clayton 257b9c1b51eSKate Stone if (reply_port != 0) { 2583a29bdbeSGreg Clayton m_comm.SetConnection(conn_ap.release()); 2593a29bdbeSGreg Clayton 260b9c1b51eSKate Stone if (m_comm.SendRequestReattach(reply_port)) { 261b9c1b51eSKate Stone if (m_comm.SendRequestConnect(reply_port, reply_port, 262b9c1b51eSKate Stone "Greetings from LLDB...")) { 2633a29bdbeSGreg Clayton m_comm.GetVersion(); 2645a3bb64fSJim Ingham 265a3706888SGreg Clayton Target &target = GetTarget(); 266a3706888SGreg Clayton ArchSpec kernel_arch; 267a3706888SGreg Clayton // The host architecture 268a3706888SGreg Clayton GetHostArchitecture(kernel_arch); 269a3706888SGreg Clayton ArchSpec target_arch = target.GetArchitecture(); 270a3706888SGreg Clayton // Merge in any unspecified stuff into the target architecture in 271a3706888SGreg Clayton // case the target arch isn't set at all or incompletely. 272a3706888SGreg Clayton target_arch.MergeFrom(kernel_arch); 273a3706888SGreg Clayton target.SetArchitecture(target_arch); 2744bd4e7e3SJason Molenda 275b9c1b51eSKate Stone /* Get the kernel's UUID and load address via KDP_KERNELVERSION 276b9c1b51eSKate Stone * packet. */ 277840f12cfSJason Molenda /* An EFI kdp session has neither UUID nor load address. */ 2784bd4e7e3SJason Molenda 2794bd4e7e3SJason Molenda UUID kernel_uuid = m_comm.GetUUID(); 2804bd4e7e3SJason Molenda addr_t kernel_load_addr = m_comm.GetLoadAddress(); 2814bd4e7e3SJason Molenda 282b9c1b51eSKate Stone if (m_comm.RemoteIsEFI()) { 283b9c1b51eSKate Stone // Select an invalid plugin name for the dynamic loader so one 28405097246SAdrian Prantl // doesn't get used since EFI does its own manual loading via 28505097246SAdrian Prantl // python scripting 286a1bce2efSGreg Clayton static ConstString g_none_dynamic_loader("none"); 287a1bce2efSGreg Clayton m_dyld_plugin_name = g_none_dynamic_loader; 288a1bce2efSGreg Clayton 289a1bce2efSGreg Clayton if (kernel_uuid.IsValid()) { 29005097246SAdrian Prantl // If EFI passed in a UUID= try to lookup UUID The slide will not 29105097246SAdrian Prantl // be provided. But the UUID lookup will be used to launch EFI 29205097246SAdrian Prantl // debug scripts from the dSYM, that can load all of the symbols. 293a1bce2efSGreg Clayton ModuleSpec module_spec; 294a1bce2efSGreg Clayton module_spec.GetUUID() = kernel_uuid; 2955a3bb64fSJim Ingham module_spec.GetArchitecture() = target.GetArchitecture(); 296a1bce2efSGreg Clayton 297a1bce2efSGreg Clayton // Lookup UUID locally, before attempting dsymForUUID like action 298b9c1b51eSKate Stone module_spec.GetSymbolFileSpec() = 299b9c1b51eSKate Stone Symbols::LocateExecutableSymbolFile(module_spec); 300b9c1b51eSKate Stone if (module_spec.GetSymbolFileSpec()) { 301b9c1b51eSKate Stone ModuleSpec executable_module_spec = 302b9c1b51eSKate Stone Symbols::LocateExecutableObjectFile(module_spec); 303b9c1b51eSKate Stone if (executable_module_spec.GetFileSpec().Exists()) { 304b9c1b51eSKate Stone module_spec.GetFileSpec() = 305b9c1b51eSKate Stone executable_module_spec.GetFileSpec(); 3068825c5c9SJason Molenda } 3078825c5c9SJason Molenda } 308b9c1b51eSKate Stone if (!module_spec.GetSymbolFileSpec() || 309b9c1b51eSKate Stone !module_spec.GetSymbolFileSpec()) 310a1bce2efSGreg Clayton Symbols::DownloadObjectAndSymbolFile(module_spec, true); 311a1bce2efSGreg Clayton 312b9c1b51eSKate Stone if (module_spec.GetFileSpec().Exists()) { 313a3706888SGreg Clayton ModuleSP module_sp(new Module(module_spec)); 314b9c1b51eSKate Stone if (module_sp.get() && module_sp->GetObjectFile()) { 315a1bce2efSGreg Clayton // Get the current target executable 3165a3bb64fSJim Ingham ModuleSP exe_module_sp(target.GetExecutableModule()); 317a1bce2efSGreg Clayton 318b9c1b51eSKate Stone // Make sure you don't already have the right module loaded 319b9c1b51eSKate Stone // and they will be uniqued 320a1bce2efSGreg Clayton if (exe_module_sp.get() != module_sp.get()) 321f9a07e9fSJonas Devlieghere target.SetExecutableModule(module_sp, eLoadDependentsNo); 322a1bce2efSGreg Clayton } 323a1bce2efSGreg Clayton } 324a1bce2efSGreg Clayton } 325b9c1b51eSKate Stone } else if (m_comm.RemoteIsDarwinKernel()) { 326b9c1b51eSKate Stone m_dyld_plugin_name = 327b9c1b51eSKate Stone DynamicLoaderDarwinKernel::GetPluginNameStatic(); 328b9c1b51eSKate Stone if (kernel_load_addr != LLDB_INVALID_ADDRESS) { 3295e8534efSJason Molenda m_kernel_load_addr = kernel_load_addr; 330a8ea4baeSJason Molenda } 3314bd4e7e3SJason Molenda } 3324bd4e7e3SJason Molenda 33397d5cf05SGreg Clayton // Set the thread ID 33497d5cf05SGreg Clayton UpdateThreadListIfNeeded(); 335a63d08c9SGreg Clayton SetID(1); 33656d9a1b3SGreg Clayton GetThreadList(); 337a63d08c9SGreg Clayton SetPrivateState(eStateStopped); 3385a3bb64fSJim Ingham StreamSP async_strm_sp(target.GetDebugger().GetAsyncOutputStream()); 339b9c1b51eSKate Stone if (async_strm_sp) { 3405b88216dSGreg Clayton const char *cstr; 341b9c1b51eSKate Stone if ((cstr = m_comm.GetKernelVersion()) != NULL) { 3425b88216dSGreg Clayton async_strm_sp->Printf("Version: %s\n", cstr); 34307e66e3eSGreg Clayton async_strm_sp->Flush(); 34407e66e3eSGreg Clayton } 3455b88216dSGreg Clayton // if ((cstr = m_comm.GetImagePath ()) != NULL) 3465b88216dSGreg Clayton // { 347b9c1b51eSKate Stone // async_strm_sp->Printf ("Image Path: 348b9c1b51eSKate Stone // %s\n", cstr); 3495b88216dSGreg Clayton // async_strm_sp->Flush(); 3505b88216dSGreg Clayton // } 35107e66e3eSGreg Clayton } 352b9c1b51eSKate Stone } else { 35397d5cf05SGreg Clayton error.SetErrorString("KDP_REATTACH failed"); 35497d5cf05SGreg Clayton } 355b9c1b51eSKate Stone } else { 35697d5cf05SGreg Clayton error.SetErrorString("KDP_REATTACH failed"); 3573a29bdbeSGreg Clayton } 358b9c1b51eSKate Stone } else { 3593a29bdbeSGreg Clayton error.SetErrorString("invalid reply port from UDP connection"); 3603a29bdbeSGreg Clayton } 361b9c1b51eSKate Stone } else { 3623a29bdbeSGreg Clayton if (error.Success()) 3633ce7e996SGreg Clayton error.SetErrorStringWithFormat("failed to connect to '%s'", 3643ce7e996SGreg Clayton remote_url.str().c_str()); 3653a29bdbeSGreg Clayton } 3663a29bdbeSGreg Clayton if (error.Fail()) 3673a29bdbeSGreg Clayton m_comm.Disconnect(); 3683a29bdbeSGreg Clayton 369f9765acdSGreg Clayton return error; 370f9765acdSGreg Clayton } 371f9765acdSGreg Clayton 372f9765acdSGreg Clayton //---------------------------------------------------------------------- 373f9765acdSGreg Clayton // Process Control 374f9765acdSGreg Clayton //---------------------------------------------------------------------- 37597206d57SZachary Turner Status ProcessKDP::DoLaunch(Module *exe_module, 37697206d57SZachary Turner ProcessLaunchInfo &launch_info) { 37797206d57SZachary Turner Status error; 378f9765acdSGreg Clayton error.SetErrorString("launching not supported in kdp-remote plug-in"); 379f9765acdSGreg Clayton return error; 380f9765acdSGreg Clayton } 381f9765acdSGreg Clayton 38297206d57SZachary Turner Status 38397206d57SZachary Turner ProcessKDP::DoAttachToProcessWithID(lldb::pid_t attach_pid, 38497206d57SZachary Turner const ProcessAttachInfo &attach_info) { 38597206d57SZachary Turner Status error; 386b9c1b51eSKate Stone error.SetErrorString( 3874ebdee0aSBruce Mitchener "attach to process by ID is not supported in kdp remote debugging"); 38884647048SHan Ming Ong return error; 38984647048SHan Ming Ong } 39084647048SHan Ming Ong 39197206d57SZachary Turner Status 39297206d57SZachary Turner ProcessKDP::DoAttachToProcessWithName(const char *process_name, 39397206d57SZachary Turner const ProcessAttachInfo &attach_info) { 39497206d57SZachary Turner Status error; 395b9c1b51eSKate Stone error.SetErrorString( 3964ebdee0aSBruce Mitchener "attach to process by name is not supported in kdp remote debugging"); 397f9765acdSGreg Clayton return error; 398f9765acdSGreg Clayton } 399f9765acdSGreg Clayton 400b9c1b51eSKate Stone void ProcessKDP::DidAttach(ArchSpec &process_arch) { 401bb006ce2SJim Ingham Process::DidAttach(process_arch); 402bb006ce2SJim Ingham 4035160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 404f9765acdSGreg Clayton if (log) 40554cb8f83SJohnny Chen log->Printf("ProcessKDP::DidAttach()"); 406b9c1b51eSKate Stone if (GetID() != LLDB_INVALID_PROCESS_ID) { 407a3706888SGreg Clayton GetHostArchitecture(process_arch); 408f9765acdSGreg Clayton } 409f9765acdSGreg Clayton } 410f9765acdSGreg Clayton 411b9c1b51eSKate Stone addr_t ProcessKDP::GetImageInfoAddress() { return m_kernel_load_addr; } 4125e8534efSJason Molenda 413b9c1b51eSKate Stone lldb_private::DynamicLoader *ProcessKDP::GetDynamicLoader() { 4145e8534efSJason Molenda if (m_dyld_ap.get() == NULL) 415b9c1b51eSKate Stone m_dyld_ap.reset(DynamicLoader::FindPlugin( 416b9c1b51eSKate Stone this, 417b9c1b51eSKate Stone m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString())); 4185e8534efSJason Molenda return m_dyld_ap.get(); 4195e8534efSJason Molenda } 4205e8534efSJason Molenda 42197206d57SZachary Turner Status ProcessKDP::WillResume() { return Status(); } 422f9765acdSGreg Clayton 42397206d57SZachary Turner Status ProcessKDP::DoResume() { 42497206d57SZachary Turner Status error; 4255160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 4267925fbbaSGreg Clayton // Only start the async thread if we try to do any process control 427acee96aeSZachary Turner if (!m_async_thread.IsJoinable()) 4287925fbbaSGreg Clayton StartAsyncThread(); 4297925fbbaSGreg Clayton 43097d5cf05SGreg Clayton bool resume = false; 4317925fbbaSGreg Clayton 43297d5cf05SGreg Clayton // With KDP there is only one thread we can tell what to do 433ba4e61d3SAndrew Kaylor ThreadSP kernel_thread_sp(m_thread_list.FindThreadByProtocolID(g_kernel_tid)); 434ba4e61d3SAndrew Kaylor 435b9c1b51eSKate Stone if (kernel_thread_sp) { 436b9c1b51eSKate Stone const StateType thread_resume_state = 437b9c1b51eSKate Stone kernel_thread_sp->GetTemporaryResumeState(); 4386e0ff1a3SGreg Clayton 4396e0ff1a3SGreg Clayton if (log) 440b9c1b51eSKate Stone log->Printf("ProcessKDP::DoResume() thread_resume_state = %s", 441b9c1b51eSKate Stone StateAsCString(thread_resume_state)); 442b9c1b51eSKate Stone switch (thread_resume_state) { 4437925fbbaSGreg Clayton case eStateSuspended: 44405097246SAdrian Prantl // Nothing to do here when a thread will stay suspended we just leave the 44505097246SAdrian Prantl // CPU mask bit set to zero for the thread 4466e0ff1a3SGreg Clayton if (log) 4476e0ff1a3SGreg Clayton log->Printf("ProcessKDP::DoResume() = suspended???"); 4487925fbbaSGreg Clayton break; 4497925fbbaSGreg Clayton 450b9c1b51eSKate Stone case eStateStepping: { 451b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 452b9c1b51eSKate Stone kernel_thread_sp->GetRegisterContext()); 4531afa68edSGreg Clayton 454b9c1b51eSKate Stone if (reg_ctx_sp) { 4556e0ff1a3SGreg Clayton if (log) 456b9c1b51eSKate Stone log->Printf( 457b9c1b51eSKate Stone "ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (true);"); 4581afa68edSGreg Clayton reg_ctx_sp->HardwareSingleStep(true); 45997d5cf05SGreg Clayton resume = true; 460b9c1b51eSKate Stone } else { 461b9c1b51eSKate Stone error.SetErrorStringWithFormat( 462b9c1b51eSKate Stone "KDP thread 0x%llx has no register context", 463b9c1b51eSKate Stone kernel_thread_sp->GetID()); 4641afa68edSGreg Clayton } 465b9c1b51eSKate Stone } break; 4667925fbbaSGreg Clayton 467b9c1b51eSKate Stone case eStateRunning: { 468b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 469b9c1b51eSKate Stone kernel_thread_sp->GetRegisterContext()); 4701afa68edSGreg Clayton 471b9c1b51eSKate Stone if (reg_ctx_sp) { 4726e0ff1a3SGreg Clayton if (log) 473b9c1b51eSKate Stone log->Printf("ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep " 474b9c1b51eSKate Stone "(false);"); 4751afa68edSGreg Clayton reg_ctx_sp->HardwareSingleStep(false); 47697d5cf05SGreg Clayton resume = true; 477b9c1b51eSKate Stone } else { 478b9c1b51eSKate Stone error.SetErrorStringWithFormat( 479b9c1b51eSKate Stone "KDP thread 0x%llx has no register context", 480b9c1b51eSKate Stone kernel_thread_sp->GetID()); 4811afa68edSGreg Clayton } 482b9c1b51eSKate Stone } break; 4837925fbbaSGreg Clayton 4847925fbbaSGreg Clayton default: 48597d5cf05SGreg Clayton // The only valid thread resume states are listed above 486a322f36cSDavid Blaikie llvm_unreachable("invalid thread resume state"); 4874b1b8b3eSGreg Clayton } 4884b1b8b3eSGreg Clayton } 4897925fbbaSGreg Clayton 490b9c1b51eSKate Stone if (resume) { 49197d5cf05SGreg Clayton if (log) 49297d5cf05SGreg Clayton log->Printf("ProcessKDP::DoResume () sending resume"); 49397d5cf05SGreg Clayton 494b9c1b51eSKate Stone if (m_comm.SendRequestResume()) { 4957925fbbaSGreg Clayton m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue); 4967925fbbaSGreg Clayton SetPrivateState(eStateRunning); 497b9c1b51eSKate Stone } else 49807e66e3eSGreg Clayton error.SetErrorString("KDP resume failed"); 499b9c1b51eSKate Stone } else { 50097d5cf05SGreg Clayton error.SetErrorString("kernel thread is suspended"); 5017925fbbaSGreg Clayton } 5027925fbbaSGreg Clayton 503f9765acdSGreg Clayton return error; 504f9765acdSGreg Clayton } 505f9765acdSGreg Clayton 506b9c1b51eSKate Stone lldb::ThreadSP ProcessKDP::GetKernelThread() { 50797d5cf05SGreg Clayton // KDP only tells us about one thread/core. Any other threads will usually 50897d5cf05SGreg Clayton // be the ones that are read from memory by the OS plug-ins. 509ba4e61d3SAndrew Kaylor 510ba4e61d3SAndrew Kaylor ThreadSP thread_sp(m_kernel_thread_wp.lock()); 511b9c1b51eSKate Stone if (!thread_sp) { 512ba4e61d3SAndrew Kaylor thread_sp.reset(new ThreadKDP(*this, g_kernel_tid)); 513ba4e61d3SAndrew Kaylor m_kernel_thread_wp = thread_sp; 514ba4e61d3SAndrew Kaylor } 51597d5cf05SGreg Clayton return thread_sp; 51697d5cf05SGreg Clayton } 51797d5cf05SGreg Clayton 518b9c1b51eSKate Stone bool ProcessKDP::UpdateThreadList(ThreadList &old_thread_list, 519b9c1b51eSKate Stone ThreadList &new_thread_list) { 520f9765acdSGreg Clayton // locker will keep a mutex locked until it goes out of scope 5215160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_THREAD)); 522250858a0SPavel Labath LLDB_LOGV(log, "pid = {0}", GetID()); 523f9765acdSGreg Clayton 52439da3efdSGreg Clayton // Even though there is a CPU mask, it doesn't mean we can see each CPU 525a868c13cSBruce Mitchener // individually, there is really only one. Lets call this thread 1. 526b9c1b51eSKate Stone ThreadSP thread_sp( 527b9c1b51eSKate Stone old_thread_list.FindThreadByProtocolID(g_kernel_tid, false)); 528ba4e61d3SAndrew Kaylor if (!thread_sp) 529ba4e61d3SAndrew Kaylor thread_sp = GetKernelThread(); 530ba4e61d3SAndrew Kaylor new_thread_list.AddThread(thread_sp); 53197d5cf05SGreg Clayton 5329fc13556SGreg Clayton return new_thread_list.GetSize(false) > 0; 533f9765acdSGreg Clayton } 534f9765acdSGreg Clayton 535b9c1b51eSKate Stone void ProcessKDP::RefreshStateAfterStop() { 53605097246SAdrian Prantl // Let all threads recover from stopping and do any clean up based on the 53705097246SAdrian Prantl // previous thread state (if any). 538f9765acdSGreg Clayton m_thread_list.RefreshStateAfterStop(); 539f9765acdSGreg Clayton } 540f9765acdSGreg Clayton 54197206d57SZachary Turner Status ProcessKDP::DoHalt(bool &caused_stop) { 54297206d57SZachary Turner Status error; 543f9765acdSGreg Clayton 544b9c1b51eSKate Stone if (m_comm.IsRunning()) { 545b9c1b51eSKate Stone if (m_destroy_in_process) { 5464ebdee0aSBruce Mitchener // If we are attempting to destroy, we need to not return an error to Halt 54705097246SAdrian Prantl // or DoDestroy won't get called. We are also currently running, so send 54805097246SAdrian Prantl // a process stopped event 54997d5cf05SGreg Clayton SetPrivateState(eStateStopped); 550b9c1b51eSKate Stone } else { 55197d5cf05SGreg Clayton error.SetErrorString("KDP cannot interrupt a running kernel"); 552f9765acdSGreg Clayton } 553f9765acdSGreg Clayton } 554f9765acdSGreg Clayton return error; 555f9765acdSGreg Clayton } 556f9765acdSGreg Clayton 55797206d57SZachary Turner Status ProcessKDP::DoDetach(bool keep_stopped) { 55897206d57SZachary Turner Status error; 5595160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 560f9765acdSGreg Clayton if (log) 561acff8950SJim Ingham log->Printf("ProcessKDP::DoDetach(keep_stopped = %i)", keep_stopped); 562f9765acdSGreg Clayton 563b9c1b51eSKate Stone if (m_comm.IsRunning()) { 56405097246SAdrian Prantl // We are running and we can't interrupt a running kernel, so we need to 56505097246SAdrian Prantl // just close the connection to the kernel and hope for the best 566b9c1b51eSKate Stone } else { 567b9c1b51eSKate Stone // If we are going to keep the target stopped, then don't send the 568b9c1b51eSKate Stone // disconnect message. 569b9c1b51eSKate Stone if (!keep_stopped && m_comm.IsConnected()) { 5706e0ff1a3SGreg Clayton const bool success = m_comm.SendRequestDisconnect(); 571b9c1b51eSKate Stone if (log) { 5726e0ff1a3SGreg Clayton if (success) 573b9c1b51eSKate Stone log->PutCString( 574b9c1b51eSKate Stone "ProcessKDP::DoDetach() detach packet sent successfully"); 575f9765acdSGreg Clayton else 576b9c1b51eSKate Stone log->PutCString( 577b9c1b51eSKate Stone "ProcessKDP::DoDetach() connection channel shutdown failed"); 578f9765acdSGreg Clayton } 5796e0ff1a3SGreg Clayton m_comm.Disconnect(); 5803a29bdbeSGreg Clayton } 58197d5cf05SGreg Clayton } 582f9765acdSGreg Clayton StopAsyncThread(); 58374d4193eSGreg Clayton m_comm.Clear(); 584f9765acdSGreg Clayton 585f9765acdSGreg Clayton SetPrivateState(eStateDetached); 586f9765acdSGreg Clayton ResumePrivateStateThread(); 587f9765acdSGreg Clayton 588f9765acdSGreg Clayton // KillDebugserverProcess (); 589f9765acdSGreg Clayton return error; 590f9765acdSGreg Clayton } 591f9765acdSGreg Clayton 59297206d57SZachary Turner Status ProcessKDP::DoDestroy() { 5937925fbbaSGreg Clayton // For KDP there really is no difference between destroy and detach 594acff8950SJim Ingham bool keep_stopped = false; 595acff8950SJim Ingham return DoDetach(keep_stopped); 596f9765acdSGreg Clayton } 597f9765acdSGreg Clayton 598f9765acdSGreg Clayton //------------------------------------------------------------------ 599f9765acdSGreg Clayton // Process Queries 600f9765acdSGreg Clayton //------------------------------------------------------------------ 601f9765acdSGreg Clayton 602b9c1b51eSKate Stone bool ProcessKDP::IsAlive() { 603a814f704SJason Molenda return m_comm.IsConnected() && Process::IsAlive(); 604f9765acdSGreg Clayton } 605f9765acdSGreg Clayton 606f9765acdSGreg Clayton //------------------------------------------------------------------ 607f9765acdSGreg Clayton // Process Memory 608f9765acdSGreg Clayton //------------------------------------------------------------------ 609b9c1b51eSKate Stone size_t ProcessKDP::DoReadMemory(addr_t addr, void *buf, size_t size, 61097206d57SZachary Turner Status &error) { 6118eb32817SJason Molenda uint8_t *data_buffer = (uint8_t *)buf; 612b9c1b51eSKate Stone if (m_comm.IsConnected()) { 6138eb32817SJason Molenda const size_t max_read_size = 512; 6148eb32817SJason Molenda size_t total_bytes_read = 0; 6158eb32817SJason Molenda 6168eb32817SJason Molenda // Read the requested amount of memory in 512 byte chunks 617b9c1b51eSKate Stone while (total_bytes_read < size) { 6188eb32817SJason Molenda size_t bytes_to_read_this_request = size - total_bytes_read; 619b9c1b51eSKate Stone if (bytes_to_read_this_request > max_read_size) { 6208eb32817SJason Molenda bytes_to_read_this_request = max_read_size; 6218eb32817SJason Molenda } 622b9c1b51eSKate Stone size_t bytes_read = m_comm.SendRequestReadMemory( 623b9c1b51eSKate Stone addr + total_bytes_read, data_buffer + total_bytes_read, 6248eb32817SJason Molenda bytes_to_read_this_request, error); 6258eb32817SJason Molenda total_bytes_read += bytes_read; 626b9c1b51eSKate Stone if (error.Fail() || bytes_read == 0) { 6278eb32817SJason Molenda return total_bytes_read; 6288eb32817SJason Molenda } 6298eb32817SJason Molenda } 6308eb32817SJason Molenda 6318eb32817SJason Molenda return total_bytes_read; 6328eb32817SJason Molenda } 633a63d08c9SGreg Clayton error.SetErrorString("not connected"); 634f9765acdSGreg Clayton return 0; 635f9765acdSGreg Clayton } 636f9765acdSGreg Clayton 637b9c1b51eSKate Stone size_t ProcessKDP::DoWriteMemory(addr_t addr, const void *buf, size_t size, 63897206d57SZachary Turner Status &error) { 6397925fbbaSGreg Clayton if (m_comm.IsConnected()) 6407925fbbaSGreg Clayton return m_comm.SendRequestWriteMemory(addr, buf, size, error); 6417925fbbaSGreg Clayton error.SetErrorString("not connected"); 642f9765acdSGreg Clayton return 0; 643f9765acdSGreg Clayton } 644f9765acdSGreg Clayton 645b9c1b51eSKate Stone lldb::addr_t ProcessKDP::DoAllocateMemory(size_t size, uint32_t permissions, 64697206d57SZachary Turner Status &error) { 647b9c1b51eSKate Stone error.SetErrorString( 6484ebdee0aSBruce Mitchener "memory allocation not supported in kdp remote debugging"); 649f9765acdSGreg Clayton return LLDB_INVALID_ADDRESS; 650f9765acdSGreg Clayton } 651f9765acdSGreg Clayton 65297206d57SZachary Turner Status ProcessKDP::DoDeallocateMemory(lldb::addr_t addr) { 65397206d57SZachary Turner Status error; 654b9c1b51eSKate Stone error.SetErrorString( 6554ebdee0aSBruce Mitchener "memory deallocation not supported in kdp remote debugging"); 656f9765acdSGreg Clayton return error; 657f9765acdSGreg Clayton } 658f9765acdSGreg Clayton 65997206d57SZachary Turner Status ProcessKDP::EnableBreakpointSite(BreakpointSite *bp_site) { 660b9c1b51eSKate Stone if (m_comm.LocalBreakpointsAreSupported()) { 66197206d57SZachary Turner Status error; 662b9c1b51eSKate Stone if (!bp_site->IsEnabled()) { 663b9c1b51eSKate Stone if (m_comm.SendRequestBreakpoint(true, bp_site->GetLoadAddress())) { 6645b88216dSGreg Clayton bp_site->SetEnabled(true); 6655b88216dSGreg Clayton bp_site->SetType(BreakpointSite::eExternal); 666b9c1b51eSKate Stone } else { 66707e66e3eSGreg Clayton error.SetErrorString("KDP set breakpoint failed"); 6685b88216dSGreg Clayton } 6695b88216dSGreg Clayton } 67007e66e3eSGreg Clayton return error; 67107e66e3eSGreg Clayton } 672f9765acdSGreg Clayton return EnableSoftwareBreakpoint(bp_site); 673f9765acdSGreg Clayton } 674f9765acdSGreg Clayton 67597206d57SZachary Turner Status ProcessKDP::DisableBreakpointSite(BreakpointSite *bp_site) { 676b9c1b51eSKate Stone if (m_comm.LocalBreakpointsAreSupported()) { 67797206d57SZachary Turner Status error; 678b9c1b51eSKate Stone if (bp_site->IsEnabled()) { 6795b88216dSGreg Clayton BreakpointSite::Type bp_type = bp_site->GetType(); 680b9c1b51eSKate Stone if (bp_type == BreakpointSite::eExternal) { 681b9c1b51eSKate Stone if (m_destroy_in_process && m_comm.IsRunning()) { 68297d5cf05SGreg Clayton // We are trying to destroy our connection and we are running 68397d5cf05SGreg Clayton bp_site->SetEnabled(false); 684b9c1b51eSKate Stone } else { 6855b88216dSGreg Clayton if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress())) 6865b88216dSGreg Clayton bp_site->SetEnabled(false); 6875b88216dSGreg Clayton else 68807e66e3eSGreg Clayton error.SetErrorString("KDP remove breakpoint failed"); 6895b88216dSGreg Clayton } 690b9c1b51eSKate Stone } else { 6915b88216dSGreg Clayton error = DisableSoftwareBreakpoint(bp_site); 6925b88216dSGreg Clayton } 6935b88216dSGreg Clayton } 69407e66e3eSGreg Clayton return error; 69507e66e3eSGreg Clayton } 696f9765acdSGreg Clayton return DisableSoftwareBreakpoint(bp_site); 697f9765acdSGreg Clayton } 698f9765acdSGreg Clayton 69997206d57SZachary Turner Status ProcessKDP::EnableWatchpoint(Watchpoint *wp, bool notify) { 70097206d57SZachary Turner Status error; 701b9c1b51eSKate Stone error.SetErrorString( 7024ebdee0aSBruce Mitchener "watchpoints are not supported in kdp remote debugging"); 703f9765acdSGreg Clayton return error; 704f9765acdSGreg Clayton } 705f9765acdSGreg Clayton 70697206d57SZachary Turner Status ProcessKDP::DisableWatchpoint(Watchpoint *wp, bool notify) { 70797206d57SZachary Turner Status error; 708b9c1b51eSKate Stone error.SetErrorString( 7094ebdee0aSBruce Mitchener "watchpoints are not supported in kdp remote debugging"); 710f9765acdSGreg Clayton return error; 711f9765acdSGreg Clayton } 712f9765acdSGreg Clayton 713b9c1b51eSKate Stone void ProcessKDP::Clear() { m_thread_list.Clear(); } 714f9765acdSGreg Clayton 71597206d57SZachary Turner Status ProcessKDP::DoSignal(int signo) { 71697206d57SZachary Turner Status error; 717b9c1b51eSKate Stone error.SetErrorString( 7184ebdee0aSBruce Mitchener "sending signals is not supported in kdp remote debugging"); 719f9765acdSGreg Clayton return error; 720f9765acdSGreg Clayton } 721f9765acdSGreg Clayton 722b9c1b51eSKate Stone void ProcessKDP::Initialize() { 723c5f28e2aSKamil Rytarowski static llvm::once_flag g_once_flag; 724f9765acdSGreg Clayton 725c5f28e2aSKamil Rytarowski llvm::call_once(g_once_flag, []() { 726f9765acdSGreg Clayton PluginManager::RegisterPlugin(GetPluginNameStatic(), 727b9c1b51eSKate Stone GetPluginDescriptionStatic(), CreateInstance, 728488c89edSBruce Mitchener DebuggerInitialize); 729f9765acdSGreg Clayton 7307b35b781SPavel Labath ProcessKDPLog::Initialize(); 731c8d69828SDavide Italiano }); 732f9765acdSGreg Clayton } 733f9765acdSGreg Clayton 734b9c1b51eSKate Stone void ProcessKDP::DebuggerInitialize(lldb_private::Debugger &debugger) { 735b9c1b51eSKate Stone if (!PluginManager::GetSettingForProcessPlugin( 736b9c1b51eSKate Stone debugger, PluginProperties::GetSettingName())) { 7377f98240dSGreg Clayton const bool is_global_setting = true; 738b9c1b51eSKate Stone PluginManager::CreateSettingForProcessPlugin( 739b9c1b51eSKate Stone debugger, GetGlobalPluginProperties()->GetValueProperties(), 7407f98240dSGreg Clayton ConstString("Properties for the kdp-remote process plug-in."), 7417f98240dSGreg Clayton is_global_setting); 7427f98240dSGreg Clayton } 7437f98240dSGreg Clayton } 7447f98240dSGreg Clayton 745b9c1b51eSKate Stone bool ProcessKDP::StartAsyncThread() { 7465160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 747f9765acdSGreg Clayton 748f9765acdSGreg Clayton if (log) 7497925fbbaSGreg Clayton log->Printf("ProcessKDP::StartAsyncThread ()"); 750f9765acdSGreg Clayton 751acee96aeSZachary Turner if (m_async_thread.IsJoinable()) 7527925fbbaSGreg Clayton return true; 7537925fbbaSGreg Clayton 754b9c1b51eSKate Stone m_async_thread = ThreadLauncher::LaunchThread( 755b9c1b51eSKate Stone "<lldb.process.kdp-remote.async>", ProcessKDP::AsyncThread, this, NULL); 756acee96aeSZachary Turner return m_async_thread.IsJoinable(); 757f9765acdSGreg Clayton } 758f9765acdSGreg Clayton 759b9c1b51eSKate Stone void ProcessKDP::StopAsyncThread() { 7605160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 761f9765acdSGreg Clayton 762f9765acdSGreg Clayton if (log) 7637925fbbaSGreg Clayton log->Printf("ProcessKDP::StopAsyncThread ()"); 764f9765acdSGreg Clayton 765f9765acdSGreg Clayton m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit); 766f9765acdSGreg Clayton 767f9765acdSGreg Clayton // Stop the stdio thread 768acee96aeSZachary Turner if (m_async_thread.IsJoinable()) 76939de3110SZachary Turner m_async_thread.Join(nullptr); 770f9765acdSGreg Clayton } 771f9765acdSGreg Clayton 772b9c1b51eSKate Stone void *ProcessKDP::AsyncThread(void *arg) { 773f9765acdSGreg Clayton ProcessKDP *process = (ProcessKDP *)arg; 774f9765acdSGreg Clayton 7757925fbbaSGreg Clayton const lldb::pid_t pid = process->GetID(); 7767925fbbaSGreg Clayton 7775160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 778f9765acdSGreg Clayton if (log) 779b9c1b51eSKate Stone log->Printf("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 780b9c1b51eSKate Stone ") thread starting...", 781b9c1b51eSKate Stone arg, pid); 782f9765acdSGreg Clayton 783583bbb1dSJim Ingham ListenerSP listener_sp(Listener::MakeListener("ProcessKDP::AsyncThread")); 784f9765acdSGreg Clayton EventSP event_sp; 785b9c1b51eSKate Stone const uint32_t desired_event_mask = 786b9c1b51eSKate Stone eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit; 787f9765acdSGreg Clayton 788b9c1b51eSKate Stone if (listener_sp->StartListeningForEvents(&process->m_async_broadcaster, 789b9c1b51eSKate Stone desired_event_mask) == 790b9c1b51eSKate Stone desired_event_mask) { 791f9765acdSGreg Clayton bool done = false; 792b9c1b51eSKate Stone while (!done) { 793f9765acdSGreg Clayton if (log) 794b9c1b51eSKate Stone log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 795b9c1b51eSKate Stone ") listener.WaitForEvent (NULL, event_sp)...", 7967925fbbaSGreg Clayton pid); 797fafff0c5SPavel Labath if (listener_sp->GetEvent(event_sp, llvm::None)) { 7987925fbbaSGreg Clayton uint32_t event_type = event_sp->GetType(); 799f9765acdSGreg Clayton if (log) 800b9c1b51eSKate Stone log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 801b9c1b51eSKate Stone ") Got an event of type: %d...", 802b9c1b51eSKate Stone pid, event_type); 803f9765acdSGreg Clayton 8047925fbbaSGreg Clayton // When we are running, poll for 1 second to try and get an exception 8057925fbbaSGreg Clayton // to indicate the process has stopped. If we don't get one, check to 8067925fbbaSGreg Clayton // make sure no one asked us to exit 8077925fbbaSGreg Clayton bool is_running = false; 8087925fbbaSGreg Clayton DataExtractor exc_reply_packet; 809b9c1b51eSKate Stone do { 810b9c1b51eSKate Stone switch (event_type) { 811b9c1b51eSKate Stone case eBroadcastBitAsyncContinue: { 8127925fbbaSGreg Clayton is_running = true; 813b9c1b51eSKate Stone if (process->m_comm.WaitForPacketWithTimeoutMicroSeconds( 814b9c1b51eSKate Stone exc_reply_packet, 1 * USEC_PER_SEC)) { 815ba4e61d3SAndrew Kaylor ThreadSP thread_sp(process->GetKernelThread()); 816b9c1b51eSKate Stone if (thread_sp) { 817b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 818b9c1b51eSKate Stone thread_sp->GetRegisterContext()); 8191afa68edSGreg Clayton if (reg_ctx_sp) 8201afa68edSGreg Clayton reg_ctx_sp->InvalidateAllRegisters(); 821b9c1b51eSKate Stone static_cast<ThreadKDP *>(thread_sp.get()) 822b9c1b51eSKate Stone ->SetStopInfoFrom_KDP_EXCEPTION(exc_reply_packet); 8231afa68edSGreg Clayton } 82497d5cf05SGreg Clayton 8257925fbbaSGreg Clayton // TODO: parse the stop reply packet 8267925fbbaSGreg Clayton is_running = false; 8277925fbbaSGreg Clayton process->SetPrivateState(eStateStopped); 828b9c1b51eSKate Stone } else { 8297925fbbaSGreg Clayton // Check to see if we are supposed to exit. There is no way to 8307925fbbaSGreg Clayton // interrupt a running kernel, so all we can do is wait for an 8317925fbbaSGreg Clayton // exception or detach... 832fafff0c5SPavel Labath if (listener_sp->GetEvent(event_sp, 833fafff0c5SPavel Labath std::chrono::microseconds(0))) { 8347925fbbaSGreg Clayton // We got an event, go through the loop again 8357925fbbaSGreg Clayton event_type = event_sp->GetType(); 8367925fbbaSGreg Clayton } 837f9765acdSGreg Clayton } 838b9c1b51eSKate Stone } break; 839f9765acdSGreg Clayton 840f9765acdSGreg Clayton case eBroadcastBitAsyncThreadShouldExit: 841f9765acdSGreg Clayton if (log) 842b9c1b51eSKate Stone log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 843b9c1b51eSKate Stone ") got eBroadcastBitAsyncThreadShouldExit...", 8447925fbbaSGreg Clayton pid); 845f9765acdSGreg Clayton done = true; 8467925fbbaSGreg Clayton is_running = false; 847f9765acdSGreg Clayton break; 848f9765acdSGreg Clayton 849f9765acdSGreg Clayton default: 850f9765acdSGreg Clayton if (log) 851b9c1b51eSKate Stone log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 852b9c1b51eSKate Stone ") got unknown event 0x%8.8x", 853b9c1b51eSKate Stone pid, event_type); 854f9765acdSGreg Clayton done = true; 8557925fbbaSGreg Clayton is_running = false; 856f9765acdSGreg Clayton break; 857f9765acdSGreg Clayton } 8587925fbbaSGreg Clayton } while (is_running); 859b9c1b51eSKate Stone } else { 860f9765acdSGreg Clayton if (log) 861b9c1b51eSKate Stone log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 862b9c1b51eSKate Stone ") listener.WaitForEvent (NULL, event_sp) => false", 8637925fbbaSGreg Clayton pid); 864f9765acdSGreg Clayton done = true; 865f9765acdSGreg Clayton } 866f9765acdSGreg Clayton } 867f9765acdSGreg Clayton } 868f9765acdSGreg Clayton 869f9765acdSGreg Clayton if (log) 870b9c1b51eSKate Stone log->Printf("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 871b9c1b51eSKate Stone ") thread exiting...", 872b9c1b51eSKate Stone arg, pid); 873f9765acdSGreg Clayton 87439de3110SZachary Turner process->m_async_thread.Reset(); 875f9765acdSGreg Clayton return NULL; 876f9765acdSGreg Clayton } 877f9765acdSGreg Clayton 878b9c1b51eSKate Stone class CommandObjectProcessKDPPacketSend : public CommandObjectParsed { 8791d19a2f2SGreg Clayton private: 8801d19a2f2SGreg Clayton OptionGroupOptions m_option_group; 8811d19a2f2SGreg Clayton OptionGroupUInt64 m_command_byte; 8821d19a2f2SGreg Clayton OptionGroupString m_packet_data; 8831d19a2f2SGreg Clayton 884b9c1b51eSKate Stone virtual Options *GetOptions() { return &m_option_group; } 8851d19a2f2SGreg Clayton 8861d19a2f2SGreg Clayton public: 887b9c1b51eSKate Stone CommandObjectProcessKDPPacketSend(CommandInterpreter &interpreter) 888b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "process plugin packet send", 889b9c1b51eSKate Stone "Send a custom packet through the KDP protocol by " 890b9c1b51eSKate Stone "specifying the command byte and the packet " 891b9c1b51eSKate Stone "payload data. A packet will be sent with a " 892b9c1b51eSKate Stone "correct header and payload, and the raw result " 893b9c1b51eSKate Stone "bytes will be displayed as a string value. ", 8941d19a2f2SGreg Clayton NULL), 895e1cfbc79STodd Fiala m_option_group(), 896b9c1b51eSKate Stone m_command_byte(LLDB_OPT_SET_1, true, "command", 'c', 0, eArgTypeNone, 897b9c1b51eSKate Stone "Specify the command byte to use when sending the KDP " 898b9c1b51eSKate Stone "request packet.", 899b9c1b51eSKate Stone 0), 900b9c1b51eSKate Stone m_packet_data(LLDB_OPT_SET_1, false, "payload", 'p', 0, eArgTypeNone, 901b9c1b51eSKate Stone "Specify packet payload bytes as a hex ASCII string with " 902b9c1b51eSKate Stone "no spaces or hex prefixes.", 903b9c1b51eSKate Stone NULL) { 9041d19a2f2SGreg Clayton m_option_group.Append(&m_command_byte, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 9051d19a2f2SGreg Clayton m_option_group.Append(&m_packet_data, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 9061d19a2f2SGreg Clayton m_option_group.Finalize(); 9071d19a2f2SGreg Clayton } 9081d19a2f2SGreg Clayton 909b9c1b51eSKate Stone ~CommandObjectProcessKDPPacketSend() {} 9101d19a2f2SGreg Clayton 911b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) { 9121d19a2f2SGreg Clayton const size_t argc = command.GetArgumentCount(); 913b9c1b51eSKate Stone if (argc == 0) { 914b9c1b51eSKate Stone if (!m_command_byte.GetOptionValue().OptionWasSet()) { 915b9c1b51eSKate Stone result.AppendError( 916b9c1b51eSKate Stone "the --command option must be set to a valid command byte"); 9171d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 918b9c1b51eSKate Stone } else { 919b9c1b51eSKate Stone const uint64_t command_byte = 920b9c1b51eSKate Stone m_command_byte.GetOptionValue().GetUInt64Value(0); 921b9c1b51eSKate Stone if (command_byte > 0 && command_byte <= UINT8_MAX) { 922b9c1b51eSKate Stone ProcessKDP *process = 923b9c1b51eSKate Stone (ProcessKDP *)m_interpreter.GetExecutionContext().GetProcessPtr(); 924b9c1b51eSKate Stone if (process) { 9251d19a2f2SGreg Clayton const StateType state = process->GetState(); 9261d19a2f2SGreg Clayton 927b9c1b51eSKate Stone if (StateIsStoppedState(state, true)) { 9281d19a2f2SGreg Clayton std::vector<uint8_t> payload_bytes; 929b9c1b51eSKate Stone const char *ascii_hex_bytes_cstr = 930b9c1b51eSKate Stone m_packet_data.GetOptionValue().GetCurrentValue(); 931b9c1b51eSKate Stone if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0]) { 9321d19a2f2SGreg Clayton StringExtractor extractor(ascii_hex_bytes_cstr); 933b9c1b51eSKate Stone const size_t ascii_hex_bytes_cstr_len = 934b9c1b51eSKate Stone extractor.GetStringRef().size(); 935b9c1b51eSKate Stone if (ascii_hex_bytes_cstr_len & 1) { 936b9c1b51eSKate Stone result.AppendErrorWithFormat("payload data must contain an " 937b9c1b51eSKate Stone "even number of ASCII hex " 938b9c1b51eSKate Stone "characters: '%s'", 939b9c1b51eSKate Stone ascii_hex_bytes_cstr); 9401d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9411d19a2f2SGreg Clayton return false; 9421d19a2f2SGreg Clayton } 9431d19a2f2SGreg Clayton payload_bytes.resize(ascii_hex_bytes_cstr_len / 2); 944b9c1b51eSKate Stone if (extractor.GetHexBytes(payload_bytes, '\xdd') != 945b9c1b51eSKate Stone payload_bytes.size()) { 946b9c1b51eSKate Stone result.AppendErrorWithFormat("payload data must only contain " 947b9c1b51eSKate Stone "ASCII hex characters (no " 948b9c1b51eSKate Stone "spaces or hex prefixes): '%s'", 949b9c1b51eSKate Stone ascii_hex_bytes_cstr); 9501d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9511d19a2f2SGreg Clayton return false; 9521d19a2f2SGreg Clayton } 9531d19a2f2SGreg Clayton } 95497206d57SZachary Turner Status error; 9551d19a2f2SGreg Clayton DataExtractor reply; 956b9c1b51eSKate Stone process->GetCommunication().SendRawRequest( 957b9c1b51eSKate Stone command_byte, 9581d19a2f2SGreg Clayton payload_bytes.empty() ? NULL : payload_bytes.data(), 959b9c1b51eSKate Stone payload_bytes.size(), reply, error); 9601d19a2f2SGreg Clayton 961b9c1b51eSKate Stone if (error.Success()) { 9621d19a2f2SGreg Clayton // Copy the binary bytes into a hex ASCII string for the result 9631d19a2f2SGreg Clayton StreamString packet; 964b9c1b51eSKate Stone packet.PutBytesAsRawHex8( 965b9c1b51eSKate Stone reply.GetDataStart(), reply.GetByteSize(), 966b9c1b51eSKate Stone endian::InlHostByteOrder(), endian::InlHostByteOrder()); 967c156427dSZachary Turner result.AppendMessage(packet.GetString()); 9681d19a2f2SGreg Clayton result.SetStatus(eReturnStatusSuccessFinishResult); 9691d19a2f2SGreg Clayton return true; 970b9c1b51eSKate Stone } else { 9711d19a2f2SGreg Clayton const char *error_cstr = error.AsCString(); 9721d19a2f2SGreg Clayton if (error_cstr && error_cstr[0]) 9731d19a2f2SGreg Clayton result.AppendError(error_cstr); 9741d19a2f2SGreg Clayton else 975b9c1b51eSKate Stone result.AppendErrorWithFormat("unknown error 0x%8.8x", 976b9c1b51eSKate Stone error.GetError()); 9771d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9781d19a2f2SGreg Clayton return false; 9791d19a2f2SGreg Clayton } 980b9c1b51eSKate Stone } else { 981b9c1b51eSKate Stone result.AppendErrorWithFormat("process must be stopped in order " 982b9c1b51eSKate Stone "to send KDP packets, state is %s", 983b9c1b51eSKate Stone StateAsCString(state)); 9841d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9851d19a2f2SGreg Clayton } 986b9c1b51eSKate Stone } else { 9871d19a2f2SGreg Clayton result.AppendError("invalid process"); 9881d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9891d19a2f2SGreg Clayton } 990b9c1b51eSKate Stone } else { 991b9c1b51eSKate Stone result.AppendErrorWithFormat("invalid command byte 0x%" PRIx64 992b9c1b51eSKate Stone ", valid values are 1 - 255", 993b9c1b51eSKate Stone command_byte); 9941d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9951d19a2f2SGreg Clayton } 9961d19a2f2SGreg Clayton } 997b9c1b51eSKate Stone } else { 998b9c1b51eSKate Stone result.AppendErrorWithFormat("'%s' takes no arguments, only options.", 999b9c1b51eSKate Stone m_cmd_name.c_str()); 10001d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 10011d19a2f2SGreg Clayton } 10021d19a2f2SGreg Clayton return false; 10031d19a2f2SGreg Clayton } 10041d19a2f2SGreg Clayton }; 10051d19a2f2SGreg Clayton 1006b9c1b51eSKate Stone class CommandObjectProcessKDPPacket : public CommandObjectMultiword { 10071d19a2f2SGreg Clayton private: 10081d19a2f2SGreg Clayton public: 1009b9c1b51eSKate Stone CommandObjectProcessKDPPacket(CommandInterpreter &interpreter) 1010b9c1b51eSKate Stone : CommandObjectMultiword(interpreter, "process plugin packet", 10111d19a2f2SGreg Clayton "Commands that deal with KDP remote packets.", 1012b9c1b51eSKate Stone NULL) { 1013b9c1b51eSKate Stone LoadSubCommand( 1014b9c1b51eSKate Stone "send", 1015b9c1b51eSKate Stone CommandObjectSP(new CommandObjectProcessKDPPacketSend(interpreter))); 10161d19a2f2SGreg Clayton } 10171d19a2f2SGreg Clayton 1018b9c1b51eSKate Stone ~CommandObjectProcessKDPPacket() {} 10191d19a2f2SGreg Clayton }; 10201d19a2f2SGreg Clayton 1021b9c1b51eSKate Stone class CommandObjectMultiwordProcessKDP : public CommandObjectMultiword { 10221d19a2f2SGreg Clayton public: 10237428a18cSKate Stone CommandObjectMultiwordProcessKDP(CommandInterpreter &interpreter) 1024b9c1b51eSKate Stone : CommandObjectMultiword( 1025b9c1b51eSKate Stone interpreter, "process plugin", 1026b9c1b51eSKate Stone "Commands for operating on a ProcessKDP process.", 1027b9c1b51eSKate Stone "process plugin <subcommand> [<subcommand-options>]") { 1028b9c1b51eSKate Stone LoadSubCommand("packet", CommandObjectSP(new CommandObjectProcessKDPPacket( 1029b9c1b51eSKate Stone interpreter))); 10301d19a2f2SGreg Clayton } 10311d19a2f2SGreg Clayton 1032b9c1b51eSKate Stone ~CommandObjectMultiwordProcessKDP() {} 10331d19a2f2SGreg Clayton }; 10341d19a2f2SGreg Clayton 1035b9c1b51eSKate Stone CommandObject *ProcessKDP::GetPluginCommandObject() { 10361d19a2f2SGreg Clayton if (!m_command_sp) 1037b9c1b51eSKate Stone m_command_sp.reset(new CommandObjectMultiwordProcessKDP( 1038b9c1b51eSKate Stone GetTarget().GetDebugger().GetCommandInterpreter())); 10391d19a2f2SGreg Clayton return m_command_sp.get(); 10401d19a2f2SGreg Clayton } 1041