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 976e47d48SRaphael Isemann #include <cerrno> 1076e47d48SRaphael Isemann #include <cstdlib> 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 53ccad1948SJonas Devlieghere LLDB_PLUGIN_DEFINE_ADV(ProcessKDP, ProcessMacOSXKernel) 54fbb4d1e4SJonas 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 76*fd2433e1SJonas Devlieghere virtual ~PluginProperties() = default; 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, 11418e4272aSMichał Górny const FileSpec *crash_file_path, 11518e4272aSMichał Górny bool can_connect) { 116c3776bf2SGreg Clayton lldb::ProcessSP process_sp; 117c3776bf2SGreg Clayton if (crash_file_path == NULL) 118796ac80bSJonas Devlieghere process_sp = std::make_shared<ProcessKDP>(target_sp, listener_sp); 119c3776bf2SGreg Clayton return process_sp; 120f9765acdSGreg Clayton } 121f9765acdSGreg Clayton 122b9c1b51eSKate Stone bool ProcessKDP::CanDebug(TargetSP target_sp, bool plugin_specified_by_name) { 123596ed24eSGreg Clayton if (plugin_specified_by_name) 124596ed24eSGreg Clayton return true; 125596ed24eSGreg Clayton 126f9765acdSGreg Clayton // For now we are just making sure the file exists for a given module 1275a3bb64fSJim Ingham Module *exe_module = target_sp->GetExecutableModulePointer(); 128b9c1b51eSKate Stone if (exe_module) { 1295a3bb64fSJim Ingham const llvm::Triple &triple_ref = target_sp->GetArchitecture().GetTriple(); 130b9c1b51eSKate Stone switch (triple_ref.getOS()) { 131b9c1b51eSKate Stone case llvm::Triple::Darwin: // Should use "macosx" for desktop and "ios" for 132b9c1b51eSKate Stone // iOS, but accept darwin just in case 13370512317SGreg Clayton case llvm::Triple::MacOSX: // For desktop targets 13470512317SGreg Clayton case llvm::Triple::IOS: // For arm targets 135a814f704SJason Molenda case llvm::Triple::TvOS: 136a814f704SJason Molenda case llvm::Triple::WatchOS: 137b9c1b51eSKate Stone if (triple_ref.getVendor() == llvm::Triple::Apple) { 138aa149cbdSGreg Clayton ObjectFile *exe_objfile = exe_module->GetObjectFile(); 139f9765acdSGreg Clayton if (exe_objfile->GetType() == ObjectFile::eTypeExecutable && 140f9765acdSGreg Clayton exe_objfile->GetStrata() == ObjectFile::eStrataKernel) 141f9765acdSGreg Clayton return true; 142f9765acdSGreg Clayton } 14370512317SGreg Clayton break; 14470512317SGreg Clayton 14570512317SGreg Clayton default: 14670512317SGreg Clayton break; 14770512317SGreg Clayton } 148f9765acdSGreg Clayton } 149596ed24eSGreg Clayton return false; 1503a29bdbeSGreg Clayton } 151f9765acdSGreg Clayton 152f9765acdSGreg Clayton // ProcessKDP constructor 153b9c1b51eSKate Stone ProcessKDP::ProcessKDP(TargetSP target_sp, ListenerSP listener_sp) 154b9c1b51eSKate Stone : Process(target_sp, listener_sp), 155f9765acdSGreg Clayton m_comm("lldb.process.kdp-remote.communication"), 1564bddaeb5SJim Ingham m_async_broadcaster(NULL, "lldb.process.kdp-remote.async-broadcaster"), 157b9c1b51eSKate Stone m_dyld_plugin_name(), m_kernel_load_addr(LLDB_INVALID_ADDRESS), 158b9c1b51eSKate Stone m_command_sp(), m_kernel_thread_wp() { 159b9c1b51eSKate Stone m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, 160b9c1b51eSKate Stone "async thread should exit"); 161b9c1b51eSKate Stone m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, 162b9c1b51eSKate Stone "async thread continue"); 163b9c1b51eSKate Stone const uint64_t timeout_seconds = 164b9c1b51eSKate Stone GetGlobalPluginProperties()->GetPacketTimeout(); 1657f98240dSGreg Clayton if (timeout_seconds > 0) 1665cddd608SPavel Labath m_comm.SetPacketTimeout(std::chrono::seconds(timeout_seconds)); 167f9765acdSGreg Clayton } 168f9765acdSGreg Clayton 169f9765acdSGreg Clayton // Destructor 170b9c1b51eSKate Stone ProcessKDP::~ProcessKDP() { 171f9765acdSGreg Clayton Clear(); 17205097246SAdrian Prantl // We need to call finalize on the process before destroying ourselves to 17305097246SAdrian Prantl // make sure all of the broadcaster cleanup goes as planned. If we destruct 17405097246SAdrian Prantl // this class, then Process::~Process() might have problems trying to fully 17505097246SAdrian Prantl // destroy the broadcaster. 176e24c4acfSGreg Clayton Finalize(); 177f9765acdSGreg Clayton } 178f9765acdSGreg Clayton 179f9765acdSGreg Clayton // PluginInterface 180b9c1b51eSKate Stone lldb_private::ConstString ProcessKDP::GetPluginName() { 181f9765acdSGreg Clayton return GetPluginNameStatic(); 182f9765acdSGreg Clayton } 183f9765acdSGreg Clayton 184b9c1b51eSKate Stone uint32_t ProcessKDP::GetPluginVersion() { return 1; } 185f9765acdSGreg Clayton 18697206d57SZachary Turner Status ProcessKDP::WillLaunch(Module *module) { 18797206d57SZachary Turner Status error; 188f9765acdSGreg Clayton error.SetErrorString("launching not supported in kdp-remote plug-in"); 189f9765acdSGreg Clayton return error; 190f9765acdSGreg Clayton } 191f9765acdSGreg Clayton 19297206d57SZachary Turner Status ProcessKDP::WillAttachToProcessWithID(lldb::pid_t pid) { 19397206d57SZachary Turner Status error; 194b9c1b51eSKate Stone error.SetErrorString( 195b9c1b51eSKate Stone "attaching to a by process ID not supported in kdp-remote plug-in"); 196f9765acdSGreg Clayton return error; 197f9765acdSGreg Clayton } 198f9765acdSGreg Clayton 19997206d57SZachary Turner Status ProcessKDP::WillAttachToProcessWithName(const char *process_name, 200b9c1b51eSKate Stone bool wait_for_launch) { 20197206d57SZachary Turner Status error; 202b9c1b51eSKate Stone error.SetErrorString( 203b9c1b51eSKate Stone "attaching to a by process name not supported in kdp-remote plug-in"); 204f9765acdSGreg Clayton return error; 205f9765acdSGreg Clayton } 206f9765acdSGreg Clayton 207b9c1b51eSKate Stone bool ProcessKDP::GetHostArchitecture(ArchSpec &arch) { 208a3706888SGreg Clayton uint32_t cpu = m_comm.GetCPUType(); 209b9c1b51eSKate Stone if (cpu) { 210a3706888SGreg Clayton uint32_t sub = m_comm.GetCPUSubtype(); 211a3706888SGreg Clayton arch.SetArchitecture(eArchTypeMachO, cpu, sub); 212a3706888SGreg Clayton // Leave architecture vendor as unspecified unknown 213a3706888SGreg Clayton arch.GetTriple().setVendor(llvm::Triple::UnknownVendor); 214a3706888SGreg Clayton arch.GetTriple().setVendorName(llvm::StringRef()); 215a3706888SGreg Clayton return true; 216a3706888SGreg Clayton } 217a3706888SGreg Clayton arch.Clear(); 218a3706888SGreg Clayton return false; 219a3706888SGreg Clayton } 220a3706888SGreg Clayton 22132d35fb7SJonas Devlieghere Status ProcessKDP::DoConnectRemote(llvm::StringRef remote_url) { 22297206d57SZachary Turner Status error; 2233a29bdbeSGreg Clayton 22405097246SAdrian Prantl // Don't let any JIT happen when doing KDP as we can't allocate memory and we 22505097246SAdrian Prantl // don't want to be mucking with threads that might already be handling 22605097246SAdrian Prantl // exceptions 2277925fbbaSGreg Clayton SetCanJIT(false); 2287925fbbaSGreg Clayton 2293ce7e996SGreg Clayton if (remote_url.empty()) { 2303ce7e996SGreg Clayton error.SetErrorStringWithFormat("empty connection URL"); 2317925fbbaSGreg Clayton return error; 2327925fbbaSGreg Clayton } 2333a29bdbeSGreg Clayton 234d5b44036SJonas Devlieghere std::unique_ptr<ConnectionFileDescriptor> conn_up( 235b9c1b51eSKate Stone new ConnectionFileDescriptor()); 236d5b44036SJonas Devlieghere if (conn_up) { 2373a29bdbeSGreg Clayton // Only try once for now. 2383a29bdbeSGreg Clayton // TODO: check if we should be retrying? 2393a29bdbeSGreg Clayton const uint32_t max_retry_count = 1; 240b9c1b51eSKate Stone for (uint32_t retry_count = 0; retry_count < max_retry_count; 241b9c1b51eSKate Stone ++retry_count) { 242d5b44036SJonas Devlieghere if (conn_up->Connect(remote_url, &error) == eConnectionStatusSuccess) 2433a29bdbeSGreg Clayton break; 2443a29bdbeSGreg Clayton usleep(100000); 2453a29bdbeSGreg Clayton } 2463a29bdbeSGreg Clayton } 2473a29bdbeSGreg Clayton 248d5b44036SJonas Devlieghere if (conn_up->IsConnected()) { 249b9c1b51eSKate Stone const TCPSocket &socket = 250d5b44036SJonas Devlieghere static_cast<const TCPSocket &>(*conn_up->GetReadObject()); 251014bb7daSVince Harron const uint16_t reply_port = socket.GetLocalPortNumber(); 2523a29bdbeSGreg Clayton 253b9c1b51eSKate Stone if (reply_port != 0) { 254451741a9SPavel Labath m_comm.SetConnection(std::move(conn_up)); 2553a29bdbeSGreg Clayton 256b9c1b51eSKate Stone if (m_comm.SendRequestReattach(reply_port)) { 257b9c1b51eSKate Stone if (m_comm.SendRequestConnect(reply_port, reply_port, 258b9c1b51eSKate Stone "Greetings from LLDB...")) { 2593a29bdbeSGreg Clayton m_comm.GetVersion(); 2605a3bb64fSJim Ingham 261a3706888SGreg Clayton Target &target = GetTarget(); 262a3706888SGreg Clayton ArchSpec kernel_arch; 263a3706888SGreg Clayton // The host architecture 264a3706888SGreg Clayton GetHostArchitecture(kernel_arch); 265a3706888SGreg Clayton ArchSpec target_arch = target.GetArchitecture(); 266a3706888SGreg Clayton // Merge in any unspecified stuff into the target architecture in 267a3706888SGreg Clayton // case the target arch isn't set at all or incompletely. 268a3706888SGreg Clayton target_arch.MergeFrom(kernel_arch); 269a3706888SGreg Clayton target.SetArchitecture(target_arch); 2704bd4e7e3SJason Molenda 271b9c1b51eSKate Stone /* Get the kernel's UUID and load address via KDP_KERNELVERSION 272b9c1b51eSKate Stone * packet. */ 273840f12cfSJason Molenda /* An EFI kdp session has neither UUID nor load address. */ 2744bd4e7e3SJason Molenda 2754bd4e7e3SJason Molenda UUID kernel_uuid = m_comm.GetUUID(); 2764bd4e7e3SJason Molenda addr_t kernel_load_addr = m_comm.GetLoadAddress(); 2774bd4e7e3SJason Molenda 278b9c1b51eSKate Stone if (m_comm.RemoteIsEFI()) { 279b9c1b51eSKate Stone // Select an invalid plugin name for the dynamic loader so one 28005097246SAdrian Prantl // doesn't get used since EFI does its own manual loading via 28105097246SAdrian Prantl // python scripting 282a1bce2efSGreg Clayton static ConstString g_none_dynamic_loader("none"); 283a1bce2efSGreg Clayton m_dyld_plugin_name = g_none_dynamic_loader; 284a1bce2efSGreg Clayton 285a1bce2efSGreg Clayton if (kernel_uuid.IsValid()) { 28605097246SAdrian Prantl // If EFI passed in a UUID= try to lookup UUID The slide will not 28705097246SAdrian Prantl // be provided. But the UUID lookup will be used to launch EFI 28805097246SAdrian Prantl // debug scripts from the dSYM, that can load all of the symbols. 289a1bce2efSGreg Clayton ModuleSpec module_spec; 290a1bce2efSGreg Clayton module_spec.GetUUID() = kernel_uuid; 2915a3bb64fSJim Ingham module_spec.GetArchitecture() = target.GetArchitecture(); 292a1bce2efSGreg Clayton 293a1bce2efSGreg Clayton // Lookup UUID locally, before attempting dsymForUUID like action 294a313ec11SZachary Turner FileSpecList search_paths = 295a313ec11SZachary Turner Target::GetDefaultDebugFileSearchPaths(); 296b9c1b51eSKate Stone module_spec.GetSymbolFileSpec() = 297a313ec11SZachary Turner Symbols::LocateExecutableSymbolFile(module_spec, 298a313ec11SZachary Turner search_paths); 299b9c1b51eSKate Stone if (module_spec.GetSymbolFileSpec()) { 300b9c1b51eSKate Stone ModuleSpec executable_module_spec = 301b9c1b51eSKate Stone Symbols::LocateExecutableObjectFile(module_spec); 302dbd7fabaSJonas Devlieghere if (FileSystem::Instance().Exists( 303dbd7fabaSJonas Devlieghere executable_module_spec.GetFileSpec())) { 304b9c1b51eSKate Stone module_spec.GetFileSpec() = 305b9c1b51eSKate Stone executable_module_spec.GetFileSpec(); 3068825c5c9SJason Molenda } 3078825c5c9SJason Molenda } 308b9c1b51eSKate Stone if (!module_spec.GetSymbolFileSpec() || 309b9c1b51eSKate Stone !module_spec.GetSymbolFileSpec()) 310a1bce2efSGreg Clayton Symbols::DownloadObjectAndSymbolFile(module_spec, true); 311a1bce2efSGreg Clayton 312dbd7fabaSJonas Devlieghere if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { 313a3706888SGreg Clayton ModuleSP module_sp(new Module(module_spec)); 314b9c1b51eSKate Stone if (module_sp.get() && module_sp->GetObjectFile()) { 315a1bce2efSGreg Clayton // Get the current target executable 3165a3bb64fSJim Ingham ModuleSP exe_module_sp(target.GetExecutableModule()); 317a1bce2efSGreg Clayton 318b9c1b51eSKate Stone // Make sure you don't already have the right module loaded 319b9c1b51eSKate Stone // and they will be uniqued 320a1bce2efSGreg Clayton if (exe_module_sp.get() != module_sp.get()) 321f9a07e9fSJonas Devlieghere target.SetExecutableModule(module_sp, eLoadDependentsNo); 322a1bce2efSGreg Clayton } 323a1bce2efSGreg Clayton } 324a1bce2efSGreg Clayton } 325b9c1b51eSKate Stone } else if (m_comm.RemoteIsDarwinKernel()) { 326b9c1b51eSKate Stone m_dyld_plugin_name = 327b9c1b51eSKate Stone DynamicLoaderDarwinKernel::GetPluginNameStatic(); 328b9c1b51eSKate Stone if (kernel_load_addr != LLDB_INVALID_ADDRESS) { 3295e8534efSJason Molenda m_kernel_load_addr = kernel_load_addr; 330a8ea4baeSJason Molenda } 3314bd4e7e3SJason Molenda } 3324bd4e7e3SJason Molenda 33397d5cf05SGreg Clayton // Set the thread ID 33497d5cf05SGreg Clayton UpdateThreadListIfNeeded(); 335a63d08c9SGreg Clayton SetID(1); 33656d9a1b3SGreg Clayton GetThreadList(); 337a63d08c9SGreg Clayton SetPrivateState(eStateStopped); 3385a3bb64fSJim Ingham StreamSP async_strm_sp(target.GetDebugger().GetAsyncOutputStream()); 339b9c1b51eSKate Stone if (async_strm_sp) { 3405b88216dSGreg Clayton const char *cstr; 341b9c1b51eSKate Stone if ((cstr = m_comm.GetKernelVersion()) != NULL) { 3425b88216dSGreg Clayton async_strm_sp->Printf("Version: %s\n", cstr); 34307e66e3eSGreg Clayton async_strm_sp->Flush(); 34407e66e3eSGreg Clayton } 3455b88216dSGreg Clayton // if ((cstr = m_comm.GetImagePath ()) != NULL) 3465b88216dSGreg Clayton // { 347b9c1b51eSKate Stone // async_strm_sp->Printf ("Image Path: 348b9c1b51eSKate Stone // %s\n", cstr); 3495b88216dSGreg Clayton // async_strm_sp->Flush(); 3505b88216dSGreg Clayton // } 35107e66e3eSGreg Clayton } 352b9c1b51eSKate Stone } else { 35397d5cf05SGreg Clayton error.SetErrorString("KDP_REATTACH failed"); 35497d5cf05SGreg Clayton } 355b9c1b51eSKate Stone } else { 35697d5cf05SGreg Clayton error.SetErrorString("KDP_REATTACH failed"); 3573a29bdbeSGreg Clayton } 358b9c1b51eSKate Stone } else { 3593a29bdbeSGreg Clayton error.SetErrorString("invalid reply port from UDP connection"); 3603a29bdbeSGreg Clayton } 361b9c1b51eSKate Stone } else { 3623a29bdbeSGreg Clayton if (error.Success()) 3633ce7e996SGreg Clayton error.SetErrorStringWithFormat("failed to connect to '%s'", 3643ce7e996SGreg Clayton remote_url.str().c_str()); 3653a29bdbeSGreg Clayton } 3663a29bdbeSGreg Clayton if (error.Fail()) 3673a29bdbeSGreg Clayton m_comm.Disconnect(); 3683a29bdbeSGreg Clayton 369f9765acdSGreg Clayton return error; 370f9765acdSGreg Clayton } 371f9765acdSGreg Clayton 372f9765acdSGreg Clayton // Process Control 37397206d57SZachary Turner Status ProcessKDP::DoLaunch(Module *exe_module, 37497206d57SZachary Turner ProcessLaunchInfo &launch_info) { 37597206d57SZachary Turner Status error; 376f9765acdSGreg Clayton error.SetErrorString("launching not supported in kdp-remote plug-in"); 377f9765acdSGreg Clayton return error; 378f9765acdSGreg Clayton } 379f9765acdSGreg Clayton 38097206d57SZachary Turner Status 38197206d57SZachary Turner ProcessKDP::DoAttachToProcessWithID(lldb::pid_t attach_pid, 38297206d57SZachary Turner const ProcessAttachInfo &attach_info) { 38397206d57SZachary Turner Status error; 384b9c1b51eSKate Stone error.SetErrorString( 3854ebdee0aSBruce Mitchener "attach to process by ID is not supported in kdp remote debugging"); 38684647048SHan Ming Ong return error; 38784647048SHan Ming Ong } 38884647048SHan Ming Ong 38997206d57SZachary Turner Status 39097206d57SZachary Turner ProcessKDP::DoAttachToProcessWithName(const char *process_name, 39197206d57SZachary Turner const ProcessAttachInfo &attach_info) { 39297206d57SZachary Turner Status error; 393b9c1b51eSKate Stone error.SetErrorString( 3944ebdee0aSBruce Mitchener "attach to process by name is not supported in kdp remote debugging"); 395f9765acdSGreg Clayton return error; 396f9765acdSGreg Clayton } 397f9765acdSGreg Clayton 398b9c1b51eSKate Stone void ProcessKDP::DidAttach(ArchSpec &process_arch) { 399bb006ce2SJim Ingham Process::DidAttach(process_arch); 400bb006ce2SJim Ingham 4015160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 40263e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DidAttach()"); 403b9c1b51eSKate Stone if (GetID() != LLDB_INVALID_PROCESS_ID) { 404a3706888SGreg Clayton GetHostArchitecture(process_arch); 405f9765acdSGreg Clayton } 406f9765acdSGreg Clayton } 407f9765acdSGreg Clayton 408b9c1b51eSKate Stone addr_t ProcessKDP::GetImageInfoAddress() { return m_kernel_load_addr; } 4095e8534efSJason Molenda 410b9c1b51eSKate Stone lldb_private::DynamicLoader *ProcessKDP::GetDynamicLoader() { 411d5b44036SJonas Devlieghere if (m_dyld_up.get() == NULL) 412d5b44036SJonas Devlieghere m_dyld_up.reset(DynamicLoader::FindPlugin( 413b9c1b51eSKate Stone this, 414b9c1b51eSKate Stone m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString())); 415d5b44036SJonas Devlieghere return m_dyld_up.get(); 4165e8534efSJason Molenda } 4175e8534efSJason Molenda 41897206d57SZachary Turner Status ProcessKDP::WillResume() { return Status(); } 419f9765acdSGreg Clayton 42097206d57SZachary Turner Status ProcessKDP::DoResume() { 42197206d57SZachary Turner Status error; 4225160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 4237925fbbaSGreg Clayton // Only start the async thread if we try to do any process control 424acee96aeSZachary Turner if (!m_async_thread.IsJoinable()) 4257925fbbaSGreg Clayton StartAsyncThread(); 4267925fbbaSGreg Clayton 42797d5cf05SGreg Clayton bool resume = false; 4287925fbbaSGreg Clayton 42997d5cf05SGreg Clayton // With KDP there is only one thread we can tell what to do 430ba4e61d3SAndrew Kaylor ThreadSP kernel_thread_sp(m_thread_list.FindThreadByProtocolID(g_kernel_tid)); 431ba4e61d3SAndrew Kaylor 432b9c1b51eSKate Stone if (kernel_thread_sp) { 433b9c1b51eSKate Stone const StateType thread_resume_state = 434b9c1b51eSKate Stone kernel_thread_sp->GetTemporaryResumeState(); 4356e0ff1a3SGreg Clayton 43663e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoResume() thread_resume_state = %s", 437b9c1b51eSKate Stone StateAsCString(thread_resume_state)); 438b9c1b51eSKate Stone switch (thread_resume_state) { 4397925fbbaSGreg Clayton case eStateSuspended: 44005097246SAdrian Prantl // Nothing to do here when a thread will stay suspended we just leave the 44105097246SAdrian Prantl // CPU mask bit set to zero for the thread 44263e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoResume() = suspended???"); 4437925fbbaSGreg Clayton break; 4447925fbbaSGreg Clayton 445b9c1b51eSKate Stone case eStateStepping: { 446b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 447b9c1b51eSKate Stone kernel_thread_sp->GetRegisterContext()); 4481afa68edSGreg Clayton 449b9c1b51eSKate Stone if (reg_ctx_sp) { 45063e5fb76SJonas Devlieghere LLDB_LOGF( 45163e5fb76SJonas Devlieghere log, 452b9c1b51eSKate Stone "ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (true);"); 4531afa68edSGreg Clayton reg_ctx_sp->HardwareSingleStep(true); 45497d5cf05SGreg Clayton resume = true; 455b9c1b51eSKate Stone } else { 456b9c1b51eSKate Stone error.SetErrorStringWithFormat( 457b9c1b51eSKate Stone "KDP thread 0x%llx has no register context", 458b9c1b51eSKate Stone kernel_thread_sp->GetID()); 4591afa68edSGreg Clayton } 460b9c1b51eSKate Stone } break; 4617925fbbaSGreg Clayton 462b9c1b51eSKate Stone case eStateRunning: { 463b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 464b9c1b51eSKate Stone kernel_thread_sp->GetRegisterContext()); 4651afa68edSGreg Clayton 466b9c1b51eSKate Stone if (reg_ctx_sp) { 46763e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep " 468b9c1b51eSKate Stone "(false);"); 4691afa68edSGreg Clayton reg_ctx_sp->HardwareSingleStep(false); 47097d5cf05SGreg Clayton resume = true; 471b9c1b51eSKate Stone } else { 472b9c1b51eSKate Stone error.SetErrorStringWithFormat( 473b9c1b51eSKate Stone "KDP thread 0x%llx has no register context", 474b9c1b51eSKate Stone kernel_thread_sp->GetID()); 4751afa68edSGreg Clayton } 476b9c1b51eSKate Stone } break; 4777925fbbaSGreg Clayton 4787925fbbaSGreg Clayton default: 47997d5cf05SGreg Clayton // The only valid thread resume states are listed above 480a322f36cSDavid Blaikie llvm_unreachable("invalid thread resume state"); 4814b1b8b3eSGreg Clayton } 4824b1b8b3eSGreg Clayton } 4837925fbbaSGreg Clayton 484b9c1b51eSKate Stone if (resume) { 48563e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoResume () sending resume"); 48697d5cf05SGreg Clayton 487b9c1b51eSKate Stone if (m_comm.SendRequestResume()) { 4887925fbbaSGreg Clayton m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue); 4897925fbbaSGreg Clayton SetPrivateState(eStateRunning); 490b9c1b51eSKate Stone } else 49107e66e3eSGreg Clayton error.SetErrorString("KDP resume failed"); 492b9c1b51eSKate Stone } else { 49397d5cf05SGreg Clayton error.SetErrorString("kernel thread is suspended"); 4947925fbbaSGreg Clayton } 4957925fbbaSGreg Clayton 496f9765acdSGreg Clayton return error; 497f9765acdSGreg Clayton } 498f9765acdSGreg Clayton 499b9c1b51eSKate Stone lldb::ThreadSP ProcessKDP::GetKernelThread() { 50097d5cf05SGreg Clayton // KDP only tells us about one thread/core. Any other threads will usually 50197d5cf05SGreg Clayton // be the ones that are read from memory by the OS plug-ins. 502ba4e61d3SAndrew Kaylor 503ba4e61d3SAndrew Kaylor ThreadSP thread_sp(m_kernel_thread_wp.lock()); 504b9c1b51eSKate Stone if (!thread_sp) { 505796ac80bSJonas Devlieghere thread_sp = std::make_shared<ThreadKDP>(*this, g_kernel_tid); 506ba4e61d3SAndrew Kaylor m_kernel_thread_wp = thread_sp; 507ba4e61d3SAndrew Kaylor } 50897d5cf05SGreg Clayton return thread_sp; 50997d5cf05SGreg Clayton } 51097d5cf05SGreg Clayton 5114bb62448SWalter Erquinigo bool ProcessKDP::DoUpdateThreadList(ThreadList &old_thread_list, 512b9c1b51eSKate Stone ThreadList &new_thread_list) { 513f9765acdSGreg Clayton // locker will keep a mutex locked until it goes out of scope 5145160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_THREAD)); 515250858a0SPavel Labath LLDB_LOGV(log, "pid = {0}", GetID()); 516f9765acdSGreg Clayton 51739da3efdSGreg Clayton // Even though there is a CPU mask, it doesn't mean we can see each CPU 518a868c13cSBruce Mitchener // individually, there is really only one. Lets call this thread 1. 519b9c1b51eSKate Stone ThreadSP thread_sp( 520b9c1b51eSKate Stone old_thread_list.FindThreadByProtocolID(g_kernel_tid, false)); 521ba4e61d3SAndrew Kaylor if (!thread_sp) 522ba4e61d3SAndrew Kaylor thread_sp = GetKernelThread(); 523ba4e61d3SAndrew Kaylor new_thread_list.AddThread(thread_sp); 52497d5cf05SGreg Clayton 5259fc13556SGreg Clayton return new_thread_list.GetSize(false) > 0; 526f9765acdSGreg Clayton } 527f9765acdSGreg Clayton 528b9c1b51eSKate Stone void ProcessKDP::RefreshStateAfterStop() { 52905097246SAdrian Prantl // Let all threads recover from stopping and do any clean up based on the 53005097246SAdrian Prantl // previous thread state (if any). 531f9765acdSGreg Clayton m_thread_list.RefreshStateAfterStop(); 532f9765acdSGreg Clayton } 533f9765acdSGreg Clayton 53497206d57SZachary Turner Status ProcessKDP::DoHalt(bool &caused_stop) { 53597206d57SZachary Turner Status error; 536f9765acdSGreg Clayton 537b9c1b51eSKate Stone if (m_comm.IsRunning()) { 538b9c1b51eSKate Stone if (m_destroy_in_process) { 5394ebdee0aSBruce Mitchener // If we are attempting to destroy, we need to not return an error to Halt 54005097246SAdrian Prantl // or DoDestroy won't get called. We are also currently running, so send 54105097246SAdrian Prantl // a process stopped event 54297d5cf05SGreg Clayton SetPrivateState(eStateStopped); 543b9c1b51eSKate Stone } else { 54497d5cf05SGreg Clayton error.SetErrorString("KDP cannot interrupt a running kernel"); 545f9765acdSGreg Clayton } 546f9765acdSGreg Clayton } 547f9765acdSGreg Clayton return error; 548f9765acdSGreg Clayton } 549f9765acdSGreg Clayton 55097206d57SZachary Turner Status ProcessKDP::DoDetach(bool keep_stopped) { 55197206d57SZachary Turner Status error; 5525160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 55363e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoDetach(keep_stopped = %i)", keep_stopped); 554f9765acdSGreg Clayton 555b9c1b51eSKate Stone if (m_comm.IsRunning()) { 55605097246SAdrian Prantl // We are running and we can't interrupt a running kernel, so we need to 55705097246SAdrian Prantl // just close the connection to the kernel and hope for the best 558b9c1b51eSKate Stone } else { 559b9c1b51eSKate Stone // If we are going to keep the target stopped, then don't send the 560b9c1b51eSKate Stone // disconnect message. 561b9c1b51eSKate Stone if (!keep_stopped && m_comm.IsConnected()) { 5626e0ff1a3SGreg Clayton const bool success = m_comm.SendRequestDisconnect(); 563b9c1b51eSKate Stone if (log) { 5646e0ff1a3SGreg Clayton if (success) 565b9c1b51eSKate Stone log->PutCString( 566b9c1b51eSKate Stone "ProcessKDP::DoDetach() detach packet sent successfully"); 567f9765acdSGreg Clayton else 568b9c1b51eSKate Stone log->PutCString( 569b9c1b51eSKate Stone "ProcessKDP::DoDetach() connection channel shutdown failed"); 570f9765acdSGreg Clayton } 5716e0ff1a3SGreg Clayton m_comm.Disconnect(); 5723a29bdbeSGreg Clayton } 57397d5cf05SGreg Clayton } 574f9765acdSGreg Clayton StopAsyncThread(); 57574d4193eSGreg Clayton m_comm.Clear(); 576f9765acdSGreg Clayton 577f9765acdSGreg Clayton SetPrivateState(eStateDetached); 578f9765acdSGreg Clayton ResumePrivateStateThread(); 579f9765acdSGreg Clayton 580f9765acdSGreg Clayton // KillDebugserverProcess (); 581f9765acdSGreg Clayton return error; 582f9765acdSGreg Clayton } 583f9765acdSGreg Clayton 58497206d57SZachary Turner Status ProcessKDP::DoDestroy() { 5857925fbbaSGreg Clayton // For KDP there really is no difference between destroy and detach 586acff8950SJim Ingham bool keep_stopped = false; 587acff8950SJim Ingham return DoDetach(keep_stopped); 588f9765acdSGreg Clayton } 589f9765acdSGreg Clayton 590f9765acdSGreg Clayton // Process Queries 591f9765acdSGreg Clayton 592b9c1b51eSKate Stone bool ProcessKDP::IsAlive() { 593a814f704SJason Molenda return m_comm.IsConnected() && Process::IsAlive(); 594f9765acdSGreg Clayton } 595f9765acdSGreg Clayton 596f9765acdSGreg Clayton // Process Memory 597b9c1b51eSKate Stone size_t ProcessKDP::DoReadMemory(addr_t addr, void *buf, size_t size, 59897206d57SZachary Turner Status &error) { 5998eb32817SJason Molenda uint8_t *data_buffer = (uint8_t *)buf; 600b9c1b51eSKate Stone if (m_comm.IsConnected()) { 6018eb32817SJason Molenda const size_t max_read_size = 512; 6028eb32817SJason Molenda size_t total_bytes_read = 0; 6038eb32817SJason Molenda 6048eb32817SJason Molenda // Read the requested amount of memory in 512 byte chunks 605b9c1b51eSKate Stone while (total_bytes_read < size) { 6068eb32817SJason Molenda size_t bytes_to_read_this_request = size - total_bytes_read; 607b9c1b51eSKate Stone if (bytes_to_read_this_request > max_read_size) { 6088eb32817SJason Molenda bytes_to_read_this_request = max_read_size; 6098eb32817SJason Molenda } 610b9c1b51eSKate Stone size_t bytes_read = m_comm.SendRequestReadMemory( 611b9c1b51eSKate Stone addr + total_bytes_read, data_buffer + total_bytes_read, 6128eb32817SJason Molenda bytes_to_read_this_request, error); 6138eb32817SJason Molenda total_bytes_read += bytes_read; 614b9c1b51eSKate Stone if (error.Fail() || bytes_read == 0) { 6158eb32817SJason Molenda return total_bytes_read; 6168eb32817SJason Molenda } 6178eb32817SJason Molenda } 6188eb32817SJason Molenda 6198eb32817SJason Molenda return total_bytes_read; 6208eb32817SJason Molenda } 621a63d08c9SGreg Clayton error.SetErrorString("not connected"); 622f9765acdSGreg Clayton return 0; 623f9765acdSGreg Clayton } 624f9765acdSGreg Clayton 625b9c1b51eSKate Stone size_t ProcessKDP::DoWriteMemory(addr_t addr, const void *buf, size_t size, 62697206d57SZachary Turner Status &error) { 6277925fbbaSGreg Clayton if (m_comm.IsConnected()) 6287925fbbaSGreg Clayton return m_comm.SendRequestWriteMemory(addr, buf, size, error); 6297925fbbaSGreg Clayton error.SetErrorString("not connected"); 630f9765acdSGreg Clayton return 0; 631f9765acdSGreg Clayton } 632f9765acdSGreg Clayton 633b9c1b51eSKate Stone lldb::addr_t ProcessKDP::DoAllocateMemory(size_t size, uint32_t permissions, 63497206d57SZachary Turner Status &error) { 635b9c1b51eSKate Stone error.SetErrorString( 6364ebdee0aSBruce Mitchener "memory allocation not supported in kdp remote debugging"); 637f9765acdSGreg Clayton return LLDB_INVALID_ADDRESS; 638f9765acdSGreg Clayton } 639f9765acdSGreg Clayton 64097206d57SZachary Turner Status ProcessKDP::DoDeallocateMemory(lldb::addr_t addr) { 64197206d57SZachary Turner Status error; 642b9c1b51eSKate Stone error.SetErrorString( 6434ebdee0aSBruce Mitchener "memory deallocation not supported in kdp remote debugging"); 644f9765acdSGreg Clayton return error; 645f9765acdSGreg Clayton } 646f9765acdSGreg Clayton 64797206d57SZachary Turner Status ProcessKDP::EnableBreakpointSite(BreakpointSite *bp_site) { 648b352e62fSTatyana Krasnukha if (bp_site->HardwareRequired()) 649b352e62fSTatyana Krasnukha return Status("Hardware breakpoints are not supported."); 650b352e62fSTatyana Krasnukha 651b9c1b51eSKate Stone if (m_comm.LocalBreakpointsAreSupported()) { 65297206d57SZachary Turner Status error; 653b9c1b51eSKate Stone if (!bp_site->IsEnabled()) { 654b9c1b51eSKate Stone if (m_comm.SendRequestBreakpoint(true, bp_site->GetLoadAddress())) { 6555b88216dSGreg Clayton bp_site->SetEnabled(true); 6565b88216dSGreg Clayton bp_site->SetType(BreakpointSite::eExternal); 657b9c1b51eSKate Stone } else { 65807e66e3eSGreg Clayton error.SetErrorString("KDP set breakpoint failed"); 6595b88216dSGreg Clayton } 6605b88216dSGreg Clayton } 66107e66e3eSGreg Clayton return error; 66207e66e3eSGreg Clayton } 663f9765acdSGreg Clayton return EnableSoftwareBreakpoint(bp_site); 664f9765acdSGreg Clayton } 665f9765acdSGreg Clayton 66697206d57SZachary Turner Status ProcessKDP::DisableBreakpointSite(BreakpointSite *bp_site) { 667b9c1b51eSKate Stone if (m_comm.LocalBreakpointsAreSupported()) { 66897206d57SZachary Turner Status error; 669b9c1b51eSKate Stone if (bp_site->IsEnabled()) { 6705b88216dSGreg Clayton BreakpointSite::Type bp_type = bp_site->GetType(); 671b9c1b51eSKate Stone if (bp_type == BreakpointSite::eExternal) { 672b9c1b51eSKate Stone if (m_destroy_in_process && m_comm.IsRunning()) { 67397d5cf05SGreg Clayton // We are trying to destroy our connection and we are running 67497d5cf05SGreg Clayton bp_site->SetEnabled(false); 675b9c1b51eSKate Stone } else { 6765b88216dSGreg Clayton if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress())) 6775b88216dSGreg Clayton bp_site->SetEnabled(false); 6785b88216dSGreg Clayton else 67907e66e3eSGreg Clayton error.SetErrorString("KDP remove breakpoint failed"); 6805b88216dSGreg Clayton } 681b9c1b51eSKate Stone } else { 6825b88216dSGreg Clayton error = DisableSoftwareBreakpoint(bp_site); 6835b88216dSGreg Clayton } 6845b88216dSGreg Clayton } 68507e66e3eSGreg Clayton return error; 68607e66e3eSGreg Clayton } 687f9765acdSGreg Clayton return DisableSoftwareBreakpoint(bp_site); 688f9765acdSGreg Clayton } 689f9765acdSGreg Clayton 69097206d57SZachary Turner Status ProcessKDP::EnableWatchpoint(Watchpoint *wp, bool notify) { 69197206d57SZachary Turner Status error; 692b9c1b51eSKate Stone error.SetErrorString( 6934ebdee0aSBruce Mitchener "watchpoints are not supported in kdp remote debugging"); 694f9765acdSGreg Clayton return error; 695f9765acdSGreg Clayton } 696f9765acdSGreg Clayton 69797206d57SZachary Turner Status ProcessKDP::DisableWatchpoint(Watchpoint *wp, bool notify) { 69897206d57SZachary Turner Status error; 699b9c1b51eSKate Stone error.SetErrorString( 7004ebdee0aSBruce Mitchener "watchpoints are not supported in kdp remote debugging"); 701f9765acdSGreg Clayton return error; 702f9765acdSGreg Clayton } 703f9765acdSGreg Clayton 704b9c1b51eSKate Stone void ProcessKDP::Clear() { m_thread_list.Clear(); } 705f9765acdSGreg Clayton 70697206d57SZachary Turner Status ProcessKDP::DoSignal(int signo) { 70797206d57SZachary Turner Status error; 708b9c1b51eSKate Stone error.SetErrorString( 7094ebdee0aSBruce Mitchener "sending signals is not supported in kdp remote debugging"); 710f9765acdSGreg Clayton return error; 711f9765acdSGreg Clayton } 712f9765acdSGreg Clayton 713b9c1b51eSKate Stone void ProcessKDP::Initialize() { 714c5f28e2aSKamil Rytarowski static llvm::once_flag g_once_flag; 715f9765acdSGreg Clayton 716c5f28e2aSKamil Rytarowski llvm::call_once(g_once_flag, []() { 717f9765acdSGreg Clayton PluginManager::RegisterPlugin(GetPluginNameStatic(), 718b9c1b51eSKate Stone GetPluginDescriptionStatic(), CreateInstance, 719488c89edSBruce Mitchener DebuggerInitialize); 720f9765acdSGreg Clayton 7217b35b781SPavel Labath ProcessKDPLog::Initialize(); 722c8d69828SDavide Italiano }); 723f9765acdSGreg Clayton } 724f9765acdSGreg Clayton 725b9c1b51eSKate Stone void ProcessKDP::DebuggerInitialize(lldb_private::Debugger &debugger) { 726b9c1b51eSKate Stone if (!PluginManager::GetSettingForProcessPlugin( 727b9c1b51eSKate Stone debugger, PluginProperties::GetSettingName())) { 7287f98240dSGreg Clayton const bool is_global_setting = true; 729b9c1b51eSKate Stone PluginManager::CreateSettingForProcessPlugin( 730b9c1b51eSKate Stone debugger, GetGlobalPluginProperties()->GetValueProperties(), 7317f98240dSGreg Clayton ConstString("Properties for the kdp-remote process plug-in."), 7327f98240dSGreg Clayton is_global_setting); 7337f98240dSGreg Clayton } 7347f98240dSGreg Clayton } 7357f98240dSGreg Clayton 736b9c1b51eSKate Stone bool ProcessKDP::StartAsyncThread() { 7375160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 738f9765acdSGreg Clayton 73963e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::StartAsyncThread ()"); 740f9765acdSGreg Clayton 741acee96aeSZachary Turner if (m_async_thread.IsJoinable()) 7427925fbbaSGreg Clayton return true; 7437925fbbaSGreg Clayton 744f39c2e18SJonas Devlieghere llvm::Expected<HostThread> async_thread = ThreadLauncher::LaunchThread( 745f39c2e18SJonas Devlieghere "<lldb.process.kdp-remote.async>", ProcessKDP::AsyncThread, this); 746f39c2e18SJonas Devlieghere if (!async_thread) { 747f39c2e18SJonas Devlieghere LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), 748f39c2e18SJonas Devlieghere "failed to launch host thread: {}", 749f39c2e18SJonas Devlieghere llvm::toString(async_thread.takeError())); 750f39c2e18SJonas Devlieghere return false; 751f39c2e18SJonas Devlieghere } 752f39c2e18SJonas Devlieghere m_async_thread = *async_thread; 753acee96aeSZachary Turner return m_async_thread.IsJoinable(); 754f9765acdSGreg Clayton } 755f9765acdSGreg Clayton 756b9c1b51eSKate Stone void ProcessKDP::StopAsyncThread() { 7575160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 758f9765acdSGreg Clayton 75963e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::StopAsyncThread ()"); 760f9765acdSGreg Clayton 761f9765acdSGreg Clayton m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit); 762f9765acdSGreg Clayton 763f9765acdSGreg Clayton // Stop the stdio thread 764acee96aeSZachary Turner if (m_async_thread.IsJoinable()) 76539de3110SZachary Turner m_async_thread.Join(nullptr); 766f9765acdSGreg Clayton } 767f9765acdSGreg Clayton 768b9c1b51eSKate Stone void *ProcessKDP::AsyncThread(void *arg) { 769f9765acdSGreg Clayton ProcessKDP *process = (ProcessKDP *)arg; 770f9765acdSGreg Clayton 7717925fbbaSGreg Clayton const lldb::pid_t pid = process->GetID(); 7727925fbbaSGreg Clayton 7735160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 77463e5fb76SJonas Devlieghere LLDB_LOGF(log, 77563e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 776b9c1b51eSKate Stone ") thread starting...", 777b9c1b51eSKate Stone arg, pid); 778f9765acdSGreg Clayton 779583bbb1dSJim Ingham ListenerSP listener_sp(Listener::MakeListener("ProcessKDP::AsyncThread")); 780f9765acdSGreg Clayton EventSP event_sp; 781b9c1b51eSKate Stone const uint32_t desired_event_mask = 782b9c1b51eSKate Stone eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit; 783f9765acdSGreg Clayton 784b9c1b51eSKate Stone if (listener_sp->StartListeningForEvents(&process->m_async_broadcaster, 785b9c1b51eSKate Stone desired_event_mask) == 786b9c1b51eSKate Stone desired_event_mask) { 787f9765acdSGreg Clayton bool done = false; 788b9c1b51eSKate Stone while (!done) { 78963e5fb76SJonas Devlieghere LLDB_LOGF(log, 79063e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 791b9c1b51eSKate Stone ") listener.WaitForEvent (NULL, event_sp)...", 7927925fbbaSGreg Clayton pid); 793fafff0c5SPavel Labath if (listener_sp->GetEvent(event_sp, llvm::None)) { 7947925fbbaSGreg Clayton uint32_t event_type = event_sp->GetType(); 79563e5fb76SJonas Devlieghere LLDB_LOGF(log, 79663e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 797b9c1b51eSKate Stone ") Got an event of type: %d...", 798b9c1b51eSKate Stone pid, event_type); 799f9765acdSGreg Clayton 8007925fbbaSGreg Clayton // When we are running, poll for 1 second to try and get an exception 8017925fbbaSGreg Clayton // to indicate the process has stopped. If we don't get one, check to 8027925fbbaSGreg Clayton // make sure no one asked us to exit 8037925fbbaSGreg Clayton bool is_running = false; 8047925fbbaSGreg Clayton DataExtractor exc_reply_packet; 805b9c1b51eSKate Stone do { 806b9c1b51eSKate Stone switch (event_type) { 807b9c1b51eSKate Stone case eBroadcastBitAsyncContinue: { 8087925fbbaSGreg Clayton is_running = true; 809b9c1b51eSKate Stone if (process->m_comm.WaitForPacketWithTimeoutMicroSeconds( 810b9c1b51eSKate Stone exc_reply_packet, 1 * USEC_PER_SEC)) { 811ba4e61d3SAndrew Kaylor ThreadSP thread_sp(process->GetKernelThread()); 812b9c1b51eSKate Stone if (thread_sp) { 813b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 814b9c1b51eSKate Stone thread_sp->GetRegisterContext()); 8151afa68edSGreg Clayton if (reg_ctx_sp) 8161afa68edSGreg Clayton reg_ctx_sp->InvalidateAllRegisters(); 817b9c1b51eSKate Stone static_cast<ThreadKDP *>(thread_sp.get()) 818b9c1b51eSKate Stone ->SetStopInfoFrom_KDP_EXCEPTION(exc_reply_packet); 8191afa68edSGreg Clayton } 82097d5cf05SGreg Clayton 8217925fbbaSGreg Clayton // TODO: parse the stop reply packet 8227925fbbaSGreg Clayton is_running = false; 8237925fbbaSGreg Clayton process->SetPrivateState(eStateStopped); 824b9c1b51eSKate Stone } else { 8257925fbbaSGreg Clayton // Check to see if we are supposed to exit. There is no way to 8267925fbbaSGreg Clayton // interrupt a running kernel, so all we can do is wait for an 8277925fbbaSGreg Clayton // exception or detach... 828fafff0c5SPavel Labath if (listener_sp->GetEvent(event_sp, 829fafff0c5SPavel Labath std::chrono::microseconds(0))) { 8307925fbbaSGreg Clayton // We got an event, go through the loop again 8317925fbbaSGreg Clayton event_type = event_sp->GetType(); 8327925fbbaSGreg Clayton } 833f9765acdSGreg Clayton } 834b9c1b51eSKate Stone } break; 835f9765acdSGreg Clayton 836f9765acdSGreg Clayton case eBroadcastBitAsyncThreadShouldExit: 83763e5fb76SJonas Devlieghere LLDB_LOGF(log, 83863e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 839b9c1b51eSKate Stone ") got eBroadcastBitAsyncThreadShouldExit...", 8407925fbbaSGreg Clayton pid); 841f9765acdSGreg Clayton done = true; 8427925fbbaSGreg Clayton is_running = false; 843f9765acdSGreg Clayton break; 844f9765acdSGreg Clayton 845f9765acdSGreg Clayton default: 84663e5fb76SJonas Devlieghere LLDB_LOGF(log, 84763e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 848b9c1b51eSKate Stone ") got unknown event 0x%8.8x", 849b9c1b51eSKate Stone pid, event_type); 850f9765acdSGreg Clayton done = true; 8517925fbbaSGreg Clayton is_running = false; 852f9765acdSGreg Clayton break; 853f9765acdSGreg Clayton } 8547925fbbaSGreg Clayton } while (is_running); 855b9c1b51eSKate Stone } else { 85663e5fb76SJonas Devlieghere LLDB_LOGF(log, 85763e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 858b9c1b51eSKate Stone ") listener.WaitForEvent (NULL, event_sp) => false", 8597925fbbaSGreg Clayton pid); 860f9765acdSGreg Clayton done = true; 861f9765acdSGreg Clayton } 862f9765acdSGreg Clayton } 863f9765acdSGreg Clayton } 864f9765acdSGreg Clayton 86563e5fb76SJonas Devlieghere LLDB_LOGF(log, 86663e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 867b9c1b51eSKate Stone ") thread exiting...", 868b9c1b51eSKate Stone arg, pid); 869f9765acdSGreg Clayton 87039de3110SZachary Turner process->m_async_thread.Reset(); 871f9765acdSGreg Clayton return NULL; 872f9765acdSGreg Clayton } 873f9765acdSGreg Clayton 874b9c1b51eSKate Stone class CommandObjectProcessKDPPacketSend : public CommandObjectParsed { 8751d19a2f2SGreg Clayton private: 8761d19a2f2SGreg Clayton OptionGroupOptions m_option_group; 8771d19a2f2SGreg Clayton OptionGroupUInt64 m_command_byte; 8781d19a2f2SGreg Clayton OptionGroupString m_packet_data; 8791d19a2f2SGreg Clayton 88044b43a52SLogan Smith Options *GetOptions() override { return &m_option_group; } 8811d19a2f2SGreg Clayton 8821d19a2f2SGreg Clayton public: 883b9c1b51eSKate Stone CommandObjectProcessKDPPacketSend(CommandInterpreter &interpreter) 884b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "process plugin packet send", 885b9c1b51eSKate Stone "Send a custom packet through the KDP protocol by " 886b9c1b51eSKate Stone "specifying the command byte and the packet " 887b9c1b51eSKate Stone "payload data. A packet will be sent with a " 888b9c1b51eSKate Stone "correct header and payload, and the raw result " 889b9c1b51eSKate Stone "bytes will be displayed as a string value. ", 8901d19a2f2SGreg Clayton NULL), 891e1cfbc79STodd Fiala m_option_group(), 892b9c1b51eSKate Stone m_command_byte(LLDB_OPT_SET_1, true, "command", 'c', 0, eArgTypeNone, 893b9c1b51eSKate Stone "Specify the command byte to use when sending the KDP " 894b9c1b51eSKate Stone "request packet.", 895b9c1b51eSKate Stone 0), 896b9c1b51eSKate Stone m_packet_data(LLDB_OPT_SET_1, false, "payload", 'p', 0, eArgTypeNone, 897b9c1b51eSKate Stone "Specify packet payload bytes as a hex ASCII string with " 898b9c1b51eSKate Stone "no spaces or hex prefixes.", 899b9c1b51eSKate Stone NULL) { 9001d19a2f2SGreg Clayton m_option_group.Append(&m_command_byte, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 9011d19a2f2SGreg Clayton m_option_group.Append(&m_packet_data, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 9021d19a2f2SGreg Clayton m_option_group.Finalize(); 9031d19a2f2SGreg Clayton } 9041d19a2f2SGreg Clayton 905*fd2433e1SJonas Devlieghere ~CommandObjectProcessKDPPacketSend() = default; 9061d19a2f2SGreg Clayton 90744b43a52SLogan Smith bool DoExecute(Args &command, CommandReturnObject &result) override { 9081d19a2f2SGreg Clayton const size_t argc = command.GetArgumentCount(); 909b9c1b51eSKate Stone if (argc == 0) { 910b9c1b51eSKate Stone if (!m_command_byte.GetOptionValue().OptionWasSet()) { 911b9c1b51eSKate Stone result.AppendError( 912b9c1b51eSKate Stone "the --command option must be set to a valid command byte"); 913b9c1b51eSKate Stone } else { 914b9c1b51eSKate Stone const uint64_t command_byte = 915b9c1b51eSKate Stone m_command_byte.GetOptionValue().GetUInt64Value(0); 916b9c1b51eSKate Stone if (command_byte > 0 && command_byte <= UINT8_MAX) { 917b9c1b51eSKate Stone ProcessKDP *process = 918b9c1b51eSKate Stone (ProcessKDP *)m_interpreter.GetExecutionContext().GetProcessPtr(); 919b9c1b51eSKate Stone if (process) { 9201d19a2f2SGreg Clayton const StateType state = process->GetState(); 9211d19a2f2SGreg Clayton 922b9c1b51eSKate Stone if (StateIsStoppedState(state, true)) { 9231d19a2f2SGreg Clayton std::vector<uint8_t> payload_bytes; 924b9c1b51eSKate Stone const char *ascii_hex_bytes_cstr = 925b9c1b51eSKate Stone m_packet_data.GetOptionValue().GetCurrentValue(); 926b9c1b51eSKate Stone if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0]) { 9271d19a2f2SGreg Clayton StringExtractor extractor(ascii_hex_bytes_cstr); 928b9c1b51eSKate Stone const size_t ascii_hex_bytes_cstr_len = 929b9c1b51eSKate Stone extractor.GetStringRef().size(); 930b9c1b51eSKate Stone if (ascii_hex_bytes_cstr_len & 1) { 931b9c1b51eSKate Stone result.AppendErrorWithFormat("payload data must contain an " 932b9c1b51eSKate Stone "even number of ASCII hex " 933b9c1b51eSKate Stone "characters: '%s'", 934b9c1b51eSKate Stone ascii_hex_bytes_cstr); 9351d19a2f2SGreg Clayton return false; 9361d19a2f2SGreg Clayton } 9371d19a2f2SGreg Clayton payload_bytes.resize(ascii_hex_bytes_cstr_len / 2); 938b9c1b51eSKate Stone if (extractor.GetHexBytes(payload_bytes, '\xdd') != 939b9c1b51eSKate Stone payload_bytes.size()) { 940b9c1b51eSKate Stone result.AppendErrorWithFormat("payload data must only contain " 941b9c1b51eSKate Stone "ASCII hex characters (no " 942b9c1b51eSKate Stone "spaces or hex prefixes): '%s'", 943b9c1b51eSKate Stone ascii_hex_bytes_cstr); 9441d19a2f2SGreg Clayton return false; 9451d19a2f2SGreg Clayton } 9461d19a2f2SGreg Clayton } 94797206d57SZachary Turner Status error; 9481d19a2f2SGreg Clayton DataExtractor reply; 949b9c1b51eSKate Stone process->GetCommunication().SendRawRequest( 950b9c1b51eSKate Stone command_byte, 9511d19a2f2SGreg Clayton payload_bytes.empty() ? NULL : payload_bytes.data(), 952b9c1b51eSKate Stone payload_bytes.size(), reply, error); 9531d19a2f2SGreg Clayton 954b9c1b51eSKate Stone if (error.Success()) { 9551d19a2f2SGreg Clayton // Copy the binary bytes into a hex ASCII string for the result 9561d19a2f2SGreg Clayton StreamString packet; 957b9c1b51eSKate Stone packet.PutBytesAsRawHex8( 958b9c1b51eSKate Stone reply.GetDataStart(), reply.GetByteSize(), 959b9c1b51eSKate Stone endian::InlHostByteOrder(), endian::InlHostByteOrder()); 960c156427dSZachary Turner result.AppendMessage(packet.GetString()); 9611d19a2f2SGreg Clayton result.SetStatus(eReturnStatusSuccessFinishResult); 9621d19a2f2SGreg Clayton return true; 963b9c1b51eSKate Stone } else { 9641d19a2f2SGreg Clayton const char *error_cstr = error.AsCString(); 9651d19a2f2SGreg Clayton if (error_cstr && error_cstr[0]) 9661d19a2f2SGreg Clayton result.AppendError(error_cstr); 9671d19a2f2SGreg Clayton else 968b9c1b51eSKate Stone result.AppendErrorWithFormat("unknown error 0x%8.8x", 969b9c1b51eSKate Stone error.GetError()); 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 } 977b9c1b51eSKate Stone } else { 9781d19a2f2SGreg Clayton result.AppendError("invalid process"); 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 } 9851d19a2f2SGreg Clayton } 986b9c1b51eSKate Stone } else { 987b9c1b51eSKate Stone result.AppendErrorWithFormat("'%s' takes no arguments, only options.", 988b9c1b51eSKate Stone m_cmd_name.c_str()); 9891d19a2f2SGreg Clayton } 9901d19a2f2SGreg Clayton return false; 9911d19a2f2SGreg Clayton } 9921d19a2f2SGreg Clayton }; 9931d19a2f2SGreg Clayton 994b9c1b51eSKate Stone class CommandObjectProcessKDPPacket : public CommandObjectMultiword { 9951d19a2f2SGreg Clayton private: 9961d19a2f2SGreg Clayton public: 997b9c1b51eSKate Stone CommandObjectProcessKDPPacket(CommandInterpreter &interpreter) 998b9c1b51eSKate Stone : CommandObjectMultiword(interpreter, "process plugin packet", 9991d19a2f2SGreg Clayton "Commands that deal with KDP remote packets.", 1000b9c1b51eSKate Stone NULL) { 1001b9c1b51eSKate Stone LoadSubCommand( 1002b9c1b51eSKate Stone "send", 1003b9c1b51eSKate Stone CommandObjectSP(new CommandObjectProcessKDPPacketSend(interpreter))); 10041d19a2f2SGreg Clayton } 10051d19a2f2SGreg Clayton 1006*fd2433e1SJonas Devlieghere ~CommandObjectProcessKDPPacket() = default; 10071d19a2f2SGreg Clayton }; 10081d19a2f2SGreg Clayton 1009b9c1b51eSKate Stone class CommandObjectMultiwordProcessKDP : public CommandObjectMultiword { 10101d19a2f2SGreg Clayton public: 10117428a18cSKate Stone CommandObjectMultiwordProcessKDP(CommandInterpreter &interpreter) 1012b9c1b51eSKate Stone : CommandObjectMultiword( 1013b9c1b51eSKate Stone interpreter, "process plugin", 1014b9c1b51eSKate Stone "Commands for operating on a ProcessKDP process.", 1015b9c1b51eSKate Stone "process plugin <subcommand> [<subcommand-options>]") { 1016b9c1b51eSKate Stone LoadSubCommand("packet", CommandObjectSP(new CommandObjectProcessKDPPacket( 1017b9c1b51eSKate Stone interpreter))); 10181d19a2f2SGreg Clayton } 10191d19a2f2SGreg Clayton 1020*fd2433e1SJonas Devlieghere ~CommandObjectMultiwordProcessKDP() = default; 10211d19a2f2SGreg Clayton }; 10221d19a2f2SGreg Clayton 1023b9c1b51eSKate Stone CommandObject *ProcessKDP::GetPluginCommandObject() { 10241d19a2f2SGreg Clayton if (!m_command_sp) 1025796ac80bSJonas Devlieghere m_command_sp = std::make_shared<CommandObjectMultiwordProcessKDP>( 1026796ac80bSJonas Devlieghere GetTarget().GetDebugger().GetCommandInterpreter()); 10271d19a2f2SGreg Clayton return m_command_sp.get(); 10281d19a2f2SGreg Clayton } 1029