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() { 685f4980f0SPavel Labath return ConstString(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 945f4980f0SPavel Labath llvm::StringRef ProcessKDP::GetPluginDescriptionStatic() { 95b9c1b51eSKate Stone return "KDP Remote protocol based debugging plug-in for darwin kernel " 96b9c1b51eSKate Stone "debugging."; 97f9765acdSGreg Clayton } 98f9765acdSGreg Clayton 99b9c1b51eSKate Stone void ProcessKDP::Terminate() { 100f9765acdSGreg Clayton PluginManager::UnregisterPlugin(ProcessKDP::CreateInstance); 101f9765acdSGreg Clayton } 102f9765acdSGreg Clayton 103b9c1b51eSKate Stone lldb::ProcessSP ProcessKDP::CreateInstance(TargetSP target_sp, 104583bbb1dSJim Ingham ListenerSP listener_sp, 10518e4272aSMichał Górny const FileSpec *crash_file_path, 10618e4272aSMichał Górny bool can_connect) { 107c3776bf2SGreg Clayton lldb::ProcessSP process_sp; 108c3776bf2SGreg Clayton if (crash_file_path == NULL) 109796ac80bSJonas Devlieghere process_sp = std::make_shared<ProcessKDP>(target_sp, listener_sp); 110c3776bf2SGreg Clayton return process_sp; 111f9765acdSGreg Clayton } 112f9765acdSGreg Clayton 113b9c1b51eSKate Stone bool ProcessKDP::CanDebug(TargetSP target_sp, bool plugin_specified_by_name) { 114596ed24eSGreg Clayton if (plugin_specified_by_name) 115596ed24eSGreg Clayton return true; 116596ed24eSGreg Clayton 117f9765acdSGreg Clayton // For now we are just making sure the file exists for a given module 1185a3bb64fSJim Ingham Module *exe_module = target_sp->GetExecutableModulePointer(); 119b9c1b51eSKate Stone if (exe_module) { 1205a3bb64fSJim Ingham const llvm::Triple &triple_ref = target_sp->GetArchitecture().GetTriple(); 121b9c1b51eSKate Stone switch (triple_ref.getOS()) { 122b9c1b51eSKate Stone case llvm::Triple::Darwin: // Should use "macosx" for desktop and "ios" for 123b9c1b51eSKate Stone // iOS, but accept darwin just in case 12470512317SGreg Clayton case llvm::Triple::MacOSX: // For desktop targets 12570512317SGreg Clayton case llvm::Triple::IOS: // For arm targets 126a814f704SJason Molenda case llvm::Triple::TvOS: 127a814f704SJason Molenda case llvm::Triple::WatchOS: 128b9c1b51eSKate Stone if (triple_ref.getVendor() == llvm::Triple::Apple) { 129aa149cbdSGreg Clayton ObjectFile *exe_objfile = exe_module->GetObjectFile(); 130f9765acdSGreg Clayton if (exe_objfile->GetType() == ObjectFile::eTypeExecutable && 131f9765acdSGreg Clayton exe_objfile->GetStrata() == ObjectFile::eStrataKernel) 132f9765acdSGreg Clayton return true; 133f9765acdSGreg Clayton } 13470512317SGreg Clayton break; 13570512317SGreg Clayton 13670512317SGreg Clayton default: 13770512317SGreg Clayton break; 13870512317SGreg Clayton } 139f9765acdSGreg Clayton } 140596ed24eSGreg Clayton return false; 1413a29bdbeSGreg Clayton } 142f9765acdSGreg Clayton 143f9765acdSGreg Clayton // ProcessKDP constructor 144b9c1b51eSKate Stone ProcessKDP::ProcessKDP(TargetSP target_sp, ListenerSP listener_sp) 145b9c1b51eSKate Stone : Process(target_sp, listener_sp), 146f9765acdSGreg Clayton m_comm("lldb.process.kdp-remote.communication"), 1474bddaeb5SJim Ingham m_async_broadcaster(NULL, "lldb.process.kdp-remote.async-broadcaster"), 1486fa1b4ffSPavel Labath m_kernel_load_addr(LLDB_INVALID_ADDRESS), m_command_sp(), 1496fa1b4ffSPavel Labath m_kernel_thread_wp() { 150b9c1b51eSKate Stone m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, 151b9c1b51eSKate Stone "async thread should exit"); 152b9c1b51eSKate Stone m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, 153b9c1b51eSKate Stone "async thread continue"); 154b9c1b51eSKate Stone const uint64_t timeout_seconds = 1553d7161e3SPavel Labath GetGlobalPluginProperties().GetPacketTimeout(); 1567f98240dSGreg Clayton if (timeout_seconds > 0) 1575cddd608SPavel Labath m_comm.SetPacketTimeout(std::chrono::seconds(timeout_seconds)); 158f9765acdSGreg Clayton } 159f9765acdSGreg Clayton 160f9765acdSGreg Clayton // Destructor 161b9c1b51eSKate Stone ProcessKDP::~ProcessKDP() { 162f9765acdSGreg Clayton Clear(); 16305097246SAdrian Prantl // We need to call finalize on the process before destroying ourselves to 16405097246SAdrian Prantl // make sure all of the broadcaster cleanup goes as planned. If we destruct 16505097246SAdrian Prantl // this class, then Process::~Process() might have problems trying to fully 16605097246SAdrian Prantl // destroy the broadcaster. 167e24c4acfSGreg Clayton Finalize(); 168f9765acdSGreg Clayton } 169f9765acdSGreg Clayton 17097206d57SZachary Turner Status ProcessKDP::WillLaunch(Module *module) { 17197206d57SZachary Turner Status error; 172f9765acdSGreg Clayton error.SetErrorString("launching not supported in kdp-remote plug-in"); 173f9765acdSGreg Clayton return error; 174f9765acdSGreg Clayton } 175f9765acdSGreg Clayton 17697206d57SZachary Turner Status ProcessKDP::WillAttachToProcessWithID(lldb::pid_t pid) { 17797206d57SZachary Turner Status error; 178b9c1b51eSKate Stone error.SetErrorString( 179b9c1b51eSKate Stone "attaching to a by process ID not supported in kdp-remote plug-in"); 180f9765acdSGreg Clayton return error; 181f9765acdSGreg Clayton } 182f9765acdSGreg Clayton 18397206d57SZachary Turner Status ProcessKDP::WillAttachToProcessWithName(const char *process_name, 184b9c1b51eSKate Stone bool wait_for_launch) { 18597206d57SZachary Turner Status error; 186b9c1b51eSKate Stone error.SetErrorString( 187b9c1b51eSKate Stone "attaching to a by process name not supported in kdp-remote plug-in"); 188f9765acdSGreg Clayton return error; 189f9765acdSGreg Clayton } 190f9765acdSGreg Clayton 191b9c1b51eSKate Stone bool ProcessKDP::GetHostArchitecture(ArchSpec &arch) { 192a3706888SGreg Clayton uint32_t cpu = m_comm.GetCPUType(); 193b9c1b51eSKate Stone if (cpu) { 194a3706888SGreg Clayton uint32_t sub = m_comm.GetCPUSubtype(); 195a3706888SGreg Clayton arch.SetArchitecture(eArchTypeMachO, cpu, sub); 196a3706888SGreg Clayton // Leave architecture vendor as unspecified unknown 197a3706888SGreg Clayton arch.GetTriple().setVendor(llvm::Triple::UnknownVendor); 198a3706888SGreg Clayton arch.GetTriple().setVendorName(llvm::StringRef()); 199a3706888SGreg Clayton return true; 200a3706888SGreg Clayton } 201a3706888SGreg Clayton arch.Clear(); 202a3706888SGreg Clayton return false; 203a3706888SGreg Clayton } 204a3706888SGreg Clayton 20532d35fb7SJonas Devlieghere Status ProcessKDP::DoConnectRemote(llvm::StringRef remote_url) { 20697206d57SZachary Turner Status error; 2073a29bdbeSGreg Clayton 20805097246SAdrian Prantl // Don't let any JIT happen when doing KDP as we can't allocate memory and we 20905097246SAdrian Prantl // don't want to be mucking with threads that might already be handling 21005097246SAdrian Prantl // exceptions 2117925fbbaSGreg Clayton SetCanJIT(false); 2127925fbbaSGreg Clayton 2133ce7e996SGreg Clayton if (remote_url.empty()) { 2143ce7e996SGreg Clayton error.SetErrorStringWithFormat("empty connection URL"); 2157925fbbaSGreg Clayton return error; 2167925fbbaSGreg Clayton } 2173a29bdbeSGreg Clayton 218d5b44036SJonas Devlieghere std::unique_ptr<ConnectionFileDescriptor> conn_up( 219b9c1b51eSKate Stone new ConnectionFileDescriptor()); 220d5b44036SJonas Devlieghere if (conn_up) { 2213a29bdbeSGreg Clayton // Only try once for now. 2223a29bdbeSGreg Clayton // TODO: check if we should be retrying? 2233a29bdbeSGreg Clayton const uint32_t max_retry_count = 1; 224b9c1b51eSKate Stone for (uint32_t retry_count = 0; retry_count < max_retry_count; 225b9c1b51eSKate Stone ++retry_count) { 226d5b44036SJonas Devlieghere if (conn_up->Connect(remote_url, &error) == eConnectionStatusSuccess) 2273a29bdbeSGreg Clayton break; 2283a29bdbeSGreg Clayton usleep(100000); 2293a29bdbeSGreg Clayton } 2303a29bdbeSGreg Clayton } 2313a29bdbeSGreg Clayton 232d5b44036SJonas Devlieghere if (conn_up->IsConnected()) { 233b9c1b51eSKate Stone const TCPSocket &socket = 234d5b44036SJonas Devlieghere static_cast<const TCPSocket &>(*conn_up->GetReadObject()); 235014bb7daSVince Harron const uint16_t reply_port = socket.GetLocalPortNumber(); 2363a29bdbeSGreg Clayton 237b9c1b51eSKate Stone if (reply_port != 0) { 238451741a9SPavel Labath m_comm.SetConnection(std::move(conn_up)); 2393a29bdbeSGreg Clayton 240b9c1b51eSKate Stone if (m_comm.SendRequestReattach(reply_port)) { 241b9c1b51eSKate Stone if (m_comm.SendRequestConnect(reply_port, reply_port, 242b9c1b51eSKate Stone "Greetings from LLDB...")) { 2433a29bdbeSGreg Clayton m_comm.GetVersion(); 2445a3bb64fSJim Ingham 245a3706888SGreg Clayton Target &target = GetTarget(); 246a3706888SGreg Clayton ArchSpec kernel_arch; 247a3706888SGreg Clayton // The host architecture 248a3706888SGreg Clayton GetHostArchitecture(kernel_arch); 249a3706888SGreg Clayton ArchSpec target_arch = target.GetArchitecture(); 250a3706888SGreg Clayton // Merge in any unspecified stuff into the target architecture in 251a3706888SGreg Clayton // case the target arch isn't set at all or incompletely. 252a3706888SGreg Clayton target_arch.MergeFrom(kernel_arch); 253a3706888SGreg Clayton target.SetArchitecture(target_arch); 2544bd4e7e3SJason Molenda 255b9c1b51eSKate Stone /* Get the kernel's UUID and load address via KDP_KERNELVERSION 256b9c1b51eSKate Stone * packet. */ 257840f12cfSJason Molenda /* An EFI kdp session has neither UUID nor load address. */ 2584bd4e7e3SJason Molenda 2594bd4e7e3SJason Molenda UUID kernel_uuid = m_comm.GetUUID(); 2604bd4e7e3SJason Molenda addr_t kernel_load_addr = m_comm.GetLoadAddress(); 2614bd4e7e3SJason Molenda 262b9c1b51eSKate Stone if (m_comm.RemoteIsEFI()) { 263b9c1b51eSKate Stone // Select an invalid plugin name for the dynamic loader so one 26405097246SAdrian Prantl // doesn't get used since EFI does its own manual loading via 26505097246SAdrian Prantl // python scripting 2666fa1b4ffSPavel Labath m_dyld_plugin_name = "none"; 267a1bce2efSGreg Clayton 268a1bce2efSGreg Clayton if (kernel_uuid.IsValid()) { 26905097246SAdrian Prantl // If EFI passed in a UUID= try to lookup UUID The slide will not 27005097246SAdrian Prantl // be provided. But the UUID lookup will be used to launch EFI 27105097246SAdrian Prantl // debug scripts from the dSYM, that can load all of the symbols. 272a1bce2efSGreg Clayton ModuleSpec module_spec; 273a1bce2efSGreg Clayton module_spec.GetUUID() = kernel_uuid; 2745a3bb64fSJim Ingham module_spec.GetArchitecture() = target.GetArchitecture(); 275a1bce2efSGreg Clayton 276a1bce2efSGreg Clayton // Lookup UUID locally, before attempting dsymForUUID like action 277a313ec11SZachary Turner FileSpecList search_paths = 278a313ec11SZachary Turner Target::GetDefaultDebugFileSearchPaths(); 279b9c1b51eSKate Stone module_spec.GetSymbolFileSpec() = 280a313ec11SZachary Turner Symbols::LocateExecutableSymbolFile(module_spec, 281a313ec11SZachary Turner search_paths); 282b9c1b51eSKate Stone if (module_spec.GetSymbolFileSpec()) { 283b9c1b51eSKate Stone ModuleSpec executable_module_spec = 284b9c1b51eSKate Stone Symbols::LocateExecutableObjectFile(module_spec); 285dbd7fabaSJonas Devlieghere if (FileSystem::Instance().Exists( 286dbd7fabaSJonas Devlieghere executable_module_spec.GetFileSpec())) { 287b9c1b51eSKate Stone module_spec.GetFileSpec() = 288b9c1b51eSKate Stone executable_module_spec.GetFileSpec(); 2898825c5c9SJason Molenda } 2908825c5c9SJason Molenda } 291b9c1b51eSKate Stone if (!module_spec.GetSymbolFileSpec() || 292b9c1b51eSKate Stone !module_spec.GetSymbolFileSpec()) 293a1bce2efSGreg Clayton Symbols::DownloadObjectAndSymbolFile(module_spec, true); 294a1bce2efSGreg Clayton 295dbd7fabaSJonas Devlieghere if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { 296a3706888SGreg Clayton ModuleSP module_sp(new Module(module_spec)); 297b9c1b51eSKate Stone if (module_sp.get() && module_sp->GetObjectFile()) { 298a1bce2efSGreg Clayton // Get the current target executable 2995a3bb64fSJim Ingham ModuleSP exe_module_sp(target.GetExecutableModule()); 300a1bce2efSGreg Clayton 301b9c1b51eSKate Stone // Make sure you don't already have the right module loaded 302b9c1b51eSKate Stone // and they will be uniqued 303a1bce2efSGreg Clayton if (exe_module_sp.get() != module_sp.get()) 304f9a07e9fSJonas Devlieghere target.SetExecutableModule(module_sp, eLoadDependentsNo); 305a1bce2efSGreg Clayton } 306a1bce2efSGreg Clayton } 307a1bce2efSGreg Clayton } 308b9c1b51eSKate Stone } else if (m_comm.RemoteIsDarwinKernel()) { 309b9c1b51eSKate Stone m_dyld_plugin_name = 310b9c1b51eSKate Stone DynamicLoaderDarwinKernel::GetPluginNameStatic(); 311b9c1b51eSKate Stone if (kernel_load_addr != LLDB_INVALID_ADDRESS) { 3125e8534efSJason Molenda m_kernel_load_addr = kernel_load_addr; 313a8ea4baeSJason Molenda } 3144bd4e7e3SJason Molenda } 3154bd4e7e3SJason Molenda 31697d5cf05SGreg Clayton // Set the thread ID 31797d5cf05SGreg Clayton UpdateThreadListIfNeeded(); 318a63d08c9SGreg Clayton SetID(1); 31956d9a1b3SGreg Clayton GetThreadList(); 320a63d08c9SGreg Clayton SetPrivateState(eStateStopped); 3215a3bb64fSJim Ingham StreamSP async_strm_sp(target.GetDebugger().GetAsyncOutputStream()); 322b9c1b51eSKate Stone if (async_strm_sp) { 3235b88216dSGreg Clayton const char *cstr; 324b9c1b51eSKate Stone if ((cstr = m_comm.GetKernelVersion()) != NULL) { 3255b88216dSGreg Clayton async_strm_sp->Printf("Version: %s\n", cstr); 32607e66e3eSGreg Clayton async_strm_sp->Flush(); 32707e66e3eSGreg Clayton } 3285b88216dSGreg Clayton // if ((cstr = m_comm.GetImagePath ()) != NULL) 3295b88216dSGreg Clayton // { 330b9c1b51eSKate Stone // async_strm_sp->Printf ("Image Path: 331b9c1b51eSKate Stone // %s\n", cstr); 3325b88216dSGreg Clayton // async_strm_sp->Flush(); 3335b88216dSGreg Clayton // } 33407e66e3eSGreg Clayton } 335b9c1b51eSKate Stone } else { 33697d5cf05SGreg Clayton error.SetErrorString("KDP_REATTACH failed"); 33797d5cf05SGreg Clayton } 338b9c1b51eSKate Stone } else { 33997d5cf05SGreg Clayton error.SetErrorString("KDP_REATTACH failed"); 3403a29bdbeSGreg Clayton } 341b9c1b51eSKate Stone } else { 3423a29bdbeSGreg Clayton error.SetErrorString("invalid reply port from UDP connection"); 3433a29bdbeSGreg Clayton } 344b9c1b51eSKate Stone } else { 3453a29bdbeSGreg Clayton if (error.Success()) 3463ce7e996SGreg Clayton error.SetErrorStringWithFormat("failed to connect to '%s'", 3473ce7e996SGreg Clayton remote_url.str().c_str()); 3483a29bdbeSGreg Clayton } 3493a29bdbeSGreg Clayton if (error.Fail()) 3503a29bdbeSGreg Clayton m_comm.Disconnect(); 3513a29bdbeSGreg Clayton 352f9765acdSGreg Clayton return error; 353f9765acdSGreg Clayton } 354f9765acdSGreg Clayton 355f9765acdSGreg Clayton // Process Control 35697206d57SZachary Turner Status ProcessKDP::DoLaunch(Module *exe_module, 35797206d57SZachary Turner ProcessLaunchInfo &launch_info) { 35897206d57SZachary Turner Status error; 359f9765acdSGreg Clayton error.SetErrorString("launching not supported in kdp-remote plug-in"); 360f9765acdSGreg Clayton return error; 361f9765acdSGreg Clayton } 362f9765acdSGreg Clayton 36397206d57SZachary Turner Status 36497206d57SZachary Turner ProcessKDP::DoAttachToProcessWithID(lldb::pid_t attach_pid, 36597206d57SZachary Turner const ProcessAttachInfo &attach_info) { 36697206d57SZachary Turner Status error; 367b9c1b51eSKate Stone error.SetErrorString( 3684ebdee0aSBruce Mitchener "attach to process by ID is not supported in kdp remote debugging"); 36984647048SHan Ming Ong return error; 37084647048SHan Ming Ong } 37184647048SHan Ming Ong 37297206d57SZachary Turner Status 37397206d57SZachary Turner ProcessKDP::DoAttachToProcessWithName(const char *process_name, 37497206d57SZachary Turner const ProcessAttachInfo &attach_info) { 37597206d57SZachary Turner Status error; 376b9c1b51eSKate Stone error.SetErrorString( 3774ebdee0aSBruce Mitchener "attach to process by name is not supported in kdp remote debugging"); 378f9765acdSGreg Clayton return error; 379f9765acdSGreg Clayton } 380f9765acdSGreg Clayton 381b9c1b51eSKate Stone void ProcessKDP::DidAttach(ArchSpec &process_arch) { 382bb006ce2SJim Ingham Process::DidAttach(process_arch); 383bb006ce2SJim Ingham 384*c8fbf803SPavel Labath Log *log = GetLog(KDPLog::Process); 38563e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DidAttach()"); 386b9c1b51eSKate Stone if (GetID() != LLDB_INVALID_PROCESS_ID) { 387a3706888SGreg Clayton GetHostArchitecture(process_arch); 388f9765acdSGreg Clayton } 389f9765acdSGreg Clayton } 390f9765acdSGreg Clayton 391b9c1b51eSKate Stone addr_t ProcessKDP::GetImageInfoAddress() { return m_kernel_load_addr; } 3925e8534efSJason Molenda 393b9c1b51eSKate Stone lldb_private::DynamicLoader *ProcessKDP::GetDynamicLoader() { 394d5b44036SJonas Devlieghere if (m_dyld_up.get() == NULL) 3956fa1b4ffSPavel Labath m_dyld_up.reset(DynamicLoader::FindPlugin(this, m_dyld_plugin_name)); 396d5b44036SJonas Devlieghere return m_dyld_up.get(); 3975e8534efSJason Molenda } 3985e8534efSJason Molenda 39997206d57SZachary Turner Status ProcessKDP::WillResume() { return Status(); } 400f9765acdSGreg Clayton 40197206d57SZachary Turner Status ProcessKDP::DoResume() { 40297206d57SZachary Turner Status error; 403*c8fbf803SPavel Labath Log *log = GetLog(KDPLog::Process); 4047925fbbaSGreg Clayton // Only start the async thread if we try to do any process control 405acee96aeSZachary Turner if (!m_async_thread.IsJoinable()) 4067925fbbaSGreg Clayton StartAsyncThread(); 4077925fbbaSGreg Clayton 40897d5cf05SGreg Clayton bool resume = false; 4097925fbbaSGreg Clayton 41097d5cf05SGreg Clayton // With KDP there is only one thread we can tell what to do 411ba4e61d3SAndrew Kaylor ThreadSP kernel_thread_sp(m_thread_list.FindThreadByProtocolID(g_kernel_tid)); 412ba4e61d3SAndrew Kaylor 413b9c1b51eSKate Stone if (kernel_thread_sp) { 414b9c1b51eSKate Stone const StateType thread_resume_state = 415b9c1b51eSKate Stone kernel_thread_sp->GetTemporaryResumeState(); 4166e0ff1a3SGreg Clayton 41763e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoResume() thread_resume_state = %s", 418b9c1b51eSKate Stone StateAsCString(thread_resume_state)); 419b9c1b51eSKate Stone switch (thread_resume_state) { 4207925fbbaSGreg Clayton case eStateSuspended: 42105097246SAdrian Prantl // Nothing to do here when a thread will stay suspended we just leave the 42205097246SAdrian Prantl // CPU mask bit set to zero for the thread 42363e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoResume() = suspended???"); 4247925fbbaSGreg Clayton break; 4257925fbbaSGreg Clayton 426b9c1b51eSKate Stone case eStateStepping: { 427b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 428b9c1b51eSKate Stone kernel_thread_sp->GetRegisterContext()); 4291afa68edSGreg Clayton 430b9c1b51eSKate Stone if (reg_ctx_sp) { 43163e5fb76SJonas Devlieghere LLDB_LOGF( 43263e5fb76SJonas Devlieghere log, 433b9c1b51eSKate Stone "ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (true);"); 4341afa68edSGreg Clayton reg_ctx_sp->HardwareSingleStep(true); 43597d5cf05SGreg Clayton resume = true; 436b9c1b51eSKate Stone } else { 437b9c1b51eSKate Stone error.SetErrorStringWithFormat( 438b9c1b51eSKate Stone "KDP thread 0x%llx has no register context", 439b9c1b51eSKate Stone kernel_thread_sp->GetID()); 4401afa68edSGreg Clayton } 441b9c1b51eSKate Stone } break; 4427925fbbaSGreg Clayton 443b9c1b51eSKate Stone case eStateRunning: { 444b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 445b9c1b51eSKate Stone kernel_thread_sp->GetRegisterContext()); 4461afa68edSGreg Clayton 447b9c1b51eSKate Stone if (reg_ctx_sp) { 44863e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep " 449b9c1b51eSKate Stone "(false);"); 4501afa68edSGreg Clayton reg_ctx_sp->HardwareSingleStep(false); 45197d5cf05SGreg Clayton resume = true; 452b9c1b51eSKate Stone } else { 453b9c1b51eSKate Stone error.SetErrorStringWithFormat( 454b9c1b51eSKate Stone "KDP thread 0x%llx has no register context", 455b9c1b51eSKate Stone kernel_thread_sp->GetID()); 4561afa68edSGreg Clayton } 457b9c1b51eSKate Stone } break; 4587925fbbaSGreg Clayton 4597925fbbaSGreg Clayton default: 46097d5cf05SGreg Clayton // The only valid thread resume states are listed above 461a322f36cSDavid Blaikie llvm_unreachable("invalid thread resume state"); 4624b1b8b3eSGreg Clayton } 4634b1b8b3eSGreg Clayton } 4647925fbbaSGreg Clayton 465b9c1b51eSKate Stone if (resume) { 46663e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoResume () sending resume"); 46797d5cf05SGreg Clayton 468b9c1b51eSKate Stone if (m_comm.SendRequestResume()) { 4697925fbbaSGreg Clayton m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue); 4707925fbbaSGreg Clayton SetPrivateState(eStateRunning); 471b9c1b51eSKate Stone } else 47207e66e3eSGreg Clayton error.SetErrorString("KDP resume failed"); 473b9c1b51eSKate Stone } else { 47497d5cf05SGreg Clayton error.SetErrorString("kernel thread is suspended"); 4757925fbbaSGreg Clayton } 4767925fbbaSGreg Clayton 477f9765acdSGreg Clayton return error; 478f9765acdSGreg Clayton } 479f9765acdSGreg Clayton 480b9c1b51eSKate Stone lldb::ThreadSP ProcessKDP::GetKernelThread() { 48197d5cf05SGreg Clayton // KDP only tells us about one thread/core. Any other threads will usually 48297d5cf05SGreg Clayton // be the ones that are read from memory by the OS plug-ins. 483ba4e61d3SAndrew Kaylor 484ba4e61d3SAndrew Kaylor ThreadSP thread_sp(m_kernel_thread_wp.lock()); 485b9c1b51eSKate Stone if (!thread_sp) { 486796ac80bSJonas Devlieghere thread_sp = std::make_shared<ThreadKDP>(*this, g_kernel_tid); 487ba4e61d3SAndrew Kaylor m_kernel_thread_wp = thread_sp; 488ba4e61d3SAndrew Kaylor } 48997d5cf05SGreg Clayton return thread_sp; 49097d5cf05SGreg Clayton } 49197d5cf05SGreg Clayton 4924bb62448SWalter Erquinigo bool ProcessKDP::DoUpdateThreadList(ThreadList &old_thread_list, 493b9c1b51eSKate Stone ThreadList &new_thread_list) { 494f9765acdSGreg Clayton // locker will keep a mutex locked until it goes out of scope 495*c8fbf803SPavel Labath Log *log = GetLog(KDPLog::Thread); 496250858a0SPavel Labath LLDB_LOGV(log, "pid = {0}", GetID()); 497f9765acdSGreg Clayton 49839da3efdSGreg Clayton // Even though there is a CPU mask, it doesn't mean we can see each CPU 499a868c13cSBruce Mitchener // individually, there is really only one. Lets call this thread 1. 500b9c1b51eSKate Stone ThreadSP thread_sp( 501b9c1b51eSKate Stone old_thread_list.FindThreadByProtocolID(g_kernel_tid, false)); 502ba4e61d3SAndrew Kaylor if (!thread_sp) 503ba4e61d3SAndrew Kaylor thread_sp = GetKernelThread(); 504ba4e61d3SAndrew Kaylor new_thread_list.AddThread(thread_sp); 50597d5cf05SGreg Clayton 5069fc13556SGreg Clayton return new_thread_list.GetSize(false) > 0; 507f9765acdSGreg Clayton } 508f9765acdSGreg Clayton 509b9c1b51eSKate Stone void ProcessKDP::RefreshStateAfterStop() { 51005097246SAdrian Prantl // Let all threads recover from stopping and do any clean up based on the 51105097246SAdrian Prantl // previous thread state (if any). 512f9765acdSGreg Clayton m_thread_list.RefreshStateAfterStop(); 513f9765acdSGreg Clayton } 514f9765acdSGreg Clayton 51597206d57SZachary Turner Status ProcessKDP::DoHalt(bool &caused_stop) { 51697206d57SZachary Turner Status error; 517f9765acdSGreg Clayton 518b9c1b51eSKate Stone if (m_comm.IsRunning()) { 519b9c1b51eSKate Stone if (m_destroy_in_process) { 5204ebdee0aSBruce Mitchener // If we are attempting to destroy, we need to not return an error to Halt 52105097246SAdrian Prantl // or DoDestroy won't get called. We are also currently running, so send 52205097246SAdrian Prantl // a process stopped event 52397d5cf05SGreg Clayton SetPrivateState(eStateStopped); 524b9c1b51eSKate Stone } else { 52597d5cf05SGreg Clayton error.SetErrorString("KDP cannot interrupt a running kernel"); 526f9765acdSGreg Clayton } 527f9765acdSGreg Clayton } 528f9765acdSGreg Clayton return error; 529f9765acdSGreg Clayton } 530f9765acdSGreg Clayton 53197206d57SZachary Turner Status ProcessKDP::DoDetach(bool keep_stopped) { 53297206d57SZachary Turner Status error; 533*c8fbf803SPavel Labath Log *log = GetLog(KDPLog::Process); 53463e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::DoDetach(keep_stopped = %i)", keep_stopped); 535f9765acdSGreg Clayton 536b9c1b51eSKate Stone if (m_comm.IsRunning()) { 53705097246SAdrian Prantl // We are running and we can't interrupt a running kernel, so we need to 53805097246SAdrian Prantl // just close the connection to the kernel and hope for the best 539b9c1b51eSKate Stone } else { 540b9c1b51eSKate Stone // If we are going to keep the target stopped, then don't send the 541b9c1b51eSKate Stone // disconnect message. 542b9c1b51eSKate Stone if (!keep_stopped && m_comm.IsConnected()) { 5436e0ff1a3SGreg Clayton const bool success = m_comm.SendRequestDisconnect(); 544b9c1b51eSKate Stone if (log) { 5456e0ff1a3SGreg Clayton if (success) 546b9c1b51eSKate Stone log->PutCString( 547b9c1b51eSKate Stone "ProcessKDP::DoDetach() detach packet sent successfully"); 548f9765acdSGreg Clayton else 549b9c1b51eSKate Stone log->PutCString( 550b9c1b51eSKate Stone "ProcessKDP::DoDetach() connection channel shutdown failed"); 551f9765acdSGreg Clayton } 5526e0ff1a3SGreg Clayton m_comm.Disconnect(); 5533a29bdbeSGreg Clayton } 55497d5cf05SGreg Clayton } 555f9765acdSGreg Clayton StopAsyncThread(); 55674d4193eSGreg Clayton m_comm.Clear(); 557f9765acdSGreg Clayton 558f9765acdSGreg Clayton SetPrivateState(eStateDetached); 559f9765acdSGreg Clayton ResumePrivateStateThread(); 560f9765acdSGreg Clayton 561f9765acdSGreg Clayton // KillDebugserverProcess (); 562f9765acdSGreg Clayton return error; 563f9765acdSGreg Clayton } 564f9765acdSGreg Clayton 56597206d57SZachary Turner Status ProcessKDP::DoDestroy() { 5667925fbbaSGreg Clayton // For KDP there really is no difference between destroy and detach 567acff8950SJim Ingham bool keep_stopped = false; 568acff8950SJim Ingham return DoDetach(keep_stopped); 569f9765acdSGreg Clayton } 570f9765acdSGreg Clayton 571f9765acdSGreg Clayton // Process Queries 572f9765acdSGreg Clayton 573b9c1b51eSKate Stone bool ProcessKDP::IsAlive() { 574a814f704SJason Molenda return m_comm.IsConnected() && Process::IsAlive(); 575f9765acdSGreg Clayton } 576f9765acdSGreg Clayton 577f9765acdSGreg Clayton // Process Memory 578b9c1b51eSKate Stone size_t ProcessKDP::DoReadMemory(addr_t addr, void *buf, size_t size, 57997206d57SZachary Turner Status &error) { 5808eb32817SJason Molenda uint8_t *data_buffer = (uint8_t *)buf; 581b9c1b51eSKate Stone if (m_comm.IsConnected()) { 5828eb32817SJason Molenda const size_t max_read_size = 512; 5838eb32817SJason Molenda size_t total_bytes_read = 0; 5848eb32817SJason Molenda 5858eb32817SJason Molenda // Read the requested amount of memory in 512 byte chunks 586b9c1b51eSKate Stone while (total_bytes_read < size) { 5878eb32817SJason Molenda size_t bytes_to_read_this_request = size - total_bytes_read; 588b9c1b51eSKate Stone if (bytes_to_read_this_request > max_read_size) { 5898eb32817SJason Molenda bytes_to_read_this_request = max_read_size; 5908eb32817SJason Molenda } 591b9c1b51eSKate Stone size_t bytes_read = m_comm.SendRequestReadMemory( 592b9c1b51eSKate Stone addr + total_bytes_read, data_buffer + total_bytes_read, 5938eb32817SJason Molenda bytes_to_read_this_request, error); 5948eb32817SJason Molenda total_bytes_read += bytes_read; 595b9c1b51eSKate Stone if (error.Fail() || bytes_read == 0) { 5968eb32817SJason Molenda return total_bytes_read; 5978eb32817SJason Molenda } 5988eb32817SJason Molenda } 5998eb32817SJason Molenda 6008eb32817SJason Molenda return total_bytes_read; 6018eb32817SJason Molenda } 602a63d08c9SGreg Clayton error.SetErrorString("not connected"); 603f9765acdSGreg Clayton return 0; 604f9765acdSGreg Clayton } 605f9765acdSGreg Clayton 606b9c1b51eSKate Stone size_t ProcessKDP::DoWriteMemory(addr_t addr, const void *buf, size_t size, 60797206d57SZachary Turner Status &error) { 6087925fbbaSGreg Clayton if (m_comm.IsConnected()) 6097925fbbaSGreg Clayton return m_comm.SendRequestWriteMemory(addr, buf, size, error); 6107925fbbaSGreg Clayton error.SetErrorString("not connected"); 611f9765acdSGreg Clayton return 0; 612f9765acdSGreg Clayton } 613f9765acdSGreg Clayton 614b9c1b51eSKate Stone lldb::addr_t ProcessKDP::DoAllocateMemory(size_t size, uint32_t permissions, 61597206d57SZachary Turner Status &error) { 616b9c1b51eSKate Stone error.SetErrorString( 6174ebdee0aSBruce Mitchener "memory allocation not supported in kdp remote debugging"); 618f9765acdSGreg Clayton return LLDB_INVALID_ADDRESS; 619f9765acdSGreg Clayton } 620f9765acdSGreg Clayton 62197206d57SZachary Turner Status ProcessKDP::DoDeallocateMemory(lldb::addr_t addr) { 62297206d57SZachary Turner Status error; 623b9c1b51eSKate Stone error.SetErrorString( 6244ebdee0aSBruce Mitchener "memory deallocation not supported in kdp remote debugging"); 625f9765acdSGreg Clayton return error; 626f9765acdSGreg Clayton } 627f9765acdSGreg Clayton 62897206d57SZachary Turner Status ProcessKDP::EnableBreakpointSite(BreakpointSite *bp_site) { 629b352e62fSTatyana Krasnukha if (bp_site->HardwareRequired()) 630b352e62fSTatyana Krasnukha return Status("Hardware breakpoints are not supported."); 631b352e62fSTatyana Krasnukha 632b9c1b51eSKate Stone if (m_comm.LocalBreakpointsAreSupported()) { 63397206d57SZachary Turner Status error; 634b9c1b51eSKate Stone if (!bp_site->IsEnabled()) { 635b9c1b51eSKate Stone if (m_comm.SendRequestBreakpoint(true, bp_site->GetLoadAddress())) { 6365b88216dSGreg Clayton bp_site->SetEnabled(true); 6375b88216dSGreg Clayton bp_site->SetType(BreakpointSite::eExternal); 638b9c1b51eSKate Stone } else { 63907e66e3eSGreg Clayton error.SetErrorString("KDP set breakpoint failed"); 6405b88216dSGreg Clayton } 6415b88216dSGreg Clayton } 64207e66e3eSGreg Clayton return error; 64307e66e3eSGreg Clayton } 644f9765acdSGreg Clayton return EnableSoftwareBreakpoint(bp_site); 645f9765acdSGreg Clayton } 646f9765acdSGreg Clayton 64797206d57SZachary Turner Status ProcessKDP::DisableBreakpointSite(BreakpointSite *bp_site) { 648b9c1b51eSKate Stone if (m_comm.LocalBreakpointsAreSupported()) { 64997206d57SZachary Turner Status error; 650b9c1b51eSKate Stone if (bp_site->IsEnabled()) { 6515b88216dSGreg Clayton BreakpointSite::Type bp_type = bp_site->GetType(); 652b9c1b51eSKate Stone if (bp_type == BreakpointSite::eExternal) { 653b9c1b51eSKate Stone if (m_destroy_in_process && m_comm.IsRunning()) { 65497d5cf05SGreg Clayton // We are trying to destroy our connection and we are running 65597d5cf05SGreg Clayton bp_site->SetEnabled(false); 656b9c1b51eSKate Stone } else { 6575b88216dSGreg Clayton if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress())) 6585b88216dSGreg Clayton bp_site->SetEnabled(false); 6595b88216dSGreg Clayton else 66007e66e3eSGreg Clayton error.SetErrorString("KDP remove breakpoint failed"); 6615b88216dSGreg Clayton } 662b9c1b51eSKate Stone } else { 6635b88216dSGreg Clayton error = DisableSoftwareBreakpoint(bp_site); 6645b88216dSGreg Clayton } 6655b88216dSGreg Clayton } 66607e66e3eSGreg Clayton return error; 66707e66e3eSGreg Clayton } 668f9765acdSGreg Clayton return DisableSoftwareBreakpoint(bp_site); 669f9765acdSGreg Clayton } 670f9765acdSGreg Clayton 67197206d57SZachary Turner Status ProcessKDP::EnableWatchpoint(Watchpoint *wp, bool notify) { 67297206d57SZachary Turner Status error; 673b9c1b51eSKate Stone error.SetErrorString( 6744ebdee0aSBruce Mitchener "watchpoints are not supported in kdp remote debugging"); 675f9765acdSGreg Clayton return error; 676f9765acdSGreg Clayton } 677f9765acdSGreg Clayton 67897206d57SZachary Turner Status ProcessKDP::DisableWatchpoint(Watchpoint *wp, bool notify) { 67997206d57SZachary Turner Status error; 680b9c1b51eSKate Stone error.SetErrorString( 6814ebdee0aSBruce Mitchener "watchpoints are not supported in kdp remote debugging"); 682f9765acdSGreg Clayton return error; 683f9765acdSGreg Clayton } 684f9765acdSGreg Clayton 685b9c1b51eSKate Stone void ProcessKDP::Clear() { m_thread_list.Clear(); } 686f9765acdSGreg Clayton 68797206d57SZachary Turner Status ProcessKDP::DoSignal(int signo) { 68897206d57SZachary Turner Status error; 689b9c1b51eSKate Stone error.SetErrorString( 6904ebdee0aSBruce Mitchener "sending signals is not supported in kdp remote debugging"); 691f9765acdSGreg Clayton return error; 692f9765acdSGreg Clayton } 693f9765acdSGreg Clayton 694b9c1b51eSKate Stone void ProcessKDP::Initialize() { 695c5f28e2aSKamil Rytarowski static llvm::once_flag g_once_flag; 696f9765acdSGreg Clayton 697c5f28e2aSKamil Rytarowski llvm::call_once(g_once_flag, []() { 698f9765acdSGreg Clayton PluginManager::RegisterPlugin(GetPluginNameStatic(), 699b9c1b51eSKate Stone GetPluginDescriptionStatic(), CreateInstance, 700488c89edSBruce Mitchener DebuggerInitialize); 701f9765acdSGreg Clayton 7027b35b781SPavel Labath ProcessKDPLog::Initialize(); 703c8d69828SDavide Italiano }); 704f9765acdSGreg Clayton } 705f9765acdSGreg Clayton 706b9c1b51eSKate Stone void ProcessKDP::DebuggerInitialize(lldb_private::Debugger &debugger) { 707b9c1b51eSKate Stone if (!PluginManager::GetSettingForProcessPlugin( 708b9c1b51eSKate Stone debugger, PluginProperties::GetSettingName())) { 7097f98240dSGreg Clayton const bool is_global_setting = true; 710b9c1b51eSKate Stone PluginManager::CreateSettingForProcessPlugin( 7113d7161e3SPavel Labath debugger, GetGlobalPluginProperties().GetValueProperties(), 7127f98240dSGreg Clayton ConstString("Properties for the kdp-remote process plug-in."), 7137f98240dSGreg Clayton is_global_setting); 7147f98240dSGreg Clayton } 7157f98240dSGreg Clayton } 7167f98240dSGreg Clayton 717b9c1b51eSKate Stone bool ProcessKDP::StartAsyncThread() { 718*c8fbf803SPavel Labath Log *log = GetLog(KDPLog::Process); 719f9765acdSGreg Clayton 72063e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::StartAsyncThread ()"); 721f9765acdSGreg Clayton 722acee96aeSZachary Turner if (m_async_thread.IsJoinable()) 7237925fbbaSGreg Clayton return true; 7247925fbbaSGreg Clayton 725f39c2e18SJonas Devlieghere llvm::Expected<HostThread> async_thread = ThreadLauncher::LaunchThread( 726f39c2e18SJonas Devlieghere "<lldb.process.kdp-remote.async>", ProcessKDP::AsyncThread, this); 727f39c2e18SJonas Devlieghere if (!async_thread) { 728*c8fbf803SPavel Labath LLDB_LOG_ERROR(GetLog(LLDBLog::Host), async_thread.takeError(), 729*c8fbf803SPavel Labath "failed to launch host thread: {}"); 730f39c2e18SJonas Devlieghere return false; 731f39c2e18SJonas Devlieghere } 732f39c2e18SJonas Devlieghere m_async_thread = *async_thread; 733acee96aeSZachary Turner return m_async_thread.IsJoinable(); 734f9765acdSGreg Clayton } 735f9765acdSGreg Clayton 736b9c1b51eSKate Stone void ProcessKDP::StopAsyncThread() { 737*c8fbf803SPavel Labath Log *log = GetLog(KDPLog::Process); 738f9765acdSGreg Clayton 73963e5fb76SJonas Devlieghere LLDB_LOGF(log, "ProcessKDP::StopAsyncThread ()"); 740f9765acdSGreg Clayton 741f9765acdSGreg Clayton m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit); 742f9765acdSGreg Clayton 743f9765acdSGreg Clayton // Stop the stdio thread 744acee96aeSZachary Turner if (m_async_thread.IsJoinable()) 74539de3110SZachary Turner m_async_thread.Join(nullptr); 746f9765acdSGreg Clayton } 747f9765acdSGreg Clayton 748b9c1b51eSKate Stone void *ProcessKDP::AsyncThread(void *arg) { 749f9765acdSGreg Clayton ProcessKDP *process = (ProcessKDP *)arg; 750f9765acdSGreg Clayton 7517925fbbaSGreg Clayton const lldb::pid_t pid = process->GetID(); 7527925fbbaSGreg Clayton 753*c8fbf803SPavel Labath Log *log = GetLog(KDPLog::Process); 75463e5fb76SJonas Devlieghere LLDB_LOGF(log, 75563e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 756b9c1b51eSKate Stone ") thread starting...", 757b9c1b51eSKate Stone arg, pid); 758f9765acdSGreg Clayton 759583bbb1dSJim Ingham ListenerSP listener_sp(Listener::MakeListener("ProcessKDP::AsyncThread")); 760f9765acdSGreg Clayton EventSP event_sp; 761b9c1b51eSKate Stone const uint32_t desired_event_mask = 762b9c1b51eSKate Stone eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit; 763f9765acdSGreg Clayton 764b9c1b51eSKate Stone if (listener_sp->StartListeningForEvents(&process->m_async_broadcaster, 765b9c1b51eSKate Stone desired_event_mask) == 766b9c1b51eSKate Stone desired_event_mask) { 767f9765acdSGreg Clayton bool done = false; 768b9c1b51eSKate Stone while (!done) { 76963e5fb76SJonas Devlieghere LLDB_LOGF(log, 77063e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 771b9c1b51eSKate Stone ") listener.WaitForEvent (NULL, event_sp)...", 7727925fbbaSGreg Clayton pid); 773fafff0c5SPavel Labath if (listener_sp->GetEvent(event_sp, llvm::None)) { 7747925fbbaSGreg Clayton uint32_t event_type = event_sp->GetType(); 77563e5fb76SJonas Devlieghere LLDB_LOGF(log, 77663e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 777b9c1b51eSKate Stone ") Got an event of type: %d...", 778b9c1b51eSKate Stone pid, event_type); 779f9765acdSGreg Clayton 7807925fbbaSGreg Clayton // When we are running, poll for 1 second to try and get an exception 7817925fbbaSGreg Clayton // to indicate the process has stopped. If we don't get one, check to 7827925fbbaSGreg Clayton // make sure no one asked us to exit 7837925fbbaSGreg Clayton bool is_running = false; 7847925fbbaSGreg Clayton DataExtractor exc_reply_packet; 785b9c1b51eSKate Stone do { 786b9c1b51eSKate Stone switch (event_type) { 787b9c1b51eSKate Stone case eBroadcastBitAsyncContinue: { 7887925fbbaSGreg Clayton is_running = true; 789b9c1b51eSKate Stone if (process->m_comm.WaitForPacketWithTimeoutMicroSeconds( 790b9c1b51eSKate Stone exc_reply_packet, 1 * USEC_PER_SEC)) { 791ba4e61d3SAndrew Kaylor ThreadSP thread_sp(process->GetKernelThread()); 792b9c1b51eSKate Stone if (thread_sp) { 793b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 794b9c1b51eSKate Stone thread_sp->GetRegisterContext()); 7951afa68edSGreg Clayton if (reg_ctx_sp) 7961afa68edSGreg Clayton reg_ctx_sp->InvalidateAllRegisters(); 797b9c1b51eSKate Stone static_cast<ThreadKDP *>(thread_sp.get()) 798b9c1b51eSKate Stone ->SetStopInfoFrom_KDP_EXCEPTION(exc_reply_packet); 7991afa68edSGreg Clayton } 80097d5cf05SGreg Clayton 8017925fbbaSGreg Clayton // TODO: parse the stop reply packet 8027925fbbaSGreg Clayton is_running = false; 8037925fbbaSGreg Clayton process->SetPrivateState(eStateStopped); 804b9c1b51eSKate Stone } else { 8057925fbbaSGreg Clayton // Check to see if we are supposed to exit. There is no way to 8067925fbbaSGreg Clayton // interrupt a running kernel, so all we can do is wait for an 8077925fbbaSGreg Clayton // exception or detach... 808fafff0c5SPavel Labath if (listener_sp->GetEvent(event_sp, 809fafff0c5SPavel Labath std::chrono::microseconds(0))) { 8107925fbbaSGreg Clayton // We got an event, go through the loop again 8117925fbbaSGreg Clayton event_type = event_sp->GetType(); 8127925fbbaSGreg Clayton } 813f9765acdSGreg Clayton } 814b9c1b51eSKate Stone } break; 815f9765acdSGreg Clayton 816f9765acdSGreg Clayton case eBroadcastBitAsyncThreadShouldExit: 81763e5fb76SJonas Devlieghere LLDB_LOGF(log, 81863e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 819b9c1b51eSKate Stone ") got eBroadcastBitAsyncThreadShouldExit...", 8207925fbbaSGreg Clayton pid); 821f9765acdSGreg Clayton done = true; 8227925fbbaSGreg Clayton is_running = false; 823f9765acdSGreg Clayton break; 824f9765acdSGreg Clayton 825f9765acdSGreg Clayton default: 82663e5fb76SJonas Devlieghere LLDB_LOGF(log, 82763e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 828b9c1b51eSKate Stone ") got unknown event 0x%8.8x", 829b9c1b51eSKate Stone pid, event_type); 830f9765acdSGreg Clayton done = true; 8317925fbbaSGreg Clayton is_running = false; 832f9765acdSGreg Clayton break; 833f9765acdSGreg Clayton } 8347925fbbaSGreg Clayton } while (is_running); 835b9c1b51eSKate Stone } else { 83663e5fb76SJonas Devlieghere LLDB_LOGF(log, 83763e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (pid = %" PRIu64 838b9c1b51eSKate Stone ") listener.WaitForEvent (NULL, event_sp) => false", 8397925fbbaSGreg Clayton pid); 840f9765acdSGreg Clayton done = true; 841f9765acdSGreg Clayton } 842f9765acdSGreg Clayton } 843f9765acdSGreg Clayton } 844f9765acdSGreg Clayton 84563e5fb76SJonas Devlieghere LLDB_LOGF(log, 84663e5fb76SJonas Devlieghere "ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 847b9c1b51eSKate Stone ") thread exiting...", 848b9c1b51eSKate Stone arg, pid); 849f9765acdSGreg Clayton 85039de3110SZachary Turner process->m_async_thread.Reset(); 851f9765acdSGreg Clayton return NULL; 852f9765acdSGreg Clayton } 853f9765acdSGreg Clayton 854b9c1b51eSKate Stone class CommandObjectProcessKDPPacketSend : public CommandObjectParsed { 8551d19a2f2SGreg Clayton private: 8561d19a2f2SGreg Clayton OptionGroupOptions m_option_group; 8571d19a2f2SGreg Clayton OptionGroupUInt64 m_command_byte; 8581d19a2f2SGreg Clayton OptionGroupString m_packet_data; 8591d19a2f2SGreg Clayton 86044b43a52SLogan Smith Options *GetOptions() override { return &m_option_group; } 8611d19a2f2SGreg Clayton 8621d19a2f2SGreg Clayton public: 863b9c1b51eSKate Stone CommandObjectProcessKDPPacketSend(CommandInterpreter &interpreter) 864b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "process plugin packet send", 865b9c1b51eSKate Stone "Send a custom packet through the KDP protocol by " 866b9c1b51eSKate Stone "specifying the command byte and the packet " 867b9c1b51eSKate Stone "payload data. A packet will be sent with a " 868b9c1b51eSKate Stone "correct header and payload, and the raw result " 869b9c1b51eSKate Stone "bytes will be displayed as a string value. ", 8701d19a2f2SGreg Clayton NULL), 871e1cfbc79STodd Fiala m_option_group(), 872b9c1b51eSKate Stone m_command_byte(LLDB_OPT_SET_1, true, "command", 'c', 0, eArgTypeNone, 873b9c1b51eSKate Stone "Specify the command byte to use when sending the KDP " 874b9c1b51eSKate Stone "request packet.", 875b9c1b51eSKate Stone 0), 876b9c1b51eSKate Stone m_packet_data(LLDB_OPT_SET_1, false, "payload", 'p', 0, eArgTypeNone, 877b9c1b51eSKate Stone "Specify packet payload bytes as a hex ASCII string with " 878b9c1b51eSKate Stone "no spaces or hex prefixes.", 879b9c1b51eSKate Stone NULL) { 8801d19a2f2SGreg Clayton m_option_group.Append(&m_command_byte, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 8811d19a2f2SGreg Clayton m_option_group.Append(&m_packet_data, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 8821d19a2f2SGreg Clayton m_option_group.Finalize(); 8831d19a2f2SGreg Clayton } 8841d19a2f2SGreg Clayton 885fd2433e1SJonas Devlieghere ~CommandObjectProcessKDPPacketSend() = default; 8861d19a2f2SGreg Clayton 88744b43a52SLogan Smith bool DoExecute(Args &command, CommandReturnObject &result) override { 8881d19a2f2SGreg Clayton const size_t argc = command.GetArgumentCount(); 889b9c1b51eSKate Stone if (argc == 0) { 890b9c1b51eSKate Stone if (!m_command_byte.GetOptionValue().OptionWasSet()) { 891b9c1b51eSKate Stone result.AppendError( 892b9c1b51eSKate Stone "the --command option must be set to a valid command byte"); 893b9c1b51eSKate Stone } else { 894b9c1b51eSKate Stone const uint64_t command_byte = 895b9c1b51eSKate Stone m_command_byte.GetOptionValue().GetUInt64Value(0); 896b9c1b51eSKate Stone if (command_byte > 0 && command_byte <= UINT8_MAX) { 897b9c1b51eSKate Stone ProcessKDP *process = 898b9c1b51eSKate Stone (ProcessKDP *)m_interpreter.GetExecutionContext().GetProcessPtr(); 899b9c1b51eSKate Stone if (process) { 9001d19a2f2SGreg Clayton const StateType state = process->GetState(); 9011d19a2f2SGreg Clayton 902b9c1b51eSKate Stone if (StateIsStoppedState(state, true)) { 9031d19a2f2SGreg Clayton std::vector<uint8_t> payload_bytes; 904b9c1b51eSKate Stone const char *ascii_hex_bytes_cstr = 905b9c1b51eSKate Stone m_packet_data.GetOptionValue().GetCurrentValue(); 906b9c1b51eSKate Stone if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0]) { 9071d19a2f2SGreg Clayton StringExtractor extractor(ascii_hex_bytes_cstr); 908b9c1b51eSKate Stone const size_t ascii_hex_bytes_cstr_len = 909b9c1b51eSKate Stone extractor.GetStringRef().size(); 910b9c1b51eSKate Stone if (ascii_hex_bytes_cstr_len & 1) { 911b9c1b51eSKate Stone result.AppendErrorWithFormat("payload data must contain an " 912b9c1b51eSKate Stone "even number of ASCII hex " 913b9c1b51eSKate Stone "characters: '%s'", 914b9c1b51eSKate Stone ascii_hex_bytes_cstr); 9151d19a2f2SGreg Clayton return false; 9161d19a2f2SGreg Clayton } 9171d19a2f2SGreg Clayton payload_bytes.resize(ascii_hex_bytes_cstr_len / 2); 918b9c1b51eSKate Stone if (extractor.GetHexBytes(payload_bytes, '\xdd') != 919b9c1b51eSKate Stone payload_bytes.size()) { 920b9c1b51eSKate Stone result.AppendErrorWithFormat("payload data must only contain " 921b9c1b51eSKate Stone "ASCII hex characters (no " 922b9c1b51eSKate Stone "spaces or hex prefixes): '%s'", 923b9c1b51eSKate Stone ascii_hex_bytes_cstr); 9241d19a2f2SGreg Clayton return false; 9251d19a2f2SGreg Clayton } 9261d19a2f2SGreg Clayton } 92797206d57SZachary Turner Status error; 9281d19a2f2SGreg Clayton DataExtractor reply; 929b9c1b51eSKate Stone process->GetCommunication().SendRawRequest( 930b9c1b51eSKate Stone command_byte, 9311d19a2f2SGreg Clayton payload_bytes.empty() ? NULL : payload_bytes.data(), 932b9c1b51eSKate Stone payload_bytes.size(), reply, error); 9331d19a2f2SGreg Clayton 934b9c1b51eSKate Stone if (error.Success()) { 9351d19a2f2SGreg Clayton // Copy the binary bytes into a hex ASCII string for the result 9361d19a2f2SGreg Clayton StreamString packet; 937b9c1b51eSKate Stone packet.PutBytesAsRawHex8( 938b9c1b51eSKate Stone reply.GetDataStart(), reply.GetByteSize(), 939b9c1b51eSKate Stone endian::InlHostByteOrder(), endian::InlHostByteOrder()); 940c156427dSZachary Turner result.AppendMessage(packet.GetString()); 9411d19a2f2SGreg Clayton result.SetStatus(eReturnStatusSuccessFinishResult); 9421d19a2f2SGreg Clayton return true; 943b9c1b51eSKate Stone } else { 9441d19a2f2SGreg Clayton const char *error_cstr = error.AsCString(); 9451d19a2f2SGreg Clayton if (error_cstr && error_cstr[0]) 9461d19a2f2SGreg Clayton result.AppendError(error_cstr); 9471d19a2f2SGreg Clayton else 948b9c1b51eSKate Stone result.AppendErrorWithFormat("unknown error 0x%8.8x", 949b9c1b51eSKate Stone error.GetError()); 9501d19a2f2SGreg Clayton return false; 9511d19a2f2SGreg Clayton } 952b9c1b51eSKate Stone } else { 953b9c1b51eSKate Stone result.AppendErrorWithFormat("process must be stopped in order " 954b9c1b51eSKate Stone "to send KDP packets, state is %s", 955b9c1b51eSKate Stone StateAsCString(state)); 9561d19a2f2SGreg Clayton } 957b9c1b51eSKate Stone } else { 9581d19a2f2SGreg Clayton result.AppendError("invalid process"); 9591d19a2f2SGreg Clayton } 960b9c1b51eSKate Stone } else { 961b9c1b51eSKate Stone result.AppendErrorWithFormat("invalid command byte 0x%" PRIx64 962b9c1b51eSKate Stone ", valid values are 1 - 255", 963b9c1b51eSKate Stone command_byte); 9641d19a2f2SGreg Clayton } 9651d19a2f2SGreg Clayton } 966b9c1b51eSKate Stone } else { 967b9c1b51eSKate Stone result.AppendErrorWithFormat("'%s' takes no arguments, only options.", 968b9c1b51eSKate Stone m_cmd_name.c_str()); 9691d19a2f2SGreg Clayton } 9701d19a2f2SGreg Clayton return false; 9711d19a2f2SGreg Clayton } 9721d19a2f2SGreg Clayton }; 9731d19a2f2SGreg Clayton 974b9c1b51eSKate Stone class CommandObjectProcessKDPPacket : public CommandObjectMultiword { 9751d19a2f2SGreg Clayton private: 9761d19a2f2SGreg Clayton public: 977b9c1b51eSKate Stone CommandObjectProcessKDPPacket(CommandInterpreter &interpreter) 978b9c1b51eSKate Stone : CommandObjectMultiword(interpreter, "process plugin packet", 9791d19a2f2SGreg Clayton "Commands that deal with KDP remote packets.", 980b9c1b51eSKate Stone NULL) { 981b9c1b51eSKate Stone LoadSubCommand( 982b9c1b51eSKate Stone "send", 983b9c1b51eSKate Stone CommandObjectSP(new CommandObjectProcessKDPPacketSend(interpreter))); 9841d19a2f2SGreg Clayton } 9851d19a2f2SGreg Clayton 986fd2433e1SJonas Devlieghere ~CommandObjectProcessKDPPacket() = default; 9871d19a2f2SGreg Clayton }; 9881d19a2f2SGreg Clayton 989b9c1b51eSKate Stone class CommandObjectMultiwordProcessKDP : public CommandObjectMultiword { 9901d19a2f2SGreg Clayton public: 9917428a18cSKate Stone CommandObjectMultiwordProcessKDP(CommandInterpreter &interpreter) 992b9c1b51eSKate Stone : CommandObjectMultiword( 993b9c1b51eSKate Stone interpreter, "process plugin", 994b9c1b51eSKate Stone "Commands for operating on a ProcessKDP process.", 995b9c1b51eSKate Stone "process plugin <subcommand> [<subcommand-options>]") { 996b9c1b51eSKate Stone LoadSubCommand("packet", CommandObjectSP(new CommandObjectProcessKDPPacket( 997b9c1b51eSKate Stone interpreter))); 9981d19a2f2SGreg Clayton } 9991d19a2f2SGreg Clayton 1000fd2433e1SJonas Devlieghere ~CommandObjectMultiwordProcessKDP() = default; 10011d19a2f2SGreg Clayton }; 10021d19a2f2SGreg Clayton 1003b9c1b51eSKate Stone CommandObject *ProcessKDP::GetPluginCommandObject() { 10041d19a2f2SGreg Clayton if (!m_command_sp) 1005796ac80bSJonas Devlieghere m_command_sp = std::make_shared<CommandObjectMultiwordProcessKDP>( 1006796ac80bSJonas Devlieghere GetTarget().GetDebugger().GetCommandInterpreter()); 10071d19a2f2SGreg Clayton return m_command_sp.get(); 10081d19a2f2SGreg Clayton } 1009