159ec512cSGreg Clayton //===-- ProcessKDP.cpp ------------------------------------------*- C++ -*-===// 2f9765acdSGreg Clayton // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6f9765acdSGreg Clayton // 7f9765acdSGreg Clayton //===----------------------------------------------------------------------===// 8f9765acdSGreg Clayton 9f9765acdSGreg Clayton #include <errno.h> 10f9765acdSGreg Clayton #include <stdlib.h> 11f9765acdSGreg Clayton 12796ac80bSJonas Devlieghere #include <memory> 133f69fa6fSBenjamin Kramer #include <mutex> 143f69fa6fSBenjamin Kramer 1507e66e3eSGreg Clayton #include "lldb/Core/Debugger.h" 161f746071SGreg Clayton #include "lldb/Core/Module.h" 174bd4e7e3SJason Molenda #include "lldb/Core/ModuleSpec.h" 18b9c1b51eSKate Stone #include "lldb/Core/PluginManager.h" 1993a66fc1SZachary Turner #include "lldb/Host/ConnectionFileDescriptor.h" 20f9765acdSGreg Clayton #include "lldb/Host/Host.h" 2139de3110SZachary Turner #include "lldb/Host/ThreadLauncher.h" 22e98628ceSOleksiy Vyalov #include "lldb/Host/common/TCPSocket.h" 231d19a2f2SGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 241d19a2f2SGreg Clayton #include "lldb/Interpreter/CommandObject.h" 251d19a2f2SGreg Clayton #include "lldb/Interpreter/CommandObjectMultiword.h" 261d19a2f2SGreg Clayton #include "lldb/Interpreter/CommandReturnObject.h" 271d19a2f2SGreg Clayton #include "lldb/Interpreter/OptionGroupString.h" 281d19a2f2SGreg Clayton #include "lldb/Interpreter/OptionGroupUInt64.h" 2941204d09SIlia K #include "lldb/Interpreter/OptionValueProperties.h" 3080552918SZachary Turner #include "lldb/Symbol/LocateSymbolFile.h" 311f746071SGreg Clayton #include "lldb/Symbol/ObjectFile.h" 327925fbbaSGreg Clayton #include "lldb/Target/RegisterContext.h" 3357508026SGreg Clayton #include "lldb/Target/Target.h" 34a63d08c9SGreg Clayton #include "lldb/Target/Thread.h" 35f39c2e18SJonas Devlieghere #include "lldb/Utility/Log.h" 36d821c997SPavel Labath #include "lldb/Utility/State.h" 3745788152SBruce Mitchener #include "lldb/Utility/StringExtractor.h" 38d821c997SPavel Labath #include "lldb/Utility/UUID.h" 39f9765acdSGreg Clayton 40c5f28e2aSKamil Rytarowski #include "llvm/Support/Threading.h" 41c5f28e2aSKamil Rytarowski 42510938e5SCharles Davis #define USEC_PER_SEC 1000000 43510938e5SCharles Davis 44b9c1b51eSKate Stone #include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h" 45b9c1b51eSKate Stone #include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h" 46f9765acdSGreg Clayton #include "ProcessKDP.h" 47f9765acdSGreg Clayton #include "ProcessKDPLog.h" 48a63d08c9SGreg Clayton #include "ThreadKDP.h" 49f9765acdSGreg Clayton 50f9765acdSGreg Clayton using namespace lldb; 51f9765acdSGreg Clayton using namespace lldb_private; 52f9765acdSGreg Clayton 537f98240dSGreg Clayton namespace { 547f98240dSGreg Clayton 55971f9ca6SJonas Devlieghere #define LLDB_PROPERTIES_processkdp 56971f9ca6SJonas Devlieghere #include "Properties.inc" 577f98240dSGreg Clayton 58971f9ca6SJonas Devlieghere enum { 59971f9ca6SJonas Devlieghere #define LLDB_PROPERTIES_processkdp 60971f9ca6SJonas Devlieghere #include "PropertiesEnum.inc" 61971f9ca6SJonas Devlieghere }; 627f98240dSGreg Clayton 63b9c1b51eSKate Stone class PluginProperties : public Properties { 647f98240dSGreg Clayton public: 65b9c1b51eSKate Stone static ConstString GetSettingName() { 667f98240dSGreg Clayton return ProcessKDP::GetPluginNameStatic(); 677f98240dSGreg Clayton } 687f98240dSGreg Clayton 69b9c1b51eSKate Stone PluginProperties() : Properties() { 70796ac80bSJonas Devlieghere m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); 71*a8ea5955SJonas Devlieghere m_collection_sp->Initialize(g_processkdp_properties); 727f98240dSGreg Clayton } 737f98240dSGreg Clayton 74b9c1b51eSKate Stone virtual ~PluginProperties() {} 757f98240dSGreg Clayton 76b9c1b51eSKate Stone uint64_t GetPacketTimeout() { 77971f9ca6SJonas Devlieghere const uint32_t idx = ePropertyKDPPacketTimeout; 78b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsUInt64( 79*a8ea5955SJonas Devlieghere NULL, idx, g_processkdp_properties[idx].default_uint_value); 807f98240dSGreg Clayton } 817f98240dSGreg Clayton }; 827f98240dSGreg Clayton 837f98240dSGreg Clayton typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP; 847f98240dSGreg Clayton 85b9c1b51eSKate Stone static const ProcessKDPPropertiesSP &GetGlobalPluginProperties() { 867f98240dSGreg Clayton static ProcessKDPPropertiesSP g_settings_sp; 877f98240dSGreg Clayton if (!g_settings_sp) 88796ac80bSJonas Devlieghere g_settings_sp = std::make_shared<PluginProperties>(); 897f98240dSGreg Clayton return g_settings_sp; 907f98240dSGreg Clayton } 917f98240dSGreg Clayton 927f98240dSGreg Clayton } // anonymous namespace end 937f98240dSGreg Clayton 94ba4e61d3SAndrew Kaylor static const lldb::tid_t g_kernel_tid = 1; 95ba4e61d3SAndrew Kaylor 96b9c1b51eSKate Stone ConstString ProcessKDP::GetPluginNameStatic() { 9757abc5d6SGreg Clayton static ConstString g_name("kdp-remote"); 9857abc5d6SGreg Clayton return g_name; 99f9765acdSGreg Clayton } 100f9765acdSGreg Clayton 101b9c1b51eSKate Stone const char *ProcessKDP::GetPluginDescriptionStatic() { 102b9c1b51eSKate Stone return "KDP Remote protocol based debugging plug-in for darwin kernel " 103b9c1b51eSKate Stone "debugging."; 104f9765acdSGreg Clayton } 105f9765acdSGreg Clayton 106b9c1b51eSKate Stone void ProcessKDP::Terminate() { 107f9765acdSGreg Clayton PluginManager::UnregisterPlugin(ProcessKDP::CreateInstance); 108f9765acdSGreg Clayton } 109f9765acdSGreg Clayton 110b9c1b51eSKate Stone lldb::ProcessSP ProcessKDP::CreateInstance(TargetSP target_sp, 111583bbb1dSJim Ingham ListenerSP listener_sp, 112b9c1b51eSKate Stone const FileSpec *crash_file_path) { 113c3776bf2SGreg Clayton lldb::ProcessSP process_sp; 114c3776bf2SGreg Clayton if (crash_file_path == NULL) 115796ac80bSJonas Devlieghere process_sp = std::make_shared<ProcessKDP>(target_sp, listener_sp); 116c3776bf2SGreg Clayton return process_sp; 117f9765acdSGreg Clayton } 118f9765acdSGreg Clayton 119b9c1b51eSKate Stone bool ProcessKDP::CanDebug(TargetSP target_sp, bool plugin_specified_by_name) { 120596ed24eSGreg Clayton if (plugin_specified_by_name) 121596ed24eSGreg Clayton return true; 122596ed24eSGreg Clayton 123f9765acdSGreg Clayton // For now we are just making sure the file exists for a given module 1245a3bb64fSJim Ingham Module *exe_module = target_sp->GetExecutableModulePointer(); 125b9c1b51eSKate Stone if (exe_module) { 1265a3bb64fSJim Ingham const llvm::Triple &triple_ref = target_sp->GetArchitecture().GetTriple(); 127b9c1b51eSKate Stone switch (triple_ref.getOS()) { 128b9c1b51eSKate Stone case llvm::Triple::Darwin: // Should use "macosx" for desktop and "ios" for 129b9c1b51eSKate Stone // iOS, but accept darwin just in case 13070512317SGreg Clayton case llvm::Triple::MacOSX: // For desktop targets 13170512317SGreg Clayton case llvm::Triple::IOS: // For arm targets 132a814f704SJason Molenda case llvm::Triple::TvOS: 133a814f704SJason Molenda case llvm::Triple::WatchOS: 134b9c1b51eSKate Stone if (triple_ref.getVendor() == llvm::Triple::Apple) { 135aa149cbdSGreg Clayton ObjectFile *exe_objfile = exe_module->GetObjectFile(); 136f9765acdSGreg Clayton if (exe_objfile->GetType() == ObjectFile::eTypeExecutable && 137f9765acdSGreg Clayton exe_objfile->GetStrata() == ObjectFile::eStrataKernel) 138f9765acdSGreg Clayton return true; 139f9765acdSGreg Clayton } 14070512317SGreg Clayton break; 14170512317SGreg Clayton 14270512317SGreg Clayton default: 14370512317SGreg Clayton break; 14470512317SGreg Clayton } 145f9765acdSGreg Clayton } 146596ed24eSGreg Clayton return false; 1473a29bdbeSGreg Clayton } 148f9765acdSGreg Clayton 149f9765acdSGreg Clayton // ProcessKDP constructor 150b9c1b51eSKate Stone ProcessKDP::ProcessKDP(TargetSP target_sp, ListenerSP listener_sp) 151b9c1b51eSKate Stone : Process(target_sp, listener_sp), 152f9765acdSGreg Clayton m_comm("lldb.process.kdp-remote.communication"), 1534bddaeb5SJim Ingham m_async_broadcaster(NULL, "lldb.process.kdp-remote.async-broadcaster"), 154b9c1b51eSKate Stone m_dyld_plugin_name(), m_kernel_load_addr(LLDB_INVALID_ADDRESS), 155b9c1b51eSKate Stone m_command_sp(), m_kernel_thread_wp() { 156b9c1b51eSKate Stone m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, 157b9c1b51eSKate Stone "async thread should exit"); 158b9c1b51eSKate Stone m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, 159b9c1b51eSKate Stone "async thread continue"); 160b9c1b51eSKate Stone const uint64_t timeout_seconds = 161b9c1b51eSKate Stone GetGlobalPluginProperties()->GetPacketTimeout(); 1627f98240dSGreg Clayton if (timeout_seconds > 0) 1635cddd608SPavel Labath m_comm.SetPacketTimeout(std::chrono::seconds(timeout_seconds)); 164f9765acdSGreg Clayton } 165f9765acdSGreg Clayton 166f9765acdSGreg Clayton // Destructor 167b9c1b51eSKate Stone ProcessKDP::~ProcessKDP() { 168f9765acdSGreg Clayton Clear(); 16905097246SAdrian Prantl // We need to call finalize on the process before destroying ourselves to 17005097246SAdrian Prantl // make sure all of the broadcaster cleanup goes as planned. If we destruct 17105097246SAdrian Prantl // this class, then Process::~Process() might have problems trying to fully 17205097246SAdrian Prantl // destroy the broadcaster. 173e24c4acfSGreg Clayton Finalize(); 174f9765acdSGreg Clayton } 175f9765acdSGreg Clayton 176f9765acdSGreg Clayton // PluginInterface 177b9c1b51eSKate Stone lldb_private::ConstString ProcessKDP::GetPluginName() { 178f9765acdSGreg Clayton return GetPluginNameStatic(); 179f9765acdSGreg Clayton } 180f9765acdSGreg Clayton 181b9c1b51eSKate Stone uint32_t ProcessKDP::GetPluginVersion() { return 1; } 182f9765acdSGreg Clayton 18397206d57SZachary Turner Status ProcessKDP::WillLaunch(Module *module) { 18497206d57SZachary Turner Status error; 185f9765acdSGreg Clayton error.SetErrorString("launching not supported in kdp-remote plug-in"); 186f9765acdSGreg Clayton return error; 187f9765acdSGreg Clayton } 188f9765acdSGreg Clayton 18997206d57SZachary Turner Status ProcessKDP::WillAttachToProcessWithID(lldb::pid_t pid) { 19097206d57SZachary Turner Status error; 191b9c1b51eSKate Stone error.SetErrorString( 192b9c1b51eSKate Stone "attaching to a by process ID not supported in kdp-remote plug-in"); 193f9765acdSGreg Clayton return error; 194f9765acdSGreg Clayton } 195f9765acdSGreg Clayton 19697206d57SZachary Turner Status ProcessKDP::WillAttachToProcessWithName(const char *process_name, 197b9c1b51eSKate Stone bool wait_for_launch) { 19897206d57SZachary Turner Status error; 199b9c1b51eSKate Stone error.SetErrorString( 200b9c1b51eSKate Stone "attaching to a by process name not supported in kdp-remote plug-in"); 201f9765acdSGreg Clayton return error; 202f9765acdSGreg Clayton } 203f9765acdSGreg Clayton 204b9c1b51eSKate Stone bool ProcessKDP::GetHostArchitecture(ArchSpec &arch) { 205a3706888SGreg Clayton uint32_t cpu = m_comm.GetCPUType(); 206b9c1b51eSKate Stone if (cpu) { 207a3706888SGreg Clayton uint32_t sub = m_comm.GetCPUSubtype(); 208a3706888SGreg Clayton arch.SetArchitecture(eArchTypeMachO, cpu, sub); 209a3706888SGreg Clayton // Leave architecture vendor as unspecified unknown 210a3706888SGreg Clayton arch.GetTriple().setVendor(llvm::Triple::UnknownVendor); 211a3706888SGreg Clayton arch.GetTriple().setVendorName(llvm::StringRef()); 212a3706888SGreg Clayton return true; 213a3706888SGreg Clayton } 214a3706888SGreg Clayton arch.Clear(); 215a3706888SGreg Clayton return false; 216a3706888SGreg Clayton } 217a3706888SGreg Clayton 21897206d57SZachary Turner Status ProcessKDP::DoConnectRemote(Stream *strm, llvm::StringRef remote_url) { 21997206d57SZachary Turner Status error; 2203a29bdbeSGreg Clayton 22105097246SAdrian Prantl // Don't let any JIT happen when doing KDP as we can't allocate memory and we 22205097246SAdrian Prantl // don't want to be mucking with threads that might already be handling 22305097246SAdrian Prantl // exceptions 2247925fbbaSGreg Clayton SetCanJIT(false); 2257925fbbaSGreg Clayton 2263ce7e996SGreg Clayton if (remote_url.empty()) { 2273ce7e996SGreg Clayton error.SetErrorStringWithFormat("empty connection URL"); 2287925fbbaSGreg Clayton return error; 2297925fbbaSGreg Clayton } 2303a29bdbeSGreg Clayton 231d5b44036SJonas Devlieghere std::unique_ptr<ConnectionFileDescriptor> conn_up( 232b9c1b51eSKate Stone new ConnectionFileDescriptor()); 233d5b44036SJonas Devlieghere if (conn_up) { 2343a29bdbeSGreg Clayton // Only try once for now. 2353a29bdbeSGreg Clayton // TODO: check if we should be retrying? 2363a29bdbeSGreg Clayton const uint32_t max_retry_count = 1; 237b9c1b51eSKate Stone for (uint32_t retry_count = 0; retry_count < max_retry_count; 238b9c1b51eSKate Stone ++retry_count) { 239d5b44036SJonas Devlieghere if (conn_up->Connect(remote_url, &error) == eConnectionStatusSuccess) 2403a29bdbeSGreg Clayton break; 2413a29bdbeSGreg Clayton usleep(100000); 2423a29bdbeSGreg Clayton } 2433a29bdbeSGreg Clayton } 2443a29bdbeSGreg Clayton 245d5b44036SJonas Devlieghere if (conn_up->IsConnected()) { 246b9c1b51eSKate Stone const TCPSocket &socket = 247d5b44036SJonas Devlieghere static_cast<const TCPSocket &>(*conn_up->GetReadObject()); 248014bb7daSVince Harron const uint16_t reply_port = socket.GetLocalPortNumber(); 2493a29bdbeSGreg Clayton 250b9c1b51eSKate Stone if (reply_port != 0) { 251d5b44036SJonas Devlieghere m_comm.SetConnection(conn_up.release()); 2523a29bdbeSGreg Clayton 253b9c1b51eSKate Stone if (m_comm.SendRequestReattach(reply_port)) { 254b9c1b51eSKate Stone if (m_comm.SendRequestConnect(reply_port, reply_port, 255b9c1b51eSKate Stone "Greetings from LLDB...")) { 2563a29bdbeSGreg Clayton m_comm.GetVersion(); 2575a3bb64fSJim Ingham 258a3706888SGreg Clayton Target &target = GetTarget(); 259a3706888SGreg Clayton ArchSpec kernel_arch; 260a3706888SGreg Clayton // The host architecture 261a3706888SGreg Clayton GetHostArchitecture(kernel_arch); 262a3706888SGreg Clayton ArchSpec target_arch = target.GetArchitecture(); 263a3706888SGreg Clayton // Merge in any unspecified stuff into the target architecture in 264a3706888SGreg Clayton // case the target arch isn't set at all or incompletely. 265a3706888SGreg Clayton target_arch.MergeFrom(kernel_arch); 266a3706888SGreg Clayton target.SetArchitecture(target_arch); 2674bd4e7e3SJason Molenda 268b9c1b51eSKate Stone /* Get the kernel's UUID and load address via KDP_KERNELVERSION 269b9c1b51eSKate Stone * packet. */ 270840f12cfSJason Molenda /* An EFI kdp session has neither UUID nor load address. */ 2714bd4e7e3SJason Molenda 2724bd4e7e3SJason Molenda UUID kernel_uuid = m_comm.GetUUID(); 2734bd4e7e3SJason Molenda addr_t kernel_load_addr = m_comm.GetLoadAddress(); 2744bd4e7e3SJason Molenda 275b9c1b51eSKate Stone if (m_comm.RemoteIsEFI()) { 276b9c1b51eSKate Stone // Select an invalid plugin name for the dynamic loader so one 27705097246SAdrian Prantl // doesn't get used since EFI does its own manual loading via 27805097246SAdrian Prantl // python scripting 279a1bce2efSGreg Clayton static ConstString g_none_dynamic_loader("none"); 280a1bce2efSGreg Clayton m_dyld_plugin_name = g_none_dynamic_loader; 281a1bce2efSGreg Clayton 282a1bce2efSGreg Clayton if (kernel_uuid.IsValid()) { 28305097246SAdrian Prantl // If EFI passed in a UUID= try to lookup UUID The slide will not 28405097246SAdrian Prantl // be provided. But the UUID lookup will be used to launch EFI 28505097246SAdrian Prantl // debug scripts from the dSYM, that can load all of the symbols. 286a1bce2efSGreg Clayton ModuleSpec module_spec; 287a1bce2efSGreg Clayton module_spec.GetUUID() = kernel_uuid; 2885a3bb64fSJim Ingham module_spec.GetArchitecture() = target.GetArchitecture(); 289a1bce2efSGreg Clayton 290a1bce2efSGreg Clayton // Lookup UUID locally, before attempting dsymForUUID like action 291a313ec11SZachary Turner FileSpecList search_paths = 292a313ec11SZachary Turner Target::GetDefaultDebugFileSearchPaths(); 293b9c1b51eSKate Stone module_spec.GetSymbolFileSpec() = 294a313ec11SZachary Turner Symbols::LocateExecutableSymbolFile(module_spec, 295a313ec11SZachary Turner search_paths); 296b9c1b51eSKate Stone if (module_spec.GetSymbolFileSpec()) { 297b9c1b51eSKate Stone ModuleSpec executable_module_spec = 298b9c1b51eSKate Stone Symbols::LocateExecutableObjectFile(module_spec); 299dbd7fabaSJonas Devlieghere if (FileSystem::Instance().Exists( 300dbd7fabaSJonas Devlieghere executable_module_spec.GetFileSpec())) { 301b9c1b51eSKate Stone module_spec.GetFileSpec() = 302b9c1b51eSKate Stone executable_module_spec.GetFileSpec(); 3038825c5c9SJason Molenda } 3048825c5c9SJason Molenda } 305b9c1b51eSKate Stone if (!module_spec.GetSymbolFileSpec() || 306b9c1b51eSKate Stone !module_spec.GetSymbolFileSpec()) 307a1bce2efSGreg Clayton Symbols::DownloadObjectAndSymbolFile(module_spec, true); 308a1bce2efSGreg Clayton 309dbd7fabaSJonas Devlieghere if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { 310a3706888SGreg Clayton ModuleSP module_sp(new Module(module_spec)); 311b9c1b51eSKate Stone if (module_sp.get() && module_sp->GetObjectFile()) { 312a1bce2efSGreg Clayton // Get the current target executable 3135a3bb64fSJim Ingham ModuleSP exe_module_sp(target.GetExecutableModule()); 314a1bce2efSGreg Clayton 315b9c1b51eSKate Stone // Make sure you don't already have the right module loaded 316b9c1b51eSKate Stone // and they will be uniqued 317a1bce2efSGreg Clayton if (exe_module_sp.get() != module_sp.get()) 318f9a07e9fSJonas Devlieghere target.SetExecutableModule(module_sp, eLoadDependentsNo); 319a1bce2efSGreg Clayton } 320a1bce2efSGreg Clayton } 321a1bce2efSGreg Clayton } 322b9c1b51eSKate Stone } else if (m_comm.RemoteIsDarwinKernel()) { 323b9c1b51eSKate Stone m_dyld_plugin_name = 324b9c1b51eSKate Stone DynamicLoaderDarwinKernel::GetPluginNameStatic(); 325b9c1b51eSKate Stone if (kernel_load_addr != LLDB_INVALID_ADDRESS) { 3265e8534efSJason Molenda m_kernel_load_addr = kernel_load_addr; 327a8ea4baeSJason Molenda } 3284bd4e7e3SJason Molenda } 3294bd4e7e3SJason Molenda 33097d5cf05SGreg Clayton // Set the thread ID 33197d5cf05SGreg Clayton UpdateThreadListIfNeeded(); 332a63d08c9SGreg Clayton SetID(1); 33356d9a1b3SGreg Clayton GetThreadList(); 334a63d08c9SGreg Clayton SetPrivateState(eStateStopped); 3355a3bb64fSJim Ingham StreamSP async_strm_sp(target.GetDebugger().GetAsyncOutputStream()); 336b9c1b51eSKate Stone if (async_strm_sp) { 3375b88216dSGreg Clayton const char *cstr; 338b9c1b51eSKate Stone if ((cstr = m_comm.GetKernelVersion()) != NULL) { 3395b88216dSGreg Clayton async_strm_sp->Printf("Version: %s\n", cstr); 34007e66e3eSGreg Clayton async_strm_sp->Flush(); 34107e66e3eSGreg Clayton } 3425b88216dSGreg Clayton // if ((cstr = m_comm.GetImagePath ()) != NULL) 3435b88216dSGreg Clayton // { 344b9c1b51eSKate Stone // async_strm_sp->Printf ("Image Path: 345b9c1b51eSKate Stone // %s\n", cstr); 3465b88216dSGreg Clayton // async_strm_sp->Flush(); 3475b88216dSGreg Clayton // } 34807e66e3eSGreg Clayton } 349b9c1b51eSKate Stone } else { 35097d5cf05SGreg Clayton error.SetErrorString("KDP_REATTACH failed"); 35197d5cf05SGreg Clayton } 352b9c1b51eSKate Stone } else { 35397d5cf05SGreg Clayton error.SetErrorString("KDP_REATTACH failed"); 3543a29bdbeSGreg Clayton } 355b9c1b51eSKate Stone } else { 3563a29bdbeSGreg Clayton error.SetErrorString("invalid reply port from UDP connection"); 3573a29bdbeSGreg Clayton } 358b9c1b51eSKate Stone } else { 3593a29bdbeSGreg Clayton if (error.Success()) 3603ce7e996SGreg Clayton error.SetErrorStringWithFormat("failed to connect to '%s'", 3613ce7e996SGreg Clayton remote_url.str().c_str()); 3623a29bdbeSGreg Clayton } 3633a29bdbeSGreg Clayton if (error.Fail()) 3643a29bdbeSGreg Clayton m_comm.Disconnect(); 3653a29bdbeSGreg Clayton 366f9765acdSGreg Clayton return error; 367f9765acdSGreg Clayton } 368f9765acdSGreg Clayton 369f9765acdSGreg Clayton // Process Control 37097206d57SZachary Turner Status ProcessKDP::DoLaunch(Module *exe_module, 37197206d57SZachary Turner ProcessLaunchInfo &launch_info) { 37297206d57SZachary Turner Status error; 373f9765acdSGreg Clayton error.SetErrorString("launching not supported in kdp-remote plug-in"); 374f9765acdSGreg Clayton return error; 375f9765acdSGreg Clayton } 376f9765acdSGreg Clayton 37797206d57SZachary Turner Status 37897206d57SZachary Turner ProcessKDP::DoAttachToProcessWithID(lldb::pid_t attach_pid, 37997206d57SZachary Turner const ProcessAttachInfo &attach_info) { 38097206d57SZachary Turner Status error; 381b9c1b51eSKate Stone error.SetErrorString( 3824ebdee0aSBruce Mitchener "attach to process by ID is not supported in kdp remote debugging"); 38384647048SHan Ming Ong return error; 38484647048SHan Ming Ong } 38584647048SHan Ming Ong 38697206d57SZachary Turner Status 38797206d57SZachary Turner ProcessKDP::DoAttachToProcessWithName(const char *process_name, 38897206d57SZachary Turner const ProcessAttachInfo &attach_info) { 38997206d57SZachary Turner Status error; 390b9c1b51eSKate Stone error.SetErrorString( 3914ebdee0aSBruce Mitchener "attach to process by name is not supported in kdp remote debugging"); 392f9765acdSGreg Clayton return error; 393f9765acdSGreg Clayton } 394f9765acdSGreg Clayton 395b9c1b51eSKate Stone void ProcessKDP::DidAttach(ArchSpec &process_arch) { 396bb006ce2SJim Ingham Process::DidAttach(process_arch); 397bb006ce2SJim Ingham 3985160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 39963e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DidAttach()"); 400b9c1b51eSKate Stone if (GetID() != LLDB_INVALID_PROCESS_ID) { 401a3706888SGreg Clayton GetHostArchitecture(process_arch); 402f9765acdSGreg Clayton } 403f9765acdSGreg Clayton } 404f9765acdSGreg Clayton 405b9c1b51eSKate Stone addr_t ProcessKDP::GetImageInfoAddress() { return m_kernel_load_addr; } 4065e8534efSJason Molenda 407b9c1b51eSKate Stone lldb_private::DynamicLoader *ProcessKDP::GetDynamicLoader() { 408d5b44036SJonas Devlieghere if (m_dyld_up.get() == NULL) 409d5b44036SJonas Devlieghere m_dyld_up.reset(DynamicLoader::FindPlugin( 410b9c1b51eSKate Stone this, 411b9c1b51eSKate Stone m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString())); 412d5b44036SJonas Devlieghere return m_dyld_up.get(); 4135e8534efSJason Molenda } 4145e8534efSJason Molenda 41597206d57SZachary Turner Status ProcessKDP::WillResume() { return Status(); } 416f9765acdSGreg Clayton 41797206d57SZachary Turner Status ProcessKDP::DoResume() { 41897206d57SZachary Turner Status error; 4195160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 4207925fbbaSGreg Clayton // Only start the async thread if we try to do any process control 421acee96aeSZachary Turner if (!m_async_thread.IsJoinable()) 4227925fbbaSGreg Clayton StartAsyncThread(); 4237925fbbaSGreg Clayton 42497d5cf05SGreg Clayton bool resume = false; 4257925fbbaSGreg Clayton 42697d5cf05SGreg Clayton // With KDP there is only one thread we can tell what to do 427ba4e61d3SAndrew Kaylor ThreadSP kernel_thread_sp(m_thread_list.FindThreadByProtocolID(g_kernel_tid)); 428ba4e61d3SAndrew Kaylor 429b9c1b51eSKate Stone if (kernel_thread_sp) { 430b9c1b51eSKate Stone const StateType thread_resume_state = 431b9c1b51eSKate Stone kernel_thread_sp->GetTemporaryResumeState(); 4326e0ff1a3SGreg Clayton 43363e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoResume() thread_resume_state = %s", 434b9c1b51eSKate Stone StateAsCString(thread_resume_state)); 435b9c1b51eSKate Stone switch (thread_resume_state) { 4367925fbbaSGreg Clayton case eStateSuspended: 43705097246SAdrian Prantl // Nothing to do here when a thread will stay suspended we just leave the 43805097246SAdrian Prantl // CPU mask bit set to zero for the thread 43963e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoResume() = suspended???"); 4407925fbbaSGreg Clayton break; 4417925fbbaSGreg Clayton 442b9c1b51eSKate Stone case eStateStepping: { 443b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 444b9c1b51eSKate Stone kernel_thread_sp->GetRegisterContext()); 4451afa68edSGreg Clayton 446b9c1b51eSKate Stone if (reg_ctx_sp) { 44763e5fb76SJonas Devlieghere LLDB_LOGF( 44863e5fb76SJonas Devlieghere log, 449b9c1b51eSKate Stone "ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (true);"); 4501afa68edSGreg Clayton reg_ctx_sp->HardwareSingleStep(true); 45197d5cf05SGreg Clayton resume = true; 452b9c1b51eSKate Stone } else { 453b9c1b51eSKate Stone error.SetErrorStringWithFormat( 454b9c1b51eSKate Stone "KDP thread 0x%llx has no register context", 455b9c1b51eSKate Stone kernel_thread_sp->GetID()); 4561afa68edSGreg Clayton } 457b9c1b51eSKate Stone } break; 4587925fbbaSGreg Clayton 459b9c1b51eSKate Stone case eStateRunning: { 460b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 461b9c1b51eSKate Stone kernel_thread_sp->GetRegisterContext()); 4621afa68edSGreg Clayton 463b9c1b51eSKate Stone if (reg_ctx_sp) { 46463e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep " 465b9c1b51eSKate Stone "(false);"); 4661afa68edSGreg Clayton reg_ctx_sp->HardwareSingleStep(false); 46797d5cf05SGreg Clayton resume = true; 468b9c1b51eSKate Stone } else { 469b9c1b51eSKate Stone error.SetErrorStringWithFormat( 470b9c1b51eSKate Stone "KDP thread 0x%llx has no register context", 471b9c1b51eSKate Stone kernel_thread_sp->GetID()); 4721afa68edSGreg Clayton } 473b9c1b51eSKate Stone } break; 4747925fbbaSGreg Clayton 4757925fbbaSGreg Clayton default: 47697d5cf05SGreg Clayton // The only valid thread resume states are listed above 477a322f36cSDavid Blaikie llvm_unreachable("invalid thread resume state"); 4784b1b8b3eSGreg Clayton } 4794b1b8b3eSGreg Clayton } 4807925fbbaSGreg Clayton 481b9c1b51eSKate Stone if (resume) { 48263e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoResume () sending resume"); 48397d5cf05SGreg Clayton 484b9c1b51eSKate Stone if (m_comm.SendRequestResume()) { 4857925fbbaSGreg Clayton m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue); 4867925fbbaSGreg Clayton SetPrivateState(eStateRunning); 487b9c1b51eSKate Stone } else 48807e66e3eSGreg Clayton error.SetErrorString("KDP resume failed"); 489b9c1b51eSKate Stone } else { 49097d5cf05SGreg Clayton error.SetErrorString("kernel thread is suspended"); 4917925fbbaSGreg Clayton } 4927925fbbaSGreg Clayton 493f9765acdSGreg Clayton return error; 494f9765acdSGreg Clayton } 495f9765acdSGreg Clayton 496b9c1b51eSKate Stone lldb::ThreadSP ProcessKDP::GetKernelThread() { 49797d5cf05SGreg Clayton // KDP only tells us about one thread/core. Any other threads will usually 49897d5cf05SGreg Clayton // be the ones that are read from memory by the OS plug-ins. 499ba4e61d3SAndrew Kaylor 500ba4e61d3SAndrew Kaylor ThreadSP thread_sp(m_kernel_thread_wp.lock()); 501b9c1b51eSKate Stone if (!thread_sp) { 502796ac80bSJonas Devlieghere thread_sp = std::make_shared<ThreadKDP>(*this, g_kernel_tid); 503ba4e61d3SAndrew Kaylor m_kernel_thread_wp = thread_sp; 504ba4e61d3SAndrew Kaylor } 50597d5cf05SGreg Clayton return thread_sp; 50697d5cf05SGreg Clayton } 50797d5cf05SGreg Clayton 508b9c1b51eSKate Stone bool ProcessKDP::UpdateThreadList(ThreadList &old_thread_list, 509b9c1b51eSKate Stone ThreadList &new_thread_list) { 510f9765acdSGreg Clayton // locker will keep a mutex locked until it goes out of scope 5115160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_THREAD)); 512250858a0SPavel Labath LLDB_LOGV(log, "pid = {0}", GetID()); 513f9765acdSGreg Clayton 51439da3efdSGreg Clayton // Even though there is a CPU mask, it doesn't mean we can see each CPU 515a868c13cSBruce Mitchener // individually, there is really only one. Lets call this thread 1. 516b9c1b51eSKate Stone ThreadSP thread_sp( 517b9c1b51eSKate Stone old_thread_list.FindThreadByProtocolID(g_kernel_tid, false)); 518ba4e61d3SAndrew Kaylor if (!thread_sp) 519ba4e61d3SAndrew Kaylor thread_sp = GetKernelThread(); 520ba4e61d3SAndrew Kaylor new_thread_list.AddThread(thread_sp); 52197d5cf05SGreg Clayton 5229fc13556SGreg Clayton return new_thread_list.GetSize(false) > 0; 523f9765acdSGreg Clayton } 524f9765acdSGreg Clayton 525b9c1b51eSKate Stone void ProcessKDP::RefreshStateAfterStop() { 52605097246SAdrian Prantl // Let all threads recover from stopping and do any clean up based on the 52705097246SAdrian Prantl // previous thread state (if any). 528f9765acdSGreg Clayton m_thread_list.RefreshStateAfterStop(); 529f9765acdSGreg Clayton } 530f9765acdSGreg Clayton 53197206d57SZachary Turner Status ProcessKDP::DoHalt(bool &caused_stop) { 53297206d57SZachary Turner Status error; 533f9765acdSGreg Clayton 534b9c1b51eSKate Stone if (m_comm.IsRunning()) { 535b9c1b51eSKate Stone if (m_destroy_in_process) { 5364ebdee0aSBruce Mitchener // If we are attempting to destroy, we need to not return an error to Halt 53705097246SAdrian Prantl // or DoDestroy won't get called. We are also currently running, so send 53805097246SAdrian Prantl // a process stopped event 53997d5cf05SGreg Clayton SetPrivateState(eStateStopped); 540b9c1b51eSKate Stone } else { 54197d5cf05SGreg Clayton error.SetErrorString("KDP cannot interrupt a running kernel"); 542f9765acdSGreg Clayton } 543f9765acdSGreg Clayton } 544f9765acdSGreg Clayton return error; 545f9765acdSGreg Clayton } 546f9765acdSGreg Clayton 54797206d57SZachary Turner Status ProcessKDP::DoDetach(bool keep_stopped) { 54897206d57SZachary Turner Status error; 5495160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 55063e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoDetach(keep_stopped = %i)", keep_stopped); 551f9765acdSGreg Clayton 552b9c1b51eSKate Stone if (m_comm.IsRunning()) { 55305097246SAdrian Prantl // We are running and we can't interrupt a running kernel, so we need to 55405097246SAdrian Prantl // just close the connection to the kernel and hope for the best 555b9c1b51eSKate Stone } else { 556b9c1b51eSKate Stone // If we are going to keep the target stopped, then don't send the 557b9c1b51eSKate Stone // disconnect message. 558b9c1b51eSKate Stone if (!keep_stopped && m_comm.IsConnected()) { 5596e0ff1a3SGreg Clayton const bool success = m_comm.SendRequestDisconnect(); 560b9c1b51eSKate Stone if (log) { 5616e0ff1a3SGreg Clayton if (success) 562b9c1b51eSKate Stone log->PutCString( 563b9c1b51eSKate Stone "ProcessKDP::DoDetach() detach packet sent successfully"); 564f9765acdSGreg Clayton else 565b9c1b51eSKate Stone log->PutCString( 566b9c1b51eSKate Stone "ProcessKDP::DoDetach() connection channel shutdown failed"); 567f9765acdSGreg Clayton } 5686e0ff1a3SGreg Clayton m_comm.Disconnect(); 5693a29bdbeSGreg Clayton } 57097d5cf05SGreg Clayton } 571f9765acdSGreg Clayton StopAsyncThread(); 57274d4193eSGreg Clayton m_comm.Clear(); 573f9765acdSGreg Clayton 574f9765acdSGreg Clayton SetPrivateState(eStateDetached); 575f9765acdSGreg Clayton ResumePrivateStateThread(); 576f9765acdSGreg Clayton 577f9765acdSGreg Clayton // KillDebugserverProcess (); 578f9765acdSGreg Clayton return error; 579f9765acdSGreg Clayton } 580f9765acdSGreg Clayton 58197206d57SZachary Turner Status ProcessKDP::DoDestroy() { 5827925fbbaSGreg Clayton // For KDP there really is no difference between destroy and detach 583acff8950SJim Ingham bool keep_stopped = false; 584acff8950SJim Ingham return DoDetach(keep_stopped); 585f9765acdSGreg Clayton } 586f9765acdSGreg Clayton 587f9765acdSGreg Clayton // Process Queries 588f9765acdSGreg Clayton 589b9c1b51eSKate Stone bool ProcessKDP::IsAlive() { 590a814f704SJason Molenda return m_comm.IsConnected() && Process::IsAlive(); 591f9765acdSGreg Clayton } 592f9765acdSGreg Clayton 593f9765acdSGreg Clayton // Process Memory 594b9c1b51eSKate Stone size_t ProcessKDP::DoReadMemory(addr_t addr, void *buf, size_t size, 59597206d57SZachary Turner Status &error) { 5968eb32817SJason Molenda uint8_t *data_buffer = (uint8_t *)buf; 597b9c1b51eSKate Stone if (m_comm.IsConnected()) { 5988eb32817SJason Molenda const size_t max_read_size = 512; 5998eb32817SJason Molenda size_t total_bytes_read = 0; 6008eb32817SJason Molenda 6018eb32817SJason Molenda // Read the requested amount of memory in 512 byte chunks 602b9c1b51eSKate Stone while (total_bytes_read < size) { 6038eb32817SJason Molenda size_t bytes_to_read_this_request = size - total_bytes_read; 604b9c1b51eSKate Stone if (bytes_to_read_this_request > max_read_size) { 6058eb32817SJason Molenda bytes_to_read_this_request = max_read_size; 6068eb32817SJason Molenda } 607b9c1b51eSKate Stone size_t bytes_read = m_comm.SendRequestReadMemory( 608b9c1b51eSKate Stone addr + total_bytes_read, data_buffer + total_bytes_read, 6098eb32817SJason Molenda bytes_to_read_this_request, error); 6108eb32817SJason Molenda total_bytes_read += bytes_read; 611b9c1b51eSKate Stone if (error.Fail() || bytes_read == 0) { 6128eb32817SJason Molenda return total_bytes_read; 6138eb32817SJason Molenda } 6148eb32817SJason Molenda } 6158eb32817SJason Molenda 6168eb32817SJason Molenda return total_bytes_read; 6178eb32817SJason Molenda } 618a63d08c9SGreg Clayton error.SetErrorString("not connected"); 619f9765acdSGreg Clayton return 0; 620f9765acdSGreg Clayton } 621f9765acdSGreg Clayton 622b9c1b51eSKate Stone size_t ProcessKDP::DoWriteMemory(addr_t addr, const void *buf, size_t size, 62397206d57SZachary Turner Status &error) { 6247925fbbaSGreg Clayton if (m_comm.IsConnected()) 6257925fbbaSGreg Clayton return m_comm.SendRequestWriteMemory(addr, buf, size, error); 6267925fbbaSGreg Clayton error.SetErrorString("not connected"); 627f9765acdSGreg Clayton return 0; 628f9765acdSGreg Clayton } 629f9765acdSGreg Clayton 630b9c1b51eSKate Stone lldb::addr_t ProcessKDP::DoAllocateMemory(size_t size, uint32_t permissions, 63197206d57SZachary Turner Status &error) { 632b9c1b51eSKate Stone error.SetErrorString( 6334ebdee0aSBruce Mitchener "memory allocation not supported in kdp remote debugging"); 634f9765acdSGreg Clayton return LLDB_INVALID_ADDRESS; 635f9765acdSGreg Clayton } 636f9765acdSGreg Clayton 63797206d57SZachary Turner Status ProcessKDP::DoDeallocateMemory(lldb::addr_t addr) { 63897206d57SZachary Turner Status error; 639b9c1b51eSKate Stone error.SetErrorString( 6404ebdee0aSBruce Mitchener "memory deallocation not supported in kdp remote debugging"); 641f9765acdSGreg Clayton return error; 642f9765acdSGreg Clayton } 643f9765acdSGreg Clayton 64497206d57SZachary Turner Status ProcessKDP::EnableBreakpointSite(BreakpointSite *bp_site) { 645b9c1b51eSKate Stone if (m_comm.LocalBreakpointsAreSupported()) { 64697206d57SZachary Turner Status error; 647b9c1b51eSKate Stone if (!bp_site->IsEnabled()) { 648b9c1b51eSKate Stone if (m_comm.SendRequestBreakpoint(true, bp_site->GetLoadAddress())) { 6495b88216dSGreg Clayton bp_site->SetEnabled(true); 6505b88216dSGreg Clayton bp_site->SetType(BreakpointSite::eExternal); 651b9c1b51eSKate Stone } else { 65207e66e3eSGreg Clayton error.SetErrorString("KDP set breakpoint failed"); 6535b88216dSGreg Clayton } 6545b88216dSGreg Clayton } 65507e66e3eSGreg Clayton return error; 65607e66e3eSGreg Clayton } 657f9765acdSGreg Clayton return EnableSoftwareBreakpoint(bp_site); 658f9765acdSGreg Clayton } 659f9765acdSGreg Clayton 66097206d57SZachary Turner Status ProcessKDP::DisableBreakpointSite(BreakpointSite *bp_site) { 661b9c1b51eSKate Stone if (m_comm.LocalBreakpointsAreSupported()) { 66297206d57SZachary Turner Status error; 663b9c1b51eSKate Stone if (bp_site->IsEnabled()) { 6645b88216dSGreg Clayton BreakpointSite::Type bp_type = bp_site->GetType(); 665b9c1b51eSKate Stone if (bp_type == BreakpointSite::eExternal) { 666b9c1b51eSKate Stone if (m_destroy_in_process && m_comm.IsRunning()) { 66797d5cf05SGreg Clayton // We are trying to destroy our connection and we are running 66897d5cf05SGreg Clayton bp_site->SetEnabled(false); 669b9c1b51eSKate Stone } else { 6705b88216dSGreg Clayton if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress())) 6715b88216dSGreg Clayton bp_site->SetEnabled(false); 6725b88216dSGreg Clayton else 67307e66e3eSGreg Clayton error.SetErrorString("KDP remove breakpoint failed"); 6745b88216dSGreg Clayton } 675b9c1b51eSKate Stone } else { 6765b88216dSGreg Clayton error = DisableSoftwareBreakpoint(bp_site); 6775b88216dSGreg Clayton } 6785b88216dSGreg Clayton } 67907e66e3eSGreg Clayton return error; 68007e66e3eSGreg Clayton } 681f9765acdSGreg Clayton return DisableSoftwareBreakpoint(bp_site); 682f9765acdSGreg Clayton } 683f9765acdSGreg Clayton 68497206d57SZachary Turner Status ProcessKDP::EnableWatchpoint(Watchpoint *wp, bool notify) { 68597206d57SZachary Turner Status error; 686b9c1b51eSKate Stone error.SetErrorString( 6874ebdee0aSBruce Mitchener "watchpoints are not supported in kdp remote debugging"); 688f9765acdSGreg Clayton return error; 689f9765acdSGreg Clayton } 690f9765acdSGreg Clayton 69197206d57SZachary Turner Status ProcessKDP::DisableWatchpoint(Watchpoint *wp, bool notify) { 69297206d57SZachary Turner Status error; 693b9c1b51eSKate Stone error.SetErrorString( 6944ebdee0aSBruce Mitchener "watchpoints are not supported in kdp remote debugging"); 695f9765acdSGreg Clayton return error; 696f9765acdSGreg Clayton } 697f9765acdSGreg Clayton 698b9c1b51eSKate Stone void ProcessKDP::Clear() { m_thread_list.Clear(); } 699f9765acdSGreg Clayton 70097206d57SZachary Turner Status ProcessKDP::DoSignal(int signo) { 70197206d57SZachary Turner Status error; 702b9c1b51eSKate Stone error.SetErrorString( 7034ebdee0aSBruce Mitchener "sending signals is not supported in kdp remote debugging"); 704f9765acdSGreg Clayton return error; 705f9765acdSGreg Clayton } 706f9765acdSGreg Clayton 707b9c1b51eSKate Stone void ProcessKDP::Initialize() { 708c5f28e2aSKamil Rytarowski static llvm::once_flag g_once_flag; 709f9765acdSGreg Clayton 710c5f28e2aSKamil Rytarowski llvm::call_once(g_once_flag, []() { 711f9765acdSGreg Clayton PluginManager::RegisterPlugin(GetPluginNameStatic(), 712b9c1b51eSKate Stone GetPluginDescriptionStatic(), CreateInstance, 713488c89edSBruce Mitchener DebuggerInitialize); 714f9765acdSGreg Clayton 7157b35b781SPavel Labath ProcessKDPLog::Initialize(); 716c8d69828SDavide Italiano }); 717f9765acdSGreg Clayton } 718f9765acdSGreg Clayton 719b9c1b51eSKate Stone void ProcessKDP::DebuggerInitialize(lldb_private::Debugger &debugger) { 720b9c1b51eSKate Stone if (!PluginManager::GetSettingForProcessPlugin( 721b9c1b51eSKate Stone debugger, PluginProperties::GetSettingName())) { 7227f98240dSGreg Clayton const bool is_global_setting = true; 723b9c1b51eSKate Stone PluginManager::CreateSettingForProcessPlugin( 724b9c1b51eSKate Stone debugger, GetGlobalPluginProperties()->GetValueProperties(), 7257f98240dSGreg Clayton ConstString("Properties for the kdp-remote process plug-in."), 7267f98240dSGreg Clayton is_global_setting); 7277f98240dSGreg Clayton } 7287f98240dSGreg Clayton } 7297f98240dSGreg Clayton 730b9c1b51eSKate Stone bool ProcessKDP::StartAsyncThread() { 7315160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 732f9765acdSGreg Clayton 73363e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::StartAsyncThread ()"); 734f9765acdSGreg Clayton 735acee96aeSZachary Turner if (m_async_thread.IsJoinable()) 7367925fbbaSGreg Clayton return true; 7377925fbbaSGreg Clayton 738f39c2e18SJonas Devlieghere llvm::Expected<HostThread> async_thread = ThreadLauncher::LaunchThread( 739f39c2e18SJonas Devlieghere "<lldb.process.kdp-remote.async>", ProcessKDP::AsyncThread, this); 740f39c2e18SJonas Devlieghere if (!async_thread) { 741f39c2e18SJonas Devlieghere LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), 742f39c2e18SJonas Devlieghere "failed to launch host thread: {}", 743f39c2e18SJonas Devlieghere llvm::toString(async_thread.takeError())); 744f39c2e18SJonas Devlieghere return false; 745f39c2e18SJonas Devlieghere } 746f39c2e18SJonas Devlieghere m_async_thread = *async_thread; 747acee96aeSZachary Turner return m_async_thread.IsJoinable(); 748f9765acdSGreg Clayton } 749f9765acdSGreg Clayton 750b9c1b51eSKate Stone void ProcessKDP::StopAsyncThread() { 7515160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 752f9765acdSGreg Clayton 75363e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::StopAsyncThread ()"); 754f9765acdSGreg Clayton 755f9765acdSGreg Clayton m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit); 756f9765acdSGreg Clayton 757f9765acdSGreg Clayton // Stop the stdio thread 758acee96aeSZachary Turner if (m_async_thread.IsJoinable()) 75939de3110SZachary Turner m_async_thread.Join(nullptr); 760f9765acdSGreg Clayton } 761f9765acdSGreg Clayton 762b9c1b51eSKate Stone void *ProcessKDP::AsyncThread(void *arg) { 763f9765acdSGreg Clayton ProcessKDP *process = (ProcessKDP *)arg; 764f9765acdSGreg Clayton 7657925fbbaSGreg Clayton const lldb::pid_t pid = process->GetID(); 7667925fbbaSGreg Clayton 7675160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 76863e5fb76SJonas Devlieghere LLDB_LOGF(log, 76963e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 770b9c1b51eSKate Stone ") thread starting...", 771b9c1b51eSKate Stone arg, pid); 772f9765acdSGreg Clayton 773583bbb1dSJim Ingham ListenerSP listener_sp(Listener::MakeListener("ProcessKDP::AsyncThread")); 774f9765acdSGreg Clayton EventSP event_sp; 775b9c1b51eSKate Stone const uint32_t desired_event_mask = 776b9c1b51eSKate Stone eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit; 777f9765acdSGreg Clayton 778b9c1b51eSKate Stone if (listener_sp->StartListeningForEvents(&process->m_async_broadcaster, 779b9c1b51eSKate Stone desired_event_mask) == 780b9c1b51eSKate Stone desired_event_mask) { 781f9765acdSGreg Clayton bool done = false; 782b9c1b51eSKate Stone while (!done) { 78363e5fb76SJonas Devlieghere LLDB_LOGF(log, 78463e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 785b9c1b51eSKate Stone ") listener.WaitForEvent (NULL, event_sp)...", 7867925fbbaSGreg Clayton pid); 787fafff0c5SPavel Labath if (listener_sp->GetEvent(event_sp, llvm::None)) { 7887925fbbaSGreg Clayton uint32_t event_type = event_sp->GetType(); 78963e5fb76SJonas Devlieghere LLDB_LOGF(log, 79063e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 791b9c1b51eSKate Stone ") Got an event of type: %d...", 792b9c1b51eSKate Stone pid, event_type); 793f9765acdSGreg Clayton 7947925fbbaSGreg Clayton // When we are running, poll for 1 second to try and get an exception 7957925fbbaSGreg Clayton // to indicate the process has stopped. If we don't get one, check to 7967925fbbaSGreg Clayton // make sure no one asked us to exit 7977925fbbaSGreg Clayton bool is_running = false; 7987925fbbaSGreg Clayton DataExtractor exc_reply_packet; 799b9c1b51eSKate Stone do { 800b9c1b51eSKate Stone switch (event_type) { 801b9c1b51eSKate Stone case eBroadcastBitAsyncContinue: { 8027925fbbaSGreg Clayton is_running = true; 803b9c1b51eSKate Stone if (process->m_comm.WaitForPacketWithTimeoutMicroSeconds( 804b9c1b51eSKate Stone exc_reply_packet, 1 * USEC_PER_SEC)) { 805ba4e61d3SAndrew Kaylor ThreadSP thread_sp(process->GetKernelThread()); 806b9c1b51eSKate Stone if (thread_sp) { 807b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 808b9c1b51eSKate Stone thread_sp->GetRegisterContext()); 8091afa68edSGreg Clayton if (reg_ctx_sp) 8101afa68edSGreg Clayton reg_ctx_sp->InvalidateAllRegisters(); 811b9c1b51eSKate Stone static_cast<ThreadKDP *>(thread_sp.get()) 812b9c1b51eSKate Stone ->SetStopInfoFrom_KDP_EXCEPTION(exc_reply_packet); 8131afa68edSGreg Clayton } 81497d5cf05SGreg Clayton 8157925fbbaSGreg Clayton // TODO: parse the stop reply packet 8167925fbbaSGreg Clayton is_running = false; 8177925fbbaSGreg Clayton process->SetPrivateState(eStateStopped); 818b9c1b51eSKate Stone } else { 8197925fbbaSGreg Clayton // Check to see if we are supposed to exit. There is no way to 8207925fbbaSGreg Clayton // interrupt a running kernel, so all we can do is wait for an 8217925fbbaSGreg Clayton // exception or detach... 822fafff0c5SPavel Labath if (listener_sp->GetEvent(event_sp, 823fafff0c5SPavel Labath std::chrono::microseconds(0))) { 8247925fbbaSGreg Clayton // We got an event, go through the loop again 8257925fbbaSGreg Clayton event_type = event_sp->GetType(); 8267925fbbaSGreg Clayton } 827f9765acdSGreg Clayton } 828b9c1b51eSKate Stone } break; 829f9765acdSGreg Clayton 830f9765acdSGreg Clayton case eBroadcastBitAsyncThreadShouldExit: 83163e5fb76SJonas Devlieghere LLDB_LOGF(log, 83263e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 833b9c1b51eSKate Stone ") got eBroadcastBitAsyncThreadShouldExit...", 8347925fbbaSGreg Clayton pid); 835f9765acdSGreg Clayton done = true; 8367925fbbaSGreg Clayton is_running = false; 837f9765acdSGreg Clayton break; 838f9765acdSGreg Clayton 839f9765acdSGreg Clayton default: 84063e5fb76SJonas Devlieghere LLDB_LOGF(log, 84163e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 842b9c1b51eSKate Stone ") got unknown event 0x%8.8x", 843b9c1b51eSKate Stone pid, event_type); 844f9765acdSGreg Clayton done = true; 8457925fbbaSGreg Clayton is_running = false; 846f9765acdSGreg Clayton break; 847f9765acdSGreg Clayton } 8487925fbbaSGreg Clayton } while (is_running); 849b9c1b51eSKate Stone } else { 85063e5fb76SJonas Devlieghere LLDB_LOGF(log, 85163e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 852b9c1b51eSKate Stone ") listener.WaitForEvent (NULL, event_sp) => false", 8537925fbbaSGreg Clayton pid); 854f9765acdSGreg Clayton done = true; 855f9765acdSGreg Clayton } 856f9765acdSGreg Clayton } 857f9765acdSGreg Clayton } 858f9765acdSGreg Clayton 85963e5fb76SJonas Devlieghere LLDB_LOGF(log, 86063e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 861b9c1b51eSKate Stone ") thread exiting...", 862b9c1b51eSKate Stone arg, pid); 863f9765acdSGreg Clayton 86439de3110SZachary Turner process->m_async_thread.Reset(); 865f9765acdSGreg Clayton return NULL; 866f9765acdSGreg Clayton } 867f9765acdSGreg Clayton 868b9c1b51eSKate Stone class CommandObjectProcessKDPPacketSend : public CommandObjectParsed { 8691d19a2f2SGreg Clayton private: 8701d19a2f2SGreg Clayton OptionGroupOptions m_option_group; 8711d19a2f2SGreg Clayton OptionGroupUInt64 m_command_byte; 8721d19a2f2SGreg Clayton OptionGroupString m_packet_data; 8731d19a2f2SGreg Clayton 874b9c1b51eSKate Stone virtual Options *GetOptions() { return &m_option_group; } 8751d19a2f2SGreg Clayton 8761d19a2f2SGreg Clayton public: 877b9c1b51eSKate Stone CommandObjectProcessKDPPacketSend(CommandInterpreter &interpreter) 878b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "process plugin packet send", 879b9c1b51eSKate Stone "Send a custom packet through the KDP protocol by " 880b9c1b51eSKate Stone "specifying the command byte and the packet " 881b9c1b51eSKate Stone "payload data. A packet will be sent with a " 882b9c1b51eSKate Stone "correct header and payload, and the raw result " 883b9c1b51eSKate Stone "bytes will be displayed as a string value. ", 8841d19a2f2SGreg Clayton NULL), 885e1cfbc79STodd Fiala m_option_group(), 886b9c1b51eSKate Stone m_command_byte(LLDB_OPT_SET_1, true, "command", 'c', 0, eArgTypeNone, 887b9c1b51eSKate Stone "Specify the command byte to use when sending the KDP " 888b9c1b51eSKate Stone "request packet.", 889b9c1b51eSKate Stone 0), 890b9c1b51eSKate Stone m_packet_data(LLDB_OPT_SET_1, false, "payload", 'p', 0, eArgTypeNone, 891b9c1b51eSKate Stone "Specify packet payload bytes as a hex ASCII string with " 892b9c1b51eSKate Stone "no spaces or hex prefixes.", 893b9c1b51eSKate Stone NULL) { 8941d19a2f2SGreg Clayton m_option_group.Append(&m_command_byte, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 8951d19a2f2SGreg Clayton m_option_group.Append(&m_packet_data, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 8961d19a2f2SGreg Clayton m_option_group.Finalize(); 8971d19a2f2SGreg Clayton } 8981d19a2f2SGreg Clayton 899b9c1b51eSKate Stone ~CommandObjectProcessKDPPacketSend() {} 9001d19a2f2SGreg Clayton 901b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) { 9021d19a2f2SGreg Clayton const size_t argc = command.GetArgumentCount(); 903b9c1b51eSKate Stone if (argc == 0) { 904b9c1b51eSKate Stone if (!m_command_byte.GetOptionValue().OptionWasSet()) { 905b9c1b51eSKate Stone result.AppendError( 906b9c1b51eSKate Stone "the --command option must be set to a valid command byte"); 9071d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 908b9c1b51eSKate Stone } else { 909b9c1b51eSKate Stone const uint64_t command_byte = 910b9c1b51eSKate Stone m_command_byte.GetOptionValue().GetUInt64Value(0); 911b9c1b51eSKate Stone if (command_byte > 0 && command_byte <= UINT8_MAX) { 912b9c1b51eSKate Stone ProcessKDP *process = 913b9c1b51eSKate Stone (ProcessKDP *)m_interpreter.GetExecutionContext().GetProcessPtr(); 914b9c1b51eSKate Stone if (process) { 9151d19a2f2SGreg Clayton const StateType state = process->GetState(); 9161d19a2f2SGreg Clayton 917b9c1b51eSKate Stone if (StateIsStoppedState(state, true)) { 9181d19a2f2SGreg Clayton std::vector<uint8_t> payload_bytes; 919b9c1b51eSKate Stone const char *ascii_hex_bytes_cstr = 920b9c1b51eSKate Stone m_packet_data.GetOptionValue().GetCurrentValue(); 921b9c1b51eSKate Stone if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0]) { 9221d19a2f2SGreg Clayton StringExtractor extractor(ascii_hex_bytes_cstr); 923b9c1b51eSKate Stone const size_t ascii_hex_bytes_cstr_len = 924b9c1b51eSKate Stone extractor.GetStringRef().size(); 925b9c1b51eSKate Stone if (ascii_hex_bytes_cstr_len & 1) { 926b9c1b51eSKate Stone result.AppendErrorWithFormat("payload data must contain an " 927b9c1b51eSKate Stone "even number of ASCII hex " 928b9c1b51eSKate Stone "characters: '%s'", 929b9c1b51eSKate Stone ascii_hex_bytes_cstr); 9301d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9311d19a2f2SGreg Clayton return false; 9321d19a2f2SGreg Clayton } 9331d19a2f2SGreg Clayton payload_bytes.resize(ascii_hex_bytes_cstr_len / 2); 934b9c1b51eSKate Stone if (extractor.GetHexBytes(payload_bytes, '\xdd') != 935b9c1b51eSKate Stone payload_bytes.size()) { 936b9c1b51eSKate Stone result.AppendErrorWithFormat("payload data must only contain " 937b9c1b51eSKate Stone "ASCII hex characters (no " 938b9c1b51eSKate Stone "spaces or hex prefixes): '%s'", 939b9c1b51eSKate Stone ascii_hex_bytes_cstr); 9401d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9411d19a2f2SGreg Clayton return false; 9421d19a2f2SGreg Clayton } 9431d19a2f2SGreg Clayton } 94497206d57SZachary Turner Status error; 9451d19a2f2SGreg Clayton DataExtractor reply; 946b9c1b51eSKate Stone process->GetCommunication().SendRawRequest( 947b9c1b51eSKate Stone command_byte, 9481d19a2f2SGreg Clayton payload_bytes.empty() ? NULL : payload_bytes.data(), 949b9c1b51eSKate Stone payload_bytes.size(), reply, error); 9501d19a2f2SGreg Clayton 951b9c1b51eSKate Stone if (error.Success()) { 9521d19a2f2SGreg Clayton // Copy the binary bytes into a hex ASCII string for the result 9531d19a2f2SGreg Clayton StreamString packet; 954b9c1b51eSKate Stone packet.PutBytesAsRawHex8( 955b9c1b51eSKate Stone reply.GetDataStart(), reply.GetByteSize(), 956b9c1b51eSKate Stone endian::InlHostByteOrder(), endian::InlHostByteOrder()); 957c156427dSZachary Turner result.AppendMessage(packet.GetString()); 9581d19a2f2SGreg Clayton result.SetStatus(eReturnStatusSuccessFinishResult); 9591d19a2f2SGreg Clayton return true; 960b9c1b51eSKate Stone } else { 9611d19a2f2SGreg Clayton const char *error_cstr = error.AsCString(); 9621d19a2f2SGreg Clayton if (error_cstr && error_cstr[0]) 9631d19a2f2SGreg Clayton result.AppendError(error_cstr); 9641d19a2f2SGreg Clayton else 965b9c1b51eSKate Stone result.AppendErrorWithFormat("unknown error 0x%8.8x", 966b9c1b51eSKate Stone error.GetError()); 9671d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9681d19a2f2SGreg Clayton return false; 9691d19a2f2SGreg Clayton } 970b9c1b51eSKate Stone } else { 971b9c1b51eSKate Stone result.AppendErrorWithFormat("process must be stopped in order " 972b9c1b51eSKate Stone "to send KDP packets, state is %s", 973b9c1b51eSKate Stone StateAsCString(state)); 9741d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9751d19a2f2SGreg Clayton } 976b9c1b51eSKate Stone } else { 9771d19a2f2SGreg Clayton result.AppendError("invalid process"); 9781d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9791d19a2f2SGreg Clayton } 980b9c1b51eSKate Stone } else { 981b9c1b51eSKate Stone result.AppendErrorWithFormat("invalid command byte 0x%" PRIx64 982b9c1b51eSKate Stone ", valid values are 1 - 255", 983b9c1b51eSKate Stone command_byte); 9841d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9851d19a2f2SGreg Clayton } 9861d19a2f2SGreg Clayton } 987b9c1b51eSKate Stone } else { 988b9c1b51eSKate Stone result.AppendErrorWithFormat("'%s' takes no arguments, only options.", 989b9c1b51eSKate Stone m_cmd_name.c_str()); 9901d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9911d19a2f2SGreg Clayton } 9921d19a2f2SGreg Clayton return false; 9931d19a2f2SGreg Clayton } 9941d19a2f2SGreg Clayton }; 9951d19a2f2SGreg Clayton 996b9c1b51eSKate Stone class CommandObjectProcessKDPPacket : public CommandObjectMultiword { 9971d19a2f2SGreg Clayton private: 9981d19a2f2SGreg Clayton public: 999b9c1b51eSKate Stone CommandObjectProcessKDPPacket(CommandInterpreter &interpreter) 1000b9c1b51eSKate Stone : CommandObjectMultiword(interpreter, "process plugin packet", 10011d19a2f2SGreg Clayton "Commands that deal with KDP remote packets.", 1002b9c1b51eSKate Stone NULL) { 1003b9c1b51eSKate Stone LoadSubCommand( 1004b9c1b51eSKate Stone "send", 1005b9c1b51eSKate Stone CommandObjectSP(new CommandObjectProcessKDPPacketSend(interpreter))); 10061d19a2f2SGreg Clayton } 10071d19a2f2SGreg Clayton 1008b9c1b51eSKate Stone ~CommandObjectProcessKDPPacket() {} 10091d19a2f2SGreg Clayton }; 10101d19a2f2SGreg Clayton 1011b9c1b51eSKate Stone class CommandObjectMultiwordProcessKDP : public CommandObjectMultiword { 10121d19a2f2SGreg Clayton public: 10137428a18cSKate Stone CommandObjectMultiwordProcessKDP(CommandInterpreter &interpreter) 1014b9c1b51eSKate Stone : CommandObjectMultiword( 1015b9c1b51eSKate Stone interpreter, "process plugin", 1016b9c1b51eSKate Stone "Commands for operating on a ProcessKDP process.", 1017b9c1b51eSKate Stone "process plugin <subcommand> [<subcommand-options>]") { 1018b9c1b51eSKate Stone LoadSubCommand("packet", CommandObjectSP(new CommandObjectProcessKDPPacket( 1019b9c1b51eSKate Stone interpreter))); 10201d19a2f2SGreg Clayton } 10211d19a2f2SGreg Clayton 1022b9c1b51eSKate Stone ~CommandObjectMultiwordProcessKDP() {} 10231d19a2f2SGreg Clayton }; 10241d19a2f2SGreg Clayton 1025b9c1b51eSKate Stone CommandObject *ProcessKDP::GetPluginCommandObject() { 10261d19a2f2SGreg Clayton if (!m_command_sp) 1027796ac80bSJonas Devlieghere m_command_sp = std::make_shared<CommandObjectMultiwordProcessKDP>( 1028796ac80bSJonas Devlieghere GetTarget().GetDebugger().GetCommandInterpreter()); 10291d19a2f2SGreg Clayton return m_command_sp.get(); 10301d19a2f2SGreg Clayton } 1031