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 76fd2433e1SJonas 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 853d7161e3SPavel Labath static PluginProperties &GetGlobalPluginProperties() { 863d7161e3SPavel Labath static PluginProperties g_settings; 873d7161e3SPavel Labath return g_settings; 887f98240dSGreg Clayton } 897f98240dSGreg Clayton 907f98240dSGreg Clayton } // anonymous namespace end 917f98240dSGreg Clayton 92ba4e61d3SAndrew Kaylor static const lldb::tid_t g_kernel_tid = 1; 93ba4e61d3SAndrew Kaylor 94b9c1b51eSKate Stone ConstString ProcessKDP::GetPluginNameStatic() { 9557abc5d6SGreg Clayton static ConstString g_name("kdp-remote"); 9657abc5d6SGreg Clayton return g_name; 97f9765acdSGreg Clayton } 98f9765acdSGreg Clayton 99b9c1b51eSKate Stone const char *ProcessKDP::GetPluginDescriptionStatic() { 100b9c1b51eSKate Stone return "KDP Remote protocol based debugging plug-in for darwin kernel " 101b9c1b51eSKate Stone "debugging."; 102f9765acdSGreg Clayton } 103f9765acdSGreg Clayton 104b9c1b51eSKate Stone void ProcessKDP::Terminate() { 105f9765acdSGreg Clayton PluginManager::UnregisterPlugin(ProcessKDP::CreateInstance); 106f9765acdSGreg Clayton } 107f9765acdSGreg Clayton 108b9c1b51eSKate Stone lldb::ProcessSP ProcessKDP::CreateInstance(TargetSP target_sp, 109583bbb1dSJim Ingham ListenerSP listener_sp, 11018e4272aSMichał Górny const FileSpec *crash_file_path, 11118e4272aSMichał Górny bool can_connect) { 112c3776bf2SGreg Clayton lldb::ProcessSP process_sp; 113c3776bf2SGreg Clayton if (crash_file_path == NULL) 114796ac80bSJonas Devlieghere process_sp = std::make_shared<ProcessKDP>(target_sp, listener_sp); 115c3776bf2SGreg Clayton return process_sp; 116f9765acdSGreg Clayton } 117f9765acdSGreg Clayton 118b9c1b51eSKate Stone bool ProcessKDP::CanDebug(TargetSP target_sp, bool plugin_specified_by_name) { 119596ed24eSGreg Clayton if (plugin_specified_by_name) 120596ed24eSGreg Clayton return true; 121596ed24eSGreg Clayton 122f9765acdSGreg Clayton // For now we are just making sure the file exists for a given module 1235a3bb64fSJim Ingham Module *exe_module = target_sp->GetExecutableModulePointer(); 124b9c1b51eSKate Stone if (exe_module) { 1255a3bb64fSJim Ingham const llvm::Triple &triple_ref = target_sp->GetArchitecture().GetTriple(); 126b9c1b51eSKate Stone switch (triple_ref.getOS()) { 127b9c1b51eSKate Stone case llvm::Triple::Darwin: // Should use "macosx" for desktop and "ios" for 128b9c1b51eSKate Stone // iOS, but accept darwin just in case 12970512317SGreg Clayton case llvm::Triple::MacOSX: // For desktop targets 13070512317SGreg Clayton case llvm::Triple::IOS: // For arm targets 131a814f704SJason Molenda case llvm::Triple::TvOS: 132a814f704SJason Molenda case llvm::Triple::WatchOS: 133b9c1b51eSKate Stone if (triple_ref.getVendor() == llvm::Triple::Apple) { 134aa149cbdSGreg Clayton ObjectFile *exe_objfile = exe_module->GetObjectFile(); 135f9765acdSGreg Clayton if (exe_objfile->GetType() == ObjectFile::eTypeExecutable && 136f9765acdSGreg Clayton exe_objfile->GetStrata() == ObjectFile::eStrataKernel) 137f9765acdSGreg Clayton return true; 138f9765acdSGreg Clayton } 13970512317SGreg Clayton break; 14070512317SGreg Clayton 14170512317SGreg Clayton default: 14270512317SGreg Clayton break; 14370512317SGreg Clayton } 144f9765acdSGreg Clayton } 145596ed24eSGreg Clayton return false; 1463a29bdbeSGreg Clayton } 147f9765acdSGreg Clayton 148f9765acdSGreg Clayton // ProcessKDP constructor 149b9c1b51eSKate Stone ProcessKDP::ProcessKDP(TargetSP target_sp, ListenerSP listener_sp) 150b9c1b51eSKate Stone : Process(target_sp, listener_sp), 151f9765acdSGreg Clayton m_comm("lldb.process.kdp-remote.communication"), 1524bddaeb5SJim Ingham m_async_broadcaster(NULL, "lldb.process.kdp-remote.async-broadcaster"), 153*6fa1b4ffSPavel Labath m_kernel_load_addr(LLDB_INVALID_ADDRESS), m_command_sp(), 154*6fa1b4ffSPavel Labath m_kernel_thread_wp() { 155b9c1b51eSKate Stone m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, 156b9c1b51eSKate Stone "async thread should exit"); 157b9c1b51eSKate Stone m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, 158b9c1b51eSKate Stone "async thread continue"); 159b9c1b51eSKate Stone const uint64_t timeout_seconds = 1603d7161e3SPavel Labath GetGlobalPluginProperties().GetPacketTimeout(); 1617f98240dSGreg Clayton if (timeout_seconds > 0) 1625cddd608SPavel Labath m_comm.SetPacketTimeout(std::chrono::seconds(timeout_seconds)); 163f9765acdSGreg Clayton } 164f9765acdSGreg Clayton 165f9765acdSGreg Clayton // Destructor 166b9c1b51eSKate Stone ProcessKDP::~ProcessKDP() { 167f9765acdSGreg Clayton Clear(); 16805097246SAdrian Prantl // We need to call finalize on the process before destroying ourselves to 16905097246SAdrian Prantl // make sure all of the broadcaster cleanup goes as planned. If we destruct 17005097246SAdrian Prantl // this class, then Process::~Process() might have problems trying to fully 17105097246SAdrian Prantl // destroy the broadcaster. 172e24c4acfSGreg Clayton Finalize(); 173f9765acdSGreg Clayton } 174f9765acdSGreg Clayton 17597206d57SZachary Turner Status ProcessKDP::WillLaunch(Module *module) { 17697206d57SZachary Turner Status error; 177f9765acdSGreg Clayton error.SetErrorString("launching not supported in kdp-remote plug-in"); 178f9765acdSGreg Clayton return error; 179f9765acdSGreg Clayton } 180f9765acdSGreg Clayton 18197206d57SZachary Turner Status ProcessKDP::WillAttachToProcessWithID(lldb::pid_t pid) { 18297206d57SZachary Turner Status error; 183b9c1b51eSKate Stone error.SetErrorString( 184b9c1b51eSKate Stone "attaching to a by process ID not supported in kdp-remote plug-in"); 185f9765acdSGreg Clayton return error; 186f9765acdSGreg Clayton } 187f9765acdSGreg Clayton 18897206d57SZachary Turner Status ProcessKDP::WillAttachToProcessWithName(const char *process_name, 189b9c1b51eSKate Stone bool wait_for_launch) { 19097206d57SZachary Turner Status error; 191b9c1b51eSKate Stone error.SetErrorString( 192b9c1b51eSKate Stone "attaching to a by process name not supported in kdp-remote plug-in"); 193f9765acdSGreg Clayton return error; 194f9765acdSGreg Clayton } 195f9765acdSGreg Clayton 196b9c1b51eSKate Stone bool ProcessKDP::GetHostArchitecture(ArchSpec &arch) { 197a3706888SGreg Clayton uint32_t cpu = m_comm.GetCPUType(); 198b9c1b51eSKate Stone if (cpu) { 199a3706888SGreg Clayton uint32_t sub = m_comm.GetCPUSubtype(); 200a3706888SGreg Clayton arch.SetArchitecture(eArchTypeMachO, cpu, sub); 201a3706888SGreg Clayton // Leave architecture vendor as unspecified unknown 202a3706888SGreg Clayton arch.GetTriple().setVendor(llvm::Triple::UnknownVendor); 203a3706888SGreg Clayton arch.GetTriple().setVendorName(llvm::StringRef()); 204a3706888SGreg Clayton return true; 205a3706888SGreg Clayton } 206a3706888SGreg Clayton arch.Clear(); 207a3706888SGreg Clayton return false; 208a3706888SGreg Clayton } 209a3706888SGreg Clayton 21032d35fb7SJonas Devlieghere Status ProcessKDP::DoConnectRemote(llvm::StringRef remote_url) { 21197206d57SZachary Turner Status error; 2123a29bdbeSGreg Clayton 21305097246SAdrian Prantl // Don't let any JIT happen when doing KDP as we can't allocate memory and we 21405097246SAdrian Prantl // don't want to be mucking with threads that might already be handling 21505097246SAdrian Prantl // exceptions 2167925fbbaSGreg Clayton SetCanJIT(false); 2177925fbbaSGreg Clayton 2183ce7e996SGreg Clayton if (remote_url.empty()) { 2193ce7e996SGreg Clayton error.SetErrorStringWithFormat("empty connection URL"); 2207925fbbaSGreg Clayton return error; 2217925fbbaSGreg Clayton } 2223a29bdbeSGreg Clayton 223d5b44036SJonas Devlieghere std::unique_ptr<ConnectionFileDescriptor> conn_up( 224b9c1b51eSKate Stone new ConnectionFileDescriptor()); 225d5b44036SJonas Devlieghere if (conn_up) { 2263a29bdbeSGreg Clayton // Only try once for now. 2273a29bdbeSGreg Clayton // TODO: check if we should be retrying? 2283a29bdbeSGreg Clayton const uint32_t max_retry_count = 1; 229b9c1b51eSKate Stone for (uint32_t retry_count = 0; retry_count < max_retry_count; 230b9c1b51eSKate Stone ++retry_count) { 231d5b44036SJonas Devlieghere if (conn_up->Connect(remote_url, &error) == eConnectionStatusSuccess) 2323a29bdbeSGreg Clayton break; 2333a29bdbeSGreg Clayton usleep(100000); 2343a29bdbeSGreg Clayton } 2353a29bdbeSGreg Clayton } 2363a29bdbeSGreg Clayton 237d5b44036SJonas Devlieghere if (conn_up->IsConnected()) { 238b9c1b51eSKate Stone const TCPSocket &socket = 239d5b44036SJonas Devlieghere static_cast<const TCPSocket &>(*conn_up->GetReadObject()); 240014bb7daSVince Harron const uint16_t reply_port = socket.GetLocalPortNumber(); 2413a29bdbeSGreg Clayton 242b9c1b51eSKate Stone if (reply_port != 0) { 243451741a9SPavel Labath m_comm.SetConnection(std::move(conn_up)); 2443a29bdbeSGreg Clayton 245b9c1b51eSKate Stone if (m_comm.SendRequestReattach(reply_port)) { 246b9c1b51eSKate Stone if (m_comm.SendRequestConnect(reply_port, reply_port, 247b9c1b51eSKate Stone "Greetings from LLDB...")) { 2483a29bdbeSGreg Clayton m_comm.GetVersion(); 2495a3bb64fSJim Ingham 250a3706888SGreg Clayton Target &target = GetTarget(); 251a3706888SGreg Clayton ArchSpec kernel_arch; 252a3706888SGreg Clayton // The host architecture 253a3706888SGreg Clayton GetHostArchitecture(kernel_arch); 254a3706888SGreg Clayton ArchSpec target_arch = target.GetArchitecture(); 255a3706888SGreg Clayton // Merge in any unspecified stuff into the target architecture in 256a3706888SGreg Clayton // case the target arch isn't set at all or incompletely. 257a3706888SGreg Clayton target_arch.MergeFrom(kernel_arch); 258a3706888SGreg Clayton target.SetArchitecture(target_arch); 2594bd4e7e3SJason Molenda 260b9c1b51eSKate Stone /* Get the kernel's UUID and load address via KDP_KERNELVERSION 261b9c1b51eSKate Stone * packet. */ 262840f12cfSJason Molenda /* An EFI kdp session has neither UUID nor load address. */ 2634bd4e7e3SJason Molenda 2644bd4e7e3SJason Molenda UUID kernel_uuid = m_comm.GetUUID(); 2654bd4e7e3SJason Molenda addr_t kernel_load_addr = m_comm.GetLoadAddress(); 2664bd4e7e3SJason Molenda 267b9c1b51eSKate Stone if (m_comm.RemoteIsEFI()) { 268b9c1b51eSKate Stone // Select an invalid plugin name for the dynamic loader so one 26905097246SAdrian Prantl // doesn't get used since EFI does its own manual loading via 27005097246SAdrian Prantl // python scripting 271*6fa1b4ffSPavel Labath m_dyld_plugin_name = "none"; 272a1bce2efSGreg Clayton 273a1bce2efSGreg Clayton if (kernel_uuid.IsValid()) { 27405097246SAdrian Prantl // If EFI passed in a UUID= try to lookup UUID The slide will not 27505097246SAdrian Prantl // be provided. But the UUID lookup will be used to launch EFI 27605097246SAdrian Prantl // debug scripts from the dSYM, that can load all of the symbols. 277a1bce2efSGreg Clayton ModuleSpec module_spec; 278a1bce2efSGreg Clayton module_spec.GetUUID() = kernel_uuid; 2795a3bb64fSJim Ingham module_spec.GetArchitecture() = target.GetArchitecture(); 280a1bce2efSGreg Clayton 281a1bce2efSGreg Clayton // Lookup UUID locally, before attempting dsymForUUID like action 282a313ec11SZachary Turner FileSpecList search_paths = 283a313ec11SZachary Turner Target::GetDefaultDebugFileSearchPaths(); 284b9c1b51eSKate Stone module_spec.GetSymbolFileSpec() = 285a313ec11SZachary Turner Symbols::LocateExecutableSymbolFile(module_spec, 286a313ec11SZachary Turner search_paths); 287b9c1b51eSKate Stone if (module_spec.GetSymbolFileSpec()) { 288b9c1b51eSKate Stone ModuleSpec executable_module_spec = 289b9c1b51eSKate Stone Symbols::LocateExecutableObjectFile(module_spec); 290dbd7fabaSJonas Devlieghere if (FileSystem::Instance().Exists( 291dbd7fabaSJonas Devlieghere executable_module_spec.GetFileSpec())) { 292b9c1b51eSKate Stone module_spec.GetFileSpec() = 293b9c1b51eSKate Stone executable_module_spec.GetFileSpec(); 2948825c5c9SJason Molenda } 2958825c5c9SJason Molenda } 296b9c1b51eSKate Stone if (!module_spec.GetSymbolFileSpec() || 297b9c1b51eSKate Stone !module_spec.GetSymbolFileSpec()) 298a1bce2efSGreg Clayton Symbols::DownloadObjectAndSymbolFile(module_spec, true); 299a1bce2efSGreg Clayton 300dbd7fabaSJonas Devlieghere if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { 301a3706888SGreg Clayton ModuleSP module_sp(new Module(module_spec)); 302b9c1b51eSKate Stone if (module_sp.get() && module_sp->GetObjectFile()) { 303a1bce2efSGreg Clayton // Get the current target executable 3045a3bb64fSJim Ingham ModuleSP exe_module_sp(target.GetExecutableModule()); 305a1bce2efSGreg Clayton 306b9c1b51eSKate Stone // Make sure you don't already have the right module loaded 307b9c1b51eSKate Stone // and they will be uniqued 308a1bce2efSGreg Clayton if (exe_module_sp.get() != module_sp.get()) 309f9a07e9fSJonas Devlieghere target.SetExecutableModule(module_sp, eLoadDependentsNo); 310a1bce2efSGreg Clayton } 311a1bce2efSGreg Clayton } 312a1bce2efSGreg Clayton } 313b9c1b51eSKate Stone } else if (m_comm.RemoteIsDarwinKernel()) { 314b9c1b51eSKate Stone m_dyld_plugin_name = 315b9c1b51eSKate Stone DynamicLoaderDarwinKernel::GetPluginNameStatic(); 316b9c1b51eSKate Stone if (kernel_load_addr != LLDB_INVALID_ADDRESS) { 3175e8534efSJason Molenda m_kernel_load_addr = kernel_load_addr; 318a8ea4baeSJason Molenda } 3194bd4e7e3SJason Molenda } 3204bd4e7e3SJason Molenda 32197d5cf05SGreg Clayton // Set the thread ID 32297d5cf05SGreg Clayton UpdateThreadListIfNeeded(); 323a63d08c9SGreg Clayton SetID(1); 32456d9a1b3SGreg Clayton GetThreadList(); 325a63d08c9SGreg Clayton SetPrivateState(eStateStopped); 3265a3bb64fSJim Ingham StreamSP async_strm_sp(target.GetDebugger().GetAsyncOutputStream()); 327b9c1b51eSKate Stone if (async_strm_sp) { 3285b88216dSGreg Clayton const char *cstr; 329b9c1b51eSKate Stone if ((cstr = m_comm.GetKernelVersion()) != NULL) { 3305b88216dSGreg Clayton async_strm_sp->Printf("Version: %s\n", cstr); 33107e66e3eSGreg Clayton async_strm_sp->Flush(); 33207e66e3eSGreg Clayton } 3335b88216dSGreg Clayton // if ((cstr = m_comm.GetImagePath ()) != NULL) 3345b88216dSGreg Clayton // { 335b9c1b51eSKate Stone // async_strm_sp->Printf ("Image Path: 336b9c1b51eSKate Stone // %s\n", cstr); 3375b88216dSGreg Clayton // async_strm_sp->Flush(); 3385b88216dSGreg Clayton // } 33907e66e3eSGreg Clayton } 340b9c1b51eSKate Stone } else { 34197d5cf05SGreg Clayton error.SetErrorString("KDP_REATTACH failed"); 34297d5cf05SGreg Clayton } 343b9c1b51eSKate Stone } else { 34497d5cf05SGreg Clayton error.SetErrorString("KDP_REATTACH failed"); 3453a29bdbeSGreg Clayton } 346b9c1b51eSKate Stone } else { 3473a29bdbeSGreg Clayton error.SetErrorString("invalid reply port from UDP connection"); 3483a29bdbeSGreg Clayton } 349b9c1b51eSKate Stone } else { 3503a29bdbeSGreg Clayton if (error.Success()) 3513ce7e996SGreg Clayton error.SetErrorStringWithFormat("failed to connect to '%s'", 3523ce7e996SGreg Clayton remote_url.str().c_str()); 3533a29bdbeSGreg Clayton } 3543a29bdbeSGreg Clayton if (error.Fail()) 3553a29bdbeSGreg Clayton m_comm.Disconnect(); 3563a29bdbeSGreg Clayton 357f9765acdSGreg Clayton return error; 358f9765acdSGreg Clayton } 359f9765acdSGreg Clayton 360f9765acdSGreg Clayton // Process Control 36197206d57SZachary Turner Status ProcessKDP::DoLaunch(Module *exe_module, 36297206d57SZachary Turner ProcessLaunchInfo &launch_info) { 36397206d57SZachary Turner Status error; 364f9765acdSGreg Clayton error.SetErrorString("launching not supported in kdp-remote plug-in"); 365f9765acdSGreg Clayton return error; 366f9765acdSGreg Clayton } 367f9765acdSGreg Clayton 36897206d57SZachary Turner Status 36997206d57SZachary Turner ProcessKDP::DoAttachToProcessWithID(lldb::pid_t attach_pid, 37097206d57SZachary Turner const ProcessAttachInfo &attach_info) { 37197206d57SZachary Turner Status error; 372b9c1b51eSKate Stone error.SetErrorString( 3734ebdee0aSBruce Mitchener "attach to process by ID is not supported in kdp remote debugging"); 37484647048SHan Ming Ong return error; 37584647048SHan Ming Ong } 37684647048SHan Ming Ong 37797206d57SZachary Turner Status 37897206d57SZachary Turner ProcessKDP::DoAttachToProcessWithName(const char *process_name, 37997206d57SZachary Turner const ProcessAttachInfo &attach_info) { 38097206d57SZachary Turner Status error; 381b9c1b51eSKate Stone error.SetErrorString( 3824ebdee0aSBruce Mitchener "attach to process by name is not supported in kdp remote debugging"); 383f9765acdSGreg Clayton return error; 384f9765acdSGreg Clayton } 385f9765acdSGreg Clayton 386b9c1b51eSKate Stone void ProcessKDP::DidAttach(ArchSpec &process_arch) { 387bb006ce2SJim Ingham Process::DidAttach(process_arch); 388bb006ce2SJim Ingham 3895160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 39063e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DidAttach()"); 391b9c1b51eSKate Stone if (GetID() != LLDB_INVALID_PROCESS_ID) { 392a3706888SGreg Clayton GetHostArchitecture(process_arch); 393f9765acdSGreg Clayton } 394f9765acdSGreg Clayton } 395f9765acdSGreg Clayton 396b9c1b51eSKate Stone addr_t ProcessKDP::GetImageInfoAddress() { return m_kernel_load_addr; } 3975e8534efSJason Molenda 398b9c1b51eSKate Stone lldb_private::DynamicLoader *ProcessKDP::GetDynamicLoader() { 399d5b44036SJonas Devlieghere if (m_dyld_up.get() == NULL) 400*6fa1b4ffSPavel Labath m_dyld_up.reset(DynamicLoader::FindPlugin(this, m_dyld_plugin_name)); 401d5b44036SJonas Devlieghere return m_dyld_up.get(); 4025e8534efSJason Molenda } 4035e8534efSJason Molenda 40497206d57SZachary Turner Status ProcessKDP::WillResume() { return Status(); } 405f9765acdSGreg Clayton 40697206d57SZachary Turner Status ProcessKDP::DoResume() { 40797206d57SZachary Turner Status error; 4085160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 4097925fbbaSGreg Clayton // Only start the async thread if we try to do any process control 410acee96aeSZachary Turner if (!m_async_thread.IsJoinable()) 4117925fbbaSGreg Clayton StartAsyncThread(); 4127925fbbaSGreg Clayton 41397d5cf05SGreg Clayton bool resume = false; 4147925fbbaSGreg Clayton 41597d5cf05SGreg Clayton // With KDP there is only one thread we can tell what to do 416ba4e61d3SAndrew Kaylor ThreadSP kernel_thread_sp(m_thread_list.FindThreadByProtocolID(g_kernel_tid)); 417ba4e61d3SAndrew Kaylor 418b9c1b51eSKate Stone if (kernel_thread_sp) { 419b9c1b51eSKate Stone const StateType thread_resume_state = 420b9c1b51eSKate Stone kernel_thread_sp->GetTemporaryResumeState(); 4216e0ff1a3SGreg Clayton 42263e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoResume() thread_resume_state = %s", 423b9c1b51eSKate Stone StateAsCString(thread_resume_state)); 424b9c1b51eSKate Stone switch (thread_resume_state) { 4257925fbbaSGreg Clayton case eStateSuspended: 42605097246SAdrian Prantl // Nothing to do here when a thread will stay suspended we just leave the 42705097246SAdrian Prantl // CPU mask bit set to zero for the thread 42863e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoResume() = suspended???"); 4297925fbbaSGreg Clayton break; 4307925fbbaSGreg Clayton 431b9c1b51eSKate Stone case eStateStepping: { 432b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 433b9c1b51eSKate Stone kernel_thread_sp->GetRegisterContext()); 4341afa68edSGreg Clayton 435b9c1b51eSKate Stone if (reg_ctx_sp) { 43663e5fb76SJonas Devlieghere LLDB_LOGF( 43763e5fb76SJonas Devlieghere log, 438b9c1b51eSKate Stone "ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (true);"); 4391afa68edSGreg Clayton reg_ctx_sp->HardwareSingleStep(true); 44097d5cf05SGreg Clayton resume = true; 441b9c1b51eSKate Stone } else { 442b9c1b51eSKate Stone error.SetErrorStringWithFormat( 443b9c1b51eSKate Stone "KDP thread 0x%llx has no register context", 444b9c1b51eSKate Stone kernel_thread_sp->GetID()); 4451afa68edSGreg Clayton } 446b9c1b51eSKate Stone } break; 4477925fbbaSGreg Clayton 448b9c1b51eSKate Stone case eStateRunning: { 449b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 450b9c1b51eSKate Stone kernel_thread_sp->GetRegisterContext()); 4511afa68edSGreg Clayton 452b9c1b51eSKate Stone if (reg_ctx_sp) { 45363e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep " 454b9c1b51eSKate Stone "(false);"); 4551afa68edSGreg Clayton reg_ctx_sp->HardwareSingleStep(false); 45697d5cf05SGreg Clayton resume = true; 457b9c1b51eSKate Stone } else { 458b9c1b51eSKate Stone error.SetErrorStringWithFormat( 459b9c1b51eSKate Stone "KDP thread 0x%llx has no register context", 460b9c1b51eSKate Stone kernel_thread_sp->GetID()); 4611afa68edSGreg Clayton } 462b9c1b51eSKate Stone } break; 4637925fbbaSGreg Clayton 4647925fbbaSGreg Clayton default: 46597d5cf05SGreg Clayton // The only valid thread resume states are listed above 466a322f36cSDavid Blaikie llvm_unreachable("invalid thread resume state"); 4674b1b8b3eSGreg Clayton } 4684b1b8b3eSGreg Clayton } 4697925fbbaSGreg Clayton 470b9c1b51eSKate Stone if (resume) { 47163e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoResume () sending resume"); 47297d5cf05SGreg Clayton 473b9c1b51eSKate Stone if (m_comm.SendRequestResume()) { 4747925fbbaSGreg Clayton m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue); 4757925fbbaSGreg Clayton SetPrivateState(eStateRunning); 476b9c1b51eSKate Stone } else 47707e66e3eSGreg Clayton error.SetErrorString("KDP resume failed"); 478b9c1b51eSKate Stone } else { 47997d5cf05SGreg Clayton error.SetErrorString("kernel thread is suspended"); 4807925fbbaSGreg Clayton } 4817925fbbaSGreg Clayton 482f9765acdSGreg Clayton return error; 483f9765acdSGreg Clayton } 484f9765acdSGreg Clayton 485b9c1b51eSKate Stone lldb::ThreadSP ProcessKDP::GetKernelThread() { 48697d5cf05SGreg Clayton // KDP only tells us about one thread/core. Any other threads will usually 48797d5cf05SGreg Clayton // be the ones that are read from memory by the OS plug-ins. 488ba4e61d3SAndrew Kaylor 489ba4e61d3SAndrew Kaylor ThreadSP thread_sp(m_kernel_thread_wp.lock()); 490b9c1b51eSKate Stone if (!thread_sp) { 491796ac80bSJonas Devlieghere thread_sp = std::make_shared<ThreadKDP>(*this, g_kernel_tid); 492ba4e61d3SAndrew Kaylor m_kernel_thread_wp = thread_sp; 493ba4e61d3SAndrew Kaylor } 49497d5cf05SGreg Clayton return thread_sp; 49597d5cf05SGreg Clayton } 49697d5cf05SGreg Clayton 4974bb62448SWalter Erquinigo bool ProcessKDP::DoUpdateThreadList(ThreadList &old_thread_list, 498b9c1b51eSKate Stone ThreadList &new_thread_list) { 499f9765acdSGreg Clayton // locker will keep a mutex locked until it goes out of scope 5005160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_THREAD)); 501250858a0SPavel Labath LLDB_LOGV(log, "pid = {0}", GetID()); 502f9765acdSGreg Clayton 50339da3efdSGreg Clayton // Even though there is a CPU mask, it doesn't mean we can see each CPU 504a868c13cSBruce Mitchener // individually, there is really only one. Lets call this thread 1. 505b9c1b51eSKate Stone ThreadSP thread_sp( 506b9c1b51eSKate Stone old_thread_list.FindThreadByProtocolID(g_kernel_tid, false)); 507ba4e61d3SAndrew Kaylor if (!thread_sp) 508ba4e61d3SAndrew Kaylor thread_sp = GetKernelThread(); 509ba4e61d3SAndrew Kaylor new_thread_list.AddThread(thread_sp); 51097d5cf05SGreg Clayton 5119fc13556SGreg Clayton return new_thread_list.GetSize(false) > 0; 512f9765acdSGreg Clayton } 513f9765acdSGreg Clayton 514b9c1b51eSKate Stone void ProcessKDP::RefreshStateAfterStop() { 51505097246SAdrian Prantl // Let all threads recover from stopping and do any clean up based on the 51605097246SAdrian Prantl // previous thread state (if any). 517f9765acdSGreg Clayton m_thread_list.RefreshStateAfterStop(); 518f9765acdSGreg Clayton } 519f9765acdSGreg Clayton 52097206d57SZachary Turner Status ProcessKDP::DoHalt(bool &caused_stop) { 52197206d57SZachary Turner Status error; 522f9765acdSGreg Clayton 523b9c1b51eSKate Stone if (m_comm.IsRunning()) { 524b9c1b51eSKate Stone if (m_destroy_in_process) { 5254ebdee0aSBruce Mitchener // If we are attempting to destroy, we need to not return an error to Halt 52605097246SAdrian Prantl // or DoDestroy won't get called. We are also currently running, so send 52705097246SAdrian Prantl // a process stopped event 52897d5cf05SGreg Clayton SetPrivateState(eStateStopped); 529b9c1b51eSKate Stone } else { 53097d5cf05SGreg Clayton error.SetErrorString("KDP cannot interrupt a running kernel"); 531f9765acdSGreg Clayton } 532f9765acdSGreg Clayton } 533f9765acdSGreg Clayton return error; 534f9765acdSGreg Clayton } 535f9765acdSGreg Clayton 53697206d57SZachary Turner Status ProcessKDP::DoDetach(bool keep_stopped) { 53797206d57SZachary Turner Status error; 5385160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 53963e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoDetach(keep_stopped = %i)", keep_stopped); 540f9765acdSGreg Clayton 541b9c1b51eSKate Stone if (m_comm.IsRunning()) { 54205097246SAdrian Prantl // We are running and we can't interrupt a running kernel, so we need to 54305097246SAdrian Prantl // just close the connection to the kernel and hope for the best 544b9c1b51eSKate Stone } else { 545b9c1b51eSKate Stone // If we are going to keep the target stopped, then don't send the 546b9c1b51eSKate Stone // disconnect message. 547b9c1b51eSKate Stone if (!keep_stopped && m_comm.IsConnected()) { 5486e0ff1a3SGreg Clayton const bool success = m_comm.SendRequestDisconnect(); 549b9c1b51eSKate Stone if (log) { 5506e0ff1a3SGreg Clayton if (success) 551b9c1b51eSKate Stone log->PutCString( 552b9c1b51eSKate Stone "ProcessKDP::DoDetach() detach packet sent successfully"); 553f9765acdSGreg Clayton else 554b9c1b51eSKate Stone log->PutCString( 555b9c1b51eSKate Stone "ProcessKDP::DoDetach() connection channel shutdown failed"); 556f9765acdSGreg Clayton } 5576e0ff1a3SGreg Clayton m_comm.Disconnect(); 5583a29bdbeSGreg Clayton } 55997d5cf05SGreg Clayton } 560f9765acdSGreg Clayton StopAsyncThread(); 56174d4193eSGreg Clayton m_comm.Clear(); 562f9765acdSGreg Clayton 563f9765acdSGreg Clayton SetPrivateState(eStateDetached); 564f9765acdSGreg Clayton ResumePrivateStateThread(); 565f9765acdSGreg Clayton 566f9765acdSGreg Clayton // KillDebugserverProcess (); 567f9765acdSGreg Clayton return error; 568f9765acdSGreg Clayton } 569f9765acdSGreg Clayton 57097206d57SZachary Turner Status ProcessKDP::DoDestroy() { 5717925fbbaSGreg Clayton // For KDP there really is no difference between destroy and detach 572acff8950SJim Ingham bool keep_stopped = false; 573acff8950SJim Ingham return DoDetach(keep_stopped); 574f9765acdSGreg Clayton } 575f9765acdSGreg Clayton 576f9765acdSGreg Clayton // Process Queries 577f9765acdSGreg Clayton 578b9c1b51eSKate Stone bool ProcessKDP::IsAlive() { 579a814f704SJason Molenda return m_comm.IsConnected() && Process::IsAlive(); 580f9765acdSGreg Clayton } 581f9765acdSGreg Clayton 582f9765acdSGreg Clayton // Process Memory 583b9c1b51eSKate Stone size_t ProcessKDP::DoReadMemory(addr_t addr, void *buf, size_t size, 58497206d57SZachary Turner Status &error) { 5858eb32817SJason Molenda uint8_t *data_buffer = (uint8_t *)buf; 586b9c1b51eSKate Stone if (m_comm.IsConnected()) { 5878eb32817SJason Molenda const size_t max_read_size = 512; 5888eb32817SJason Molenda size_t total_bytes_read = 0; 5898eb32817SJason Molenda 5908eb32817SJason Molenda // Read the requested amount of memory in 512 byte chunks 591b9c1b51eSKate Stone while (total_bytes_read < size) { 5928eb32817SJason Molenda size_t bytes_to_read_this_request = size - total_bytes_read; 593b9c1b51eSKate Stone if (bytes_to_read_this_request > max_read_size) { 5948eb32817SJason Molenda bytes_to_read_this_request = max_read_size; 5958eb32817SJason Molenda } 596b9c1b51eSKate Stone size_t bytes_read = m_comm.SendRequestReadMemory( 597b9c1b51eSKate Stone addr + total_bytes_read, data_buffer + total_bytes_read, 5988eb32817SJason Molenda bytes_to_read_this_request, error); 5998eb32817SJason Molenda total_bytes_read += bytes_read; 600b9c1b51eSKate Stone if (error.Fail() || bytes_read == 0) { 6018eb32817SJason Molenda return total_bytes_read; 6028eb32817SJason Molenda } 6038eb32817SJason Molenda } 6048eb32817SJason Molenda 6058eb32817SJason Molenda return total_bytes_read; 6068eb32817SJason Molenda } 607a63d08c9SGreg Clayton error.SetErrorString("not connected"); 608f9765acdSGreg Clayton return 0; 609f9765acdSGreg Clayton } 610f9765acdSGreg Clayton 611b9c1b51eSKate Stone size_t ProcessKDP::DoWriteMemory(addr_t addr, const void *buf, size_t size, 61297206d57SZachary Turner Status &error) { 6137925fbbaSGreg Clayton if (m_comm.IsConnected()) 6147925fbbaSGreg Clayton return m_comm.SendRequestWriteMemory(addr, buf, size, error); 6157925fbbaSGreg Clayton error.SetErrorString("not connected"); 616f9765acdSGreg Clayton return 0; 617f9765acdSGreg Clayton } 618f9765acdSGreg Clayton 619b9c1b51eSKate Stone lldb::addr_t ProcessKDP::DoAllocateMemory(size_t size, uint32_t permissions, 62097206d57SZachary Turner Status &error) { 621b9c1b51eSKate Stone error.SetErrorString( 6224ebdee0aSBruce Mitchener "memory allocation not supported in kdp remote debugging"); 623f9765acdSGreg Clayton return LLDB_INVALID_ADDRESS; 624f9765acdSGreg Clayton } 625f9765acdSGreg Clayton 62697206d57SZachary Turner Status ProcessKDP::DoDeallocateMemory(lldb::addr_t addr) { 62797206d57SZachary Turner Status error; 628b9c1b51eSKate Stone error.SetErrorString( 6294ebdee0aSBruce Mitchener "memory deallocation not supported in kdp remote debugging"); 630f9765acdSGreg Clayton return error; 631f9765acdSGreg Clayton } 632f9765acdSGreg Clayton 63397206d57SZachary Turner Status ProcessKDP::EnableBreakpointSite(BreakpointSite *bp_site) { 634b352e62fSTatyana Krasnukha if (bp_site->HardwareRequired()) 635b352e62fSTatyana Krasnukha return Status("Hardware breakpoints are not supported."); 636b352e62fSTatyana Krasnukha 637b9c1b51eSKate Stone if (m_comm.LocalBreakpointsAreSupported()) { 63897206d57SZachary Turner Status error; 639b9c1b51eSKate Stone if (!bp_site->IsEnabled()) { 640b9c1b51eSKate Stone if (m_comm.SendRequestBreakpoint(true, bp_site->GetLoadAddress())) { 6415b88216dSGreg Clayton bp_site->SetEnabled(true); 6425b88216dSGreg Clayton bp_site->SetType(BreakpointSite::eExternal); 643b9c1b51eSKate Stone } else { 64407e66e3eSGreg Clayton error.SetErrorString("KDP set breakpoint failed"); 6455b88216dSGreg Clayton } 6465b88216dSGreg Clayton } 64707e66e3eSGreg Clayton return error; 64807e66e3eSGreg Clayton } 649f9765acdSGreg Clayton return EnableSoftwareBreakpoint(bp_site); 650f9765acdSGreg Clayton } 651f9765acdSGreg Clayton 65297206d57SZachary Turner Status ProcessKDP::DisableBreakpointSite(BreakpointSite *bp_site) { 653b9c1b51eSKate Stone if (m_comm.LocalBreakpointsAreSupported()) { 65497206d57SZachary Turner Status error; 655b9c1b51eSKate Stone if (bp_site->IsEnabled()) { 6565b88216dSGreg Clayton BreakpointSite::Type bp_type = bp_site->GetType(); 657b9c1b51eSKate Stone if (bp_type == BreakpointSite::eExternal) { 658b9c1b51eSKate Stone if (m_destroy_in_process && m_comm.IsRunning()) { 65997d5cf05SGreg Clayton // We are trying to destroy our connection and we are running 66097d5cf05SGreg Clayton bp_site->SetEnabled(false); 661b9c1b51eSKate Stone } else { 6625b88216dSGreg Clayton if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress())) 6635b88216dSGreg Clayton bp_site->SetEnabled(false); 6645b88216dSGreg Clayton else 66507e66e3eSGreg Clayton error.SetErrorString("KDP remove breakpoint failed"); 6665b88216dSGreg Clayton } 667b9c1b51eSKate Stone } else { 6685b88216dSGreg Clayton error = DisableSoftwareBreakpoint(bp_site); 6695b88216dSGreg Clayton } 6705b88216dSGreg Clayton } 67107e66e3eSGreg Clayton return error; 67207e66e3eSGreg Clayton } 673f9765acdSGreg Clayton return DisableSoftwareBreakpoint(bp_site); 674f9765acdSGreg Clayton } 675f9765acdSGreg Clayton 67697206d57SZachary Turner Status ProcessKDP::EnableWatchpoint(Watchpoint *wp, bool notify) { 67797206d57SZachary Turner Status error; 678b9c1b51eSKate Stone error.SetErrorString( 6794ebdee0aSBruce Mitchener "watchpoints are not supported in kdp remote debugging"); 680f9765acdSGreg Clayton return error; 681f9765acdSGreg Clayton } 682f9765acdSGreg Clayton 68397206d57SZachary Turner Status ProcessKDP::DisableWatchpoint(Watchpoint *wp, bool notify) { 68497206d57SZachary Turner Status error; 685b9c1b51eSKate Stone error.SetErrorString( 6864ebdee0aSBruce Mitchener "watchpoints are not supported in kdp remote debugging"); 687f9765acdSGreg Clayton return error; 688f9765acdSGreg Clayton } 689f9765acdSGreg Clayton 690b9c1b51eSKate Stone void ProcessKDP::Clear() { m_thread_list.Clear(); } 691f9765acdSGreg Clayton 69297206d57SZachary Turner Status ProcessKDP::DoSignal(int signo) { 69397206d57SZachary Turner Status error; 694b9c1b51eSKate Stone error.SetErrorString( 6954ebdee0aSBruce Mitchener "sending signals is not supported in kdp remote debugging"); 696f9765acdSGreg Clayton return error; 697f9765acdSGreg Clayton } 698f9765acdSGreg Clayton 699b9c1b51eSKate Stone void ProcessKDP::Initialize() { 700c5f28e2aSKamil Rytarowski static llvm::once_flag g_once_flag; 701f9765acdSGreg Clayton 702c5f28e2aSKamil Rytarowski llvm::call_once(g_once_flag, []() { 703f9765acdSGreg Clayton PluginManager::RegisterPlugin(GetPluginNameStatic(), 704b9c1b51eSKate Stone GetPluginDescriptionStatic(), CreateInstance, 705488c89edSBruce Mitchener DebuggerInitialize); 706f9765acdSGreg Clayton 7077b35b781SPavel Labath ProcessKDPLog::Initialize(); 708c8d69828SDavide Italiano }); 709f9765acdSGreg Clayton } 710f9765acdSGreg Clayton 711b9c1b51eSKate Stone void ProcessKDP::DebuggerInitialize(lldb_private::Debugger &debugger) { 712b9c1b51eSKate Stone if (!PluginManager::GetSettingForProcessPlugin( 713b9c1b51eSKate Stone debugger, PluginProperties::GetSettingName())) { 7147f98240dSGreg Clayton const bool is_global_setting = true; 715b9c1b51eSKate Stone PluginManager::CreateSettingForProcessPlugin( 7163d7161e3SPavel Labath debugger, GetGlobalPluginProperties().GetValueProperties(), 7177f98240dSGreg Clayton ConstString("Properties for the kdp-remote process plug-in."), 7187f98240dSGreg Clayton is_global_setting); 7197f98240dSGreg Clayton } 7207f98240dSGreg Clayton } 7217f98240dSGreg Clayton 722b9c1b51eSKate Stone bool ProcessKDP::StartAsyncThread() { 7235160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 724f9765acdSGreg Clayton 72563e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::StartAsyncThread ()"); 726f9765acdSGreg Clayton 727acee96aeSZachary Turner if (m_async_thread.IsJoinable()) 7287925fbbaSGreg Clayton return true; 7297925fbbaSGreg Clayton 730f39c2e18SJonas Devlieghere llvm::Expected<HostThread> async_thread = ThreadLauncher::LaunchThread( 731f39c2e18SJonas Devlieghere "<lldb.process.kdp-remote.async>", ProcessKDP::AsyncThread, this); 732f39c2e18SJonas Devlieghere if (!async_thread) { 733f39c2e18SJonas Devlieghere LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), 734f39c2e18SJonas Devlieghere "failed to launch host thread: {}", 735f39c2e18SJonas Devlieghere llvm::toString(async_thread.takeError())); 736f39c2e18SJonas Devlieghere return false; 737f39c2e18SJonas Devlieghere } 738f39c2e18SJonas Devlieghere m_async_thread = *async_thread; 739acee96aeSZachary Turner return m_async_thread.IsJoinable(); 740f9765acdSGreg Clayton } 741f9765acdSGreg Clayton 742b9c1b51eSKate Stone void ProcessKDP::StopAsyncThread() { 7435160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 744f9765acdSGreg Clayton 74563e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::StopAsyncThread ()"); 746f9765acdSGreg Clayton 747f9765acdSGreg Clayton m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit); 748f9765acdSGreg Clayton 749f9765acdSGreg Clayton // Stop the stdio thread 750acee96aeSZachary Turner if (m_async_thread.IsJoinable()) 75139de3110SZachary Turner m_async_thread.Join(nullptr); 752f9765acdSGreg Clayton } 753f9765acdSGreg Clayton 754b9c1b51eSKate Stone void *ProcessKDP::AsyncThread(void *arg) { 755f9765acdSGreg Clayton ProcessKDP *process = (ProcessKDP *)arg; 756f9765acdSGreg Clayton 7577925fbbaSGreg Clayton const lldb::pid_t pid = process->GetID(); 7587925fbbaSGreg Clayton 7595160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 76063e5fb76SJonas Devlieghere LLDB_LOGF(log, 76163e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 762b9c1b51eSKate Stone ") thread starting...", 763b9c1b51eSKate Stone arg, pid); 764f9765acdSGreg Clayton 765583bbb1dSJim Ingham ListenerSP listener_sp(Listener::MakeListener("ProcessKDP::AsyncThread")); 766f9765acdSGreg Clayton EventSP event_sp; 767b9c1b51eSKate Stone const uint32_t desired_event_mask = 768b9c1b51eSKate Stone eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit; 769f9765acdSGreg Clayton 770b9c1b51eSKate Stone if (listener_sp->StartListeningForEvents(&process->m_async_broadcaster, 771b9c1b51eSKate Stone desired_event_mask) == 772b9c1b51eSKate Stone desired_event_mask) { 773f9765acdSGreg Clayton bool done = false; 774b9c1b51eSKate Stone while (!done) { 77563e5fb76SJonas Devlieghere LLDB_LOGF(log, 77663e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 777b9c1b51eSKate Stone ") listener.WaitForEvent (NULL, event_sp)...", 7787925fbbaSGreg Clayton pid); 779fafff0c5SPavel Labath if (listener_sp->GetEvent(event_sp, llvm::None)) { 7807925fbbaSGreg Clayton uint32_t event_type = event_sp->GetType(); 78163e5fb76SJonas Devlieghere LLDB_LOGF(log, 78263e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 783b9c1b51eSKate Stone ") Got an event of type: %d...", 784b9c1b51eSKate Stone pid, event_type); 785f9765acdSGreg Clayton 7867925fbbaSGreg Clayton // When we are running, poll for 1 second to try and get an exception 7877925fbbaSGreg Clayton // to indicate the process has stopped. If we don't get one, check to 7887925fbbaSGreg Clayton // make sure no one asked us to exit 7897925fbbaSGreg Clayton bool is_running = false; 7907925fbbaSGreg Clayton DataExtractor exc_reply_packet; 791b9c1b51eSKate Stone do { 792b9c1b51eSKate Stone switch (event_type) { 793b9c1b51eSKate Stone case eBroadcastBitAsyncContinue: { 7947925fbbaSGreg Clayton is_running = true; 795b9c1b51eSKate Stone if (process->m_comm.WaitForPacketWithTimeoutMicroSeconds( 796b9c1b51eSKate Stone exc_reply_packet, 1 * USEC_PER_SEC)) { 797ba4e61d3SAndrew Kaylor ThreadSP thread_sp(process->GetKernelThread()); 798b9c1b51eSKate Stone if (thread_sp) { 799b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 800b9c1b51eSKate Stone thread_sp->GetRegisterContext()); 8011afa68edSGreg Clayton if (reg_ctx_sp) 8021afa68edSGreg Clayton reg_ctx_sp->InvalidateAllRegisters(); 803b9c1b51eSKate Stone static_cast<ThreadKDP *>(thread_sp.get()) 804b9c1b51eSKate Stone ->SetStopInfoFrom_KDP_EXCEPTION(exc_reply_packet); 8051afa68edSGreg Clayton } 80697d5cf05SGreg Clayton 8077925fbbaSGreg Clayton // TODO: parse the stop reply packet 8087925fbbaSGreg Clayton is_running = false; 8097925fbbaSGreg Clayton process->SetPrivateState(eStateStopped); 810b9c1b51eSKate Stone } else { 8117925fbbaSGreg Clayton // Check to see if we are supposed to exit. There is no way to 8127925fbbaSGreg Clayton // interrupt a running kernel, so all we can do is wait for an 8137925fbbaSGreg Clayton // exception or detach... 814fafff0c5SPavel Labath if (listener_sp->GetEvent(event_sp, 815fafff0c5SPavel Labath std::chrono::microseconds(0))) { 8167925fbbaSGreg Clayton // We got an event, go through the loop again 8177925fbbaSGreg Clayton event_type = event_sp->GetType(); 8187925fbbaSGreg Clayton } 819f9765acdSGreg Clayton } 820b9c1b51eSKate Stone } break; 821f9765acdSGreg Clayton 822f9765acdSGreg Clayton case eBroadcastBitAsyncThreadShouldExit: 82363e5fb76SJonas Devlieghere LLDB_LOGF(log, 82463e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 825b9c1b51eSKate Stone ") got eBroadcastBitAsyncThreadShouldExit...", 8267925fbbaSGreg Clayton pid); 827f9765acdSGreg Clayton done = true; 8287925fbbaSGreg Clayton is_running = false; 829f9765acdSGreg Clayton break; 830f9765acdSGreg Clayton 831f9765acdSGreg Clayton default: 83263e5fb76SJonas Devlieghere LLDB_LOGF(log, 83363e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 834b9c1b51eSKate Stone ") got unknown event 0x%8.8x", 835b9c1b51eSKate Stone pid, event_type); 836f9765acdSGreg Clayton done = true; 8377925fbbaSGreg Clayton is_running = false; 838f9765acdSGreg Clayton break; 839f9765acdSGreg Clayton } 8407925fbbaSGreg Clayton } while (is_running); 841b9c1b51eSKate Stone } else { 84263e5fb76SJonas Devlieghere LLDB_LOGF(log, 84363e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 844b9c1b51eSKate Stone ") listener.WaitForEvent (NULL, event_sp) => false", 8457925fbbaSGreg Clayton pid); 846f9765acdSGreg Clayton done = true; 847f9765acdSGreg Clayton } 848f9765acdSGreg Clayton } 849f9765acdSGreg Clayton } 850f9765acdSGreg Clayton 85163e5fb76SJonas Devlieghere LLDB_LOGF(log, 85263e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 853b9c1b51eSKate Stone ") thread exiting...", 854b9c1b51eSKate Stone arg, pid); 855f9765acdSGreg Clayton 85639de3110SZachary Turner process->m_async_thread.Reset(); 857f9765acdSGreg Clayton return NULL; 858f9765acdSGreg Clayton } 859f9765acdSGreg Clayton 860b9c1b51eSKate Stone class CommandObjectProcessKDPPacketSend : public CommandObjectParsed { 8611d19a2f2SGreg Clayton private: 8621d19a2f2SGreg Clayton OptionGroupOptions m_option_group; 8631d19a2f2SGreg Clayton OptionGroupUInt64 m_command_byte; 8641d19a2f2SGreg Clayton OptionGroupString m_packet_data; 8651d19a2f2SGreg Clayton 86644b43a52SLogan Smith Options *GetOptions() override { return &m_option_group; } 8671d19a2f2SGreg Clayton 8681d19a2f2SGreg Clayton public: 869b9c1b51eSKate Stone CommandObjectProcessKDPPacketSend(CommandInterpreter &interpreter) 870b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "process plugin packet send", 871b9c1b51eSKate Stone "Send a custom packet through the KDP protocol by " 872b9c1b51eSKate Stone "specifying the command byte and the packet " 873b9c1b51eSKate Stone "payload data. A packet will be sent with a " 874b9c1b51eSKate Stone "correct header and payload, and the raw result " 875b9c1b51eSKate Stone "bytes will be displayed as a string value. ", 8761d19a2f2SGreg Clayton NULL), 877e1cfbc79STodd Fiala m_option_group(), 878b9c1b51eSKate Stone m_command_byte(LLDB_OPT_SET_1, true, "command", 'c', 0, eArgTypeNone, 879b9c1b51eSKate Stone "Specify the command byte to use when sending the KDP " 880b9c1b51eSKate Stone "request packet.", 881b9c1b51eSKate Stone 0), 882b9c1b51eSKate Stone m_packet_data(LLDB_OPT_SET_1, false, "payload", 'p', 0, eArgTypeNone, 883b9c1b51eSKate Stone "Specify packet payload bytes as a hex ASCII string with " 884b9c1b51eSKate Stone "no spaces or hex prefixes.", 885b9c1b51eSKate Stone NULL) { 8861d19a2f2SGreg Clayton m_option_group.Append(&m_command_byte, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 8871d19a2f2SGreg Clayton m_option_group.Append(&m_packet_data, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 8881d19a2f2SGreg Clayton m_option_group.Finalize(); 8891d19a2f2SGreg Clayton } 8901d19a2f2SGreg Clayton 891fd2433e1SJonas Devlieghere ~CommandObjectProcessKDPPacketSend() = default; 8921d19a2f2SGreg Clayton 89344b43a52SLogan Smith bool DoExecute(Args &command, CommandReturnObject &result) override { 8941d19a2f2SGreg Clayton const size_t argc = command.GetArgumentCount(); 895b9c1b51eSKate Stone if (argc == 0) { 896b9c1b51eSKate Stone if (!m_command_byte.GetOptionValue().OptionWasSet()) { 897b9c1b51eSKate Stone result.AppendError( 898b9c1b51eSKate Stone "the --command option must be set to a valid command byte"); 899b9c1b51eSKate Stone } else { 900b9c1b51eSKate Stone const uint64_t command_byte = 901b9c1b51eSKate Stone m_command_byte.GetOptionValue().GetUInt64Value(0); 902b9c1b51eSKate Stone if (command_byte > 0 && command_byte <= UINT8_MAX) { 903b9c1b51eSKate Stone ProcessKDP *process = 904b9c1b51eSKate Stone (ProcessKDP *)m_interpreter.GetExecutionContext().GetProcessPtr(); 905b9c1b51eSKate Stone if (process) { 9061d19a2f2SGreg Clayton const StateType state = process->GetState(); 9071d19a2f2SGreg Clayton 908b9c1b51eSKate Stone if (StateIsStoppedState(state, true)) { 9091d19a2f2SGreg Clayton std::vector<uint8_t> payload_bytes; 910b9c1b51eSKate Stone const char *ascii_hex_bytes_cstr = 911b9c1b51eSKate Stone m_packet_data.GetOptionValue().GetCurrentValue(); 912b9c1b51eSKate Stone if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0]) { 9131d19a2f2SGreg Clayton StringExtractor extractor(ascii_hex_bytes_cstr); 914b9c1b51eSKate Stone const size_t ascii_hex_bytes_cstr_len = 915b9c1b51eSKate Stone extractor.GetStringRef().size(); 916b9c1b51eSKate Stone if (ascii_hex_bytes_cstr_len & 1) { 917b9c1b51eSKate Stone result.AppendErrorWithFormat("payload data must contain an " 918b9c1b51eSKate Stone "even number of ASCII hex " 919b9c1b51eSKate Stone "characters: '%s'", 920b9c1b51eSKate Stone ascii_hex_bytes_cstr); 9211d19a2f2SGreg Clayton return false; 9221d19a2f2SGreg Clayton } 9231d19a2f2SGreg Clayton payload_bytes.resize(ascii_hex_bytes_cstr_len / 2); 924b9c1b51eSKate Stone if (extractor.GetHexBytes(payload_bytes, '\xdd') != 925b9c1b51eSKate Stone payload_bytes.size()) { 926b9c1b51eSKate Stone result.AppendErrorWithFormat("payload data must only contain " 927b9c1b51eSKate Stone "ASCII hex characters (no " 928b9c1b51eSKate Stone "spaces or hex prefixes): '%s'", 929b9c1b51eSKate Stone ascii_hex_bytes_cstr); 9301d19a2f2SGreg Clayton return false; 9311d19a2f2SGreg Clayton } 9321d19a2f2SGreg Clayton } 93397206d57SZachary Turner Status error; 9341d19a2f2SGreg Clayton DataExtractor reply; 935b9c1b51eSKate Stone process->GetCommunication().SendRawRequest( 936b9c1b51eSKate Stone command_byte, 9371d19a2f2SGreg Clayton payload_bytes.empty() ? NULL : payload_bytes.data(), 938b9c1b51eSKate Stone payload_bytes.size(), reply, error); 9391d19a2f2SGreg Clayton 940b9c1b51eSKate Stone if (error.Success()) { 9411d19a2f2SGreg Clayton // Copy the binary bytes into a hex ASCII string for the result 9421d19a2f2SGreg Clayton StreamString packet; 943b9c1b51eSKate Stone packet.PutBytesAsRawHex8( 944b9c1b51eSKate Stone reply.GetDataStart(), reply.GetByteSize(), 945b9c1b51eSKate Stone endian::InlHostByteOrder(), endian::InlHostByteOrder()); 946c156427dSZachary Turner result.AppendMessage(packet.GetString()); 9471d19a2f2SGreg Clayton result.SetStatus(eReturnStatusSuccessFinishResult); 9481d19a2f2SGreg Clayton return true; 949b9c1b51eSKate Stone } else { 9501d19a2f2SGreg Clayton const char *error_cstr = error.AsCString(); 9511d19a2f2SGreg Clayton if (error_cstr && error_cstr[0]) 9521d19a2f2SGreg Clayton result.AppendError(error_cstr); 9531d19a2f2SGreg Clayton else 954b9c1b51eSKate Stone result.AppendErrorWithFormat("unknown error 0x%8.8x", 955b9c1b51eSKate Stone error.GetError()); 9561d19a2f2SGreg Clayton return false; 9571d19a2f2SGreg Clayton } 958b9c1b51eSKate Stone } else { 959b9c1b51eSKate Stone result.AppendErrorWithFormat("process must be stopped in order " 960b9c1b51eSKate Stone "to send KDP packets, state is %s", 961b9c1b51eSKate Stone StateAsCString(state)); 9621d19a2f2SGreg Clayton } 963b9c1b51eSKate Stone } else { 9641d19a2f2SGreg Clayton result.AppendError("invalid process"); 9651d19a2f2SGreg Clayton } 966b9c1b51eSKate Stone } else { 967b9c1b51eSKate Stone result.AppendErrorWithFormat("invalid command byte 0x%" PRIx64 968b9c1b51eSKate Stone ", valid values are 1 - 255", 969b9c1b51eSKate Stone command_byte); 9701d19a2f2SGreg Clayton } 9711d19a2f2SGreg Clayton } 972b9c1b51eSKate Stone } else { 973b9c1b51eSKate Stone result.AppendErrorWithFormat("'%s' takes no arguments, only options.", 974b9c1b51eSKate Stone m_cmd_name.c_str()); 9751d19a2f2SGreg Clayton } 9761d19a2f2SGreg Clayton return false; 9771d19a2f2SGreg Clayton } 9781d19a2f2SGreg Clayton }; 9791d19a2f2SGreg Clayton 980b9c1b51eSKate Stone class CommandObjectProcessKDPPacket : public CommandObjectMultiword { 9811d19a2f2SGreg Clayton private: 9821d19a2f2SGreg Clayton public: 983b9c1b51eSKate Stone CommandObjectProcessKDPPacket(CommandInterpreter &interpreter) 984b9c1b51eSKate Stone : CommandObjectMultiword(interpreter, "process plugin packet", 9851d19a2f2SGreg Clayton "Commands that deal with KDP remote packets.", 986b9c1b51eSKate Stone NULL) { 987b9c1b51eSKate Stone LoadSubCommand( 988b9c1b51eSKate Stone "send", 989b9c1b51eSKate Stone CommandObjectSP(new CommandObjectProcessKDPPacketSend(interpreter))); 9901d19a2f2SGreg Clayton } 9911d19a2f2SGreg Clayton 992fd2433e1SJonas Devlieghere ~CommandObjectProcessKDPPacket() = default; 9931d19a2f2SGreg Clayton }; 9941d19a2f2SGreg Clayton 995b9c1b51eSKate Stone class CommandObjectMultiwordProcessKDP : public CommandObjectMultiword { 9961d19a2f2SGreg Clayton public: 9977428a18cSKate Stone CommandObjectMultiwordProcessKDP(CommandInterpreter &interpreter) 998b9c1b51eSKate Stone : CommandObjectMultiword( 999b9c1b51eSKate Stone interpreter, "process plugin", 1000b9c1b51eSKate Stone "Commands for operating on a ProcessKDP process.", 1001b9c1b51eSKate Stone "process plugin <subcommand> [<subcommand-options>]") { 1002b9c1b51eSKate Stone LoadSubCommand("packet", CommandObjectSP(new CommandObjectProcessKDPPacket( 1003b9c1b51eSKate Stone interpreter))); 10041d19a2f2SGreg Clayton } 10051d19a2f2SGreg Clayton 1006fd2433e1SJonas Devlieghere ~CommandObjectMultiwordProcessKDP() = default; 10071d19a2f2SGreg Clayton }; 10081d19a2f2SGreg Clayton 1009b9c1b51eSKate Stone CommandObject *ProcessKDP::GetPluginCommandObject() { 10101d19a2f2SGreg Clayton if (!m_command_sp) 1011796ac80bSJonas Devlieghere m_command_sp = std::make_shared<CommandObjectMultiwordProcessKDP>( 1012796ac80bSJonas Devlieghere GetTarget().GetDebugger().GetCommandInterpreter()); 10131d19a2f2SGreg Clayton return m_command_sp.get(); 10141d19a2f2SGreg Clayton } 1015