159ec512cSGreg Clayton //===-- ProcessKDP.cpp ------------------------------------------*- C++ -*-===// 2f9765acdSGreg Clayton // 3f9765acdSGreg Clayton // The LLVM Compiler Infrastructure 4f9765acdSGreg Clayton // 5f9765acdSGreg Clayton // This file is distributed under the University of Illinois Open Source 6f9765acdSGreg Clayton // License. See LICENSE.TXT for details. 7f9765acdSGreg Clayton // 8f9765acdSGreg Clayton //===----------------------------------------------------------------------===// 9f9765acdSGreg Clayton 10f9765acdSGreg Clayton // C Includes 11f9765acdSGreg Clayton #include <errno.h> 12f9765acdSGreg Clayton #include <stdlib.h> 13f9765acdSGreg Clayton 14f9765acdSGreg Clayton // C++ Includes 153f69fa6fSBenjamin Kramer #include <mutex> 163f69fa6fSBenjamin Kramer 17f9765acdSGreg Clayton // Other libraries and framework includes 1807e66e3eSGreg Clayton #include "lldb/Core/Debugger.h" 191f746071SGreg Clayton #include "lldb/Core/Module.h" 204bd4e7e3SJason Molenda #include "lldb/Core/ModuleSpec.h" 21b9c1b51eSKate Stone #include "lldb/Core/PluginManager.h" 22f9765acdSGreg Clayton #include "lldb/Core/State.h" 234bd4e7e3SJason Molenda #include "lldb/Core/UUID.h" 2493a66fc1SZachary Turner #include "lldb/Host/ConnectionFileDescriptor.h" 25f9765acdSGreg Clayton #include "lldb/Host/Host.h" 264bd4e7e3SJason Molenda #include "lldb/Host/Symbols.h" 2739de3110SZachary Turner #include "lldb/Host/ThreadLauncher.h" 28e98628ceSOleksiy Vyalov #include "lldb/Host/common/TCPSocket.h" 291d19a2f2SGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 301d19a2f2SGreg Clayton #include "lldb/Interpreter/CommandObject.h" 311d19a2f2SGreg Clayton #include "lldb/Interpreter/CommandObjectMultiword.h" 321d19a2f2SGreg Clayton #include "lldb/Interpreter/CommandReturnObject.h" 331d19a2f2SGreg Clayton #include "lldb/Interpreter/OptionGroupString.h" 341d19a2f2SGreg Clayton #include "lldb/Interpreter/OptionGroupUInt64.h" 3541204d09SIlia K #include "lldb/Interpreter/OptionValueProperties.h" 361f746071SGreg Clayton #include "lldb/Symbol/ObjectFile.h" 377925fbbaSGreg Clayton #include "lldb/Target/RegisterContext.h" 3857508026SGreg Clayton #include "lldb/Target/Target.h" 39a63d08c9SGreg Clayton #include "lldb/Target/Thread.h" 4045788152SBruce Mitchener #include "lldb/Utility/StringExtractor.h" 41f9765acdSGreg Clayton 42510938e5SCharles Davis #define USEC_PER_SEC 1000000 43510938e5SCharles Davis 44f9765acdSGreg Clayton // Project includes 45b9c1b51eSKate Stone #include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h" 46b9c1b51eSKate Stone #include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h" 47f9765acdSGreg Clayton #include "ProcessKDP.h" 48f9765acdSGreg Clayton #include "ProcessKDPLog.h" 49a63d08c9SGreg Clayton #include "ThreadKDP.h" 50f9765acdSGreg Clayton 51f9765acdSGreg Clayton using namespace lldb; 52f9765acdSGreg Clayton using namespace lldb_private; 53f9765acdSGreg Clayton 547f98240dSGreg Clayton namespace { 557f98240dSGreg Clayton 56b9c1b51eSKate Stone static PropertyDefinition g_properties[] = { 57b9c1b51eSKate Stone {"packet-timeout", OptionValue::eTypeUInt64, true, 5, NULL, NULL, 58b9c1b51eSKate Stone "Specify the default packet timeout in seconds."}, 59b9c1b51eSKate Stone {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}}; 607f98240dSGreg Clayton 61b9c1b51eSKate Stone enum { ePropertyPacketTimeout }; 627f98240dSGreg Clayton 63b9c1b51eSKate Stone class PluginProperties : public Properties { 647f98240dSGreg Clayton public: 65b9c1b51eSKate Stone static ConstString GetSettingName() { 667f98240dSGreg Clayton return ProcessKDP::GetPluginNameStatic(); 677f98240dSGreg Clayton } 687f98240dSGreg Clayton 69b9c1b51eSKate Stone PluginProperties() : Properties() { 707f98240dSGreg Clayton m_collection_sp.reset(new OptionValueProperties(GetSettingName())); 717f98240dSGreg Clayton m_collection_sp->Initialize(g_properties); 727f98240dSGreg Clayton } 737f98240dSGreg Clayton 74b9c1b51eSKate Stone virtual ~PluginProperties() {} 757f98240dSGreg Clayton 76b9c1b51eSKate Stone uint64_t GetPacketTimeout() { 777f98240dSGreg Clayton const uint32_t idx = ePropertyPacketTimeout; 78b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsUInt64( 79b9c1b51eSKate Stone NULL, idx, g_properties[idx].default_uint_value); 807f98240dSGreg Clayton } 817f98240dSGreg Clayton }; 827f98240dSGreg Clayton 837f98240dSGreg Clayton typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP; 847f98240dSGreg Clayton 85b9c1b51eSKate Stone static const ProcessKDPPropertiesSP &GetGlobalPluginProperties() { 867f98240dSGreg Clayton static ProcessKDPPropertiesSP g_settings_sp; 877f98240dSGreg Clayton if (!g_settings_sp) 887f98240dSGreg Clayton g_settings_sp.reset(new PluginProperties()); 897f98240dSGreg Clayton return g_settings_sp; 907f98240dSGreg Clayton } 917f98240dSGreg Clayton 927f98240dSGreg Clayton } // anonymous namespace end 937f98240dSGreg Clayton 94ba4e61d3SAndrew Kaylor static const lldb::tid_t g_kernel_tid = 1; 95ba4e61d3SAndrew Kaylor 96b9c1b51eSKate Stone ConstString ProcessKDP::GetPluginNameStatic() { 9757abc5d6SGreg Clayton static ConstString g_name("kdp-remote"); 9857abc5d6SGreg Clayton return g_name; 99f9765acdSGreg Clayton } 100f9765acdSGreg Clayton 101b9c1b51eSKate Stone const char *ProcessKDP::GetPluginDescriptionStatic() { 102b9c1b51eSKate Stone return "KDP Remote protocol based debugging plug-in for darwin kernel " 103b9c1b51eSKate Stone "debugging."; 104f9765acdSGreg Clayton } 105f9765acdSGreg Clayton 106b9c1b51eSKate Stone void ProcessKDP::Terminate() { 107f9765acdSGreg Clayton PluginManager::UnregisterPlugin(ProcessKDP::CreateInstance); 108f9765acdSGreg Clayton } 109f9765acdSGreg Clayton 110b9c1b51eSKate Stone lldb::ProcessSP ProcessKDP::CreateInstance(TargetSP target_sp, 111583bbb1dSJim Ingham ListenerSP listener_sp, 112b9c1b51eSKate Stone const FileSpec *crash_file_path) { 113c3776bf2SGreg Clayton lldb::ProcessSP process_sp; 114c3776bf2SGreg Clayton if (crash_file_path == NULL) 115583bbb1dSJim Ingham process_sp.reset(new ProcessKDP(target_sp, listener_sp)); 116c3776bf2SGreg Clayton return process_sp; 117f9765acdSGreg Clayton } 118f9765acdSGreg Clayton 119b9c1b51eSKate Stone bool ProcessKDP::CanDebug(TargetSP target_sp, bool plugin_specified_by_name) { 120596ed24eSGreg Clayton if (plugin_specified_by_name) 121596ed24eSGreg Clayton return true; 122596ed24eSGreg Clayton 123f9765acdSGreg Clayton // For now we are just making sure the file exists for a given module 1245a3bb64fSJim Ingham Module *exe_module = target_sp->GetExecutableModulePointer(); 125b9c1b51eSKate Stone if (exe_module) { 1265a3bb64fSJim Ingham const llvm::Triple &triple_ref = target_sp->GetArchitecture().GetTriple(); 127b9c1b51eSKate Stone switch (triple_ref.getOS()) { 128b9c1b51eSKate Stone case llvm::Triple::Darwin: // Should use "macosx" for desktop and "ios" for 129b9c1b51eSKate Stone // iOS, but accept darwin just in case 13070512317SGreg Clayton case llvm::Triple::MacOSX: // For desktop targets 13170512317SGreg Clayton case llvm::Triple::IOS: // For arm targets 132a814f704SJason Molenda case llvm::Triple::TvOS: 133a814f704SJason Molenda case llvm::Triple::WatchOS: 134b9c1b51eSKate Stone if (triple_ref.getVendor() == llvm::Triple::Apple) { 135aa149cbdSGreg Clayton ObjectFile *exe_objfile = exe_module->GetObjectFile(); 136f9765acdSGreg Clayton if (exe_objfile->GetType() == ObjectFile::eTypeExecutable && 137f9765acdSGreg Clayton exe_objfile->GetStrata() == ObjectFile::eStrataKernel) 138f9765acdSGreg Clayton return true; 139f9765acdSGreg Clayton } 14070512317SGreg Clayton break; 14170512317SGreg Clayton 14270512317SGreg Clayton default: 14370512317SGreg Clayton break; 14470512317SGreg Clayton } 145f9765acdSGreg Clayton } 146596ed24eSGreg Clayton return false; 1473a29bdbeSGreg Clayton } 148f9765acdSGreg Clayton 149f9765acdSGreg Clayton //---------------------------------------------------------------------- 150f9765acdSGreg Clayton // ProcessKDP constructor 151f9765acdSGreg Clayton //---------------------------------------------------------------------- 152b9c1b51eSKate Stone ProcessKDP::ProcessKDP(TargetSP target_sp, ListenerSP listener_sp) 153b9c1b51eSKate Stone : Process(target_sp, listener_sp), 154f9765acdSGreg Clayton m_comm("lldb.process.kdp-remote.communication"), 1554bddaeb5SJim Ingham m_async_broadcaster(NULL, "lldb.process.kdp-remote.async-broadcaster"), 156b9c1b51eSKate Stone m_dyld_plugin_name(), m_kernel_load_addr(LLDB_INVALID_ADDRESS), 157b9c1b51eSKate Stone m_command_sp(), m_kernel_thread_wp() { 158b9c1b51eSKate Stone m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, 159b9c1b51eSKate Stone "async thread should exit"); 160b9c1b51eSKate Stone m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, 161b9c1b51eSKate Stone "async thread continue"); 162b9c1b51eSKate Stone const uint64_t timeout_seconds = 163b9c1b51eSKate Stone GetGlobalPluginProperties()->GetPacketTimeout(); 1647f98240dSGreg Clayton if (timeout_seconds > 0) 1655cddd608SPavel Labath m_comm.SetPacketTimeout(std::chrono::seconds(timeout_seconds)); 166f9765acdSGreg Clayton } 167f9765acdSGreg Clayton 168f9765acdSGreg Clayton //---------------------------------------------------------------------- 169f9765acdSGreg Clayton // Destructor 170f9765acdSGreg Clayton //---------------------------------------------------------------------- 171b9c1b51eSKate Stone ProcessKDP::~ProcessKDP() { 172f9765acdSGreg Clayton Clear(); 173e24c4acfSGreg Clayton // We need to call finalize on the process before destroying ourselves 174e24c4acfSGreg Clayton // to make sure all of the broadcaster cleanup goes as planned. If we 175e24c4acfSGreg Clayton // destruct this class, then Process::~Process() might have problems 176e24c4acfSGreg Clayton // trying to fully destroy the broadcaster. 177e24c4acfSGreg Clayton Finalize(); 178f9765acdSGreg Clayton } 179f9765acdSGreg Clayton 180f9765acdSGreg Clayton //---------------------------------------------------------------------- 181f9765acdSGreg Clayton // PluginInterface 182f9765acdSGreg Clayton //---------------------------------------------------------------------- 183b9c1b51eSKate Stone lldb_private::ConstString ProcessKDP::GetPluginName() { 184f9765acdSGreg Clayton return GetPluginNameStatic(); 185f9765acdSGreg Clayton } 186f9765acdSGreg Clayton 187b9c1b51eSKate Stone uint32_t ProcessKDP::GetPluginVersion() { return 1; } 188f9765acdSGreg Clayton 189b9c1b51eSKate Stone Error ProcessKDP::WillLaunch(Module *module) { 190f9765acdSGreg Clayton Error error; 191f9765acdSGreg Clayton error.SetErrorString("launching not supported in kdp-remote plug-in"); 192f9765acdSGreg Clayton return error; 193f9765acdSGreg Clayton } 194f9765acdSGreg Clayton 195b9c1b51eSKate Stone Error ProcessKDP::WillAttachToProcessWithID(lldb::pid_t pid) { 196f9765acdSGreg Clayton Error error; 197b9c1b51eSKate Stone error.SetErrorString( 198b9c1b51eSKate Stone "attaching to a by process ID not supported in kdp-remote plug-in"); 199f9765acdSGreg Clayton return error; 200f9765acdSGreg Clayton } 201f9765acdSGreg Clayton 202b9c1b51eSKate Stone Error ProcessKDP::WillAttachToProcessWithName(const char *process_name, 203b9c1b51eSKate Stone bool wait_for_launch) { 204f9765acdSGreg Clayton Error error; 205b9c1b51eSKate Stone error.SetErrorString( 206b9c1b51eSKate Stone "attaching to a by process name not supported in kdp-remote plug-in"); 207f9765acdSGreg Clayton return error; 208f9765acdSGreg Clayton } 209f9765acdSGreg Clayton 210b9c1b51eSKate Stone bool ProcessKDP::GetHostArchitecture(ArchSpec &arch) { 211a3706888SGreg Clayton uint32_t cpu = m_comm.GetCPUType(); 212b9c1b51eSKate Stone if (cpu) { 213a3706888SGreg Clayton uint32_t sub = m_comm.GetCPUSubtype(); 214a3706888SGreg Clayton arch.SetArchitecture(eArchTypeMachO, cpu, sub); 215a3706888SGreg Clayton // Leave architecture vendor as unspecified unknown 216a3706888SGreg Clayton arch.GetTriple().setVendor(llvm::Triple::UnknownVendor); 217a3706888SGreg Clayton arch.GetTriple().setVendorName(llvm::StringRef()); 218a3706888SGreg Clayton return true; 219a3706888SGreg Clayton } 220a3706888SGreg Clayton arch.Clear(); 221a3706888SGreg Clayton return false; 222a3706888SGreg Clayton } 223a3706888SGreg Clayton 224b9c1b51eSKate Stone Error ProcessKDP::DoConnectRemote(Stream *strm, const char *remote_url) { 225f9765acdSGreg Clayton Error error; 2263a29bdbeSGreg Clayton 2277925fbbaSGreg Clayton // Don't let any JIT happen when doing KDP as we can't allocate 2287925fbbaSGreg Clayton // memory and we don't want to be mucking with threads that might 2297925fbbaSGreg Clayton // already be handling exceptions 2307925fbbaSGreg Clayton SetCanJIT(false); 2317925fbbaSGreg Clayton 232b9c1b51eSKate Stone if (remote_url == NULL || remote_url[0] == '\0') { 2337925fbbaSGreg Clayton error.SetErrorStringWithFormat("invalid connection URL '%s'", remote_url); 2347925fbbaSGreg Clayton return error; 2357925fbbaSGreg Clayton } 2363a29bdbeSGreg Clayton 237b9c1b51eSKate Stone std::unique_ptr<ConnectionFileDescriptor> conn_ap( 238b9c1b51eSKate Stone new ConnectionFileDescriptor()); 239b9c1b51eSKate Stone if (conn_ap.get()) { 2403a29bdbeSGreg Clayton // Only try once for now. 2413a29bdbeSGreg Clayton // TODO: check if we should be retrying? 2423a29bdbeSGreg Clayton const uint32_t max_retry_count = 1; 243b9c1b51eSKate Stone for (uint32_t retry_count = 0; retry_count < max_retry_count; 244b9c1b51eSKate Stone ++retry_count) { 2453a29bdbeSGreg Clayton if (conn_ap->Connect(remote_url, &error) == eConnectionStatusSuccess) 2463a29bdbeSGreg Clayton break; 2473a29bdbeSGreg Clayton usleep(100000); 2483a29bdbeSGreg Clayton } 2493a29bdbeSGreg Clayton } 2503a29bdbeSGreg Clayton 251b9c1b51eSKate Stone if (conn_ap->IsConnected()) { 252b9c1b51eSKate Stone const TCPSocket &socket = 253b9c1b51eSKate Stone static_cast<const TCPSocket &>(*conn_ap->GetReadObject()); 254014bb7daSVince Harron const uint16_t reply_port = socket.GetLocalPortNumber(); 2553a29bdbeSGreg Clayton 256b9c1b51eSKate Stone if (reply_port != 0) { 2573a29bdbeSGreg Clayton m_comm.SetConnection(conn_ap.release()); 2583a29bdbeSGreg Clayton 259b9c1b51eSKate Stone if (m_comm.SendRequestReattach(reply_port)) { 260b9c1b51eSKate Stone if (m_comm.SendRequestConnect(reply_port, reply_port, 261b9c1b51eSKate Stone "Greetings from LLDB...")) { 2623a29bdbeSGreg Clayton m_comm.GetVersion(); 2635a3bb64fSJim Ingham 264a3706888SGreg Clayton Target &target = GetTarget(); 265a3706888SGreg Clayton ArchSpec kernel_arch; 266a3706888SGreg Clayton // The host architecture 267a3706888SGreg Clayton GetHostArchitecture(kernel_arch); 268a3706888SGreg Clayton ArchSpec target_arch = target.GetArchitecture(); 269a3706888SGreg Clayton // Merge in any unspecified stuff into the target architecture in 270a3706888SGreg Clayton // case the target arch isn't set at all or incompletely. 271a3706888SGreg Clayton target_arch.MergeFrom(kernel_arch); 272a3706888SGreg Clayton target.SetArchitecture(target_arch); 2734bd4e7e3SJason Molenda 274b9c1b51eSKate Stone /* Get the kernel's UUID and load address via KDP_KERNELVERSION 275b9c1b51eSKate Stone * packet. */ 276840f12cfSJason Molenda /* An EFI kdp session has neither UUID nor load address. */ 2774bd4e7e3SJason Molenda 2784bd4e7e3SJason Molenda UUID kernel_uuid = m_comm.GetUUID(); 2794bd4e7e3SJason Molenda addr_t kernel_load_addr = m_comm.GetLoadAddress(); 2804bd4e7e3SJason Molenda 281b9c1b51eSKate Stone if (m_comm.RemoteIsEFI()) { 282b9c1b51eSKate Stone // Select an invalid plugin name for the dynamic loader so one 283b9c1b51eSKate Stone // doesn't get used 284a1bce2efSGreg Clayton // since EFI does its own manual loading via python scripting 285a1bce2efSGreg Clayton static ConstString g_none_dynamic_loader("none"); 286a1bce2efSGreg Clayton m_dyld_plugin_name = g_none_dynamic_loader; 287a1bce2efSGreg Clayton 288a1bce2efSGreg Clayton if (kernel_uuid.IsValid()) { 289a1bce2efSGreg Clayton // If EFI passed in a UUID= try to lookup UUID 290a1bce2efSGreg Clayton // The slide will not be provided. But the UUID 291a1bce2efSGreg Clayton // lookup will be used to launch EFI debug scripts 292a1bce2efSGreg Clayton // from the dSYM, that can load all of the symbols. 293a1bce2efSGreg Clayton ModuleSpec module_spec; 294a1bce2efSGreg Clayton module_spec.GetUUID() = kernel_uuid; 2955a3bb64fSJim Ingham module_spec.GetArchitecture() = target.GetArchitecture(); 296a1bce2efSGreg Clayton 297a1bce2efSGreg Clayton // Lookup UUID locally, before attempting dsymForUUID like action 298b9c1b51eSKate Stone module_spec.GetSymbolFileSpec() = 299b9c1b51eSKate Stone Symbols::LocateExecutableSymbolFile(module_spec); 300b9c1b51eSKate Stone if (module_spec.GetSymbolFileSpec()) { 301b9c1b51eSKate Stone ModuleSpec executable_module_spec = 302b9c1b51eSKate Stone Symbols::LocateExecutableObjectFile(module_spec); 303b9c1b51eSKate Stone if (executable_module_spec.GetFileSpec().Exists()) { 304b9c1b51eSKate Stone module_spec.GetFileSpec() = 305b9c1b51eSKate Stone executable_module_spec.GetFileSpec(); 3068825c5c9SJason Molenda } 3078825c5c9SJason Molenda } 308b9c1b51eSKate Stone if (!module_spec.GetSymbolFileSpec() || 309b9c1b51eSKate Stone !module_spec.GetSymbolFileSpec()) 310a1bce2efSGreg Clayton Symbols::DownloadObjectAndSymbolFile(module_spec, true); 311a1bce2efSGreg Clayton 312b9c1b51eSKate Stone if (module_spec.GetFileSpec().Exists()) { 313a3706888SGreg Clayton ModuleSP module_sp(new Module(module_spec)); 314b9c1b51eSKate Stone if (module_sp.get() && module_sp->GetObjectFile()) { 315a1bce2efSGreg Clayton // Get the current target executable 3165a3bb64fSJim Ingham ModuleSP exe_module_sp(target.GetExecutableModule()); 317a1bce2efSGreg Clayton 318b9c1b51eSKate Stone // Make sure you don't already have the right module loaded 319b9c1b51eSKate Stone // and they will be uniqued 320a1bce2efSGreg Clayton if (exe_module_sp.get() != module_sp.get()) 3215a3bb64fSJim Ingham target.SetExecutableModule(module_sp, false); 322a1bce2efSGreg Clayton } 323a1bce2efSGreg Clayton } 324a1bce2efSGreg Clayton } 325b9c1b51eSKate Stone } else if (m_comm.RemoteIsDarwinKernel()) { 326b9c1b51eSKate Stone m_dyld_plugin_name = 327b9c1b51eSKate Stone DynamicLoaderDarwinKernel::GetPluginNameStatic(); 328b9c1b51eSKate Stone if (kernel_load_addr != LLDB_INVALID_ADDRESS) { 3295e8534efSJason Molenda m_kernel_load_addr = kernel_load_addr; 330a8ea4baeSJason Molenda } 3314bd4e7e3SJason Molenda } 3324bd4e7e3SJason Molenda 33397d5cf05SGreg Clayton // Set the thread ID 33497d5cf05SGreg Clayton UpdateThreadListIfNeeded(); 335a63d08c9SGreg Clayton SetID(1); 33656d9a1b3SGreg Clayton GetThreadList(); 337a63d08c9SGreg Clayton SetPrivateState(eStateStopped); 3385a3bb64fSJim Ingham StreamSP async_strm_sp(target.GetDebugger().GetAsyncOutputStream()); 339b9c1b51eSKate Stone if (async_strm_sp) { 3405b88216dSGreg Clayton const char *cstr; 341b9c1b51eSKate Stone if ((cstr = m_comm.GetKernelVersion()) != NULL) { 3425b88216dSGreg Clayton async_strm_sp->Printf("Version: %s\n", cstr); 34307e66e3eSGreg Clayton async_strm_sp->Flush(); 34407e66e3eSGreg Clayton } 3455b88216dSGreg Clayton // if ((cstr = m_comm.GetImagePath ()) != NULL) 3465b88216dSGreg Clayton // { 347b9c1b51eSKate Stone // async_strm_sp->Printf ("Image Path: 348b9c1b51eSKate Stone // %s\n", cstr); 3495b88216dSGreg Clayton // async_strm_sp->Flush(); 3505b88216dSGreg Clayton // } 35107e66e3eSGreg Clayton } 352b9c1b51eSKate Stone } else { 35397d5cf05SGreg Clayton error.SetErrorString("KDP_REATTACH failed"); 35497d5cf05SGreg Clayton } 355b9c1b51eSKate Stone } else { 35697d5cf05SGreg Clayton error.SetErrorString("KDP_REATTACH failed"); 3573a29bdbeSGreg Clayton } 358b9c1b51eSKate Stone } else { 3593a29bdbeSGreg Clayton error.SetErrorString("invalid reply port from UDP connection"); 3603a29bdbeSGreg Clayton } 361b9c1b51eSKate Stone } else { 3623a29bdbeSGreg Clayton if (error.Success()) 3633a29bdbeSGreg Clayton error.SetErrorStringWithFormat("failed to connect to '%s'", remote_url); 3643a29bdbeSGreg Clayton } 3653a29bdbeSGreg Clayton if (error.Fail()) 3663a29bdbeSGreg Clayton m_comm.Disconnect(); 3673a29bdbeSGreg Clayton 368f9765acdSGreg Clayton return error; 369f9765acdSGreg Clayton } 370f9765acdSGreg Clayton 371f9765acdSGreg Clayton //---------------------------------------------------------------------- 372f9765acdSGreg Clayton // Process Control 373f9765acdSGreg Clayton //---------------------------------------------------------------------- 374b9c1b51eSKate Stone Error ProcessKDP::DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) { 375f9765acdSGreg Clayton Error error; 376f9765acdSGreg Clayton error.SetErrorString("launching not supported in kdp-remote plug-in"); 377f9765acdSGreg Clayton return error; 378f9765acdSGreg Clayton } 379f9765acdSGreg Clayton 380b9c1b51eSKate Stone Error ProcessKDP::DoAttachToProcessWithID( 381b9c1b51eSKate Stone lldb::pid_t attach_pid, const ProcessAttachInfo &attach_info) { 38284647048SHan Ming Ong Error error; 383b9c1b51eSKate Stone error.SetErrorString( 384b9c1b51eSKate Stone "attach to process by ID is not suppported in kdp remote debugging"); 38584647048SHan Ming Ong return error; 38684647048SHan Ming Ong } 38784647048SHan Ming Ong 388b9c1b51eSKate Stone Error ProcessKDP::DoAttachToProcessWithName( 389b9c1b51eSKate Stone const char *process_name, const ProcessAttachInfo &attach_info) { 390f9765acdSGreg Clayton Error error; 391b9c1b51eSKate Stone error.SetErrorString( 392b9c1b51eSKate Stone "attach to process by name is not suppported in kdp remote debugging"); 393f9765acdSGreg Clayton return error; 394f9765acdSGreg Clayton } 395f9765acdSGreg Clayton 396b9c1b51eSKate Stone void ProcessKDP::DidAttach(ArchSpec &process_arch) { 397bb006ce2SJim Ingham Process::DidAttach(process_arch); 398bb006ce2SJim Ingham 3995160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 400f9765acdSGreg Clayton if (log) 40154cb8f83SJohnny Chen log->Printf("ProcessKDP::DidAttach()"); 402b9c1b51eSKate Stone if (GetID() != LLDB_INVALID_PROCESS_ID) { 403a3706888SGreg Clayton GetHostArchitecture(process_arch); 404f9765acdSGreg Clayton } 405f9765acdSGreg Clayton } 406f9765acdSGreg Clayton 407b9c1b51eSKate Stone addr_t ProcessKDP::GetImageInfoAddress() { return m_kernel_load_addr; } 4085e8534efSJason Molenda 409b9c1b51eSKate Stone lldb_private::DynamicLoader *ProcessKDP::GetDynamicLoader() { 4105e8534efSJason Molenda if (m_dyld_ap.get() == NULL) 411b9c1b51eSKate Stone m_dyld_ap.reset(DynamicLoader::FindPlugin( 412b9c1b51eSKate Stone this, 413b9c1b51eSKate Stone m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString())); 4145e8534efSJason Molenda return m_dyld_ap.get(); 4155e8534efSJason Molenda } 4165e8534efSJason Molenda 417*c1edf566SMehdi Amini Error ProcessKDP::WillResume() { return Error(); } 418f9765acdSGreg Clayton 419b9c1b51eSKate Stone Error ProcessKDP::DoResume() { 420f9765acdSGreg Clayton Error error; 4215160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 4227925fbbaSGreg Clayton // Only start the async thread if we try to do any process control 423acee96aeSZachary Turner if (!m_async_thread.IsJoinable()) 4247925fbbaSGreg Clayton StartAsyncThread(); 4257925fbbaSGreg Clayton 42697d5cf05SGreg Clayton bool resume = false; 4277925fbbaSGreg Clayton 42897d5cf05SGreg Clayton // With KDP there is only one thread we can tell what to do 429ba4e61d3SAndrew Kaylor ThreadSP kernel_thread_sp(m_thread_list.FindThreadByProtocolID(g_kernel_tid)); 430ba4e61d3SAndrew Kaylor 431b9c1b51eSKate Stone if (kernel_thread_sp) { 432b9c1b51eSKate Stone const StateType thread_resume_state = 433b9c1b51eSKate Stone kernel_thread_sp->GetTemporaryResumeState(); 4346e0ff1a3SGreg Clayton 4356e0ff1a3SGreg Clayton if (log) 436b9c1b51eSKate Stone log->Printf("ProcessKDP::DoResume() thread_resume_state = %s", 437b9c1b51eSKate Stone StateAsCString(thread_resume_state)); 438b9c1b51eSKate Stone switch (thread_resume_state) { 4397925fbbaSGreg Clayton case eStateSuspended: 4407925fbbaSGreg Clayton // Nothing to do here when a thread will stay suspended 4417925fbbaSGreg Clayton // we just leave the CPU mask bit set to zero for the thread 4426e0ff1a3SGreg Clayton if (log) 4436e0ff1a3SGreg Clayton log->Printf("ProcessKDP::DoResume() = suspended???"); 4447925fbbaSGreg Clayton break; 4457925fbbaSGreg Clayton 446b9c1b51eSKate Stone case eStateStepping: { 447b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 448b9c1b51eSKate Stone kernel_thread_sp->GetRegisterContext()); 4491afa68edSGreg Clayton 450b9c1b51eSKate Stone if (reg_ctx_sp) { 4516e0ff1a3SGreg Clayton if (log) 452b9c1b51eSKate Stone log->Printf( 453b9c1b51eSKate Stone "ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (true);"); 4541afa68edSGreg Clayton reg_ctx_sp->HardwareSingleStep(true); 45597d5cf05SGreg Clayton resume = true; 456b9c1b51eSKate Stone } else { 457b9c1b51eSKate Stone error.SetErrorStringWithFormat( 458b9c1b51eSKate Stone "KDP thread 0x%llx has no register context", 459b9c1b51eSKate Stone kernel_thread_sp->GetID()); 4601afa68edSGreg Clayton } 461b9c1b51eSKate Stone } break; 4627925fbbaSGreg Clayton 463b9c1b51eSKate Stone case eStateRunning: { 464b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 465b9c1b51eSKate Stone kernel_thread_sp->GetRegisterContext()); 4661afa68edSGreg Clayton 467b9c1b51eSKate Stone if (reg_ctx_sp) { 4686e0ff1a3SGreg Clayton if (log) 469b9c1b51eSKate Stone log->Printf("ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep " 470b9c1b51eSKate Stone "(false);"); 4711afa68edSGreg Clayton reg_ctx_sp->HardwareSingleStep(false); 47297d5cf05SGreg Clayton resume = true; 473b9c1b51eSKate Stone } else { 474b9c1b51eSKate Stone error.SetErrorStringWithFormat( 475b9c1b51eSKate Stone "KDP thread 0x%llx has no register context", 476b9c1b51eSKate Stone kernel_thread_sp->GetID()); 4771afa68edSGreg Clayton } 478b9c1b51eSKate Stone } break; 4797925fbbaSGreg Clayton 4807925fbbaSGreg Clayton default: 48197d5cf05SGreg Clayton // The only valid thread resume states are listed above 4827925fbbaSGreg Clayton assert(!"invalid thread resume state"); 4837925fbbaSGreg Clayton break; 4844b1b8b3eSGreg Clayton } 4854b1b8b3eSGreg Clayton } 4867925fbbaSGreg Clayton 487b9c1b51eSKate Stone if (resume) { 48897d5cf05SGreg Clayton if (log) 48997d5cf05SGreg Clayton log->Printf("ProcessKDP::DoResume () sending resume"); 49097d5cf05SGreg Clayton 491b9c1b51eSKate Stone if (m_comm.SendRequestResume()) { 4927925fbbaSGreg Clayton m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue); 4937925fbbaSGreg Clayton SetPrivateState(eStateRunning); 494b9c1b51eSKate Stone } else 49507e66e3eSGreg Clayton error.SetErrorString("KDP resume failed"); 496b9c1b51eSKate Stone } else { 49797d5cf05SGreg Clayton error.SetErrorString("kernel thread is suspended"); 4987925fbbaSGreg Clayton } 4997925fbbaSGreg Clayton 500f9765acdSGreg Clayton return error; 501f9765acdSGreg Clayton } 502f9765acdSGreg Clayton 503b9c1b51eSKate Stone lldb::ThreadSP ProcessKDP::GetKernelThread() { 50497d5cf05SGreg Clayton // KDP only tells us about one thread/core. Any other threads will usually 50597d5cf05SGreg Clayton // be the ones that are read from memory by the OS plug-ins. 506ba4e61d3SAndrew Kaylor 507ba4e61d3SAndrew Kaylor ThreadSP thread_sp(m_kernel_thread_wp.lock()); 508b9c1b51eSKate Stone if (!thread_sp) { 509ba4e61d3SAndrew Kaylor thread_sp.reset(new ThreadKDP(*this, g_kernel_tid)); 510ba4e61d3SAndrew Kaylor m_kernel_thread_wp = thread_sp; 511ba4e61d3SAndrew Kaylor } 51297d5cf05SGreg Clayton return thread_sp; 51397d5cf05SGreg Clayton } 51497d5cf05SGreg Clayton 515b9c1b51eSKate Stone bool ProcessKDP::UpdateThreadList(ThreadList &old_thread_list, 516b9c1b51eSKate Stone ThreadList &new_thread_list) { 517f9765acdSGreg Clayton // locker will keep a mutex locked until it goes out of scope 5185160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_THREAD)); 519f9765acdSGreg Clayton if (log && log->GetMask().Test(KDP_LOG_VERBOSE)) 520d01b2953SDaniel Malea log->Printf("ProcessKDP::%s (pid = %" PRIu64 ")", __FUNCTION__, GetID()); 521f9765acdSGreg Clayton 52239da3efdSGreg Clayton // Even though there is a CPU mask, it doesn't mean we can see each CPU 523a868c13cSBruce Mitchener // individually, there is really only one. Lets call this thread 1. 524b9c1b51eSKate Stone ThreadSP thread_sp( 525b9c1b51eSKate Stone old_thread_list.FindThreadByProtocolID(g_kernel_tid, false)); 526ba4e61d3SAndrew Kaylor if (!thread_sp) 527ba4e61d3SAndrew Kaylor thread_sp = GetKernelThread(); 528ba4e61d3SAndrew Kaylor new_thread_list.AddThread(thread_sp); 52997d5cf05SGreg Clayton 5309fc13556SGreg Clayton return new_thread_list.GetSize(false) > 0; 531f9765acdSGreg Clayton } 532f9765acdSGreg Clayton 533b9c1b51eSKate Stone void ProcessKDP::RefreshStateAfterStop() { 534f9765acdSGreg Clayton // Let all threads recover from stopping and do any clean up based 535f9765acdSGreg Clayton // on the previous thread state (if any). 536f9765acdSGreg Clayton m_thread_list.RefreshStateAfterStop(); 537f9765acdSGreg Clayton } 538f9765acdSGreg Clayton 539b9c1b51eSKate Stone Error ProcessKDP::DoHalt(bool &caused_stop) { 540f9765acdSGreg Clayton Error error; 541f9765acdSGreg Clayton 542b9c1b51eSKate Stone if (m_comm.IsRunning()) { 543b9c1b51eSKate Stone if (m_destroy_in_process) { 54497d5cf05SGreg Clayton // If we are attemping to destroy, we need to not return an error to 54597d5cf05SGreg Clayton // Halt or DoDestroy won't get called. 54697d5cf05SGreg Clayton // We are also currently running, so send a process stopped event 54797d5cf05SGreg Clayton SetPrivateState(eStateStopped); 548b9c1b51eSKate Stone } else { 54997d5cf05SGreg Clayton error.SetErrorString("KDP cannot interrupt a running kernel"); 550f9765acdSGreg Clayton } 551f9765acdSGreg Clayton } 552f9765acdSGreg Clayton return error; 553f9765acdSGreg Clayton } 554f9765acdSGreg Clayton 555b9c1b51eSKate Stone Error ProcessKDP::DoDetach(bool keep_stopped) { 556f9765acdSGreg Clayton Error error; 5575160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 558f9765acdSGreg Clayton if (log) 559acff8950SJim Ingham log->Printf("ProcessKDP::DoDetach(keep_stopped = %i)", keep_stopped); 560f9765acdSGreg Clayton 561b9c1b51eSKate Stone if (m_comm.IsRunning()) { 56297d5cf05SGreg Clayton // We are running and we can't interrupt a running kernel, so we need 56397d5cf05SGreg Clayton // to just close the connection to the kernel and hope for the best 564b9c1b51eSKate Stone } else { 565b9c1b51eSKate Stone // If we are going to keep the target stopped, then don't send the 566b9c1b51eSKate Stone // disconnect message. 567b9c1b51eSKate Stone if (!keep_stopped && m_comm.IsConnected()) { 5686e0ff1a3SGreg Clayton const bool success = m_comm.SendRequestDisconnect(); 569b9c1b51eSKate Stone if (log) { 5706e0ff1a3SGreg Clayton if (success) 571b9c1b51eSKate Stone log->PutCString( 572b9c1b51eSKate Stone "ProcessKDP::DoDetach() detach packet sent successfully"); 573f9765acdSGreg Clayton else 574b9c1b51eSKate Stone log->PutCString( 575b9c1b51eSKate Stone "ProcessKDP::DoDetach() connection channel shutdown failed"); 576f9765acdSGreg Clayton } 5776e0ff1a3SGreg Clayton m_comm.Disconnect(); 5783a29bdbeSGreg Clayton } 57997d5cf05SGreg Clayton } 580f9765acdSGreg Clayton StopAsyncThread(); 58174d4193eSGreg Clayton m_comm.Clear(); 582f9765acdSGreg Clayton 583f9765acdSGreg Clayton SetPrivateState(eStateDetached); 584f9765acdSGreg Clayton ResumePrivateStateThread(); 585f9765acdSGreg Clayton 586f9765acdSGreg Clayton // KillDebugserverProcess (); 587f9765acdSGreg Clayton return error; 588f9765acdSGreg Clayton } 589f9765acdSGreg Clayton 590b9c1b51eSKate Stone Error ProcessKDP::DoDestroy() { 5917925fbbaSGreg Clayton // For KDP there really is no difference between destroy and detach 592acff8950SJim Ingham bool keep_stopped = false; 593acff8950SJim Ingham return DoDetach(keep_stopped); 594f9765acdSGreg Clayton } 595f9765acdSGreg Clayton 596f9765acdSGreg Clayton //------------------------------------------------------------------ 597f9765acdSGreg Clayton // Process Queries 598f9765acdSGreg Clayton //------------------------------------------------------------------ 599f9765acdSGreg Clayton 600b9c1b51eSKate Stone bool ProcessKDP::IsAlive() { 601a814f704SJason Molenda return m_comm.IsConnected() && Process::IsAlive(); 602f9765acdSGreg Clayton } 603f9765acdSGreg Clayton 604f9765acdSGreg Clayton //------------------------------------------------------------------ 605f9765acdSGreg Clayton // Process Memory 606f9765acdSGreg Clayton //------------------------------------------------------------------ 607b9c1b51eSKate Stone size_t ProcessKDP::DoReadMemory(addr_t addr, void *buf, size_t size, 608b9c1b51eSKate Stone Error &error) { 6098eb32817SJason Molenda uint8_t *data_buffer = (uint8_t *)buf; 610b9c1b51eSKate Stone if (m_comm.IsConnected()) { 6118eb32817SJason Molenda const size_t max_read_size = 512; 6128eb32817SJason Molenda size_t total_bytes_read = 0; 6138eb32817SJason Molenda 6148eb32817SJason Molenda // Read the requested amount of memory in 512 byte chunks 615b9c1b51eSKate Stone while (total_bytes_read < size) { 6168eb32817SJason Molenda size_t bytes_to_read_this_request = size - total_bytes_read; 617b9c1b51eSKate Stone if (bytes_to_read_this_request > max_read_size) { 6188eb32817SJason Molenda bytes_to_read_this_request = max_read_size; 6198eb32817SJason Molenda } 620b9c1b51eSKate Stone size_t bytes_read = m_comm.SendRequestReadMemory( 621b9c1b51eSKate Stone addr + total_bytes_read, data_buffer + total_bytes_read, 6228eb32817SJason Molenda bytes_to_read_this_request, error); 6238eb32817SJason Molenda total_bytes_read += bytes_read; 624b9c1b51eSKate Stone if (error.Fail() || bytes_read == 0) { 6258eb32817SJason Molenda return total_bytes_read; 6268eb32817SJason Molenda } 6278eb32817SJason Molenda } 6288eb32817SJason Molenda 6298eb32817SJason Molenda return total_bytes_read; 6308eb32817SJason Molenda } 631a63d08c9SGreg Clayton error.SetErrorString("not connected"); 632f9765acdSGreg Clayton return 0; 633f9765acdSGreg Clayton } 634f9765acdSGreg Clayton 635b9c1b51eSKate Stone size_t ProcessKDP::DoWriteMemory(addr_t addr, const void *buf, size_t size, 636b9c1b51eSKate Stone Error &error) { 6377925fbbaSGreg Clayton if (m_comm.IsConnected()) 6387925fbbaSGreg Clayton return m_comm.SendRequestWriteMemory(addr, buf, size, error); 6397925fbbaSGreg Clayton error.SetErrorString("not connected"); 640f9765acdSGreg Clayton return 0; 641f9765acdSGreg Clayton } 642f9765acdSGreg Clayton 643b9c1b51eSKate Stone lldb::addr_t ProcessKDP::DoAllocateMemory(size_t size, uint32_t permissions, 644b9c1b51eSKate Stone Error &error) { 645b9c1b51eSKate Stone error.SetErrorString( 646b9c1b51eSKate Stone "memory allocation not suppported in kdp remote debugging"); 647f9765acdSGreg Clayton return LLDB_INVALID_ADDRESS; 648f9765acdSGreg Clayton } 649f9765acdSGreg Clayton 650b9c1b51eSKate Stone Error ProcessKDP::DoDeallocateMemory(lldb::addr_t addr) { 651f9765acdSGreg Clayton Error error; 652b9c1b51eSKate Stone error.SetErrorString( 653b9c1b51eSKate Stone "memory deallocation not suppported in kdp remote debugging"); 654f9765acdSGreg Clayton return error; 655f9765acdSGreg Clayton } 656f9765acdSGreg Clayton 657b9c1b51eSKate Stone Error ProcessKDP::EnableBreakpointSite(BreakpointSite *bp_site) { 658b9c1b51eSKate Stone if (m_comm.LocalBreakpointsAreSupported()) { 65907e66e3eSGreg Clayton Error error; 660b9c1b51eSKate Stone if (!bp_site->IsEnabled()) { 661b9c1b51eSKate Stone if (m_comm.SendRequestBreakpoint(true, bp_site->GetLoadAddress())) { 6625b88216dSGreg Clayton bp_site->SetEnabled(true); 6635b88216dSGreg Clayton bp_site->SetType(BreakpointSite::eExternal); 664b9c1b51eSKate Stone } else { 66507e66e3eSGreg Clayton error.SetErrorString("KDP set breakpoint failed"); 6665b88216dSGreg Clayton } 6675b88216dSGreg Clayton } 66807e66e3eSGreg Clayton return error; 66907e66e3eSGreg Clayton } 670f9765acdSGreg Clayton return EnableSoftwareBreakpoint(bp_site); 671f9765acdSGreg Clayton } 672f9765acdSGreg Clayton 673b9c1b51eSKate Stone Error ProcessKDP::DisableBreakpointSite(BreakpointSite *bp_site) { 674b9c1b51eSKate Stone if (m_comm.LocalBreakpointsAreSupported()) { 67507e66e3eSGreg Clayton Error error; 676b9c1b51eSKate Stone if (bp_site->IsEnabled()) { 6775b88216dSGreg Clayton BreakpointSite::Type bp_type = bp_site->GetType(); 678b9c1b51eSKate Stone if (bp_type == BreakpointSite::eExternal) { 679b9c1b51eSKate Stone if (m_destroy_in_process && m_comm.IsRunning()) { 68097d5cf05SGreg Clayton // We are trying to destroy our connection and we are running 68197d5cf05SGreg Clayton bp_site->SetEnabled(false); 682b9c1b51eSKate Stone } else { 6835b88216dSGreg Clayton if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress())) 6845b88216dSGreg Clayton bp_site->SetEnabled(false); 6855b88216dSGreg Clayton else 68607e66e3eSGreg Clayton error.SetErrorString("KDP remove breakpoint failed"); 6875b88216dSGreg Clayton } 688b9c1b51eSKate Stone } else { 6895b88216dSGreg Clayton error = DisableSoftwareBreakpoint(bp_site); 6905b88216dSGreg Clayton } 6915b88216dSGreg Clayton } 69207e66e3eSGreg Clayton return error; 69307e66e3eSGreg Clayton } 694f9765acdSGreg Clayton return DisableSoftwareBreakpoint(bp_site); 695f9765acdSGreg Clayton } 696f9765acdSGreg Clayton 697b9c1b51eSKate Stone Error ProcessKDP::EnableWatchpoint(Watchpoint *wp, bool notify) { 698f9765acdSGreg Clayton Error error; 699b9c1b51eSKate Stone error.SetErrorString( 700b9c1b51eSKate Stone "watchpoints are not suppported in kdp remote debugging"); 701f9765acdSGreg Clayton return error; 702f9765acdSGreg Clayton } 703f9765acdSGreg Clayton 704b9c1b51eSKate Stone Error ProcessKDP::DisableWatchpoint(Watchpoint *wp, bool notify) { 705f9765acdSGreg Clayton Error error; 706b9c1b51eSKate Stone error.SetErrorString( 707b9c1b51eSKate Stone "watchpoints are not suppported in kdp remote debugging"); 708f9765acdSGreg Clayton return error; 709f9765acdSGreg Clayton } 710f9765acdSGreg Clayton 711b9c1b51eSKate Stone void ProcessKDP::Clear() { m_thread_list.Clear(); } 712f9765acdSGreg Clayton 713b9c1b51eSKate Stone Error ProcessKDP::DoSignal(int signo) { 714f9765acdSGreg Clayton Error error; 715b9c1b51eSKate Stone error.SetErrorString( 716b9c1b51eSKate Stone "sending signals is not suppported in kdp remote debugging"); 717f9765acdSGreg Clayton return error; 718f9765acdSGreg Clayton } 719f9765acdSGreg Clayton 720b9c1b51eSKate Stone void ProcessKDP::Initialize() { 721c8d69828SDavide Italiano static std::once_flag g_once_flag; 722f9765acdSGreg Clayton 723b9c1b51eSKate Stone std::call_once(g_once_flag, []() { 724f9765acdSGreg Clayton PluginManager::RegisterPlugin(GetPluginNameStatic(), 725b9c1b51eSKate Stone GetPluginDescriptionStatic(), CreateInstance, 726488c89edSBruce Mitchener DebuggerInitialize); 727f9765acdSGreg Clayton 728b9c1b51eSKate Stone Log::Callbacks log_callbacks = {ProcessKDPLog::DisableLog, 729f9765acdSGreg Clayton ProcessKDPLog::EnableLog, 730b9c1b51eSKate Stone ProcessKDPLog::ListLogCategories}; 731f9765acdSGreg Clayton 732f9765acdSGreg Clayton Log::RegisterLogChannel(ProcessKDP::GetPluginNameStatic(), log_callbacks); 733c8d69828SDavide Italiano }); 734f9765acdSGreg Clayton } 735f9765acdSGreg Clayton 736b9c1b51eSKate Stone void ProcessKDP::DebuggerInitialize(lldb_private::Debugger &debugger) { 737b9c1b51eSKate Stone if (!PluginManager::GetSettingForProcessPlugin( 738b9c1b51eSKate Stone debugger, PluginProperties::GetSettingName())) { 7397f98240dSGreg Clayton const bool is_global_setting = true; 740b9c1b51eSKate Stone PluginManager::CreateSettingForProcessPlugin( 741b9c1b51eSKate Stone debugger, GetGlobalPluginProperties()->GetValueProperties(), 7427f98240dSGreg Clayton ConstString("Properties for the kdp-remote process plug-in."), 7437f98240dSGreg Clayton is_global_setting); 7447f98240dSGreg Clayton } 7457f98240dSGreg Clayton } 7467f98240dSGreg Clayton 747b9c1b51eSKate Stone bool ProcessKDP::StartAsyncThread() { 7485160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 749f9765acdSGreg Clayton 750f9765acdSGreg Clayton if (log) 7517925fbbaSGreg Clayton log->Printf("ProcessKDP::StartAsyncThread ()"); 752f9765acdSGreg Clayton 753acee96aeSZachary Turner if (m_async_thread.IsJoinable()) 7547925fbbaSGreg Clayton return true; 7557925fbbaSGreg Clayton 756b9c1b51eSKate Stone m_async_thread = ThreadLauncher::LaunchThread( 757b9c1b51eSKate Stone "<lldb.process.kdp-remote.async>", ProcessKDP::AsyncThread, this, NULL); 758acee96aeSZachary Turner return m_async_thread.IsJoinable(); 759f9765acdSGreg Clayton } 760f9765acdSGreg Clayton 761b9c1b51eSKate Stone void ProcessKDP::StopAsyncThread() { 7625160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 763f9765acdSGreg Clayton 764f9765acdSGreg Clayton if (log) 7657925fbbaSGreg Clayton log->Printf("ProcessKDP::StopAsyncThread ()"); 766f9765acdSGreg Clayton 767f9765acdSGreg Clayton m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit); 768f9765acdSGreg Clayton 769f9765acdSGreg Clayton // Stop the stdio thread 770acee96aeSZachary Turner if (m_async_thread.IsJoinable()) 77139de3110SZachary Turner m_async_thread.Join(nullptr); 772f9765acdSGreg Clayton } 773f9765acdSGreg Clayton 774b9c1b51eSKate Stone void *ProcessKDP::AsyncThread(void *arg) { 775f9765acdSGreg Clayton ProcessKDP *process = (ProcessKDP *)arg; 776f9765acdSGreg Clayton 7777925fbbaSGreg Clayton const lldb::pid_t pid = process->GetID(); 7787925fbbaSGreg Clayton 7795160ce5cSGreg Clayton Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); 780f9765acdSGreg Clayton if (log) 781b9c1b51eSKate Stone log->Printf("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 782b9c1b51eSKate Stone ") thread starting...", 783b9c1b51eSKate Stone arg, pid); 784f9765acdSGreg Clayton 785583bbb1dSJim Ingham ListenerSP listener_sp(Listener::MakeListener("ProcessKDP::AsyncThread")); 786f9765acdSGreg Clayton EventSP event_sp; 787b9c1b51eSKate Stone const uint32_t desired_event_mask = 788b9c1b51eSKate Stone eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit; 789f9765acdSGreg Clayton 790b9c1b51eSKate Stone if (listener_sp->StartListeningForEvents(&process->m_async_broadcaster, 791b9c1b51eSKate Stone desired_event_mask) == 792b9c1b51eSKate Stone desired_event_mask) { 793f9765acdSGreg Clayton bool done = false; 794b9c1b51eSKate Stone while (!done) { 795f9765acdSGreg Clayton if (log) 796b9c1b51eSKate Stone log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 797b9c1b51eSKate Stone ") listener.WaitForEvent (NULL, event_sp)...", 7987925fbbaSGreg Clayton pid); 799b9c1b51eSKate Stone if (listener_sp->WaitForEvent(std::chrono::microseconds(0), event_sp)) { 8007925fbbaSGreg Clayton uint32_t event_type = event_sp->GetType(); 801f9765acdSGreg Clayton if (log) 802b9c1b51eSKate Stone log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 803b9c1b51eSKate Stone ") Got an event of type: %d...", 804b9c1b51eSKate Stone pid, event_type); 805f9765acdSGreg Clayton 8067925fbbaSGreg Clayton // When we are running, poll for 1 second to try and get an exception 8077925fbbaSGreg Clayton // to indicate the process has stopped. If we don't get one, check to 8087925fbbaSGreg Clayton // make sure no one asked us to exit 8097925fbbaSGreg Clayton bool is_running = false; 8107925fbbaSGreg Clayton DataExtractor exc_reply_packet; 811b9c1b51eSKate Stone do { 812b9c1b51eSKate Stone switch (event_type) { 813b9c1b51eSKate Stone case eBroadcastBitAsyncContinue: { 8147925fbbaSGreg Clayton is_running = true; 815b9c1b51eSKate Stone if (process->m_comm.WaitForPacketWithTimeoutMicroSeconds( 816b9c1b51eSKate Stone exc_reply_packet, 1 * USEC_PER_SEC)) { 817ba4e61d3SAndrew Kaylor ThreadSP thread_sp(process->GetKernelThread()); 818b9c1b51eSKate Stone if (thread_sp) { 819b9c1b51eSKate Stone lldb::RegisterContextSP reg_ctx_sp( 820b9c1b51eSKate Stone thread_sp->GetRegisterContext()); 8211afa68edSGreg Clayton if (reg_ctx_sp) 8221afa68edSGreg Clayton reg_ctx_sp->InvalidateAllRegisters(); 823b9c1b51eSKate Stone static_cast<ThreadKDP *>(thread_sp.get()) 824b9c1b51eSKate Stone ->SetStopInfoFrom_KDP_EXCEPTION(exc_reply_packet); 8251afa68edSGreg Clayton } 82697d5cf05SGreg Clayton 8277925fbbaSGreg Clayton // TODO: parse the stop reply packet 8287925fbbaSGreg Clayton is_running = false; 8297925fbbaSGreg Clayton process->SetPrivateState(eStateStopped); 830b9c1b51eSKate Stone } else { 8317925fbbaSGreg Clayton // Check to see if we are supposed to exit. There is no way to 8327925fbbaSGreg Clayton // interrupt a running kernel, so all we can do is wait for an 8337925fbbaSGreg Clayton // exception or detach... 834b9c1b51eSKate Stone if (listener_sp->GetNextEvent(event_sp)) { 8357925fbbaSGreg Clayton // We got an event, go through the loop again 8367925fbbaSGreg Clayton event_type = event_sp->GetType(); 8377925fbbaSGreg Clayton } 838f9765acdSGreg Clayton } 839b9c1b51eSKate Stone } break; 840f9765acdSGreg Clayton 841f9765acdSGreg Clayton case eBroadcastBitAsyncThreadShouldExit: 842f9765acdSGreg Clayton if (log) 843b9c1b51eSKate Stone log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 844b9c1b51eSKate Stone ") got eBroadcastBitAsyncThreadShouldExit...", 8457925fbbaSGreg Clayton pid); 846f9765acdSGreg Clayton done = true; 8477925fbbaSGreg Clayton is_running = false; 848f9765acdSGreg Clayton break; 849f9765acdSGreg Clayton 850f9765acdSGreg Clayton default: 851f9765acdSGreg Clayton if (log) 852b9c1b51eSKate Stone log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 853b9c1b51eSKate Stone ") got unknown event 0x%8.8x", 854b9c1b51eSKate Stone pid, event_type); 855f9765acdSGreg Clayton done = true; 8567925fbbaSGreg Clayton is_running = false; 857f9765acdSGreg Clayton break; 858f9765acdSGreg Clayton } 8597925fbbaSGreg Clayton } while (is_running); 860b9c1b51eSKate Stone } else { 861f9765acdSGreg Clayton if (log) 862b9c1b51eSKate Stone log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 863b9c1b51eSKate Stone ") listener.WaitForEvent (NULL, event_sp) => false", 8647925fbbaSGreg Clayton pid); 865f9765acdSGreg Clayton done = true; 866f9765acdSGreg Clayton } 867f9765acdSGreg Clayton } 868f9765acdSGreg Clayton } 869f9765acdSGreg Clayton 870f9765acdSGreg Clayton if (log) 871b9c1b51eSKate Stone log->Printf("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 872b9c1b51eSKate Stone ") thread exiting...", 873b9c1b51eSKate Stone arg, pid); 874f9765acdSGreg Clayton 87539de3110SZachary Turner process->m_async_thread.Reset(); 876f9765acdSGreg Clayton return NULL; 877f9765acdSGreg Clayton } 878f9765acdSGreg Clayton 879b9c1b51eSKate Stone class CommandObjectProcessKDPPacketSend : public CommandObjectParsed { 8801d19a2f2SGreg Clayton private: 8811d19a2f2SGreg Clayton OptionGroupOptions m_option_group; 8821d19a2f2SGreg Clayton OptionGroupUInt64 m_command_byte; 8831d19a2f2SGreg Clayton OptionGroupString m_packet_data; 8841d19a2f2SGreg Clayton 885b9c1b51eSKate Stone virtual Options *GetOptions() { return &m_option_group; } 8861d19a2f2SGreg Clayton 8871d19a2f2SGreg Clayton public: 888b9c1b51eSKate Stone CommandObjectProcessKDPPacketSend(CommandInterpreter &interpreter) 889b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "process plugin packet send", 890b9c1b51eSKate Stone "Send a custom packet through the KDP protocol by " 891b9c1b51eSKate Stone "specifying the command byte and the packet " 892b9c1b51eSKate Stone "payload data. A packet will be sent with a " 893b9c1b51eSKate Stone "correct header and payload, and the raw result " 894b9c1b51eSKate Stone "bytes will be displayed as a string value. ", 8951d19a2f2SGreg Clayton NULL), 896e1cfbc79STodd Fiala m_option_group(), 897b9c1b51eSKate Stone m_command_byte(LLDB_OPT_SET_1, true, "command", 'c', 0, eArgTypeNone, 898b9c1b51eSKate Stone "Specify the command byte to use when sending the KDP " 899b9c1b51eSKate Stone "request packet.", 900b9c1b51eSKate Stone 0), 901b9c1b51eSKate Stone m_packet_data(LLDB_OPT_SET_1, false, "payload", 'p', 0, eArgTypeNone, 902b9c1b51eSKate Stone "Specify packet payload bytes as a hex ASCII string with " 903b9c1b51eSKate Stone "no spaces or hex prefixes.", 904b9c1b51eSKate Stone NULL) { 9051d19a2f2SGreg Clayton m_option_group.Append(&m_command_byte, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 9061d19a2f2SGreg Clayton m_option_group.Append(&m_packet_data, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 9071d19a2f2SGreg Clayton m_option_group.Finalize(); 9081d19a2f2SGreg Clayton } 9091d19a2f2SGreg Clayton 910b9c1b51eSKate Stone ~CommandObjectProcessKDPPacketSend() {} 9111d19a2f2SGreg Clayton 912b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) { 9131d19a2f2SGreg Clayton const size_t argc = command.GetArgumentCount(); 914b9c1b51eSKate Stone if (argc == 0) { 915b9c1b51eSKate Stone if (!m_command_byte.GetOptionValue().OptionWasSet()) { 916b9c1b51eSKate Stone result.AppendError( 917b9c1b51eSKate Stone "the --command option must be set to a valid command byte"); 9181d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 919b9c1b51eSKate Stone } else { 920b9c1b51eSKate Stone const uint64_t command_byte = 921b9c1b51eSKate Stone m_command_byte.GetOptionValue().GetUInt64Value(0); 922b9c1b51eSKate Stone if (command_byte > 0 && command_byte <= UINT8_MAX) { 923b9c1b51eSKate Stone ProcessKDP *process = 924b9c1b51eSKate Stone (ProcessKDP *)m_interpreter.GetExecutionContext().GetProcessPtr(); 925b9c1b51eSKate Stone if (process) { 9261d19a2f2SGreg Clayton const StateType state = process->GetState(); 9271d19a2f2SGreg Clayton 928b9c1b51eSKate Stone if (StateIsStoppedState(state, true)) { 9291d19a2f2SGreg Clayton std::vector<uint8_t> payload_bytes; 930b9c1b51eSKate Stone const char *ascii_hex_bytes_cstr = 931b9c1b51eSKate Stone m_packet_data.GetOptionValue().GetCurrentValue(); 932b9c1b51eSKate Stone if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0]) { 9331d19a2f2SGreg Clayton StringExtractor extractor(ascii_hex_bytes_cstr); 934b9c1b51eSKate Stone const size_t ascii_hex_bytes_cstr_len = 935b9c1b51eSKate Stone extractor.GetStringRef().size(); 936b9c1b51eSKate Stone if (ascii_hex_bytes_cstr_len & 1) { 937b9c1b51eSKate Stone result.AppendErrorWithFormat("payload data must contain an " 938b9c1b51eSKate Stone "even number of ASCII hex " 939b9c1b51eSKate Stone "characters: '%s'", 940b9c1b51eSKate Stone ascii_hex_bytes_cstr); 9411d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9421d19a2f2SGreg Clayton return false; 9431d19a2f2SGreg Clayton } 9441d19a2f2SGreg Clayton payload_bytes.resize(ascii_hex_bytes_cstr_len / 2); 945b9c1b51eSKate Stone if (extractor.GetHexBytes(payload_bytes, '\xdd') != 946b9c1b51eSKate Stone payload_bytes.size()) { 947b9c1b51eSKate Stone result.AppendErrorWithFormat("payload data must only contain " 948b9c1b51eSKate Stone "ASCII hex characters (no " 949b9c1b51eSKate Stone "spaces or hex prefixes): '%s'", 950b9c1b51eSKate Stone ascii_hex_bytes_cstr); 9511d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9521d19a2f2SGreg Clayton return false; 9531d19a2f2SGreg Clayton } 9541d19a2f2SGreg Clayton } 9551d19a2f2SGreg Clayton Error error; 9561d19a2f2SGreg Clayton DataExtractor reply; 957b9c1b51eSKate Stone process->GetCommunication().SendRawRequest( 958b9c1b51eSKate Stone command_byte, 9591d19a2f2SGreg Clayton payload_bytes.empty() ? NULL : payload_bytes.data(), 960b9c1b51eSKate Stone payload_bytes.size(), reply, error); 9611d19a2f2SGreg Clayton 962b9c1b51eSKate Stone if (error.Success()) { 9631d19a2f2SGreg Clayton // Copy the binary bytes into a hex ASCII string for the result 9641d19a2f2SGreg Clayton StreamString packet; 965b9c1b51eSKate Stone packet.PutBytesAsRawHex8( 966b9c1b51eSKate Stone reply.GetDataStart(), reply.GetByteSize(), 967b9c1b51eSKate Stone endian::InlHostByteOrder(), endian::InlHostByteOrder()); 9681d19a2f2SGreg Clayton result.AppendMessage(packet.GetString().c_str()); 9691d19a2f2SGreg Clayton result.SetStatus(eReturnStatusSuccessFinishResult); 9701d19a2f2SGreg Clayton return true; 971b9c1b51eSKate Stone } else { 9721d19a2f2SGreg Clayton const char *error_cstr = error.AsCString(); 9731d19a2f2SGreg Clayton if (error_cstr && error_cstr[0]) 9741d19a2f2SGreg Clayton result.AppendError(error_cstr); 9751d19a2f2SGreg Clayton else 976b9c1b51eSKate Stone result.AppendErrorWithFormat("unknown error 0x%8.8x", 977b9c1b51eSKate Stone error.GetError()); 9781d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9791d19a2f2SGreg Clayton return false; 9801d19a2f2SGreg Clayton } 981b9c1b51eSKate Stone } else { 982b9c1b51eSKate Stone result.AppendErrorWithFormat("process must be stopped in order " 983b9c1b51eSKate Stone "to send KDP packets, state is %s", 984b9c1b51eSKate Stone StateAsCString(state)); 9851d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9861d19a2f2SGreg Clayton } 987b9c1b51eSKate Stone } else { 9881d19a2f2SGreg Clayton result.AppendError("invalid process"); 9891d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9901d19a2f2SGreg Clayton } 991b9c1b51eSKate Stone } else { 992b9c1b51eSKate Stone result.AppendErrorWithFormat("invalid command byte 0x%" PRIx64 993b9c1b51eSKate Stone ", valid values are 1 - 255", 994b9c1b51eSKate Stone command_byte); 9951d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 9961d19a2f2SGreg Clayton } 9971d19a2f2SGreg Clayton } 998b9c1b51eSKate Stone } else { 999b9c1b51eSKate Stone result.AppendErrorWithFormat("'%s' takes no arguments, only options.", 1000b9c1b51eSKate Stone m_cmd_name.c_str()); 10011d19a2f2SGreg Clayton result.SetStatus(eReturnStatusFailed); 10021d19a2f2SGreg Clayton } 10031d19a2f2SGreg Clayton return false; 10041d19a2f2SGreg Clayton } 10051d19a2f2SGreg Clayton }; 10061d19a2f2SGreg Clayton 1007b9c1b51eSKate Stone class CommandObjectProcessKDPPacket : public CommandObjectMultiword { 10081d19a2f2SGreg Clayton private: 10091d19a2f2SGreg Clayton public: 1010b9c1b51eSKate Stone CommandObjectProcessKDPPacket(CommandInterpreter &interpreter) 1011b9c1b51eSKate Stone : CommandObjectMultiword(interpreter, "process plugin packet", 10121d19a2f2SGreg Clayton "Commands that deal with KDP remote packets.", 1013b9c1b51eSKate Stone NULL) { 1014b9c1b51eSKate Stone LoadSubCommand( 1015b9c1b51eSKate Stone "send", 1016b9c1b51eSKate Stone CommandObjectSP(new CommandObjectProcessKDPPacketSend(interpreter))); 10171d19a2f2SGreg Clayton } 10181d19a2f2SGreg Clayton 1019b9c1b51eSKate Stone ~CommandObjectProcessKDPPacket() {} 10201d19a2f2SGreg Clayton }; 10211d19a2f2SGreg Clayton 1022b9c1b51eSKate Stone class CommandObjectMultiwordProcessKDP : public CommandObjectMultiword { 10231d19a2f2SGreg Clayton public: 10247428a18cSKate Stone CommandObjectMultiwordProcessKDP(CommandInterpreter &interpreter) 1025b9c1b51eSKate Stone : CommandObjectMultiword( 1026b9c1b51eSKate Stone interpreter, "process plugin", 1027b9c1b51eSKate Stone "Commands for operating on a ProcessKDP process.", 1028b9c1b51eSKate Stone "process plugin <subcommand> [<subcommand-options>]") { 1029b9c1b51eSKate Stone LoadSubCommand("packet", CommandObjectSP(new CommandObjectProcessKDPPacket( 1030b9c1b51eSKate Stone interpreter))); 10311d19a2f2SGreg Clayton } 10321d19a2f2SGreg Clayton 1033b9c1b51eSKate Stone ~CommandObjectMultiwordProcessKDP() {} 10341d19a2f2SGreg Clayton }; 10351d19a2f2SGreg Clayton 1036b9c1b51eSKate Stone CommandObject *ProcessKDP::GetPluginCommandObject() { 10371d19a2f2SGreg Clayton if (!m_command_sp) 1038b9c1b51eSKate Stone m_command_sp.reset(new CommandObjectMultiwordProcessKDP( 1039b9c1b51eSKate Stone GetTarget().GetDebugger().GetCommandInterpreter())); 10401d19a2f2SGreg Clayton return m_command_sp.get(); 10411d19a2f2SGreg Clayton } 1042