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 58e40db05bSTatyana Krasnukha static constexpr PropertyDefinition g_properties[] = { 59f929e2b0STatyana Krasnukha {"packet-timeout", OptionValue::eTypeUInt64, true, 5, NULL, {}, 60e40db05bSTatyana 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); 303*dbd7fabaSJonas Devlieghere if (FileSystem::Instance().Exists( 304*dbd7fabaSJonas Devlieghere executable_module_spec.GetFileSpec())) { 305b9c1b51eSKate Stone module_spec.GetFileSpec() = 306b9c1b51eSKate Stone executable_module_spec.GetFileSpec(); 3078825c5c9SJason Molenda } 3088825c5c9SJason Molenda } 309b9c1b51eSKate Stone if (!module_spec.GetSymbolFileSpec() || 310b9c1b51eSKate Stone !module_spec.GetSymbolFileSpec()) 311a1bce2efSGreg Clayton Symbols::DownloadObjectAndSymbolFile(module_spec, true); 312a1bce2efSGreg Clayton 313*dbd7fabaSJonas Devlieghere if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { 314a3706888SGreg Clayton ModuleSP module_sp(new Module(module_spec)); 315b9c1b51eSKate Stone if (module_sp.get() && module_sp->GetObjectFile()) { 316a1bce2efSGreg Clayton // Get the current target executable 3175a3bb64fSJim Ingham ModuleSP exe_module_sp(target.GetExecutableModule()); 318a1bce2efSGreg Clayton 319b9c1b51eSKate Stone // Make sure you don't already have the right module loaded 320b9c1b51eSKate Stone // and they will be uniqued 321a1bce2efSGreg Clayton if (exe_module_sp.get() != module_sp.get()) 322f9a07e9fSJonas Devlieghere target.SetExecutableModule(module_sp, eLoadDependentsNo); 323a1bce2efSGreg Clayton } 324a1bce2efSGreg Clayton } 325a1bce2efSGreg Clayton } 326b9c1b51eSKate Stone } else if (m_comm.RemoteIsDarwinKernel()) { 327b9c1b51eSKate Stone m_dyld_plugin_name = 328b9c1b51eSKate Stone DynamicLoaderDarwinKernel::GetPluginNameStatic(); 329b9c1b51eSKate Stone if (kernel_load_addr != LLDB_INVALID_ADDRESS) { 3305e8534efSJason Molenda m_kernel_load_addr = kernel_load_addr; 331a8ea4baeSJason Molenda } 3324bd4e7e3SJason Molenda } 3334bd4e7e3SJason Molenda 33497d5cf05SGreg Clayton // Set the thread ID 33597d5cf05SGreg Clayton UpdateThreadListIfNeeded(); 336a63d08c9SGreg Clayton SetID(1); 33756d9a1b3SGreg Clayton GetThreadList(); 338a63d08c9SGreg Clayton SetPrivateState(eStateStopped); 3395a3bb64fSJim Ingham StreamSP async_strm_sp(target.GetDebugger().GetAsyncOutputStream()); 340b9c1b51eSKate Stone if (async_strm_sp) { 3415b88216dSGreg Clayton const char *cstr; 342b9c1b51eSKate Stone if ((cstr = m_comm.GetKernelVersion()) != NULL) { 3435b88216dSGreg Clayton async_strm_sp->Printf("Version: %s\n", cstr); 34407e66e3eSGreg Clayton async_strm_sp->Flush(); 34507e66e3eSGreg Clayton } 3465b88216dSGreg Clayton // if ((cstr = m_comm.GetImagePath ()) != NULL) 3475b88216dSGreg Clayton // { 348b9c1b51eSKate Stone // async_strm_sp->Printf ("Image Path: 349b9c1b51eSKate Stone // %s\n", cstr); 3505b88216dSGreg Clayton // async_strm_sp->Flush(); 3515b88216dSGreg Clayton // } 35207e66e3eSGreg Clayton } 353b9c1b51eSKate Stone } else { 35497d5cf05SGreg Clayton error.SetErrorString("KDP_REATTACH failed"); 35597d5cf05SGreg Clayton } 356b9c1b51eSKate Stone } else { 35797d5cf05SGreg Clayton error.SetErrorString("KDP_REATTACH failed"); 3583a29bdbeSGreg Clayton } 359b9c1b51eSKate Stone } else { 3603a29bdbeSGreg Clayton error.SetErrorString("invalid reply port from UDP connection"); 3613a29bdbeSGreg Clayton } 362b9c1b51eSKate Stone } else { 3633a29bdbeSGreg Clayton if (error.Success()) 3643ce7e996SGreg Clayton error.SetErrorStringWithFormat("failed to connect to '%s'", 3653ce7e996SGreg Clayton remote_url.str().c_str()); 3663a29bdbeSGreg Clayton } 3673a29bdbeSGreg Clayton if (error.Fail()) 3683a29bdbeSGreg Clayton m_comm.Disconnect(); 3693a29bdbeSGreg Clayton 370f9765acdSGreg Clayton return error; 371f9765acdSGreg Clayton } 372f9765acdSGreg Clayton 373f9765acdSGreg Clayton //---------------------------------------------------------------------- 374f9765acdSGreg Clayton // Process Control 375f9765acdSGreg Clayton //---------------------------------------------------------------------- 37697206d57SZachary Turner Status ProcessKDP::DoLaunch(Module *exe_module, 37797206d57SZachary Turner ProcessLaunchInfo &launch_info) { 37897206d57SZachary Turner Status error; 379f9765acdSGreg Clayton error.SetErrorString("launching not supported in kdp-remote plug-in"); 380f9765acdSGreg Clayton return error; 381f9765acdSGreg Clayton } 382f9765acdSGreg Clayton 38397206d57SZachary Turner Status 38497206d57SZachary Turner ProcessKDP::DoAttachToProcessWithID(lldb::pid_t attach_pid, 38597206d57SZachary Turner const ProcessAttachInfo &attach_info) { 38697206d57SZachary Turner Status error; 387b9c1b51eSKate Stone error.SetErrorString( 3884ebdee0aSBruce Mitchener "attach to process by ID is not supported in kdp remote debugging"); 38984647048SHan Ming Ong return error; 39084647048SHan Ming Ong } 39184647048SHan Ming Ong 39297206d57SZachary Turner Status 39397206d57SZachary Turner ProcessKDP::DoAttachToProcessWithName(const char *process_name, 39497206d57SZachary Turner const ProcessAttachInfo &attach_info) { 39597206d57SZachary Turner Status error; 396b9c1b51eSKate Stone error.SetErrorString( 3974ebdee0aSBruce Mitchener "attach to process by name is not supported in kdp remote debugging"); 398f9765acdSGreg Clayton return error; 399f9765acdSGreg Clayton } 400f9765acdSGreg Clayton 401b9c1b51eSKate Stone void ProcessKDP::DidAttach(ArchSpec &process_arch) { 402bb006ce2SJim Ingham Process::DidAttach(process_arch); 403bb006ce2SJim Ingham 4045160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 405f9765acdSGreg Clayton if (log) 40654cb8f83SJohnny Chen log->Printf("ProcessKDP::DidAttach()"); 407b9c1b51eSKate Stone if (GetID() != LLDB_INVALID_PROCESS_ID) { 408a3706888SGreg Clayton GetHostArchitecture(process_arch); 409f9765acdSGreg Clayton } 410f9765acdSGreg Clayton } 411f9765acdSGreg Clayton 412b9c1b51eSKate Stone addr_t ProcessKDP::GetImageInfoAddress() { return m_kernel_load_addr; } 4135e8534efSJason Molenda 414b9c1b51eSKate Stone lldb_private::DynamicLoader *ProcessKDP::GetDynamicLoader() { 4155e8534efSJason Molenda if (m_dyld_ap.get() == NULL) 416b9c1b51eSKate Stone m_dyld_ap.reset(DynamicLoader::FindPlugin( 417b9c1b51eSKate Stone this, 418b9c1b51eSKate Stone m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString())); 4195e8534efSJason Molenda return m_dyld_ap.get(); 4205e8534efSJason Molenda } 4215e8534efSJason Molenda 42297206d57SZachary Turner Status ProcessKDP::WillResume() { return Status(); } 423f9765acdSGreg Clayton 42497206d57SZachary Turner Status ProcessKDP::DoResume() { 42597206d57SZachary Turner Status error; 4265160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 4277925fbbaSGreg Clayton // Only start the async thread if we try to do any process control 428acee96aeSZachary Turner if (!m_async_thread.IsJoinable()) 4297925fbbaSGreg Clayton StartAsyncThread(); 4307925fbbaSGreg Clayton 43197d5cf05SGreg Clayton bool resume = false; 4327925fbbaSGreg Clayton 43397d5cf05SGreg Clayton // With KDP there is only one thread we can tell what to do 434ba4e61d3SAndrew Kaylor ThreadSP kernel_thread_sp(m_thread_list.FindThreadByProtocolID(g_kernel_tid)); 435ba4e61d3SAndrew Kaylor 436b9c1b51eSKate Stone if (kernel_thread_sp) { 437b9c1b51eSKate Stone const StateType thread_resume_state = 438b9c1b51eSKate Stone kernel_thread_sp->GetTemporaryResumeState(); 4396e0ff1a3SGreg Clayton 4406e0ff1a3SGreg Clayton if (log) 441b9c1b51eSKate Stone log->Printf("ProcessKDP::DoResume() thread_resume_state = %s", 442b9c1b51eSKate Stone StateAsCString(thread_resume_state)); 443b9c1b51eSKate Stone switch (thread_resume_state) { 4447925fbbaSGreg Clayton case eStateSuspended: 44505097246SAdrian Prantl // Nothing to do here when a thread will stay suspended we just leave the 44605097246SAdrian Prantl // CPU mask bit set to zero for the thread 4476e0ff1a3SGreg Clayton if (log) 4486e0ff1a3SGreg Clayton log->Printf("ProcessKDP::DoResume() = suspended???"); 4497925fbbaSGreg Clayton break; 4507925fbbaSGreg Clayton 451b9c1b51eSKate Stone case eStateStepping: { 452b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 453b9c1b51eSKate Stone kernel_thread_sp->GetRegisterContext()); 4541afa68edSGreg Clayton 455b9c1b51eSKate Stone if (reg_ctx_sp) { 4566e0ff1a3SGreg Clayton if (log) 457b9c1b51eSKate Stone log->Printf( 458b9c1b51eSKate Stone "ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (true);"); 4591afa68edSGreg Clayton reg_ctx_sp->HardwareSingleStep(true); 46097d5cf05SGreg Clayton resume = true; 461b9c1b51eSKate Stone } else { 462b9c1b51eSKate Stone error.SetErrorStringWithFormat( 463b9c1b51eSKate Stone "KDP thread 0x%llx has no register context", 464b9c1b51eSKate Stone kernel_thread_sp->GetID()); 4651afa68edSGreg Clayton } 466b9c1b51eSKate Stone } break; 4677925fbbaSGreg Clayton 468b9c1b51eSKate Stone case eStateRunning: { 469b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 470b9c1b51eSKate Stone kernel_thread_sp->GetRegisterContext()); 4711afa68edSGreg Clayton 472b9c1b51eSKate Stone if (reg_ctx_sp) { 4736e0ff1a3SGreg Clayton if (log) 474b9c1b51eSKate Stone log->Printf("ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep " 475b9c1b51eSKate Stone "(false);"); 4761afa68edSGreg Clayton reg_ctx_sp->HardwareSingleStep(false); 47797d5cf05SGreg Clayton resume = true; 478b9c1b51eSKate Stone } else { 479b9c1b51eSKate Stone error.SetErrorStringWithFormat( 480b9c1b51eSKate Stone "KDP thread 0x%llx has no register context", 481b9c1b51eSKate Stone kernel_thread_sp->GetID()); 4821afa68edSGreg Clayton } 483b9c1b51eSKate Stone } break; 4847925fbbaSGreg Clayton 4857925fbbaSGreg Clayton default: 48697d5cf05SGreg Clayton // The only valid thread resume states are listed above 487a322f36cSDavid Blaikie llvm_unreachable("invalid thread resume state"); 4884b1b8b3eSGreg Clayton } 4894b1b8b3eSGreg Clayton } 4907925fbbaSGreg Clayton 491b9c1b51eSKate Stone if (resume) { 49297d5cf05SGreg Clayton if (log) 49397d5cf05SGreg Clayton log->Printf("ProcessKDP::DoResume () sending resume"); 49497d5cf05SGreg Clayton 495b9c1b51eSKate Stone if (m_comm.SendRequestResume()) { 4967925fbbaSGreg Clayton m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue); 4977925fbbaSGreg Clayton SetPrivateState(eStateRunning); 498b9c1b51eSKate Stone } else 49907e66e3eSGreg Clayton error.SetErrorString("KDP resume failed"); 500b9c1b51eSKate Stone } else { 50197d5cf05SGreg Clayton error.SetErrorString("kernel thread is suspended"); 5027925fbbaSGreg Clayton } 5037925fbbaSGreg Clayton 504f9765acdSGreg Clayton return error; 505f9765acdSGreg Clayton } 506f9765acdSGreg Clayton 507b9c1b51eSKate Stone lldb::ThreadSP ProcessKDP::GetKernelThread() { 50897d5cf05SGreg Clayton // KDP only tells us about one thread/core. Any other threads will usually 50997d5cf05SGreg Clayton // be the ones that are read from memory by the OS plug-ins. 510ba4e61d3SAndrew Kaylor 511ba4e61d3SAndrew Kaylor ThreadSP thread_sp(m_kernel_thread_wp.lock()); 512b9c1b51eSKate Stone if (!thread_sp) { 513ba4e61d3SAndrew Kaylor thread_sp.reset(new ThreadKDP(*this, g_kernel_tid)); 514ba4e61d3SAndrew Kaylor m_kernel_thread_wp = thread_sp; 515ba4e61d3SAndrew Kaylor } 51697d5cf05SGreg Clayton return thread_sp; 51797d5cf05SGreg Clayton } 51897d5cf05SGreg Clayton 519b9c1b51eSKate Stone bool ProcessKDP::UpdateThreadList(ThreadList &old_thread_list, 520b9c1b51eSKate Stone ThreadList &new_thread_list) { 521f9765acdSGreg Clayton // locker will keep a mutex locked until it goes out of scope 5225160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_THREAD)); 523250858a0SPavel Labath LLDB_LOGV(log, "pid = {0}", GetID()); 524f9765acdSGreg Clayton 52539da3efdSGreg Clayton // Even though there is a CPU mask, it doesn't mean we can see each CPU 526a868c13cSBruce Mitchener // individually, there is really only one. Lets call this thread 1. 527b9c1b51eSKate Stone ThreadSP thread_sp( 528b9c1b51eSKate Stone old_thread_list.FindThreadByProtocolID(g_kernel_tid, false)); 529ba4e61d3SAndrew Kaylor if (!thread_sp) 530ba4e61d3SAndrew Kaylor thread_sp = GetKernelThread(); 531ba4e61d3SAndrew Kaylor new_thread_list.AddThread(thread_sp); 53297d5cf05SGreg Clayton 5339fc13556SGreg Clayton return new_thread_list.GetSize(false) > 0; 534f9765acdSGreg Clayton } 535f9765acdSGreg Clayton 536b9c1b51eSKate Stone void ProcessKDP::RefreshStateAfterStop() { 53705097246SAdrian Prantl // Let all threads recover from stopping and do any clean up based on the 53805097246SAdrian Prantl // previous thread state (if any). 539f9765acdSGreg Clayton m_thread_list.RefreshStateAfterStop(); 540f9765acdSGreg Clayton } 541f9765acdSGreg Clayton 54297206d57SZachary Turner Status ProcessKDP::DoHalt(bool &caused_stop) { 54397206d57SZachary Turner Status error; 544f9765acdSGreg Clayton 545b9c1b51eSKate Stone if (m_comm.IsRunning()) { 546b9c1b51eSKate Stone if (m_destroy_in_process) { 5474ebdee0aSBruce Mitchener // If we are attempting to destroy, we need to not return an error to Halt 54805097246SAdrian Prantl // or DoDestroy won't get called. We are also currently running, so send 54905097246SAdrian Prantl // a process stopped event 55097d5cf05SGreg Clayton SetPrivateState(eStateStopped); 551b9c1b51eSKate Stone } else { 55297d5cf05SGreg Clayton error.SetErrorString("KDP cannot interrupt a running kernel"); 553f9765acdSGreg Clayton } 554f9765acdSGreg Clayton } 555f9765acdSGreg Clayton return error; 556f9765acdSGreg Clayton } 557f9765acdSGreg Clayton 55897206d57SZachary Turner Status ProcessKDP::DoDetach(bool keep_stopped) { 55997206d57SZachary Turner Status error; 5605160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 561f9765acdSGreg Clayton if (log) 562acff8950SJim Ingham log->Printf("ProcessKDP::DoDetach(keep_stopped = %i)", keep_stopped); 563f9765acdSGreg Clayton 564b9c1b51eSKate Stone if (m_comm.IsRunning()) { 56505097246SAdrian Prantl // We are running and we can't interrupt a running kernel, so we need to 56605097246SAdrian Prantl // just close the connection to the kernel and hope for the best 567b9c1b51eSKate Stone } else { 568b9c1b51eSKate Stone // If we are going to keep the target stopped, then don't send the 569b9c1b51eSKate Stone // disconnect message. 570b9c1b51eSKate Stone if (!keep_stopped && m_comm.IsConnected()) { 5716e0ff1a3SGreg Clayton const bool success = m_comm.SendRequestDisconnect(); 572b9c1b51eSKate Stone if (log) { 5736e0ff1a3SGreg Clayton if (success) 574b9c1b51eSKate Stone log->PutCString( 575b9c1b51eSKate Stone "ProcessKDP::DoDetach() detach packet sent successfully"); 576f9765acdSGreg Clayton else 577b9c1b51eSKate Stone log->PutCString( 578b9c1b51eSKate Stone "ProcessKDP::DoDetach() connection channel shutdown failed"); 579f9765acdSGreg Clayton } 5806e0ff1a3SGreg Clayton m_comm.Disconnect(); 5813a29bdbeSGreg Clayton } 58297d5cf05SGreg Clayton } 583f9765acdSGreg Clayton StopAsyncThread(); 58474d4193eSGreg Clayton m_comm.Clear(); 585f9765acdSGreg Clayton 586f9765acdSGreg Clayton SetPrivateState(eStateDetached); 587f9765acdSGreg Clayton ResumePrivateStateThread(); 588f9765acdSGreg Clayton 589f9765acdSGreg Clayton // KillDebugserverProcess (); 590f9765acdSGreg Clayton return error; 591f9765acdSGreg Clayton } 592f9765acdSGreg Clayton 59397206d57SZachary Turner Status ProcessKDP::DoDestroy() { 5947925fbbaSGreg Clayton // For KDP there really is no difference between destroy and detach 595acff8950SJim Ingham bool keep_stopped = false; 596acff8950SJim Ingham return DoDetach(keep_stopped); 597f9765acdSGreg Clayton } 598f9765acdSGreg Clayton 599f9765acdSGreg Clayton //------------------------------------------------------------------ 600f9765acdSGreg Clayton // Process Queries 601f9765acdSGreg Clayton //------------------------------------------------------------------ 602f9765acdSGreg Clayton 603b9c1b51eSKate Stone bool ProcessKDP::IsAlive() { 604a814f704SJason Molenda return m_comm.IsConnected() && Process::IsAlive(); 605f9765acdSGreg Clayton } 606f9765acdSGreg Clayton 607f9765acdSGreg Clayton //------------------------------------------------------------------ 608f9765acdSGreg Clayton // Process Memory 609f9765acdSGreg Clayton //------------------------------------------------------------------ 610b9c1b51eSKate Stone size_t ProcessKDP::DoReadMemory(addr_t addr, void *buf, size_t size, 61197206d57SZachary Turner Status &error) { 6128eb32817SJason Molenda uint8_t *data_buffer = (uint8_t *)buf; 613b9c1b51eSKate Stone if (m_comm.IsConnected()) { 6148eb32817SJason Molenda const size_t max_read_size = 512; 6158eb32817SJason Molenda size_t total_bytes_read = 0; 6168eb32817SJason Molenda 6178eb32817SJason Molenda // Read the requested amount of memory in 512 byte chunks 618b9c1b51eSKate Stone while (total_bytes_read < size) { 6198eb32817SJason Molenda size_t bytes_to_read_this_request = size - total_bytes_read; 620b9c1b51eSKate Stone if (bytes_to_read_this_request > max_read_size) { 6218eb32817SJason Molenda bytes_to_read_this_request = max_read_size; 6228eb32817SJason Molenda } 623b9c1b51eSKate Stone size_t bytes_read = m_comm.SendRequestReadMemory( 624b9c1b51eSKate Stone addr + total_bytes_read, data_buffer + total_bytes_read, 6258eb32817SJason Molenda bytes_to_read_this_request, error); 6268eb32817SJason Molenda total_bytes_read += bytes_read; 627b9c1b51eSKate Stone if (error.Fail() || bytes_read == 0) { 6288eb32817SJason Molenda return total_bytes_read; 6298eb32817SJason Molenda } 6308eb32817SJason Molenda } 6318eb32817SJason Molenda 6328eb32817SJason Molenda return total_bytes_read; 6338eb32817SJason Molenda } 634a63d08c9SGreg Clayton error.SetErrorString("not connected"); 635f9765acdSGreg Clayton return 0; 636f9765acdSGreg Clayton } 637f9765acdSGreg Clayton 638b9c1b51eSKate Stone size_t ProcessKDP::DoWriteMemory(addr_t addr, const void *buf, size_t size, 63997206d57SZachary Turner Status &error) { 6407925fbbaSGreg Clayton if (m_comm.IsConnected()) 6417925fbbaSGreg Clayton return m_comm.SendRequestWriteMemory(addr, buf, size, error); 6427925fbbaSGreg Clayton error.SetErrorString("not connected"); 643f9765acdSGreg Clayton return 0; 644f9765acdSGreg Clayton } 645f9765acdSGreg Clayton 646b9c1b51eSKate Stone lldb::addr_t ProcessKDP::DoAllocateMemory(size_t size, uint32_t permissions, 64797206d57SZachary Turner Status &error) { 648b9c1b51eSKate Stone error.SetErrorString( 6494ebdee0aSBruce Mitchener "memory allocation not supported in kdp remote debugging"); 650f9765acdSGreg Clayton return LLDB_INVALID_ADDRESS; 651f9765acdSGreg Clayton } 652f9765acdSGreg Clayton 65397206d57SZachary Turner Status ProcessKDP::DoDeallocateMemory(lldb::addr_t addr) { 65497206d57SZachary Turner Status error; 655b9c1b51eSKate Stone error.SetErrorString( 6564ebdee0aSBruce Mitchener "memory deallocation not supported in kdp remote debugging"); 657f9765acdSGreg Clayton return error; 658f9765acdSGreg Clayton } 659f9765acdSGreg Clayton 66097206d57SZachary Turner Status ProcessKDP::EnableBreakpointSite(BreakpointSite *bp_site) { 661b9c1b51eSKate Stone if (m_comm.LocalBreakpointsAreSupported()) { 66297206d57SZachary Turner Status error; 663b9c1b51eSKate Stone if (!bp_site->IsEnabled()) { 664b9c1b51eSKate Stone if (m_comm.SendRequestBreakpoint(true, bp_site->GetLoadAddress())) { 6655b88216dSGreg Clayton bp_site->SetEnabled(true); 6665b88216dSGreg Clayton bp_site->SetType(BreakpointSite::eExternal); 667b9c1b51eSKate Stone } else { 66807e66e3eSGreg Clayton error.SetErrorString("KDP set breakpoint failed"); 6695b88216dSGreg Clayton } 6705b88216dSGreg Clayton } 67107e66e3eSGreg Clayton return error; 67207e66e3eSGreg Clayton } 673f9765acdSGreg Clayton return EnableSoftwareBreakpoint(bp_site); 674f9765acdSGreg Clayton } 675f9765acdSGreg Clayton 67697206d57SZachary Turner Status ProcessKDP::DisableBreakpointSite(BreakpointSite *bp_site) { 677b9c1b51eSKate Stone if (m_comm.LocalBreakpointsAreSupported()) { 67897206d57SZachary Turner Status error; 679b9c1b51eSKate Stone if (bp_site->IsEnabled()) { 6805b88216dSGreg Clayton BreakpointSite::Type bp_type = bp_site->GetType(); 681b9c1b51eSKate Stone if (bp_type == BreakpointSite::eExternal) { 682b9c1b51eSKate Stone if (m_destroy_in_process && m_comm.IsRunning()) { 68397d5cf05SGreg Clayton // We are trying to destroy our connection and we are running 68497d5cf05SGreg Clayton bp_site->SetEnabled(false); 685b9c1b51eSKate Stone } else { 6865b88216dSGreg Clayton if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress())) 6875b88216dSGreg Clayton bp_site->SetEnabled(false); 6885b88216dSGreg Clayton else 68907e66e3eSGreg Clayton error.SetErrorString("KDP remove breakpoint failed"); 6905b88216dSGreg Clayton } 691b9c1b51eSKate Stone } else { 6925b88216dSGreg Clayton error = DisableSoftwareBreakpoint(bp_site); 6935b88216dSGreg Clayton } 6945b88216dSGreg Clayton } 69507e66e3eSGreg Clayton return error; 69607e66e3eSGreg Clayton } 697f9765acdSGreg Clayton return DisableSoftwareBreakpoint(bp_site); 698f9765acdSGreg Clayton } 699f9765acdSGreg Clayton 70097206d57SZachary Turner Status ProcessKDP::EnableWatchpoint(Watchpoint *wp, bool notify) { 70197206d57SZachary Turner Status error; 702b9c1b51eSKate Stone error.SetErrorString( 7034ebdee0aSBruce Mitchener "watchpoints are not supported in kdp remote debugging"); 704f9765acdSGreg Clayton return error; 705f9765acdSGreg Clayton } 706f9765acdSGreg Clayton 70797206d57SZachary Turner Status ProcessKDP::DisableWatchpoint(Watchpoint *wp, bool notify) { 70897206d57SZachary Turner Status error; 709b9c1b51eSKate Stone error.SetErrorString( 7104ebdee0aSBruce Mitchener "watchpoints are not supported in kdp remote debugging"); 711f9765acdSGreg Clayton return error; 712f9765acdSGreg Clayton } 713f9765acdSGreg Clayton 714b9c1b51eSKate Stone void ProcessKDP::Clear() { m_thread_list.Clear(); } 715f9765acdSGreg Clayton 71697206d57SZachary Turner Status ProcessKDP::DoSignal(int signo) { 71797206d57SZachary Turner Status error; 718b9c1b51eSKate Stone error.SetErrorString( 7194ebdee0aSBruce Mitchener "sending signals is not supported in kdp remote debugging"); 720f9765acdSGreg Clayton return error; 721f9765acdSGreg Clayton } 722f9765acdSGreg Clayton 723b9c1b51eSKate Stone void ProcessKDP::Initialize() { 724c5f28e2aSKamil Rytarowski static llvm::once_flag g_once_flag; 725f9765acdSGreg Clayton 726c5f28e2aSKamil Rytarowski llvm::call_once(g_once_flag, []() { 727f9765acdSGreg Clayton PluginManager::RegisterPlugin(GetPluginNameStatic(), 728b9c1b51eSKate Stone GetPluginDescriptionStatic(), CreateInstance, 729488c89edSBruce Mitchener DebuggerInitialize); 730f9765acdSGreg Clayton 7317b35b781SPavel Labath ProcessKDPLog::Initialize(); 732c8d69828SDavide Italiano }); 733f9765acdSGreg Clayton } 734f9765acdSGreg Clayton 735b9c1b51eSKate Stone void ProcessKDP::DebuggerInitialize(lldb_private::Debugger &debugger) { 736b9c1b51eSKate Stone if (!PluginManager::GetSettingForProcessPlugin( 737b9c1b51eSKate Stone debugger, PluginProperties::GetSettingName())) { 7387f98240dSGreg Clayton const bool is_global_setting = true; 739b9c1b51eSKate Stone PluginManager::CreateSettingForProcessPlugin( 740b9c1b51eSKate Stone debugger, GetGlobalPluginProperties()->GetValueProperties(), 7417f98240dSGreg Clayton ConstString("Properties for the kdp-remote process plug-in."), 7427f98240dSGreg Clayton is_global_setting); 7437f98240dSGreg Clayton } 7447f98240dSGreg Clayton } 7457f98240dSGreg Clayton 746b9c1b51eSKate Stone bool ProcessKDP::StartAsyncThread() { 7475160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 748f9765acdSGreg Clayton 749f9765acdSGreg Clayton if (log) 7507925fbbaSGreg Clayton log->Printf("ProcessKDP::StartAsyncThread ()"); 751f9765acdSGreg Clayton 752acee96aeSZachary Turner if (m_async_thread.IsJoinable()) 7537925fbbaSGreg Clayton return true; 7547925fbbaSGreg Clayton 755b9c1b51eSKate Stone m_async_thread = ThreadLauncher::LaunchThread( 756b9c1b51eSKate Stone "<lldb.process.kdp-remote.async>", ProcessKDP::AsyncThread, this, NULL); 757acee96aeSZachary Turner return m_async_thread.IsJoinable(); 758f9765acdSGreg Clayton } 759f9765acdSGreg Clayton 760b9c1b51eSKate Stone void ProcessKDP::StopAsyncThread() { 7615160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 762f9765acdSGreg Clayton 763f9765acdSGreg Clayton if (log) 7647925fbbaSGreg Clayton log->Printf("ProcessKDP::StopAsyncThread ()"); 765f9765acdSGreg Clayton 766f9765acdSGreg Clayton m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit); 767f9765acdSGreg Clayton 768f9765acdSGreg Clayton // Stop the stdio thread 769acee96aeSZachary Turner if (m_async_thread.IsJoinable()) 77039de3110SZachary Turner m_async_thread.Join(nullptr); 771f9765acdSGreg Clayton } 772f9765acdSGreg Clayton 773b9c1b51eSKate Stone void *ProcessKDP::AsyncThread(void *arg) { 774f9765acdSGreg Clayton ProcessKDP *process = (ProcessKDP *)arg; 775f9765acdSGreg Clayton 7767925fbbaSGreg Clayton const lldb::pid_t pid = process->GetID(); 7777925fbbaSGreg Clayton 7785160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 779f9765acdSGreg Clayton if (log) 780b9c1b51eSKate Stone log->Printf("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 781b9c1b51eSKate Stone ") thread starting...", 782b9c1b51eSKate Stone arg, pid); 783f9765acdSGreg Clayton 784583bbb1dSJim Ingham ListenerSP listener_sp(Listener::MakeListener("ProcessKDP::AsyncThread")); 785f9765acdSGreg Clayton EventSP event_sp; 786b9c1b51eSKate Stone const uint32_t desired_event_mask = 787b9c1b51eSKate Stone eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit; 788f9765acdSGreg Clayton 789b9c1b51eSKate Stone if (listener_sp->StartListeningForEvents(&process->m_async_broadcaster, 790b9c1b51eSKate Stone desired_event_mask) == 791b9c1b51eSKate Stone desired_event_mask) { 792f9765acdSGreg Clayton bool done = false; 793b9c1b51eSKate Stone while (!done) { 794f9765acdSGreg Clayton if (log) 795b9c1b51eSKate Stone log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 796b9c1b51eSKate Stone ") listener.WaitForEvent (NULL, event_sp)...", 7977925fbbaSGreg Clayton pid); 798fafff0c5SPavel Labath if (listener_sp->GetEvent(event_sp, llvm::None)) { 7997925fbbaSGreg Clayton uint32_t event_type = event_sp->GetType(); 800f9765acdSGreg Clayton if (log) 801b9c1b51eSKate Stone log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 802b9c1b51eSKate Stone ") Got an event of type: %d...", 803b9c1b51eSKate Stone pid, event_type); 804f9765acdSGreg Clayton 8057925fbbaSGreg Clayton // When we are running, poll for 1 second to try and get an exception 8067925fbbaSGreg Clayton // to indicate the process has stopped. If we don't get one, check to 8077925fbbaSGreg Clayton // make sure no one asked us to exit 8087925fbbaSGreg Clayton bool is_running = false; 8097925fbbaSGreg Clayton DataExtractor exc_reply_packet; 810b9c1b51eSKate Stone do { 811b9c1b51eSKate Stone switch (event_type) { 812b9c1b51eSKate Stone case eBroadcastBitAsyncContinue: { 8137925fbbaSGreg Clayton is_running = true; 814b9c1b51eSKate Stone if (process->m_comm.WaitForPacketWithTimeoutMicroSeconds( 815b9c1b51eSKate Stone exc_reply_packet, 1 * USEC_PER_SEC)) { 816ba4e61d3SAndrew Kaylor ThreadSP thread_sp(process->GetKernelThread()); 817b9c1b51eSKate Stone if (thread_sp) { 818b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 819b9c1b51eSKate Stone thread_sp->GetRegisterContext()); 8201afa68edSGreg Clayton if (reg_ctx_sp) 8211afa68edSGreg Clayton reg_ctx_sp->InvalidateAllRegisters(); 822b9c1b51eSKate Stone static_cast<ThreadKDP *>(thread_sp.get()) 823b9c1b51eSKate Stone ->SetStopInfoFrom_KDP_EXCEPTION(exc_reply_packet); 8241afa68edSGreg Clayton } 82597d5cf05SGreg Clayton 8267925fbbaSGreg Clayton // TODO: parse the stop reply packet 8277925fbbaSGreg Clayton is_running = false; 8287925fbbaSGreg Clayton process->SetPrivateState(eStateStopped); 829b9c1b51eSKate Stone } else { 8307925fbbaSGreg Clayton // Check to see if we are supposed to exit. There is no way to 8317925fbbaSGreg Clayton // interrupt a running kernel, so all we can do is wait for an 8327925fbbaSGreg Clayton // exception or detach... 833fafff0c5SPavel Labath if (listener_sp->GetEvent(event_sp, 834fafff0c5SPavel Labath std::chrono::microseconds(0))) { 8357925fbbaSGreg Clayton // We got an event, go through the loop again 8367925fbbaSGreg Clayton event_type = event_sp->GetType(); 8377925fbbaSGreg Clayton } 838f9765acdSGreg Clayton } 839b9c1b51eSKate Stone } break; 840f9765acdSGreg Clayton 841f9765acdSGreg Clayton case eBroadcastBitAsyncThreadShouldExit: 842f9765acdSGreg Clayton if (log) 843b9c1b51eSKate Stone log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 844b9c1b51eSKate Stone ") got eBroadcastBitAsyncThreadShouldExit...", 8457925fbbaSGreg Clayton pid); 846f9765acdSGreg Clayton done = true; 8477925fbbaSGreg Clayton is_running = false; 848f9765acdSGreg Clayton break; 849f9765acdSGreg Clayton 850f9765acdSGreg Clayton default: 851f9765acdSGreg Clayton if (log) 852b9c1b51eSKate Stone log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 853b9c1b51eSKate Stone ") got unknown event 0x%8.8x", 854b9c1b51eSKate Stone pid, event_type); 855f9765acdSGreg Clayton done = true; 8567925fbbaSGreg Clayton is_running = false; 857f9765acdSGreg Clayton break; 858f9765acdSGreg Clayton } 8597925fbbaSGreg Clayton } while (is_running); 860b9c1b51eSKate Stone } else { 861f9765acdSGreg Clayton if (log) 862b9c1b51eSKate Stone log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 863b9c1b51eSKate Stone ") listener.WaitForEvent (NULL, event_sp) => false", 8647925fbbaSGreg Clayton pid); 865f9765acdSGreg Clayton done = true; 866f9765acdSGreg Clayton } 867f9765acdSGreg Clayton } 868f9765acdSGreg Clayton } 869f9765acdSGreg Clayton 870f9765acdSGreg Clayton if (log) 871b9c1b51eSKate Stone log->Printf("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 872b9c1b51eSKate Stone ") thread exiting...", 873b9c1b51eSKate Stone arg, pid); 874f9765acdSGreg Clayton 87539de3110SZachary Turner process->m_async_thread.Reset(); 876f9765acdSGreg Clayton return NULL; 877f9765acdSGreg Clayton } 878f9765acdSGreg Clayton 879b9c1b51eSKate Stone class CommandObjectProcessKDPPacketSend : public CommandObjectParsed { 8801d19a2f2SGreg Clayton private: 8811d19a2f2SGreg Clayton OptionGroupOptions m_option_group; 8821d19a2f2SGreg Clayton OptionGroupUInt64 m_command_byte; 8831d19a2f2SGreg Clayton OptionGroupString m_packet_data; 8841d19a2f2SGreg Clayton 885b9c1b51eSKate Stone virtual Options *GetOptions() { return &m_option_group; } 8861d19a2f2SGreg Clayton 8871d19a2f2SGreg Clayton public: 888b9c1b51eSKate Stone CommandObjectProcessKDPPacketSend(CommandInterpreter &interpreter) 889b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "process plugin packet send", 890b9c1b51eSKate Stone "Send a custom packet through the KDP protocol by " 891b9c1b51eSKate Stone "specifying the command byte and the packet " 892b9c1b51eSKate Stone "payload data. A packet will be sent with a " 893b9c1b51eSKate Stone "correct header and payload, and the raw result " 894b9c1b51eSKate Stone "bytes will be displayed as a string value. ", 8951d19a2f2SGreg Clayton NULL), 896e1cfbc79STodd Fiala m_option_group(), 897b9c1b51eSKate Stone m_command_byte(LLDB_OPT_SET_1, true, "command", 'c', 0, eArgTypeNone, 898b9c1b51eSKate Stone "Specify the command byte to use when sending the KDP " 899b9c1b51eSKate Stone "request packet.", 900b9c1b51eSKate Stone 0), 901b9c1b51eSKate Stone m_packet_data(LLDB_OPT_SET_1, false, "payload", 'p', 0, eArgTypeNone, 902b9c1b51eSKate Stone "Specify packet payload bytes as a hex ASCII string with " 903b9c1b51eSKate Stone "no spaces or hex prefixes.", 904b9c1b51eSKate Stone NULL) { 9051d19a2f2SGreg Clayton m_option_group.Append(&m_command_byte, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 9061d19a2f2SGreg Clayton m_option_group.Append(&m_packet_data, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 9071d19a2f2SGreg Clayton m_option_group.Finalize(); 9081d19a2f2SGreg Clayton } 9091d19a2f2SGreg Clayton 910b9c1b51eSKate Stone ~CommandObjectProcessKDPPacketSend() {} 9111d19a2f2SGreg Clayton 912b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) { 9131d19a2f2SGreg Clayton const size_t argc = command.GetArgumentCount(); 914b9c1b51eSKate Stone if (argc == 0) { 915b9c1b51eSKate Stone if (!m_command_byte.GetOptionValue().OptionWasSet()) { 916b9c1b51eSKate Stone result.AppendError( 917b9c1b51eSKate Stone "the --command option must be set to a valid command byte"); 9181d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 919b9c1b51eSKate Stone } else { 920b9c1b51eSKate Stone const uint64_t command_byte = 921b9c1b51eSKate Stone m_command_byte.GetOptionValue().GetUInt64Value(0); 922b9c1b51eSKate Stone if (command_byte > 0 && command_byte <= UINT8_MAX) { 923b9c1b51eSKate Stone ProcessKDP *process = 924b9c1b51eSKate Stone (ProcessKDP *)m_interpreter.GetExecutionContext().GetProcessPtr(); 925b9c1b51eSKate Stone if (process) { 9261d19a2f2SGreg Clayton const StateType state = process->GetState(); 9271d19a2f2SGreg Clayton 928b9c1b51eSKate Stone if (StateIsStoppedState(state, true)) { 9291d19a2f2SGreg Clayton std::vector<uint8_t> payload_bytes; 930b9c1b51eSKate Stone const char *ascii_hex_bytes_cstr = 931b9c1b51eSKate Stone m_packet_data.GetOptionValue().GetCurrentValue(); 932b9c1b51eSKate Stone if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0]) { 9331d19a2f2SGreg Clayton StringExtractor extractor(ascii_hex_bytes_cstr); 934b9c1b51eSKate Stone const size_t ascii_hex_bytes_cstr_len = 935b9c1b51eSKate Stone extractor.GetStringRef().size(); 936b9c1b51eSKate Stone if (ascii_hex_bytes_cstr_len & 1) { 937b9c1b51eSKate Stone result.AppendErrorWithFormat("payload data must contain an " 938b9c1b51eSKate Stone "even number of ASCII hex " 939b9c1b51eSKate Stone "characters: '%s'", 940b9c1b51eSKate Stone ascii_hex_bytes_cstr); 9411d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9421d19a2f2SGreg Clayton return false; 9431d19a2f2SGreg Clayton } 9441d19a2f2SGreg Clayton payload_bytes.resize(ascii_hex_bytes_cstr_len / 2); 945b9c1b51eSKate Stone if (extractor.GetHexBytes(payload_bytes, '\xdd') != 946b9c1b51eSKate Stone payload_bytes.size()) { 947b9c1b51eSKate Stone result.AppendErrorWithFormat("payload data must only contain " 948b9c1b51eSKate Stone "ASCII hex characters (no " 949b9c1b51eSKate Stone "spaces or hex prefixes): '%s'", 950b9c1b51eSKate Stone ascii_hex_bytes_cstr); 9511d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9521d19a2f2SGreg Clayton return false; 9531d19a2f2SGreg Clayton } 9541d19a2f2SGreg Clayton } 95597206d57SZachary Turner Status error; 9561d19a2f2SGreg Clayton DataExtractor reply; 957b9c1b51eSKate Stone process->GetCommunication().SendRawRequest( 958b9c1b51eSKate Stone command_byte, 9591d19a2f2SGreg Clayton payload_bytes.empty() ? NULL : payload_bytes.data(), 960b9c1b51eSKate Stone payload_bytes.size(), reply, error); 9611d19a2f2SGreg Clayton 962b9c1b51eSKate Stone if (error.Success()) { 9631d19a2f2SGreg Clayton // Copy the binary bytes into a hex ASCII string for the result 9641d19a2f2SGreg Clayton StreamString packet; 965b9c1b51eSKate Stone packet.PutBytesAsRawHex8( 966b9c1b51eSKate Stone reply.GetDataStart(), reply.GetByteSize(), 967b9c1b51eSKate Stone endian::InlHostByteOrder(), endian::InlHostByteOrder()); 968c156427dSZachary Turner result.AppendMessage(packet.GetString()); 9691d19a2f2SGreg Clayton result.SetStatus(eReturnStatusSuccessFinishResult); 9701d19a2f2SGreg Clayton return true; 971b9c1b51eSKate Stone } else { 9721d19a2f2SGreg Clayton const char *error_cstr = error.AsCString(); 9731d19a2f2SGreg Clayton if (error_cstr && error_cstr[0]) 9741d19a2f2SGreg Clayton result.AppendError(error_cstr); 9751d19a2f2SGreg Clayton else 976b9c1b51eSKate Stone result.AppendErrorWithFormat("unknown error 0x%8.8x", 977b9c1b51eSKate Stone error.GetError()); 9781d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9791d19a2f2SGreg Clayton return false; 9801d19a2f2SGreg Clayton } 981b9c1b51eSKate Stone } else { 982b9c1b51eSKate Stone result.AppendErrorWithFormat("process must be stopped in order " 983b9c1b51eSKate Stone "to send KDP packets, state is %s", 984b9c1b51eSKate Stone StateAsCString(state)); 9851d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9861d19a2f2SGreg Clayton } 987b9c1b51eSKate Stone } else { 9881d19a2f2SGreg Clayton result.AppendError("invalid process"); 9891d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9901d19a2f2SGreg Clayton } 991b9c1b51eSKate Stone } else { 992b9c1b51eSKate Stone result.AppendErrorWithFormat("invalid command byte 0x%" PRIx64 993b9c1b51eSKate Stone ", valid values are 1 - 255", 994b9c1b51eSKate Stone command_byte); 9951d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9961d19a2f2SGreg Clayton } 9971d19a2f2SGreg Clayton } 998b9c1b51eSKate Stone } else { 999b9c1b51eSKate Stone result.AppendErrorWithFormat("'%s' takes no arguments, only options.", 1000b9c1b51eSKate Stone m_cmd_name.c_str()); 10011d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 10021d19a2f2SGreg Clayton } 10031d19a2f2SGreg Clayton return false; 10041d19a2f2SGreg Clayton } 10051d19a2f2SGreg Clayton }; 10061d19a2f2SGreg Clayton 1007b9c1b51eSKate Stone class CommandObjectProcessKDPPacket : public CommandObjectMultiword { 10081d19a2f2SGreg Clayton private: 10091d19a2f2SGreg Clayton public: 1010b9c1b51eSKate Stone CommandObjectProcessKDPPacket(CommandInterpreter &interpreter) 1011b9c1b51eSKate Stone : CommandObjectMultiword(interpreter, "process plugin packet", 10121d19a2f2SGreg Clayton "Commands that deal with KDP remote packets.", 1013b9c1b51eSKate Stone NULL) { 1014b9c1b51eSKate Stone LoadSubCommand( 1015b9c1b51eSKate Stone "send", 1016b9c1b51eSKate Stone CommandObjectSP(new CommandObjectProcessKDPPacketSend(interpreter))); 10171d19a2f2SGreg Clayton } 10181d19a2f2SGreg Clayton 1019b9c1b51eSKate Stone ~CommandObjectProcessKDPPacket() {} 10201d19a2f2SGreg Clayton }; 10211d19a2f2SGreg Clayton 1022b9c1b51eSKate Stone class CommandObjectMultiwordProcessKDP : public CommandObjectMultiword { 10231d19a2f2SGreg Clayton public: 10247428a18cSKate Stone CommandObjectMultiwordProcessKDP(CommandInterpreter &interpreter) 1025b9c1b51eSKate Stone : CommandObjectMultiword( 1026b9c1b51eSKate Stone interpreter, "process plugin", 1027b9c1b51eSKate Stone "Commands for operating on a ProcessKDP process.", 1028b9c1b51eSKate Stone "process plugin <subcommand> [<subcommand-options>]") { 1029b9c1b51eSKate Stone LoadSubCommand("packet", CommandObjectSP(new CommandObjectProcessKDPPacket( 1030b9c1b51eSKate Stone interpreter))); 10311d19a2f2SGreg Clayton } 10321d19a2f2SGreg Clayton 1033b9c1b51eSKate Stone ~CommandObjectMultiwordProcessKDP() {} 10341d19a2f2SGreg Clayton }; 10351d19a2f2SGreg Clayton 1036b9c1b51eSKate Stone CommandObject *ProcessKDP::GetPluginCommandObject() { 10371d19a2f2SGreg Clayton if (!m_command_sp) 1038b9c1b51eSKate Stone m_command_sp.reset(new CommandObjectMultiwordProcessKDP( 1039b9c1b51eSKate Stone GetTarget().GetDebugger().GetCommandInterpreter())); 10401d19a2f2SGreg Clayton return m_command_sp.get(); 10411d19a2f2SGreg Clayton } 1042