180814287SRaphael Isemann //===-- ProcessKDP.cpp ----------------------------------------------------===// 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 53*fbb4d1e4SJonas Devlieghere LLDB_PLUGIN(ProcessKDP); 54*fbb4d1e4SJonas Devlieghere 557f98240dSGreg Clayton namespace { 567f98240dSGreg Clayton 57971f9ca6SJonas Devlieghere #define LLDB_PROPERTIES_processkdp 586a253d37SJordan Rupprecht #include "ProcessKDPProperties.inc" 597f98240dSGreg Clayton 60971f9ca6SJonas Devlieghere enum { 61971f9ca6SJonas Devlieghere #define LLDB_PROPERTIES_processkdp 626a253d37SJordan Rupprecht #include "ProcessKDPPropertiesEnum.inc" 63971f9ca6SJonas Devlieghere }; 647f98240dSGreg Clayton 65b9c1b51eSKate Stone class PluginProperties : public Properties { 667f98240dSGreg Clayton public: 67b9c1b51eSKate Stone static ConstString GetSettingName() { 687f98240dSGreg Clayton return ProcessKDP::GetPluginNameStatic(); 697f98240dSGreg Clayton } 707f98240dSGreg Clayton 71b9c1b51eSKate Stone PluginProperties() : Properties() { 72796ac80bSJonas Devlieghere m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); 73a8ea5955SJonas Devlieghere m_collection_sp->Initialize(g_processkdp_properties); 747f98240dSGreg Clayton } 757f98240dSGreg Clayton 76b9c1b51eSKate Stone virtual ~PluginProperties() {} 777f98240dSGreg Clayton 78b9c1b51eSKate Stone uint64_t GetPacketTimeout() { 79971f9ca6SJonas Devlieghere const uint32_t idx = ePropertyKDPPacketTimeout; 80b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsUInt64( 81a8ea5955SJonas Devlieghere NULL, idx, g_processkdp_properties[idx].default_uint_value); 827f98240dSGreg Clayton } 837f98240dSGreg Clayton }; 847f98240dSGreg Clayton 857f98240dSGreg Clayton typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP; 867f98240dSGreg Clayton 87b9c1b51eSKate Stone static const ProcessKDPPropertiesSP &GetGlobalPluginProperties() { 887f98240dSGreg Clayton static ProcessKDPPropertiesSP g_settings_sp; 897f98240dSGreg Clayton if (!g_settings_sp) 90796ac80bSJonas Devlieghere g_settings_sp = std::make_shared<PluginProperties>(); 917f98240dSGreg Clayton return g_settings_sp; 927f98240dSGreg Clayton } 937f98240dSGreg Clayton 947f98240dSGreg Clayton } // anonymous namespace end 957f98240dSGreg Clayton 96ba4e61d3SAndrew Kaylor static const lldb::tid_t g_kernel_tid = 1; 97ba4e61d3SAndrew Kaylor 98b9c1b51eSKate Stone ConstString ProcessKDP::GetPluginNameStatic() { 9957abc5d6SGreg Clayton static ConstString g_name("kdp-remote"); 10057abc5d6SGreg Clayton return g_name; 101f9765acdSGreg Clayton } 102f9765acdSGreg Clayton 103b9c1b51eSKate Stone const char *ProcessKDP::GetPluginDescriptionStatic() { 104b9c1b51eSKate Stone return "KDP Remote protocol based debugging plug-in for darwin kernel " 105b9c1b51eSKate Stone "debugging."; 106f9765acdSGreg Clayton } 107f9765acdSGreg Clayton 108b9c1b51eSKate Stone void ProcessKDP::Terminate() { 109f9765acdSGreg Clayton PluginManager::UnregisterPlugin(ProcessKDP::CreateInstance); 110f9765acdSGreg Clayton } 111f9765acdSGreg Clayton 112b9c1b51eSKate Stone lldb::ProcessSP ProcessKDP::CreateInstance(TargetSP target_sp, 113583bbb1dSJim Ingham ListenerSP listener_sp, 114b9c1b51eSKate Stone const FileSpec *crash_file_path) { 115c3776bf2SGreg Clayton lldb::ProcessSP process_sp; 116c3776bf2SGreg Clayton if (crash_file_path == NULL) 117796ac80bSJonas Devlieghere process_sp = std::make_shared<ProcessKDP>(target_sp, listener_sp); 118c3776bf2SGreg Clayton return process_sp; 119f9765acdSGreg Clayton } 120f9765acdSGreg Clayton 121b9c1b51eSKate Stone bool ProcessKDP::CanDebug(TargetSP target_sp, bool plugin_specified_by_name) { 122596ed24eSGreg Clayton if (plugin_specified_by_name) 123596ed24eSGreg Clayton return true; 124596ed24eSGreg Clayton 125f9765acdSGreg Clayton // For now we are just making sure the file exists for a given module 1265a3bb64fSJim Ingham Module *exe_module = target_sp->GetExecutableModulePointer(); 127b9c1b51eSKate Stone if (exe_module) { 1285a3bb64fSJim Ingham const llvm::Triple &triple_ref = target_sp->GetArchitecture().GetTriple(); 129b9c1b51eSKate Stone switch (triple_ref.getOS()) { 130b9c1b51eSKate Stone case llvm::Triple::Darwin: // Should use "macosx" for desktop and "ios" for 131b9c1b51eSKate Stone // iOS, but accept darwin just in case 13270512317SGreg Clayton case llvm::Triple::MacOSX: // For desktop targets 13370512317SGreg Clayton case llvm::Triple::IOS: // For arm targets 134a814f704SJason Molenda case llvm::Triple::TvOS: 135a814f704SJason Molenda case llvm::Triple::WatchOS: 136b9c1b51eSKate Stone if (triple_ref.getVendor() == llvm::Triple::Apple) { 137aa149cbdSGreg Clayton ObjectFile *exe_objfile = exe_module->GetObjectFile(); 138f9765acdSGreg Clayton if (exe_objfile->GetType() == ObjectFile::eTypeExecutable && 139f9765acdSGreg Clayton exe_objfile->GetStrata() == ObjectFile::eStrataKernel) 140f9765acdSGreg Clayton return true; 141f9765acdSGreg Clayton } 14270512317SGreg Clayton break; 14370512317SGreg Clayton 14470512317SGreg Clayton default: 14570512317SGreg Clayton break; 14670512317SGreg Clayton } 147f9765acdSGreg Clayton } 148596ed24eSGreg Clayton return false; 1493a29bdbeSGreg Clayton } 150f9765acdSGreg Clayton 151f9765acdSGreg Clayton // ProcessKDP constructor 152b9c1b51eSKate Stone ProcessKDP::ProcessKDP(TargetSP target_sp, ListenerSP listener_sp) 153b9c1b51eSKate Stone : Process(target_sp, listener_sp), 154f9765acdSGreg Clayton m_comm("lldb.process.kdp-remote.communication"), 1554bddaeb5SJim Ingham m_async_broadcaster(NULL, "lldb.process.kdp-remote.async-broadcaster"), 156b9c1b51eSKate Stone m_dyld_plugin_name(), m_kernel_load_addr(LLDB_INVALID_ADDRESS), 157b9c1b51eSKate Stone m_command_sp(), m_kernel_thread_wp() { 158b9c1b51eSKate Stone m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, 159b9c1b51eSKate Stone "async thread should exit"); 160b9c1b51eSKate Stone m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, 161b9c1b51eSKate Stone "async thread continue"); 162b9c1b51eSKate Stone const uint64_t timeout_seconds = 163b9c1b51eSKate Stone GetGlobalPluginProperties()->GetPacketTimeout(); 1647f98240dSGreg Clayton if (timeout_seconds > 0) 1655cddd608SPavel Labath m_comm.SetPacketTimeout(std::chrono::seconds(timeout_seconds)); 166f9765acdSGreg Clayton } 167f9765acdSGreg Clayton 168f9765acdSGreg Clayton // Destructor 169b9c1b51eSKate Stone ProcessKDP::~ProcessKDP() { 170f9765acdSGreg Clayton Clear(); 17105097246SAdrian Prantl // We need to call finalize on the process before destroying ourselves to 17205097246SAdrian Prantl // make sure all of the broadcaster cleanup goes as planned. If we destruct 17305097246SAdrian Prantl // this class, then Process::~Process() might have problems trying to fully 17405097246SAdrian Prantl // destroy the broadcaster. 175e24c4acfSGreg Clayton Finalize(); 176f9765acdSGreg Clayton } 177f9765acdSGreg Clayton 178f9765acdSGreg Clayton // PluginInterface 179b9c1b51eSKate Stone lldb_private::ConstString ProcessKDP::GetPluginName() { 180f9765acdSGreg Clayton return GetPluginNameStatic(); 181f9765acdSGreg Clayton } 182f9765acdSGreg Clayton 183b9c1b51eSKate Stone uint32_t ProcessKDP::GetPluginVersion() { return 1; } 184f9765acdSGreg Clayton 18597206d57SZachary Turner Status ProcessKDP::WillLaunch(Module *module) { 18697206d57SZachary Turner Status error; 187f9765acdSGreg Clayton error.SetErrorString("launching not supported in kdp-remote plug-in"); 188f9765acdSGreg Clayton return error; 189f9765acdSGreg Clayton } 190f9765acdSGreg Clayton 19197206d57SZachary Turner Status ProcessKDP::WillAttachToProcessWithID(lldb::pid_t pid) { 19297206d57SZachary Turner Status error; 193b9c1b51eSKate Stone error.SetErrorString( 194b9c1b51eSKate Stone "attaching to a by process ID not supported in kdp-remote plug-in"); 195f9765acdSGreg Clayton return error; 196f9765acdSGreg Clayton } 197f9765acdSGreg Clayton 19897206d57SZachary Turner Status ProcessKDP::WillAttachToProcessWithName(const char *process_name, 199b9c1b51eSKate Stone bool wait_for_launch) { 20097206d57SZachary Turner Status error; 201b9c1b51eSKate Stone error.SetErrorString( 202b9c1b51eSKate Stone "attaching to a by process name not supported in kdp-remote plug-in"); 203f9765acdSGreg Clayton return error; 204f9765acdSGreg Clayton } 205f9765acdSGreg Clayton 206b9c1b51eSKate Stone bool ProcessKDP::GetHostArchitecture(ArchSpec &arch) { 207a3706888SGreg Clayton uint32_t cpu = m_comm.GetCPUType(); 208b9c1b51eSKate Stone if (cpu) { 209a3706888SGreg Clayton uint32_t sub = m_comm.GetCPUSubtype(); 210a3706888SGreg Clayton arch.SetArchitecture(eArchTypeMachO, cpu, sub); 211a3706888SGreg Clayton // Leave architecture vendor as unspecified unknown 212a3706888SGreg Clayton arch.GetTriple().setVendor(llvm::Triple::UnknownVendor); 213a3706888SGreg Clayton arch.GetTriple().setVendorName(llvm::StringRef()); 214a3706888SGreg Clayton return true; 215a3706888SGreg Clayton } 216a3706888SGreg Clayton arch.Clear(); 217a3706888SGreg Clayton return false; 218a3706888SGreg Clayton } 219a3706888SGreg Clayton 22097206d57SZachary Turner Status ProcessKDP::DoConnectRemote(Stream *strm, llvm::StringRef remote_url) { 22197206d57SZachary Turner Status error; 2223a29bdbeSGreg Clayton 22305097246SAdrian Prantl // Don't let any JIT happen when doing KDP as we can't allocate memory and we 22405097246SAdrian Prantl // don't want to be mucking with threads that might already be handling 22505097246SAdrian Prantl // exceptions 2267925fbbaSGreg Clayton SetCanJIT(false); 2277925fbbaSGreg Clayton 2283ce7e996SGreg Clayton if (remote_url.empty()) { 2293ce7e996SGreg Clayton error.SetErrorStringWithFormat("empty connection URL"); 2307925fbbaSGreg Clayton return error; 2317925fbbaSGreg Clayton } 2323a29bdbeSGreg Clayton 233d5b44036SJonas Devlieghere std::unique_ptr<ConnectionFileDescriptor> conn_up( 234b9c1b51eSKate Stone new ConnectionFileDescriptor()); 235d5b44036SJonas Devlieghere if (conn_up) { 2363a29bdbeSGreg Clayton // Only try once for now. 2373a29bdbeSGreg Clayton // TODO: check if we should be retrying? 2383a29bdbeSGreg Clayton const uint32_t max_retry_count = 1; 239b9c1b51eSKate Stone for (uint32_t retry_count = 0; retry_count < max_retry_count; 240b9c1b51eSKate Stone ++retry_count) { 241d5b44036SJonas Devlieghere if (conn_up->Connect(remote_url, &error) == eConnectionStatusSuccess) 2423a29bdbeSGreg Clayton break; 2433a29bdbeSGreg Clayton usleep(100000); 2443a29bdbeSGreg Clayton } 2453a29bdbeSGreg Clayton } 2463a29bdbeSGreg Clayton 247d5b44036SJonas Devlieghere if (conn_up->IsConnected()) { 248b9c1b51eSKate Stone const TCPSocket &socket = 249d5b44036SJonas Devlieghere static_cast<const TCPSocket &>(*conn_up->GetReadObject()); 250014bb7daSVince Harron const uint16_t reply_port = socket.GetLocalPortNumber(); 2513a29bdbeSGreg Clayton 252b9c1b51eSKate Stone if (reply_port != 0) { 253d5b44036SJonas Devlieghere m_comm.SetConnection(conn_up.release()); 2543a29bdbeSGreg Clayton 255b9c1b51eSKate Stone if (m_comm.SendRequestReattach(reply_port)) { 256b9c1b51eSKate Stone if (m_comm.SendRequestConnect(reply_port, reply_port, 257b9c1b51eSKate Stone "Greetings from LLDB...")) { 2583a29bdbeSGreg Clayton m_comm.GetVersion(); 2595a3bb64fSJim Ingham 260a3706888SGreg Clayton Target &target = GetTarget(); 261a3706888SGreg Clayton ArchSpec kernel_arch; 262a3706888SGreg Clayton // The host architecture 263a3706888SGreg Clayton GetHostArchitecture(kernel_arch); 264a3706888SGreg Clayton ArchSpec target_arch = target.GetArchitecture(); 265a3706888SGreg Clayton // Merge in any unspecified stuff into the target architecture in 266a3706888SGreg Clayton // case the target arch isn't set at all or incompletely. 267a3706888SGreg Clayton target_arch.MergeFrom(kernel_arch); 268a3706888SGreg Clayton target.SetArchitecture(target_arch); 2694bd4e7e3SJason Molenda 270b9c1b51eSKate Stone /* Get the kernel's UUID and load address via KDP_KERNELVERSION 271b9c1b51eSKate Stone * packet. */ 272840f12cfSJason Molenda /* An EFI kdp session has neither UUID nor load address. */ 2734bd4e7e3SJason Molenda 2744bd4e7e3SJason Molenda UUID kernel_uuid = m_comm.GetUUID(); 2754bd4e7e3SJason Molenda addr_t kernel_load_addr = m_comm.GetLoadAddress(); 2764bd4e7e3SJason Molenda 277b9c1b51eSKate Stone if (m_comm.RemoteIsEFI()) { 278b9c1b51eSKate Stone // Select an invalid plugin name for the dynamic loader so one 27905097246SAdrian Prantl // doesn't get used since EFI does its own manual loading via 28005097246SAdrian Prantl // python scripting 281a1bce2efSGreg Clayton static ConstString g_none_dynamic_loader("none"); 282a1bce2efSGreg Clayton m_dyld_plugin_name = g_none_dynamic_loader; 283a1bce2efSGreg Clayton 284a1bce2efSGreg Clayton if (kernel_uuid.IsValid()) { 28505097246SAdrian Prantl // If EFI passed in a UUID= try to lookup UUID The slide will not 28605097246SAdrian Prantl // be provided. But the UUID lookup will be used to launch EFI 28705097246SAdrian Prantl // debug scripts from the dSYM, that can load all of the symbols. 288a1bce2efSGreg Clayton ModuleSpec module_spec; 289a1bce2efSGreg Clayton module_spec.GetUUID() = kernel_uuid; 2905a3bb64fSJim Ingham module_spec.GetArchitecture() = target.GetArchitecture(); 291a1bce2efSGreg Clayton 292a1bce2efSGreg Clayton // Lookup UUID locally, before attempting dsymForUUID like action 293a313ec11SZachary Turner FileSpecList search_paths = 294a313ec11SZachary Turner Target::GetDefaultDebugFileSearchPaths(); 295b9c1b51eSKate Stone module_spec.GetSymbolFileSpec() = 296a313ec11SZachary Turner Symbols::LocateExecutableSymbolFile(module_spec, 297a313ec11SZachary Turner search_paths); 298b9c1b51eSKate Stone if (module_spec.GetSymbolFileSpec()) { 299b9c1b51eSKate Stone ModuleSpec executable_module_spec = 300b9c1b51eSKate Stone Symbols::LocateExecutableObjectFile(module_spec); 301dbd7fabaSJonas Devlieghere if (FileSystem::Instance().Exists( 302dbd7fabaSJonas Devlieghere executable_module_spec.GetFileSpec())) { 303b9c1b51eSKate Stone module_spec.GetFileSpec() = 304b9c1b51eSKate Stone executable_module_spec.GetFileSpec(); 3058825c5c9SJason Molenda } 3068825c5c9SJason Molenda } 307b9c1b51eSKate Stone if (!module_spec.GetSymbolFileSpec() || 308b9c1b51eSKate Stone !module_spec.GetSymbolFileSpec()) 309a1bce2efSGreg Clayton Symbols::DownloadObjectAndSymbolFile(module_spec, true); 310a1bce2efSGreg Clayton 311dbd7fabaSJonas Devlieghere if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { 312a3706888SGreg Clayton ModuleSP module_sp(new Module(module_spec)); 313b9c1b51eSKate Stone if (module_sp.get() && module_sp->GetObjectFile()) { 314a1bce2efSGreg Clayton // Get the current target executable 3155a3bb64fSJim Ingham ModuleSP exe_module_sp(target.GetExecutableModule()); 316a1bce2efSGreg Clayton 317b9c1b51eSKate Stone // Make sure you don't already have the right module loaded 318b9c1b51eSKate Stone // and they will be uniqued 319a1bce2efSGreg Clayton if (exe_module_sp.get() != module_sp.get()) 320f9a07e9fSJonas Devlieghere target.SetExecutableModule(module_sp, eLoadDependentsNo); 321a1bce2efSGreg Clayton } 322a1bce2efSGreg Clayton } 323a1bce2efSGreg Clayton } 324b9c1b51eSKate Stone } else if (m_comm.RemoteIsDarwinKernel()) { 325b9c1b51eSKate Stone m_dyld_plugin_name = 326b9c1b51eSKate Stone DynamicLoaderDarwinKernel::GetPluginNameStatic(); 327b9c1b51eSKate Stone if (kernel_load_addr != LLDB_INVALID_ADDRESS) { 3285e8534efSJason Molenda m_kernel_load_addr = kernel_load_addr; 329a8ea4baeSJason Molenda } 3304bd4e7e3SJason Molenda } 3314bd4e7e3SJason Molenda 33297d5cf05SGreg Clayton // Set the thread ID 33397d5cf05SGreg Clayton UpdateThreadListIfNeeded(); 334a63d08c9SGreg Clayton SetID(1); 33556d9a1b3SGreg Clayton GetThreadList(); 336a63d08c9SGreg Clayton SetPrivateState(eStateStopped); 3375a3bb64fSJim Ingham StreamSP async_strm_sp(target.GetDebugger().GetAsyncOutputStream()); 338b9c1b51eSKate Stone if (async_strm_sp) { 3395b88216dSGreg Clayton const char *cstr; 340b9c1b51eSKate Stone if ((cstr = m_comm.GetKernelVersion()) != NULL) { 3415b88216dSGreg Clayton async_strm_sp->Printf("Version: %s\n", cstr); 34207e66e3eSGreg Clayton async_strm_sp->Flush(); 34307e66e3eSGreg Clayton } 3445b88216dSGreg Clayton // if ((cstr = m_comm.GetImagePath ()) != NULL) 3455b88216dSGreg Clayton // { 346b9c1b51eSKate Stone // async_strm_sp->Printf ("Image Path: 347b9c1b51eSKate Stone // %s\n", cstr); 3485b88216dSGreg Clayton // async_strm_sp->Flush(); 3495b88216dSGreg Clayton // } 35007e66e3eSGreg Clayton } 351b9c1b51eSKate Stone } else { 35297d5cf05SGreg Clayton error.SetErrorString("KDP_REATTACH failed"); 35397d5cf05SGreg Clayton } 354b9c1b51eSKate Stone } else { 35597d5cf05SGreg Clayton error.SetErrorString("KDP_REATTACH failed"); 3563a29bdbeSGreg Clayton } 357b9c1b51eSKate Stone } else { 3583a29bdbeSGreg Clayton error.SetErrorString("invalid reply port from UDP connection"); 3593a29bdbeSGreg Clayton } 360b9c1b51eSKate Stone } else { 3613a29bdbeSGreg Clayton if (error.Success()) 3623ce7e996SGreg Clayton error.SetErrorStringWithFormat("failed to connect to '%s'", 3633ce7e996SGreg Clayton remote_url.str().c_str()); 3643a29bdbeSGreg Clayton } 3653a29bdbeSGreg Clayton if (error.Fail()) 3663a29bdbeSGreg Clayton m_comm.Disconnect(); 3673a29bdbeSGreg Clayton 368f9765acdSGreg Clayton return error; 369f9765acdSGreg Clayton } 370f9765acdSGreg Clayton 371f9765acdSGreg Clayton // Process Control 37297206d57SZachary Turner Status ProcessKDP::DoLaunch(Module *exe_module, 37397206d57SZachary Turner ProcessLaunchInfo &launch_info) { 37497206d57SZachary Turner Status error; 375f9765acdSGreg Clayton error.SetErrorString("launching not supported in kdp-remote plug-in"); 376f9765acdSGreg Clayton return error; 377f9765acdSGreg Clayton } 378f9765acdSGreg Clayton 37997206d57SZachary Turner Status 38097206d57SZachary Turner ProcessKDP::DoAttachToProcessWithID(lldb::pid_t attach_pid, 38197206d57SZachary Turner const ProcessAttachInfo &attach_info) { 38297206d57SZachary Turner Status error; 383b9c1b51eSKate Stone error.SetErrorString( 3844ebdee0aSBruce Mitchener "attach to process by ID is not supported in kdp remote debugging"); 38584647048SHan Ming Ong return error; 38684647048SHan Ming Ong } 38784647048SHan Ming Ong 38897206d57SZachary Turner Status 38997206d57SZachary Turner ProcessKDP::DoAttachToProcessWithName(const char *process_name, 39097206d57SZachary Turner const ProcessAttachInfo &attach_info) { 39197206d57SZachary Turner Status error; 392b9c1b51eSKate Stone error.SetErrorString( 3934ebdee0aSBruce Mitchener "attach to process by name is not supported in kdp remote debugging"); 394f9765acdSGreg Clayton return error; 395f9765acdSGreg Clayton } 396f9765acdSGreg Clayton 397b9c1b51eSKate Stone void ProcessKDP::DidAttach(ArchSpec &process_arch) { 398bb006ce2SJim Ingham Process::DidAttach(process_arch); 399bb006ce2SJim Ingham 4005160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 40163e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DidAttach()"); 402b9c1b51eSKate Stone if (GetID() != LLDB_INVALID_PROCESS_ID) { 403a3706888SGreg Clayton GetHostArchitecture(process_arch); 404f9765acdSGreg Clayton } 405f9765acdSGreg Clayton } 406f9765acdSGreg Clayton 407b9c1b51eSKate Stone addr_t ProcessKDP::GetImageInfoAddress() { return m_kernel_load_addr; } 4085e8534efSJason Molenda 409b9c1b51eSKate Stone lldb_private::DynamicLoader *ProcessKDP::GetDynamicLoader() { 410d5b44036SJonas Devlieghere if (m_dyld_up.get() == NULL) 411d5b44036SJonas Devlieghere m_dyld_up.reset(DynamicLoader::FindPlugin( 412b9c1b51eSKate Stone this, 413b9c1b51eSKate Stone m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString())); 414d5b44036SJonas Devlieghere return m_dyld_up.get(); 4155e8534efSJason Molenda } 4165e8534efSJason Molenda 41797206d57SZachary Turner Status ProcessKDP::WillResume() { return Status(); } 418f9765acdSGreg Clayton 41997206d57SZachary Turner Status ProcessKDP::DoResume() { 42097206d57SZachary Turner Status error; 4215160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 4227925fbbaSGreg Clayton // Only start the async thread if we try to do any process control 423acee96aeSZachary Turner if (!m_async_thread.IsJoinable()) 4247925fbbaSGreg Clayton StartAsyncThread(); 4257925fbbaSGreg Clayton 42697d5cf05SGreg Clayton bool resume = false; 4277925fbbaSGreg Clayton 42897d5cf05SGreg Clayton // With KDP there is only one thread we can tell what to do 429ba4e61d3SAndrew Kaylor ThreadSP kernel_thread_sp(m_thread_list.FindThreadByProtocolID(g_kernel_tid)); 430ba4e61d3SAndrew Kaylor 431b9c1b51eSKate Stone if (kernel_thread_sp) { 432b9c1b51eSKate Stone const StateType thread_resume_state = 433b9c1b51eSKate Stone kernel_thread_sp->GetTemporaryResumeState(); 4346e0ff1a3SGreg Clayton 43563e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoResume() thread_resume_state = %s", 436b9c1b51eSKate Stone StateAsCString(thread_resume_state)); 437b9c1b51eSKate Stone switch (thread_resume_state) { 4387925fbbaSGreg Clayton case eStateSuspended: 43905097246SAdrian Prantl // Nothing to do here when a thread will stay suspended we just leave the 44005097246SAdrian Prantl // CPU mask bit set to zero for the thread 44163e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoResume() = suspended???"); 4427925fbbaSGreg Clayton break; 4437925fbbaSGreg Clayton 444b9c1b51eSKate Stone case eStateStepping: { 445b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 446b9c1b51eSKate Stone kernel_thread_sp->GetRegisterContext()); 4471afa68edSGreg Clayton 448b9c1b51eSKate Stone if (reg_ctx_sp) { 44963e5fb76SJonas Devlieghere LLDB_LOGF( 45063e5fb76SJonas Devlieghere log, 451b9c1b51eSKate Stone "ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (true);"); 4521afa68edSGreg Clayton reg_ctx_sp->HardwareSingleStep(true); 45397d5cf05SGreg Clayton resume = true; 454b9c1b51eSKate Stone } else { 455b9c1b51eSKate Stone error.SetErrorStringWithFormat( 456b9c1b51eSKate Stone "KDP thread 0x%llx has no register context", 457b9c1b51eSKate Stone kernel_thread_sp->GetID()); 4581afa68edSGreg Clayton } 459b9c1b51eSKate Stone } break; 4607925fbbaSGreg Clayton 461b9c1b51eSKate Stone case eStateRunning: { 462b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 463b9c1b51eSKate Stone kernel_thread_sp->GetRegisterContext()); 4641afa68edSGreg Clayton 465b9c1b51eSKate Stone if (reg_ctx_sp) { 46663e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep " 467b9c1b51eSKate Stone "(false);"); 4681afa68edSGreg Clayton reg_ctx_sp->HardwareSingleStep(false); 46997d5cf05SGreg Clayton resume = true; 470b9c1b51eSKate Stone } else { 471b9c1b51eSKate Stone error.SetErrorStringWithFormat( 472b9c1b51eSKate Stone "KDP thread 0x%llx has no register context", 473b9c1b51eSKate Stone kernel_thread_sp->GetID()); 4741afa68edSGreg Clayton } 475b9c1b51eSKate Stone } break; 4767925fbbaSGreg Clayton 4777925fbbaSGreg Clayton default: 47897d5cf05SGreg Clayton // The only valid thread resume states are listed above 479a322f36cSDavid Blaikie llvm_unreachable("invalid thread resume state"); 4804b1b8b3eSGreg Clayton } 4814b1b8b3eSGreg Clayton } 4827925fbbaSGreg Clayton 483b9c1b51eSKate Stone if (resume) { 48463e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoResume () sending resume"); 48597d5cf05SGreg Clayton 486b9c1b51eSKate Stone if (m_comm.SendRequestResume()) { 4877925fbbaSGreg Clayton m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue); 4887925fbbaSGreg Clayton SetPrivateState(eStateRunning); 489b9c1b51eSKate Stone } else 49007e66e3eSGreg Clayton error.SetErrorString("KDP resume failed"); 491b9c1b51eSKate Stone } else { 49297d5cf05SGreg Clayton error.SetErrorString("kernel thread is suspended"); 4937925fbbaSGreg Clayton } 4947925fbbaSGreg Clayton 495f9765acdSGreg Clayton return error; 496f9765acdSGreg Clayton } 497f9765acdSGreg Clayton 498b9c1b51eSKate Stone lldb::ThreadSP ProcessKDP::GetKernelThread() { 49997d5cf05SGreg Clayton // KDP only tells us about one thread/core. Any other threads will usually 50097d5cf05SGreg Clayton // be the ones that are read from memory by the OS plug-ins. 501ba4e61d3SAndrew Kaylor 502ba4e61d3SAndrew Kaylor ThreadSP thread_sp(m_kernel_thread_wp.lock()); 503b9c1b51eSKate Stone if (!thread_sp) { 504796ac80bSJonas Devlieghere thread_sp = std::make_shared<ThreadKDP>(*this, g_kernel_tid); 505ba4e61d3SAndrew Kaylor m_kernel_thread_wp = thread_sp; 506ba4e61d3SAndrew Kaylor } 50797d5cf05SGreg Clayton return thread_sp; 50897d5cf05SGreg Clayton } 50997d5cf05SGreg Clayton 510b9c1b51eSKate Stone bool ProcessKDP::UpdateThreadList(ThreadList &old_thread_list, 511b9c1b51eSKate Stone ThreadList &new_thread_list) { 512f9765acdSGreg Clayton // locker will keep a mutex locked until it goes out of scope 5135160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_THREAD)); 514250858a0SPavel Labath LLDB_LOGV(log, "pid = {0}", GetID()); 515f9765acdSGreg Clayton 51639da3efdSGreg Clayton // Even though there is a CPU mask, it doesn't mean we can see each CPU 517a868c13cSBruce Mitchener // individually, there is really only one. Lets call this thread 1. 518b9c1b51eSKate Stone ThreadSP thread_sp( 519b9c1b51eSKate Stone old_thread_list.FindThreadByProtocolID(g_kernel_tid, false)); 520ba4e61d3SAndrew Kaylor if (!thread_sp) 521ba4e61d3SAndrew Kaylor thread_sp = GetKernelThread(); 522ba4e61d3SAndrew Kaylor new_thread_list.AddThread(thread_sp); 52397d5cf05SGreg Clayton 5249fc13556SGreg Clayton return new_thread_list.GetSize(false) > 0; 525f9765acdSGreg Clayton } 526f9765acdSGreg Clayton 527b9c1b51eSKate Stone void ProcessKDP::RefreshStateAfterStop() { 52805097246SAdrian Prantl // Let all threads recover from stopping and do any clean up based on the 52905097246SAdrian Prantl // previous thread state (if any). 530f9765acdSGreg Clayton m_thread_list.RefreshStateAfterStop(); 531f9765acdSGreg Clayton } 532f9765acdSGreg Clayton 53397206d57SZachary Turner Status ProcessKDP::DoHalt(bool &caused_stop) { 53497206d57SZachary Turner Status error; 535f9765acdSGreg Clayton 536b9c1b51eSKate Stone if (m_comm.IsRunning()) { 537b9c1b51eSKate Stone if (m_destroy_in_process) { 5384ebdee0aSBruce Mitchener // If we are attempting to destroy, we need to not return an error to Halt 53905097246SAdrian Prantl // or DoDestroy won't get called. We are also currently running, so send 54005097246SAdrian Prantl // a process stopped event 54197d5cf05SGreg Clayton SetPrivateState(eStateStopped); 542b9c1b51eSKate Stone } else { 54397d5cf05SGreg Clayton error.SetErrorString("KDP cannot interrupt a running kernel"); 544f9765acdSGreg Clayton } 545f9765acdSGreg Clayton } 546f9765acdSGreg Clayton return error; 547f9765acdSGreg Clayton } 548f9765acdSGreg Clayton 54997206d57SZachary Turner Status ProcessKDP::DoDetach(bool keep_stopped) { 55097206d57SZachary Turner Status error; 5515160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 55263e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoDetach(keep_stopped = %i)", keep_stopped); 553f9765acdSGreg Clayton 554b9c1b51eSKate Stone if (m_comm.IsRunning()) { 55505097246SAdrian Prantl // We are running and we can't interrupt a running kernel, so we need to 55605097246SAdrian Prantl // just close the connection to the kernel and hope for the best 557b9c1b51eSKate Stone } else { 558b9c1b51eSKate Stone // If we are going to keep the target stopped, then don't send the 559b9c1b51eSKate Stone // disconnect message. 560b9c1b51eSKate Stone if (!keep_stopped && m_comm.IsConnected()) { 5616e0ff1a3SGreg Clayton const bool success = m_comm.SendRequestDisconnect(); 562b9c1b51eSKate Stone if (log) { 5636e0ff1a3SGreg Clayton if (success) 564b9c1b51eSKate Stone log->PutCString( 565b9c1b51eSKate Stone "ProcessKDP::DoDetach() detach packet sent successfully"); 566f9765acdSGreg Clayton else 567b9c1b51eSKate Stone log->PutCString( 568b9c1b51eSKate Stone "ProcessKDP::DoDetach() connection channel shutdown failed"); 569f9765acdSGreg Clayton } 5706e0ff1a3SGreg Clayton m_comm.Disconnect(); 5713a29bdbeSGreg Clayton } 57297d5cf05SGreg Clayton } 573f9765acdSGreg Clayton StopAsyncThread(); 57474d4193eSGreg Clayton m_comm.Clear(); 575f9765acdSGreg Clayton 576f9765acdSGreg Clayton SetPrivateState(eStateDetached); 577f9765acdSGreg Clayton ResumePrivateStateThread(); 578f9765acdSGreg Clayton 579f9765acdSGreg Clayton // KillDebugserverProcess (); 580f9765acdSGreg Clayton return error; 581f9765acdSGreg Clayton } 582f9765acdSGreg Clayton 58397206d57SZachary Turner Status ProcessKDP::DoDestroy() { 5847925fbbaSGreg Clayton // For KDP there really is no difference between destroy and detach 585acff8950SJim Ingham bool keep_stopped = false; 586acff8950SJim Ingham return DoDetach(keep_stopped); 587f9765acdSGreg Clayton } 588f9765acdSGreg Clayton 589f9765acdSGreg Clayton // Process Queries 590f9765acdSGreg Clayton 591b9c1b51eSKate Stone bool ProcessKDP::IsAlive() { 592a814f704SJason Molenda return m_comm.IsConnected() && Process::IsAlive(); 593f9765acdSGreg Clayton } 594f9765acdSGreg Clayton 595f9765acdSGreg Clayton // Process Memory 596b9c1b51eSKate Stone size_t ProcessKDP::DoReadMemory(addr_t addr, void *buf, size_t size, 59797206d57SZachary Turner Status &error) { 5988eb32817SJason Molenda uint8_t *data_buffer = (uint8_t *)buf; 599b9c1b51eSKate Stone if (m_comm.IsConnected()) { 6008eb32817SJason Molenda const size_t max_read_size = 512; 6018eb32817SJason Molenda size_t total_bytes_read = 0; 6028eb32817SJason Molenda 6038eb32817SJason Molenda // Read the requested amount of memory in 512 byte chunks 604b9c1b51eSKate Stone while (total_bytes_read < size) { 6058eb32817SJason Molenda size_t bytes_to_read_this_request = size - total_bytes_read; 606b9c1b51eSKate Stone if (bytes_to_read_this_request > max_read_size) { 6078eb32817SJason Molenda bytes_to_read_this_request = max_read_size; 6088eb32817SJason Molenda } 609b9c1b51eSKate Stone size_t bytes_read = m_comm.SendRequestReadMemory( 610b9c1b51eSKate Stone addr + total_bytes_read, data_buffer + total_bytes_read, 6118eb32817SJason Molenda bytes_to_read_this_request, error); 6128eb32817SJason Molenda total_bytes_read += bytes_read; 613b9c1b51eSKate Stone if (error.Fail() || bytes_read == 0) { 6148eb32817SJason Molenda return total_bytes_read; 6158eb32817SJason Molenda } 6168eb32817SJason Molenda } 6178eb32817SJason Molenda 6188eb32817SJason Molenda return total_bytes_read; 6198eb32817SJason Molenda } 620a63d08c9SGreg Clayton error.SetErrorString("not connected"); 621f9765acdSGreg Clayton return 0; 622f9765acdSGreg Clayton } 623f9765acdSGreg Clayton 624b9c1b51eSKate Stone size_t ProcessKDP::DoWriteMemory(addr_t addr, const void *buf, size_t size, 62597206d57SZachary Turner Status &error) { 6267925fbbaSGreg Clayton if (m_comm.IsConnected()) 6277925fbbaSGreg Clayton return m_comm.SendRequestWriteMemory(addr, buf, size, error); 6287925fbbaSGreg Clayton error.SetErrorString("not connected"); 629f9765acdSGreg Clayton return 0; 630f9765acdSGreg Clayton } 631f9765acdSGreg Clayton 632b9c1b51eSKate Stone lldb::addr_t ProcessKDP::DoAllocateMemory(size_t size, uint32_t permissions, 63397206d57SZachary Turner Status &error) { 634b9c1b51eSKate Stone error.SetErrorString( 6354ebdee0aSBruce Mitchener "memory allocation not supported in kdp remote debugging"); 636f9765acdSGreg Clayton return LLDB_INVALID_ADDRESS; 637f9765acdSGreg Clayton } 638f9765acdSGreg Clayton 63997206d57SZachary Turner Status ProcessKDP::DoDeallocateMemory(lldb::addr_t addr) { 64097206d57SZachary Turner Status error; 641b9c1b51eSKate Stone error.SetErrorString( 6424ebdee0aSBruce Mitchener "memory deallocation not supported in kdp remote debugging"); 643f9765acdSGreg Clayton return error; 644f9765acdSGreg Clayton } 645f9765acdSGreg Clayton 64697206d57SZachary Turner Status ProcessKDP::EnableBreakpointSite(BreakpointSite *bp_site) { 647b9c1b51eSKate Stone if (m_comm.LocalBreakpointsAreSupported()) { 64897206d57SZachary Turner Status error; 649b9c1b51eSKate Stone if (!bp_site->IsEnabled()) { 650b9c1b51eSKate Stone if (m_comm.SendRequestBreakpoint(true, bp_site->GetLoadAddress())) { 6515b88216dSGreg Clayton bp_site->SetEnabled(true); 6525b88216dSGreg Clayton bp_site->SetType(BreakpointSite::eExternal); 653b9c1b51eSKate Stone } else { 65407e66e3eSGreg Clayton error.SetErrorString("KDP set breakpoint failed"); 6555b88216dSGreg Clayton } 6565b88216dSGreg Clayton } 65707e66e3eSGreg Clayton return error; 65807e66e3eSGreg Clayton } 659f9765acdSGreg Clayton return EnableSoftwareBreakpoint(bp_site); 660f9765acdSGreg Clayton } 661f9765acdSGreg Clayton 66297206d57SZachary Turner Status ProcessKDP::DisableBreakpointSite(BreakpointSite *bp_site) { 663b9c1b51eSKate Stone if (m_comm.LocalBreakpointsAreSupported()) { 66497206d57SZachary Turner Status error; 665b9c1b51eSKate Stone if (bp_site->IsEnabled()) { 6665b88216dSGreg Clayton BreakpointSite::Type bp_type = bp_site->GetType(); 667b9c1b51eSKate Stone if (bp_type == BreakpointSite::eExternal) { 668b9c1b51eSKate Stone if (m_destroy_in_process && m_comm.IsRunning()) { 66997d5cf05SGreg Clayton // We are trying to destroy our connection and we are running 67097d5cf05SGreg Clayton bp_site->SetEnabled(false); 671b9c1b51eSKate Stone } else { 6725b88216dSGreg Clayton if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress())) 6735b88216dSGreg Clayton bp_site->SetEnabled(false); 6745b88216dSGreg Clayton else 67507e66e3eSGreg Clayton error.SetErrorString("KDP remove breakpoint failed"); 6765b88216dSGreg Clayton } 677b9c1b51eSKate Stone } else { 6785b88216dSGreg Clayton error = DisableSoftwareBreakpoint(bp_site); 6795b88216dSGreg Clayton } 6805b88216dSGreg Clayton } 68107e66e3eSGreg Clayton return error; 68207e66e3eSGreg Clayton } 683f9765acdSGreg Clayton return DisableSoftwareBreakpoint(bp_site); 684f9765acdSGreg Clayton } 685f9765acdSGreg Clayton 68697206d57SZachary Turner Status ProcessKDP::EnableWatchpoint(Watchpoint *wp, bool notify) { 68797206d57SZachary Turner Status error; 688b9c1b51eSKate Stone error.SetErrorString( 6894ebdee0aSBruce Mitchener "watchpoints are not supported in kdp remote debugging"); 690f9765acdSGreg Clayton return error; 691f9765acdSGreg Clayton } 692f9765acdSGreg Clayton 69397206d57SZachary Turner Status ProcessKDP::DisableWatchpoint(Watchpoint *wp, bool notify) { 69497206d57SZachary Turner Status error; 695b9c1b51eSKate Stone error.SetErrorString( 6964ebdee0aSBruce Mitchener "watchpoints are not supported in kdp remote debugging"); 697f9765acdSGreg Clayton return error; 698f9765acdSGreg Clayton } 699f9765acdSGreg Clayton 700b9c1b51eSKate Stone void ProcessKDP::Clear() { m_thread_list.Clear(); } 701f9765acdSGreg Clayton 70297206d57SZachary Turner Status ProcessKDP::DoSignal(int signo) { 70397206d57SZachary Turner Status error; 704b9c1b51eSKate Stone error.SetErrorString( 7054ebdee0aSBruce Mitchener "sending signals is not supported in kdp remote debugging"); 706f9765acdSGreg Clayton return error; 707f9765acdSGreg Clayton } 708f9765acdSGreg Clayton 709b9c1b51eSKate Stone void ProcessKDP::Initialize() { 710c5f28e2aSKamil Rytarowski static llvm::once_flag g_once_flag; 711f9765acdSGreg Clayton 712c5f28e2aSKamil Rytarowski llvm::call_once(g_once_flag, []() { 713f9765acdSGreg Clayton PluginManager::RegisterPlugin(GetPluginNameStatic(), 714b9c1b51eSKate Stone GetPluginDescriptionStatic(), CreateInstance, 715488c89edSBruce Mitchener DebuggerInitialize); 716f9765acdSGreg Clayton 7177b35b781SPavel Labath ProcessKDPLog::Initialize(); 718c8d69828SDavide Italiano }); 719f9765acdSGreg Clayton } 720f9765acdSGreg Clayton 721b9c1b51eSKate Stone void ProcessKDP::DebuggerInitialize(lldb_private::Debugger &debugger) { 722b9c1b51eSKate Stone if (!PluginManager::GetSettingForProcessPlugin( 723b9c1b51eSKate Stone debugger, PluginProperties::GetSettingName())) { 7247f98240dSGreg Clayton const bool is_global_setting = true; 725b9c1b51eSKate Stone PluginManager::CreateSettingForProcessPlugin( 726b9c1b51eSKate Stone debugger, GetGlobalPluginProperties()->GetValueProperties(), 7277f98240dSGreg Clayton ConstString("Properties for the kdp-remote process plug-in."), 7287f98240dSGreg Clayton is_global_setting); 7297f98240dSGreg Clayton } 7307f98240dSGreg Clayton } 7317f98240dSGreg Clayton 732b9c1b51eSKate Stone bool ProcessKDP::StartAsyncThread() { 7335160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 734f9765acdSGreg Clayton 73563e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::StartAsyncThread ()"); 736f9765acdSGreg Clayton 737acee96aeSZachary Turner if (m_async_thread.IsJoinable()) 7387925fbbaSGreg Clayton return true; 7397925fbbaSGreg Clayton 740f39c2e18SJonas Devlieghere llvm::Expected<HostThread> async_thread = ThreadLauncher::LaunchThread( 741f39c2e18SJonas Devlieghere "<lldb.process.kdp-remote.async>", ProcessKDP::AsyncThread, this); 742f39c2e18SJonas Devlieghere if (!async_thread) { 743f39c2e18SJonas Devlieghere LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), 744f39c2e18SJonas Devlieghere "failed to launch host thread: {}", 745f39c2e18SJonas Devlieghere llvm::toString(async_thread.takeError())); 746f39c2e18SJonas Devlieghere return false; 747f39c2e18SJonas Devlieghere } 748f39c2e18SJonas Devlieghere m_async_thread = *async_thread; 749acee96aeSZachary Turner return m_async_thread.IsJoinable(); 750f9765acdSGreg Clayton } 751f9765acdSGreg Clayton 752b9c1b51eSKate Stone void ProcessKDP::StopAsyncThread() { 7535160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 754f9765acdSGreg Clayton 75563e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::StopAsyncThread ()"); 756f9765acdSGreg Clayton 757f9765acdSGreg Clayton m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit); 758f9765acdSGreg Clayton 759f9765acdSGreg Clayton // Stop the stdio thread 760acee96aeSZachary Turner if (m_async_thread.IsJoinable()) 76139de3110SZachary Turner m_async_thread.Join(nullptr); 762f9765acdSGreg Clayton } 763f9765acdSGreg Clayton 764b9c1b51eSKate Stone void *ProcessKDP::AsyncThread(void *arg) { 765f9765acdSGreg Clayton ProcessKDP *process = (ProcessKDP *)arg; 766f9765acdSGreg Clayton 7677925fbbaSGreg Clayton const lldb::pid_t pid = process->GetID(); 7687925fbbaSGreg Clayton 7695160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 77063e5fb76SJonas Devlieghere LLDB_LOGF(log, 77163e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 772b9c1b51eSKate Stone ") thread starting...", 773b9c1b51eSKate Stone arg, pid); 774f9765acdSGreg Clayton 775583bbb1dSJim Ingham ListenerSP listener_sp(Listener::MakeListener("ProcessKDP::AsyncThread")); 776f9765acdSGreg Clayton EventSP event_sp; 777b9c1b51eSKate Stone const uint32_t desired_event_mask = 778b9c1b51eSKate Stone eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit; 779f9765acdSGreg Clayton 780b9c1b51eSKate Stone if (listener_sp->StartListeningForEvents(&process->m_async_broadcaster, 781b9c1b51eSKate Stone desired_event_mask) == 782b9c1b51eSKate Stone desired_event_mask) { 783f9765acdSGreg Clayton bool done = false; 784b9c1b51eSKate Stone while (!done) { 78563e5fb76SJonas Devlieghere LLDB_LOGF(log, 78663e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 787b9c1b51eSKate Stone ") listener.WaitForEvent (NULL, event_sp)...", 7887925fbbaSGreg Clayton pid); 789fafff0c5SPavel Labath if (listener_sp->GetEvent(event_sp, llvm::None)) { 7907925fbbaSGreg Clayton uint32_t event_type = event_sp->GetType(); 79163e5fb76SJonas Devlieghere LLDB_LOGF(log, 79263e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 793b9c1b51eSKate Stone ") Got an event of type: %d...", 794b9c1b51eSKate Stone pid, event_type); 795f9765acdSGreg Clayton 7967925fbbaSGreg Clayton // When we are running, poll for 1 second to try and get an exception 7977925fbbaSGreg Clayton // to indicate the process has stopped. If we don't get one, check to 7987925fbbaSGreg Clayton // make sure no one asked us to exit 7997925fbbaSGreg Clayton bool is_running = false; 8007925fbbaSGreg Clayton DataExtractor exc_reply_packet; 801b9c1b51eSKate Stone do { 802b9c1b51eSKate Stone switch (event_type) { 803b9c1b51eSKate Stone case eBroadcastBitAsyncContinue: { 8047925fbbaSGreg Clayton is_running = true; 805b9c1b51eSKate Stone if (process->m_comm.WaitForPacketWithTimeoutMicroSeconds( 806b9c1b51eSKate Stone exc_reply_packet, 1 * USEC_PER_SEC)) { 807ba4e61d3SAndrew Kaylor ThreadSP thread_sp(process->GetKernelThread()); 808b9c1b51eSKate Stone if (thread_sp) { 809b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 810b9c1b51eSKate Stone thread_sp->GetRegisterContext()); 8111afa68edSGreg Clayton if (reg_ctx_sp) 8121afa68edSGreg Clayton reg_ctx_sp->InvalidateAllRegisters(); 813b9c1b51eSKate Stone static_cast<ThreadKDP *>(thread_sp.get()) 814b9c1b51eSKate Stone ->SetStopInfoFrom_KDP_EXCEPTION(exc_reply_packet); 8151afa68edSGreg Clayton } 81697d5cf05SGreg Clayton 8177925fbbaSGreg Clayton // TODO: parse the stop reply packet 8187925fbbaSGreg Clayton is_running = false; 8197925fbbaSGreg Clayton process->SetPrivateState(eStateStopped); 820b9c1b51eSKate Stone } else { 8217925fbbaSGreg Clayton // Check to see if we are supposed to exit. There is no way to 8227925fbbaSGreg Clayton // interrupt a running kernel, so all we can do is wait for an 8237925fbbaSGreg Clayton // exception or detach... 824fafff0c5SPavel Labath if (listener_sp->GetEvent(event_sp, 825fafff0c5SPavel Labath std::chrono::microseconds(0))) { 8267925fbbaSGreg Clayton // We got an event, go through the loop again 8277925fbbaSGreg Clayton event_type = event_sp->GetType(); 8287925fbbaSGreg Clayton } 829f9765acdSGreg Clayton } 830b9c1b51eSKate Stone } break; 831f9765acdSGreg Clayton 832f9765acdSGreg Clayton case eBroadcastBitAsyncThreadShouldExit: 83363e5fb76SJonas Devlieghere LLDB_LOGF(log, 83463e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 835b9c1b51eSKate Stone ") got eBroadcastBitAsyncThreadShouldExit...", 8367925fbbaSGreg Clayton pid); 837f9765acdSGreg Clayton done = true; 8387925fbbaSGreg Clayton is_running = false; 839f9765acdSGreg Clayton break; 840f9765acdSGreg Clayton 841f9765acdSGreg Clayton default: 84263e5fb76SJonas Devlieghere LLDB_LOGF(log, 84363e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 844b9c1b51eSKate Stone ") got unknown event 0x%8.8x", 845b9c1b51eSKate Stone pid, event_type); 846f9765acdSGreg Clayton done = true; 8477925fbbaSGreg Clayton is_running = false; 848f9765acdSGreg Clayton break; 849f9765acdSGreg Clayton } 8507925fbbaSGreg Clayton } while (is_running); 851b9c1b51eSKate Stone } else { 85263e5fb76SJonas Devlieghere LLDB_LOGF(log, 85363e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 854b9c1b51eSKate Stone ") listener.WaitForEvent (NULL, event_sp) => false", 8557925fbbaSGreg Clayton pid); 856f9765acdSGreg Clayton done = true; 857f9765acdSGreg Clayton } 858f9765acdSGreg Clayton } 859f9765acdSGreg Clayton } 860f9765acdSGreg Clayton 86163e5fb76SJonas Devlieghere LLDB_LOGF(log, 86263e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 863b9c1b51eSKate Stone ") thread exiting...", 864b9c1b51eSKate Stone arg, pid); 865f9765acdSGreg Clayton 86639de3110SZachary Turner process->m_async_thread.Reset(); 867f9765acdSGreg Clayton return NULL; 868f9765acdSGreg Clayton } 869f9765acdSGreg Clayton 870b9c1b51eSKate Stone class CommandObjectProcessKDPPacketSend : public CommandObjectParsed { 8711d19a2f2SGreg Clayton private: 8721d19a2f2SGreg Clayton OptionGroupOptions m_option_group; 8731d19a2f2SGreg Clayton OptionGroupUInt64 m_command_byte; 8741d19a2f2SGreg Clayton OptionGroupString m_packet_data; 8751d19a2f2SGreg Clayton 876b9c1b51eSKate Stone virtual Options *GetOptions() { return &m_option_group; } 8771d19a2f2SGreg Clayton 8781d19a2f2SGreg Clayton public: 879b9c1b51eSKate Stone CommandObjectProcessKDPPacketSend(CommandInterpreter &interpreter) 880b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "process plugin packet send", 881b9c1b51eSKate Stone "Send a custom packet through the KDP protocol by " 882b9c1b51eSKate Stone "specifying the command byte and the packet " 883b9c1b51eSKate Stone "payload data. A packet will be sent with a " 884b9c1b51eSKate Stone "correct header and payload, and the raw result " 885b9c1b51eSKate Stone "bytes will be displayed as a string value. ", 8861d19a2f2SGreg Clayton NULL), 887e1cfbc79STodd Fiala m_option_group(), 888b9c1b51eSKate Stone m_command_byte(LLDB_OPT_SET_1, true, "command", 'c', 0, eArgTypeNone, 889b9c1b51eSKate Stone "Specify the command byte to use when sending the KDP " 890b9c1b51eSKate Stone "request packet.", 891b9c1b51eSKate Stone 0), 892b9c1b51eSKate Stone m_packet_data(LLDB_OPT_SET_1, false, "payload", 'p', 0, eArgTypeNone, 893b9c1b51eSKate Stone "Specify packet payload bytes as a hex ASCII string with " 894b9c1b51eSKate Stone "no spaces or hex prefixes.", 895b9c1b51eSKate Stone NULL) { 8961d19a2f2SGreg Clayton m_option_group.Append(&m_command_byte, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 8971d19a2f2SGreg Clayton m_option_group.Append(&m_packet_data, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 8981d19a2f2SGreg Clayton m_option_group.Finalize(); 8991d19a2f2SGreg Clayton } 9001d19a2f2SGreg Clayton 901b9c1b51eSKate Stone ~CommandObjectProcessKDPPacketSend() {} 9021d19a2f2SGreg Clayton 903b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) { 9041d19a2f2SGreg Clayton const size_t argc = command.GetArgumentCount(); 905b9c1b51eSKate Stone if (argc == 0) { 906b9c1b51eSKate Stone if (!m_command_byte.GetOptionValue().OptionWasSet()) { 907b9c1b51eSKate Stone result.AppendError( 908b9c1b51eSKate Stone "the --command option must be set to a valid command byte"); 9091d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 910b9c1b51eSKate Stone } else { 911b9c1b51eSKate Stone const uint64_t command_byte = 912b9c1b51eSKate Stone m_command_byte.GetOptionValue().GetUInt64Value(0); 913b9c1b51eSKate Stone if (command_byte > 0 && command_byte <= UINT8_MAX) { 914b9c1b51eSKate Stone ProcessKDP *process = 915b9c1b51eSKate Stone (ProcessKDP *)m_interpreter.GetExecutionContext().GetProcessPtr(); 916b9c1b51eSKate Stone if (process) { 9171d19a2f2SGreg Clayton const StateType state = process->GetState(); 9181d19a2f2SGreg Clayton 919b9c1b51eSKate Stone if (StateIsStoppedState(state, true)) { 9201d19a2f2SGreg Clayton std::vector<uint8_t> payload_bytes; 921b9c1b51eSKate Stone const char *ascii_hex_bytes_cstr = 922b9c1b51eSKate Stone m_packet_data.GetOptionValue().GetCurrentValue(); 923b9c1b51eSKate Stone if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0]) { 9241d19a2f2SGreg Clayton StringExtractor extractor(ascii_hex_bytes_cstr); 925b9c1b51eSKate Stone const size_t ascii_hex_bytes_cstr_len = 926b9c1b51eSKate Stone extractor.GetStringRef().size(); 927b9c1b51eSKate Stone if (ascii_hex_bytes_cstr_len & 1) { 928b9c1b51eSKate Stone result.AppendErrorWithFormat("payload data must contain an " 929b9c1b51eSKate Stone "even number of ASCII hex " 930b9c1b51eSKate Stone "characters: '%s'", 931b9c1b51eSKate Stone ascii_hex_bytes_cstr); 9321d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9331d19a2f2SGreg Clayton return false; 9341d19a2f2SGreg Clayton } 9351d19a2f2SGreg Clayton payload_bytes.resize(ascii_hex_bytes_cstr_len / 2); 936b9c1b51eSKate Stone if (extractor.GetHexBytes(payload_bytes, '\xdd') != 937b9c1b51eSKate Stone payload_bytes.size()) { 938b9c1b51eSKate Stone result.AppendErrorWithFormat("payload data must only contain " 939b9c1b51eSKate Stone "ASCII hex characters (no " 940b9c1b51eSKate Stone "spaces or hex prefixes): '%s'", 941b9c1b51eSKate Stone ascii_hex_bytes_cstr); 9421d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9431d19a2f2SGreg Clayton return false; 9441d19a2f2SGreg Clayton } 9451d19a2f2SGreg Clayton } 94697206d57SZachary Turner Status error; 9471d19a2f2SGreg Clayton DataExtractor reply; 948b9c1b51eSKate Stone process->GetCommunication().SendRawRequest( 949b9c1b51eSKate Stone command_byte, 9501d19a2f2SGreg Clayton payload_bytes.empty() ? NULL : payload_bytes.data(), 951b9c1b51eSKate Stone payload_bytes.size(), reply, error); 9521d19a2f2SGreg Clayton 953b9c1b51eSKate Stone if (error.Success()) { 9541d19a2f2SGreg Clayton // Copy the binary bytes into a hex ASCII string for the result 9551d19a2f2SGreg Clayton StreamString packet; 956b9c1b51eSKate Stone packet.PutBytesAsRawHex8( 957b9c1b51eSKate Stone reply.GetDataStart(), reply.GetByteSize(), 958b9c1b51eSKate Stone endian::InlHostByteOrder(), endian::InlHostByteOrder()); 959c156427dSZachary Turner result.AppendMessage(packet.GetString()); 9601d19a2f2SGreg Clayton result.SetStatus(eReturnStatusSuccessFinishResult); 9611d19a2f2SGreg Clayton return true; 962b9c1b51eSKate Stone } else { 9631d19a2f2SGreg Clayton const char *error_cstr = error.AsCString(); 9641d19a2f2SGreg Clayton if (error_cstr && error_cstr[0]) 9651d19a2f2SGreg Clayton result.AppendError(error_cstr); 9661d19a2f2SGreg Clayton else 967b9c1b51eSKate Stone result.AppendErrorWithFormat("unknown error 0x%8.8x", 968b9c1b51eSKate Stone error.GetError()); 9691d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9701d19a2f2SGreg Clayton return false; 9711d19a2f2SGreg Clayton } 972b9c1b51eSKate Stone } else { 973b9c1b51eSKate Stone result.AppendErrorWithFormat("process must be stopped in order " 974b9c1b51eSKate Stone "to send KDP packets, state is %s", 975b9c1b51eSKate Stone StateAsCString(state)); 9761d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9771d19a2f2SGreg Clayton } 978b9c1b51eSKate Stone } else { 9791d19a2f2SGreg Clayton result.AppendError("invalid process"); 9801d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9811d19a2f2SGreg Clayton } 982b9c1b51eSKate Stone } else { 983b9c1b51eSKate Stone result.AppendErrorWithFormat("invalid command byte 0x%" PRIx64 984b9c1b51eSKate Stone ", valid values are 1 - 255", 985b9c1b51eSKate Stone command_byte); 9861d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9871d19a2f2SGreg Clayton } 9881d19a2f2SGreg Clayton } 989b9c1b51eSKate Stone } else { 990b9c1b51eSKate Stone result.AppendErrorWithFormat("'%s' takes no arguments, only options.", 991b9c1b51eSKate Stone m_cmd_name.c_str()); 9921d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9931d19a2f2SGreg Clayton } 9941d19a2f2SGreg Clayton return false; 9951d19a2f2SGreg Clayton } 9961d19a2f2SGreg Clayton }; 9971d19a2f2SGreg Clayton 998b9c1b51eSKate Stone class CommandObjectProcessKDPPacket : public CommandObjectMultiword { 9991d19a2f2SGreg Clayton private: 10001d19a2f2SGreg Clayton public: 1001b9c1b51eSKate Stone CommandObjectProcessKDPPacket(CommandInterpreter &interpreter) 1002b9c1b51eSKate Stone : CommandObjectMultiword(interpreter, "process plugin packet", 10031d19a2f2SGreg Clayton "Commands that deal with KDP remote packets.", 1004b9c1b51eSKate Stone NULL) { 1005b9c1b51eSKate Stone LoadSubCommand( 1006b9c1b51eSKate Stone "send", 1007b9c1b51eSKate Stone CommandObjectSP(new CommandObjectProcessKDPPacketSend(interpreter))); 10081d19a2f2SGreg Clayton } 10091d19a2f2SGreg Clayton 1010b9c1b51eSKate Stone ~CommandObjectProcessKDPPacket() {} 10111d19a2f2SGreg Clayton }; 10121d19a2f2SGreg Clayton 1013b9c1b51eSKate Stone class CommandObjectMultiwordProcessKDP : public CommandObjectMultiword { 10141d19a2f2SGreg Clayton public: 10157428a18cSKate Stone CommandObjectMultiwordProcessKDP(CommandInterpreter &interpreter) 1016b9c1b51eSKate Stone : CommandObjectMultiword( 1017b9c1b51eSKate Stone interpreter, "process plugin", 1018b9c1b51eSKate Stone "Commands for operating on a ProcessKDP process.", 1019b9c1b51eSKate Stone "process plugin <subcommand> [<subcommand-options>]") { 1020b9c1b51eSKate Stone LoadSubCommand("packet", CommandObjectSP(new CommandObjectProcessKDPPacket( 1021b9c1b51eSKate Stone interpreter))); 10221d19a2f2SGreg Clayton } 10231d19a2f2SGreg Clayton 1024b9c1b51eSKate Stone ~CommandObjectMultiwordProcessKDP() {} 10251d19a2f2SGreg Clayton }; 10261d19a2f2SGreg Clayton 1027b9c1b51eSKate Stone CommandObject *ProcessKDP::GetPluginCommandObject() { 10281d19a2f2SGreg Clayton if (!m_command_sp) 1029796ac80bSJonas Devlieghere m_command_sp = std::make_shared<CommandObjectMultiwordProcessKDP>( 1030796ac80bSJonas Devlieghere GetTarget().GetDebugger().GetCommandInterpreter()); 10311d19a2f2SGreg Clayton return m_command_sp.get(); 10321d19a2f2SGreg Clayton } 1033