15ffd83dbSDimitry Andric //===-- ProcessGDBRemote.cpp ----------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "lldb/Host/Config.h" 100b57cec5SDimitry Andric 11fe6060f1SDimitry Andric #include <cerrno> 12fe6060f1SDimitry Andric #include <cstdlib> 13480093f4SDimitry Andric #if LLDB_ENABLE_POSIX 140b57cec5SDimitry Andric #include <netinet/in.h> 150b57cec5SDimitry Andric #include <sys/mman.h> 160b57cec5SDimitry Andric #include <sys/socket.h> 170b57cec5SDimitry Andric #include <unistd.h> 180b57cec5SDimitry Andric #endif 190b57cec5SDimitry Andric #include <sys/stat.h> 205ffd83dbSDimitry Andric #if defined(__APPLE__) 215ffd83dbSDimitry Andric #include <sys/sysctl.h> 225ffd83dbSDimitry Andric #endif 23fe6060f1SDimitry Andric #include <ctime> 240b57cec5SDimitry Andric #include <sys/types.h> 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric #include "lldb/Breakpoint/Watchpoint.h" 27*5f757f3fSDimitry Andric #include "lldb/Breakpoint/WatchpointResource.h" 280b57cec5SDimitry Andric #include "lldb/Core/Debugger.h" 290b57cec5SDimitry Andric #include "lldb/Core/Module.h" 300b57cec5SDimitry Andric #include "lldb/Core/ModuleSpec.h" 310b57cec5SDimitry Andric #include "lldb/Core/PluginManager.h" 320b57cec5SDimitry Andric #include "lldb/Core/Value.h" 330b57cec5SDimitry Andric #include "lldb/DataFormatters/FormatManager.h" 340b57cec5SDimitry Andric #include "lldb/Host/ConnectionFileDescriptor.h" 350b57cec5SDimitry Andric #include "lldb/Host/FileSystem.h" 360b57cec5SDimitry Andric #include "lldb/Host/HostThread.h" 370b57cec5SDimitry Andric #include "lldb/Host/PosixApi.h" 380b57cec5SDimitry Andric #include "lldb/Host/PseudoTerminal.h" 39*5f757f3fSDimitry Andric #include "lldb/Host/StreamFile.h" 400b57cec5SDimitry Andric #include "lldb/Host/ThreadLauncher.h" 410b57cec5SDimitry Andric #include "lldb/Host/XML.h" 420b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h" 430b57cec5SDimitry Andric #include "lldb/Interpreter/CommandObject.h" 440b57cec5SDimitry Andric #include "lldb/Interpreter/CommandObjectMultiword.h" 450b57cec5SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h" 460b57cec5SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h" 470b57cec5SDimitry Andric #include "lldb/Interpreter/OptionGroupBoolean.h" 480b57cec5SDimitry Andric #include "lldb/Interpreter/OptionGroupUInt64.h" 490b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValueProperties.h" 500b57cec5SDimitry Andric #include "lldb/Interpreter/Options.h" 510b57cec5SDimitry Andric #include "lldb/Interpreter/Property.h" 520b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h" 530b57cec5SDimitry Andric #include "lldb/Target/ABI.h" 540b57cec5SDimitry Andric #include "lldb/Target/DynamicLoader.h" 550b57cec5SDimitry Andric #include "lldb/Target/MemoryRegionInfo.h" 5606c3fb27SDimitry Andric #include "lldb/Target/RegisterFlags.h" 570b57cec5SDimitry Andric #include "lldb/Target/SystemRuntime.h" 580b57cec5SDimitry Andric #include "lldb/Target/Target.h" 590b57cec5SDimitry Andric #include "lldb/Target/TargetList.h" 600b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanCallFunction.h" 610b57cec5SDimitry Andric #include "lldb/Utility/Args.h" 620b57cec5SDimitry Andric #include "lldb/Utility/FileSpec.h" 6381ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h" 640b57cec5SDimitry Andric #include "lldb/Utility/State.h" 650b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h" 660b57cec5SDimitry Andric #include "lldb/Utility/Timer.h" 6704eeddc0SDimitry Andric #include <algorithm> 6804eeddc0SDimitry Andric #include <csignal> 6904eeddc0SDimitry Andric #include <map> 7004eeddc0SDimitry Andric #include <memory> 7104eeddc0SDimitry Andric #include <mutex> 72bdd1243dSDimitry Andric #include <optional> 7304eeddc0SDimitry Andric #include <sstream> 7404eeddc0SDimitry Andric #include <thread> 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric #include "GDBRemoteRegisterContext.h" 7704eeddc0SDimitry Andric #include "GDBRemoteRegisterFallback.h" 780b57cec5SDimitry Andric #include "Plugins/Process/Utility/GDBRemoteSignals.h" 790b57cec5SDimitry Andric #include "Plugins/Process/Utility/InferiorCallPOSIX.h" 800b57cec5SDimitry Andric #include "Plugins/Process/Utility/StopInfoMachException.h" 810b57cec5SDimitry Andric #include "ProcessGDBRemote.h" 820b57cec5SDimitry Andric #include "ProcessGDBRemoteLog.h" 830b57cec5SDimitry Andric #include "ThreadGDBRemote.h" 840b57cec5SDimitry Andric #include "lldb/Host/Host.h" 850b57cec5SDimitry Andric #include "lldb/Utility/StringExtractorGDBRemote.h" 860b57cec5SDimitry Andric 879dba64beSDimitry Andric #include "llvm/ADT/ScopeExit.h" 8806c3fb27SDimitry Andric #include "llvm/ADT/StringMap.h" 890b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h" 90bdd1243dSDimitry Andric #include "llvm/Support/FormatAdapters.h" 910b57cec5SDimitry Andric #include "llvm/Support/Threading.h" 920b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric #define DEBUGSERVER_BASENAME "debugserver" 950b57cec5SDimitry Andric using namespace lldb; 960b57cec5SDimitry Andric using namespace lldb_private; 970b57cec5SDimitry Andric using namespace lldb_private::process_gdb_remote; 980b57cec5SDimitry Andric 995ffd83dbSDimitry Andric LLDB_PLUGIN_DEFINE(ProcessGDBRemote) 1005ffd83dbSDimitry Andric 1010b57cec5SDimitry Andric namespace lldb { 1020b57cec5SDimitry Andric // Provide a function that can easily dump the packet history if we know a 1030b57cec5SDimitry Andric // ProcessGDBRemote * value (which we can get from logs or from debugging). We 1040b57cec5SDimitry Andric // need the function in the lldb namespace so it makes it into the final 1050b57cec5SDimitry Andric // executable since the LLDB shared library only exports stuff in the lldb 1060b57cec5SDimitry Andric // namespace. This allows you to attach with a debugger and call this function 1070b57cec5SDimitry Andric // and get the packet history dumped to a file. 1080b57cec5SDimitry Andric void DumpProcessGDBRemotePacketHistory(void *p, const char *path) { 1099dba64beSDimitry Andric auto file = FileSystem::Instance().Open( 110349cc55cSDimitry Andric FileSpec(path), File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate); 1119dba64beSDimitry Andric if (!file) { 1129dba64beSDimitry Andric llvm::consumeError(file.takeError()); 1139dba64beSDimitry Andric return; 1149dba64beSDimitry Andric } 1159dba64beSDimitry Andric StreamFile stream(std::move(file.get())); 11606c3fb27SDimitry Andric ((Process *)p)->DumpPluginHistory(stream); 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric } // namespace lldb 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric namespace { 1210b57cec5SDimitry Andric 1229dba64beSDimitry Andric #define LLDB_PROPERTIES_processgdbremote 1239dba64beSDimitry Andric #include "ProcessGDBRemoteProperties.inc" 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric enum { 1269dba64beSDimitry Andric #define LLDB_PROPERTIES_processgdbremote 1279dba64beSDimitry Andric #include "ProcessGDBRemotePropertiesEnum.inc" 1280b57cec5SDimitry Andric }; 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric class PluginProperties : public Properties { 1310b57cec5SDimitry Andric public: 132*5f757f3fSDimitry Andric static llvm::StringRef GetSettingName() { 133*5f757f3fSDimitry Andric return ProcessGDBRemote::GetPluginNameStatic(); 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric PluginProperties() : Properties() { 1370b57cec5SDimitry Andric m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); 1389dba64beSDimitry Andric m_collection_sp->Initialize(g_processgdbremote_properties); 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric 141fe6060f1SDimitry Andric ~PluginProperties() override = default; 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric uint64_t GetPacketTimeout() { 1440b57cec5SDimitry Andric const uint32_t idx = ePropertyPacketTimeout; 14506c3fb27SDimitry Andric return GetPropertyAtIndexAs<uint64_t>( 14606c3fb27SDimitry Andric idx, g_processgdbremote_properties[idx].default_uint_value); 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric bool SetPacketTimeout(uint64_t timeout) { 1500b57cec5SDimitry Andric const uint32_t idx = ePropertyPacketTimeout; 15106c3fb27SDimitry Andric return SetPropertyAtIndex(idx, timeout); 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric FileSpec GetTargetDefinitionFile() const { 1550b57cec5SDimitry Andric const uint32_t idx = ePropertyTargetDefinitionFile; 15606c3fb27SDimitry Andric return GetPropertyAtIndexAs<FileSpec>(idx, {}); 1570b57cec5SDimitry Andric } 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric bool GetUseSVR4() const { 1600b57cec5SDimitry Andric const uint32_t idx = ePropertyUseSVR4; 16106c3fb27SDimitry Andric return GetPropertyAtIndexAs<bool>( 16206c3fb27SDimitry Andric idx, g_processgdbremote_properties[idx].default_uint_value != 0); 1630b57cec5SDimitry Andric } 164480093f4SDimitry Andric 165480093f4SDimitry Andric bool GetUseGPacketForReading() const { 166480093f4SDimitry Andric const uint32_t idx = ePropertyUseGPacketForReading; 16706c3fb27SDimitry Andric return GetPropertyAtIndexAs<bool>(idx, true); 168480093f4SDimitry Andric } 1690b57cec5SDimitry Andric }; 1700b57cec5SDimitry Andric 171bdd1243dSDimitry Andric } // namespace 172bdd1243dSDimitry Andric 173349cc55cSDimitry Andric static PluginProperties &GetGlobalPluginProperties() { 174349cc55cSDimitry Andric static PluginProperties g_settings; 175349cc55cSDimitry Andric return g_settings; 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric // TODO Randomly assigning a port is unsafe. We should get an unused 1790b57cec5SDimitry Andric // ephemeral port from the kernel and make sure we reserve it before passing it 1800b57cec5SDimitry Andric // to debugserver. 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric #if defined(__APPLE__) 1830b57cec5SDimitry Andric #define LOW_PORT (IPPORT_RESERVED) 1840b57cec5SDimitry Andric #define HIGH_PORT (IPPORT_HIFIRSTAUTO) 1850b57cec5SDimitry Andric #else 1860b57cec5SDimitry Andric #define LOW_PORT (1024u) 1870b57cec5SDimitry Andric #define HIGH_PORT (49151u) 1880b57cec5SDimitry Andric #endif 1890b57cec5SDimitry Andric 190349cc55cSDimitry Andric llvm::StringRef ProcessGDBRemote::GetPluginDescriptionStatic() { 1910b57cec5SDimitry Andric return "GDB Remote protocol based debugging plug-in."; 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric void ProcessGDBRemote::Terminate() { 1950b57cec5SDimitry Andric PluginManager::UnregisterPlugin(ProcessGDBRemote::CreateInstance); 1960b57cec5SDimitry Andric } 1970b57cec5SDimitry Andric 198bdd1243dSDimitry Andric lldb::ProcessSP ProcessGDBRemote::CreateInstance( 199bdd1243dSDimitry Andric lldb::TargetSP target_sp, ListenerSP listener_sp, 200bdd1243dSDimitry Andric const FileSpec *crash_file_path, bool can_connect) { 2010b57cec5SDimitry Andric lldb::ProcessSP process_sp; 2020b57cec5SDimitry Andric if (crash_file_path == nullptr) 203bdd1243dSDimitry Andric process_sp = std::shared_ptr<ProcessGDBRemote>( 204bdd1243dSDimitry Andric new ProcessGDBRemote(target_sp, listener_sp)); 2050b57cec5SDimitry Andric return process_sp; 2060b57cec5SDimitry Andric } 2070b57cec5SDimitry Andric 20806c3fb27SDimitry Andric void ProcessGDBRemote::DumpPluginHistory(Stream &s) { 20906c3fb27SDimitry Andric GDBRemoteCommunicationClient &gdb_comm(GetGDBRemote()); 21006c3fb27SDimitry Andric gdb_comm.DumpHistory(s); 21106c3fb27SDimitry Andric } 21206c3fb27SDimitry Andric 213fe6060f1SDimitry Andric std::chrono::seconds ProcessGDBRemote::GetPacketTimeout() { 214349cc55cSDimitry Andric return std::chrono::seconds(GetGlobalPluginProperties().GetPacketTimeout()); 215fe6060f1SDimitry Andric } 216fe6060f1SDimitry Andric 21781ad6265SDimitry Andric ArchSpec ProcessGDBRemote::GetSystemArchitecture() { 21881ad6265SDimitry Andric return m_gdb_comm.GetHostArchitecture(); 21981ad6265SDimitry Andric } 22081ad6265SDimitry Andric 2210b57cec5SDimitry Andric bool ProcessGDBRemote::CanDebug(lldb::TargetSP target_sp, 2220b57cec5SDimitry Andric bool plugin_specified_by_name) { 2230b57cec5SDimitry Andric if (plugin_specified_by_name) 2240b57cec5SDimitry Andric return true; 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric // For now we are just making sure the file exists for a given module 2270b57cec5SDimitry Andric Module *exe_module = target_sp->GetExecutableModulePointer(); 2280b57cec5SDimitry Andric if (exe_module) { 2290b57cec5SDimitry Andric ObjectFile *exe_objfile = exe_module->GetObjectFile(); 2300b57cec5SDimitry Andric // We can't debug core files... 2310b57cec5SDimitry Andric switch (exe_objfile->GetType()) { 2320b57cec5SDimitry Andric case ObjectFile::eTypeInvalid: 2330b57cec5SDimitry Andric case ObjectFile::eTypeCoreFile: 2340b57cec5SDimitry Andric case ObjectFile::eTypeDebugInfo: 2350b57cec5SDimitry Andric case ObjectFile::eTypeObjectFile: 2360b57cec5SDimitry Andric case ObjectFile::eTypeSharedLibrary: 2370b57cec5SDimitry Andric case ObjectFile::eTypeStubLibrary: 2380b57cec5SDimitry Andric case ObjectFile::eTypeJIT: 2390b57cec5SDimitry Andric return false; 2400b57cec5SDimitry Andric case ObjectFile::eTypeExecutable: 2410b57cec5SDimitry Andric case ObjectFile::eTypeDynamicLinker: 2420b57cec5SDimitry Andric case ObjectFile::eTypeUnknown: 2430b57cec5SDimitry Andric break; 2440b57cec5SDimitry Andric } 2450b57cec5SDimitry Andric return FileSystem::Instance().Exists(exe_module->GetFileSpec()); 2460b57cec5SDimitry Andric } 2470b57cec5SDimitry Andric // However, if there is no executable module, we return true since we might 2480b57cec5SDimitry Andric // be preparing to attach. 2490b57cec5SDimitry Andric return true; 2500b57cec5SDimitry Andric } 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric // ProcessGDBRemote constructor 2530b57cec5SDimitry Andric ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, 2540b57cec5SDimitry Andric ListenerSP listener_sp) 2550b57cec5SDimitry Andric : Process(target_sp, listener_sp), 256349cc55cSDimitry Andric m_debugserver_pid(LLDB_INVALID_PROCESS_ID), m_register_info_sp(nullptr), 2570b57cec5SDimitry Andric m_async_broadcaster(nullptr, "lldb.process.gdb-remote.async-broadcaster"), 2580b57cec5SDimitry Andric m_async_listener_sp( 2590b57cec5SDimitry Andric Listener::MakeListener("lldb.process.gdb-remote.async-listener")), 2600b57cec5SDimitry Andric m_async_thread_state_mutex(), m_thread_ids(), m_thread_pcs(), 2610b57cec5SDimitry Andric m_jstopinfo_sp(), m_jthreadsinfo_sp(), m_continue_c_tids(), 2620b57cec5SDimitry Andric m_continue_C_tids(), m_continue_s_tids(), m_continue_S_tids(), 2630b57cec5SDimitry Andric m_max_memory_size(0), m_remote_stub_max_memory_size(0), 2640b57cec5SDimitry Andric m_addr_to_mmap_size(), m_thread_create_bp_sp(), 26581ad6265SDimitry Andric m_waiting_for_attach(false), 2660b57cec5SDimitry Andric m_command_sp(), m_breakpoint_pc_offset(0), 26704eeddc0SDimitry Andric m_initial_tid(LLDB_INVALID_THREAD_ID), m_allow_flash_writes(false), 26804eeddc0SDimitry Andric m_erased_flash_ranges(), m_vfork_in_progress(false) { 2690b57cec5SDimitry Andric m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, 2700b57cec5SDimitry Andric "async thread should exit"); 2710b57cec5SDimitry Andric m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, 2720b57cec5SDimitry Andric "async thread continue"); 2730b57cec5SDimitry Andric m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadDidExit, 2740b57cec5SDimitry Andric "async thread did exit"); 2750b57cec5SDimitry Andric 2761fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Async); 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric const uint32_t async_event_mask = 2790b57cec5SDimitry Andric eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit; 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric if (m_async_listener_sp->StartListeningForEvents( 2820b57cec5SDimitry Andric &m_async_broadcaster, async_event_mask) != async_event_mask) { 2839dba64beSDimitry Andric LLDB_LOGF(log, 2849dba64beSDimitry Andric "ProcessGDBRemote::%s failed to listen for " 2850b57cec5SDimitry Andric "m_async_broadcaster events", 2860b57cec5SDimitry Andric __FUNCTION__); 2870b57cec5SDimitry Andric } 2880b57cec5SDimitry Andric 2890b57cec5SDimitry Andric const uint64_t timeout_seconds = 290349cc55cSDimitry Andric GetGlobalPluginProperties().GetPacketTimeout(); 2910b57cec5SDimitry Andric if (timeout_seconds > 0) 2920b57cec5SDimitry Andric m_gdb_comm.SetPacketTimeout(std::chrono::seconds(timeout_seconds)); 293480093f4SDimitry Andric 294480093f4SDimitry Andric m_use_g_packet_for_reading = 295349cc55cSDimitry Andric GetGlobalPluginProperties().GetUseGPacketForReading(); 2960b57cec5SDimitry Andric } 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric // Destructor 2990b57cec5SDimitry Andric ProcessGDBRemote::~ProcessGDBRemote() { 3000b57cec5SDimitry Andric // m_mach_process.UnregisterNotificationCallbacks (this); 3010b57cec5SDimitry Andric Clear(); 3020b57cec5SDimitry Andric // We need to call finalize on the process before destroying ourselves to 3030b57cec5SDimitry Andric // make sure all of the broadcaster cleanup goes as planned. If we destruct 3040b57cec5SDimitry Andric // this class, then Process::~Process() might have problems trying to fully 3050b57cec5SDimitry Andric // destroy the broadcaster. 306*5f757f3fSDimitry Andric Finalize(true /* destructing */); 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric // The general Finalize is going to try to destroy the process and that 3090b57cec5SDimitry Andric // SHOULD shut down the async thread. However, if we don't kill it it will 3100b57cec5SDimitry Andric // get stranded and its connection will go away so when it wakes up it will 3110b57cec5SDimitry Andric // crash. So kill it for sure here. 3120b57cec5SDimitry Andric StopAsyncThread(); 3130b57cec5SDimitry Andric KillDebugserverProcess(); 3140b57cec5SDimitry Andric } 3150b57cec5SDimitry Andric 3160b57cec5SDimitry Andric bool ProcessGDBRemote::ParsePythonTargetDefinition( 3170b57cec5SDimitry Andric const FileSpec &target_definition_fspec) { 3180b57cec5SDimitry Andric ScriptInterpreter *interpreter = 3190b57cec5SDimitry Andric GetTarget().GetDebugger().GetScriptInterpreter(); 3200b57cec5SDimitry Andric Status error; 3210b57cec5SDimitry Andric StructuredData::ObjectSP module_object_sp( 3220b57cec5SDimitry Andric interpreter->LoadPluginModule(target_definition_fspec, error)); 3230b57cec5SDimitry Andric if (module_object_sp) { 3240b57cec5SDimitry Andric StructuredData::DictionarySP target_definition_sp( 3250b57cec5SDimitry Andric interpreter->GetDynamicSettings(module_object_sp, &GetTarget(), 3260b57cec5SDimitry Andric "gdb-server-target-definition", error)); 3270b57cec5SDimitry Andric 3280b57cec5SDimitry Andric if (target_definition_sp) { 3290b57cec5SDimitry Andric StructuredData::ObjectSP target_object( 3300b57cec5SDimitry Andric target_definition_sp->GetValueForKey("host-info")); 3310b57cec5SDimitry Andric if (target_object) { 3320b57cec5SDimitry Andric if (auto host_info_dict = target_object->GetAsDictionary()) { 3330b57cec5SDimitry Andric StructuredData::ObjectSP triple_value = 3340b57cec5SDimitry Andric host_info_dict->GetValueForKey("triple"); 3350b57cec5SDimitry Andric if (auto triple_string_value = triple_value->GetAsString()) { 3365ffd83dbSDimitry Andric std::string triple_string = 3375ffd83dbSDimitry Andric std::string(triple_string_value->GetValue()); 3380b57cec5SDimitry Andric ArchSpec host_arch(triple_string.c_str()); 3390b57cec5SDimitry Andric if (!host_arch.IsCompatibleMatch(GetTarget().GetArchitecture())) { 3400b57cec5SDimitry Andric GetTarget().SetArchitecture(host_arch); 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric } 3430b57cec5SDimitry Andric } 3440b57cec5SDimitry Andric } 3450b57cec5SDimitry Andric m_breakpoint_pc_offset = 0; 3460b57cec5SDimitry Andric StructuredData::ObjectSP breakpoint_pc_offset_value = 3470b57cec5SDimitry Andric target_definition_sp->GetValueForKey("breakpoint-pc-offset"); 3480b57cec5SDimitry Andric if (breakpoint_pc_offset_value) { 3490b57cec5SDimitry Andric if (auto breakpoint_pc_int_value = 35006c3fb27SDimitry Andric breakpoint_pc_offset_value->GetAsSignedInteger()) 3510b57cec5SDimitry Andric m_breakpoint_pc_offset = breakpoint_pc_int_value->GetValue(); 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric 354e8d8bef9SDimitry Andric if (m_register_info_sp->SetRegisterInfo( 355e8d8bef9SDimitry Andric *target_definition_sp, GetTarget().GetArchitecture()) > 0) { 3560b57cec5SDimitry Andric return true; 3570b57cec5SDimitry Andric } 3580b57cec5SDimitry Andric } 3590b57cec5SDimitry Andric } 3600b57cec5SDimitry Andric return false; 3610b57cec5SDimitry Andric } 3620b57cec5SDimitry Andric 3630b57cec5SDimitry Andric static size_t SplitCommaSeparatedRegisterNumberString( 364349cc55cSDimitry Andric const llvm::StringRef &comma_separated_register_numbers, 3650b57cec5SDimitry Andric std::vector<uint32_t> ®nums, int base) { 3660b57cec5SDimitry Andric regnums.clear(); 367349cc55cSDimitry Andric for (llvm::StringRef x : llvm::split(comma_separated_register_numbers, ',')) { 368349cc55cSDimitry Andric uint32_t reg; 369349cc55cSDimitry Andric if (llvm::to_integer(x, reg, base)) 3700b57cec5SDimitry Andric regnums.push_back(reg); 3710b57cec5SDimitry Andric } 3720b57cec5SDimitry Andric return regnums.size(); 3730b57cec5SDimitry Andric } 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) { 376e8d8bef9SDimitry Andric if (!force && m_register_info_sp) 3770b57cec5SDimitry Andric return; 3780b57cec5SDimitry Andric 379e8d8bef9SDimitry Andric m_register_info_sp = std::make_shared<GDBRemoteDynamicRegisterInfo>(); 3800b57cec5SDimitry Andric 3810b57cec5SDimitry Andric // Check if qHostInfo specified a specific packet timeout for this 3820b57cec5SDimitry Andric // connection. If so then lets update our setting so the user knows what the 3830b57cec5SDimitry Andric // timeout is and can see it. 3840b57cec5SDimitry Andric const auto host_packet_timeout = m_gdb_comm.GetHostDefaultPacketTimeout(); 3850b57cec5SDimitry Andric if (host_packet_timeout > std::chrono::seconds(0)) { 386349cc55cSDimitry Andric GetGlobalPluginProperties().SetPacketTimeout(host_packet_timeout.count()); 3870b57cec5SDimitry Andric } 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric // Register info search order: 3900b57cec5SDimitry Andric // 1 - Use the target definition python file if one is specified. 3910b57cec5SDimitry Andric // 2 - If the target definition doesn't have any of the info from the 3920b57cec5SDimitry Andric // target.xml (registers) then proceed to read the target.xml. 3930b57cec5SDimitry Andric // 3 - Fall back on the qRegisterInfo packets. 39404eeddc0SDimitry Andric // 4 - Use hardcoded defaults if available. 3950b57cec5SDimitry Andric 3960b57cec5SDimitry Andric FileSpec target_definition_fspec = 397349cc55cSDimitry Andric GetGlobalPluginProperties().GetTargetDefinitionFile(); 3980b57cec5SDimitry Andric if (!FileSystem::Instance().Exists(target_definition_fspec)) { 3990b57cec5SDimitry Andric // If the filename doesn't exist, it may be a ~ not having been expanded - 4000b57cec5SDimitry Andric // try to resolve it. 4010b57cec5SDimitry Andric FileSystem::Instance().Resolve(target_definition_fspec); 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric if (target_definition_fspec) { 4040b57cec5SDimitry Andric // See if we can get register definitions from a python file 40581ad6265SDimitry Andric if (ParsePythonTargetDefinition(target_definition_fspec)) 4060b57cec5SDimitry Andric return; 40781ad6265SDimitry Andric 40881ad6265SDimitry Andric Debugger::ReportError("target description file " + 40981ad6265SDimitry Andric target_definition_fspec.GetPath() + 41081ad6265SDimitry Andric " failed to parse", 41181ad6265SDimitry Andric GetTarget().GetDebugger().GetID()); 4120b57cec5SDimitry Andric } 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andric const ArchSpec &target_arch = GetTarget().GetArchitecture(); 4150b57cec5SDimitry Andric const ArchSpec &remote_host_arch = m_gdb_comm.GetHostArchitecture(); 4160b57cec5SDimitry Andric const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture(); 4170b57cec5SDimitry Andric 4180b57cec5SDimitry Andric // Use the process' architecture instead of the host arch, if available 4190b57cec5SDimitry Andric ArchSpec arch_to_use; 4200b57cec5SDimitry Andric if (remote_process_arch.IsValid()) 4210b57cec5SDimitry Andric arch_to_use = remote_process_arch; 4220b57cec5SDimitry Andric else 4230b57cec5SDimitry Andric arch_to_use = remote_host_arch; 4240b57cec5SDimitry Andric 4250b57cec5SDimitry Andric if (!arch_to_use.IsValid()) 4260b57cec5SDimitry Andric arch_to_use = target_arch; 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric if (GetGDBServerRegisterInfo(arch_to_use)) 4290b57cec5SDimitry Andric return; 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric char packet[128]; 432349cc55cSDimitry Andric std::vector<DynamicRegisterInfo::Register> registers; 4330b57cec5SDimitry Andric uint32_t reg_num = 0; 4340b57cec5SDimitry Andric for (StringExtractorGDBRemote::ResponseType response_type = 4350b57cec5SDimitry Andric StringExtractorGDBRemote::eResponse; 4360b57cec5SDimitry Andric response_type == StringExtractorGDBRemote::eResponse; ++reg_num) { 4370b57cec5SDimitry Andric const int packet_len = 4380b57cec5SDimitry Andric ::snprintf(packet, sizeof(packet), "qRegisterInfo%x", reg_num); 4390b57cec5SDimitry Andric assert(packet_len < (int)sizeof(packet)); 4400b57cec5SDimitry Andric UNUSED_IF_ASSERT_DISABLED(packet_len); 4410b57cec5SDimitry Andric StringExtractorGDBRemote response; 442fe6060f1SDimitry Andric if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response) == 4430b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult::Success) { 4440b57cec5SDimitry Andric response_type = response.GetResponseType(); 4450b57cec5SDimitry Andric if (response_type == StringExtractorGDBRemote::eResponse) { 4460b57cec5SDimitry Andric llvm::StringRef name; 4470b57cec5SDimitry Andric llvm::StringRef value; 448349cc55cSDimitry Andric DynamicRegisterInfo::Register reg_info; 4490b57cec5SDimitry Andric 4500b57cec5SDimitry Andric while (response.GetNameColonValue(name, value)) { 4510b57cec5SDimitry Andric if (name.equals("name")) { 452349cc55cSDimitry Andric reg_info.name.SetString(value); 4530b57cec5SDimitry Andric } else if (name.equals("alt-name")) { 454349cc55cSDimitry Andric reg_info.alt_name.SetString(value); 4550b57cec5SDimitry Andric } else if (name.equals("bitsize")) { 456349cc55cSDimitry Andric if (!value.getAsInteger(0, reg_info.byte_size)) 4570b57cec5SDimitry Andric reg_info.byte_size /= CHAR_BIT; 4580b57cec5SDimitry Andric } else if (name.equals("offset")) { 459349cc55cSDimitry Andric value.getAsInteger(0, reg_info.byte_offset); 4600b57cec5SDimitry Andric } else if (name.equals("encoding")) { 4610b57cec5SDimitry Andric const Encoding encoding = Args::StringToEncoding(value); 4620b57cec5SDimitry Andric if (encoding != eEncodingInvalid) 4630b57cec5SDimitry Andric reg_info.encoding = encoding; 4640b57cec5SDimitry Andric } else if (name.equals("format")) { 465349cc55cSDimitry Andric if (!OptionArgParser::ToFormat(value.str().c_str(), reg_info.format, nullptr) 4660b57cec5SDimitry Andric .Success()) 4670b57cec5SDimitry Andric reg_info.format = 4680b57cec5SDimitry Andric llvm::StringSwitch<Format>(value) 4690b57cec5SDimitry Andric .Case("binary", eFormatBinary) 4700b57cec5SDimitry Andric .Case("decimal", eFormatDecimal) 4710b57cec5SDimitry Andric .Case("hex", eFormatHex) 4720b57cec5SDimitry Andric .Case("float", eFormatFloat) 4730b57cec5SDimitry Andric .Case("vector-sint8", eFormatVectorOfSInt8) 4740b57cec5SDimitry Andric .Case("vector-uint8", eFormatVectorOfUInt8) 4750b57cec5SDimitry Andric .Case("vector-sint16", eFormatVectorOfSInt16) 4760b57cec5SDimitry Andric .Case("vector-uint16", eFormatVectorOfUInt16) 4770b57cec5SDimitry Andric .Case("vector-sint32", eFormatVectorOfSInt32) 4780b57cec5SDimitry Andric .Case("vector-uint32", eFormatVectorOfUInt32) 4790b57cec5SDimitry Andric .Case("vector-float32", eFormatVectorOfFloat32) 4800b57cec5SDimitry Andric .Case("vector-uint64", eFormatVectorOfUInt64) 4810b57cec5SDimitry Andric .Case("vector-uint128", eFormatVectorOfUInt128) 4820b57cec5SDimitry Andric .Default(eFormatInvalid); 4830b57cec5SDimitry Andric } else if (name.equals("set")) { 484349cc55cSDimitry Andric reg_info.set_name.SetString(value); 4850b57cec5SDimitry Andric } else if (name.equals("gcc") || name.equals("ehframe")) { 486349cc55cSDimitry Andric value.getAsInteger(0, reg_info.regnum_ehframe); 4870b57cec5SDimitry Andric } else if (name.equals("dwarf")) { 488349cc55cSDimitry Andric value.getAsInteger(0, reg_info.regnum_dwarf); 4890b57cec5SDimitry Andric } else if (name.equals("generic")) { 490349cc55cSDimitry Andric reg_info.regnum_generic = Args::StringToGenericRegister(value); 4910b57cec5SDimitry Andric } else if (name.equals("container-regs")) { 492349cc55cSDimitry Andric SplitCommaSeparatedRegisterNumberString(value, reg_info.value_regs, 16); 4930b57cec5SDimitry Andric } else if (name.equals("invalidate-regs")) { 494349cc55cSDimitry Andric SplitCommaSeparatedRegisterNumberString(value, reg_info.invalidate_regs, 16); 4950b57cec5SDimitry Andric } 4960b57cec5SDimitry Andric } 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric assert(reg_info.byte_size != 0); 499349cc55cSDimitry Andric registers.push_back(reg_info); 5000b57cec5SDimitry Andric } else { 5010b57cec5SDimitry Andric break; // ensure exit before reg_num is incremented 5020b57cec5SDimitry Andric } 5030b57cec5SDimitry Andric } else { 5040b57cec5SDimitry Andric break; 5050b57cec5SDimitry Andric } 5060b57cec5SDimitry Andric } 5070b57cec5SDimitry Andric 50804eeddc0SDimitry Andric if (registers.empty()) 50904eeddc0SDimitry Andric registers = GetFallbackRegisters(arch_to_use); 51004eeddc0SDimitry Andric 511349cc55cSDimitry Andric AddRemoteRegisters(registers, arch_to_use); 5120b57cec5SDimitry Andric } 5130b57cec5SDimitry Andric 514bdd1243dSDimitry Andric Status ProcessGDBRemote::DoWillLaunch(lldb_private::Module *module) { 5150b57cec5SDimitry Andric return WillLaunchOrAttach(); 5160b57cec5SDimitry Andric } 5170b57cec5SDimitry Andric 518bdd1243dSDimitry Andric Status ProcessGDBRemote::DoWillAttachToProcessWithID(lldb::pid_t pid) { 5190b57cec5SDimitry Andric return WillLaunchOrAttach(); 5200b57cec5SDimitry Andric } 5210b57cec5SDimitry Andric 522bdd1243dSDimitry Andric Status ProcessGDBRemote::DoWillAttachToProcessWithName(const char *process_name, 5230b57cec5SDimitry Andric bool wait_for_launch) { 5240b57cec5SDimitry Andric return WillLaunchOrAttach(); 5250b57cec5SDimitry Andric } 5260b57cec5SDimitry Andric 5275ffd83dbSDimitry Andric Status ProcessGDBRemote::DoConnectRemote(llvm::StringRef remote_url) { 52804eeddc0SDimitry Andric Log *log = GetLog(GDBRLog::Process); 5290eae32dcSDimitry Andric 5300b57cec5SDimitry Andric Status error(WillLaunchOrAttach()); 5310b57cec5SDimitry Andric if (error.Fail()) 5320b57cec5SDimitry Andric return error; 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric error = ConnectToDebugserver(remote_url); 5350b57cec5SDimitry Andric if (error.Fail()) 5360b57cec5SDimitry Andric return error; 5370eae32dcSDimitry Andric 5380b57cec5SDimitry Andric StartAsyncThread(); 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID(); 5410b57cec5SDimitry Andric if (pid == LLDB_INVALID_PROCESS_ID) { 5420b57cec5SDimitry Andric // We don't have a valid process ID, so note that we are connected and 5430b57cec5SDimitry Andric // could now request to launch or attach, or get remote process listings... 5440b57cec5SDimitry Andric SetPrivateState(eStateConnected); 5450b57cec5SDimitry Andric } else { 5460b57cec5SDimitry Andric // We have a valid process 5470b57cec5SDimitry Andric SetID(pid); 5480b57cec5SDimitry Andric GetThreadList(); 5490b57cec5SDimitry Andric StringExtractorGDBRemote response; 5500b57cec5SDimitry Andric if (m_gdb_comm.GetStopReply(response)) { 5510b57cec5SDimitry Andric SetLastStopPacket(response); 5520b57cec5SDimitry Andric 5530b57cec5SDimitry Andric Target &target = GetTarget(); 5540b57cec5SDimitry Andric if (!target.GetArchitecture().IsValid()) { 5550b57cec5SDimitry Andric if (m_gdb_comm.GetProcessArchitecture().IsValid()) { 5560b57cec5SDimitry Andric target.SetArchitecture(m_gdb_comm.GetProcessArchitecture()); 5570b57cec5SDimitry Andric } else { 5580b57cec5SDimitry Andric if (m_gdb_comm.GetHostArchitecture().IsValid()) { 5590b57cec5SDimitry Andric target.SetArchitecture(m_gdb_comm.GetHostArchitecture()); 5600b57cec5SDimitry Andric } 5610b57cec5SDimitry Andric } 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric 5640b57cec5SDimitry Andric const StateType state = SetThreadStopInfo(response); 5650b57cec5SDimitry Andric if (state != eStateInvalid) { 5660b57cec5SDimitry Andric SetPrivateState(state); 5670b57cec5SDimitry Andric } else 5680b57cec5SDimitry Andric error.SetErrorStringWithFormat( 5690b57cec5SDimitry Andric "Process %" PRIu64 " was reported after connecting to " 5700b57cec5SDimitry Andric "'%s', but state was not stopped: %s", 5710b57cec5SDimitry Andric pid, remote_url.str().c_str(), StateAsCString(state)); 5720b57cec5SDimitry Andric } else 5730b57cec5SDimitry Andric error.SetErrorStringWithFormat("Process %" PRIu64 5740b57cec5SDimitry Andric " was reported after connecting to '%s', " 5750b57cec5SDimitry Andric "but no stop reply packet was received", 5760b57cec5SDimitry Andric pid, remote_url.str().c_str()); 5770b57cec5SDimitry Andric } 5780b57cec5SDimitry Andric 5799dba64beSDimitry Andric LLDB_LOGF(log, 5809dba64beSDimitry Andric "ProcessGDBRemote::%s pid %" PRIu64 5810b57cec5SDimitry Andric ": normalizing target architecture initial triple: %s " 5820b57cec5SDimitry Andric "(GetTarget().GetArchitecture().IsValid() %s, " 5830b57cec5SDimitry Andric "m_gdb_comm.GetHostArchitecture().IsValid(): %s)", 5840b57cec5SDimitry Andric __FUNCTION__, GetID(), 5850b57cec5SDimitry Andric GetTarget().GetArchitecture().GetTriple().getTriple().c_str(), 5860b57cec5SDimitry Andric GetTarget().GetArchitecture().IsValid() ? "true" : "false", 5870b57cec5SDimitry Andric m_gdb_comm.GetHostArchitecture().IsValid() ? "true" : "false"); 5880b57cec5SDimitry Andric 5890b57cec5SDimitry Andric if (error.Success() && !GetTarget().GetArchitecture().IsValid() && 5900b57cec5SDimitry Andric m_gdb_comm.GetHostArchitecture().IsValid()) { 5910b57cec5SDimitry Andric // Prefer the *process'* architecture over that of the *host*, if 5920b57cec5SDimitry Andric // available. 5930b57cec5SDimitry Andric if (m_gdb_comm.GetProcessArchitecture().IsValid()) 5940b57cec5SDimitry Andric GetTarget().SetArchitecture(m_gdb_comm.GetProcessArchitecture()); 5950b57cec5SDimitry Andric else 5960b57cec5SDimitry Andric GetTarget().SetArchitecture(m_gdb_comm.GetHostArchitecture()); 5970b57cec5SDimitry Andric } 5980b57cec5SDimitry Andric 5999dba64beSDimitry Andric LLDB_LOGF(log, 6009dba64beSDimitry Andric "ProcessGDBRemote::%s pid %" PRIu64 6010b57cec5SDimitry Andric ": normalized target architecture triple: %s", 6020b57cec5SDimitry Andric __FUNCTION__, GetID(), 6030b57cec5SDimitry Andric GetTarget().GetArchitecture().GetTriple().getTriple().c_str()); 6040b57cec5SDimitry Andric 6050b57cec5SDimitry Andric return error; 6060b57cec5SDimitry Andric } 6070b57cec5SDimitry Andric 6080b57cec5SDimitry Andric Status ProcessGDBRemote::WillLaunchOrAttach() { 6090b57cec5SDimitry Andric Status error; 6100b57cec5SDimitry Andric m_stdio_communication.Clear(); 6110b57cec5SDimitry Andric return error; 6120b57cec5SDimitry Andric } 6130b57cec5SDimitry Andric 6140b57cec5SDimitry Andric // Process Control 6150b57cec5SDimitry Andric Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module, 6160b57cec5SDimitry Andric ProcessLaunchInfo &launch_info) { 6171fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 6180b57cec5SDimitry Andric Status error; 6190b57cec5SDimitry Andric 6209dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::%s() entered", __FUNCTION__); 6210b57cec5SDimitry Andric 6220b57cec5SDimitry Andric uint32_t launch_flags = launch_info.GetFlags().Get(); 6230b57cec5SDimitry Andric FileSpec stdin_file_spec{}; 6240b57cec5SDimitry Andric FileSpec stdout_file_spec{}; 6250b57cec5SDimitry Andric FileSpec stderr_file_spec{}; 6260b57cec5SDimitry Andric FileSpec working_dir = launch_info.GetWorkingDirectory(); 6270b57cec5SDimitry Andric 6280b57cec5SDimitry Andric const FileAction *file_action; 6290b57cec5SDimitry Andric file_action = launch_info.GetFileActionForFD(STDIN_FILENO); 6300b57cec5SDimitry Andric if (file_action) { 6310b57cec5SDimitry Andric if (file_action->GetAction() == FileAction::eFileActionOpen) 6320b57cec5SDimitry Andric stdin_file_spec = file_action->GetFileSpec(); 6330b57cec5SDimitry Andric } 6340b57cec5SDimitry Andric file_action = launch_info.GetFileActionForFD(STDOUT_FILENO); 6350b57cec5SDimitry Andric if (file_action) { 6360b57cec5SDimitry Andric if (file_action->GetAction() == FileAction::eFileActionOpen) 6370b57cec5SDimitry Andric stdout_file_spec = file_action->GetFileSpec(); 6380b57cec5SDimitry Andric } 6390b57cec5SDimitry Andric file_action = launch_info.GetFileActionForFD(STDERR_FILENO); 6400b57cec5SDimitry Andric if (file_action) { 6410b57cec5SDimitry Andric if (file_action->GetAction() == FileAction::eFileActionOpen) 6420b57cec5SDimitry Andric stderr_file_spec = file_action->GetFileSpec(); 6430b57cec5SDimitry Andric } 6440b57cec5SDimitry Andric 6450b57cec5SDimitry Andric if (log) { 6460b57cec5SDimitry Andric if (stdin_file_spec || stdout_file_spec || stderr_file_spec) 6479dba64beSDimitry Andric LLDB_LOGF(log, 6489dba64beSDimitry Andric "ProcessGDBRemote::%s provided with STDIO paths via " 6490b57cec5SDimitry Andric "launch_info: stdin=%s, stdout=%s, stderr=%s", 6500b57cec5SDimitry Andric __FUNCTION__, 651bdd1243dSDimitry Andric stdin_file_spec ? stdin_file_spec.GetPath().c_str() : "<null>", 652bdd1243dSDimitry Andric stdout_file_spec ? stdout_file_spec.GetPath().c_str() : "<null>", 653bdd1243dSDimitry Andric stderr_file_spec ? stderr_file_spec.GetPath().c_str() : "<null>"); 6540b57cec5SDimitry Andric else 6559dba64beSDimitry Andric LLDB_LOGF(log, 6569dba64beSDimitry Andric "ProcessGDBRemote::%s no STDIO paths given via launch_info", 6570b57cec5SDimitry Andric __FUNCTION__); 6580b57cec5SDimitry Andric } 6590b57cec5SDimitry Andric 6600b57cec5SDimitry Andric const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0; 6610b57cec5SDimitry Andric if (stdin_file_spec || disable_stdio) { 6620b57cec5SDimitry Andric // the inferior will be reading stdin from the specified file or stdio is 6630b57cec5SDimitry Andric // completely disabled 6640b57cec5SDimitry Andric m_stdin_forward = false; 6650b57cec5SDimitry Andric } else { 6660b57cec5SDimitry Andric m_stdin_forward = true; 6670b57cec5SDimitry Andric } 6680b57cec5SDimitry Andric 6690b57cec5SDimitry Andric // ::LogSetBitMask (GDBR_LOG_DEFAULT); 6700b57cec5SDimitry Andric // ::LogSetOptions (LLDB_LOG_OPTION_THREADSAFE | 6710b57cec5SDimitry Andric // LLDB_LOG_OPTION_PREPEND_TIMESTAMP | 6720b57cec5SDimitry Andric // LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD); 6730b57cec5SDimitry Andric // ::LogSetLogFile ("/dev/stdout"); 6740b57cec5SDimitry Andric 6750b57cec5SDimitry Andric error = EstablishConnectionIfNeeded(launch_info); 6760b57cec5SDimitry Andric if (error.Success()) { 6770b57cec5SDimitry Andric PseudoTerminal pty; 6780b57cec5SDimitry Andric const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0; 6790b57cec5SDimitry Andric 6800b57cec5SDimitry Andric PlatformSP platform_sp(GetTarget().GetPlatform()); 6810b57cec5SDimitry Andric if (disable_stdio) { 6820b57cec5SDimitry Andric // set to /dev/null unless redirected to a file above 6830b57cec5SDimitry Andric if (!stdin_file_spec) 6840b57cec5SDimitry Andric stdin_file_spec.SetFile(FileSystem::DEV_NULL, 6850b57cec5SDimitry Andric FileSpec::Style::native); 6860b57cec5SDimitry Andric if (!stdout_file_spec) 6870b57cec5SDimitry Andric stdout_file_spec.SetFile(FileSystem::DEV_NULL, 6880b57cec5SDimitry Andric FileSpec::Style::native); 6890b57cec5SDimitry Andric if (!stderr_file_spec) 6900b57cec5SDimitry Andric stderr_file_spec.SetFile(FileSystem::DEV_NULL, 6910b57cec5SDimitry Andric FileSpec::Style::native); 6920b57cec5SDimitry Andric } else if (platform_sp && platform_sp->IsHost()) { 6930b57cec5SDimitry Andric // If the debugserver is local and we aren't disabling STDIO, lets use 6940b57cec5SDimitry Andric // a pseudo terminal to instead of relying on the 'O' packets for stdio 6950b57cec5SDimitry Andric // since 'O' packets can really slow down debugging if the inferior 6960b57cec5SDimitry Andric // does a lot of output. 6970b57cec5SDimitry Andric if ((!stdin_file_spec || !stdout_file_spec || !stderr_file_spec) && 698e8d8bef9SDimitry Andric !errorToBool(pty.OpenFirstAvailablePrimary(O_RDWR | O_NOCTTY))) { 699e8d8bef9SDimitry Andric FileSpec secondary_name(pty.GetSecondaryName()); 7000b57cec5SDimitry Andric 7010b57cec5SDimitry Andric if (!stdin_file_spec) 7025ffd83dbSDimitry Andric stdin_file_spec = secondary_name; 7030b57cec5SDimitry Andric 7040b57cec5SDimitry Andric if (!stdout_file_spec) 7055ffd83dbSDimitry Andric stdout_file_spec = secondary_name; 7060b57cec5SDimitry Andric 7070b57cec5SDimitry Andric if (!stderr_file_spec) 7085ffd83dbSDimitry Andric stderr_file_spec = secondary_name; 7090b57cec5SDimitry Andric } 7109dba64beSDimitry Andric LLDB_LOGF( 7119dba64beSDimitry Andric log, 7120b57cec5SDimitry Andric "ProcessGDBRemote::%s adjusted STDIO paths for local platform " 7135ffd83dbSDimitry Andric "(IsHost() is true) using secondary: stdin=%s, stdout=%s, " 7145ffd83dbSDimitry Andric "stderr=%s", 7150b57cec5SDimitry Andric __FUNCTION__, 716bdd1243dSDimitry Andric stdin_file_spec ? stdin_file_spec.GetPath().c_str() : "<null>", 717bdd1243dSDimitry Andric stdout_file_spec ? stdout_file_spec.GetPath().c_str() : "<null>", 718bdd1243dSDimitry Andric stderr_file_spec ? stderr_file_spec.GetPath().c_str() : "<null>"); 7190b57cec5SDimitry Andric } 7200b57cec5SDimitry Andric 7219dba64beSDimitry Andric LLDB_LOGF(log, 7229dba64beSDimitry Andric "ProcessGDBRemote::%s final STDIO paths after all " 7230b57cec5SDimitry Andric "adjustments: stdin=%s, stdout=%s, stderr=%s", 7240b57cec5SDimitry Andric __FUNCTION__, 725bdd1243dSDimitry Andric stdin_file_spec ? stdin_file_spec.GetPath().c_str() : "<null>", 726bdd1243dSDimitry Andric stdout_file_spec ? stdout_file_spec.GetPath().c_str() : "<null>", 727bdd1243dSDimitry Andric stderr_file_spec ? stderr_file_spec.GetPath().c_str() : "<null>"); 7280b57cec5SDimitry Andric 7290b57cec5SDimitry Andric if (stdin_file_spec) 7300b57cec5SDimitry Andric m_gdb_comm.SetSTDIN(stdin_file_spec); 7310b57cec5SDimitry Andric if (stdout_file_spec) 7320b57cec5SDimitry Andric m_gdb_comm.SetSTDOUT(stdout_file_spec); 7330b57cec5SDimitry Andric if (stderr_file_spec) 7340b57cec5SDimitry Andric m_gdb_comm.SetSTDERR(stderr_file_spec); 7350b57cec5SDimitry Andric 7360b57cec5SDimitry Andric m_gdb_comm.SetDisableASLR(launch_flags & eLaunchFlagDisableASLR); 7370b57cec5SDimitry Andric m_gdb_comm.SetDetachOnError(launch_flags & eLaunchFlagDetachOnError); 7380b57cec5SDimitry Andric 7390b57cec5SDimitry Andric m_gdb_comm.SendLaunchArchPacket( 7400b57cec5SDimitry Andric GetTarget().GetArchitecture().GetArchitectureName()); 7410b57cec5SDimitry Andric 7420b57cec5SDimitry Andric const char *launch_event_data = launch_info.GetLaunchEventData(); 7430b57cec5SDimitry Andric if (launch_event_data != nullptr && *launch_event_data != '\0') 7440b57cec5SDimitry Andric m_gdb_comm.SendLaunchEventDataPacket(launch_event_data); 7450b57cec5SDimitry Andric 7460b57cec5SDimitry Andric if (working_dir) { 7470b57cec5SDimitry Andric m_gdb_comm.SetWorkingDir(working_dir); 7480b57cec5SDimitry Andric } 7490b57cec5SDimitry Andric 7500b57cec5SDimitry Andric // Send the environment and the program + arguments after we connect 7510b57cec5SDimitry Andric m_gdb_comm.SendEnvironment(launch_info.GetEnvironment()); 7520b57cec5SDimitry Andric 7530b57cec5SDimitry Andric { 7540b57cec5SDimitry Andric // Scope for the scoped timeout object 7550b57cec5SDimitry Andric GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_comm, 7560b57cec5SDimitry Andric std::chrono::seconds(10)); 7570b57cec5SDimitry Andric 758bdd1243dSDimitry Andric // Since we can't send argv0 separate from the executable path, we need to 759bdd1243dSDimitry Andric // make sure to use the actual executable path found in the launch_info... 760bdd1243dSDimitry Andric Args args = launch_info.GetArguments(); 761bdd1243dSDimitry Andric if (FileSpec exe_file = launch_info.GetExecutableFile()) 762bdd1243dSDimitry Andric args.ReplaceArgumentAtIndex(0, exe_file.GetPath(false)); 763bdd1243dSDimitry Andric if (llvm::Error err = m_gdb_comm.LaunchProcess(args)) { 764bdd1243dSDimitry Andric error.SetErrorStringWithFormatv("Cannot launch '{0}': {1}", 765bdd1243dSDimitry Andric args.GetArgumentAtIndex(0), 766bdd1243dSDimitry Andric llvm::fmt_consume(std::move(err))); 767bdd1243dSDimitry Andric } else { 7680b57cec5SDimitry Andric SetID(m_gdb_comm.GetCurrentProcessID()); 7690b57cec5SDimitry Andric } 7700b57cec5SDimitry Andric } 7710b57cec5SDimitry Andric 7720b57cec5SDimitry Andric if (GetID() == LLDB_INVALID_PROCESS_ID) { 7739dba64beSDimitry Andric LLDB_LOGF(log, "failed to connect to debugserver: %s", 7740b57cec5SDimitry Andric error.AsCString()); 7750b57cec5SDimitry Andric KillDebugserverProcess(); 7760b57cec5SDimitry Andric return error; 7770b57cec5SDimitry Andric } 7780b57cec5SDimitry Andric 7790b57cec5SDimitry Andric StringExtractorGDBRemote response; 7800b57cec5SDimitry Andric if (m_gdb_comm.GetStopReply(response)) { 7810b57cec5SDimitry Andric SetLastStopPacket(response); 7820b57cec5SDimitry Andric 7830b57cec5SDimitry Andric const ArchSpec &process_arch = m_gdb_comm.GetProcessArchitecture(); 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric if (process_arch.IsValid()) { 7860b57cec5SDimitry Andric GetTarget().MergeArchitecture(process_arch); 7870b57cec5SDimitry Andric } else { 7880b57cec5SDimitry Andric const ArchSpec &host_arch = m_gdb_comm.GetHostArchitecture(); 7890b57cec5SDimitry Andric if (host_arch.IsValid()) 7900b57cec5SDimitry Andric GetTarget().MergeArchitecture(host_arch); 7910b57cec5SDimitry Andric } 7920b57cec5SDimitry Andric 7930b57cec5SDimitry Andric SetPrivateState(SetThreadStopInfo(response)); 7940b57cec5SDimitry Andric 7950b57cec5SDimitry Andric if (!disable_stdio) { 7965ffd83dbSDimitry Andric if (pty.GetPrimaryFileDescriptor() != PseudoTerminal::invalid_fd) 7975ffd83dbSDimitry Andric SetSTDIOFileDescriptor(pty.ReleasePrimaryFileDescriptor()); 7980b57cec5SDimitry Andric } 7990b57cec5SDimitry Andric } 8000b57cec5SDimitry Andric } else { 8019dba64beSDimitry Andric LLDB_LOGF(log, "failed to connect to debugserver: %s", error.AsCString()); 8020b57cec5SDimitry Andric } 8030b57cec5SDimitry Andric return error; 8040b57cec5SDimitry Andric } 8050b57cec5SDimitry Andric 8060b57cec5SDimitry Andric Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) { 8070b57cec5SDimitry Andric Status error; 8080b57cec5SDimitry Andric // Only connect if we have a valid connect URL 8091fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 8100b57cec5SDimitry Andric 8110b57cec5SDimitry Andric if (!connect_url.empty()) { 8129dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::%s Connecting to %s", __FUNCTION__, 8130b57cec5SDimitry Andric connect_url.str().c_str()); 8140b57cec5SDimitry Andric std::unique_ptr<ConnectionFileDescriptor> conn_up( 8150b57cec5SDimitry Andric new ConnectionFileDescriptor()); 8160b57cec5SDimitry Andric if (conn_up) { 8170b57cec5SDimitry Andric const uint32_t max_retry_count = 50; 8180b57cec5SDimitry Andric uint32_t retry_count = 0; 8190b57cec5SDimitry Andric while (!m_gdb_comm.IsConnected()) { 8200b57cec5SDimitry Andric if (conn_up->Connect(connect_url, &error) == eConnectionStatusSuccess) { 8215ffd83dbSDimitry Andric m_gdb_comm.SetConnection(std::move(conn_up)); 8220b57cec5SDimitry Andric break; 8230b57cec5SDimitry Andric } 8240b57cec5SDimitry Andric 8250b57cec5SDimitry Andric retry_count++; 8260b57cec5SDimitry Andric 8270b57cec5SDimitry Andric if (retry_count >= max_retry_count) 8280b57cec5SDimitry Andric break; 8290b57cec5SDimitry Andric 8309dba64beSDimitry Andric std::this_thread::sleep_for(std::chrono::milliseconds(100)); 8310b57cec5SDimitry Andric } 8320b57cec5SDimitry Andric } 8330b57cec5SDimitry Andric } 8340b57cec5SDimitry Andric 8350b57cec5SDimitry Andric if (!m_gdb_comm.IsConnected()) { 8360b57cec5SDimitry Andric if (error.Success()) 8370b57cec5SDimitry Andric error.SetErrorString("not connected to remote gdb server"); 8380b57cec5SDimitry Andric return error; 8390b57cec5SDimitry Andric } 8400b57cec5SDimitry Andric 8410b57cec5SDimitry Andric // We always seem to be able to open a connection to a local port so we need 8420b57cec5SDimitry Andric // to make sure we can then send data to it. If we can't then we aren't 8430b57cec5SDimitry Andric // actually connected to anything, so try and do the handshake with the 8440b57cec5SDimitry Andric // remote GDB server and make sure that goes alright. 8450b57cec5SDimitry Andric if (!m_gdb_comm.HandshakeWithServer(&error)) { 8460b57cec5SDimitry Andric m_gdb_comm.Disconnect(); 8470b57cec5SDimitry Andric if (error.Success()) 8480b57cec5SDimitry Andric error.SetErrorString("not connected to remote gdb server"); 8490b57cec5SDimitry Andric return error; 8500b57cec5SDimitry Andric } 8510b57cec5SDimitry Andric 8520b57cec5SDimitry Andric m_gdb_comm.GetEchoSupported(); 8530b57cec5SDimitry Andric m_gdb_comm.GetThreadSuffixSupported(); 8540b57cec5SDimitry Andric m_gdb_comm.GetListThreadsInStopReplySupported(); 8550b57cec5SDimitry Andric m_gdb_comm.GetHostInfo(); 8560b57cec5SDimitry Andric m_gdb_comm.GetVContSupported('c'); 8570b57cec5SDimitry Andric m_gdb_comm.GetVAttachOrWaitSupported(); 8580b57cec5SDimitry Andric m_gdb_comm.EnableErrorStringInPacket(); 8590b57cec5SDimitry Andric 86081ad6265SDimitry Andric // First dispatch any commands from the platform: 86181ad6265SDimitry Andric auto handle_cmds = [&] (const Args &args) -> void { 86281ad6265SDimitry Andric for (const Args::ArgEntry &entry : args) { 8630b57cec5SDimitry Andric StringExtractorGDBRemote response; 8640b57cec5SDimitry Andric m_gdb_comm.SendPacketAndWaitForResponse( 86581ad6265SDimitry Andric entry.c_str(), response); 8660b57cec5SDimitry Andric } 86781ad6265SDimitry Andric }; 86881ad6265SDimitry Andric 86981ad6265SDimitry Andric PlatformSP platform_sp = GetTarget().GetPlatform(); 87081ad6265SDimitry Andric if (platform_sp) { 87181ad6265SDimitry Andric handle_cmds(platform_sp->GetExtraStartupCommands()); 87281ad6265SDimitry Andric } 87381ad6265SDimitry Andric 87481ad6265SDimitry Andric // Then dispatch any process commands: 87581ad6265SDimitry Andric handle_cmds(GetExtraStartupCommands()); 87681ad6265SDimitry Andric 8770b57cec5SDimitry Andric return error; 8780b57cec5SDimitry Andric } 8790b57cec5SDimitry Andric 8800b57cec5SDimitry Andric void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { 8811fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 8820b57cec5SDimitry Andric BuildDynamicRegisterInfo(false); 8830b57cec5SDimitry Andric 8845ffd83dbSDimitry Andric // See if the GDB server supports qHostInfo or qProcessInfo packets. Prefer 8855ffd83dbSDimitry Andric // qProcessInfo as it will be more specific to our process. 8860b57cec5SDimitry Andric 8870b57cec5SDimitry Andric const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture(); 8880b57cec5SDimitry Andric if (remote_process_arch.IsValid()) { 8890b57cec5SDimitry Andric process_arch = remote_process_arch; 8905ffd83dbSDimitry Andric LLDB_LOG(log, "gdb-remote had process architecture, using {0} {1}", 8915ffd83dbSDimitry Andric process_arch.GetArchitectureName(), 8925ffd83dbSDimitry Andric process_arch.GetTriple().getTriple()); 8930b57cec5SDimitry Andric } else { 8940b57cec5SDimitry Andric process_arch = m_gdb_comm.GetHostArchitecture(); 8955ffd83dbSDimitry Andric LLDB_LOG(log, 8965ffd83dbSDimitry Andric "gdb-remote did not have process architecture, using gdb-remote " 8975ffd83dbSDimitry Andric "host architecture {0} {1}", 8985ffd83dbSDimitry Andric process_arch.GetArchitectureName(), 8995ffd83dbSDimitry Andric process_arch.GetTriple().getTriple()); 9000b57cec5SDimitry Andric } 9010b57cec5SDimitry Andric 902*5f757f3fSDimitry Andric AddressableBits addressable_bits = m_gdb_comm.GetAddressableBits(); 903*5f757f3fSDimitry Andric addressable_bits.SetProcessMasks(*this); 904fe6060f1SDimitry Andric 9050b57cec5SDimitry Andric if (process_arch.IsValid()) { 9060b57cec5SDimitry Andric const ArchSpec &target_arch = GetTarget().GetArchitecture(); 9070b57cec5SDimitry Andric if (target_arch.IsValid()) { 9085ffd83dbSDimitry Andric LLDB_LOG(log, "analyzing target arch, currently {0} {1}", 9095ffd83dbSDimitry Andric target_arch.GetArchitectureName(), 9105ffd83dbSDimitry Andric target_arch.GetTriple().getTriple()); 9110b57cec5SDimitry Andric 9120b57cec5SDimitry Andric // If the remote host is ARM and we have apple as the vendor, then 9130b57cec5SDimitry Andric // ARM executables and shared libraries can have mixed ARM 9140b57cec5SDimitry Andric // architectures. 9150b57cec5SDimitry Andric // You can have an armv6 executable, and if the host is armv7, then the 9160b57cec5SDimitry Andric // system will load the best possible architecture for all shared 9170b57cec5SDimitry Andric // libraries it has, so we really need to take the remote host 9180b57cec5SDimitry Andric // architecture as our defacto architecture in this case. 9190b57cec5SDimitry Andric 9200b57cec5SDimitry Andric if ((process_arch.GetMachine() == llvm::Triple::arm || 9210b57cec5SDimitry Andric process_arch.GetMachine() == llvm::Triple::thumb) && 9220b57cec5SDimitry Andric process_arch.GetTriple().getVendor() == llvm::Triple::Apple) { 9230b57cec5SDimitry Andric GetTarget().SetArchitecture(process_arch); 9245ffd83dbSDimitry Andric LLDB_LOG(log, 9255ffd83dbSDimitry Andric "remote process is ARM/Apple, " 9265ffd83dbSDimitry Andric "setting target arch to {0} {1}", 9275ffd83dbSDimitry Andric process_arch.GetArchitectureName(), 9285ffd83dbSDimitry Andric process_arch.GetTriple().getTriple()); 9290b57cec5SDimitry Andric } else { 9300b57cec5SDimitry Andric // Fill in what is missing in the triple 9310b57cec5SDimitry Andric const llvm::Triple &remote_triple = process_arch.GetTriple(); 9320b57cec5SDimitry Andric llvm::Triple new_target_triple = target_arch.GetTriple(); 9330b57cec5SDimitry Andric if (new_target_triple.getVendorName().size() == 0) { 9340b57cec5SDimitry Andric new_target_triple.setVendor(remote_triple.getVendor()); 9350b57cec5SDimitry Andric 9360b57cec5SDimitry Andric if (new_target_triple.getOSName().size() == 0) { 9370b57cec5SDimitry Andric new_target_triple.setOS(remote_triple.getOS()); 9380b57cec5SDimitry Andric 9390b57cec5SDimitry Andric if (new_target_triple.getEnvironmentName().size() == 0) 9405ffd83dbSDimitry Andric new_target_triple.setEnvironment(remote_triple.getEnvironment()); 9410b57cec5SDimitry Andric } 9420b57cec5SDimitry Andric 9430b57cec5SDimitry Andric ArchSpec new_target_arch = target_arch; 9440b57cec5SDimitry Andric new_target_arch.SetTriple(new_target_triple); 9450b57cec5SDimitry Andric GetTarget().SetArchitecture(new_target_arch); 9460b57cec5SDimitry Andric } 9470b57cec5SDimitry Andric } 9480b57cec5SDimitry Andric 9495ffd83dbSDimitry Andric LLDB_LOG(log, 9505ffd83dbSDimitry Andric "final target arch after adjustments for remote architecture: " 9515ffd83dbSDimitry Andric "{0} {1}", 9525ffd83dbSDimitry Andric target_arch.GetArchitectureName(), 9535ffd83dbSDimitry Andric target_arch.GetTriple().getTriple()); 9540b57cec5SDimitry Andric } else { 9550b57cec5SDimitry Andric // The target doesn't have a valid architecture yet, set it from the 9560b57cec5SDimitry Andric // architecture we got from the remote GDB server 9570b57cec5SDimitry Andric GetTarget().SetArchitecture(process_arch); 9580b57cec5SDimitry Andric } 9590b57cec5SDimitry Andric } 9600b57cec5SDimitry Andric 961bdd1243dSDimitry Andric // Target and Process are reasonably initailized; 962bdd1243dSDimitry Andric // load any binaries we have metadata for / set load address. 963bdd1243dSDimitry Andric LoadStubBinaries(); 9645ffd83dbSDimitry Andric MaybeLoadExecutableModule(); 9655ffd83dbSDimitry Andric 9660b57cec5SDimitry Andric // Find out which StructuredDataPlugins are supported by the debug monitor. 9670b57cec5SDimitry Andric // These plugins transmit data over async $J packets. 9685ffd83dbSDimitry Andric if (StructuredData::Array *supported_packets = 9695ffd83dbSDimitry Andric m_gdb_comm.GetSupportedStructuredDataPlugins()) 9705ffd83dbSDimitry Andric MapSupportedStructuredDataPlugins(*supported_packets); 971349cc55cSDimitry Andric 972349cc55cSDimitry Andric // If connected to LLDB ("native-signals+"), use signal defs for 973349cc55cSDimitry Andric // the remote platform. If connected to GDB, just use the standard set. 974349cc55cSDimitry Andric if (!m_gdb_comm.UsesNativeSignals()) { 975349cc55cSDimitry Andric SetUnixSignals(std::make_shared<GDBRemoteSignals>()); 976349cc55cSDimitry Andric } else { 977349cc55cSDimitry Andric PlatformSP platform_sp = GetTarget().GetPlatform(); 978349cc55cSDimitry Andric if (platform_sp && platform_sp->IsConnected()) 979349cc55cSDimitry Andric SetUnixSignals(platform_sp->GetUnixSignals()); 980349cc55cSDimitry Andric else 981349cc55cSDimitry Andric SetUnixSignals(UnixSignals::Create(GetTarget().GetArchitecture())); 982349cc55cSDimitry Andric } 9835ffd83dbSDimitry Andric } 9845ffd83dbSDimitry Andric 985bdd1243dSDimitry Andric void ProcessGDBRemote::LoadStubBinaries() { 986bdd1243dSDimitry Andric // The remote stub may know about the "main binary" in 987bdd1243dSDimitry Andric // the context of a firmware debug session, and can 988bdd1243dSDimitry Andric // give us a UUID and an address/slide of where the 989bdd1243dSDimitry Andric // binary is loaded in memory. 990bdd1243dSDimitry Andric UUID standalone_uuid; 991bdd1243dSDimitry Andric addr_t standalone_value; 992bdd1243dSDimitry Andric bool standalone_value_is_offset; 993bdd1243dSDimitry Andric if (m_gdb_comm.GetProcessStandaloneBinary(standalone_uuid, standalone_value, 994bdd1243dSDimitry Andric standalone_value_is_offset)) { 995bdd1243dSDimitry Andric ModuleSP module_sp; 996bdd1243dSDimitry Andric 997bdd1243dSDimitry Andric if (standalone_uuid.IsValid()) { 998bdd1243dSDimitry Andric const bool force_symbol_search = true; 999bdd1243dSDimitry Andric const bool notify = true; 100006c3fb27SDimitry Andric const bool set_address_in_target = true; 1001*5f757f3fSDimitry Andric const bool allow_memory_image_last_resort = false; 1002bdd1243dSDimitry Andric DynamicLoader::LoadBinaryWithUUIDAndAddress( 1003bdd1243dSDimitry Andric this, "", standalone_uuid, standalone_value, 100406c3fb27SDimitry Andric standalone_value_is_offset, force_symbol_search, notify, 1005*5f757f3fSDimitry Andric set_address_in_target, allow_memory_image_last_resort); 1006bdd1243dSDimitry Andric } 1007bdd1243dSDimitry Andric } 1008bdd1243dSDimitry Andric 1009bdd1243dSDimitry Andric // The remote stub may know about a list of binaries to 1010bdd1243dSDimitry Andric // force load into the process -- a firmware type situation 1011bdd1243dSDimitry Andric // where multiple binaries are present in virtual memory, 1012bdd1243dSDimitry Andric // and we are only given the addresses of the binaries. 1013bdd1243dSDimitry Andric // Not intended for use with userland debugging, when we use 1014bdd1243dSDimitry Andric // a DynamicLoader plugin that knows how to find the loaded 1015bdd1243dSDimitry Andric // binaries, and will track updates as binaries are added. 1016bdd1243dSDimitry Andric 1017bdd1243dSDimitry Andric std::vector<addr_t> bin_addrs = m_gdb_comm.GetProcessStandaloneBinaries(); 1018bdd1243dSDimitry Andric if (bin_addrs.size()) { 1019bdd1243dSDimitry Andric UUID uuid; 1020bdd1243dSDimitry Andric const bool value_is_slide = false; 1021bdd1243dSDimitry Andric for (addr_t addr : bin_addrs) { 1022bdd1243dSDimitry Andric const bool notify = true; 1023bdd1243dSDimitry Andric // First see if this is a special platform 1024bdd1243dSDimitry Andric // binary that may determine the DynamicLoader and 1025bdd1243dSDimitry Andric // Platform to be used in this Process and Target. 1026bdd1243dSDimitry Andric if (GetTarget() 1027bdd1243dSDimitry Andric .GetDebugger() 1028bdd1243dSDimitry Andric .GetPlatformList() 1029bdd1243dSDimitry Andric .LoadPlatformBinaryAndSetup(this, addr, notify)) 1030bdd1243dSDimitry Andric continue; 1031bdd1243dSDimitry Andric 1032bdd1243dSDimitry Andric const bool force_symbol_search = true; 103306c3fb27SDimitry Andric const bool set_address_in_target = true; 1034*5f757f3fSDimitry Andric const bool allow_memory_image_last_resort = false; 1035bdd1243dSDimitry Andric // Second manually load this binary into the Target. 103606c3fb27SDimitry Andric DynamicLoader::LoadBinaryWithUUIDAndAddress( 103706c3fb27SDimitry Andric this, llvm::StringRef(), uuid, addr, value_is_slide, 1038*5f757f3fSDimitry Andric force_symbol_search, notify, set_address_in_target, 1039*5f757f3fSDimitry Andric allow_memory_image_last_resort); 1040bdd1243dSDimitry Andric } 1041bdd1243dSDimitry Andric } 1042bdd1243dSDimitry Andric } 1043bdd1243dSDimitry Andric 10445ffd83dbSDimitry Andric void ProcessGDBRemote::MaybeLoadExecutableModule() { 10455ffd83dbSDimitry Andric ModuleSP module_sp = GetTarget().GetExecutableModule(); 10465ffd83dbSDimitry Andric if (!module_sp) 10475ffd83dbSDimitry Andric return; 10485ffd83dbSDimitry Andric 1049bdd1243dSDimitry Andric std::optional<QOffsets> offsets = m_gdb_comm.GetQOffsets(); 10505ffd83dbSDimitry Andric if (!offsets) 10515ffd83dbSDimitry Andric return; 10525ffd83dbSDimitry Andric 10535ffd83dbSDimitry Andric bool is_uniform = 10545ffd83dbSDimitry Andric size_t(llvm::count(offsets->offsets, offsets->offsets[0])) == 10555ffd83dbSDimitry Andric offsets->offsets.size(); 10565ffd83dbSDimitry Andric if (!is_uniform) 10575ffd83dbSDimitry Andric return; // TODO: Handle non-uniform responses. 10585ffd83dbSDimitry Andric 10595ffd83dbSDimitry Andric bool changed = false; 10605ffd83dbSDimitry Andric module_sp->SetLoadAddress(GetTarget(), offsets->offsets[0], 10615ffd83dbSDimitry Andric /*value_is_offset=*/true, changed); 10625ffd83dbSDimitry Andric if (changed) { 10635ffd83dbSDimitry Andric ModuleList list; 10645ffd83dbSDimitry Andric list.Append(module_sp); 10655ffd83dbSDimitry Andric m_process->GetTarget().ModulesDidLoad(list); 10660b57cec5SDimitry Andric } 10670b57cec5SDimitry Andric } 10680b57cec5SDimitry Andric 10690b57cec5SDimitry Andric void ProcessGDBRemote::DidLaunch() { 10700b57cec5SDimitry Andric ArchSpec process_arch; 10710b57cec5SDimitry Andric DidLaunchOrAttach(process_arch); 10720b57cec5SDimitry Andric } 10730b57cec5SDimitry Andric 10740b57cec5SDimitry Andric Status ProcessGDBRemote::DoAttachToProcessWithID( 10750b57cec5SDimitry Andric lldb::pid_t attach_pid, const ProcessAttachInfo &attach_info) { 10761fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 10770b57cec5SDimitry Andric Status error; 10780b57cec5SDimitry Andric 10799dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::%s()", __FUNCTION__); 10800b57cec5SDimitry Andric 10810b57cec5SDimitry Andric // Clear out and clean up from any current state 10820b57cec5SDimitry Andric Clear(); 10830b57cec5SDimitry Andric if (attach_pid != LLDB_INVALID_PROCESS_ID) { 10840b57cec5SDimitry Andric error = EstablishConnectionIfNeeded(attach_info); 10850b57cec5SDimitry Andric if (error.Success()) { 10860b57cec5SDimitry Andric m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError()); 10870b57cec5SDimitry Andric 10880b57cec5SDimitry Andric char packet[64]; 10890b57cec5SDimitry Andric const int packet_len = 10900b57cec5SDimitry Andric ::snprintf(packet, sizeof(packet), "vAttach;%" PRIx64, attach_pid); 10910b57cec5SDimitry Andric SetID(attach_pid); 10920b57cec5SDimitry Andric m_async_broadcaster.BroadcastEvent( 10930b57cec5SDimitry Andric eBroadcastBitAsyncContinue, new EventDataBytes(packet, packet_len)); 10940b57cec5SDimitry Andric } else 10950b57cec5SDimitry Andric SetExitStatus(-1, error.AsCString()); 10960b57cec5SDimitry Andric } 10970b57cec5SDimitry Andric 10980b57cec5SDimitry Andric return error; 10990b57cec5SDimitry Andric } 11000b57cec5SDimitry Andric 11010b57cec5SDimitry Andric Status ProcessGDBRemote::DoAttachToProcessWithName( 11020b57cec5SDimitry Andric const char *process_name, const ProcessAttachInfo &attach_info) { 11030b57cec5SDimitry Andric Status error; 11040b57cec5SDimitry Andric // Clear out and clean up from any current state 11050b57cec5SDimitry Andric Clear(); 11060b57cec5SDimitry Andric 11070b57cec5SDimitry Andric if (process_name && process_name[0]) { 11080b57cec5SDimitry Andric error = EstablishConnectionIfNeeded(attach_info); 11090b57cec5SDimitry Andric if (error.Success()) { 11100b57cec5SDimitry Andric StreamString packet; 11110b57cec5SDimitry Andric 11120b57cec5SDimitry Andric m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError()); 11130b57cec5SDimitry Andric 11140b57cec5SDimitry Andric if (attach_info.GetWaitForLaunch()) { 11150b57cec5SDimitry Andric if (!m_gdb_comm.GetVAttachOrWaitSupported()) { 11160b57cec5SDimitry Andric packet.PutCString("vAttachWait"); 11170b57cec5SDimitry Andric } else { 11180b57cec5SDimitry Andric if (attach_info.GetIgnoreExisting()) 11190b57cec5SDimitry Andric packet.PutCString("vAttachWait"); 11200b57cec5SDimitry Andric else 11210b57cec5SDimitry Andric packet.PutCString("vAttachOrWait"); 11220b57cec5SDimitry Andric } 11230b57cec5SDimitry Andric } else 11240b57cec5SDimitry Andric packet.PutCString("vAttachName"); 11250b57cec5SDimitry Andric packet.PutChar(';'); 11260b57cec5SDimitry Andric packet.PutBytesAsRawHex8(process_name, strlen(process_name), 11270b57cec5SDimitry Andric endian::InlHostByteOrder(), 11280b57cec5SDimitry Andric endian::InlHostByteOrder()); 11290b57cec5SDimitry Andric 11300b57cec5SDimitry Andric m_async_broadcaster.BroadcastEvent( 11310b57cec5SDimitry Andric eBroadcastBitAsyncContinue, 11320b57cec5SDimitry Andric new EventDataBytes(packet.GetString().data(), packet.GetSize())); 11330b57cec5SDimitry Andric 11340b57cec5SDimitry Andric } else 11350b57cec5SDimitry Andric SetExitStatus(-1, error.AsCString()); 11360b57cec5SDimitry Andric } 11370b57cec5SDimitry Andric return error; 11380b57cec5SDimitry Andric } 11390b57cec5SDimitry Andric 1140fe6060f1SDimitry Andric llvm::Expected<TraceSupportedResponse> ProcessGDBRemote::TraceSupported() { 1141fe6060f1SDimitry Andric return m_gdb_comm.SendTraceSupported(GetInterruptTimeout()); 11420b57cec5SDimitry Andric } 11430b57cec5SDimitry Andric 1144fe6060f1SDimitry Andric llvm::Error ProcessGDBRemote::TraceStop(const TraceStopRequest &request) { 1145fe6060f1SDimitry Andric return m_gdb_comm.SendTraceStop(request, GetInterruptTimeout()); 11460b57cec5SDimitry Andric } 11470b57cec5SDimitry Andric 1148fe6060f1SDimitry Andric llvm::Error ProcessGDBRemote::TraceStart(const llvm::json::Value &request) { 1149fe6060f1SDimitry Andric return m_gdb_comm.SendTraceStart(request, GetInterruptTimeout()); 11500b57cec5SDimitry Andric } 11510b57cec5SDimitry Andric 1152fe6060f1SDimitry Andric llvm::Expected<std::string> 1153fe6060f1SDimitry Andric ProcessGDBRemote::TraceGetState(llvm::StringRef type) { 1154fe6060f1SDimitry Andric return m_gdb_comm.SendTraceGetState(type, GetInterruptTimeout()); 11550b57cec5SDimitry Andric } 11560b57cec5SDimitry Andric 1157fe6060f1SDimitry Andric llvm::Expected<std::vector<uint8_t>> 1158fe6060f1SDimitry Andric ProcessGDBRemote::TraceGetBinaryData(const TraceGetBinaryDataRequest &request) { 1159fe6060f1SDimitry Andric return m_gdb_comm.SendTraceGetBinaryData(request, GetInterruptTimeout()); 1160e8d8bef9SDimitry Andric } 1161e8d8bef9SDimitry Andric 11620b57cec5SDimitry Andric void ProcessGDBRemote::DidExit() { 11630b57cec5SDimitry Andric // When we exit, disconnect from the GDB server communications 11640b57cec5SDimitry Andric m_gdb_comm.Disconnect(); 11650b57cec5SDimitry Andric } 11660b57cec5SDimitry Andric 11670b57cec5SDimitry Andric void ProcessGDBRemote::DidAttach(ArchSpec &process_arch) { 11680b57cec5SDimitry Andric // If you can figure out what the architecture is, fill it in here. 11690b57cec5SDimitry Andric process_arch.Clear(); 11700b57cec5SDimitry Andric DidLaunchOrAttach(process_arch); 11710b57cec5SDimitry Andric } 11720b57cec5SDimitry Andric 11730b57cec5SDimitry Andric Status ProcessGDBRemote::WillResume() { 11740b57cec5SDimitry Andric m_continue_c_tids.clear(); 11750b57cec5SDimitry Andric m_continue_C_tids.clear(); 11760b57cec5SDimitry Andric m_continue_s_tids.clear(); 11770b57cec5SDimitry Andric m_continue_S_tids.clear(); 11780b57cec5SDimitry Andric m_jstopinfo_sp.reset(); 11790b57cec5SDimitry Andric m_jthreadsinfo_sp.reset(); 11800b57cec5SDimitry Andric return Status(); 11810b57cec5SDimitry Andric } 11820b57cec5SDimitry Andric 11830b57cec5SDimitry Andric Status ProcessGDBRemote::DoResume() { 11840b57cec5SDimitry Andric Status error; 11851fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 11869dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::Resume()"); 11870b57cec5SDimitry Andric 11880b57cec5SDimitry Andric ListenerSP listener_sp( 11890b57cec5SDimitry Andric Listener::MakeListener("gdb-remote.resume-packet-sent")); 11900b57cec5SDimitry Andric if (listener_sp->StartListeningForEvents( 1191bdd1243dSDimitry Andric &m_gdb_comm, GDBRemoteClientBase::eBroadcastBitRunPacketSent)) { 11920b57cec5SDimitry Andric listener_sp->StartListeningForEvents( 11930b57cec5SDimitry Andric &m_async_broadcaster, 11940b57cec5SDimitry Andric ProcessGDBRemote::eBroadcastBitAsyncThreadDidExit); 11950b57cec5SDimitry Andric 11960b57cec5SDimitry Andric const size_t num_threads = GetThreadList().GetSize(); 11970b57cec5SDimitry Andric 11980b57cec5SDimitry Andric StreamString continue_packet; 11990b57cec5SDimitry Andric bool continue_packet_error = false; 12000b57cec5SDimitry Andric if (m_gdb_comm.HasAnyVContSupport()) { 1201bdd1243dSDimitry Andric std::string pid_prefix; 1202bdd1243dSDimitry Andric if (m_gdb_comm.GetMultiprocessSupported()) 1203bdd1243dSDimitry Andric pid_prefix = llvm::formatv("p{0:x-}.", GetID()); 1204bdd1243dSDimitry Andric 1205349cc55cSDimitry Andric if (m_continue_c_tids.size() == num_threads || 12060b57cec5SDimitry Andric (m_continue_c_tids.empty() && m_continue_C_tids.empty() && 1207349cc55cSDimitry Andric m_continue_s_tids.empty() && m_continue_S_tids.empty())) { 1208bdd1243dSDimitry Andric // All threads are continuing 1209bdd1243dSDimitry Andric if (m_gdb_comm.GetMultiprocessSupported()) 1210bdd1243dSDimitry Andric continue_packet.Format("vCont;c:{0}-1", pid_prefix); 1211bdd1243dSDimitry Andric else 12120b57cec5SDimitry Andric continue_packet.PutCString("c"); 12130b57cec5SDimitry Andric } else { 12140b57cec5SDimitry Andric continue_packet.PutCString("vCont"); 12150b57cec5SDimitry Andric 12160b57cec5SDimitry Andric if (!m_continue_c_tids.empty()) { 12170b57cec5SDimitry Andric if (m_gdb_comm.GetVContSupported('c')) { 12180b57cec5SDimitry Andric for (tid_collection::const_iterator 12190b57cec5SDimitry Andric t_pos = m_continue_c_tids.begin(), 12200b57cec5SDimitry Andric t_end = m_continue_c_tids.end(); 12210b57cec5SDimitry Andric t_pos != t_end; ++t_pos) 1222bdd1243dSDimitry Andric continue_packet.Format(";c:{0}{1:x-}", pid_prefix, *t_pos); 12230b57cec5SDimitry Andric } else 12240b57cec5SDimitry Andric continue_packet_error = true; 12250b57cec5SDimitry Andric } 12260b57cec5SDimitry Andric 12270b57cec5SDimitry Andric if (!continue_packet_error && !m_continue_C_tids.empty()) { 12280b57cec5SDimitry Andric if (m_gdb_comm.GetVContSupported('C')) { 12290b57cec5SDimitry Andric for (tid_sig_collection::const_iterator 12300b57cec5SDimitry Andric s_pos = m_continue_C_tids.begin(), 12310b57cec5SDimitry Andric s_end = m_continue_C_tids.end(); 12320b57cec5SDimitry Andric s_pos != s_end; ++s_pos) 1233bdd1243dSDimitry Andric continue_packet.Format(";C{0:x-2}:{1}{2:x-}", s_pos->second, 1234bdd1243dSDimitry Andric pid_prefix, s_pos->first); 12350b57cec5SDimitry Andric } else 12360b57cec5SDimitry Andric continue_packet_error = true; 12370b57cec5SDimitry Andric } 12380b57cec5SDimitry Andric 12390b57cec5SDimitry Andric if (!continue_packet_error && !m_continue_s_tids.empty()) { 12400b57cec5SDimitry Andric if (m_gdb_comm.GetVContSupported('s')) { 12410b57cec5SDimitry Andric for (tid_collection::const_iterator 12420b57cec5SDimitry Andric t_pos = m_continue_s_tids.begin(), 12430b57cec5SDimitry Andric t_end = m_continue_s_tids.end(); 12440b57cec5SDimitry Andric t_pos != t_end; ++t_pos) 1245bdd1243dSDimitry Andric continue_packet.Format(";s:{0}{1:x-}", pid_prefix, *t_pos); 12460b57cec5SDimitry Andric } else 12470b57cec5SDimitry Andric continue_packet_error = true; 12480b57cec5SDimitry Andric } 12490b57cec5SDimitry Andric 12500b57cec5SDimitry Andric if (!continue_packet_error && !m_continue_S_tids.empty()) { 12510b57cec5SDimitry Andric if (m_gdb_comm.GetVContSupported('S')) { 12520b57cec5SDimitry Andric for (tid_sig_collection::const_iterator 12530b57cec5SDimitry Andric s_pos = m_continue_S_tids.begin(), 12540b57cec5SDimitry Andric s_end = m_continue_S_tids.end(); 12550b57cec5SDimitry Andric s_pos != s_end; ++s_pos) 1256bdd1243dSDimitry Andric continue_packet.Format(";S{0:x-2}:{1}{2:x-}", s_pos->second, 1257bdd1243dSDimitry Andric pid_prefix, s_pos->first); 12580b57cec5SDimitry Andric } else 12590b57cec5SDimitry Andric continue_packet_error = true; 12600b57cec5SDimitry Andric } 12610b57cec5SDimitry Andric 12620b57cec5SDimitry Andric if (continue_packet_error) 12630b57cec5SDimitry Andric continue_packet.Clear(); 12640b57cec5SDimitry Andric } 12650b57cec5SDimitry Andric } else 12660b57cec5SDimitry Andric continue_packet_error = true; 12670b57cec5SDimitry Andric 12680b57cec5SDimitry Andric if (continue_packet_error) { 12690b57cec5SDimitry Andric // Either no vCont support, or we tried to use part of the vCont packet 12700b57cec5SDimitry Andric // that wasn't supported by the remote GDB server. We need to try and 12710b57cec5SDimitry Andric // make a simple packet that can do our continue 12720b57cec5SDimitry Andric const size_t num_continue_c_tids = m_continue_c_tids.size(); 12730b57cec5SDimitry Andric const size_t num_continue_C_tids = m_continue_C_tids.size(); 12740b57cec5SDimitry Andric const size_t num_continue_s_tids = m_continue_s_tids.size(); 12750b57cec5SDimitry Andric const size_t num_continue_S_tids = m_continue_S_tids.size(); 12760b57cec5SDimitry Andric if (num_continue_c_tids > 0) { 12770b57cec5SDimitry Andric if (num_continue_c_tids == num_threads) { 12780b57cec5SDimitry Andric // All threads are resuming... 12790b57cec5SDimitry Andric m_gdb_comm.SetCurrentThreadForRun(-1); 12800b57cec5SDimitry Andric continue_packet.PutChar('c'); 12810b57cec5SDimitry Andric continue_packet_error = false; 12820b57cec5SDimitry Andric } else if (num_continue_c_tids == 1 && num_continue_C_tids == 0 && 12830b57cec5SDimitry Andric num_continue_s_tids == 0 && num_continue_S_tids == 0) { 12840b57cec5SDimitry Andric // Only one thread is continuing 12850b57cec5SDimitry Andric m_gdb_comm.SetCurrentThreadForRun(m_continue_c_tids.front()); 12860b57cec5SDimitry Andric continue_packet.PutChar('c'); 12870b57cec5SDimitry Andric continue_packet_error = false; 12880b57cec5SDimitry Andric } 12890b57cec5SDimitry Andric } 12900b57cec5SDimitry Andric 12910b57cec5SDimitry Andric if (continue_packet_error && num_continue_C_tids > 0) { 12920b57cec5SDimitry Andric if ((num_continue_C_tids + num_continue_c_tids) == num_threads && 12930b57cec5SDimitry Andric num_continue_C_tids > 0 && num_continue_s_tids == 0 && 12940b57cec5SDimitry Andric num_continue_S_tids == 0) { 12950b57cec5SDimitry Andric const int continue_signo = m_continue_C_tids.front().second; 12960b57cec5SDimitry Andric // Only one thread is continuing 12970b57cec5SDimitry Andric if (num_continue_C_tids > 1) { 12980b57cec5SDimitry Andric // More that one thread with a signal, yet we don't have vCont 12990b57cec5SDimitry Andric // support and we are being asked to resume each thread with a 13000b57cec5SDimitry Andric // signal, we need to make sure they are all the same signal, or we 13010b57cec5SDimitry Andric // can't issue the continue accurately with the current support... 13020b57cec5SDimitry Andric if (num_continue_C_tids > 1) { 13030b57cec5SDimitry Andric continue_packet_error = false; 13040b57cec5SDimitry Andric for (size_t i = 1; i < m_continue_C_tids.size(); ++i) { 13050b57cec5SDimitry Andric if (m_continue_C_tids[i].second != continue_signo) 13060b57cec5SDimitry Andric continue_packet_error = true; 13070b57cec5SDimitry Andric } 13080b57cec5SDimitry Andric } 13090b57cec5SDimitry Andric if (!continue_packet_error) 13100b57cec5SDimitry Andric m_gdb_comm.SetCurrentThreadForRun(-1); 13110b57cec5SDimitry Andric } else { 13120b57cec5SDimitry Andric // Set the continue thread ID 13130b57cec5SDimitry Andric continue_packet_error = false; 13140b57cec5SDimitry Andric m_gdb_comm.SetCurrentThreadForRun(m_continue_C_tids.front().first); 13150b57cec5SDimitry Andric } 13160b57cec5SDimitry Andric if (!continue_packet_error) { 13170b57cec5SDimitry Andric // Add threads continuing with the same signo... 13180b57cec5SDimitry Andric continue_packet.Printf("C%2.2x", continue_signo); 13190b57cec5SDimitry Andric } 13200b57cec5SDimitry Andric } 13210b57cec5SDimitry Andric } 13220b57cec5SDimitry Andric 13230b57cec5SDimitry Andric if (continue_packet_error && num_continue_s_tids > 0) { 13240b57cec5SDimitry Andric if (num_continue_s_tids == num_threads) { 13250b57cec5SDimitry Andric // All threads are resuming... 13260b57cec5SDimitry Andric m_gdb_comm.SetCurrentThreadForRun(-1); 13270b57cec5SDimitry Andric 13280b57cec5SDimitry Andric continue_packet.PutChar('s'); 13290b57cec5SDimitry Andric 13300b57cec5SDimitry Andric continue_packet_error = false; 13310b57cec5SDimitry Andric } else if (num_continue_c_tids == 0 && num_continue_C_tids == 0 && 13320b57cec5SDimitry Andric num_continue_s_tids == 1 && num_continue_S_tids == 0) { 13330b57cec5SDimitry Andric // Only one thread is stepping 13340b57cec5SDimitry Andric m_gdb_comm.SetCurrentThreadForRun(m_continue_s_tids.front()); 13350b57cec5SDimitry Andric continue_packet.PutChar('s'); 13360b57cec5SDimitry Andric continue_packet_error = false; 13370b57cec5SDimitry Andric } 13380b57cec5SDimitry Andric } 13390b57cec5SDimitry Andric 13400b57cec5SDimitry Andric if (!continue_packet_error && num_continue_S_tids > 0) { 13410b57cec5SDimitry Andric if (num_continue_S_tids == num_threads) { 13420b57cec5SDimitry Andric const int step_signo = m_continue_S_tids.front().second; 13430b57cec5SDimitry Andric // Are all threads trying to step with the same signal? 13440b57cec5SDimitry Andric continue_packet_error = false; 13450b57cec5SDimitry Andric if (num_continue_S_tids > 1) { 13460b57cec5SDimitry Andric for (size_t i = 1; i < num_threads; ++i) { 13470b57cec5SDimitry Andric if (m_continue_S_tids[i].second != step_signo) 13480b57cec5SDimitry Andric continue_packet_error = true; 13490b57cec5SDimitry Andric } 13500b57cec5SDimitry Andric } 13510b57cec5SDimitry Andric if (!continue_packet_error) { 13520b57cec5SDimitry Andric // Add threads stepping with the same signo... 13530b57cec5SDimitry Andric m_gdb_comm.SetCurrentThreadForRun(-1); 13540b57cec5SDimitry Andric continue_packet.Printf("S%2.2x", step_signo); 13550b57cec5SDimitry Andric } 13560b57cec5SDimitry Andric } else if (num_continue_c_tids == 0 && num_continue_C_tids == 0 && 13570b57cec5SDimitry Andric num_continue_s_tids == 0 && num_continue_S_tids == 1) { 13580b57cec5SDimitry Andric // Only one thread is stepping with signal 13590b57cec5SDimitry Andric m_gdb_comm.SetCurrentThreadForRun(m_continue_S_tids.front().first); 13600b57cec5SDimitry Andric continue_packet.Printf("S%2.2x", m_continue_S_tids.front().second); 13610b57cec5SDimitry Andric continue_packet_error = false; 13620b57cec5SDimitry Andric } 13630b57cec5SDimitry Andric } 13640b57cec5SDimitry Andric } 13650b57cec5SDimitry Andric 13660b57cec5SDimitry Andric if (continue_packet_error) { 13670b57cec5SDimitry Andric error.SetErrorString("can't make continue packet for this resume"); 13680b57cec5SDimitry Andric } else { 13690b57cec5SDimitry Andric EventSP event_sp; 13700b57cec5SDimitry Andric if (!m_async_thread.IsJoinable()) { 13710b57cec5SDimitry Andric error.SetErrorString("Trying to resume but the async thread is dead."); 13729dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::DoResume: Trying to resume but the " 13730b57cec5SDimitry Andric "async thread is dead."); 13740b57cec5SDimitry Andric return error; 13750b57cec5SDimitry Andric } 13760b57cec5SDimitry Andric 13770b57cec5SDimitry Andric m_async_broadcaster.BroadcastEvent( 13780b57cec5SDimitry Andric eBroadcastBitAsyncContinue, 13790b57cec5SDimitry Andric new EventDataBytes(continue_packet.GetString().data(), 13800b57cec5SDimitry Andric continue_packet.GetSize())); 13810b57cec5SDimitry Andric 13820b57cec5SDimitry Andric if (!listener_sp->GetEvent(event_sp, std::chrono::seconds(5))) { 13830b57cec5SDimitry Andric error.SetErrorString("Resume timed out."); 13849dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::DoResume: Resume timed out."); 13850b57cec5SDimitry Andric } else if (event_sp->BroadcasterIs(&m_async_broadcaster)) { 13860b57cec5SDimitry Andric error.SetErrorString("Broadcast continue, but the async thread was " 13870b57cec5SDimitry Andric "killed before we got an ack back."); 13889dba64beSDimitry Andric LLDB_LOGF(log, 13899dba64beSDimitry Andric "ProcessGDBRemote::DoResume: Broadcast continue, but the " 13900b57cec5SDimitry Andric "async thread was killed before we got an ack back."); 13910b57cec5SDimitry Andric return error; 13920b57cec5SDimitry Andric } 13930b57cec5SDimitry Andric } 13940b57cec5SDimitry Andric } 13950b57cec5SDimitry Andric 13960b57cec5SDimitry Andric return error; 13970b57cec5SDimitry Andric } 13980b57cec5SDimitry Andric 13990b57cec5SDimitry Andric void ProcessGDBRemote::ClearThreadIDList() { 14000b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex()); 14010b57cec5SDimitry Andric m_thread_ids.clear(); 14020b57cec5SDimitry Andric m_thread_pcs.clear(); 14030b57cec5SDimitry Andric } 14040b57cec5SDimitry Andric 1405fe6060f1SDimitry Andric size_t ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue( 1406fe6060f1SDimitry Andric llvm::StringRef value) { 14070b57cec5SDimitry Andric m_thread_ids.clear(); 1408fe6060f1SDimitry Andric lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID(); 1409fe6060f1SDimitry Andric StringExtractorGDBRemote thread_ids{value}; 1410fe6060f1SDimitry Andric 1411fe6060f1SDimitry Andric do { 1412fe6060f1SDimitry Andric auto pid_tid = thread_ids.GetPidTid(pid); 1413fe6060f1SDimitry Andric if (pid_tid && pid_tid->first == pid) { 1414fe6060f1SDimitry Andric lldb::tid_t tid = pid_tid->second; 1415fe6060f1SDimitry Andric if (tid != LLDB_INVALID_THREAD_ID && 1416fe6060f1SDimitry Andric tid != StringExtractorGDBRemote::AllProcesses) 14170b57cec5SDimitry Andric m_thread_ids.push_back(tid); 14180b57cec5SDimitry Andric } 1419fe6060f1SDimitry Andric } while (thread_ids.GetChar() == ','); 1420fe6060f1SDimitry Andric 14210b57cec5SDimitry Andric return m_thread_ids.size(); 14220b57cec5SDimitry Andric } 14230b57cec5SDimitry Andric 1424349cc55cSDimitry Andric size_t ProcessGDBRemote::UpdateThreadPCsFromStopReplyThreadsValue( 1425349cc55cSDimitry Andric llvm::StringRef value) { 14260b57cec5SDimitry Andric m_thread_pcs.clear(); 1427349cc55cSDimitry Andric for (llvm::StringRef x : llvm::split(value, ',')) { 14280b57cec5SDimitry Andric lldb::addr_t pc; 1429349cc55cSDimitry Andric if (llvm::to_integer(x, pc, 16)) 14300b57cec5SDimitry Andric m_thread_pcs.push_back(pc); 14310b57cec5SDimitry Andric } 14320b57cec5SDimitry Andric return m_thread_pcs.size(); 14330b57cec5SDimitry Andric } 14340b57cec5SDimitry Andric 14350b57cec5SDimitry Andric bool ProcessGDBRemote::UpdateThreadIDList() { 14360b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex()); 14370b57cec5SDimitry Andric 14380b57cec5SDimitry Andric if (m_jthreadsinfo_sp) { 14390b57cec5SDimitry Andric // If we have the JSON threads info, we can get the thread list from that 14400b57cec5SDimitry Andric StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray(); 14410b57cec5SDimitry Andric if (thread_infos && thread_infos->GetSize() > 0) { 14420b57cec5SDimitry Andric m_thread_ids.clear(); 14430b57cec5SDimitry Andric m_thread_pcs.clear(); 14440b57cec5SDimitry Andric thread_infos->ForEach([this](StructuredData::Object *object) -> bool { 14450b57cec5SDimitry Andric StructuredData::Dictionary *thread_dict = object->GetAsDictionary(); 14460b57cec5SDimitry Andric if (thread_dict) { 14470b57cec5SDimitry Andric // Set the thread stop info from the JSON dictionary 14480b57cec5SDimitry Andric SetThreadStopInfo(thread_dict); 14490b57cec5SDimitry Andric lldb::tid_t tid = LLDB_INVALID_THREAD_ID; 14500b57cec5SDimitry Andric if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>("tid", tid)) 14510b57cec5SDimitry Andric m_thread_ids.push_back(tid); 14520b57cec5SDimitry Andric } 14530b57cec5SDimitry Andric return true; // Keep iterating through all thread_info objects 14540b57cec5SDimitry Andric }); 14550b57cec5SDimitry Andric } 14560b57cec5SDimitry Andric if (!m_thread_ids.empty()) 14570b57cec5SDimitry Andric return true; 14580b57cec5SDimitry Andric } else { 14590b57cec5SDimitry Andric // See if we can get the thread IDs from the current stop reply packets 14600b57cec5SDimitry Andric // that might contain a "threads" key/value pair 14610b57cec5SDimitry Andric 1462349cc55cSDimitry Andric if (m_last_stop_packet) { 14630b57cec5SDimitry Andric // Get the thread stop info 1464349cc55cSDimitry Andric StringExtractorGDBRemote &stop_info = *m_last_stop_packet; 1465349cc55cSDimitry Andric const std::string &stop_info_str = std::string(stop_info.GetStringRef()); 14660b57cec5SDimitry Andric 14670b57cec5SDimitry Andric m_thread_pcs.clear(); 14680b57cec5SDimitry Andric const size_t thread_pcs_pos = stop_info_str.find(";thread-pcs:"); 14690b57cec5SDimitry Andric if (thread_pcs_pos != std::string::npos) { 14700b57cec5SDimitry Andric const size_t start = thread_pcs_pos + strlen(";thread-pcs:"); 14710b57cec5SDimitry Andric const size_t end = stop_info_str.find(';', start); 14720b57cec5SDimitry Andric if (end != std::string::npos) { 14730b57cec5SDimitry Andric std::string value = stop_info_str.substr(start, end - start); 14740b57cec5SDimitry Andric UpdateThreadPCsFromStopReplyThreadsValue(value); 14750b57cec5SDimitry Andric } 14760b57cec5SDimitry Andric } 14770b57cec5SDimitry Andric 14780b57cec5SDimitry Andric const size_t threads_pos = stop_info_str.find(";threads:"); 14790b57cec5SDimitry Andric if (threads_pos != std::string::npos) { 14800b57cec5SDimitry Andric const size_t start = threads_pos + strlen(";threads:"); 14810b57cec5SDimitry Andric const size_t end = stop_info_str.find(';', start); 14820b57cec5SDimitry Andric if (end != std::string::npos) { 14830b57cec5SDimitry Andric std::string value = stop_info_str.substr(start, end - start); 14840b57cec5SDimitry Andric if (UpdateThreadIDsFromStopReplyThreadsValue(value)) 14850b57cec5SDimitry Andric return true; 14860b57cec5SDimitry Andric } 14870b57cec5SDimitry Andric } 14880b57cec5SDimitry Andric } 14890b57cec5SDimitry Andric } 14900b57cec5SDimitry Andric 14910b57cec5SDimitry Andric bool sequence_mutex_unavailable = false; 14920b57cec5SDimitry Andric m_gdb_comm.GetCurrentThreadIDs(m_thread_ids, sequence_mutex_unavailable); 14930b57cec5SDimitry Andric if (sequence_mutex_unavailable) { 14940b57cec5SDimitry Andric return false; // We just didn't get the list 14950b57cec5SDimitry Andric } 14960b57cec5SDimitry Andric return true; 14970b57cec5SDimitry Andric } 14980b57cec5SDimitry Andric 1499e8d8bef9SDimitry Andric bool ProcessGDBRemote::DoUpdateThreadList(ThreadList &old_thread_list, 15000b57cec5SDimitry Andric ThreadList &new_thread_list) { 15010b57cec5SDimitry Andric // locker will keep a mutex locked until it goes out of scope 15021fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Thread); 15030b57cec5SDimitry Andric LLDB_LOGV(log, "pid = {0}", GetID()); 15040b57cec5SDimitry Andric 15050b57cec5SDimitry Andric size_t num_thread_ids = m_thread_ids.size(); 15060b57cec5SDimitry Andric // The "m_thread_ids" thread ID list should always be updated after each stop 15070b57cec5SDimitry Andric // reply packet, but in case it isn't, update it here. 15080b57cec5SDimitry Andric if (num_thread_ids == 0) { 15090b57cec5SDimitry Andric if (!UpdateThreadIDList()) 15100b57cec5SDimitry Andric return false; 15110b57cec5SDimitry Andric num_thread_ids = m_thread_ids.size(); 15120b57cec5SDimitry Andric } 15130b57cec5SDimitry Andric 15140b57cec5SDimitry Andric ThreadList old_thread_list_copy(old_thread_list); 15150b57cec5SDimitry Andric if (num_thread_ids > 0) { 15160b57cec5SDimitry Andric for (size_t i = 0; i < num_thread_ids; ++i) { 15170b57cec5SDimitry Andric tid_t tid = m_thread_ids[i]; 15180b57cec5SDimitry Andric ThreadSP thread_sp( 15190b57cec5SDimitry Andric old_thread_list_copy.RemoveThreadByProtocolID(tid, false)); 15200b57cec5SDimitry Andric if (!thread_sp) { 15210b57cec5SDimitry Andric thread_sp = std::make_shared<ThreadGDBRemote>(*this, tid); 15220b57cec5SDimitry Andric LLDB_LOGV(log, "Making new thread: {0} for thread ID: {1:x}.", 15230b57cec5SDimitry Andric thread_sp.get(), thread_sp->GetID()); 15240b57cec5SDimitry Andric } else { 15250b57cec5SDimitry Andric LLDB_LOGV(log, "Found old thread: {0} for thread ID: {1:x}.", 15260b57cec5SDimitry Andric thread_sp.get(), thread_sp->GetID()); 15270b57cec5SDimitry Andric } 15280b57cec5SDimitry Andric 15290b57cec5SDimitry Andric SetThreadPc(thread_sp, i); 15300b57cec5SDimitry Andric new_thread_list.AddThreadSortedByIndexID(thread_sp); 15310b57cec5SDimitry Andric } 15320b57cec5SDimitry Andric } 15330b57cec5SDimitry Andric 15340b57cec5SDimitry Andric // Whatever that is left in old_thread_list_copy are not present in 15350b57cec5SDimitry Andric // new_thread_list. Remove non-existent threads from internal id table. 15360b57cec5SDimitry Andric size_t old_num_thread_ids = old_thread_list_copy.GetSize(false); 15370b57cec5SDimitry Andric for (size_t i = 0; i < old_num_thread_ids; i++) { 15380b57cec5SDimitry Andric ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex(i, false)); 15390b57cec5SDimitry Andric if (old_thread_sp) { 15400b57cec5SDimitry Andric lldb::tid_t old_thread_id = old_thread_sp->GetProtocolID(); 15410b57cec5SDimitry Andric m_thread_id_to_index_id_map.erase(old_thread_id); 15420b57cec5SDimitry Andric } 15430b57cec5SDimitry Andric } 15440b57cec5SDimitry Andric 15450b57cec5SDimitry Andric return true; 15460b57cec5SDimitry Andric } 15470b57cec5SDimitry Andric 15480b57cec5SDimitry Andric void ProcessGDBRemote::SetThreadPc(const ThreadSP &thread_sp, uint64_t index) { 15490b57cec5SDimitry Andric if (m_thread_ids.size() == m_thread_pcs.size() && thread_sp.get() && 15500b57cec5SDimitry Andric GetByteOrder() != eByteOrderInvalid) { 15510b57cec5SDimitry Andric ThreadGDBRemote *gdb_thread = 15520b57cec5SDimitry Andric static_cast<ThreadGDBRemote *>(thread_sp.get()); 15530b57cec5SDimitry Andric RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext()); 15540b57cec5SDimitry Andric if (reg_ctx_sp) { 15550b57cec5SDimitry Andric uint32_t pc_regnum = reg_ctx_sp->ConvertRegisterKindToRegisterNumber( 15560b57cec5SDimitry Andric eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 15570b57cec5SDimitry Andric if (pc_regnum != LLDB_INVALID_REGNUM) { 15580b57cec5SDimitry Andric gdb_thread->PrivateSetRegisterValue(pc_regnum, m_thread_pcs[index]); 15590b57cec5SDimitry Andric } 15600b57cec5SDimitry Andric } 15610b57cec5SDimitry Andric } 15620b57cec5SDimitry Andric } 15630b57cec5SDimitry Andric 15640b57cec5SDimitry Andric bool ProcessGDBRemote::GetThreadStopInfoFromJSON( 15650b57cec5SDimitry Andric ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp) { 15660b57cec5SDimitry Andric // See if we got thread stop infos for all threads via the "jThreadsInfo" 15670b57cec5SDimitry Andric // packet 15680b57cec5SDimitry Andric if (thread_infos_sp) { 15690b57cec5SDimitry Andric StructuredData::Array *thread_infos = thread_infos_sp->GetAsArray(); 15700b57cec5SDimitry Andric if (thread_infos) { 15710b57cec5SDimitry Andric lldb::tid_t tid; 15720b57cec5SDimitry Andric const size_t n = thread_infos->GetSize(); 15730b57cec5SDimitry Andric for (size_t i = 0; i < n; ++i) { 15740b57cec5SDimitry Andric StructuredData::Dictionary *thread_dict = 15750b57cec5SDimitry Andric thread_infos->GetItemAtIndex(i)->GetAsDictionary(); 15760b57cec5SDimitry Andric if (thread_dict) { 15770b57cec5SDimitry Andric if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>( 15780b57cec5SDimitry Andric "tid", tid, LLDB_INVALID_THREAD_ID)) { 15790b57cec5SDimitry Andric if (tid == thread->GetID()) 15800b57cec5SDimitry Andric return (bool)SetThreadStopInfo(thread_dict); 15810b57cec5SDimitry Andric } 15820b57cec5SDimitry Andric } 15830b57cec5SDimitry Andric } 15840b57cec5SDimitry Andric } 15850b57cec5SDimitry Andric } 15860b57cec5SDimitry Andric return false; 15870b57cec5SDimitry Andric } 15880b57cec5SDimitry Andric 15890b57cec5SDimitry Andric bool ProcessGDBRemote::CalculateThreadStopInfo(ThreadGDBRemote *thread) { 15900b57cec5SDimitry Andric // See if we got thread stop infos for all threads via the "jThreadsInfo" 15910b57cec5SDimitry Andric // packet 15920b57cec5SDimitry Andric if (GetThreadStopInfoFromJSON(thread, m_jthreadsinfo_sp)) 15930b57cec5SDimitry Andric return true; 15940b57cec5SDimitry Andric 15950b57cec5SDimitry Andric // See if we got thread stop info for any threads valid stop info reasons 15960b57cec5SDimitry Andric // threads via the "jstopinfo" packet stop reply packet key/value pair? 15970b57cec5SDimitry Andric if (m_jstopinfo_sp) { 15980b57cec5SDimitry Andric // If we have "jstopinfo" then we have stop descriptions for all threads 15990b57cec5SDimitry Andric // that have stop reasons, and if there is no entry for a thread, then it 16000b57cec5SDimitry Andric // has no stop reason. 16010b57cec5SDimitry Andric thread->GetRegisterContext()->InvalidateIfNeeded(true); 16020b57cec5SDimitry Andric if (!GetThreadStopInfoFromJSON(thread, m_jstopinfo_sp)) { 16030b57cec5SDimitry Andric thread->SetStopInfo(StopInfoSP()); 16040b57cec5SDimitry Andric } 16050b57cec5SDimitry Andric return true; 16060b57cec5SDimitry Andric } 16070b57cec5SDimitry Andric 16080b57cec5SDimitry Andric // Fall back to using the qThreadStopInfo packet 16090b57cec5SDimitry Andric StringExtractorGDBRemote stop_packet; 16100b57cec5SDimitry Andric if (GetGDBRemote().GetThreadStopInfo(thread->GetProtocolID(), stop_packet)) 16110b57cec5SDimitry Andric return SetThreadStopInfo(stop_packet) == eStateStopped; 16120b57cec5SDimitry Andric return false; 16130b57cec5SDimitry Andric } 16140b57cec5SDimitry Andric 1615*5f757f3fSDimitry Andric void ProcessGDBRemote::ParseExpeditedRegisters( 1616*5f757f3fSDimitry Andric ExpeditedRegisterMap &expedited_register_map, ThreadSP thread_sp) { 1617*5f757f3fSDimitry Andric ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *>(thread_sp.get()); 1618*5f757f3fSDimitry Andric RegisterContextSP gdb_reg_ctx_sp(gdb_thread->GetRegisterContext()); 1619*5f757f3fSDimitry Andric 1620*5f757f3fSDimitry Andric for (const auto &pair : expedited_register_map) { 1621*5f757f3fSDimitry Andric StringExtractor reg_value_extractor(pair.second); 1622*5f757f3fSDimitry Andric WritableDataBufferSP buffer_sp( 1623*5f757f3fSDimitry Andric new DataBufferHeap(reg_value_extractor.GetStringRef().size() / 2, 0)); 1624*5f757f3fSDimitry Andric reg_value_extractor.GetHexBytes(buffer_sp->GetData(), '\xcc'); 1625*5f757f3fSDimitry Andric uint32_t lldb_regnum = gdb_reg_ctx_sp->ConvertRegisterKindToRegisterNumber( 1626*5f757f3fSDimitry Andric eRegisterKindProcessPlugin, pair.first); 1627*5f757f3fSDimitry Andric gdb_thread->PrivateSetRegisterValue(lldb_regnum, buffer_sp->GetData()); 1628*5f757f3fSDimitry Andric } 1629*5f757f3fSDimitry Andric } 1630*5f757f3fSDimitry Andric 16310b57cec5SDimitry Andric ThreadSP ProcessGDBRemote::SetThreadStopInfo( 16320b57cec5SDimitry Andric lldb::tid_t tid, ExpeditedRegisterMap &expedited_register_map, 16330b57cec5SDimitry Andric uint8_t signo, const std::string &thread_name, const std::string &reason, 16340b57cec5SDimitry Andric const std::string &description, uint32_t exc_type, 16350b57cec5SDimitry Andric const std::vector<addr_t> &exc_data, addr_t thread_dispatch_qaddr, 16360b57cec5SDimitry Andric bool queue_vars_valid, // Set to true if queue_name, queue_kind and 16370b57cec5SDimitry Andric // queue_serial are valid 16380b57cec5SDimitry Andric LazyBool associated_with_dispatch_queue, addr_t dispatch_queue_t, 16390b57cec5SDimitry Andric std::string &queue_name, QueueKind queue_kind, uint64_t queue_serial) { 1640bdd1243dSDimitry Andric 1641bdd1243dSDimitry Andric if (tid == LLDB_INVALID_THREAD_ID) 1642bdd1243dSDimitry Andric return nullptr; 1643bdd1243dSDimitry Andric 16440b57cec5SDimitry Andric ThreadSP thread_sp; 16450b57cec5SDimitry Andric // Scope for "locker" below 16460b57cec5SDimitry Andric { 1647bdd1243dSDimitry Andric // m_thread_list_real does have its own mutex, but we need to hold onto the 1648bdd1243dSDimitry Andric // mutex between the call to m_thread_list_real.FindThreadByID(...) and the 1649bdd1243dSDimitry Andric // m_thread_list_real.AddThread(...) so it doesn't change on us 1650bdd1243dSDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex()); 16510b57cec5SDimitry Andric thread_sp = m_thread_list_real.FindThreadByProtocolID(tid, false); 16520b57cec5SDimitry Andric 16530b57cec5SDimitry Andric if (!thread_sp) { 16540b57cec5SDimitry Andric // Create the thread if we need to 16550b57cec5SDimitry Andric thread_sp = std::make_shared<ThreadGDBRemote>(*this, tid); 16560b57cec5SDimitry Andric m_thread_list_real.AddThread(thread_sp); 16570b57cec5SDimitry Andric } 16580b57cec5SDimitry Andric } 16590b57cec5SDimitry Andric 1660bdd1243dSDimitry Andric ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *>(thread_sp.get()); 1661*5f757f3fSDimitry Andric RegisterContextSP reg_ctx_sp(gdb_thread->GetRegisterContext()); 1662fe6060f1SDimitry Andric 1663*5f757f3fSDimitry Andric reg_ctx_sp->InvalidateIfNeeded(true); 16640b57cec5SDimitry Andric 16650b57cec5SDimitry Andric auto iter = std::find(m_thread_ids.begin(), m_thread_ids.end(), tid); 1666bdd1243dSDimitry Andric if (iter != m_thread_ids.end()) 16670b57cec5SDimitry Andric SetThreadPc(thread_sp, iter - m_thread_ids.begin()); 16680b57cec5SDimitry Andric 1669*5f757f3fSDimitry Andric ParseExpeditedRegisters(expedited_register_map, thread_sp); 16700b57cec5SDimitry Andric 1671*5f757f3fSDimitry Andric if (reg_ctx_sp->ReconfigureRegisterInfo()) { 1672*5f757f3fSDimitry Andric // Now we have changed the offsets of all the registers, so the values 1673*5f757f3fSDimitry Andric // will be corrupted. 1674*5f757f3fSDimitry Andric reg_ctx_sp->InvalidateAllRegisters(); 1675*5f757f3fSDimitry Andric // Expedited registers values will never contain registers that would be 1676*5f757f3fSDimitry Andric // resized by a reconfigure. So we are safe to continue using these 1677*5f757f3fSDimitry Andric // values. 1678*5f757f3fSDimitry Andric ParseExpeditedRegisters(expedited_register_map, thread_sp); 1679e8d8bef9SDimitry Andric } 1680e8d8bef9SDimitry Andric 16810b57cec5SDimitry Andric thread_sp->SetName(thread_name.empty() ? nullptr : thread_name.c_str()); 16820b57cec5SDimitry Andric 16830b57cec5SDimitry Andric gdb_thread->SetThreadDispatchQAddr(thread_dispatch_qaddr); 1684bdd1243dSDimitry Andric // Check if the GDB server was able to provide the queue name, kind and serial 1685bdd1243dSDimitry Andric // number 16860b57cec5SDimitry Andric if (queue_vars_valid) 1687bdd1243dSDimitry Andric gdb_thread->SetQueueInfo(std::move(queue_name), queue_kind, queue_serial, 1688bdd1243dSDimitry Andric dispatch_queue_t, associated_with_dispatch_queue); 16890b57cec5SDimitry Andric else 16900b57cec5SDimitry Andric gdb_thread->ClearQueueInfo(); 16910b57cec5SDimitry Andric 1692bdd1243dSDimitry Andric gdb_thread->SetAssociatedWithLibdispatchQueue(associated_with_dispatch_queue); 16930b57cec5SDimitry Andric 16940b57cec5SDimitry Andric if (dispatch_queue_t != LLDB_INVALID_ADDRESS) 16950b57cec5SDimitry Andric gdb_thread->SetQueueLibdispatchQueueAddress(dispatch_queue_t); 16960b57cec5SDimitry Andric 1697bdd1243dSDimitry Andric // Make sure we update our thread stop reason just once, but don't overwrite 1698bdd1243dSDimitry Andric // the stop info for threads that haven't moved: 1699bdd1243dSDimitry Andric StopInfoSP current_stop_info_sp = thread_sp->GetPrivateStopInfo(false); 1700bdd1243dSDimitry Andric if (thread_sp->GetTemporaryResumeState() == eStateSuspended && 1701bdd1243dSDimitry Andric current_stop_info_sp) { 1702bdd1243dSDimitry Andric thread_sp->SetStopInfo(current_stop_info_sp); 1703bdd1243dSDimitry Andric return thread_sp; 1704bdd1243dSDimitry Andric } 1705bdd1243dSDimitry Andric 17060b57cec5SDimitry Andric if (!thread_sp->StopInfoIsUpToDate()) { 17070b57cec5SDimitry Andric thread_sp->SetStopInfo(StopInfoSP()); 1708bdd1243dSDimitry Andric // If there's a memory thread backed by this thread, we need to use it to 1709bdd1243dSDimitry Andric // calculate StopInfo. 1710bdd1243dSDimitry Andric if (ThreadSP memory_thread_sp = m_thread_list.GetBackingThread(thread_sp)) 17110b57cec5SDimitry Andric thread_sp = memory_thread_sp; 17120b57cec5SDimitry Andric 17130b57cec5SDimitry Andric if (exc_type != 0) { 17140b57cec5SDimitry Andric const size_t exc_data_size = exc_data.size(); 17150b57cec5SDimitry Andric 17160b57cec5SDimitry Andric thread_sp->SetStopInfo( 17170b57cec5SDimitry Andric StopInfoMachException::CreateStopReasonWithMachException( 17180b57cec5SDimitry Andric *thread_sp, exc_type, exc_data_size, 17190b57cec5SDimitry Andric exc_data_size >= 1 ? exc_data[0] : 0, 17200b57cec5SDimitry Andric exc_data_size >= 2 ? exc_data[1] : 0, 17210b57cec5SDimitry Andric exc_data_size >= 3 ? exc_data[2] : 0)); 17220b57cec5SDimitry Andric } else { 17230b57cec5SDimitry Andric bool handled = false; 17240b57cec5SDimitry Andric bool did_exec = false; 17250b57cec5SDimitry Andric if (!reason.empty()) { 17260b57cec5SDimitry Andric if (reason == "trace") { 17270b57cec5SDimitry Andric addr_t pc = thread_sp->GetRegisterContext()->GetPC(); 1728bdd1243dSDimitry Andric lldb::BreakpointSiteSP bp_site_sp = 1729bdd1243dSDimitry Andric thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress( 1730bdd1243dSDimitry Andric pc); 17310b57cec5SDimitry Andric 1732bdd1243dSDimitry Andric // If the current pc is a breakpoint site then the StopInfo should be 1733bdd1243dSDimitry Andric // set to Breakpoint Otherwise, it will be set to Trace. 1734fe6060f1SDimitry Andric if (bp_site_sp && bp_site_sp->ValidForThisThread(*thread_sp)) { 17350b57cec5SDimitry Andric thread_sp->SetStopInfo( 17360b57cec5SDimitry Andric StopInfo::CreateStopReasonWithBreakpointSiteID( 17370b57cec5SDimitry Andric *thread_sp, bp_site_sp->GetID())); 17380b57cec5SDimitry Andric } else 17390b57cec5SDimitry Andric thread_sp->SetStopInfo( 17400b57cec5SDimitry Andric StopInfo::CreateStopReasonToTrace(*thread_sp)); 17410b57cec5SDimitry Andric handled = true; 17420b57cec5SDimitry Andric } else if (reason == "breakpoint") { 17430b57cec5SDimitry Andric addr_t pc = thread_sp->GetRegisterContext()->GetPC(); 1744bdd1243dSDimitry Andric lldb::BreakpointSiteSP bp_site_sp = 1745bdd1243dSDimitry Andric thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress( 1746bdd1243dSDimitry Andric pc); 17470b57cec5SDimitry Andric if (bp_site_sp) { 1748bdd1243dSDimitry Andric // If the breakpoint is for this thread, then we'll report the hit, 1749bdd1243dSDimitry Andric // but if it is for another thread, we can just report no reason. 1750bdd1243dSDimitry Andric // We don't need to worry about stepping over the breakpoint here, 1751bdd1243dSDimitry Andric // that will be taken care of when the thread resumes and notices 1752bdd1243dSDimitry Andric // that there's a breakpoint under the pc. 17530b57cec5SDimitry Andric handled = true; 1754fe6060f1SDimitry Andric if (bp_site_sp->ValidForThisThread(*thread_sp)) { 17550b57cec5SDimitry Andric thread_sp->SetStopInfo( 17560b57cec5SDimitry Andric StopInfo::CreateStopReasonWithBreakpointSiteID( 17570b57cec5SDimitry Andric *thread_sp, bp_site_sp->GetID())); 17580b57cec5SDimitry Andric } else { 17590b57cec5SDimitry Andric StopInfoSP invalid_stop_info_sp; 17600b57cec5SDimitry Andric thread_sp->SetStopInfo(invalid_stop_info_sp); 17610b57cec5SDimitry Andric } 17620b57cec5SDimitry Andric } 17630b57cec5SDimitry Andric } else if (reason == "trap") { 17640b57cec5SDimitry Andric // Let the trap just use the standard signal stop reason below... 17650b57cec5SDimitry Andric } else if (reason == "watchpoint") { 176606c3fb27SDimitry Andric // We will have between 1 and 3 fields in the description. 176706c3fb27SDimitry Andric // 176806c3fb27SDimitry Andric // \a wp_addr which is the original start address that 176906c3fb27SDimitry Andric // lldb requested be watched, or an address that the 177006c3fb27SDimitry Andric // hardware reported. This address should be within the 177106c3fb27SDimitry Andric // range of a currently active watchpoint region - lldb 177206c3fb27SDimitry Andric // should be able to find a watchpoint with this address. 177306c3fb27SDimitry Andric // 177406c3fb27SDimitry Andric // \a wp_index is the hardware watchpoint register number. 177506c3fb27SDimitry Andric // 177606c3fb27SDimitry Andric // \a wp_hit_addr is the actual address reported by the hardware, 177706c3fb27SDimitry Andric // which may be outside the range of a region we are watching. 177806c3fb27SDimitry Andric // 177906c3fb27SDimitry Andric // On MIPS, we may get a false watchpoint exception where an 178006c3fb27SDimitry Andric // access to the same 8 byte granule as a watchpoint will trigger, 178106c3fb27SDimitry Andric // even if the access was not within the range of the watched 178206c3fb27SDimitry Andric // region. When we get a \a wp_hit_addr outside the range of any 178306c3fb27SDimitry Andric // set watchpoint, continue execution without making it visible to 178406c3fb27SDimitry Andric // the user. 178506c3fb27SDimitry Andric // 178606c3fb27SDimitry Andric // On ARM, a related issue where a large access that starts 178706c3fb27SDimitry Andric // before the watched region (and extends into the watched 178806c3fb27SDimitry Andric // region) may report a hit address before the watched region. 178906c3fb27SDimitry Andric // lldb will not find the "nearest" watchpoint to 179006c3fb27SDimitry Andric // disable/step/re-enable it, so one of the valid watchpoint 179106c3fb27SDimitry Andric // addresses should be provided as \a wp_addr. 17920b57cec5SDimitry Andric StringExtractor desc_extractor(description.c_str()); 1793*5f757f3fSDimitry Andric // FIXME NativeThreadLinux::SetStoppedByWatchpoint sends this 1794*5f757f3fSDimitry Andric // up as 1795*5f757f3fSDimitry Andric // <address within wp range> <wp hw index> <actual accessed addr> 1796*5f757f3fSDimitry Andric // but this is not reading the <wp hw index>. Seems like it 1797*5f757f3fSDimitry Andric // wouldn't work on MIPS, where that third field is important. 17980b57cec5SDimitry Andric addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); 17990b57cec5SDimitry Andric addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); 18000b57cec5SDimitry Andric watch_id_t watch_id = LLDB_INVALID_WATCH_ID; 180106c3fb27SDimitry Andric bool silently_continue = false; 1802*5f757f3fSDimitry Andric WatchpointResourceSP wp_resource_sp; 180306c3fb27SDimitry Andric if (wp_hit_addr != LLDB_INVALID_ADDRESS) { 1804*5f757f3fSDimitry Andric wp_resource_sp = 1805*5f757f3fSDimitry Andric m_watchpoint_resource_list.FindByAddress(wp_hit_addr); 180606c3fb27SDimitry Andric // On MIPS, \a wp_hit_addr outside the range of a watched 180706c3fb27SDimitry Andric // region means we should silently continue, it is a false hit. 18080b57cec5SDimitry Andric ArchSpec::Core core = GetTarget().GetArchitecture().GetCore(); 1809*5f757f3fSDimitry Andric if (!wp_resource_sp && core >= ArchSpec::kCore_mips_first && 181006c3fb27SDimitry Andric core <= ArchSpec::kCore_mips_last) 181106c3fb27SDimitry Andric silently_continue = true; 181206c3fb27SDimitry Andric } 1813*5f757f3fSDimitry Andric if (!wp_resource_sp && wp_addr != LLDB_INVALID_ADDRESS) 1814*5f757f3fSDimitry Andric wp_resource_sp = m_watchpoint_resource_list.FindByAddress(wp_addr); 1815*5f757f3fSDimitry Andric if (!wp_resource_sp) { 18161fd87a68SDimitry Andric Log *log(GetLog(GDBRLog::Watchpoints)); 18179dba64beSDimitry Andric LLDB_LOGF(log, "failed to find watchpoint"); 1818*5f757f3fSDimitry Andric watch_id = LLDB_INVALID_SITE_ID; 1819*5f757f3fSDimitry Andric } else { 1820*5f757f3fSDimitry Andric // LWP_TODO: This is hardcoding a single Watchpoint in a 1821*5f757f3fSDimitry Andric // Resource, need to add 1822*5f757f3fSDimitry Andric // StopInfo::CreateStopReasonWithWatchpointResource which 1823*5f757f3fSDimitry Andric // represents all watchpoints that were tripped at this stop. 1824*5f757f3fSDimitry Andric watch_id = wp_resource_sp->GetConstituentAtIndex(0)->GetID(); 18250b57cec5SDimitry Andric } 18260b57cec5SDimitry Andric thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithWatchpointID( 182706c3fb27SDimitry Andric *thread_sp, watch_id, silently_continue)); 18280b57cec5SDimitry Andric handled = true; 18290b57cec5SDimitry Andric } else if (reason == "exception") { 18300b57cec5SDimitry Andric thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithException( 18310b57cec5SDimitry Andric *thread_sp, description.c_str())); 18320b57cec5SDimitry Andric handled = true; 18330b57cec5SDimitry Andric } else if (reason == "exec") { 18340b57cec5SDimitry Andric did_exec = true; 18350b57cec5SDimitry Andric thread_sp->SetStopInfo( 18360b57cec5SDimitry Andric StopInfo::CreateStopReasonWithExec(*thread_sp)); 18370b57cec5SDimitry Andric handled = true; 1838fe6060f1SDimitry Andric } else if (reason == "processor trace") { 1839fe6060f1SDimitry Andric thread_sp->SetStopInfo(StopInfo::CreateStopReasonProcessorTrace( 1840fe6060f1SDimitry Andric *thread_sp, description.c_str())); 1841349cc55cSDimitry Andric } else if (reason == "fork") { 1842349cc55cSDimitry Andric StringExtractor desc_extractor(description.c_str()); 1843bdd1243dSDimitry Andric lldb::pid_t child_pid = 1844bdd1243dSDimitry Andric desc_extractor.GetU64(LLDB_INVALID_PROCESS_ID); 1845bdd1243dSDimitry Andric lldb::tid_t child_tid = desc_extractor.GetU64(LLDB_INVALID_THREAD_ID); 1846bdd1243dSDimitry Andric thread_sp->SetStopInfo( 1847bdd1243dSDimitry Andric StopInfo::CreateStopReasonFork(*thread_sp, child_pid, child_tid)); 1848349cc55cSDimitry Andric handled = true; 1849349cc55cSDimitry Andric } else if (reason == "vfork") { 1850349cc55cSDimitry Andric StringExtractor desc_extractor(description.c_str()); 1851bdd1243dSDimitry Andric lldb::pid_t child_pid = 1852bdd1243dSDimitry Andric desc_extractor.GetU64(LLDB_INVALID_PROCESS_ID); 1853bdd1243dSDimitry Andric lldb::tid_t child_tid = desc_extractor.GetU64(LLDB_INVALID_THREAD_ID); 1854349cc55cSDimitry Andric thread_sp->SetStopInfo(StopInfo::CreateStopReasonVFork( 1855349cc55cSDimitry Andric *thread_sp, child_pid, child_tid)); 1856349cc55cSDimitry Andric handled = true; 1857349cc55cSDimitry Andric } else if (reason == "vforkdone") { 1858349cc55cSDimitry Andric thread_sp->SetStopInfo( 1859349cc55cSDimitry Andric StopInfo::CreateStopReasonVForkDone(*thread_sp)); 1860349cc55cSDimitry Andric handled = true; 18610b57cec5SDimitry Andric } 18620b57cec5SDimitry Andric } else if (!signo) { 18630b57cec5SDimitry Andric addr_t pc = thread_sp->GetRegisterContext()->GetPC(); 18640b57cec5SDimitry Andric lldb::BreakpointSiteSP bp_site_sp = 1865bdd1243dSDimitry Andric thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); 18660b57cec5SDimitry Andric 1867bdd1243dSDimitry Andric // If the current pc is a breakpoint site then the StopInfo should be 1868bdd1243dSDimitry Andric // set to Breakpoint even though the remote stub did not set it as such. 1869bdd1243dSDimitry Andric // This can happen when the thread is involuntarily interrupted (e.g. 1870bdd1243dSDimitry Andric // due to stops on other threads) just as it is about to execute the 1871bdd1243dSDimitry Andric // breakpoint instruction. 1872fe6060f1SDimitry Andric if (bp_site_sp && bp_site_sp->ValidForThisThread(*thread_sp)) { 1873bdd1243dSDimitry Andric thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID( 18740b57cec5SDimitry Andric *thread_sp, bp_site_sp->GetID())); 18750b57cec5SDimitry Andric handled = true; 18760b57cec5SDimitry Andric } 18770b57cec5SDimitry Andric } 18780b57cec5SDimitry Andric 18790b57cec5SDimitry Andric if (!handled && signo && !did_exec) { 18800b57cec5SDimitry Andric if (signo == SIGTRAP) { 18810b57cec5SDimitry Andric // Currently we are going to assume SIGTRAP means we are either 18820b57cec5SDimitry Andric // hitting a breakpoint or hardware single stepping. 18830b57cec5SDimitry Andric handled = true; 1884bdd1243dSDimitry Andric addr_t pc = 1885bdd1243dSDimitry Andric thread_sp->GetRegisterContext()->GetPC() + m_breakpoint_pc_offset; 1886bdd1243dSDimitry Andric lldb::BreakpointSiteSP bp_site_sp = 1887bdd1243dSDimitry Andric thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress( 1888bdd1243dSDimitry Andric pc); 18890b57cec5SDimitry Andric 18900b57cec5SDimitry Andric if (bp_site_sp) { 1891bdd1243dSDimitry Andric // If the breakpoint is for this thread, then we'll report the hit, 1892bdd1243dSDimitry Andric // but if it is for another thread, we can just report no reason. 1893bdd1243dSDimitry Andric // We don't need to worry about stepping over the breakpoint here, 1894bdd1243dSDimitry Andric // that will be taken care of when the thread resumes and notices 1895bdd1243dSDimitry Andric // that there's a breakpoint under the pc. 1896fe6060f1SDimitry Andric if (bp_site_sp->ValidForThisThread(*thread_sp)) { 18970b57cec5SDimitry Andric if (m_breakpoint_pc_offset != 0) 18980b57cec5SDimitry Andric thread_sp->GetRegisterContext()->SetPC(pc); 18990b57cec5SDimitry Andric thread_sp->SetStopInfo( 19000b57cec5SDimitry Andric StopInfo::CreateStopReasonWithBreakpointSiteID( 19010b57cec5SDimitry Andric *thread_sp, bp_site_sp->GetID())); 19020b57cec5SDimitry Andric } else { 19030b57cec5SDimitry Andric StopInfoSP invalid_stop_info_sp; 19040b57cec5SDimitry Andric thread_sp->SetStopInfo(invalid_stop_info_sp); 19050b57cec5SDimitry Andric } 19060b57cec5SDimitry Andric } else { 1907bdd1243dSDimitry Andric // If we were stepping then assume the stop was the result of the 1908bdd1243dSDimitry Andric // trace. If we were not stepping then report the SIGTRAP. 1909bdd1243dSDimitry Andric // FIXME: We are still missing the case where we single step over a 1910bdd1243dSDimitry Andric // trap instruction. 19110b57cec5SDimitry Andric if (thread_sp->GetTemporaryResumeState() == eStateStepping) 19120b57cec5SDimitry Andric thread_sp->SetStopInfo( 19130b57cec5SDimitry Andric StopInfo::CreateStopReasonToTrace(*thread_sp)); 19140b57cec5SDimitry Andric else 19150b57cec5SDimitry Andric thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithSignal( 19160b57cec5SDimitry Andric *thread_sp, signo, description.c_str())); 19170b57cec5SDimitry Andric } 19180b57cec5SDimitry Andric } 19190b57cec5SDimitry Andric if (!handled) 19200b57cec5SDimitry Andric thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithSignal( 19210b57cec5SDimitry Andric *thread_sp, signo, description.c_str())); 19220b57cec5SDimitry Andric } 19230b57cec5SDimitry Andric 19240b57cec5SDimitry Andric if (!description.empty()) { 19250b57cec5SDimitry Andric lldb::StopInfoSP stop_info_sp(thread_sp->GetStopInfo()); 19260b57cec5SDimitry Andric if (stop_info_sp) { 19270b57cec5SDimitry Andric const char *stop_info_desc = stop_info_sp->GetDescription(); 19280b57cec5SDimitry Andric if (!stop_info_desc || !stop_info_desc[0]) 19290b57cec5SDimitry Andric stop_info_sp->SetDescription(description.c_str()); 19300b57cec5SDimitry Andric } else { 19310b57cec5SDimitry Andric thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithException( 19320b57cec5SDimitry Andric *thread_sp, description.c_str())); 19330b57cec5SDimitry Andric } 19340b57cec5SDimitry Andric } 19350b57cec5SDimitry Andric } 19360b57cec5SDimitry Andric } 19370b57cec5SDimitry Andric return thread_sp; 19380b57cec5SDimitry Andric } 19390b57cec5SDimitry Andric 19400b57cec5SDimitry Andric lldb::ThreadSP 19410b57cec5SDimitry Andric ProcessGDBRemote::SetThreadStopInfo(StructuredData::Dictionary *thread_dict) { 1942*5f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_tid("tid"); 1943*5f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_name("name"); 1944*5f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_reason("reason"); 1945*5f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_metype("metype"); 1946*5f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_medata("medata"); 1947*5f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_qaddr("qaddr"); 1948*5f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_dispatch_queue_t( 1949*5f757f3fSDimitry Andric "dispatch_queue_t"); 1950*5f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_associated_with_dispatch_queue( 19510b57cec5SDimitry Andric "associated_with_dispatch_queue"); 1952*5f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_queue_name("qname"); 1953*5f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_queue_kind("qkind"); 1954*5f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_queue_serial_number("qserialnum"); 1955*5f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_registers("registers"); 1956*5f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_memory("memory"); 1957*5f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_description("description"); 1958*5f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_signal("signal"); 19590b57cec5SDimitry Andric 19600b57cec5SDimitry Andric // Stop with signal and thread info 19610b57cec5SDimitry Andric lldb::tid_t tid = LLDB_INVALID_THREAD_ID; 19620b57cec5SDimitry Andric uint8_t signo = 0; 19630b57cec5SDimitry Andric std::string value; 19640b57cec5SDimitry Andric std::string thread_name; 19650b57cec5SDimitry Andric std::string reason; 19660b57cec5SDimitry Andric std::string description; 19670b57cec5SDimitry Andric uint32_t exc_type = 0; 19680b57cec5SDimitry Andric std::vector<addr_t> exc_data; 19690b57cec5SDimitry Andric addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS; 19700b57cec5SDimitry Andric ExpeditedRegisterMap expedited_register_map; 19710b57cec5SDimitry Andric bool queue_vars_valid = false; 19720b57cec5SDimitry Andric addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS; 19730b57cec5SDimitry Andric LazyBool associated_with_dispatch_queue = eLazyBoolCalculate; 19740b57cec5SDimitry Andric std::string queue_name; 19750b57cec5SDimitry Andric QueueKind queue_kind = eQueueKindUnknown; 19760b57cec5SDimitry Andric uint64_t queue_serial_number = 0; 19770b57cec5SDimitry Andric // Iterate through all of the thread dictionary key/value pairs from the 19780b57cec5SDimitry Andric // structured data dictionary 19790b57cec5SDimitry Andric 1980349cc55cSDimitry Andric // FIXME: we're silently ignoring invalid data here 19810b57cec5SDimitry Andric thread_dict->ForEach([this, &tid, &expedited_register_map, &thread_name, 19820b57cec5SDimitry Andric &signo, &reason, &description, &exc_type, &exc_data, 19830b57cec5SDimitry Andric &thread_dispatch_qaddr, &queue_vars_valid, 19840b57cec5SDimitry Andric &associated_with_dispatch_queue, &dispatch_queue_t, 19850b57cec5SDimitry Andric &queue_name, &queue_kind, &queue_serial_number]( 1986*5f757f3fSDimitry Andric llvm::StringRef key, 19870b57cec5SDimitry Andric StructuredData::Object *object) -> bool { 19880b57cec5SDimitry Andric if (key == g_key_tid) { 19890b57cec5SDimitry Andric // thread in big endian hex 199006c3fb27SDimitry Andric tid = object->GetUnsignedIntegerValue(LLDB_INVALID_THREAD_ID); 19910b57cec5SDimitry Andric } else if (key == g_key_metype) { 19920b57cec5SDimitry Andric // exception type in big endian hex 199306c3fb27SDimitry Andric exc_type = object->GetUnsignedIntegerValue(0); 19940b57cec5SDimitry Andric } else if (key == g_key_medata) { 19950b57cec5SDimitry Andric // exception data in big endian hex 19960b57cec5SDimitry Andric StructuredData::Array *array = object->GetAsArray(); 19970b57cec5SDimitry Andric if (array) { 19980b57cec5SDimitry Andric array->ForEach([&exc_data](StructuredData::Object *object) -> bool { 199906c3fb27SDimitry Andric exc_data.push_back(object->GetUnsignedIntegerValue()); 20000b57cec5SDimitry Andric return true; // Keep iterating through all array items 20010b57cec5SDimitry Andric }); 20020b57cec5SDimitry Andric } 20030b57cec5SDimitry Andric } else if (key == g_key_name) { 20045ffd83dbSDimitry Andric thread_name = std::string(object->GetStringValue()); 20050b57cec5SDimitry Andric } else if (key == g_key_qaddr) { 200606c3fb27SDimitry Andric thread_dispatch_qaddr = 200706c3fb27SDimitry Andric object->GetUnsignedIntegerValue(LLDB_INVALID_ADDRESS); 20080b57cec5SDimitry Andric } else if (key == g_key_queue_name) { 20090b57cec5SDimitry Andric queue_vars_valid = true; 20105ffd83dbSDimitry Andric queue_name = std::string(object->GetStringValue()); 20110b57cec5SDimitry Andric } else if (key == g_key_queue_kind) { 20125ffd83dbSDimitry Andric std::string queue_kind_str = std::string(object->GetStringValue()); 20130b57cec5SDimitry Andric if (queue_kind_str == "serial") { 20140b57cec5SDimitry Andric queue_vars_valid = true; 20150b57cec5SDimitry Andric queue_kind = eQueueKindSerial; 20160b57cec5SDimitry Andric } else if (queue_kind_str == "concurrent") { 20170b57cec5SDimitry Andric queue_vars_valid = true; 20180b57cec5SDimitry Andric queue_kind = eQueueKindConcurrent; 20190b57cec5SDimitry Andric } 20200b57cec5SDimitry Andric } else if (key == g_key_queue_serial_number) { 202106c3fb27SDimitry Andric queue_serial_number = object->GetUnsignedIntegerValue(0); 20220b57cec5SDimitry Andric if (queue_serial_number != 0) 20230b57cec5SDimitry Andric queue_vars_valid = true; 20240b57cec5SDimitry Andric } else if (key == g_key_dispatch_queue_t) { 202506c3fb27SDimitry Andric dispatch_queue_t = object->GetUnsignedIntegerValue(0); 20260b57cec5SDimitry Andric if (dispatch_queue_t != 0 && dispatch_queue_t != LLDB_INVALID_ADDRESS) 20270b57cec5SDimitry Andric queue_vars_valid = true; 20280b57cec5SDimitry Andric } else if (key == g_key_associated_with_dispatch_queue) { 20290b57cec5SDimitry Andric queue_vars_valid = true; 20300b57cec5SDimitry Andric bool associated = object->GetBooleanValue(); 20310b57cec5SDimitry Andric if (associated) 20320b57cec5SDimitry Andric associated_with_dispatch_queue = eLazyBoolYes; 20330b57cec5SDimitry Andric else 20340b57cec5SDimitry Andric associated_with_dispatch_queue = eLazyBoolNo; 20350b57cec5SDimitry Andric } else if (key == g_key_reason) { 20365ffd83dbSDimitry Andric reason = std::string(object->GetStringValue()); 20370b57cec5SDimitry Andric } else if (key == g_key_description) { 20385ffd83dbSDimitry Andric description = std::string(object->GetStringValue()); 20390b57cec5SDimitry Andric } else if (key == g_key_registers) { 20400b57cec5SDimitry Andric StructuredData::Dictionary *registers_dict = object->GetAsDictionary(); 20410b57cec5SDimitry Andric 20420b57cec5SDimitry Andric if (registers_dict) { 20430b57cec5SDimitry Andric registers_dict->ForEach( 2044*5f757f3fSDimitry Andric [&expedited_register_map](llvm::StringRef key, 20450b57cec5SDimitry Andric StructuredData::Object *object) -> bool { 2046349cc55cSDimitry Andric uint32_t reg; 2047*5f757f3fSDimitry Andric if (llvm::to_integer(key, reg)) 20485ffd83dbSDimitry Andric expedited_register_map[reg] = 20495ffd83dbSDimitry Andric std::string(object->GetStringValue()); 20500b57cec5SDimitry Andric return true; // Keep iterating through all array items 20510b57cec5SDimitry Andric }); 20520b57cec5SDimitry Andric } 20530b57cec5SDimitry Andric } else if (key == g_key_memory) { 20540b57cec5SDimitry Andric StructuredData::Array *array = object->GetAsArray(); 20550b57cec5SDimitry Andric if (array) { 20560b57cec5SDimitry Andric array->ForEach([this](StructuredData::Object *object) -> bool { 20570b57cec5SDimitry Andric StructuredData::Dictionary *mem_cache_dict = 20580b57cec5SDimitry Andric object->GetAsDictionary(); 20590b57cec5SDimitry Andric if (mem_cache_dict) { 20600b57cec5SDimitry Andric lldb::addr_t mem_cache_addr = LLDB_INVALID_ADDRESS; 20610b57cec5SDimitry Andric if (mem_cache_dict->GetValueForKeyAsInteger<lldb::addr_t>( 20620b57cec5SDimitry Andric "address", mem_cache_addr)) { 20630b57cec5SDimitry Andric if (mem_cache_addr != LLDB_INVALID_ADDRESS) { 20640b57cec5SDimitry Andric llvm::StringRef str; 20650b57cec5SDimitry Andric if (mem_cache_dict->GetValueForKeyAsString("bytes", str)) { 20660b57cec5SDimitry Andric StringExtractor bytes(str); 20670b57cec5SDimitry Andric bytes.SetFilePos(0); 20680b57cec5SDimitry Andric 20690b57cec5SDimitry Andric const size_t byte_size = bytes.GetStringRef().size() / 2; 207081ad6265SDimitry Andric WritableDataBufferSP data_buffer_sp( 207181ad6265SDimitry Andric new DataBufferHeap(byte_size, 0)); 20720b57cec5SDimitry Andric const size_t bytes_copied = 20730b57cec5SDimitry Andric bytes.GetHexBytes(data_buffer_sp->GetData(), 0); 20740b57cec5SDimitry Andric if (bytes_copied == byte_size) 20750b57cec5SDimitry Andric m_memory_cache.AddL1CacheData(mem_cache_addr, 20760b57cec5SDimitry Andric data_buffer_sp); 20770b57cec5SDimitry Andric } 20780b57cec5SDimitry Andric } 20790b57cec5SDimitry Andric } 20800b57cec5SDimitry Andric } 20810b57cec5SDimitry Andric return true; // Keep iterating through all array items 20820b57cec5SDimitry Andric }); 20830b57cec5SDimitry Andric } 20840b57cec5SDimitry Andric 20850b57cec5SDimitry Andric } else if (key == g_key_signal) 208606c3fb27SDimitry Andric signo = object->GetUnsignedIntegerValue(LLDB_INVALID_SIGNAL_NUMBER); 20870b57cec5SDimitry Andric return true; // Keep iterating through all dictionary key/value pairs 20880b57cec5SDimitry Andric }); 20890b57cec5SDimitry Andric 20900b57cec5SDimitry Andric return SetThreadStopInfo(tid, expedited_register_map, signo, thread_name, 20910b57cec5SDimitry Andric reason, description, exc_type, exc_data, 20920b57cec5SDimitry Andric thread_dispatch_qaddr, queue_vars_valid, 20930b57cec5SDimitry Andric associated_with_dispatch_queue, dispatch_queue_t, 20940b57cec5SDimitry Andric queue_name, queue_kind, queue_serial_number); 20950b57cec5SDimitry Andric } 20960b57cec5SDimitry Andric 20970b57cec5SDimitry Andric StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) { 2098fe6060f1SDimitry Andric lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID(); 20990b57cec5SDimitry Andric stop_packet.SetFilePos(0); 21000b57cec5SDimitry Andric const char stop_type = stop_packet.GetChar(); 21010b57cec5SDimitry Andric switch (stop_type) { 21020b57cec5SDimitry Andric case 'T': 21030b57cec5SDimitry Andric case 'S': { 2104*5f757f3fSDimitry Andric // This is a bit of a hack, but it is required. If we did exec, we need to 21050b57cec5SDimitry Andric // clear our thread lists and also know to rebuild our dynamic register 21060b57cec5SDimitry Andric // info before we lookup and threads and populate the expedited register 21070b57cec5SDimitry Andric // values so we need to know this right away so we can cleanup and update 21080b57cec5SDimitry Andric // our registers. 21090b57cec5SDimitry Andric const uint32_t stop_id = GetStopID(); 21100b57cec5SDimitry Andric if (stop_id == 0) { 21110b57cec5SDimitry Andric // Our first stop, make sure we have a process ID, and also make sure we 21120b57cec5SDimitry Andric // know about our registers 2113fe6060f1SDimitry Andric if (GetID() == LLDB_INVALID_PROCESS_ID && pid != LLDB_INVALID_PROCESS_ID) 21140b57cec5SDimitry Andric SetID(pid); 21150b57cec5SDimitry Andric BuildDynamicRegisterInfo(true); 21160b57cec5SDimitry Andric } 21170b57cec5SDimitry Andric // Stop with signal and thread info 2118fe6060f1SDimitry Andric lldb::pid_t stop_pid = LLDB_INVALID_PROCESS_ID; 21190b57cec5SDimitry Andric lldb::tid_t tid = LLDB_INVALID_THREAD_ID; 21200b57cec5SDimitry Andric const uint8_t signo = stop_packet.GetHexU8(); 21210b57cec5SDimitry Andric llvm::StringRef key; 21220b57cec5SDimitry Andric llvm::StringRef value; 21230b57cec5SDimitry Andric std::string thread_name; 21240b57cec5SDimitry Andric std::string reason; 21250b57cec5SDimitry Andric std::string description; 21260b57cec5SDimitry Andric uint32_t exc_type = 0; 21270b57cec5SDimitry Andric std::vector<addr_t> exc_data; 21280b57cec5SDimitry Andric addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS; 21290b57cec5SDimitry Andric bool queue_vars_valid = 21300b57cec5SDimitry Andric false; // says if locals below that start with "queue_" are valid 21310b57cec5SDimitry Andric addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS; 21320b57cec5SDimitry Andric LazyBool associated_with_dispatch_queue = eLazyBoolCalculate; 21330b57cec5SDimitry Andric std::string queue_name; 21340b57cec5SDimitry Andric QueueKind queue_kind = eQueueKindUnknown; 21350b57cec5SDimitry Andric uint64_t queue_serial_number = 0; 21360b57cec5SDimitry Andric ExpeditedRegisterMap expedited_register_map; 2137*5f757f3fSDimitry Andric AddressableBits addressable_bits; 21380b57cec5SDimitry Andric while (stop_packet.GetNameColonValue(key, value)) { 21390b57cec5SDimitry Andric if (key.compare("metype") == 0) { 21400b57cec5SDimitry Andric // exception type in big endian hex 21410b57cec5SDimitry Andric value.getAsInteger(16, exc_type); 21420b57cec5SDimitry Andric } else if (key.compare("medata") == 0) { 21430b57cec5SDimitry Andric // exception data in big endian hex 21440b57cec5SDimitry Andric uint64_t x; 21450b57cec5SDimitry Andric value.getAsInteger(16, x); 21460b57cec5SDimitry Andric exc_data.push_back(x); 21470b57cec5SDimitry Andric } else if (key.compare("thread") == 0) { 2148fe6060f1SDimitry Andric // thread-id 2149fe6060f1SDimitry Andric StringExtractorGDBRemote thread_id{value}; 2150fe6060f1SDimitry Andric auto pid_tid = thread_id.GetPidTid(pid); 2151fe6060f1SDimitry Andric if (pid_tid) { 2152fe6060f1SDimitry Andric stop_pid = pid_tid->first; 2153fe6060f1SDimitry Andric tid = pid_tid->second; 2154fe6060f1SDimitry Andric } else 21550b57cec5SDimitry Andric tid = LLDB_INVALID_THREAD_ID; 21560b57cec5SDimitry Andric } else if (key.compare("threads") == 0) { 21570b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard( 21580b57cec5SDimitry Andric m_thread_list_real.GetMutex()); 2159fe6060f1SDimitry Andric UpdateThreadIDsFromStopReplyThreadsValue(value); 21600b57cec5SDimitry Andric } else if (key.compare("thread-pcs") == 0) { 21610b57cec5SDimitry Andric m_thread_pcs.clear(); 21620b57cec5SDimitry Andric // A comma separated list of all threads in the current 21630b57cec5SDimitry Andric // process that includes the thread for this stop reply packet 21640b57cec5SDimitry Andric lldb::addr_t pc; 21650b57cec5SDimitry Andric while (!value.empty()) { 21660b57cec5SDimitry Andric llvm::StringRef pc_str; 21670b57cec5SDimitry Andric std::tie(pc_str, value) = value.split(','); 21680b57cec5SDimitry Andric if (pc_str.getAsInteger(16, pc)) 21690b57cec5SDimitry Andric pc = LLDB_INVALID_ADDRESS; 21700b57cec5SDimitry Andric m_thread_pcs.push_back(pc); 21710b57cec5SDimitry Andric } 21720b57cec5SDimitry Andric } else if (key.compare("jstopinfo") == 0) { 21730b57cec5SDimitry Andric StringExtractor json_extractor(value); 21740b57cec5SDimitry Andric std::string json; 21750b57cec5SDimitry Andric // Now convert the HEX bytes into a string value 21760b57cec5SDimitry Andric json_extractor.GetHexByteString(json); 21770b57cec5SDimitry Andric 21780b57cec5SDimitry Andric // This JSON contains thread IDs and thread stop info for all threads. 21790b57cec5SDimitry Andric // It doesn't contain expedited registers, memory or queue info. 21800b57cec5SDimitry Andric m_jstopinfo_sp = StructuredData::ParseJSON(json); 21810b57cec5SDimitry Andric } else if (key.compare("hexname") == 0) { 21820b57cec5SDimitry Andric StringExtractor name_extractor(value); 21830b57cec5SDimitry Andric std::string name; 21840b57cec5SDimitry Andric // Now convert the HEX bytes into a string value 21850b57cec5SDimitry Andric name_extractor.GetHexByteString(thread_name); 21860b57cec5SDimitry Andric } else if (key.compare("name") == 0) { 21875ffd83dbSDimitry Andric thread_name = std::string(value); 21880b57cec5SDimitry Andric } else if (key.compare("qaddr") == 0) { 21890b57cec5SDimitry Andric value.getAsInteger(16, thread_dispatch_qaddr); 21900b57cec5SDimitry Andric } else if (key.compare("dispatch_queue_t") == 0) { 21910b57cec5SDimitry Andric queue_vars_valid = true; 21920b57cec5SDimitry Andric value.getAsInteger(16, dispatch_queue_t); 21930b57cec5SDimitry Andric } else if (key.compare("qname") == 0) { 21940b57cec5SDimitry Andric queue_vars_valid = true; 21950b57cec5SDimitry Andric StringExtractor name_extractor(value); 21960b57cec5SDimitry Andric // Now convert the HEX bytes into a string value 21970b57cec5SDimitry Andric name_extractor.GetHexByteString(queue_name); 21980b57cec5SDimitry Andric } else if (key.compare("qkind") == 0) { 21990b57cec5SDimitry Andric queue_kind = llvm::StringSwitch<QueueKind>(value) 22000b57cec5SDimitry Andric .Case("serial", eQueueKindSerial) 22010b57cec5SDimitry Andric .Case("concurrent", eQueueKindConcurrent) 22020b57cec5SDimitry Andric .Default(eQueueKindUnknown); 22030b57cec5SDimitry Andric queue_vars_valid = queue_kind != eQueueKindUnknown; 22040b57cec5SDimitry Andric } else if (key.compare("qserialnum") == 0) { 22050b57cec5SDimitry Andric if (!value.getAsInteger(0, queue_serial_number)) 22060b57cec5SDimitry Andric queue_vars_valid = true; 22070b57cec5SDimitry Andric } else if (key.compare("reason") == 0) { 22085ffd83dbSDimitry Andric reason = std::string(value); 22090b57cec5SDimitry Andric } else if (key.compare("description") == 0) { 22100b57cec5SDimitry Andric StringExtractor desc_extractor(value); 22110b57cec5SDimitry Andric // Now convert the HEX bytes into a string value 22120b57cec5SDimitry Andric desc_extractor.GetHexByteString(description); 22130b57cec5SDimitry Andric } else if (key.compare("memory") == 0) { 22140b57cec5SDimitry Andric // Expedited memory. GDB servers can choose to send back expedited 22150b57cec5SDimitry Andric // memory that can populate the L1 memory cache in the process so that 22160b57cec5SDimitry Andric // things like the frame pointer backchain can be expedited. This will 22170b57cec5SDimitry Andric // help stack backtracing be more efficient by not having to send as 22180b57cec5SDimitry Andric // many memory read requests down the remote GDB server. 22190b57cec5SDimitry Andric 22200b57cec5SDimitry Andric // Key/value pair format: memory:<addr>=<bytes>; 22210b57cec5SDimitry Andric // <addr> is a number whose base will be interpreted by the prefix: 22220b57cec5SDimitry Andric // "0x[0-9a-fA-F]+" for hex 22230b57cec5SDimitry Andric // "0[0-7]+" for octal 22240b57cec5SDimitry Andric // "[1-9]+" for decimal 22250b57cec5SDimitry Andric // <bytes> is native endian ASCII hex bytes just like the register 22260b57cec5SDimitry Andric // values 22270b57cec5SDimitry Andric llvm::StringRef addr_str, bytes_str; 22280b57cec5SDimitry Andric std::tie(addr_str, bytes_str) = value.split('='); 22290b57cec5SDimitry Andric if (!addr_str.empty() && !bytes_str.empty()) { 22300b57cec5SDimitry Andric lldb::addr_t mem_cache_addr = LLDB_INVALID_ADDRESS; 22310b57cec5SDimitry Andric if (!addr_str.getAsInteger(0, mem_cache_addr)) { 22320b57cec5SDimitry Andric StringExtractor bytes(bytes_str); 22330b57cec5SDimitry Andric const size_t byte_size = bytes.GetBytesLeft() / 2; 223481ad6265SDimitry Andric WritableDataBufferSP data_buffer_sp( 223581ad6265SDimitry Andric new DataBufferHeap(byte_size, 0)); 22360b57cec5SDimitry Andric const size_t bytes_copied = 22370b57cec5SDimitry Andric bytes.GetHexBytes(data_buffer_sp->GetData(), 0); 22380b57cec5SDimitry Andric if (bytes_copied == byte_size) 22390b57cec5SDimitry Andric m_memory_cache.AddL1CacheData(mem_cache_addr, data_buffer_sp); 22400b57cec5SDimitry Andric } 22410b57cec5SDimitry Andric } 22420b57cec5SDimitry Andric } else if (key.compare("watch") == 0 || key.compare("rwatch") == 0 || 22430b57cec5SDimitry Andric key.compare("awatch") == 0) { 22440b57cec5SDimitry Andric // Support standard GDB remote stop reply packet 'TAAwatch:addr' 22450b57cec5SDimitry Andric lldb::addr_t wp_addr = LLDB_INVALID_ADDRESS; 22460b57cec5SDimitry Andric value.getAsInteger(16, wp_addr); 22470b57cec5SDimitry Andric 2248*5f757f3fSDimitry Andric WatchpointResourceSP wp_resource_sp = 2249*5f757f3fSDimitry Andric m_watchpoint_resource_list.FindByAddress(wp_addr); 22500b57cec5SDimitry Andric 225106c3fb27SDimitry Andric // Rewrite gdb standard watch/rwatch/awatch to 225206c3fb27SDimitry Andric // "reason:watchpoint" + "description:ADDR", 225306c3fb27SDimitry Andric // which is parsed in SetThreadStopInfo. 22540b57cec5SDimitry Andric reason = "watchpoint"; 22550b57cec5SDimitry Andric StreamString ostr; 2256*5f757f3fSDimitry Andric ostr.Printf("%" PRIu64, wp_addr); 22575ffd83dbSDimitry Andric description = std::string(ostr.GetString()); 22580b57cec5SDimitry Andric } else if (key.compare("library") == 0) { 22599dba64beSDimitry Andric auto error = LoadModules(); 22609dba64beSDimitry Andric if (error) { 22611fd87a68SDimitry Andric Log *log(GetLog(GDBRLog::Process)); 22629dba64beSDimitry Andric LLDB_LOG_ERROR(log, std::move(error), "Failed to load modules: {0}"); 22639dba64beSDimitry Andric } 2264349cc55cSDimitry Andric } else if (key.compare("fork") == 0 || key.compare("vfork") == 0) { 2265349cc55cSDimitry Andric // fork includes child pid/tid in thread-id format 2266349cc55cSDimitry Andric StringExtractorGDBRemote thread_id{value}; 2267349cc55cSDimitry Andric auto pid_tid = thread_id.GetPidTid(LLDB_INVALID_PROCESS_ID); 2268349cc55cSDimitry Andric if (!pid_tid) { 22691fd87a68SDimitry Andric Log *log(GetLog(GDBRLog::Process)); 2270349cc55cSDimitry Andric LLDB_LOG(log, "Invalid PID/TID to fork: {0}", value); 2271349cc55cSDimitry Andric pid_tid = {{LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID}}; 2272349cc55cSDimitry Andric } 2273349cc55cSDimitry Andric 2274349cc55cSDimitry Andric reason = key.str(); 2275349cc55cSDimitry Andric StreamString ostr; 2276349cc55cSDimitry Andric ostr.Printf("%" PRIu64 " %" PRIu64, pid_tid->first, pid_tid->second); 2277349cc55cSDimitry Andric description = std::string(ostr.GetString()); 227806c3fb27SDimitry Andric } else if (key.compare("addressing_bits") == 0) { 227906c3fb27SDimitry Andric uint64_t addressing_bits; 228006c3fb27SDimitry Andric if (!value.getAsInteger(0, addressing_bits)) { 2281*5f757f3fSDimitry Andric addressable_bits.SetAddressableBits(addressing_bits); 2282*5f757f3fSDimitry Andric } 2283*5f757f3fSDimitry Andric } else if (key.compare("low_mem_addressing_bits") == 0) { 2284*5f757f3fSDimitry Andric uint64_t addressing_bits; 2285*5f757f3fSDimitry Andric if (!value.getAsInteger(0, addressing_bits)) { 2286*5f757f3fSDimitry Andric addressable_bits.SetLowmemAddressableBits(addressing_bits); 2287*5f757f3fSDimitry Andric } 2288*5f757f3fSDimitry Andric } else if (key.compare("high_mem_addressing_bits") == 0) { 2289*5f757f3fSDimitry Andric uint64_t addressing_bits; 2290*5f757f3fSDimitry Andric if (!value.getAsInteger(0, addressing_bits)) { 2291*5f757f3fSDimitry Andric addressable_bits.SetHighmemAddressableBits(addressing_bits); 229206c3fb27SDimitry Andric } 22930b57cec5SDimitry Andric } else if (key.size() == 2 && ::isxdigit(key[0]) && ::isxdigit(key[1])) { 22940b57cec5SDimitry Andric uint32_t reg = UINT32_MAX; 22950b57cec5SDimitry Andric if (!key.getAsInteger(16, reg)) 22965ffd83dbSDimitry Andric expedited_register_map[reg] = std::string(std::move(value)); 22970b57cec5SDimitry Andric } 22980b57cec5SDimitry Andric } 22990b57cec5SDimitry Andric 2300fe6060f1SDimitry Andric if (stop_pid != LLDB_INVALID_PROCESS_ID && stop_pid != pid) { 23011fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 2302fe6060f1SDimitry Andric LLDB_LOG(log, 2303fe6060f1SDimitry Andric "Received stop for incorrect PID = {0} (inferior PID = {1})", 2304fe6060f1SDimitry Andric stop_pid, pid); 2305fe6060f1SDimitry Andric return eStateInvalid; 2306fe6060f1SDimitry Andric } 2307fe6060f1SDimitry Andric 23080b57cec5SDimitry Andric if (tid == LLDB_INVALID_THREAD_ID) { 23090b57cec5SDimitry Andric // A thread id may be invalid if the response is old style 'S' packet 23100b57cec5SDimitry Andric // which does not provide the 23110b57cec5SDimitry Andric // thread information. So update the thread list and choose the first 23120b57cec5SDimitry Andric // one. 23130b57cec5SDimitry Andric UpdateThreadIDList(); 23140b57cec5SDimitry Andric 23150b57cec5SDimitry Andric if (!m_thread_ids.empty()) { 23160b57cec5SDimitry Andric tid = m_thread_ids.front(); 23170b57cec5SDimitry Andric } 23180b57cec5SDimitry Andric } 23190b57cec5SDimitry Andric 2320*5f757f3fSDimitry Andric addressable_bits.SetProcessMasks(*this); 2321*5f757f3fSDimitry Andric 23220b57cec5SDimitry Andric ThreadSP thread_sp = SetThreadStopInfo( 23230b57cec5SDimitry Andric tid, expedited_register_map, signo, thread_name, reason, description, 23240b57cec5SDimitry Andric exc_type, exc_data, thread_dispatch_qaddr, queue_vars_valid, 23250b57cec5SDimitry Andric associated_with_dispatch_queue, dispatch_queue_t, queue_name, 23260b57cec5SDimitry Andric queue_kind, queue_serial_number); 23270b57cec5SDimitry Andric 23280b57cec5SDimitry Andric return eStateStopped; 23290b57cec5SDimitry Andric } break; 23300b57cec5SDimitry Andric 23310b57cec5SDimitry Andric case 'W': 23320b57cec5SDimitry Andric case 'X': 23330b57cec5SDimitry Andric // process exited 23340b57cec5SDimitry Andric return eStateExited; 23350b57cec5SDimitry Andric 23360b57cec5SDimitry Andric default: 23370b57cec5SDimitry Andric break; 23380b57cec5SDimitry Andric } 23390b57cec5SDimitry Andric return eStateInvalid; 23400b57cec5SDimitry Andric } 23410b57cec5SDimitry Andric 23420b57cec5SDimitry Andric void ProcessGDBRemote::RefreshStateAfterStop() { 23430b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex()); 23440b57cec5SDimitry Andric 23450b57cec5SDimitry Andric m_thread_ids.clear(); 23460b57cec5SDimitry Andric m_thread_pcs.clear(); 2347480093f4SDimitry Andric 23480b57cec5SDimitry Andric // Set the thread stop info. It might have a "threads" key whose value is a 23490b57cec5SDimitry Andric // list of all thread IDs in the current process, so m_thread_ids might get 23500b57cec5SDimitry Andric // set. 23510b57cec5SDimitry Andric // Check to see if SetThreadStopInfo() filled in m_thread_ids? 23520b57cec5SDimitry Andric if (m_thread_ids.empty()) { 23530b57cec5SDimitry Andric // No, we need to fetch the thread list manually 23540b57cec5SDimitry Andric UpdateThreadIDList(); 23550b57cec5SDimitry Andric } 2356480093f4SDimitry Andric 23570b57cec5SDimitry Andric // We might set some stop info's so make sure the thread list is up to 23580b57cec5SDimitry Andric // date before we do that or we might overwrite what was computed here. 23590b57cec5SDimitry Andric UpdateThreadListIfNeeded(); 23600b57cec5SDimitry Andric 2361349cc55cSDimitry Andric if (m_last_stop_packet) 2362349cc55cSDimitry Andric SetThreadStopInfo(*m_last_stop_packet); 2363349cc55cSDimitry Andric m_last_stop_packet.reset(); 23640b57cec5SDimitry Andric 23650b57cec5SDimitry Andric // If we have queried for a default thread id 23660b57cec5SDimitry Andric if (m_initial_tid != LLDB_INVALID_THREAD_ID) { 23670b57cec5SDimitry Andric m_thread_list.SetSelectedThreadByID(m_initial_tid); 23680b57cec5SDimitry Andric m_initial_tid = LLDB_INVALID_THREAD_ID; 23690b57cec5SDimitry Andric } 23700b57cec5SDimitry Andric 23710b57cec5SDimitry Andric // Let all threads recover from stopping and do any clean up based on the 23720b57cec5SDimitry Andric // previous thread state (if any). 23730b57cec5SDimitry Andric m_thread_list_real.RefreshStateAfterStop(); 23740b57cec5SDimitry Andric } 23750b57cec5SDimitry Andric 23760b57cec5SDimitry Andric Status ProcessGDBRemote::DoHalt(bool &caused_stop) { 23770b57cec5SDimitry Andric Status error; 23780b57cec5SDimitry Andric 23790b57cec5SDimitry Andric if (m_public_state.GetValue() == eStateAttaching) { 2380*5f757f3fSDimitry Andric // We are being asked to halt during an attach. We used to just close our 2381*5f757f3fSDimitry Andric // file handle and debugserver will go away, but with remote proxies, it 2382*5f757f3fSDimitry Andric // is better to send a positive signal, so let's send the interrupt first... 2383*5f757f3fSDimitry Andric caused_stop = m_gdb_comm.Interrupt(GetInterruptTimeout()); 23840b57cec5SDimitry Andric m_gdb_comm.Disconnect(); 23850b57cec5SDimitry Andric } else 2386fe6060f1SDimitry Andric caused_stop = m_gdb_comm.Interrupt(GetInterruptTimeout()); 23870b57cec5SDimitry Andric return error; 23880b57cec5SDimitry Andric } 23890b57cec5SDimitry Andric 23900b57cec5SDimitry Andric Status ProcessGDBRemote::DoDetach(bool keep_stopped) { 23910b57cec5SDimitry Andric Status error; 23921fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 23939dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::DoDetach(keep_stopped: %i)", keep_stopped); 23940b57cec5SDimitry Andric 23950b57cec5SDimitry Andric error = m_gdb_comm.Detach(keep_stopped); 23960b57cec5SDimitry Andric if (log) { 23970b57cec5SDimitry Andric if (error.Success()) 23980b57cec5SDimitry Andric log->PutCString( 23990b57cec5SDimitry Andric "ProcessGDBRemote::DoDetach() detach packet sent successfully"); 24000b57cec5SDimitry Andric else 24019dba64beSDimitry Andric LLDB_LOGF(log, 24029dba64beSDimitry Andric "ProcessGDBRemote::DoDetach() detach packet send failed: %s", 24030b57cec5SDimitry Andric error.AsCString() ? error.AsCString() : "<unknown error>"); 24040b57cec5SDimitry Andric } 24050b57cec5SDimitry Andric 24060b57cec5SDimitry Andric if (!error.Success()) 24070b57cec5SDimitry Andric return error; 24080b57cec5SDimitry Andric 24090b57cec5SDimitry Andric // Sleep for one second to let the process get all detached... 24100b57cec5SDimitry Andric StopAsyncThread(); 24110b57cec5SDimitry Andric 24120b57cec5SDimitry Andric SetPrivateState(eStateDetached); 24130b57cec5SDimitry Andric ResumePrivateStateThread(); 24140b57cec5SDimitry Andric 24150b57cec5SDimitry Andric // KillDebugserverProcess (); 24160b57cec5SDimitry Andric return error; 24170b57cec5SDimitry Andric } 24180b57cec5SDimitry Andric 24190b57cec5SDimitry Andric Status ProcessGDBRemote::DoDestroy() { 24201fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 24219dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::DoDestroy()"); 24220b57cec5SDimitry Andric 24230b57cec5SDimitry Andric // Interrupt if our inferior is running... 24240b57cec5SDimitry Andric int exit_status = SIGABRT; 24250b57cec5SDimitry Andric std::string exit_string; 24260b57cec5SDimitry Andric 24270b57cec5SDimitry Andric if (m_gdb_comm.IsConnected()) { 24280b57cec5SDimitry Andric if (m_public_state.GetValue() != eStateAttaching) { 2429972a253aSDimitry Andric llvm::Expected<int> kill_res = m_gdb_comm.KillProcess(GetID()); 24300b57cec5SDimitry Andric 2431972a253aSDimitry Andric if (kill_res) { 2432972a253aSDimitry Andric exit_status = kill_res.get(); 24330b57cec5SDimitry Andric #if defined(__APPLE__) 24340b57cec5SDimitry Andric // For Native processes on Mac OS X, we launch through the Host 24350b57cec5SDimitry Andric // Platform, then hand the process off to debugserver, which becomes 24360b57cec5SDimitry Andric // the parent process through "PT_ATTACH". Then when we go to kill 24370b57cec5SDimitry Andric // the process on Mac OS X we call ptrace(PT_KILL) to kill it, then 24380b57cec5SDimitry Andric // we call waitpid which returns with no error and the correct 24390b57cec5SDimitry Andric // status. But amusingly enough that doesn't seem to actually reap 24400b57cec5SDimitry Andric // the process, but instead it is left around as a Zombie. Probably 24410b57cec5SDimitry Andric // the kernel is in the process of switching ownership back to lldb 24420b57cec5SDimitry Andric // which was the original parent, and gets confused in the handoff. 24430b57cec5SDimitry Andric // Anyway, so call waitpid here to finally reap it. 24440b57cec5SDimitry Andric PlatformSP platform_sp(GetTarget().GetPlatform()); 24450b57cec5SDimitry Andric if (platform_sp && platform_sp->IsHost()) { 24460b57cec5SDimitry Andric int status; 24470b57cec5SDimitry Andric ::pid_t reap_pid; 24480b57cec5SDimitry Andric reap_pid = waitpid(GetID(), &status, WNOHANG); 24499dba64beSDimitry Andric LLDB_LOGF(log, "Reaped pid: %d, status: %d.\n", reap_pid, status); 24500b57cec5SDimitry Andric } 24510b57cec5SDimitry Andric #endif 24520b57cec5SDimitry Andric ClearThreadIDList(); 2453972a253aSDimitry Andric exit_string.assign("killed"); 24540b57cec5SDimitry Andric } else { 2455972a253aSDimitry Andric exit_string.assign(llvm::toString(kill_res.takeError())); 24560b57cec5SDimitry Andric } 24570b57cec5SDimitry Andric } else { 24580b57cec5SDimitry Andric exit_string.assign("killed or interrupted while attaching."); 24590b57cec5SDimitry Andric } 24600b57cec5SDimitry Andric } else { 24610b57cec5SDimitry Andric // If we missed setting the exit status on the way out, do it here. 24620b57cec5SDimitry Andric // NB set exit status can be called multiple times, the first one sets the 24630b57cec5SDimitry Andric // status. 24640b57cec5SDimitry Andric exit_string.assign("destroying when not connected to debugserver"); 24650b57cec5SDimitry Andric } 24660b57cec5SDimitry Andric 24670b57cec5SDimitry Andric SetExitStatus(exit_status, exit_string.c_str()); 24680b57cec5SDimitry Andric 24690b57cec5SDimitry Andric StopAsyncThread(); 24700b57cec5SDimitry Andric KillDebugserverProcess(); 2471972a253aSDimitry Andric return Status(); 24720b57cec5SDimitry Andric } 24730b57cec5SDimitry Andric 24740b57cec5SDimitry Andric void ProcessGDBRemote::SetLastStopPacket( 24750b57cec5SDimitry Andric const StringExtractorGDBRemote &response) { 24760b57cec5SDimitry Andric const bool did_exec = 24770b57cec5SDimitry Andric response.GetStringRef().find(";reason:exec;") != std::string::npos; 24780b57cec5SDimitry Andric if (did_exec) { 24791fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 24809dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::SetLastStopPacket () - detected exec"); 24810b57cec5SDimitry Andric 24820b57cec5SDimitry Andric m_thread_list_real.Clear(); 24830b57cec5SDimitry Andric m_thread_list.Clear(); 24840b57cec5SDimitry Andric BuildDynamicRegisterInfo(true); 24850b57cec5SDimitry Andric m_gdb_comm.ResetDiscoverableSettings(did_exec); 24860b57cec5SDimitry Andric } 24870b57cec5SDimitry Andric 2488349cc55cSDimitry Andric m_last_stop_packet = response; 24890b57cec5SDimitry Andric } 24900b57cec5SDimitry Andric 24910b57cec5SDimitry Andric void ProcessGDBRemote::SetUnixSignals(const UnixSignalsSP &signals_sp) { 24920b57cec5SDimitry Andric Process::SetUnixSignals(std::make_shared<GDBRemoteSignals>(signals_sp)); 24930b57cec5SDimitry Andric } 24940b57cec5SDimitry Andric 24950b57cec5SDimitry Andric // Process Queries 24960b57cec5SDimitry Andric 24970b57cec5SDimitry Andric bool ProcessGDBRemote::IsAlive() { 24980b57cec5SDimitry Andric return m_gdb_comm.IsConnected() && Process::IsAlive(); 24990b57cec5SDimitry Andric } 25000b57cec5SDimitry Andric 25010b57cec5SDimitry Andric addr_t ProcessGDBRemote::GetImageInfoAddress() { 25020b57cec5SDimitry Andric // request the link map address via the $qShlibInfoAddr packet 25030b57cec5SDimitry Andric lldb::addr_t addr = m_gdb_comm.GetShlibInfoAddr(); 25040b57cec5SDimitry Andric 25050b57cec5SDimitry Andric // the loaded module list can also provides a link map address 25060b57cec5SDimitry Andric if (addr == LLDB_INVALID_ADDRESS) { 25079dba64beSDimitry Andric llvm::Expected<LoadedModuleInfoList> list = GetLoadedModuleList(); 25089dba64beSDimitry Andric if (!list) { 25091fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 2510e8d8bef9SDimitry Andric LLDB_LOG_ERROR(log, list.takeError(), "Failed to read module list: {0}."); 25119dba64beSDimitry Andric } else { 25129dba64beSDimitry Andric addr = list->m_link_map; 25139dba64beSDimitry Andric } 25140b57cec5SDimitry Andric } 25150b57cec5SDimitry Andric 25160b57cec5SDimitry Andric return addr; 25170b57cec5SDimitry Andric } 25180b57cec5SDimitry Andric 25190b57cec5SDimitry Andric void ProcessGDBRemote::WillPublicStop() { 25200b57cec5SDimitry Andric // See if the GDB remote client supports the JSON threads info. If so, we 25210b57cec5SDimitry Andric // gather stop info for all threads, expedited registers, expedited memory, 25220b57cec5SDimitry Andric // runtime queue information (iOS and MacOSX only), and more. Expediting 25230b57cec5SDimitry Andric // memory will help stack backtracing be much faster. Expediting registers 25240b57cec5SDimitry Andric // will make sure we don't have to read the thread registers for GPRs. 25250b57cec5SDimitry Andric m_jthreadsinfo_sp = m_gdb_comm.GetThreadsInfo(); 25260b57cec5SDimitry Andric 25270b57cec5SDimitry Andric if (m_jthreadsinfo_sp) { 25280b57cec5SDimitry Andric // Now set the stop info for each thread and also expedite any registers 25290b57cec5SDimitry Andric // and memory that was in the jThreadsInfo response. 25300b57cec5SDimitry Andric StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray(); 25310b57cec5SDimitry Andric if (thread_infos) { 25320b57cec5SDimitry Andric const size_t n = thread_infos->GetSize(); 25330b57cec5SDimitry Andric for (size_t i = 0; i < n; ++i) { 25340b57cec5SDimitry Andric StructuredData::Dictionary *thread_dict = 25350b57cec5SDimitry Andric thread_infos->GetItemAtIndex(i)->GetAsDictionary(); 25360b57cec5SDimitry Andric if (thread_dict) 25370b57cec5SDimitry Andric SetThreadStopInfo(thread_dict); 25380b57cec5SDimitry Andric } 25390b57cec5SDimitry Andric } 25400b57cec5SDimitry Andric } 25410b57cec5SDimitry Andric } 25420b57cec5SDimitry Andric 25430b57cec5SDimitry Andric // Process Memory 25440b57cec5SDimitry Andric size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size, 25450b57cec5SDimitry Andric Status &error) { 25460b57cec5SDimitry Andric GetMaxMemorySize(); 25470b57cec5SDimitry Andric bool binary_memory_read = m_gdb_comm.GetxPacketSupported(); 25480b57cec5SDimitry Andric // M and m packets take 2 bytes for 1 byte of memory 25490b57cec5SDimitry Andric size_t max_memory_size = 25500b57cec5SDimitry Andric binary_memory_read ? m_max_memory_size : m_max_memory_size / 2; 25510b57cec5SDimitry Andric if (size > max_memory_size) { 25520b57cec5SDimitry Andric // Keep memory read sizes down to a sane limit. This function will be 25530b57cec5SDimitry Andric // called multiple times in order to complete the task by 25540b57cec5SDimitry Andric // lldb_private::Process so it is ok to do this. 25550b57cec5SDimitry Andric size = max_memory_size; 25560b57cec5SDimitry Andric } 25570b57cec5SDimitry Andric 25580b57cec5SDimitry Andric char packet[64]; 25590b57cec5SDimitry Andric int packet_len; 25600b57cec5SDimitry Andric packet_len = ::snprintf(packet, sizeof(packet), "%c%" PRIx64 ",%" PRIx64, 25610b57cec5SDimitry Andric binary_memory_read ? 'x' : 'm', (uint64_t)addr, 25620b57cec5SDimitry Andric (uint64_t)size); 25630b57cec5SDimitry Andric assert(packet_len + 1 < (int)sizeof(packet)); 25640b57cec5SDimitry Andric UNUSED_IF_ASSERT_DISABLED(packet_len); 25650b57cec5SDimitry Andric StringExtractorGDBRemote response; 2566fe6060f1SDimitry Andric if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response, 2567fe6060f1SDimitry Andric GetInterruptTimeout()) == 25680b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult::Success) { 25690b57cec5SDimitry Andric if (response.IsNormalResponse()) { 25700b57cec5SDimitry Andric error.Clear(); 25710b57cec5SDimitry Andric if (binary_memory_read) { 25720b57cec5SDimitry Andric // The lower level GDBRemoteCommunication packet receive layer has 25730b57cec5SDimitry Andric // already de-quoted any 0x7d character escaping that was present in 25740b57cec5SDimitry Andric // the packet 25750b57cec5SDimitry Andric 25760b57cec5SDimitry Andric size_t data_received_size = response.GetBytesLeft(); 25770b57cec5SDimitry Andric if (data_received_size > size) { 25780b57cec5SDimitry Andric // Don't write past the end of BUF if the remote debug server gave us 25790b57cec5SDimitry Andric // too much data for some reason. 25800b57cec5SDimitry Andric data_received_size = size; 25810b57cec5SDimitry Andric } 25820b57cec5SDimitry Andric memcpy(buf, response.GetStringRef().data(), data_received_size); 25830b57cec5SDimitry Andric return data_received_size; 25840b57cec5SDimitry Andric } else { 25850b57cec5SDimitry Andric return response.GetHexBytes( 25860b57cec5SDimitry Andric llvm::MutableArrayRef<uint8_t>((uint8_t *)buf, size), '\xdd'); 25870b57cec5SDimitry Andric } 25880b57cec5SDimitry Andric } else if (response.IsErrorResponse()) 25890b57cec5SDimitry Andric error.SetErrorStringWithFormat("memory read failed for 0x%" PRIx64, addr); 25900b57cec5SDimitry Andric else if (response.IsUnsupportedResponse()) 25910b57cec5SDimitry Andric error.SetErrorStringWithFormat( 25920b57cec5SDimitry Andric "GDB server does not support reading memory"); 25930b57cec5SDimitry Andric else 25940b57cec5SDimitry Andric error.SetErrorStringWithFormat( 25950b57cec5SDimitry Andric "unexpected response to GDB server memory read packet '%s': '%s'", 25969dba64beSDimitry Andric packet, response.GetStringRef().data()); 25970b57cec5SDimitry Andric } else { 25980b57cec5SDimitry Andric error.SetErrorStringWithFormat("failed to send packet: '%s'", packet); 25990b57cec5SDimitry Andric } 26000b57cec5SDimitry Andric return 0; 26010b57cec5SDimitry Andric } 26020b57cec5SDimitry Andric 2603fe6060f1SDimitry Andric bool ProcessGDBRemote::SupportsMemoryTagging() { 2604fe6060f1SDimitry Andric return m_gdb_comm.GetMemoryTaggingSupported(); 2605fe6060f1SDimitry Andric } 2606fe6060f1SDimitry Andric 2607fe6060f1SDimitry Andric llvm::Expected<std::vector<uint8_t>> 2608fe6060f1SDimitry Andric ProcessGDBRemote::DoReadMemoryTags(lldb::addr_t addr, size_t len, 2609fe6060f1SDimitry Andric int32_t type) { 2610fe6060f1SDimitry Andric // By this point ReadMemoryTags has validated that tagging is enabled 2611fe6060f1SDimitry Andric // for this target/process/address. 2612fe6060f1SDimitry Andric DataBufferSP buffer_sp = m_gdb_comm.ReadMemoryTags(addr, len, type); 2613fe6060f1SDimitry Andric if (!buffer_sp) { 2614fe6060f1SDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 2615fe6060f1SDimitry Andric "Error reading memory tags from remote"); 2616fe6060f1SDimitry Andric } 2617fe6060f1SDimitry Andric 2618fe6060f1SDimitry Andric // Return the raw tag data 2619fe6060f1SDimitry Andric llvm::ArrayRef<uint8_t> tag_data = buffer_sp->GetData(); 2620fe6060f1SDimitry Andric std::vector<uint8_t> got; 2621fe6060f1SDimitry Andric got.reserve(tag_data.size()); 2622fe6060f1SDimitry Andric std::copy(tag_data.begin(), tag_data.end(), std::back_inserter(got)); 2623fe6060f1SDimitry Andric return got; 2624fe6060f1SDimitry Andric } 2625fe6060f1SDimitry Andric 2626fe6060f1SDimitry Andric Status ProcessGDBRemote::DoWriteMemoryTags(lldb::addr_t addr, size_t len, 2627fe6060f1SDimitry Andric int32_t type, 2628fe6060f1SDimitry Andric const std::vector<uint8_t> &tags) { 2629fe6060f1SDimitry Andric // By now WriteMemoryTags should have validated that tagging is enabled 2630fe6060f1SDimitry Andric // for this target/process. 2631fe6060f1SDimitry Andric return m_gdb_comm.WriteMemoryTags(addr, len, type, tags); 2632fe6060f1SDimitry Andric } 2633fe6060f1SDimitry Andric 26340b57cec5SDimitry Andric Status ProcessGDBRemote::WriteObjectFile( 26350b57cec5SDimitry Andric std::vector<ObjectFile::LoadableData> entries) { 26360b57cec5SDimitry Andric Status error; 26370b57cec5SDimitry Andric // Sort the entries by address because some writes, like those to flash 26380b57cec5SDimitry Andric // memory, must happen in order of increasing address. 26390b57cec5SDimitry Andric std::stable_sort( 26400b57cec5SDimitry Andric std::begin(entries), std::end(entries), 26410b57cec5SDimitry Andric [](const ObjectFile::LoadableData a, const ObjectFile::LoadableData b) { 26420b57cec5SDimitry Andric return a.Dest < b.Dest; 26430b57cec5SDimitry Andric }); 26440b57cec5SDimitry Andric m_allow_flash_writes = true; 26450b57cec5SDimitry Andric error = Process::WriteObjectFile(entries); 26460b57cec5SDimitry Andric if (error.Success()) 26470b57cec5SDimitry Andric error = FlashDone(); 26480b57cec5SDimitry Andric else 26490b57cec5SDimitry Andric // Even though some of the writing failed, try to send a flash done if some 26500b57cec5SDimitry Andric // of the writing succeeded so the flash state is reset to normal, but 26510b57cec5SDimitry Andric // don't stomp on the error status that was set in the write failure since 26520b57cec5SDimitry Andric // that's the one we want to report back. 26530b57cec5SDimitry Andric FlashDone(); 26540b57cec5SDimitry Andric m_allow_flash_writes = false; 26550b57cec5SDimitry Andric return error; 26560b57cec5SDimitry Andric } 26570b57cec5SDimitry Andric 26580b57cec5SDimitry Andric bool ProcessGDBRemote::HasErased(FlashRange range) { 26590b57cec5SDimitry Andric auto size = m_erased_flash_ranges.GetSize(); 26600b57cec5SDimitry Andric for (size_t i = 0; i < size; ++i) 26610b57cec5SDimitry Andric if (m_erased_flash_ranges.GetEntryAtIndex(i)->Contains(range)) 26620b57cec5SDimitry Andric return true; 26630b57cec5SDimitry Andric return false; 26640b57cec5SDimitry Andric } 26650b57cec5SDimitry Andric 26660b57cec5SDimitry Andric Status ProcessGDBRemote::FlashErase(lldb::addr_t addr, size_t size) { 26670b57cec5SDimitry Andric Status status; 26680b57cec5SDimitry Andric 26690b57cec5SDimitry Andric MemoryRegionInfo region; 26700b57cec5SDimitry Andric status = GetMemoryRegionInfo(addr, region); 26710b57cec5SDimitry Andric if (!status.Success()) 26720b57cec5SDimitry Andric return status; 26730b57cec5SDimitry Andric 26740b57cec5SDimitry Andric // The gdb spec doesn't say if erasures are allowed across multiple regions, 26750b57cec5SDimitry Andric // but we'll disallow it to be safe and to keep the logic simple by worring 26760b57cec5SDimitry Andric // about only one region's block size. DoMemoryWrite is this function's 26770b57cec5SDimitry Andric // primary user, and it can easily keep writes within a single memory region 26780b57cec5SDimitry Andric if (addr + size > region.GetRange().GetRangeEnd()) { 26790b57cec5SDimitry Andric status.SetErrorString("Unable to erase flash in multiple regions"); 26800b57cec5SDimitry Andric return status; 26810b57cec5SDimitry Andric } 26820b57cec5SDimitry Andric 26830b57cec5SDimitry Andric uint64_t blocksize = region.GetBlocksize(); 26840b57cec5SDimitry Andric if (blocksize == 0) { 26850b57cec5SDimitry Andric status.SetErrorString("Unable to erase flash because blocksize is 0"); 26860b57cec5SDimitry Andric return status; 26870b57cec5SDimitry Andric } 26880b57cec5SDimitry Andric 26890b57cec5SDimitry Andric // Erasures can only be done on block boundary adresses, so round down addr 26900b57cec5SDimitry Andric // and round up size 26910b57cec5SDimitry Andric lldb::addr_t block_start_addr = addr - (addr % blocksize); 26920b57cec5SDimitry Andric size += (addr - block_start_addr); 26930b57cec5SDimitry Andric if ((size % blocksize) != 0) 26940b57cec5SDimitry Andric size += (blocksize - size % blocksize); 26950b57cec5SDimitry Andric 26960b57cec5SDimitry Andric FlashRange range(block_start_addr, size); 26970b57cec5SDimitry Andric 26980b57cec5SDimitry Andric if (HasErased(range)) 26990b57cec5SDimitry Andric return status; 27000b57cec5SDimitry Andric 27010b57cec5SDimitry Andric // We haven't erased the entire range, but we may have erased part of it. 27020b57cec5SDimitry Andric // (e.g., block A is already erased and range starts in A and ends in B). So, 27030b57cec5SDimitry Andric // adjust range if necessary to exclude already erased blocks. 27040b57cec5SDimitry Andric if (!m_erased_flash_ranges.IsEmpty()) { 27050b57cec5SDimitry Andric // Assuming that writes and erasures are done in increasing addr order, 27060b57cec5SDimitry Andric // because that is a requirement of the vFlashWrite command. Therefore, we 27070b57cec5SDimitry Andric // only need to look at the last range in the list for overlap. 27080b57cec5SDimitry Andric const auto &last_range = *m_erased_flash_ranges.Back(); 27090b57cec5SDimitry Andric if (range.GetRangeBase() < last_range.GetRangeEnd()) { 27100b57cec5SDimitry Andric auto overlap = last_range.GetRangeEnd() - range.GetRangeBase(); 27110b57cec5SDimitry Andric // overlap will be less than range.GetByteSize() or else HasErased() 27120b57cec5SDimitry Andric // would have been true 27130b57cec5SDimitry Andric range.SetByteSize(range.GetByteSize() - overlap); 27140b57cec5SDimitry Andric range.SetRangeBase(range.GetRangeBase() + overlap); 27150b57cec5SDimitry Andric } 27160b57cec5SDimitry Andric } 27170b57cec5SDimitry Andric 27180b57cec5SDimitry Andric StreamString packet; 27190b57cec5SDimitry Andric packet.Printf("vFlashErase:%" PRIx64 ",%" PRIx64, range.GetRangeBase(), 27200b57cec5SDimitry Andric (uint64_t)range.GetByteSize()); 27210b57cec5SDimitry Andric 27220b57cec5SDimitry Andric StringExtractorGDBRemote response; 27230b57cec5SDimitry Andric if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response, 2724fe6060f1SDimitry Andric GetInterruptTimeout()) == 27250b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult::Success) { 27260b57cec5SDimitry Andric if (response.IsOKResponse()) { 27270b57cec5SDimitry Andric m_erased_flash_ranges.Insert(range, true); 27280b57cec5SDimitry Andric } else { 27290b57cec5SDimitry Andric if (response.IsErrorResponse()) 27300b57cec5SDimitry Andric status.SetErrorStringWithFormat("flash erase failed for 0x%" PRIx64, 27310b57cec5SDimitry Andric addr); 27320b57cec5SDimitry Andric else if (response.IsUnsupportedResponse()) 27330b57cec5SDimitry Andric status.SetErrorStringWithFormat("GDB server does not support flashing"); 27340b57cec5SDimitry Andric else 27350b57cec5SDimitry Andric status.SetErrorStringWithFormat( 27360b57cec5SDimitry Andric "unexpected response to GDB server flash erase packet '%s': '%s'", 27379dba64beSDimitry Andric packet.GetData(), response.GetStringRef().data()); 27380b57cec5SDimitry Andric } 27390b57cec5SDimitry Andric } else { 27400b57cec5SDimitry Andric status.SetErrorStringWithFormat("failed to send packet: '%s'", 27410b57cec5SDimitry Andric packet.GetData()); 27420b57cec5SDimitry Andric } 27430b57cec5SDimitry Andric return status; 27440b57cec5SDimitry Andric } 27450b57cec5SDimitry Andric 27460b57cec5SDimitry Andric Status ProcessGDBRemote::FlashDone() { 27470b57cec5SDimitry Andric Status status; 27480b57cec5SDimitry Andric // If we haven't erased any blocks, then we must not have written anything 27490b57cec5SDimitry Andric // either, so there is no need to actually send a vFlashDone command 27500b57cec5SDimitry Andric if (m_erased_flash_ranges.IsEmpty()) 27510b57cec5SDimitry Andric return status; 27520b57cec5SDimitry Andric StringExtractorGDBRemote response; 2753fe6060f1SDimitry Andric if (m_gdb_comm.SendPacketAndWaitForResponse("vFlashDone", response, 2754fe6060f1SDimitry Andric GetInterruptTimeout()) == 27550b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult::Success) { 27560b57cec5SDimitry Andric if (response.IsOKResponse()) { 27570b57cec5SDimitry Andric m_erased_flash_ranges.Clear(); 27580b57cec5SDimitry Andric } else { 27590b57cec5SDimitry Andric if (response.IsErrorResponse()) 27600b57cec5SDimitry Andric status.SetErrorStringWithFormat("flash done failed"); 27610b57cec5SDimitry Andric else if (response.IsUnsupportedResponse()) 27620b57cec5SDimitry Andric status.SetErrorStringWithFormat("GDB server does not support flashing"); 27630b57cec5SDimitry Andric else 27640b57cec5SDimitry Andric status.SetErrorStringWithFormat( 27650b57cec5SDimitry Andric "unexpected response to GDB server flash done packet: '%s'", 27669dba64beSDimitry Andric response.GetStringRef().data()); 27670b57cec5SDimitry Andric } 27680b57cec5SDimitry Andric } else { 27690b57cec5SDimitry Andric status.SetErrorStringWithFormat("failed to send flash done packet"); 27700b57cec5SDimitry Andric } 27710b57cec5SDimitry Andric return status; 27720b57cec5SDimitry Andric } 27730b57cec5SDimitry Andric 27740b57cec5SDimitry Andric size_t ProcessGDBRemote::DoWriteMemory(addr_t addr, const void *buf, 27750b57cec5SDimitry Andric size_t size, Status &error) { 27760b57cec5SDimitry Andric GetMaxMemorySize(); 27770b57cec5SDimitry Andric // M and m packets take 2 bytes for 1 byte of memory 27780b57cec5SDimitry Andric size_t max_memory_size = m_max_memory_size / 2; 27790b57cec5SDimitry Andric if (size > max_memory_size) { 27800b57cec5SDimitry Andric // Keep memory read sizes down to a sane limit. This function will be 27810b57cec5SDimitry Andric // called multiple times in order to complete the task by 27820b57cec5SDimitry Andric // lldb_private::Process so it is ok to do this. 27830b57cec5SDimitry Andric size = max_memory_size; 27840b57cec5SDimitry Andric } 27850b57cec5SDimitry Andric 27860b57cec5SDimitry Andric StreamGDBRemote packet; 27870b57cec5SDimitry Andric 27880b57cec5SDimitry Andric MemoryRegionInfo region; 27890b57cec5SDimitry Andric Status region_status = GetMemoryRegionInfo(addr, region); 27900b57cec5SDimitry Andric 27910b57cec5SDimitry Andric bool is_flash = 27920b57cec5SDimitry Andric region_status.Success() && region.GetFlash() == MemoryRegionInfo::eYes; 27930b57cec5SDimitry Andric 27940b57cec5SDimitry Andric if (is_flash) { 27950b57cec5SDimitry Andric if (!m_allow_flash_writes) { 27960b57cec5SDimitry Andric error.SetErrorString("Writing to flash memory is not allowed"); 27970b57cec5SDimitry Andric return 0; 27980b57cec5SDimitry Andric } 27990b57cec5SDimitry Andric // Keep the write within a flash memory region 28000b57cec5SDimitry Andric if (addr + size > region.GetRange().GetRangeEnd()) 28010b57cec5SDimitry Andric size = region.GetRange().GetRangeEnd() - addr; 28020b57cec5SDimitry Andric // Flash memory must be erased before it can be written 28030b57cec5SDimitry Andric error = FlashErase(addr, size); 28040b57cec5SDimitry Andric if (!error.Success()) 28050b57cec5SDimitry Andric return 0; 28060b57cec5SDimitry Andric packet.Printf("vFlashWrite:%" PRIx64 ":", addr); 28070b57cec5SDimitry Andric packet.PutEscapedBytes(buf, size); 28080b57cec5SDimitry Andric } else { 28090b57cec5SDimitry Andric packet.Printf("M%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size); 28100b57cec5SDimitry Andric packet.PutBytesAsRawHex8(buf, size, endian::InlHostByteOrder(), 28110b57cec5SDimitry Andric endian::InlHostByteOrder()); 28120b57cec5SDimitry Andric } 28130b57cec5SDimitry Andric StringExtractorGDBRemote response; 28140b57cec5SDimitry Andric if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response, 2815fe6060f1SDimitry Andric GetInterruptTimeout()) == 28160b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult::Success) { 28170b57cec5SDimitry Andric if (response.IsOKResponse()) { 28180b57cec5SDimitry Andric error.Clear(); 28190b57cec5SDimitry Andric return size; 28200b57cec5SDimitry Andric } else if (response.IsErrorResponse()) 28210b57cec5SDimitry Andric error.SetErrorStringWithFormat("memory write failed for 0x%" PRIx64, 28220b57cec5SDimitry Andric addr); 28230b57cec5SDimitry Andric else if (response.IsUnsupportedResponse()) 28240b57cec5SDimitry Andric error.SetErrorStringWithFormat( 28250b57cec5SDimitry Andric "GDB server does not support writing memory"); 28260b57cec5SDimitry Andric else 28270b57cec5SDimitry Andric error.SetErrorStringWithFormat( 28280b57cec5SDimitry Andric "unexpected response to GDB server memory write packet '%s': '%s'", 28299dba64beSDimitry Andric packet.GetData(), response.GetStringRef().data()); 28300b57cec5SDimitry Andric } else { 28310b57cec5SDimitry Andric error.SetErrorStringWithFormat("failed to send packet: '%s'", 28320b57cec5SDimitry Andric packet.GetData()); 28330b57cec5SDimitry Andric } 28340b57cec5SDimitry Andric return 0; 28350b57cec5SDimitry Andric } 28360b57cec5SDimitry Andric 28370b57cec5SDimitry Andric lldb::addr_t ProcessGDBRemote::DoAllocateMemory(size_t size, 28380b57cec5SDimitry Andric uint32_t permissions, 28390b57cec5SDimitry Andric Status &error) { 284081ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process | LLDBLog::Expressions); 28410b57cec5SDimitry Andric addr_t allocated_addr = LLDB_INVALID_ADDRESS; 28420b57cec5SDimitry Andric 28430b57cec5SDimitry Andric if (m_gdb_comm.SupportsAllocDeallocMemory() != eLazyBoolNo) { 28440b57cec5SDimitry Andric allocated_addr = m_gdb_comm.AllocateMemory(size, permissions); 28450b57cec5SDimitry Andric if (allocated_addr != LLDB_INVALID_ADDRESS || 28460b57cec5SDimitry Andric m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolYes) 28470b57cec5SDimitry Andric return allocated_addr; 28480b57cec5SDimitry Andric } 28490b57cec5SDimitry Andric 28500b57cec5SDimitry Andric if (m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolNo) { 28510b57cec5SDimitry Andric // Call mmap() to create memory in the inferior.. 28520b57cec5SDimitry Andric unsigned prot = 0; 28530b57cec5SDimitry Andric if (permissions & lldb::ePermissionsReadable) 28540b57cec5SDimitry Andric prot |= eMmapProtRead; 28550b57cec5SDimitry Andric if (permissions & lldb::ePermissionsWritable) 28560b57cec5SDimitry Andric prot |= eMmapProtWrite; 28570b57cec5SDimitry Andric if (permissions & lldb::ePermissionsExecutable) 28580b57cec5SDimitry Andric prot |= eMmapProtExec; 28590b57cec5SDimitry Andric 28600b57cec5SDimitry Andric if (InferiorCallMmap(this, allocated_addr, 0, size, prot, 28610b57cec5SDimitry Andric eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) 28620b57cec5SDimitry Andric m_addr_to_mmap_size[allocated_addr] = size; 28630b57cec5SDimitry Andric else { 28640b57cec5SDimitry Andric allocated_addr = LLDB_INVALID_ADDRESS; 28659dba64beSDimitry Andric LLDB_LOGF(log, 28669dba64beSDimitry Andric "ProcessGDBRemote::%s no direct stub support for memory " 28670b57cec5SDimitry Andric "allocation, and InferiorCallMmap also failed - is stub " 28680b57cec5SDimitry Andric "missing register context save/restore capability?", 28690b57cec5SDimitry Andric __FUNCTION__); 28700b57cec5SDimitry Andric } 28710b57cec5SDimitry Andric } 28720b57cec5SDimitry Andric 28730b57cec5SDimitry Andric if (allocated_addr == LLDB_INVALID_ADDRESS) 28740b57cec5SDimitry Andric error.SetErrorStringWithFormat( 28750b57cec5SDimitry Andric "unable to allocate %" PRIu64 " bytes of memory with permissions %s", 28760b57cec5SDimitry Andric (uint64_t)size, GetPermissionsAsCString(permissions)); 28770b57cec5SDimitry Andric else 28780b57cec5SDimitry Andric error.Clear(); 28790b57cec5SDimitry Andric return allocated_addr; 28800b57cec5SDimitry Andric } 28810b57cec5SDimitry Andric 2882d56accc7SDimitry Andric Status ProcessGDBRemote::DoGetMemoryRegionInfo(addr_t load_addr, 28830b57cec5SDimitry Andric MemoryRegionInfo ®ion_info) { 28840b57cec5SDimitry Andric 28850b57cec5SDimitry Andric Status error(m_gdb_comm.GetMemoryRegionInfo(load_addr, region_info)); 28860b57cec5SDimitry Andric return error; 28870b57cec5SDimitry Andric } 28880b57cec5SDimitry Andric 288906c3fb27SDimitry Andric std::optional<uint32_t> ProcessGDBRemote::GetWatchpointSlotCount() { 289006c3fb27SDimitry Andric return m_gdb_comm.GetWatchpointSlotCount(); 28910b57cec5SDimitry Andric } 28920b57cec5SDimitry Andric 289306c3fb27SDimitry Andric std::optional<bool> ProcessGDBRemote::DoGetWatchpointReportedAfter() { 289406c3fb27SDimitry Andric return m_gdb_comm.GetWatchpointReportedAfter(); 28950b57cec5SDimitry Andric } 28960b57cec5SDimitry Andric 28970b57cec5SDimitry Andric Status ProcessGDBRemote::DoDeallocateMemory(lldb::addr_t addr) { 28980b57cec5SDimitry Andric Status error; 28990b57cec5SDimitry Andric LazyBool supported = m_gdb_comm.SupportsAllocDeallocMemory(); 29000b57cec5SDimitry Andric 29010b57cec5SDimitry Andric switch (supported) { 29020b57cec5SDimitry Andric case eLazyBoolCalculate: 29030b57cec5SDimitry Andric // We should never be deallocating memory without allocating memory first 29040b57cec5SDimitry Andric // so we should never get eLazyBoolCalculate 29050b57cec5SDimitry Andric error.SetErrorString( 29060b57cec5SDimitry Andric "tried to deallocate memory without ever allocating memory"); 29070b57cec5SDimitry Andric break; 29080b57cec5SDimitry Andric 29090b57cec5SDimitry Andric case eLazyBoolYes: 29100b57cec5SDimitry Andric if (!m_gdb_comm.DeallocateMemory(addr)) 29110b57cec5SDimitry Andric error.SetErrorStringWithFormat( 29120b57cec5SDimitry Andric "unable to deallocate memory at 0x%" PRIx64, addr); 29130b57cec5SDimitry Andric break; 29140b57cec5SDimitry Andric 29150b57cec5SDimitry Andric case eLazyBoolNo: 29160b57cec5SDimitry Andric // Call munmap() to deallocate memory in the inferior.. 29170b57cec5SDimitry Andric { 29180b57cec5SDimitry Andric MMapMap::iterator pos = m_addr_to_mmap_size.find(addr); 29190b57cec5SDimitry Andric if (pos != m_addr_to_mmap_size.end() && 29200b57cec5SDimitry Andric InferiorCallMunmap(this, addr, pos->second)) 29210b57cec5SDimitry Andric m_addr_to_mmap_size.erase(pos); 29220b57cec5SDimitry Andric else 29230b57cec5SDimitry Andric error.SetErrorStringWithFormat( 29240b57cec5SDimitry Andric "unable to deallocate memory at 0x%" PRIx64, addr); 29250b57cec5SDimitry Andric } 29260b57cec5SDimitry Andric break; 29270b57cec5SDimitry Andric } 29280b57cec5SDimitry Andric 29290b57cec5SDimitry Andric return error; 29300b57cec5SDimitry Andric } 29310b57cec5SDimitry Andric 29320b57cec5SDimitry Andric // Process STDIO 29330b57cec5SDimitry Andric size_t ProcessGDBRemote::PutSTDIN(const char *src, size_t src_len, 29340b57cec5SDimitry Andric Status &error) { 29350b57cec5SDimitry Andric if (m_stdio_communication.IsConnected()) { 29360b57cec5SDimitry Andric ConnectionStatus status; 2937bdd1243dSDimitry Andric m_stdio_communication.WriteAll(src, src_len, status, nullptr); 29380b57cec5SDimitry Andric } else if (m_stdin_forward) { 29390b57cec5SDimitry Andric m_gdb_comm.SendStdinNotification(src, src_len); 29400b57cec5SDimitry Andric } 29410b57cec5SDimitry Andric return 0; 29420b57cec5SDimitry Andric } 29430b57cec5SDimitry Andric 29440b57cec5SDimitry Andric Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) { 29450b57cec5SDimitry Andric Status error; 29460b57cec5SDimitry Andric assert(bp_site != nullptr); 29470b57cec5SDimitry Andric 29480b57cec5SDimitry Andric // Get logging info 29491fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Breakpoints); 29500b57cec5SDimitry Andric user_id_t site_id = bp_site->GetID(); 29510b57cec5SDimitry Andric 29520b57cec5SDimitry Andric // Get the breakpoint address 29530b57cec5SDimitry Andric const addr_t addr = bp_site->GetLoadAddress(); 29540b57cec5SDimitry Andric 29550b57cec5SDimitry Andric // Log that a breakpoint was requested 29569dba64beSDimitry Andric LLDB_LOGF(log, 29579dba64beSDimitry Andric "ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 29580b57cec5SDimitry Andric ") address = 0x%" PRIx64, 29590b57cec5SDimitry Andric site_id, (uint64_t)addr); 29600b57cec5SDimitry Andric 29610b57cec5SDimitry Andric // Breakpoint already exists and is enabled 29620b57cec5SDimitry Andric if (bp_site->IsEnabled()) { 29639dba64beSDimitry Andric LLDB_LOGF(log, 29649dba64beSDimitry Andric "ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 29650b57cec5SDimitry Andric ") address = 0x%" PRIx64 " -- SUCCESS (already enabled)", 29660b57cec5SDimitry Andric site_id, (uint64_t)addr); 29670b57cec5SDimitry Andric return error; 29680b57cec5SDimitry Andric } 29690b57cec5SDimitry Andric 29700b57cec5SDimitry Andric // Get the software breakpoint trap opcode size 29710b57cec5SDimitry Andric const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site); 29720b57cec5SDimitry Andric 29730b57cec5SDimitry Andric // SupportsGDBStoppointPacket() simply checks a boolean, indicating if this 29740b57cec5SDimitry Andric // breakpoint type is supported by the remote stub. These are set to true by 29750b57cec5SDimitry Andric // default, and later set to false only after we receive an unimplemented 29760b57cec5SDimitry Andric // response when sending a breakpoint packet. This means initially that 29770b57cec5SDimitry Andric // unless we were specifically instructed to use a hardware breakpoint, LLDB 29780b57cec5SDimitry Andric // will attempt to set a software breakpoint. HardwareRequired() also queries 29790b57cec5SDimitry Andric // a boolean variable which indicates if the user specifically asked for 29800b57cec5SDimitry Andric // hardware breakpoints. If true then we will skip over software 29810b57cec5SDimitry Andric // breakpoints. 29820b57cec5SDimitry Andric if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware) && 29830b57cec5SDimitry Andric (!bp_site->HardwareRequired())) { 29840b57cec5SDimitry Andric // Try to send off a software breakpoint packet ($Z0) 29850b57cec5SDimitry Andric uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket( 2986fe6060f1SDimitry Andric eBreakpointSoftware, true, addr, bp_op_size, GetInterruptTimeout()); 29870b57cec5SDimitry Andric if (error_no == 0) { 29880b57cec5SDimitry Andric // The breakpoint was placed successfully 29890b57cec5SDimitry Andric bp_site->SetEnabled(true); 29900b57cec5SDimitry Andric bp_site->SetType(BreakpointSite::eExternal); 29910b57cec5SDimitry Andric return error; 29920b57cec5SDimitry Andric } 29930b57cec5SDimitry Andric 29940b57cec5SDimitry Andric // SendGDBStoppointTypePacket() will return an error if it was unable to 29950b57cec5SDimitry Andric // set this breakpoint. We need to differentiate between a error specific 29960b57cec5SDimitry Andric // to placing this breakpoint or if we have learned that this breakpoint 29970b57cec5SDimitry Andric // type is unsupported. To do this, we must test the support boolean for 29980b57cec5SDimitry Andric // this breakpoint type to see if it now indicates that this breakpoint 29990b57cec5SDimitry Andric // type is unsupported. If they are still supported then we should return 30000b57cec5SDimitry Andric // with the error code. If they are now unsupported, then we would like to 30010b57cec5SDimitry Andric // fall through and try another form of breakpoint. 30020b57cec5SDimitry Andric if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware)) { 30030b57cec5SDimitry Andric if (error_no != UINT8_MAX) 30040b57cec5SDimitry Andric error.SetErrorStringWithFormat( 30055ffd83dbSDimitry Andric "error: %d sending the breakpoint request", error_no); 30060b57cec5SDimitry Andric else 30070b57cec5SDimitry Andric error.SetErrorString("error sending the breakpoint request"); 30080b57cec5SDimitry Andric return error; 30090b57cec5SDimitry Andric } 30100b57cec5SDimitry Andric 30110b57cec5SDimitry Andric // We reach here when software breakpoints have been found to be 30120b57cec5SDimitry Andric // unsupported. For future calls to set a breakpoint, we will not attempt 30130b57cec5SDimitry Andric // to set a breakpoint with a type that is known not to be supported. 30149dba64beSDimitry Andric LLDB_LOGF(log, "Software breakpoints are unsupported"); 30150b57cec5SDimitry Andric 30160b57cec5SDimitry Andric // So we will fall through and try a hardware breakpoint 30170b57cec5SDimitry Andric } 30180b57cec5SDimitry Andric 30190b57cec5SDimitry Andric // The process of setting a hardware breakpoint is much the same as above. 30200b57cec5SDimitry Andric // We check the supported boolean for this breakpoint type, and if it is 30210b57cec5SDimitry Andric // thought to be supported then we will try to set this breakpoint with a 30220b57cec5SDimitry Andric // hardware breakpoint. 30230b57cec5SDimitry Andric if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) { 30240b57cec5SDimitry Andric // Try to send off a hardware breakpoint packet ($Z1) 30250b57cec5SDimitry Andric uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket( 3026fe6060f1SDimitry Andric eBreakpointHardware, true, addr, bp_op_size, GetInterruptTimeout()); 30270b57cec5SDimitry Andric if (error_no == 0) { 30280b57cec5SDimitry Andric // The breakpoint was placed successfully 30290b57cec5SDimitry Andric bp_site->SetEnabled(true); 30300b57cec5SDimitry Andric bp_site->SetType(BreakpointSite::eHardware); 30310b57cec5SDimitry Andric return error; 30320b57cec5SDimitry Andric } 30330b57cec5SDimitry Andric 30340b57cec5SDimitry Andric // Check if the error was something other then an unsupported breakpoint 30350b57cec5SDimitry Andric // type 30360b57cec5SDimitry Andric if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) { 30370b57cec5SDimitry Andric // Unable to set this hardware breakpoint 30380b57cec5SDimitry Andric if (error_no != UINT8_MAX) 30390b57cec5SDimitry Andric error.SetErrorStringWithFormat( 30400b57cec5SDimitry Andric "error: %d sending the hardware breakpoint request " 30410b57cec5SDimitry Andric "(hardware breakpoint resources might be exhausted or unavailable)", 30420b57cec5SDimitry Andric error_no); 30430b57cec5SDimitry Andric else 30440b57cec5SDimitry Andric error.SetErrorString("error sending the hardware breakpoint request " 30450b57cec5SDimitry Andric "(hardware breakpoint resources " 30460b57cec5SDimitry Andric "might be exhausted or unavailable)"); 30470b57cec5SDimitry Andric return error; 30480b57cec5SDimitry Andric } 30490b57cec5SDimitry Andric 30500b57cec5SDimitry Andric // We will reach here when the stub gives an unsupported response to a 30510b57cec5SDimitry Andric // hardware breakpoint 30529dba64beSDimitry Andric LLDB_LOGF(log, "Hardware breakpoints are unsupported"); 30530b57cec5SDimitry Andric 30540b57cec5SDimitry Andric // Finally we will falling through to a #trap style breakpoint 30550b57cec5SDimitry Andric } 30560b57cec5SDimitry Andric 30570b57cec5SDimitry Andric // Don't fall through when hardware breakpoints were specifically requested 30580b57cec5SDimitry Andric if (bp_site->HardwareRequired()) { 30590b57cec5SDimitry Andric error.SetErrorString("hardware breakpoints are not supported"); 30600b57cec5SDimitry Andric return error; 30610b57cec5SDimitry Andric } 30620b57cec5SDimitry Andric 30630b57cec5SDimitry Andric // As a last resort we want to place a manual breakpoint. An instruction is 30640b57cec5SDimitry Andric // placed into the process memory using memory write packets. 30650b57cec5SDimitry Andric return EnableSoftwareBreakpoint(bp_site); 30660b57cec5SDimitry Andric } 30670b57cec5SDimitry Andric 30680b57cec5SDimitry Andric Status ProcessGDBRemote::DisableBreakpointSite(BreakpointSite *bp_site) { 30690b57cec5SDimitry Andric Status error; 30700b57cec5SDimitry Andric assert(bp_site != nullptr); 30710b57cec5SDimitry Andric addr_t addr = bp_site->GetLoadAddress(); 30720b57cec5SDimitry Andric user_id_t site_id = bp_site->GetID(); 30731fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Breakpoints); 30749dba64beSDimitry Andric LLDB_LOGF(log, 30759dba64beSDimitry Andric "ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 30760b57cec5SDimitry Andric ") addr = 0x%8.8" PRIx64, 30770b57cec5SDimitry Andric site_id, (uint64_t)addr); 30780b57cec5SDimitry Andric 30790b57cec5SDimitry Andric if (bp_site->IsEnabled()) { 30800b57cec5SDimitry Andric const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site); 30810b57cec5SDimitry Andric 30820b57cec5SDimitry Andric BreakpointSite::Type bp_type = bp_site->GetType(); 30830b57cec5SDimitry Andric switch (bp_type) { 30840b57cec5SDimitry Andric case BreakpointSite::eSoftware: 30850b57cec5SDimitry Andric error = DisableSoftwareBreakpoint(bp_site); 30860b57cec5SDimitry Andric break; 30870b57cec5SDimitry Andric 30880b57cec5SDimitry Andric case BreakpointSite::eHardware: 30890b57cec5SDimitry Andric if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, false, 3090fe6060f1SDimitry Andric addr, bp_op_size, 3091fe6060f1SDimitry Andric GetInterruptTimeout())) 30920b57cec5SDimitry Andric error.SetErrorToGenericError(); 30930b57cec5SDimitry Andric break; 30940b57cec5SDimitry Andric 30950b57cec5SDimitry Andric case BreakpointSite::eExternal: { 3096e8d8bef9SDimitry Andric if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false, 3097fe6060f1SDimitry Andric addr, bp_op_size, 3098fe6060f1SDimitry Andric GetInterruptTimeout())) 30990b57cec5SDimitry Andric error.SetErrorToGenericError(); 31000b57cec5SDimitry Andric } break; 31010b57cec5SDimitry Andric } 31020b57cec5SDimitry Andric if (error.Success()) 31030b57cec5SDimitry Andric bp_site->SetEnabled(false); 31040b57cec5SDimitry Andric } else { 31059dba64beSDimitry Andric LLDB_LOGF(log, 31069dba64beSDimitry Andric "ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 31070b57cec5SDimitry Andric ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", 31080b57cec5SDimitry Andric site_id, (uint64_t)addr); 31090b57cec5SDimitry Andric return error; 31100b57cec5SDimitry Andric } 31110b57cec5SDimitry Andric 31120b57cec5SDimitry Andric if (error.Success()) 31130b57cec5SDimitry Andric error.SetErrorToGenericError(); 31140b57cec5SDimitry Andric return error; 31150b57cec5SDimitry Andric } 31160b57cec5SDimitry Andric 31170b57cec5SDimitry Andric // Pre-requisite: wp != NULL. 3118*5f757f3fSDimitry Andric static GDBStoppointType 3119*5f757f3fSDimitry Andric GetGDBStoppointType(const WatchpointResourceSP &wp_res_sp) { 3120*5f757f3fSDimitry Andric assert(wp_res_sp); 3121*5f757f3fSDimitry Andric bool read = wp_res_sp->WatchpointResourceRead(); 3122*5f757f3fSDimitry Andric bool write = wp_res_sp->WatchpointResourceWrite(); 31230b57cec5SDimitry Andric 3124*5f757f3fSDimitry Andric assert((read || write) && 3125*5f757f3fSDimitry Andric "WatchpointResource type is neither read nor write"); 3126*5f757f3fSDimitry Andric if (read && write) 31270b57cec5SDimitry Andric return eWatchpointReadWrite; 3128*5f757f3fSDimitry Andric else if (read) 31290b57cec5SDimitry Andric return eWatchpointRead; 3130*5f757f3fSDimitry Andric else 31310b57cec5SDimitry Andric return eWatchpointWrite; 31320b57cec5SDimitry Andric } 31330b57cec5SDimitry Andric 3134*5f757f3fSDimitry Andric Status ProcessGDBRemote::EnableWatchpoint(WatchpointSP wp_sp, bool notify) { 31350b57cec5SDimitry Andric Status error; 3136*5f757f3fSDimitry Andric if (!wp_sp) { 3137*5f757f3fSDimitry Andric error.SetErrorString("No watchpoint specified"); 3138*5f757f3fSDimitry Andric return error; 3139*5f757f3fSDimitry Andric } 3140*5f757f3fSDimitry Andric user_id_t watchID = wp_sp->GetID(); 3141*5f757f3fSDimitry Andric addr_t addr = wp_sp->GetLoadAddress(); 31421fd87a68SDimitry Andric Log *log(GetLog(GDBRLog::Watchpoints)); 31439dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ")", 31440b57cec5SDimitry Andric watchID); 3145*5f757f3fSDimitry Andric if (wp_sp->IsEnabled()) { 31469dba64beSDimitry Andric LLDB_LOGF(log, 31479dba64beSDimitry Andric "ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 31480b57cec5SDimitry Andric ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", 31490b57cec5SDimitry Andric watchID, (uint64_t)addr); 31500b57cec5SDimitry Andric return error; 31510b57cec5SDimitry Andric } 31520b57cec5SDimitry Andric 3153*5f757f3fSDimitry Andric bool read = wp_sp->WatchpointRead(); 3154*5f757f3fSDimitry Andric bool write = wp_sp->WatchpointWrite() || wp_sp->WatchpointModify(); 3155*5f757f3fSDimitry Andric size_t size = wp_sp->GetByteSize(); 3156*5f757f3fSDimitry Andric 3157*5f757f3fSDimitry Andric // New WatchpointResources needed to implement this Watchpoint. 3158*5f757f3fSDimitry Andric std::vector<WatchpointResourceSP> resources; 3159*5f757f3fSDimitry Andric 3160*5f757f3fSDimitry Andric // LWP_TODO: Break up the user's request into pieces that can be watched 3161*5f757f3fSDimitry Andric // given the capabilities of the target cpu / stub software. 3162*5f757f3fSDimitry Andric // As a default, breaking the watched region up into target-pointer-sized, 3163*5f757f3fSDimitry Andric // aligned, groups. 3164*5f757f3fSDimitry Andric // 3165*5f757f3fSDimitry Andric // Beyond the default, a stub can / should inform us of its capabilities, 3166*5f757f3fSDimitry Andric // e.g. a stub that can do AArch64 power-of-2 MASK watchpoints. 3167*5f757f3fSDimitry Andric // 3168*5f757f3fSDimitry Andric // And the cpu may have unique capabilities. AArch64 BAS watchpoints 3169*5f757f3fSDimitry Andric // can watch any sequential bytes in a doubleword, but Intel watchpoints 3170*5f757f3fSDimitry Andric // can only watch 1, 2, 4, 8 bytes within a doubleword. 3171*5f757f3fSDimitry Andric WatchpointResourceSP wp_res_sp = 3172*5f757f3fSDimitry Andric std::make_shared<WatchpointResource>(addr, size, read, write); 3173*5f757f3fSDimitry Andric resources.push_back(wp_res_sp); 3174*5f757f3fSDimitry Andric 3175*5f757f3fSDimitry Andric // LWP_TODO: Now that we know the WP Resources needed to implement this 3176*5f757f3fSDimitry Andric // Watchpoint, we need to look at currently allocated Resources in the 3177*5f757f3fSDimitry Andric // Process and if they match, or are within the same memory granule, or 3178*5f757f3fSDimitry Andric // overlapping memory ranges, then we need to combine them. e.g. one 3179*5f757f3fSDimitry Andric // Watchpoint watching 1 byte at 0x1002 and a second watchpoint watching 1 3180*5f757f3fSDimitry Andric // byte at 0x1003, they must use the same hardware watchpoint register 3181*5f757f3fSDimitry Andric // (Resource) to watch them. 3182*5f757f3fSDimitry Andric 3183*5f757f3fSDimitry Andric // This may mean that an existing resource changes its type (read to 3184*5f757f3fSDimitry Andric // read+write) or address range it is watching, in which case the old 3185*5f757f3fSDimitry Andric // watchpoint needs to be disabled and the new Resource addr/size/type 3186*5f757f3fSDimitry Andric // watchpoint enabled. 3187*5f757f3fSDimitry Andric 3188*5f757f3fSDimitry Andric // If we modify a shared Resource to accomodate this newly added Watchpoint, 3189*5f757f3fSDimitry Andric // and we are unable to set all of the Resources for it in the inferior, we 3190*5f757f3fSDimitry Andric // will return an error for this Watchpoint and the shared Resource should 3191*5f757f3fSDimitry Andric // be restored. e.g. this Watchpoint requires three Resources, one which 3192*5f757f3fSDimitry Andric // is shared with another Watchpoint. We extend the shared Resouce to 3193*5f757f3fSDimitry Andric // handle both Watchpoints and we try to set two new ones. But if we don't 3194*5f757f3fSDimitry Andric // have sufficient watchpoint register for all 3, we need to show an error 3195*5f757f3fSDimitry Andric // for creating this Watchpoint and we should reset the shared Resource to 3196*5f757f3fSDimitry Andric // its original configuration because it is no longer shared. 3197*5f757f3fSDimitry Andric 3198*5f757f3fSDimitry Andric bool set_all_resources = true; 3199*5f757f3fSDimitry Andric std::vector<WatchpointResourceSP> succesfully_set_resources; 3200*5f757f3fSDimitry Andric for (const auto &wp_res_sp : resources) { 3201*5f757f3fSDimitry Andric addr_t addr = wp_res_sp->GetLoadAddress(); 3202*5f757f3fSDimitry Andric size_t size = wp_res_sp->GetByteSize(); 3203*5f757f3fSDimitry Andric GDBStoppointType type = GetGDBStoppointType(wp_res_sp); 3204*5f757f3fSDimitry Andric if (!m_gdb_comm.SupportsGDBStoppointPacket(type) || 3205*5f757f3fSDimitry Andric m_gdb_comm.SendGDBStoppointTypePacket(type, true, addr, size, 3206*5f757f3fSDimitry Andric GetInterruptTimeout())) { 3207*5f757f3fSDimitry Andric set_all_resources = false; 3208*5f757f3fSDimitry Andric break; 32090b57cec5SDimitry Andric } else { 3210*5f757f3fSDimitry Andric succesfully_set_resources.push_back(wp_res_sp); 32110b57cec5SDimitry Andric } 3212*5f757f3fSDimitry Andric } 3213*5f757f3fSDimitry Andric if (set_all_resources) { 3214*5f757f3fSDimitry Andric wp_sp->SetEnabled(true, notify); 3215*5f757f3fSDimitry Andric for (const auto &wp_res_sp : resources) { 3216*5f757f3fSDimitry Andric // LWP_TODO: If we expanded/reused an existing Resource, 3217*5f757f3fSDimitry Andric // it's already in the WatchpointResourceList. 3218*5f757f3fSDimitry Andric wp_res_sp->AddConstituent(wp_sp); 3219*5f757f3fSDimitry Andric m_watchpoint_resource_list.Add(wp_res_sp); 3220*5f757f3fSDimitry Andric } 3221*5f757f3fSDimitry Andric return error; 3222*5f757f3fSDimitry Andric } else { 3223*5f757f3fSDimitry Andric // We failed to allocate one of the resources. Unset all 3224*5f757f3fSDimitry Andric // of the new resources we did successfully set in the 3225*5f757f3fSDimitry Andric // process. 3226*5f757f3fSDimitry Andric for (const auto &wp_res_sp : succesfully_set_resources) { 3227*5f757f3fSDimitry Andric addr_t addr = wp_res_sp->GetLoadAddress(); 3228*5f757f3fSDimitry Andric size_t size = wp_res_sp->GetByteSize(); 3229*5f757f3fSDimitry Andric GDBStoppointType type = GetGDBStoppointType(wp_res_sp); 3230*5f757f3fSDimitry Andric m_gdb_comm.SendGDBStoppointTypePacket(type, false, addr, size, 3231*5f757f3fSDimitry Andric GetInterruptTimeout()); 3232*5f757f3fSDimitry Andric } 3233*5f757f3fSDimitry Andric error.SetErrorString("Setting one of the watchpoint resources failed"); 3234*5f757f3fSDimitry Andric } 32350b57cec5SDimitry Andric return error; 32360b57cec5SDimitry Andric } 32370b57cec5SDimitry Andric 3238*5f757f3fSDimitry Andric Status ProcessGDBRemote::DisableWatchpoint(WatchpointSP wp_sp, bool notify) { 32390b57cec5SDimitry Andric Status error; 3240*5f757f3fSDimitry Andric if (!wp_sp) { 3241*5f757f3fSDimitry Andric error.SetErrorString("Watchpoint argument was NULL."); 3242*5f757f3fSDimitry Andric return error; 3243*5f757f3fSDimitry Andric } 3244*5f757f3fSDimitry Andric 3245*5f757f3fSDimitry Andric user_id_t watchID = wp_sp->GetID(); 32460b57cec5SDimitry Andric 32471fd87a68SDimitry Andric Log *log(GetLog(GDBRLog::Watchpoints)); 32480b57cec5SDimitry Andric 3249*5f757f3fSDimitry Andric addr_t addr = wp_sp->GetLoadAddress(); 32500b57cec5SDimitry Andric 32519dba64beSDimitry Andric LLDB_LOGF(log, 32529dba64beSDimitry Andric "ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 32530b57cec5SDimitry Andric ") addr = 0x%8.8" PRIx64, 32540b57cec5SDimitry Andric watchID, (uint64_t)addr); 32550b57cec5SDimitry Andric 3256*5f757f3fSDimitry Andric if (!wp_sp->IsEnabled()) { 32579dba64beSDimitry Andric LLDB_LOGF(log, 32589dba64beSDimitry Andric "ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 32590b57cec5SDimitry Andric ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", 32600b57cec5SDimitry Andric watchID, (uint64_t)addr); 32610b57cec5SDimitry Andric // See also 'class WatchpointSentry' within StopInfo.cpp. This disabling 32620b57cec5SDimitry Andric // attempt might come from the user-supplied actions, we'll route it in 32630b57cec5SDimitry Andric // order for the watchpoint object to intelligently process this action. 3264*5f757f3fSDimitry Andric wp_sp->SetEnabled(false, notify); 32650b57cec5SDimitry Andric return error; 32660b57cec5SDimitry Andric } 32670b57cec5SDimitry Andric 3268*5f757f3fSDimitry Andric if (wp_sp->IsHardware()) { 3269*5f757f3fSDimitry Andric bool disabled_all = true; 3270*5f757f3fSDimitry Andric 3271*5f757f3fSDimitry Andric std::vector<WatchpointResourceSP> unused_resources; 3272*5f757f3fSDimitry Andric for (const auto &wp_res_sp : m_watchpoint_resource_list.Sites()) { 3273*5f757f3fSDimitry Andric if (wp_res_sp->ConstituentsContains(wp_sp)) { 3274*5f757f3fSDimitry Andric GDBStoppointType type = GetGDBStoppointType(wp_res_sp); 3275*5f757f3fSDimitry Andric addr_t addr = wp_res_sp->GetLoadAddress(); 3276*5f757f3fSDimitry Andric size_t size = wp_res_sp->GetByteSize(); 3277*5f757f3fSDimitry Andric if (m_gdb_comm.SendGDBStoppointTypePacket(type, false, addr, size, 3278*5f757f3fSDimitry Andric GetInterruptTimeout())) { 3279*5f757f3fSDimitry Andric disabled_all = false; 32800b57cec5SDimitry Andric } else { 3281*5f757f3fSDimitry Andric wp_res_sp->RemoveConstituent(wp_sp); 3282*5f757f3fSDimitry Andric if (wp_res_sp->GetNumberOfConstituents() == 0) 3283*5f757f3fSDimitry Andric unused_resources.push_back(wp_res_sp); 32840b57cec5SDimitry Andric } 3285*5f757f3fSDimitry Andric } 3286*5f757f3fSDimitry Andric } 3287*5f757f3fSDimitry Andric for (auto &wp_res_sp : unused_resources) 3288*5f757f3fSDimitry Andric m_watchpoint_resource_list.Remove(wp_res_sp->GetID()); 3289*5f757f3fSDimitry Andric 3290*5f757f3fSDimitry Andric wp_sp->SetEnabled(false, notify); 3291*5f757f3fSDimitry Andric if (!disabled_all) 3292*5f757f3fSDimitry Andric error.SetErrorString("Failure disabling one of the watchpoint locations"); 3293*5f757f3fSDimitry Andric } 32940b57cec5SDimitry Andric return error; 32950b57cec5SDimitry Andric } 32960b57cec5SDimitry Andric 32970b57cec5SDimitry Andric void ProcessGDBRemote::Clear() { 32980b57cec5SDimitry Andric m_thread_list_real.Clear(); 32990b57cec5SDimitry Andric m_thread_list.Clear(); 33000b57cec5SDimitry Andric } 33010b57cec5SDimitry Andric 33020b57cec5SDimitry Andric Status ProcessGDBRemote::DoSignal(int signo) { 33030b57cec5SDimitry Andric Status error; 33041fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 33059dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::DoSignal (signal = %d)", signo); 33060b57cec5SDimitry Andric 3307fe6060f1SDimitry Andric if (!m_gdb_comm.SendAsyncSignal(signo, GetInterruptTimeout())) 33080b57cec5SDimitry Andric error.SetErrorStringWithFormat("failed to send signal %i", signo); 33090b57cec5SDimitry Andric return error; 33100b57cec5SDimitry Andric } 33110b57cec5SDimitry Andric 33120b57cec5SDimitry Andric Status 33130b57cec5SDimitry Andric ProcessGDBRemote::EstablishConnectionIfNeeded(const ProcessInfo &process_info) { 33140b57cec5SDimitry Andric // Make sure we aren't already connected? 33150b57cec5SDimitry Andric if (m_gdb_comm.IsConnected()) 33160b57cec5SDimitry Andric return Status(); 33170b57cec5SDimitry Andric 33180b57cec5SDimitry Andric PlatformSP platform_sp(GetTarget().GetPlatform()); 33190b57cec5SDimitry Andric if (platform_sp && !platform_sp->IsHost()) 33200b57cec5SDimitry Andric return Status("Lost debug server connection"); 33210b57cec5SDimitry Andric 33220b57cec5SDimitry Andric auto error = LaunchAndConnectToDebugserver(process_info); 33230b57cec5SDimitry Andric if (error.Fail()) { 33240b57cec5SDimitry Andric const char *error_string = error.AsCString(); 33250b57cec5SDimitry Andric if (error_string == nullptr) 33260b57cec5SDimitry Andric error_string = "unable to launch " DEBUGSERVER_BASENAME; 33270b57cec5SDimitry Andric } 33280b57cec5SDimitry Andric return error; 33290b57cec5SDimitry Andric } 33300b57cec5SDimitry Andric #if !defined(_WIN32) 33310b57cec5SDimitry Andric #define USE_SOCKETPAIR_FOR_LOCAL_CONNECTION 1 33320b57cec5SDimitry Andric #endif 33330b57cec5SDimitry Andric 33340b57cec5SDimitry Andric #ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION 33350b57cec5SDimitry Andric static bool SetCloexecFlag(int fd) { 33360b57cec5SDimitry Andric #if defined(FD_CLOEXEC) 33370b57cec5SDimitry Andric int flags = ::fcntl(fd, F_GETFD); 33380b57cec5SDimitry Andric if (flags == -1) 33390b57cec5SDimitry Andric return false; 33400b57cec5SDimitry Andric return (::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == 0); 33410b57cec5SDimitry Andric #else 33420b57cec5SDimitry Andric return false; 33430b57cec5SDimitry Andric #endif 33440b57cec5SDimitry Andric } 33450b57cec5SDimitry Andric #endif 33460b57cec5SDimitry Andric 33470b57cec5SDimitry Andric Status ProcessGDBRemote::LaunchAndConnectToDebugserver( 33480b57cec5SDimitry Andric const ProcessInfo &process_info) { 33490b57cec5SDimitry Andric using namespace std::placeholders; // For _1, _2, etc. 33500b57cec5SDimitry Andric 33510b57cec5SDimitry Andric Status error; 33520b57cec5SDimitry Andric if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID) { 33530b57cec5SDimitry Andric // If we locate debugserver, keep that located version around 33540b57cec5SDimitry Andric static FileSpec g_debugserver_file_spec; 33550b57cec5SDimitry Andric 33560b57cec5SDimitry Andric ProcessLaunchInfo debugserver_launch_info; 33570b57cec5SDimitry Andric // Make debugserver run in its own session so signals generated by special 33580b57cec5SDimitry Andric // terminal key sequences (^C) don't affect debugserver. 33590b57cec5SDimitry Andric debugserver_launch_info.SetLaunchInSeparateProcessGroup(true); 33600b57cec5SDimitry Andric 33610b57cec5SDimitry Andric const std::weak_ptr<ProcessGDBRemote> this_wp = 33620b57cec5SDimitry Andric std::static_pointer_cast<ProcessGDBRemote>(shared_from_this()); 33630b57cec5SDimitry Andric debugserver_launch_info.SetMonitorProcessCallback( 336481ad6265SDimitry Andric std::bind(MonitorDebugserverProcess, this_wp, _1, _2, _3)); 33650b57cec5SDimitry Andric debugserver_launch_info.SetUserID(process_info.GetUserID()); 33660b57cec5SDimitry Andric 33675ffd83dbSDimitry Andric #if defined(__APPLE__) 33685ffd83dbSDimitry Andric // On macOS 11, we need to support x86_64 applications translated to 33695ffd83dbSDimitry Andric // arm64. We check whether a binary is translated and spawn the correct 33705ffd83dbSDimitry Andric // debugserver accordingly. 33715ffd83dbSDimitry Andric int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, 33725ffd83dbSDimitry Andric static_cast<int>(process_info.GetProcessID()) }; 33735ffd83dbSDimitry Andric struct kinfo_proc processInfo; 33745ffd83dbSDimitry Andric size_t bufsize = sizeof(processInfo); 33755ffd83dbSDimitry Andric if (sysctl(mib, (unsigned)(sizeof(mib)/sizeof(int)), &processInfo, 33765ffd83dbSDimitry Andric &bufsize, NULL, 0) == 0 && bufsize > 0) { 33775ffd83dbSDimitry Andric if (processInfo.kp_proc.p_flag & P_TRANSLATED) { 33785ffd83dbSDimitry Andric FileSpec rosetta_debugserver("/Library/Apple/usr/libexec/oah/debugserver"); 33795ffd83dbSDimitry Andric debugserver_launch_info.SetExecutableFile(rosetta_debugserver, false); 33805ffd83dbSDimitry Andric } 33815ffd83dbSDimitry Andric } 33825ffd83dbSDimitry Andric #endif 33835ffd83dbSDimitry Andric 33840b57cec5SDimitry Andric int communication_fd = -1; 33850b57cec5SDimitry Andric #ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION 33860b57cec5SDimitry Andric // Use a socketpair on non-Windows systems for security and performance 33870b57cec5SDimitry Andric // reasons. 33880b57cec5SDimitry Andric int sockets[2]; /* the pair of socket descriptors */ 33890b57cec5SDimitry Andric if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) { 33900b57cec5SDimitry Andric error.SetErrorToErrno(); 33910b57cec5SDimitry Andric return error; 33920b57cec5SDimitry Andric } 33930b57cec5SDimitry Andric 33940b57cec5SDimitry Andric int our_socket = sockets[0]; 33950b57cec5SDimitry Andric int gdb_socket = sockets[1]; 33969dba64beSDimitry Andric auto cleanup_our = llvm::make_scope_exit([&]() { close(our_socket); }); 33979dba64beSDimitry Andric auto cleanup_gdb = llvm::make_scope_exit([&]() { close(gdb_socket); }); 33980b57cec5SDimitry Andric 33990b57cec5SDimitry Andric // Don't let any child processes inherit our communication socket 34000b57cec5SDimitry Andric SetCloexecFlag(our_socket); 34010b57cec5SDimitry Andric communication_fd = gdb_socket; 34020b57cec5SDimitry Andric #endif 34030b57cec5SDimitry Andric 34040b57cec5SDimitry Andric error = m_gdb_comm.StartDebugserverProcess( 34050b57cec5SDimitry Andric nullptr, GetTarget().GetPlatform().get(), debugserver_launch_info, 34060b57cec5SDimitry Andric nullptr, nullptr, communication_fd); 34070b57cec5SDimitry Andric 34080b57cec5SDimitry Andric if (error.Success()) 34090b57cec5SDimitry Andric m_debugserver_pid = debugserver_launch_info.GetProcessID(); 34100b57cec5SDimitry Andric else 34110b57cec5SDimitry Andric m_debugserver_pid = LLDB_INVALID_PROCESS_ID; 34120b57cec5SDimitry Andric 34130b57cec5SDimitry Andric if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID) { 34140b57cec5SDimitry Andric #ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION 34150b57cec5SDimitry Andric // Our process spawned correctly, we can now set our connection to use 34160b57cec5SDimitry Andric // our end of the socket pair 34179dba64beSDimitry Andric cleanup_our.release(); 34185ffd83dbSDimitry Andric m_gdb_comm.SetConnection( 34195ffd83dbSDimitry Andric std::make_unique<ConnectionFileDescriptor>(our_socket, true)); 34200b57cec5SDimitry Andric #endif 34210b57cec5SDimitry Andric StartAsyncThread(); 34220b57cec5SDimitry Andric } 34230b57cec5SDimitry Andric 34240b57cec5SDimitry Andric if (error.Fail()) { 34251fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 34260b57cec5SDimitry Andric 34279dba64beSDimitry Andric LLDB_LOGF(log, "failed to start debugserver process: %s", 34280b57cec5SDimitry Andric error.AsCString()); 34290b57cec5SDimitry Andric return error; 34300b57cec5SDimitry Andric } 34310b57cec5SDimitry Andric 34320b57cec5SDimitry Andric if (m_gdb_comm.IsConnected()) { 34330b57cec5SDimitry Andric // Finish the connection process by doing the handshake without 34340b57cec5SDimitry Andric // connecting (send NULL URL) 34350b57cec5SDimitry Andric error = ConnectToDebugserver(""); 34360b57cec5SDimitry Andric } else { 34370b57cec5SDimitry Andric error.SetErrorString("connection failed"); 34380b57cec5SDimitry Andric } 34390b57cec5SDimitry Andric } 34400b57cec5SDimitry Andric return error; 34410b57cec5SDimitry Andric } 34420b57cec5SDimitry Andric 344381ad6265SDimitry Andric void ProcessGDBRemote::MonitorDebugserverProcess( 34440b57cec5SDimitry Andric std::weak_ptr<ProcessGDBRemote> process_wp, lldb::pid_t debugserver_pid, 34450b57cec5SDimitry Andric int signo, // Zero for no signal 34460b57cec5SDimitry Andric int exit_status // Exit value of process if signal is zero 34470b57cec5SDimitry Andric ) { 34480b57cec5SDimitry Andric // "debugserver_pid" argument passed in is the process ID for debugserver 34490b57cec5SDimitry Andric // that we are tracking... 34501fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 34510b57cec5SDimitry Andric 34529dba64beSDimitry Andric LLDB_LOGF(log, 34539dba64beSDimitry Andric "ProcessGDBRemote::%s(process_wp, pid=%" PRIu64 34540b57cec5SDimitry Andric ", signo=%i (0x%x), exit_status=%i)", 34550b57cec5SDimitry Andric __FUNCTION__, debugserver_pid, signo, signo, exit_status); 34560b57cec5SDimitry Andric 34570b57cec5SDimitry Andric std::shared_ptr<ProcessGDBRemote> process_sp = process_wp.lock(); 34589dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::%s(process = %p)", __FUNCTION__, 34590b57cec5SDimitry Andric static_cast<void *>(process_sp.get())); 34600b57cec5SDimitry Andric if (!process_sp || process_sp->m_debugserver_pid != debugserver_pid) 346181ad6265SDimitry Andric return; 34620b57cec5SDimitry Andric 34630b57cec5SDimitry Andric // Sleep for a half a second to make sure our inferior process has time to 34640b57cec5SDimitry Andric // set its exit status before we set it incorrectly when both the debugserver 34650b57cec5SDimitry Andric // and the inferior process shut down. 34669dba64beSDimitry Andric std::this_thread::sleep_for(std::chrono::milliseconds(500)); 34679dba64beSDimitry Andric 34680b57cec5SDimitry Andric // If our process hasn't yet exited, debugserver might have died. If the 34690b57cec5SDimitry Andric // process did exit, then we are reaping it. 34700b57cec5SDimitry Andric const StateType state = process_sp->GetState(); 34710b57cec5SDimitry Andric 34720b57cec5SDimitry Andric if (state != eStateInvalid && state != eStateUnloaded && 34730b57cec5SDimitry Andric state != eStateExited && state != eStateDetached) { 3474*5f757f3fSDimitry Andric StreamString stream; 3475*5f757f3fSDimitry Andric if (signo == 0) 3476*5f757f3fSDimitry Andric stream.Format(DEBUGSERVER_BASENAME " died with an exit status of {0:x8}", 34770b57cec5SDimitry Andric exit_status); 3478*5f757f3fSDimitry Andric else { 3479*5f757f3fSDimitry Andric llvm::StringRef signal_name = 3480*5f757f3fSDimitry Andric process_sp->GetUnixSignals()->GetSignalAsStringRef(signo); 3481*5f757f3fSDimitry Andric const char *format_str = DEBUGSERVER_BASENAME " died with signal {0}"; 3482*5f757f3fSDimitry Andric if (!signal_name.empty()) 3483*5f757f3fSDimitry Andric stream.Format(format_str, signal_name); 3484*5f757f3fSDimitry Andric else 3485*5f757f3fSDimitry Andric stream.Format(format_str, signo); 34860b57cec5SDimitry Andric } 3487*5f757f3fSDimitry Andric process_sp->SetExitStatus(-1, stream.GetString()); 34880b57cec5SDimitry Andric } 34890b57cec5SDimitry Andric // Debugserver has exited we need to let our ProcessGDBRemote know that it no 34900b57cec5SDimitry Andric // longer has a debugserver instance 34910b57cec5SDimitry Andric process_sp->m_debugserver_pid = LLDB_INVALID_PROCESS_ID; 34920b57cec5SDimitry Andric } 34930b57cec5SDimitry Andric 34940b57cec5SDimitry Andric void ProcessGDBRemote::KillDebugserverProcess() { 34950b57cec5SDimitry Andric m_gdb_comm.Disconnect(); 34960b57cec5SDimitry Andric if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID) { 34970b57cec5SDimitry Andric Host::Kill(m_debugserver_pid, SIGINT); 34980b57cec5SDimitry Andric m_debugserver_pid = LLDB_INVALID_PROCESS_ID; 34990b57cec5SDimitry Andric } 35000b57cec5SDimitry Andric } 35010b57cec5SDimitry Andric 35020b57cec5SDimitry Andric void ProcessGDBRemote::Initialize() { 35030b57cec5SDimitry Andric static llvm::once_flag g_once_flag; 35040b57cec5SDimitry Andric 35050b57cec5SDimitry Andric llvm::call_once(g_once_flag, []() { 35060b57cec5SDimitry Andric PluginManager::RegisterPlugin(GetPluginNameStatic(), 35070b57cec5SDimitry Andric GetPluginDescriptionStatic(), CreateInstance, 35080b57cec5SDimitry Andric DebuggerInitialize); 35090b57cec5SDimitry Andric }); 35100b57cec5SDimitry Andric } 35110b57cec5SDimitry Andric 35120b57cec5SDimitry Andric void ProcessGDBRemote::DebuggerInitialize(Debugger &debugger) { 35130b57cec5SDimitry Andric if (!PluginManager::GetSettingForProcessPlugin( 35140b57cec5SDimitry Andric debugger, PluginProperties::GetSettingName())) { 35150b57cec5SDimitry Andric const bool is_global_setting = true; 35160b57cec5SDimitry Andric PluginManager::CreateSettingForProcessPlugin( 3517349cc55cSDimitry Andric debugger, GetGlobalPluginProperties().GetValueProperties(), 351806c3fb27SDimitry Andric "Properties for the gdb-remote process plug-in.", is_global_setting); 35190b57cec5SDimitry Andric } 35200b57cec5SDimitry Andric } 35210b57cec5SDimitry Andric 35220b57cec5SDimitry Andric bool ProcessGDBRemote::StartAsyncThread() { 35231fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 35240b57cec5SDimitry Andric 35259dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::%s ()", __FUNCTION__); 35260b57cec5SDimitry Andric 35270b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex); 35280b57cec5SDimitry Andric if (!m_async_thread.IsJoinable()) { 35290b57cec5SDimitry Andric // Create a thread that watches our internal state and controls which 35300b57cec5SDimitry Andric // events make it to clients (into the DCProcess event queue). 35310b57cec5SDimitry Andric 353281ad6265SDimitry Andric llvm::Expected<HostThread> async_thread = 353381ad6265SDimitry Andric ThreadLauncher::LaunchThread("<lldb.process.gdb-remote.async>", [this] { 353481ad6265SDimitry Andric return ProcessGDBRemote::AsyncThread(); 353581ad6265SDimitry Andric }); 35360b57cec5SDimitry Andric if (!async_thread) { 353781ad6265SDimitry Andric LLDB_LOG_ERROR(GetLog(LLDBLog::Host), async_thread.takeError(), 353806c3fb27SDimitry Andric "failed to launch host thread: {0}"); 35390b57cec5SDimitry Andric return false; 35400b57cec5SDimitry Andric } 35410b57cec5SDimitry Andric m_async_thread = *async_thread; 35429dba64beSDimitry Andric } else 35439dba64beSDimitry Andric LLDB_LOGF(log, 35449dba64beSDimitry Andric "ProcessGDBRemote::%s () - Called when Async thread was " 35450b57cec5SDimitry Andric "already running.", 35460b57cec5SDimitry Andric __FUNCTION__); 35470b57cec5SDimitry Andric 35480b57cec5SDimitry Andric return m_async_thread.IsJoinable(); 35490b57cec5SDimitry Andric } 35500b57cec5SDimitry Andric 35510b57cec5SDimitry Andric void ProcessGDBRemote::StopAsyncThread() { 35521fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 35530b57cec5SDimitry Andric 35549dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::%s ()", __FUNCTION__); 35550b57cec5SDimitry Andric 35560b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex); 35570b57cec5SDimitry Andric if (m_async_thread.IsJoinable()) { 35580b57cec5SDimitry Andric m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit); 35590b57cec5SDimitry Andric 35600b57cec5SDimitry Andric // This will shut down the async thread. 35610b57cec5SDimitry Andric m_gdb_comm.Disconnect(); // Disconnect from the debug server. 35620b57cec5SDimitry Andric 35630b57cec5SDimitry Andric // Stop the stdio thread 35640b57cec5SDimitry Andric m_async_thread.Join(nullptr); 35650b57cec5SDimitry Andric m_async_thread.Reset(); 35669dba64beSDimitry Andric } else 35679dba64beSDimitry Andric LLDB_LOGF( 35689dba64beSDimitry Andric log, 35690b57cec5SDimitry Andric "ProcessGDBRemote::%s () - Called when Async thread was not running.", 35700b57cec5SDimitry Andric __FUNCTION__); 35710b57cec5SDimitry Andric } 35720b57cec5SDimitry Andric 357381ad6265SDimitry Andric thread_result_t ProcessGDBRemote::AsyncThread() { 35741fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 357581ad6265SDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::%s(pid = %" PRIu64 ") thread starting...", 357681ad6265SDimitry Andric __FUNCTION__, GetID()); 35770b57cec5SDimitry Andric 35780b57cec5SDimitry Andric EventSP event_sp; 3579fe6060f1SDimitry Andric 3580fe6060f1SDimitry Andric // We need to ignore any packets that come in after we have 3581fe6060f1SDimitry Andric // have decided the process has exited. There are some 3582fe6060f1SDimitry Andric // situations, for instance when we try to interrupt a running 3583fe6060f1SDimitry Andric // process and the interrupt fails, where another packet might 3584fe6060f1SDimitry Andric // get delivered after we've decided to give up on the process. 3585fe6060f1SDimitry Andric // But once we've decided we are done with the process we will 3586fe6060f1SDimitry Andric // not be in a state to do anything useful with new packets. 3587fe6060f1SDimitry Andric // So it is safer to simply ignore any remaining packets by 3588fe6060f1SDimitry Andric // explicitly checking for eStateExited before reentering the 3589fe6060f1SDimitry Andric // fetch loop. 3590fe6060f1SDimitry Andric 35910b57cec5SDimitry Andric bool done = false; 359281ad6265SDimitry Andric while (!done && GetPrivateState() != eStateExited) { 35939dba64beSDimitry Andric LLDB_LOGF(log, 359481ad6265SDimitry Andric "ProcessGDBRemote::%s(pid = %" PRIu64 35950b57cec5SDimitry Andric ") listener.WaitForEvent (NULL, event_sp)...", 359681ad6265SDimitry Andric __FUNCTION__, GetID()); 3597fe6060f1SDimitry Andric 3598bdd1243dSDimitry Andric if (m_async_listener_sp->GetEvent(event_sp, std::nullopt)) { 35990b57cec5SDimitry Andric const uint32_t event_type = event_sp->GetType(); 360081ad6265SDimitry Andric if (event_sp->BroadcasterIs(&m_async_broadcaster)) { 36019dba64beSDimitry Andric LLDB_LOGF(log, 360281ad6265SDimitry Andric "ProcessGDBRemote::%s(pid = %" PRIu64 36030b57cec5SDimitry Andric ") Got an event of type: %d...", 360481ad6265SDimitry Andric __FUNCTION__, GetID(), event_type); 36050b57cec5SDimitry Andric 36060b57cec5SDimitry Andric switch (event_type) { 36070b57cec5SDimitry Andric case eBroadcastBitAsyncContinue: { 36080b57cec5SDimitry Andric const EventDataBytes *continue_packet = 36090b57cec5SDimitry Andric EventDataBytes::GetEventDataFromEvent(event_sp.get()); 36100b57cec5SDimitry Andric 36110b57cec5SDimitry Andric if (continue_packet) { 36120b57cec5SDimitry Andric const char *continue_cstr = 36130b57cec5SDimitry Andric (const char *)continue_packet->GetBytes(); 36140b57cec5SDimitry Andric const size_t continue_cstr_len = continue_packet->GetByteSize(); 36159dba64beSDimitry Andric LLDB_LOGF(log, 361681ad6265SDimitry Andric "ProcessGDBRemote::%s(pid = %" PRIu64 36170b57cec5SDimitry Andric ") got eBroadcastBitAsyncContinue: %s", 361881ad6265SDimitry Andric __FUNCTION__, GetID(), continue_cstr); 36190b57cec5SDimitry Andric 36200b57cec5SDimitry Andric if (::strstr(continue_cstr, "vAttach") == nullptr) 362181ad6265SDimitry Andric SetPrivateState(eStateRunning); 36220b57cec5SDimitry Andric StringExtractorGDBRemote response; 36230b57cec5SDimitry Andric 36240b57cec5SDimitry Andric StateType stop_state = 362581ad6265SDimitry Andric GetGDBRemote().SendContinuePacketAndWaitForResponse( 362681ad6265SDimitry Andric *this, *GetUnixSignals(), 36270b57cec5SDimitry Andric llvm::StringRef(continue_cstr, continue_cstr_len), 362881ad6265SDimitry Andric GetInterruptTimeout(), response); 36290b57cec5SDimitry Andric 36300b57cec5SDimitry Andric // We need to immediately clear the thread ID list so we are sure 36310b57cec5SDimitry Andric // to get a valid list of threads. The thread ID list might be 36320b57cec5SDimitry Andric // contained within the "response", or the stop reply packet that 36330b57cec5SDimitry Andric // caused the stop. So clear it now before we give the stop reply 36340b57cec5SDimitry Andric // packet to the process using the 363581ad6265SDimitry Andric // SetLastStopPacket()... 363681ad6265SDimitry Andric ClearThreadIDList(); 36370b57cec5SDimitry Andric 36380b57cec5SDimitry Andric switch (stop_state) { 36390b57cec5SDimitry Andric case eStateStopped: 36400b57cec5SDimitry Andric case eStateCrashed: 36410b57cec5SDimitry Andric case eStateSuspended: 364281ad6265SDimitry Andric SetLastStopPacket(response); 364381ad6265SDimitry Andric SetPrivateState(stop_state); 36440b57cec5SDimitry Andric break; 36450b57cec5SDimitry Andric 36460b57cec5SDimitry Andric case eStateExited: { 364781ad6265SDimitry Andric SetLastStopPacket(response); 364881ad6265SDimitry Andric ClearThreadIDList(); 36490b57cec5SDimitry Andric response.SetFilePos(1); 36500b57cec5SDimitry Andric 36510b57cec5SDimitry Andric int exit_status = response.GetHexU8(); 36520b57cec5SDimitry Andric std::string desc_string; 3653349cc55cSDimitry Andric if (response.GetBytesLeft() > 0 && response.GetChar('-') == ';') { 36540b57cec5SDimitry Andric llvm::StringRef desc_str; 36550b57cec5SDimitry Andric llvm::StringRef desc_token; 36560b57cec5SDimitry Andric while (response.GetNameColonValue(desc_token, desc_str)) { 36570b57cec5SDimitry Andric if (desc_token != "description") 36580b57cec5SDimitry Andric continue; 36590b57cec5SDimitry Andric StringExtractor extractor(desc_str); 36600b57cec5SDimitry Andric extractor.GetHexByteString(desc_string); 36610b57cec5SDimitry Andric } 36620b57cec5SDimitry Andric } 366381ad6265SDimitry Andric SetExitStatus(exit_status, desc_string.c_str()); 36640b57cec5SDimitry Andric done = true; 36650b57cec5SDimitry Andric break; 36660b57cec5SDimitry Andric } 36670b57cec5SDimitry Andric case eStateInvalid: { 36680b57cec5SDimitry Andric // Check to see if we were trying to attach and if we got back 36690b57cec5SDimitry Andric // the "E87" error code from debugserver -- this indicates that 36700b57cec5SDimitry Andric // the process is not debuggable. Return a slightly more 36710b57cec5SDimitry Andric // helpful error message about why the attach failed. 36720b57cec5SDimitry Andric if (::strstr(continue_cstr, "vAttach") != nullptr && 36730b57cec5SDimitry Andric response.GetError() == 0x87) { 367481ad6265SDimitry Andric SetExitStatus(-1, "cannot attach to process due to " 36750b57cec5SDimitry Andric "System Integrity Protection"); 36760b57cec5SDimitry Andric } else if (::strstr(continue_cstr, "vAttach") != nullptr && 36770b57cec5SDimitry Andric response.GetStatus().Fail()) { 367881ad6265SDimitry Andric SetExitStatus(-1, response.GetStatus().AsCString()); 36790b57cec5SDimitry Andric } else { 368081ad6265SDimitry Andric SetExitStatus(-1, "lost connection"); 36810b57cec5SDimitry Andric } 3682fe6060f1SDimitry Andric done = true; 36830b57cec5SDimitry Andric break; 36840b57cec5SDimitry Andric } 36850b57cec5SDimitry Andric 36860b57cec5SDimitry Andric default: 368781ad6265SDimitry Andric SetPrivateState(stop_state); 36880b57cec5SDimitry Andric break; 36890b57cec5SDimitry Andric } // switch(stop_state) 36900b57cec5SDimitry Andric } // if (continue_packet) 36915ffd83dbSDimitry Andric } // case eBroadcastBitAsyncContinue 36920b57cec5SDimitry Andric break; 36930b57cec5SDimitry Andric 36940b57cec5SDimitry Andric case eBroadcastBitAsyncThreadShouldExit: 36959dba64beSDimitry Andric LLDB_LOGF(log, 369681ad6265SDimitry Andric "ProcessGDBRemote::%s(pid = %" PRIu64 36970b57cec5SDimitry Andric ") got eBroadcastBitAsyncThreadShouldExit...", 369881ad6265SDimitry Andric __FUNCTION__, GetID()); 36990b57cec5SDimitry Andric done = true; 37000b57cec5SDimitry Andric break; 37010b57cec5SDimitry Andric 37020b57cec5SDimitry Andric default: 37039dba64beSDimitry Andric LLDB_LOGF(log, 370481ad6265SDimitry Andric "ProcessGDBRemote::%s(pid = %" PRIu64 37050b57cec5SDimitry Andric ") got unknown event 0x%8.8x", 370681ad6265SDimitry Andric __FUNCTION__, GetID(), event_type); 37070b57cec5SDimitry Andric done = true; 37080b57cec5SDimitry Andric break; 37090b57cec5SDimitry Andric } 37100b57cec5SDimitry Andric } 37110b57cec5SDimitry Andric } else { 37129dba64beSDimitry Andric LLDB_LOGF(log, 371381ad6265SDimitry Andric "ProcessGDBRemote::%s(pid = %" PRIu64 37140b57cec5SDimitry Andric ") listener.WaitForEvent (NULL, event_sp) => false", 371581ad6265SDimitry Andric __FUNCTION__, GetID()); 37160b57cec5SDimitry Andric done = true; 37170b57cec5SDimitry Andric } 37180b57cec5SDimitry Andric } 37190b57cec5SDimitry Andric 372081ad6265SDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::%s(pid = %" PRIu64 ") thread exiting...", 372181ad6265SDimitry Andric __FUNCTION__, GetID()); 37220b57cec5SDimitry Andric 37230b57cec5SDimitry Andric return {}; 37240b57cec5SDimitry Andric } 37250b57cec5SDimitry Andric 37260b57cec5SDimitry Andric // uint32_t 37270b57cec5SDimitry Andric // ProcessGDBRemote::ListProcessesMatchingName (const char *name, StringList 37280b57cec5SDimitry Andric // &matches, std::vector<lldb::pid_t> &pids) 37290b57cec5SDimitry Andric //{ 37300b57cec5SDimitry Andric // // If we are planning to launch the debugserver remotely, then we need to 37310b57cec5SDimitry Andric // fire up a debugserver 37320b57cec5SDimitry Andric // // process and ask it for the list of processes. But if we are local, we 37330b57cec5SDimitry Andric // can let the Host do it. 37340b57cec5SDimitry Andric // if (m_local_debugserver) 37350b57cec5SDimitry Andric // { 37360b57cec5SDimitry Andric // return Host::ListProcessesMatchingName (name, matches, pids); 37370b57cec5SDimitry Andric // } 37380b57cec5SDimitry Andric // else 37390b57cec5SDimitry Andric // { 37400b57cec5SDimitry Andric // // FIXME: Implement talking to the remote debugserver. 37410b57cec5SDimitry Andric // return 0; 37420b57cec5SDimitry Andric // } 37430b57cec5SDimitry Andric // 37440b57cec5SDimitry Andric //} 37450b57cec5SDimitry Andric // 37460b57cec5SDimitry Andric bool ProcessGDBRemote::NewThreadNotifyBreakpointHit( 37470b57cec5SDimitry Andric void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, 37480b57cec5SDimitry Andric lldb::user_id_t break_loc_id) { 37490b57cec5SDimitry Andric // I don't think I have to do anything here, just make sure I notice the new 37500b57cec5SDimitry Andric // thread when it starts to 37510b57cec5SDimitry Andric // run so I can stop it if that's what I want to do. 375281ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Step); 37539dba64beSDimitry Andric LLDB_LOGF(log, "Hit New Thread Notification breakpoint."); 37540b57cec5SDimitry Andric return false; 37550b57cec5SDimitry Andric } 37560b57cec5SDimitry Andric 37570b57cec5SDimitry Andric Status ProcessGDBRemote::UpdateAutomaticSignalFiltering() { 37581fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 37590b57cec5SDimitry Andric LLDB_LOG(log, "Check if need to update ignored signals"); 37600b57cec5SDimitry Andric 37610b57cec5SDimitry Andric // QPassSignals package is not supported by the server, there is no way we 37620b57cec5SDimitry Andric // can ignore any signals on server side. 37630b57cec5SDimitry Andric if (!m_gdb_comm.GetQPassSignalsSupported()) 37640b57cec5SDimitry Andric return Status(); 37650b57cec5SDimitry Andric 37660b57cec5SDimitry Andric // No signals, nothing to send. 37670b57cec5SDimitry Andric if (m_unix_signals_sp == nullptr) 37680b57cec5SDimitry Andric return Status(); 37690b57cec5SDimitry Andric 37700b57cec5SDimitry Andric // Signals' version hasn't changed, no need to send anything. 37710b57cec5SDimitry Andric uint64_t new_signals_version = m_unix_signals_sp->GetVersion(); 37720b57cec5SDimitry Andric if (new_signals_version == m_last_signals_version) { 37730b57cec5SDimitry Andric LLDB_LOG(log, "Signals' version hasn't changed. version={0}", 37740b57cec5SDimitry Andric m_last_signals_version); 37750b57cec5SDimitry Andric return Status(); 37760b57cec5SDimitry Andric } 37770b57cec5SDimitry Andric 37780b57cec5SDimitry Andric auto signals_to_ignore = 37790b57cec5SDimitry Andric m_unix_signals_sp->GetFilteredSignals(false, false, false); 37800b57cec5SDimitry Andric Status error = m_gdb_comm.SendSignalsToIgnore(signals_to_ignore); 37810b57cec5SDimitry Andric 37820b57cec5SDimitry Andric LLDB_LOG(log, 37830b57cec5SDimitry Andric "Signals' version changed. old version={0}, new version={1}, " 37840b57cec5SDimitry Andric "signals ignored={2}, update result={3}", 37850b57cec5SDimitry Andric m_last_signals_version, new_signals_version, 37860b57cec5SDimitry Andric signals_to_ignore.size(), error); 37870b57cec5SDimitry Andric 37880b57cec5SDimitry Andric if (error.Success()) 37890b57cec5SDimitry Andric m_last_signals_version = new_signals_version; 37900b57cec5SDimitry Andric 37910b57cec5SDimitry Andric return error; 37920b57cec5SDimitry Andric } 37930b57cec5SDimitry Andric 37940b57cec5SDimitry Andric bool ProcessGDBRemote::StartNoticingNewThreads() { 379581ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Step); 37960b57cec5SDimitry Andric if (m_thread_create_bp_sp) { 37970b57cec5SDimitry Andric if (log && log->GetVerbose()) 37989dba64beSDimitry Andric LLDB_LOGF(log, "Enabled noticing new thread breakpoint."); 37990b57cec5SDimitry Andric m_thread_create_bp_sp->SetEnabled(true); 38000b57cec5SDimitry Andric } else { 38010b57cec5SDimitry Andric PlatformSP platform_sp(GetTarget().GetPlatform()); 38020b57cec5SDimitry Andric if (platform_sp) { 38030b57cec5SDimitry Andric m_thread_create_bp_sp = 38040b57cec5SDimitry Andric platform_sp->SetThreadCreationBreakpoint(GetTarget()); 38050b57cec5SDimitry Andric if (m_thread_create_bp_sp) { 38060b57cec5SDimitry Andric if (log && log->GetVerbose()) 38079dba64beSDimitry Andric LLDB_LOGF( 38089dba64beSDimitry Andric log, "Successfully created new thread notification breakpoint %i", 38090b57cec5SDimitry Andric m_thread_create_bp_sp->GetID()); 38100b57cec5SDimitry Andric m_thread_create_bp_sp->SetCallback( 38110b57cec5SDimitry Andric ProcessGDBRemote::NewThreadNotifyBreakpointHit, this, true); 38120b57cec5SDimitry Andric } else { 38139dba64beSDimitry Andric LLDB_LOGF(log, "Failed to create new thread notification breakpoint."); 38140b57cec5SDimitry Andric } 38150b57cec5SDimitry Andric } 38160b57cec5SDimitry Andric } 38170b57cec5SDimitry Andric return m_thread_create_bp_sp.get() != nullptr; 38180b57cec5SDimitry Andric } 38190b57cec5SDimitry Andric 38200b57cec5SDimitry Andric bool ProcessGDBRemote::StopNoticingNewThreads() { 382181ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Step); 38220b57cec5SDimitry Andric if (log && log->GetVerbose()) 38239dba64beSDimitry Andric LLDB_LOGF(log, "Disabling new thread notification breakpoint."); 38240b57cec5SDimitry Andric 38250b57cec5SDimitry Andric if (m_thread_create_bp_sp) 38260b57cec5SDimitry Andric m_thread_create_bp_sp->SetEnabled(false); 38270b57cec5SDimitry Andric 38280b57cec5SDimitry Andric return true; 38290b57cec5SDimitry Andric } 38300b57cec5SDimitry Andric 38310b57cec5SDimitry Andric DynamicLoader *ProcessGDBRemote::GetDynamicLoader() { 38320b57cec5SDimitry Andric if (m_dyld_up.get() == nullptr) 3833349cc55cSDimitry Andric m_dyld_up.reset(DynamicLoader::FindPlugin(this, "")); 38340b57cec5SDimitry Andric return m_dyld_up.get(); 38350b57cec5SDimitry Andric } 38360b57cec5SDimitry Andric 38370b57cec5SDimitry Andric Status ProcessGDBRemote::SendEventData(const char *data) { 38380b57cec5SDimitry Andric int return_value; 38390b57cec5SDimitry Andric bool was_supported; 38400b57cec5SDimitry Andric 38410b57cec5SDimitry Andric Status error; 38420b57cec5SDimitry Andric 38430b57cec5SDimitry Andric return_value = m_gdb_comm.SendLaunchEventDataPacket(data, &was_supported); 38440b57cec5SDimitry Andric if (return_value != 0) { 38450b57cec5SDimitry Andric if (!was_supported) 38460b57cec5SDimitry Andric error.SetErrorString("Sending events is not supported for this process."); 38470b57cec5SDimitry Andric else 38480b57cec5SDimitry Andric error.SetErrorStringWithFormat("Error sending event data: %d.", 38490b57cec5SDimitry Andric return_value); 38500b57cec5SDimitry Andric } 38510b57cec5SDimitry Andric return error; 38520b57cec5SDimitry Andric } 38530b57cec5SDimitry Andric 38540b57cec5SDimitry Andric DataExtractor ProcessGDBRemote::GetAuxvData() { 38550b57cec5SDimitry Andric DataBufferSP buf; 38560b57cec5SDimitry Andric if (m_gdb_comm.GetQXferAuxvReadSupported()) { 3857349cc55cSDimitry Andric llvm::Expected<std::string> response = m_gdb_comm.ReadExtFeature("auxv", ""); 3858349cc55cSDimitry Andric if (response) 3859349cc55cSDimitry Andric buf = std::make_shared<DataBufferHeap>(response->c_str(), 3860349cc55cSDimitry Andric response->length()); 3861349cc55cSDimitry Andric else 38621fd87a68SDimitry Andric LLDB_LOG_ERROR(GetLog(GDBRLog::Process), response.takeError(), "{0}"); 38630b57cec5SDimitry Andric } 38640b57cec5SDimitry Andric return DataExtractor(buf, GetByteOrder(), GetAddressByteSize()); 38650b57cec5SDimitry Andric } 38660b57cec5SDimitry Andric 38670b57cec5SDimitry Andric StructuredData::ObjectSP 38680b57cec5SDimitry Andric ProcessGDBRemote::GetExtendedInfoForThread(lldb::tid_t tid) { 38690b57cec5SDimitry Andric StructuredData::ObjectSP object_sp; 38700b57cec5SDimitry Andric 38710b57cec5SDimitry Andric if (m_gdb_comm.GetThreadExtendedInfoSupported()) { 38720b57cec5SDimitry Andric StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); 38730b57cec5SDimitry Andric SystemRuntime *runtime = GetSystemRuntime(); 38740b57cec5SDimitry Andric if (runtime) { 38750b57cec5SDimitry Andric runtime->AddThreadExtendedInfoPacketHints(args_dict); 38760b57cec5SDimitry Andric } 38770b57cec5SDimitry Andric args_dict->GetAsDictionary()->AddIntegerItem("thread", tid); 38780b57cec5SDimitry Andric 38790b57cec5SDimitry Andric StreamString packet; 38800b57cec5SDimitry Andric packet << "jThreadExtendedInfo:"; 38810b57cec5SDimitry Andric args_dict->Dump(packet, false); 38820b57cec5SDimitry Andric 38830b57cec5SDimitry Andric // FIXME the final character of a JSON dictionary, '}', is the escape 38840b57cec5SDimitry Andric // character in gdb-remote binary mode. lldb currently doesn't escape 38850b57cec5SDimitry Andric // these characters in its packet output -- so we add the quoted version of 38860b57cec5SDimitry Andric // the } character here manually in case we talk to a debugserver which un- 38870b57cec5SDimitry Andric // escapes the characters at packet read time. 38880b57cec5SDimitry Andric packet << (char)(0x7d ^ 0x20); 38890b57cec5SDimitry Andric 38900b57cec5SDimitry Andric StringExtractorGDBRemote response; 38910b57cec5SDimitry Andric response.SetResponseValidatorToJSON(); 3892fe6060f1SDimitry Andric if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) == 38930b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult::Success) { 38940b57cec5SDimitry Andric StringExtractorGDBRemote::ResponseType response_type = 38950b57cec5SDimitry Andric response.GetResponseType(); 38960b57cec5SDimitry Andric if (response_type == StringExtractorGDBRemote::eResponse) { 38970b57cec5SDimitry Andric if (!response.Empty()) { 389806c3fb27SDimitry Andric object_sp = StructuredData::ParseJSON(response.GetStringRef()); 38990b57cec5SDimitry Andric } 39000b57cec5SDimitry Andric } 39010b57cec5SDimitry Andric } 39020b57cec5SDimitry Andric } 39030b57cec5SDimitry Andric return object_sp; 39040b57cec5SDimitry Andric } 39050b57cec5SDimitry Andric 39060b57cec5SDimitry Andric StructuredData::ObjectSP ProcessGDBRemote::GetLoadedDynamicLibrariesInfos( 39070b57cec5SDimitry Andric lldb::addr_t image_list_address, lldb::addr_t image_count) { 39080b57cec5SDimitry Andric 39090b57cec5SDimitry Andric StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); 39100b57cec5SDimitry Andric args_dict->GetAsDictionary()->AddIntegerItem("image_list_address", 39110b57cec5SDimitry Andric image_list_address); 39120b57cec5SDimitry Andric args_dict->GetAsDictionary()->AddIntegerItem("image_count", image_count); 39130b57cec5SDimitry Andric 39140b57cec5SDimitry Andric return GetLoadedDynamicLibrariesInfos_sender(args_dict); 39150b57cec5SDimitry Andric } 39160b57cec5SDimitry Andric 39170b57cec5SDimitry Andric StructuredData::ObjectSP ProcessGDBRemote::GetLoadedDynamicLibrariesInfos() { 39180b57cec5SDimitry Andric StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); 39190b57cec5SDimitry Andric 39200b57cec5SDimitry Andric args_dict->GetAsDictionary()->AddBooleanItem("fetch_all_solibs", true); 39210b57cec5SDimitry Andric 39220b57cec5SDimitry Andric return GetLoadedDynamicLibrariesInfos_sender(args_dict); 39230b57cec5SDimitry Andric } 39240b57cec5SDimitry Andric 39250b57cec5SDimitry Andric StructuredData::ObjectSP ProcessGDBRemote::GetLoadedDynamicLibrariesInfos( 39260b57cec5SDimitry Andric const std::vector<lldb::addr_t> &load_addresses) { 39270b57cec5SDimitry Andric StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); 39280b57cec5SDimitry Andric StructuredData::ArraySP addresses(new StructuredData::Array); 39290b57cec5SDimitry Andric 393006c3fb27SDimitry Andric for (auto addr : load_addresses) 393106c3fb27SDimitry Andric addresses->AddIntegerItem(addr); 39320b57cec5SDimitry Andric 39330b57cec5SDimitry Andric args_dict->GetAsDictionary()->AddItem("solib_addresses", addresses); 39340b57cec5SDimitry Andric 39350b57cec5SDimitry Andric return GetLoadedDynamicLibrariesInfos_sender(args_dict); 39360b57cec5SDimitry Andric } 39370b57cec5SDimitry Andric 39380b57cec5SDimitry Andric StructuredData::ObjectSP 39390b57cec5SDimitry Andric ProcessGDBRemote::GetLoadedDynamicLibrariesInfos_sender( 39400b57cec5SDimitry Andric StructuredData::ObjectSP args_dict) { 39410b57cec5SDimitry Andric StructuredData::ObjectSP object_sp; 39420b57cec5SDimitry Andric 39430b57cec5SDimitry Andric if (m_gdb_comm.GetLoadedDynamicLibrariesInfosSupported()) { 39440b57cec5SDimitry Andric // Scope for the scoped timeout object 39450b57cec5SDimitry Andric GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_comm, 39460b57cec5SDimitry Andric std::chrono::seconds(10)); 39470b57cec5SDimitry Andric 39480b57cec5SDimitry Andric StreamString packet; 39490b57cec5SDimitry Andric packet << "jGetLoadedDynamicLibrariesInfos:"; 39500b57cec5SDimitry Andric args_dict->Dump(packet, false); 39510b57cec5SDimitry Andric 39520b57cec5SDimitry Andric // FIXME the final character of a JSON dictionary, '}', is the escape 39530b57cec5SDimitry Andric // character in gdb-remote binary mode. lldb currently doesn't escape 39540b57cec5SDimitry Andric // these characters in its packet output -- so we add the quoted version of 39550b57cec5SDimitry Andric // the } character here manually in case we talk to a debugserver which un- 39560b57cec5SDimitry Andric // escapes the characters at packet read time. 39570b57cec5SDimitry Andric packet << (char)(0x7d ^ 0x20); 39580b57cec5SDimitry Andric 39590b57cec5SDimitry Andric StringExtractorGDBRemote response; 39600b57cec5SDimitry Andric response.SetResponseValidatorToJSON(); 3961fe6060f1SDimitry Andric if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) == 39620b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult::Success) { 39630b57cec5SDimitry Andric StringExtractorGDBRemote::ResponseType response_type = 39640b57cec5SDimitry Andric response.GetResponseType(); 39650b57cec5SDimitry Andric if (response_type == StringExtractorGDBRemote::eResponse) { 39660b57cec5SDimitry Andric if (!response.Empty()) { 396706c3fb27SDimitry Andric object_sp = StructuredData::ParseJSON(response.GetStringRef()); 39680b57cec5SDimitry Andric } 39690b57cec5SDimitry Andric } 39700b57cec5SDimitry Andric } 39710b57cec5SDimitry Andric } 39720b57cec5SDimitry Andric return object_sp; 39730b57cec5SDimitry Andric } 39740b57cec5SDimitry Andric 3975bdd1243dSDimitry Andric StructuredData::ObjectSP ProcessGDBRemote::GetDynamicLoaderProcessState() { 3976bdd1243dSDimitry Andric StructuredData::ObjectSP object_sp; 3977bdd1243dSDimitry Andric StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); 3978bdd1243dSDimitry Andric 3979bdd1243dSDimitry Andric if (m_gdb_comm.GetDynamicLoaderProcessStateSupported()) { 3980bdd1243dSDimitry Andric StringExtractorGDBRemote response; 3981bdd1243dSDimitry Andric response.SetResponseValidatorToJSON(); 3982bdd1243dSDimitry Andric if (m_gdb_comm.SendPacketAndWaitForResponse("jGetDyldProcessState", 3983bdd1243dSDimitry Andric response) == 3984bdd1243dSDimitry Andric GDBRemoteCommunication::PacketResult::Success) { 3985bdd1243dSDimitry Andric StringExtractorGDBRemote::ResponseType response_type = 3986bdd1243dSDimitry Andric response.GetResponseType(); 3987bdd1243dSDimitry Andric if (response_type == StringExtractorGDBRemote::eResponse) { 3988bdd1243dSDimitry Andric if (!response.Empty()) { 398906c3fb27SDimitry Andric object_sp = StructuredData::ParseJSON(response.GetStringRef()); 3990bdd1243dSDimitry Andric } 3991bdd1243dSDimitry Andric } 3992bdd1243dSDimitry Andric } 3993bdd1243dSDimitry Andric } 3994bdd1243dSDimitry Andric return object_sp; 3995bdd1243dSDimitry Andric } 3996bdd1243dSDimitry Andric 39970b57cec5SDimitry Andric StructuredData::ObjectSP ProcessGDBRemote::GetSharedCacheInfo() { 39980b57cec5SDimitry Andric StructuredData::ObjectSP object_sp; 39990b57cec5SDimitry Andric StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); 40000b57cec5SDimitry Andric 40010b57cec5SDimitry Andric if (m_gdb_comm.GetSharedCacheInfoSupported()) { 40020b57cec5SDimitry Andric StreamString packet; 40030b57cec5SDimitry Andric packet << "jGetSharedCacheInfo:"; 40040b57cec5SDimitry Andric args_dict->Dump(packet, false); 40050b57cec5SDimitry Andric 40060b57cec5SDimitry Andric // FIXME the final character of a JSON dictionary, '}', is the escape 40070b57cec5SDimitry Andric // character in gdb-remote binary mode. lldb currently doesn't escape 40080b57cec5SDimitry Andric // these characters in its packet output -- so we add the quoted version of 40090b57cec5SDimitry Andric // the } character here manually in case we talk to a debugserver which un- 40100b57cec5SDimitry Andric // escapes the characters at packet read time. 40110b57cec5SDimitry Andric packet << (char)(0x7d ^ 0x20); 40120b57cec5SDimitry Andric 40130b57cec5SDimitry Andric StringExtractorGDBRemote response; 40140b57cec5SDimitry Andric response.SetResponseValidatorToJSON(); 4015fe6060f1SDimitry Andric if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) == 40160b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult::Success) { 40170b57cec5SDimitry Andric StringExtractorGDBRemote::ResponseType response_type = 40180b57cec5SDimitry Andric response.GetResponseType(); 40190b57cec5SDimitry Andric if (response_type == StringExtractorGDBRemote::eResponse) { 40200b57cec5SDimitry Andric if (!response.Empty()) { 402106c3fb27SDimitry Andric object_sp = StructuredData::ParseJSON(response.GetStringRef()); 40220b57cec5SDimitry Andric } 40230b57cec5SDimitry Andric } 40240b57cec5SDimitry Andric } 40250b57cec5SDimitry Andric } 40260b57cec5SDimitry Andric return object_sp; 40270b57cec5SDimitry Andric } 40280b57cec5SDimitry Andric 40290b57cec5SDimitry Andric Status ProcessGDBRemote::ConfigureStructuredData( 403006c3fb27SDimitry Andric llvm::StringRef type_name, const StructuredData::ObjectSP &config_sp) { 40310b57cec5SDimitry Andric return m_gdb_comm.ConfigureRemoteStructuredData(type_name, config_sp); 40320b57cec5SDimitry Andric } 40330b57cec5SDimitry Andric 40340b57cec5SDimitry Andric // Establish the largest memory read/write payloads we should use. If the 40350b57cec5SDimitry Andric // remote stub has a max packet size, stay under that size. 40360b57cec5SDimitry Andric // 40370b57cec5SDimitry Andric // If the remote stub's max packet size is crazy large, use a reasonable 40380b57cec5SDimitry Andric // largeish default. 40390b57cec5SDimitry Andric // 40400b57cec5SDimitry Andric // If the remote stub doesn't advertise a max packet size, use a conservative 40410b57cec5SDimitry Andric // default. 40420b57cec5SDimitry Andric 40430b57cec5SDimitry Andric void ProcessGDBRemote::GetMaxMemorySize() { 40440b57cec5SDimitry Andric const uint64_t reasonable_largeish_default = 128 * 1024; 40450b57cec5SDimitry Andric const uint64_t conservative_default = 512; 40460b57cec5SDimitry Andric 40470b57cec5SDimitry Andric if (m_max_memory_size == 0) { 40480b57cec5SDimitry Andric uint64_t stub_max_size = m_gdb_comm.GetRemoteMaxPacketSize(); 40490b57cec5SDimitry Andric if (stub_max_size != UINT64_MAX && stub_max_size != 0) { 40500b57cec5SDimitry Andric // Save the stub's claimed maximum packet size 40510b57cec5SDimitry Andric m_remote_stub_max_memory_size = stub_max_size; 40520b57cec5SDimitry Andric 40530b57cec5SDimitry Andric // Even if the stub says it can support ginormous packets, don't exceed 40540b57cec5SDimitry Andric // our reasonable largeish default packet size. 40550b57cec5SDimitry Andric if (stub_max_size > reasonable_largeish_default) { 40560b57cec5SDimitry Andric stub_max_size = reasonable_largeish_default; 40570b57cec5SDimitry Andric } 40580b57cec5SDimitry Andric 40590b57cec5SDimitry Andric // Memory packet have other overheads too like Maddr,size:#NN Instead of 40600b57cec5SDimitry Andric // calculating the bytes taken by size and addr every time, we take a 40610b57cec5SDimitry Andric // maximum guess here. 40620b57cec5SDimitry Andric if (stub_max_size > 70) 40630b57cec5SDimitry Andric stub_max_size -= 32 + 32 + 6; 40640b57cec5SDimitry Andric else { 40650b57cec5SDimitry Andric // In unlikely scenario that max packet size is less then 70, we will 40660b57cec5SDimitry Andric // hope that data being written is small enough to fit. 40671fd87a68SDimitry Andric Log *log(GetLog(GDBRLog::Comm | GDBRLog::Memory)); 40680b57cec5SDimitry Andric if (log) 40690b57cec5SDimitry Andric log->Warning("Packet size is too small. " 40700b57cec5SDimitry Andric "LLDB may face problems while writing memory"); 40710b57cec5SDimitry Andric } 40720b57cec5SDimitry Andric 40730b57cec5SDimitry Andric m_max_memory_size = stub_max_size; 40740b57cec5SDimitry Andric } else { 40750b57cec5SDimitry Andric m_max_memory_size = conservative_default; 40760b57cec5SDimitry Andric } 40770b57cec5SDimitry Andric } 40780b57cec5SDimitry Andric } 40790b57cec5SDimitry Andric 40800b57cec5SDimitry Andric void ProcessGDBRemote::SetUserSpecifiedMaxMemoryTransferSize( 40810b57cec5SDimitry Andric uint64_t user_specified_max) { 40820b57cec5SDimitry Andric if (user_specified_max != 0) { 40830b57cec5SDimitry Andric GetMaxMemorySize(); 40840b57cec5SDimitry Andric 40850b57cec5SDimitry Andric if (m_remote_stub_max_memory_size != 0) { 40860b57cec5SDimitry Andric if (m_remote_stub_max_memory_size < user_specified_max) { 40870b57cec5SDimitry Andric m_max_memory_size = m_remote_stub_max_memory_size; // user specified a 40880b57cec5SDimitry Andric // packet size too 40890b57cec5SDimitry Andric // big, go as big 40900b57cec5SDimitry Andric // as the remote stub says we can go. 40910b57cec5SDimitry Andric } else { 40920b57cec5SDimitry Andric m_max_memory_size = user_specified_max; // user's packet size is good 40930b57cec5SDimitry Andric } 40940b57cec5SDimitry Andric } else { 40950b57cec5SDimitry Andric m_max_memory_size = 40960b57cec5SDimitry Andric user_specified_max; // user's packet size is probably fine 40970b57cec5SDimitry Andric } 40980b57cec5SDimitry Andric } 40990b57cec5SDimitry Andric } 41000b57cec5SDimitry Andric 41010b57cec5SDimitry Andric bool ProcessGDBRemote::GetModuleSpec(const FileSpec &module_file_spec, 41020b57cec5SDimitry Andric const ArchSpec &arch, 41030b57cec5SDimitry Andric ModuleSpec &module_spec) { 410481ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Platform); 41050b57cec5SDimitry Andric 41060b57cec5SDimitry Andric const ModuleCacheKey key(module_file_spec.GetPath(), 41070b57cec5SDimitry Andric arch.GetTriple().getTriple()); 41080b57cec5SDimitry Andric auto cached = m_cached_module_specs.find(key); 41090b57cec5SDimitry Andric if (cached != m_cached_module_specs.end()) { 41100b57cec5SDimitry Andric module_spec = cached->second; 41110b57cec5SDimitry Andric return bool(module_spec); 41120b57cec5SDimitry Andric } 41130b57cec5SDimitry Andric 41140b57cec5SDimitry Andric if (!m_gdb_comm.GetModuleInfo(module_file_spec, arch, module_spec)) { 41159dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::%s - failed to get module info for %s:%s", 41160b57cec5SDimitry Andric __FUNCTION__, module_file_spec.GetPath().c_str(), 41170b57cec5SDimitry Andric arch.GetTriple().getTriple().c_str()); 41180b57cec5SDimitry Andric return false; 41190b57cec5SDimitry Andric } 41200b57cec5SDimitry Andric 41210b57cec5SDimitry Andric if (log) { 41220b57cec5SDimitry Andric StreamString stream; 41230b57cec5SDimitry Andric module_spec.Dump(stream); 41249dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::%s - got module info for (%s:%s) : %s", 41250b57cec5SDimitry Andric __FUNCTION__, module_file_spec.GetPath().c_str(), 41260b57cec5SDimitry Andric arch.GetTriple().getTriple().c_str(), stream.GetData()); 41270b57cec5SDimitry Andric } 41280b57cec5SDimitry Andric 41290b57cec5SDimitry Andric m_cached_module_specs[key] = module_spec; 41300b57cec5SDimitry Andric return true; 41310b57cec5SDimitry Andric } 41320b57cec5SDimitry Andric 41330b57cec5SDimitry Andric void ProcessGDBRemote::PrefetchModuleSpecs( 41340b57cec5SDimitry Andric llvm::ArrayRef<FileSpec> module_file_specs, const llvm::Triple &triple) { 41350b57cec5SDimitry Andric auto module_specs = m_gdb_comm.GetModulesInfo(module_file_specs, triple); 41360b57cec5SDimitry Andric if (module_specs) { 41370b57cec5SDimitry Andric for (const FileSpec &spec : module_file_specs) 41380b57cec5SDimitry Andric m_cached_module_specs[ModuleCacheKey(spec.GetPath(), 41390b57cec5SDimitry Andric triple.getTriple())] = ModuleSpec(); 41400b57cec5SDimitry Andric for (const ModuleSpec &spec : *module_specs) 41410b57cec5SDimitry Andric m_cached_module_specs[ModuleCacheKey(spec.GetFileSpec().GetPath(), 41420b57cec5SDimitry Andric triple.getTriple())] = spec; 41430b57cec5SDimitry Andric } 41440b57cec5SDimitry Andric } 41450b57cec5SDimitry Andric 41460b57cec5SDimitry Andric llvm::VersionTuple ProcessGDBRemote::GetHostOSVersion() { 41470b57cec5SDimitry Andric return m_gdb_comm.GetOSVersion(); 41480b57cec5SDimitry Andric } 41490b57cec5SDimitry Andric 41509dba64beSDimitry Andric llvm::VersionTuple ProcessGDBRemote::GetHostMacCatalystVersion() { 41519dba64beSDimitry Andric return m_gdb_comm.GetMacCatalystVersion(); 41529dba64beSDimitry Andric } 41539dba64beSDimitry Andric 41540b57cec5SDimitry Andric namespace { 41550b57cec5SDimitry Andric 41560b57cec5SDimitry Andric typedef std::vector<std::string> stringVec; 41570b57cec5SDimitry Andric 41580b57cec5SDimitry Andric typedef std::vector<struct GdbServerRegisterInfo> GDBServerRegisterVec; 41590b57cec5SDimitry Andric struct RegisterSetInfo { 41600b57cec5SDimitry Andric ConstString name; 41610b57cec5SDimitry Andric }; 41620b57cec5SDimitry Andric 41630b57cec5SDimitry Andric typedef std::map<uint32_t, RegisterSetInfo> RegisterSetMap; 41640b57cec5SDimitry Andric 41650b57cec5SDimitry Andric struct GdbServerTargetInfo { 41660b57cec5SDimitry Andric std::string arch; 41670b57cec5SDimitry Andric std::string osabi; 41680b57cec5SDimitry Andric stringVec includes; 41690b57cec5SDimitry Andric RegisterSetMap reg_set_map; 41700b57cec5SDimitry Andric }; 41710b57cec5SDimitry Andric 417206c3fb27SDimitry Andric static std::vector<RegisterFlags::Field> ParseFlagsFields(XMLNode flags_node, 417306c3fb27SDimitry Andric unsigned size) { 417406c3fb27SDimitry Andric Log *log(GetLog(GDBRLog::Process)); 417506c3fb27SDimitry Andric const unsigned max_start_bit = size * 8 - 1; 417606c3fb27SDimitry Andric 417706c3fb27SDimitry Andric // Process the fields of this set of flags. 417806c3fb27SDimitry Andric std::vector<RegisterFlags::Field> fields; 417906c3fb27SDimitry Andric flags_node.ForEachChildElementWithName("field", [&fields, max_start_bit, 418006c3fb27SDimitry Andric &log](const XMLNode 418106c3fb27SDimitry Andric &field_node) { 418206c3fb27SDimitry Andric std::optional<llvm::StringRef> name; 418306c3fb27SDimitry Andric std::optional<unsigned> start; 418406c3fb27SDimitry Andric std::optional<unsigned> end; 418506c3fb27SDimitry Andric 418606c3fb27SDimitry Andric field_node.ForEachAttribute([&name, &start, &end, max_start_bit, 418706c3fb27SDimitry Andric &log](const llvm::StringRef &attr_name, 418806c3fb27SDimitry Andric const llvm::StringRef &attr_value) { 418906c3fb27SDimitry Andric // Note that XML in general requires that each of these attributes only 419006c3fb27SDimitry Andric // appears once, so we don't have to handle that here. 419106c3fb27SDimitry Andric if (attr_name == "name") { 419206c3fb27SDimitry Andric LLDB_LOG(log, 419306c3fb27SDimitry Andric "ProcessGDBRemote::ParseFlags Found field node name \"{0}\"", 419406c3fb27SDimitry Andric attr_value.data()); 419506c3fb27SDimitry Andric name = attr_value; 419606c3fb27SDimitry Andric } else if (attr_name == "start") { 419706c3fb27SDimitry Andric unsigned parsed_start = 0; 419806c3fb27SDimitry Andric if (llvm::to_integer(attr_value, parsed_start)) { 419906c3fb27SDimitry Andric if (parsed_start > max_start_bit) { 420006c3fb27SDimitry Andric LLDB_LOG( 420106c3fb27SDimitry Andric log, 420206c3fb27SDimitry Andric "ProcessGDBRemote::ParseFlags Invalid start {0} in field node, " 420306c3fb27SDimitry Andric "cannot be > {1}", 420406c3fb27SDimitry Andric parsed_start, max_start_bit); 420506c3fb27SDimitry Andric } else 420606c3fb27SDimitry Andric start = parsed_start; 420706c3fb27SDimitry Andric } else { 420806c3fb27SDimitry Andric LLDB_LOG(log, 420906c3fb27SDimitry Andric "ProcessGDBRemote::ParseFlags Invalid start \"{0}\" in " 421006c3fb27SDimitry Andric "field node", 421106c3fb27SDimitry Andric attr_value.data()); 421206c3fb27SDimitry Andric } 421306c3fb27SDimitry Andric } else if (attr_name == "end") { 421406c3fb27SDimitry Andric unsigned parsed_end = 0; 421506c3fb27SDimitry Andric if (llvm::to_integer(attr_value, parsed_end)) 421606c3fb27SDimitry Andric if (parsed_end > max_start_bit) { 421706c3fb27SDimitry Andric LLDB_LOG( 421806c3fb27SDimitry Andric log, 421906c3fb27SDimitry Andric "ProcessGDBRemote::ParseFlags Invalid end {0} in field node, " 422006c3fb27SDimitry Andric "cannot be > {1}", 422106c3fb27SDimitry Andric parsed_end, max_start_bit); 422206c3fb27SDimitry Andric } else 422306c3fb27SDimitry Andric end = parsed_end; 422406c3fb27SDimitry Andric else { 422506c3fb27SDimitry Andric LLDB_LOG( 422606c3fb27SDimitry Andric log, 422706c3fb27SDimitry Andric "ProcessGDBRemote::ParseFlags Invalid end \"{0}\" in field node", 422806c3fb27SDimitry Andric attr_value.data()); 422906c3fb27SDimitry Andric } 423006c3fb27SDimitry Andric } else if (attr_name == "type") { 423106c3fb27SDimitry Andric // Type is a known attribute but we do not currently use it and it is 423206c3fb27SDimitry Andric // not required. 423306c3fb27SDimitry Andric } else { 423406c3fb27SDimitry Andric LLDB_LOG(log, 423506c3fb27SDimitry Andric "ProcessGDBRemote::ParseFlags Ignoring unknown attribute " 423606c3fb27SDimitry Andric "\"{0}\" in field node", 423706c3fb27SDimitry Andric attr_name.data()); 423806c3fb27SDimitry Andric } 423906c3fb27SDimitry Andric 424006c3fb27SDimitry Andric return true; // Walk all attributes of the field. 424106c3fb27SDimitry Andric }); 424206c3fb27SDimitry Andric 424306c3fb27SDimitry Andric if (name && start && end) { 424406c3fb27SDimitry Andric if (*start > *end) { 424506c3fb27SDimitry Andric LLDB_LOG(log, 424606c3fb27SDimitry Andric "ProcessGDBRemote::ParseFlags Start {0} > end {1} in field " 424706c3fb27SDimitry Andric "\"{2}\", ignoring", 424806c3fb27SDimitry Andric *start, *end, name->data()); 424906c3fb27SDimitry Andric } else { 425006c3fb27SDimitry Andric fields.push_back(RegisterFlags::Field(name->str(), *start, *end)); 425106c3fb27SDimitry Andric } 425206c3fb27SDimitry Andric } 425306c3fb27SDimitry Andric 425406c3fb27SDimitry Andric return true; // Iterate all "field" nodes. 425506c3fb27SDimitry Andric }); 425606c3fb27SDimitry Andric return fields; 425706c3fb27SDimitry Andric } 425806c3fb27SDimitry Andric 425906c3fb27SDimitry Andric void ParseFlags( 426006c3fb27SDimitry Andric XMLNode feature_node, 426106c3fb27SDimitry Andric llvm::StringMap<std::unique_ptr<RegisterFlags>> ®isters_flags_types) { 426206c3fb27SDimitry Andric Log *log(GetLog(GDBRLog::Process)); 426306c3fb27SDimitry Andric 426406c3fb27SDimitry Andric feature_node.ForEachChildElementWithName( 426506c3fb27SDimitry Andric "flags", 426606c3fb27SDimitry Andric [&log, ®isters_flags_types](const XMLNode &flags_node) -> bool { 426706c3fb27SDimitry Andric LLDB_LOG(log, "ProcessGDBRemote::ParseFlags Found flags node \"{0}\"", 426806c3fb27SDimitry Andric flags_node.GetAttributeValue("id").c_str()); 426906c3fb27SDimitry Andric 427006c3fb27SDimitry Andric std::optional<llvm::StringRef> id; 427106c3fb27SDimitry Andric std::optional<unsigned> size; 427206c3fb27SDimitry Andric flags_node.ForEachAttribute( 427306c3fb27SDimitry Andric [&id, &size, &log](const llvm::StringRef &name, 427406c3fb27SDimitry Andric const llvm::StringRef &value) { 427506c3fb27SDimitry Andric if (name == "id") { 427606c3fb27SDimitry Andric id = value; 427706c3fb27SDimitry Andric } else if (name == "size") { 427806c3fb27SDimitry Andric unsigned parsed_size = 0; 427906c3fb27SDimitry Andric if (llvm::to_integer(value, parsed_size)) 428006c3fb27SDimitry Andric size = parsed_size; 428106c3fb27SDimitry Andric else { 428206c3fb27SDimitry Andric LLDB_LOG(log, 428306c3fb27SDimitry Andric "ProcessGDBRemote::ParseFlags Invalid size \"{0}\" " 428406c3fb27SDimitry Andric "in flags node", 428506c3fb27SDimitry Andric value.data()); 428606c3fb27SDimitry Andric } 428706c3fb27SDimitry Andric } else { 428806c3fb27SDimitry Andric LLDB_LOG(log, 428906c3fb27SDimitry Andric "ProcessGDBRemote::ParseFlags Ignoring unknown " 429006c3fb27SDimitry Andric "attribute \"{0}\" in flags node", 429106c3fb27SDimitry Andric name.data()); 429206c3fb27SDimitry Andric } 429306c3fb27SDimitry Andric return true; // Walk all attributes. 429406c3fb27SDimitry Andric }); 429506c3fb27SDimitry Andric 429606c3fb27SDimitry Andric if (id && size) { 429706c3fb27SDimitry Andric // Process the fields of this set of flags. 429806c3fb27SDimitry Andric std::vector<RegisterFlags::Field> fields = 429906c3fb27SDimitry Andric ParseFlagsFields(flags_node, *size); 430006c3fb27SDimitry Andric if (fields.size()) { 430106c3fb27SDimitry Andric // Sort so that the fields with the MSBs are first. 430206c3fb27SDimitry Andric std::sort(fields.rbegin(), fields.rend()); 430306c3fb27SDimitry Andric std::vector<RegisterFlags::Field>::const_iterator overlap = 430406c3fb27SDimitry Andric std::adjacent_find(fields.begin(), fields.end(), 430506c3fb27SDimitry Andric [](const RegisterFlags::Field &lhs, 430606c3fb27SDimitry Andric const RegisterFlags::Field &rhs) { 430706c3fb27SDimitry Andric return lhs.Overlaps(rhs); 430806c3fb27SDimitry Andric }); 430906c3fb27SDimitry Andric 431006c3fb27SDimitry Andric // If no fields overlap, use them. 431106c3fb27SDimitry Andric if (overlap == fields.end()) { 431206c3fb27SDimitry Andric if (registers_flags_types.contains(*id)) { 431306c3fb27SDimitry Andric // In theory you could define some flag set, use it with a 431406c3fb27SDimitry Andric // register then redefine it. We do not know if anyone does 431506c3fb27SDimitry Andric // that, or what they would expect to happen in that case. 431606c3fb27SDimitry Andric // 431706c3fb27SDimitry Andric // LLDB chooses to take the first definition and ignore the rest 431806c3fb27SDimitry Andric // as waiting until everything has been processed is more 431906c3fb27SDimitry Andric // expensive and difficult. This means that pointers to flag 432006c3fb27SDimitry Andric // sets in the register info remain valid if later the flag set 432106c3fb27SDimitry Andric // is redefined. If we allowed redefinitions, LLDB would crash 432206c3fb27SDimitry Andric // when you tried to print a register that used the original 432306c3fb27SDimitry Andric // definition. 432406c3fb27SDimitry Andric LLDB_LOG( 432506c3fb27SDimitry Andric log, 432606c3fb27SDimitry Andric "ProcessGDBRemote::ParseFlags Definition of flags " 432706c3fb27SDimitry Andric "\"{0}\" shadows " 432806c3fb27SDimitry Andric "previous definition, using original definition instead.", 432906c3fb27SDimitry Andric id->data()); 433006c3fb27SDimitry Andric } else { 433106c3fb27SDimitry Andric registers_flags_types.insert_or_assign( 433206c3fb27SDimitry Andric *id, std::make_unique<RegisterFlags>(id->str(), *size, 433306c3fb27SDimitry Andric std::move(fields))); 433406c3fb27SDimitry Andric } 433506c3fb27SDimitry Andric } else { 433606c3fb27SDimitry Andric // If any fields overlap, ignore the whole set of flags. 433706c3fb27SDimitry Andric std::vector<RegisterFlags::Field>::const_iterator next = 433806c3fb27SDimitry Andric std::next(overlap); 433906c3fb27SDimitry Andric LLDB_LOG( 434006c3fb27SDimitry Andric log, 434106c3fb27SDimitry Andric "ProcessGDBRemote::ParseFlags Ignoring flags because fields " 434206c3fb27SDimitry Andric "{0} (start: {1} end: {2}) and {3} (start: {4} end: {5}) " 434306c3fb27SDimitry Andric "overlap.", 434406c3fb27SDimitry Andric overlap->GetName().c_str(), overlap->GetStart(), 434506c3fb27SDimitry Andric overlap->GetEnd(), next->GetName().c_str(), next->GetStart(), 434606c3fb27SDimitry Andric next->GetEnd()); 434706c3fb27SDimitry Andric } 434806c3fb27SDimitry Andric } else { 434906c3fb27SDimitry Andric LLDB_LOG( 435006c3fb27SDimitry Andric log, 435106c3fb27SDimitry Andric "ProcessGDBRemote::ParseFlags Ignoring definition of flags " 435206c3fb27SDimitry Andric "\"{0}\" because it contains no fields.", 435306c3fb27SDimitry Andric id->data()); 435406c3fb27SDimitry Andric } 435506c3fb27SDimitry Andric } 435606c3fb27SDimitry Andric 435706c3fb27SDimitry Andric return true; // Keep iterating through all "flags" elements. 435806c3fb27SDimitry Andric }); 435906c3fb27SDimitry Andric } 436006c3fb27SDimitry Andric 436106c3fb27SDimitry Andric bool ParseRegisters( 436206c3fb27SDimitry Andric XMLNode feature_node, GdbServerTargetInfo &target_info, 436306c3fb27SDimitry Andric std::vector<DynamicRegisterInfo::Register> ®isters, 436406c3fb27SDimitry Andric llvm::StringMap<std::unique_ptr<RegisterFlags>> ®isters_flags_types) { 43650b57cec5SDimitry Andric if (!feature_node) 43660b57cec5SDimitry Andric return false; 43670b57cec5SDimitry Andric 4368bdd1243dSDimitry Andric Log *log(GetLog(GDBRLog::Process)); 4369bdd1243dSDimitry Andric 437006c3fb27SDimitry Andric ParseFlags(feature_node, registers_flags_types); 437106c3fb27SDimitry Andric for (const auto &flags : registers_flags_types) 437206c3fb27SDimitry Andric flags.second->log(log); 437306c3fb27SDimitry Andric 43740b57cec5SDimitry Andric feature_node.ForEachChildElementWithName( 437506c3fb27SDimitry Andric "reg", 437606c3fb27SDimitry Andric [&target_info, ®isters, ®isters_flags_types, 437706c3fb27SDimitry Andric log](const XMLNode ®_node) -> bool { 43780b57cec5SDimitry Andric std::string gdb_group; 43790b57cec5SDimitry Andric std::string gdb_type; 4380349cc55cSDimitry Andric DynamicRegisterInfo::Register reg_info; 43810b57cec5SDimitry Andric bool encoding_set = false; 43820b57cec5SDimitry Andric bool format_set = false; 43830b57cec5SDimitry Andric 4384349cc55cSDimitry Andric // FIXME: we're silently ignoring invalid data here 43850b57cec5SDimitry Andric reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, 4386bdd1243dSDimitry Andric &encoding_set, &format_set, ®_info, 4387bdd1243dSDimitry Andric log](const llvm::StringRef &name, 43880b57cec5SDimitry Andric const llvm::StringRef &value) -> bool { 43890b57cec5SDimitry Andric if (name == "name") { 4390349cc55cSDimitry Andric reg_info.name.SetString(value); 43910b57cec5SDimitry Andric } else if (name == "bitsize") { 4392349cc55cSDimitry Andric if (llvm::to_integer(value, reg_info.byte_size)) 43930b57cec5SDimitry Andric reg_info.byte_size = 4394349cc55cSDimitry Andric llvm::divideCeil(reg_info.byte_size, CHAR_BIT); 43950b57cec5SDimitry Andric } else if (name == "type") { 43960b57cec5SDimitry Andric gdb_type = value.str(); 43970b57cec5SDimitry Andric } else if (name == "group") { 43980b57cec5SDimitry Andric gdb_group = value.str(); 43990b57cec5SDimitry Andric } else if (name == "regnum") { 4400349cc55cSDimitry Andric llvm::to_integer(value, reg_info.regnum_remote); 44010b57cec5SDimitry Andric } else if (name == "offset") { 4402349cc55cSDimitry Andric llvm::to_integer(value, reg_info.byte_offset); 44030b57cec5SDimitry Andric } else if (name == "altname") { 4404349cc55cSDimitry Andric reg_info.alt_name.SetString(value); 44050b57cec5SDimitry Andric } else if (name == "encoding") { 44060b57cec5SDimitry Andric encoding_set = true; 44070b57cec5SDimitry Andric reg_info.encoding = Args::StringToEncoding(value, eEncodingUint); 44080b57cec5SDimitry Andric } else if (name == "format") { 44090b57cec5SDimitry Andric format_set = true; 4410349cc55cSDimitry Andric if (!OptionArgParser::ToFormat(value.data(), reg_info.format, 4411349cc55cSDimitry Andric nullptr) 44120b57cec5SDimitry Andric .Success()) 4413349cc55cSDimitry Andric reg_info.format = 4414349cc55cSDimitry Andric llvm::StringSwitch<lldb::Format>(value) 4415349cc55cSDimitry Andric .Case("vector-sint8", eFormatVectorOfSInt8) 4416349cc55cSDimitry Andric .Case("vector-uint8", eFormatVectorOfUInt8) 4417349cc55cSDimitry Andric .Case("vector-sint16", eFormatVectorOfSInt16) 4418349cc55cSDimitry Andric .Case("vector-uint16", eFormatVectorOfUInt16) 4419349cc55cSDimitry Andric .Case("vector-sint32", eFormatVectorOfSInt32) 4420349cc55cSDimitry Andric .Case("vector-uint32", eFormatVectorOfUInt32) 4421349cc55cSDimitry Andric .Case("vector-float32", eFormatVectorOfFloat32) 4422349cc55cSDimitry Andric .Case("vector-uint64", eFormatVectorOfUInt64) 4423349cc55cSDimitry Andric .Case("vector-uint128", eFormatVectorOfUInt128) 4424349cc55cSDimitry Andric .Default(eFormatInvalid); 44250b57cec5SDimitry Andric } else if (name == "group_id") { 4426349cc55cSDimitry Andric uint32_t set_id = UINT32_MAX; 4427349cc55cSDimitry Andric llvm::to_integer(value, set_id); 44280b57cec5SDimitry Andric RegisterSetMap::const_iterator pos = 44290b57cec5SDimitry Andric target_info.reg_set_map.find(set_id); 44300b57cec5SDimitry Andric if (pos != target_info.reg_set_map.end()) 4431349cc55cSDimitry Andric reg_info.set_name = pos->second.name; 44320b57cec5SDimitry Andric } else if (name == "gcc_regnum" || name == "ehframe_regnum") { 4433349cc55cSDimitry Andric llvm::to_integer(value, reg_info.regnum_ehframe); 44340b57cec5SDimitry Andric } else if (name == "dwarf_regnum") { 4435349cc55cSDimitry Andric llvm::to_integer(value, reg_info.regnum_dwarf); 44360b57cec5SDimitry Andric } else if (name == "generic") { 4437349cc55cSDimitry Andric reg_info.regnum_generic = Args::StringToGenericRegister(value); 44380b57cec5SDimitry Andric } else if (name == "value_regnums") { 4439349cc55cSDimitry Andric SplitCommaSeparatedRegisterNumberString(value, reg_info.value_regs, 4440349cc55cSDimitry Andric 0); 44410b57cec5SDimitry Andric } else if (name == "invalidate_regnums") { 4442349cc55cSDimitry Andric SplitCommaSeparatedRegisterNumberString( 4443349cc55cSDimitry Andric value, reg_info.invalidate_regs, 0); 44440b57cec5SDimitry Andric } else { 4445349cc55cSDimitry Andric LLDB_LOGF(log, 4446bdd1243dSDimitry Andric "ProcessGDBRemote::ParseRegisters unhandled reg " 4447bdd1243dSDimitry Andric "attribute %s = %s", 4448bdd1243dSDimitry Andric name.data(), value.data()); 44490b57cec5SDimitry Andric } 44500b57cec5SDimitry Andric return true; // Keep iterating through all attributes 44510b57cec5SDimitry Andric }); 44520b57cec5SDimitry Andric 445306c3fb27SDimitry Andric if (!gdb_type.empty()) { 445406c3fb27SDimitry Andric // gdb_type could reference some flags type defined in XML. 445506c3fb27SDimitry Andric llvm::StringMap<std::unique_ptr<RegisterFlags>>::iterator it = 445606c3fb27SDimitry Andric registers_flags_types.find(gdb_type); 445706c3fb27SDimitry Andric if (it != registers_flags_types.end()) { 445806c3fb27SDimitry Andric auto flags_type = it->second.get(); 445906c3fb27SDimitry Andric if (reg_info.byte_size == flags_type->GetSize()) 446006c3fb27SDimitry Andric reg_info.flags_type = flags_type; 446106c3fb27SDimitry Andric else 446206c3fb27SDimitry Andric LLDB_LOGF(log, 446306c3fb27SDimitry Andric "ProcessGDBRemote::ParseRegisters Size of register " 446406c3fb27SDimitry Andric "flags %s (%d bytes) for " 446506c3fb27SDimitry Andric "register %s does not match the register size (%d " 446606c3fb27SDimitry Andric "bytes). Ignoring this set of flags.", 446706c3fb27SDimitry Andric flags_type->GetID().c_str(), flags_type->GetSize(), 446806c3fb27SDimitry Andric reg_info.name.AsCString(), reg_info.byte_size); 446906c3fb27SDimitry Andric } 447006c3fb27SDimitry Andric 447106c3fb27SDimitry Andric // There's a slim chance that the gdb_type name is both a flags type 447206c3fb27SDimitry Andric // and a simple type. Just in case, look for that too (setting both 447306c3fb27SDimitry Andric // does no harm). 44740b57cec5SDimitry Andric if (!gdb_type.empty() && !(encoding_set || format_set)) { 4475*5f757f3fSDimitry Andric if (llvm::StringRef(gdb_type).starts_with("int")) { 44760b57cec5SDimitry Andric reg_info.format = eFormatHex; 44770b57cec5SDimitry Andric reg_info.encoding = eEncodingUint; 44780b57cec5SDimitry Andric } else if (gdb_type == "data_ptr" || gdb_type == "code_ptr") { 44790b57cec5SDimitry Andric reg_info.format = eFormatAddressInfo; 44800b57cec5SDimitry Andric reg_info.encoding = eEncodingUint; 4481349cc55cSDimitry Andric } else if (gdb_type == "float") { 44820b57cec5SDimitry Andric reg_info.format = eFormatFloat; 44830b57cec5SDimitry Andric reg_info.encoding = eEncodingIEEE754; 4484349cc55cSDimitry Andric } else if (gdb_type == "aarch64v" || 4485*5f757f3fSDimitry Andric llvm::StringRef(gdb_type).starts_with("vec") || 4486349cc55cSDimitry Andric gdb_type == "i387_ext" || gdb_type == "uint128") { 448706c3fb27SDimitry Andric // lldb doesn't handle 128-bit uints correctly (for ymm*h), so 448806c3fb27SDimitry Andric // treat them as vector (similarly to xmm/ymm) 4489349cc55cSDimitry Andric reg_info.format = eFormatVectorOfUInt8; 4490349cc55cSDimitry Andric reg_info.encoding = eEncodingVector; 4491bdd1243dSDimitry Andric } else { 4492bdd1243dSDimitry Andric LLDB_LOGF( 4493bdd1243dSDimitry Andric log, 4494bdd1243dSDimitry Andric "ProcessGDBRemote::ParseRegisters Could not determine lldb" 4495bdd1243dSDimitry Andric "format and encoding for gdb type %s", 4496bdd1243dSDimitry Andric gdb_type.c_str()); 44970b57cec5SDimitry Andric } 44980b57cec5SDimitry Andric } 449906c3fb27SDimitry Andric } 45000b57cec5SDimitry Andric 45010b57cec5SDimitry Andric // Only update the register set name if we didn't get a "reg_set" 45020b57cec5SDimitry Andric // attribute. "set_name" will be empty if we didn't have a "reg_set" 45030b57cec5SDimitry Andric // attribute. 4504349cc55cSDimitry Andric if (!reg_info.set_name) { 45050b57cec5SDimitry Andric if (!gdb_group.empty()) { 4506349cc55cSDimitry Andric reg_info.set_name.SetCString(gdb_group.c_str()); 45070b57cec5SDimitry Andric } else { 45080b57cec5SDimitry Andric // If no register group name provided anywhere, 45090b57cec5SDimitry Andric // we'll create a 'general' register set 4510349cc55cSDimitry Andric reg_info.set_name.SetCString("general"); 45110b57cec5SDimitry Andric } 45120b57cec5SDimitry Andric } 45130b57cec5SDimitry Andric 4514349cc55cSDimitry Andric if (reg_info.byte_size == 0) { 4515349cc55cSDimitry Andric LLDB_LOGF(log, 4516349cc55cSDimitry Andric "ProcessGDBRemote::%s Skipping zero bitsize register %s", 4517349cc55cSDimitry Andric __FUNCTION__, reg_info.name.AsCString()); 4518349cc55cSDimitry Andric } else 4519349cc55cSDimitry Andric registers.push_back(reg_info); 45200b57cec5SDimitry Andric 45210b57cec5SDimitry Andric return true; // Keep iterating through all "reg" elements 45220b57cec5SDimitry Andric }); 45230b57cec5SDimitry Andric return true; 45240b57cec5SDimitry Andric } 45250b57cec5SDimitry Andric 45260b57cec5SDimitry Andric } // namespace 45270b57cec5SDimitry Andric 45280b57cec5SDimitry Andric // This method fetches a register description feature xml file from 45290b57cec5SDimitry Andric // the remote stub and adds registers/register groupsets/architecture 45300b57cec5SDimitry Andric // information to the current process. It will call itself recursively 45310b57cec5SDimitry Andric // for nested register definition files. It returns true if it was able 45320b57cec5SDimitry Andric // to fetch and parse an xml file. 45339dba64beSDimitry Andric bool ProcessGDBRemote::GetGDBServerRegisterInfoXMLAndProcess( 4534349cc55cSDimitry Andric ArchSpec &arch_to_use, std::string xml_filename, 4535349cc55cSDimitry Andric std::vector<DynamicRegisterInfo::Register> ®isters) { 45360b57cec5SDimitry Andric // request the target xml file 4537349cc55cSDimitry Andric llvm::Expected<std::string> raw = m_gdb_comm.ReadExtFeature("features", xml_filename); 4538349cc55cSDimitry Andric if (errorToBool(raw.takeError())) 45390b57cec5SDimitry Andric return false; 45400b57cec5SDimitry Andric 45410b57cec5SDimitry Andric XMLDocument xml_document; 45420b57cec5SDimitry Andric 4543349cc55cSDimitry Andric if (xml_document.ParseMemory(raw->c_str(), raw->size(), 4544349cc55cSDimitry Andric xml_filename.c_str())) { 45450b57cec5SDimitry Andric GdbServerTargetInfo target_info; 45460b57cec5SDimitry Andric std::vector<XMLNode> feature_nodes; 45470b57cec5SDimitry Andric 45480b57cec5SDimitry Andric // The top level feature XML file will start with a <target> tag. 45490b57cec5SDimitry Andric XMLNode target_node = xml_document.GetRootElement("target"); 45500b57cec5SDimitry Andric if (target_node) { 45510b57cec5SDimitry Andric target_node.ForEachChildElement([&target_info, &feature_nodes]( 45520b57cec5SDimitry Andric const XMLNode &node) -> bool { 45530b57cec5SDimitry Andric llvm::StringRef name = node.GetName(); 45540b57cec5SDimitry Andric if (name == "architecture") { 45550b57cec5SDimitry Andric node.GetElementText(target_info.arch); 45560b57cec5SDimitry Andric } else if (name == "osabi") { 45570b57cec5SDimitry Andric node.GetElementText(target_info.osabi); 45580b57cec5SDimitry Andric } else if (name == "xi:include" || name == "include") { 455904eeddc0SDimitry Andric std::string href = node.GetAttributeValue("href"); 45600b57cec5SDimitry Andric if (!href.empty()) 456104eeddc0SDimitry Andric target_info.includes.push_back(href); 45620b57cec5SDimitry Andric } else if (name == "feature") { 45630b57cec5SDimitry Andric feature_nodes.push_back(node); 45640b57cec5SDimitry Andric } else if (name == "groups") { 45650b57cec5SDimitry Andric node.ForEachChildElementWithName( 45660b57cec5SDimitry Andric "group", [&target_info](const XMLNode &node) -> bool { 45670b57cec5SDimitry Andric uint32_t set_id = UINT32_MAX; 45680b57cec5SDimitry Andric RegisterSetInfo set_info; 45690b57cec5SDimitry Andric 45700b57cec5SDimitry Andric node.ForEachAttribute( 45710b57cec5SDimitry Andric [&set_id, &set_info](const llvm::StringRef &name, 45720b57cec5SDimitry Andric const llvm::StringRef &value) -> bool { 4573349cc55cSDimitry Andric // FIXME: we're silently ignoring invalid data here 45740b57cec5SDimitry Andric if (name == "id") 4575349cc55cSDimitry Andric llvm::to_integer(value, set_id); 45760b57cec5SDimitry Andric if (name == "name") 45770b57cec5SDimitry Andric set_info.name = ConstString(value); 45780b57cec5SDimitry Andric return true; // Keep iterating through all attributes 45790b57cec5SDimitry Andric }); 45800b57cec5SDimitry Andric 45810b57cec5SDimitry Andric if (set_id != UINT32_MAX) 45820b57cec5SDimitry Andric target_info.reg_set_map[set_id] = set_info; 45830b57cec5SDimitry Andric return true; // Keep iterating through all "group" elements 45840b57cec5SDimitry Andric }); 45850b57cec5SDimitry Andric } 45860b57cec5SDimitry Andric return true; // Keep iterating through all children of the target_node 45870b57cec5SDimitry Andric }); 45880b57cec5SDimitry Andric } else { 45890b57cec5SDimitry Andric // In an included XML feature file, we're already "inside" the <target> 45900b57cec5SDimitry Andric // tag of the initial XML file; this included file will likely only have 45910b57cec5SDimitry Andric // a <feature> tag. Need to check for any more included files in this 45920b57cec5SDimitry Andric // <feature> element. 45930b57cec5SDimitry Andric XMLNode feature_node = xml_document.GetRootElement("feature"); 45940b57cec5SDimitry Andric if (feature_node) { 45950b57cec5SDimitry Andric feature_nodes.push_back(feature_node); 45960b57cec5SDimitry Andric feature_node.ForEachChildElement([&target_info]( 45970b57cec5SDimitry Andric const XMLNode &node) -> bool { 45980b57cec5SDimitry Andric llvm::StringRef name = node.GetName(); 45990b57cec5SDimitry Andric if (name == "xi:include" || name == "include") { 460004eeddc0SDimitry Andric std::string href = node.GetAttributeValue("href"); 46010b57cec5SDimitry Andric if (!href.empty()) 460204eeddc0SDimitry Andric target_info.includes.push_back(href); 46030b57cec5SDimitry Andric } 46040b57cec5SDimitry Andric return true; 46050b57cec5SDimitry Andric }); 46060b57cec5SDimitry Andric } 46070b57cec5SDimitry Andric } 46080b57cec5SDimitry Andric 4609349cc55cSDimitry Andric // gdbserver does not implement the LLDB packets used to determine host 4610349cc55cSDimitry Andric // or process architecture. If that is the case, attempt to use 4611349cc55cSDimitry Andric // the <architecture/> field from target.xml, e.g.: 4612349cc55cSDimitry Andric // 46130b57cec5SDimitry Andric // <architecture>i386:x86-64</architecture> (seen from VMWare ESXi) 4614349cc55cSDimitry Andric // <architecture>arm</architecture> (seen from Segger JLink on unspecified 4615349cc55cSDimitry Andric // arm board) 46160b57cec5SDimitry Andric if (!arch_to_use.IsValid() && !target_info.arch.empty()) { 46170b57cec5SDimitry Andric // We don't have any information about vendor or OS. 4618349cc55cSDimitry Andric arch_to_use.SetTriple(llvm::StringSwitch<std::string>(target_info.arch) 4619349cc55cSDimitry Andric .Case("i386:x86-64", "x86_64") 4620349cc55cSDimitry Andric .Default(target_info.arch) + 4621349cc55cSDimitry Andric "--"); 46220b57cec5SDimitry Andric 4623349cc55cSDimitry Andric if (arch_to_use.IsValid()) 46240b57cec5SDimitry Andric GetTarget().MergeArchitecture(arch_to_use); 46250b57cec5SDimitry Andric } 46260b57cec5SDimitry Andric 46270b57cec5SDimitry Andric if (arch_to_use.IsValid()) { 46280b57cec5SDimitry Andric for (auto &feature_node : feature_nodes) { 462906c3fb27SDimitry Andric ParseRegisters(feature_node, target_info, registers, 463006c3fb27SDimitry Andric m_registers_flags_types); 46310b57cec5SDimitry Andric } 46320b57cec5SDimitry Andric 46330b57cec5SDimitry Andric for (const auto &include : target_info.includes) { 4634e8d8bef9SDimitry Andric GetGDBServerRegisterInfoXMLAndProcess(arch_to_use, include, 4635349cc55cSDimitry Andric registers); 46360b57cec5SDimitry Andric } 46370b57cec5SDimitry Andric } 46380b57cec5SDimitry Andric } else { 46390b57cec5SDimitry Andric return false; 46400b57cec5SDimitry Andric } 46410b57cec5SDimitry Andric return true; 46420b57cec5SDimitry Andric } 46430b57cec5SDimitry Andric 4644349cc55cSDimitry Andric void ProcessGDBRemote::AddRemoteRegisters( 4645349cc55cSDimitry Andric std::vector<DynamicRegisterInfo::Register> ®isters, 4646349cc55cSDimitry Andric const ArchSpec &arch_to_use) { 4647349cc55cSDimitry Andric std::map<uint32_t, uint32_t> remote_to_local_map; 4648349cc55cSDimitry Andric uint32_t remote_regnum = 0; 4649349cc55cSDimitry Andric for (auto it : llvm::enumerate(registers)) { 4650349cc55cSDimitry Andric DynamicRegisterInfo::Register &remote_reg_info = it.value(); 4651349cc55cSDimitry Andric 4652349cc55cSDimitry Andric // Assign successive remote regnums if missing. 4653349cc55cSDimitry Andric if (remote_reg_info.regnum_remote == LLDB_INVALID_REGNUM) 4654349cc55cSDimitry Andric remote_reg_info.regnum_remote = remote_regnum; 4655349cc55cSDimitry Andric 4656349cc55cSDimitry Andric // Create a mapping from remote to local regnos. 4657349cc55cSDimitry Andric remote_to_local_map[remote_reg_info.regnum_remote] = it.index(); 4658349cc55cSDimitry Andric 4659349cc55cSDimitry Andric remote_regnum = remote_reg_info.regnum_remote + 1; 4660349cc55cSDimitry Andric } 4661349cc55cSDimitry Andric 4662349cc55cSDimitry Andric for (DynamicRegisterInfo::Register &remote_reg_info : registers) { 4663349cc55cSDimitry Andric auto proc_to_lldb = [&remote_to_local_map](uint32_t process_regnum) { 4664349cc55cSDimitry Andric auto lldb_regit = remote_to_local_map.find(process_regnum); 4665349cc55cSDimitry Andric return lldb_regit != remote_to_local_map.end() ? lldb_regit->second 4666349cc55cSDimitry Andric : LLDB_INVALID_REGNUM; 4667349cc55cSDimitry Andric }; 4668349cc55cSDimitry Andric 4669349cc55cSDimitry Andric llvm::transform(remote_reg_info.value_regs, 4670349cc55cSDimitry Andric remote_reg_info.value_regs.begin(), proc_to_lldb); 4671349cc55cSDimitry Andric llvm::transform(remote_reg_info.invalidate_regs, 4672349cc55cSDimitry Andric remote_reg_info.invalidate_regs.begin(), proc_to_lldb); 4673349cc55cSDimitry Andric } 4674349cc55cSDimitry Andric 4675349cc55cSDimitry Andric // Don't use Process::GetABI, this code gets called from DidAttach, and 4676349cc55cSDimitry Andric // in that context we haven't set the Target's architecture yet, so the 4677349cc55cSDimitry Andric // ABI is also potentially incorrect. 4678349cc55cSDimitry Andric if (ABISP abi_sp = ABI::FindPlugin(shared_from_this(), arch_to_use)) 4679349cc55cSDimitry Andric abi_sp->AugmentRegisterInfo(registers); 4680349cc55cSDimitry Andric 4681349cc55cSDimitry Andric m_register_info_sp->SetRegisterInfo(std::move(registers), arch_to_use); 4682349cc55cSDimitry Andric } 4683349cc55cSDimitry Andric 46840b57cec5SDimitry Andric // query the target of gdb-remote for extended target information returns 46850b57cec5SDimitry Andric // true on success (got register definitions), false on failure (did not). 46860b57cec5SDimitry Andric bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) { 46870b57cec5SDimitry Andric // Make sure LLDB has an XML parser it can use first 46880b57cec5SDimitry Andric if (!XMLDocument::XMLEnabled()) 46890b57cec5SDimitry Andric return false; 46900b57cec5SDimitry Andric 46910b57cec5SDimitry Andric // check that we have extended feature read support 46920b57cec5SDimitry Andric if (!m_gdb_comm.GetQXferFeaturesReadSupported()) 46930b57cec5SDimitry Andric return false; 46940b57cec5SDimitry Andric 469506c3fb27SDimitry Andric // This holds register flags information for the whole of target.xml. 469606c3fb27SDimitry Andric // target.xml may include further documents that 469706c3fb27SDimitry Andric // GetGDBServerRegisterInfoXMLAndProcess will recurse to fetch and process. 469806c3fb27SDimitry Andric // That's why we clear the cache here, and not in 469906c3fb27SDimitry Andric // GetGDBServerRegisterInfoXMLAndProcess. To prevent it being cleared on every 470006c3fb27SDimitry Andric // include read. 470106c3fb27SDimitry Andric m_registers_flags_types.clear(); 4702349cc55cSDimitry Andric std::vector<DynamicRegisterInfo::Register> registers; 4703e8d8bef9SDimitry Andric if (GetGDBServerRegisterInfoXMLAndProcess(arch_to_use, "target.xml", 4704349cc55cSDimitry Andric registers)) 4705349cc55cSDimitry Andric AddRemoteRegisters(registers, arch_to_use); 47060b57cec5SDimitry Andric 4707e8d8bef9SDimitry Andric return m_register_info_sp->GetNumRegisters() > 0; 47080b57cec5SDimitry Andric } 47090b57cec5SDimitry Andric 47109dba64beSDimitry Andric llvm::Expected<LoadedModuleInfoList> ProcessGDBRemote::GetLoadedModuleList() { 47110b57cec5SDimitry Andric // Make sure LLDB has an XML parser it can use first 47120b57cec5SDimitry Andric if (!XMLDocument::XMLEnabled()) 47139dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 47149dba64beSDimitry Andric "XML parsing not available"); 47150b57cec5SDimitry Andric 471681ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 47179dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::%s", __FUNCTION__); 47180b57cec5SDimitry Andric 47199dba64beSDimitry Andric LoadedModuleInfoList list; 47200b57cec5SDimitry Andric GDBRemoteCommunicationClient &comm = m_gdb_comm; 4721349cc55cSDimitry Andric bool can_use_svr4 = GetGlobalPluginProperties().GetUseSVR4(); 47220b57cec5SDimitry Andric 47230b57cec5SDimitry Andric // check that we have extended feature read support 47240b57cec5SDimitry Andric if (can_use_svr4 && comm.GetQXferLibrariesSVR4ReadSupported()) { 47250b57cec5SDimitry Andric // request the loaded library list 4726349cc55cSDimitry Andric llvm::Expected<std::string> raw = comm.ReadExtFeature("libraries-svr4", ""); 4727349cc55cSDimitry Andric if (!raw) 4728349cc55cSDimitry Andric return raw.takeError(); 47290b57cec5SDimitry Andric 47300b57cec5SDimitry Andric // parse the xml file in memory 4731349cc55cSDimitry Andric LLDB_LOGF(log, "parsing: %s", raw->c_str()); 47320b57cec5SDimitry Andric XMLDocument doc; 47330b57cec5SDimitry Andric 4734349cc55cSDimitry Andric if (!doc.ParseMemory(raw->c_str(), raw->size(), "noname.xml")) 47359dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 47369dba64beSDimitry Andric "Error reading noname.xml"); 47370b57cec5SDimitry Andric 47380b57cec5SDimitry Andric XMLNode root_element = doc.GetRootElement("library-list-svr4"); 47390b57cec5SDimitry Andric if (!root_element) 47409dba64beSDimitry Andric return llvm::createStringError( 47419dba64beSDimitry Andric llvm::inconvertibleErrorCode(), 47429dba64beSDimitry Andric "Error finding library-list-svr4 xml element"); 47430b57cec5SDimitry Andric 47440b57cec5SDimitry Andric // main link map structure 474504eeddc0SDimitry Andric std::string main_lm = root_element.GetAttributeValue("main-lm"); 4746349cc55cSDimitry Andric // FIXME: we're silently ignoring invalid data here 4747349cc55cSDimitry Andric if (!main_lm.empty()) 4748349cc55cSDimitry Andric llvm::to_integer(main_lm, list.m_link_map); 47490b57cec5SDimitry Andric 47500b57cec5SDimitry Andric root_element.ForEachChildElementWithName( 47510b57cec5SDimitry Andric "library", [log, &list](const XMLNode &library) -> bool { 47520b57cec5SDimitry Andric LoadedModuleInfoList::LoadedModuleInfo module; 47530b57cec5SDimitry Andric 4754349cc55cSDimitry Andric // FIXME: we're silently ignoring invalid data here 47550b57cec5SDimitry Andric library.ForEachAttribute( 47560b57cec5SDimitry Andric [&module](const llvm::StringRef &name, 47570b57cec5SDimitry Andric const llvm::StringRef &value) -> bool { 4758349cc55cSDimitry Andric uint64_t uint_value = LLDB_INVALID_ADDRESS; 47590b57cec5SDimitry Andric if (name == "name") 47600b57cec5SDimitry Andric module.set_name(value.str()); 47610b57cec5SDimitry Andric else if (name == "lm") { 47620b57cec5SDimitry Andric // the address of the link_map struct. 4763349cc55cSDimitry Andric llvm::to_integer(value, uint_value); 4764349cc55cSDimitry Andric module.set_link_map(uint_value); 47650b57cec5SDimitry Andric } else if (name == "l_addr") { 47660b57cec5SDimitry Andric // the displacement as read from the field 'l_addr' of the 47670b57cec5SDimitry Andric // link_map struct. 4768349cc55cSDimitry Andric llvm::to_integer(value, uint_value); 4769349cc55cSDimitry Andric module.set_base(uint_value); 47700b57cec5SDimitry Andric // base address is always a displacement, not an absolute 47710b57cec5SDimitry Andric // value. 47720b57cec5SDimitry Andric module.set_base_is_offset(true); 47730b57cec5SDimitry Andric } else if (name == "l_ld") { 47745ffd83dbSDimitry Andric // the memory address of the libraries PT_DYNAMIC section. 4775349cc55cSDimitry Andric llvm::to_integer(value, uint_value); 4776349cc55cSDimitry Andric module.set_dynamic(uint_value); 47770b57cec5SDimitry Andric } 47780b57cec5SDimitry Andric 47790b57cec5SDimitry Andric return true; // Keep iterating over all properties of "library" 47800b57cec5SDimitry Andric }); 47810b57cec5SDimitry Andric 47820b57cec5SDimitry Andric if (log) { 47830b57cec5SDimitry Andric std::string name; 47840b57cec5SDimitry Andric lldb::addr_t lm = 0, base = 0, ld = 0; 47850b57cec5SDimitry Andric bool base_is_offset; 47860b57cec5SDimitry Andric 47870b57cec5SDimitry Andric module.get_name(name); 47880b57cec5SDimitry Andric module.get_link_map(lm); 47890b57cec5SDimitry Andric module.get_base(base); 47900b57cec5SDimitry Andric module.get_base_is_offset(base_is_offset); 47910b57cec5SDimitry Andric module.get_dynamic(ld); 47920b57cec5SDimitry Andric 47939dba64beSDimitry Andric LLDB_LOGF(log, 47949dba64beSDimitry Andric "found (link_map:0x%08" PRIx64 ", base:0x%08" PRIx64 47950b57cec5SDimitry Andric "[%s], ld:0x%08" PRIx64 ", name:'%s')", 47960b57cec5SDimitry Andric lm, base, (base_is_offset ? "offset" : "absolute"), ld, 47970b57cec5SDimitry Andric name.c_str()); 47980b57cec5SDimitry Andric } 47990b57cec5SDimitry Andric 48000b57cec5SDimitry Andric list.add(module); 48010b57cec5SDimitry Andric return true; // Keep iterating over all "library" elements in the root 48020b57cec5SDimitry Andric // node 48030b57cec5SDimitry Andric }); 48040b57cec5SDimitry Andric 48050b57cec5SDimitry Andric if (log) 48069dba64beSDimitry Andric LLDB_LOGF(log, "found %" PRId32 " modules in total", 48070b57cec5SDimitry Andric (int)list.m_list.size()); 48089dba64beSDimitry Andric return list; 48090b57cec5SDimitry Andric } else if (comm.GetQXferLibrariesReadSupported()) { 48100b57cec5SDimitry Andric // request the loaded library list 4811349cc55cSDimitry Andric llvm::Expected<std::string> raw = comm.ReadExtFeature("libraries", ""); 48120b57cec5SDimitry Andric 4813349cc55cSDimitry Andric if (!raw) 4814349cc55cSDimitry Andric return raw.takeError(); 48150b57cec5SDimitry Andric 4816349cc55cSDimitry Andric LLDB_LOGF(log, "parsing: %s", raw->c_str()); 48170b57cec5SDimitry Andric XMLDocument doc; 48180b57cec5SDimitry Andric 4819349cc55cSDimitry Andric if (!doc.ParseMemory(raw->c_str(), raw->size(), "noname.xml")) 48209dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 48219dba64beSDimitry Andric "Error reading noname.xml"); 48220b57cec5SDimitry Andric 48230b57cec5SDimitry Andric XMLNode root_element = doc.GetRootElement("library-list"); 48240b57cec5SDimitry Andric if (!root_element) 48259dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 48269dba64beSDimitry Andric "Error finding library-list xml element"); 48270b57cec5SDimitry Andric 4828349cc55cSDimitry Andric // FIXME: we're silently ignoring invalid data here 48290b57cec5SDimitry Andric root_element.ForEachChildElementWithName( 48300b57cec5SDimitry Andric "library", [log, &list](const XMLNode &library) -> bool { 48310b57cec5SDimitry Andric LoadedModuleInfoList::LoadedModuleInfo module; 48320b57cec5SDimitry Andric 483304eeddc0SDimitry Andric std::string name = library.GetAttributeValue("name"); 483404eeddc0SDimitry Andric module.set_name(name); 48350b57cec5SDimitry Andric 48360b57cec5SDimitry Andric // The base address of a given library will be the address of its 48370b57cec5SDimitry Andric // first section. Most remotes send only one section for Windows 48380b57cec5SDimitry Andric // targets for example. 48390b57cec5SDimitry Andric const XMLNode §ion = 48400b57cec5SDimitry Andric library.FindFirstChildElementWithName("section"); 484104eeddc0SDimitry Andric std::string address = section.GetAttributeValue("address"); 4842349cc55cSDimitry Andric uint64_t address_value = LLDB_INVALID_ADDRESS; 4843349cc55cSDimitry Andric llvm::to_integer(address, address_value); 4844349cc55cSDimitry Andric module.set_base(address_value); 48450b57cec5SDimitry Andric // These addresses are absolute values. 48460b57cec5SDimitry Andric module.set_base_is_offset(false); 48470b57cec5SDimitry Andric 48480b57cec5SDimitry Andric if (log) { 48490b57cec5SDimitry Andric std::string name; 48500b57cec5SDimitry Andric lldb::addr_t base = 0; 48510b57cec5SDimitry Andric bool base_is_offset; 48520b57cec5SDimitry Andric module.get_name(name); 48530b57cec5SDimitry Andric module.get_base(base); 48540b57cec5SDimitry Andric module.get_base_is_offset(base_is_offset); 48550b57cec5SDimitry Andric 48569dba64beSDimitry Andric LLDB_LOGF(log, "found (base:0x%08" PRIx64 "[%s], name:'%s')", base, 48570b57cec5SDimitry Andric (base_is_offset ? "offset" : "absolute"), name.c_str()); 48580b57cec5SDimitry Andric } 48590b57cec5SDimitry Andric 48600b57cec5SDimitry Andric list.add(module); 48610b57cec5SDimitry Andric return true; // Keep iterating over all "library" elements in the root 48620b57cec5SDimitry Andric // node 48630b57cec5SDimitry Andric }); 48640b57cec5SDimitry Andric 48650b57cec5SDimitry Andric if (log) 48669dba64beSDimitry Andric LLDB_LOGF(log, "found %" PRId32 " modules in total", 48670b57cec5SDimitry Andric (int)list.m_list.size()); 48689dba64beSDimitry Andric return list; 48690b57cec5SDimitry Andric } else { 48709dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 48719dba64beSDimitry Andric "Remote libraries not supported"); 48720b57cec5SDimitry Andric } 48730b57cec5SDimitry Andric } 48740b57cec5SDimitry Andric 48750b57cec5SDimitry Andric lldb::ModuleSP ProcessGDBRemote::LoadModuleAtAddress(const FileSpec &file, 48760b57cec5SDimitry Andric lldb::addr_t link_map, 48770b57cec5SDimitry Andric lldb::addr_t base_addr, 48780b57cec5SDimitry Andric bool value_is_offset) { 48790b57cec5SDimitry Andric DynamicLoader *loader = GetDynamicLoader(); 48800b57cec5SDimitry Andric if (!loader) 48810b57cec5SDimitry Andric return nullptr; 48820b57cec5SDimitry Andric 48830b57cec5SDimitry Andric return loader->LoadModuleAtAddress(file, link_map, base_addr, 48840b57cec5SDimitry Andric value_is_offset); 48850b57cec5SDimitry Andric } 48860b57cec5SDimitry Andric 48879dba64beSDimitry Andric llvm::Error ProcessGDBRemote::LoadModules() { 48880b57cec5SDimitry Andric using lldb_private::process_gdb_remote::ProcessGDBRemote; 48890b57cec5SDimitry Andric 48900b57cec5SDimitry Andric // request a list of loaded libraries from GDBServer 48919dba64beSDimitry Andric llvm::Expected<LoadedModuleInfoList> module_list = GetLoadedModuleList(); 48929dba64beSDimitry Andric if (!module_list) 48939dba64beSDimitry Andric return module_list.takeError(); 48940b57cec5SDimitry Andric 48950b57cec5SDimitry Andric // get a list of all the modules 48960b57cec5SDimitry Andric ModuleList new_modules; 48970b57cec5SDimitry Andric 48989dba64beSDimitry Andric for (LoadedModuleInfoList::LoadedModuleInfo &modInfo : module_list->m_list) { 48990b57cec5SDimitry Andric std::string mod_name; 49000b57cec5SDimitry Andric lldb::addr_t mod_base; 49010b57cec5SDimitry Andric lldb::addr_t link_map; 49020b57cec5SDimitry Andric bool mod_base_is_offset; 49030b57cec5SDimitry Andric 49040b57cec5SDimitry Andric bool valid = true; 49050b57cec5SDimitry Andric valid &= modInfo.get_name(mod_name); 49060b57cec5SDimitry Andric valid &= modInfo.get_base(mod_base); 49070b57cec5SDimitry Andric valid &= modInfo.get_base_is_offset(mod_base_is_offset); 49080b57cec5SDimitry Andric if (!valid) 49090b57cec5SDimitry Andric continue; 49100b57cec5SDimitry Andric 49110b57cec5SDimitry Andric if (!modInfo.get_link_map(link_map)) 49120b57cec5SDimitry Andric link_map = LLDB_INVALID_ADDRESS; 49130b57cec5SDimitry Andric 49140b57cec5SDimitry Andric FileSpec file(mod_name); 49150b57cec5SDimitry Andric FileSystem::Instance().Resolve(file); 49160b57cec5SDimitry Andric lldb::ModuleSP module_sp = 49170b57cec5SDimitry Andric LoadModuleAtAddress(file, link_map, mod_base, mod_base_is_offset); 49180b57cec5SDimitry Andric 49190b57cec5SDimitry Andric if (module_sp.get()) 49200b57cec5SDimitry Andric new_modules.Append(module_sp); 49210b57cec5SDimitry Andric } 49220b57cec5SDimitry Andric 49230b57cec5SDimitry Andric if (new_modules.GetSize() > 0) { 49240b57cec5SDimitry Andric ModuleList removed_modules; 49250b57cec5SDimitry Andric Target &target = GetTarget(); 49260b57cec5SDimitry Andric ModuleList &loaded_modules = m_process->GetTarget().GetImages(); 49270b57cec5SDimitry Andric 49280b57cec5SDimitry Andric for (size_t i = 0; i < loaded_modules.GetSize(); ++i) { 49290b57cec5SDimitry Andric const lldb::ModuleSP loaded_module = loaded_modules.GetModuleAtIndex(i); 49300b57cec5SDimitry Andric 49310b57cec5SDimitry Andric bool found = false; 49320b57cec5SDimitry Andric for (size_t j = 0; j < new_modules.GetSize(); ++j) { 49330b57cec5SDimitry Andric if (new_modules.GetModuleAtIndex(j).get() == loaded_module.get()) 49340b57cec5SDimitry Andric found = true; 49350b57cec5SDimitry Andric } 49360b57cec5SDimitry Andric 49370b57cec5SDimitry Andric // The main executable will never be included in libraries-svr4, don't 49380b57cec5SDimitry Andric // remove it 49390b57cec5SDimitry Andric if (!found && 49400b57cec5SDimitry Andric loaded_module.get() != target.GetExecutableModulePointer()) { 49410b57cec5SDimitry Andric removed_modules.Append(loaded_module); 49420b57cec5SDimitry Andric } 49430b57cec5SDimitry Andric } 49440b57cec5SDimitry Andric 49450b57cec5SDimitry Andric loaded_modules.Remove(removed_modules); 49460b57cec5SDimitry Andric m_process->GetTarget().ModulesDidUnload(removed_modules, false); 49470b57cec5SDimitry Andric 49480b57cec5SDimitry Andric new_modules.ForEach([&target](const lldb::ModuleSP module_sp) -> bool { 49490b57cec5SDimitry Andric lldb_private::ObjectFile *obj = module_sp->GetObjectFile(); 49500b57cec5SDimitry Andric if (!obj) 49510b57cec5SDimitry Andric return true; 49520b57cec5SDimitry Andric 49530b57cec5SDimitry Andric if (obj->GetType() != ObjectFile::Type::eTypeExecutable) 49540b57cec5SDimitry Andric return true; 49550b57cec5SDimitry Andric 49560b57cec5SDimitry Andric lldb::ModuleSP module_copy_sp = module_sp; 49570b57cec5SDimitry Andric target.SetExecutableModule(module_copy_sp, eLoadDependentsNo); 49580b57cec5SDimitry Andric return false; 49590b57cec5SDimitry Andric }); 49600b57cec5SDimitry Andric 49610b57cec5SDimitry Andric loaded_modules.AppendIfNeeded(new_modules); 49620b57cec5SDimitry Andric m_process->GetTarget().ModulesDidLoad(new_modules); 49630b57cec5SDimitry Andric } 49640b57cec5SDimitry Andric 49659dba64beSDimitry Andric return llvm::ErrorSuccess(); 49660b57cec5SDimitry Andric } 49670b57cec5SDimitry Andric 49680b57cec5SDimitry Andric Status ProcessGDBRemote::GetFileLoadAddress(const FileSpec &file, 49690b57cec5SDimitry Andric bool &is_loaded, 49700b57cec5SDimitry Andric lldb::addr_t &load_addr) { 49710b57cec5SDimitry Andric is_loaded = false; 49720b57cec5SDimitry Andric load_addr = LLDB_INVALID_ADDRESS; 49730b57cec5SDimitry Andric 49740b57cec5SDimitry Andric std::string file_path = file.GetPath(false); 49750b57cec5SDimitry Andric if (file_path.empty()) 49760b57cec5SDimitry Andric return Status("Empty file name specified"); 49770b57cec5SDimitry Andric 49780b57cec5SDimitry Andric StreamString packet; 49790b57cec5SDimitry Andric packet.PutCString("qFileLoadAddress:"); 49800b57cec5SDimitry Andric packet.PutStringAsRawHex8(file_path); 49810b57cec5SDimitry Andric 49820b57cec5SDimitry Andric StringExtractorGDBRemote response; 4983fe6060f1SDimitry Andric if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) != 49840b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult::Success) 49850b57cec5SDimitry Andric return Status("Sending qFileLoadAddress packet failed"); 49860b57cec5SDimitry Andric 49870b57cec5SDimitry Andric if (response.IsErrorResponse()) { 49880b57cec5SDimitry Andric if (response.GetError() == 1) { 49890b57cec5SDimitry Andric // The file is not loaded into the inferior 49900b57cec5SDimitry Andric is_loaded = false; 49910b57cec5SDimitry Andric load_addr = LLDB_INVALID_ADDRESS; 49920b57cec5SDimitry Andric return Status(); 49930b57cec5SDimitry Andric } 49940b57cec5SDimitry Andric 49950b57cec5SDimitry Andric return Status( 49960b57cec5SDimitry Andric "Fetching file load address from remote server returned an error"); 49970b57cec5SDimitry Andric } 49980b57cec5SDimitry Andric 49990b57cec5SDimitry Andric if (response.IsNormalResponse()) { 50000b57cec5SDimitry Andric is_loaded = true; 50010b57cec5SDimitry Andric load_addr = response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); 50020b57cec5SDimitry Andric return Status(); 50030b57cec5SDimitry Andric } 50040b57cec5SDimitry Andric 50050b57cec5SDimitry Andric return Status( 50060b57cec5SDimitry Andric "Unknown error happened during sending the load address packet"); 50070b57cec5SDimitry Andric } 50080b57cec5SDimitry Andric 50090b57cec5SDimitry Andric void ProcessGDBRemote::ModulesDidLoad(ModuleList &module_list) { 50100b57cec5SDimitry Andric // We must call the lldb_private::Process::ModulesDidLoad () first before we 50110b57cec5SDimitry Andric // do anything 50120b57cec5SDimitry Andric Process::ModulesDidLoad(module_list); 50130b57cec5SDimitry Andric 50140b57cec5SDimitry Andric // After loading shared libraries, we can ask our remote GDB server if it 50150b57cec5SDimitry Andric // needs any symbols. 50160b57cec5SDimitry Andric m_gdb_comm.ServeSymbolLookups(this); 50170b57cec5SDimitry Andric } 50180b57cec5SDimitry Andric 50190b57cec5SDimitry Andric void ProcessGDBRemote::HandleAsyncStdout(llvm::StringRef out) { 50200b57cec5SDimitry Andric AppendSTDOUT(out.data(), out.size()); 50210b57cec5SDimitry Andric } 50220b57cec5SDimitry Andric 50230b57cec5SDimitry Andric static const char *end_delimiter = "--end--;"; 50240b57cec5SDimitry Andric static const int end_delimiter_len = 8; 50250b57cec5SDimitry Andric 50260b57cec5SDimitry Andric void ProcessGDBRemote::HandleAsyncMisc(llvm::StringRef data) { 50270b57cec5SDimitry Andric std::string input = data.str(); // '1' to move beyond 'A' 50280b57cec5SDimitry Andric if (m_partial_profile_data.length() > 0) { 50290b57cec5SDimitry Andric m_partial_profile_data.append(input); 50300b57cec5SDimitry Andric input = m_partial_profile_data; 50310b57cec5SDimitry Andric m_partial_profile_data.clear(); 50320b57cec5SDimitry Andric } 50330b57cec5SDimitry Andric 50340b57cec5SDimitry Andric size_t found, pos = 0, len = input.length(); 50350b57cec5SDimitry Andric while ((found = input.find(end_delimiter, pos)) != std::string::npos) { 50360b57cec5SDimitry Andric StringExtractorGDBRemote profileDataExtractor( 50370b57cec5SDimitry Andric input.substr(pos, found).c_str()); 50380b57cec5SDimitry Andric std::string profile_data = 50390b57cec5SDimitry Andric HarmonizeThreadIdsForProfileData(profileDataExtractor); 50400b57cec5SDimitry Andric BroadcastAsyncProfileData(profile_data); 50410b57cec5SDimitry Andric 50420b57cec5SDimitry Andric pos = found + end_delimiter_len; 50430b57cec5SDimitry Andric } 50440b57cec5SDimitry Andric 50450b57cec5SDimitry Andric if (pos < len) { 50460b57cec5SDimitry Andric // Last incomplete chunk. 50470b57cec5SDimitry Andric m_partial_profile_data = input.substr(pos); 50480b57cec5SDimitry Andric } 50490b57cec5SDimitry Andric } 50500b57cec5SDimitry Andric 50510b57cec5SDimitry Andric std::string ProcessGDBRemote::HarmonizeThreadIdsForProfileData( 50520b57cec5SDimitry Andric StringExtractorGDBRemote &profileDataExtractor) { 50530b57cec5SDimitry Andric std::map<uint64_t, uint32_t> new_thread_id_to_used_usec_map; 50540b57cec5SDimitry Andric std::string output; 50550b57cec5SDimitry Andric llvm::raw_string_ostream output_stream(output); 50560b57cec5SDimitry Andric llvm::StringRef name, value; 50570b57cec5SDimitry Andric 50580b57cec5SDimitry Andric // Going to assuming thread_used_usec comes first, else bail out. 50590b57cec5SDimitry Andric while (profileDataExtractor.GetNameColonValue(name, value)) { 50600b57cec5SDimitry Andric if (name.compare("thread_used_id") == 0) { 50610b57cec5SDimitry Andric StringExtractor threadIDHexExtractor(value); 50620b57cec5SDimitry Andric uint64_t thread_id = threadIDHexExtractor.GetHexMaxU64(false, 0); 50630b57cec5SDimitry Andric 50640b57cec5SDimitry Andric bool has_used_usec = false; 50650b57cec5SDimitry Andric uint32_t curr_used_usec = 0; 50660b57cec5SDimitry Andric llvm::StringRef usec_name, usec_value; 50670b57cec5SDimitry Andric uint32_t input_file_pos = profileDataExtractor.GetFilePos(); 50680b57cec5SDimitry Andric if (profileDataExtractor.GetNameColonValue(usec_name, usec_value)) { 50690b57cec5SDimitry Andric if (usec_name.equals("thread_used_usec")) { 50700b57cec5SDimitry Andric has_used_usec = true; 50710b57cec5SDimitry Andric usec_value.getAsInteger(0, curr_used_usec); 50720b57cec5SDimitry Andric } else { 50730b57cec5SDimitry Andric // We didn't find what we want, it is probably an older version. Bail 50740b57cec5SDimitry Andric // out. 50750b57cec5SDimitry Andric profileDataExtractor.SetFilePos(input_file_pos); 50760b57cec5SDimitry Andric } 50770b57cec5SDimitry Andric } 50780b57cec5SDimitry Andric 50790b57cec5SDimitry Andric if (has_used_usec) { 50800b57cec5SDimitry Andric uint32_t prev_used_usec = 0; 50810b57cec5SDimitry Andric std::map<uint64_t, uint32_t>::iterator iterator = 50820b57cec5SDimitry Andric m_thread_id_to_used_usec_map.find(thread_id); 50830b57cec5SDimitry Andric if (iterator != m_thread_id_to_used_usec_map.end()) { 50840b57cec5SDimitry Andric prev_used_usec = m_thread_id_to_used_usec_map[thread_id]; 50850b57cec5SDimitry Andric } 50860b57cec5SDimitry Andric 50870b57cec5SDimitry Andric uint32_t real_used_usec = curr_used_usec - prev_used_usec; 50880b57cec5SDimitry Andric // A good first time record is one that runs for at least 0.25 sec 50890b57cec5SDimitry Andric bool good_first_time = 50900b57cec5SDimitry Andric (prev_used_usec == 0) && (real_used_usec > 250000); 50910b57cec5SDimitry Andric bool good_subsequent_time = 50920b57cec5SDimitry Andric (prev_used_usec > 0) && 50930b57cec5SDimitry Andric ((real_used_usec > 0) || (HasAssignedIndexIDToThread(thread_id))); 50940b57cec5SDimitry Andric 50950b57cec5SDimitry Andric if (good_first_time || good_subsequent_time) { 50960b57cec5SDimitry Andric // We try to avoid doing too many index id reservation, resulting in 50970b57cec5SDimitry Andric // fast increase of index ids. 50980b57cec5SDimitry Andric 50990b57cec5SDimitry Andric output_stream << name << ":"; 51000b57cec5SDimitry Andric int32_t index_id = AssignIndexIDToThread(thread_id); 51010b57cec5SDimitry Andric output_stream << index_id << ";"; 51020b57cec5SDimitry Andric 51030b57cec5SDimitry Andric output_stream << usec_name << ":" << usec_value << ";"; 51040b57cec5SDimitry Andric } else { 51050b57cec5SDimitry Andric // Skip past 'thread_used_name'. 51060b57cec5SDimitry Andric llvm::StringRef local_name, local_value; 51070b57cec5SDimitry Andric profileDataExtractor.GetNameColonValue(local_name, local_value); 51080b57cec5SDimitry Andric } 51090b57cec5SDimitry Andric 51100b57cec5SDimitry Andric // Store current time as previous time so that they can be compared 51110b57cec5SDimitry Andric // later. 51120b57cec5SDimitry Andric new_thread_id_to_used_usec_map[thread_id] = curr_used_usec; 51130b57cec5SDimitry Andric } else { 51140b57cec5SDimitry Andric // Bail out and use old string. 51150b57cec5SDimitry Andric output_stream << name << ":" << value << ";"; 51160b57cec5SDimitry Andric } 51170b57cec5SDimitry Andric } else { 51180b57cec5SDimitry Andric output_stream << name << ":" << value << ";"; 51190b57cec5SDimitry Andric } 51200b57cec5SDimitry Andric } 51210b57cec5SDimitry Andric output_stream << end_delimiter; 51220b57cec5SDimitry Andric m_thread_id_to_used_usec_map = new_thread_id_to_used_usec_map; 51230b57cec5SDimitry Andric 51240b57cec5SDimitry Andric return output_stream.str(); 51250b57cec5SDimitry Andric } 51260b57cec5SDimitry Andric 51270b57cec5SDimitry Andric void ProcessGDBRemote::HandleStopReply() { 51280b57cec5SDimitry Andric if (GetStopID() != 0) 51290b57cec5SDimitry Andric return; 51300b57cec5SDimitry Andric 51310b57cec5SDimitry Andric if (GetID() == LLDB_INVALID_PROCESS_ID) { 51320b57cec5SDimitry Andric lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID(); 51330b57cec5SDimitry Andric if (pid != LLDB_INVALID_PROCESS_ID) 51340b57cec5SDimitry Andric SetID(pid); 51350b57cec5SDimitry Andric } 51360b57cec5SDimitry Andric BuildDynamicRegisterInfo(true); 51370b57cec5SDimitry Andric } 51380b57cec5SDimitry Andric 5139349cc55cSDimitry Andric llvm::Expected<bool> ProcessGDBRemote::SaveCore(llvm::StringRef outfile) { 5140349cc55cSDimitry Andric if (!m_gdb_comm.GetSaveCoreSupported()) 5141349cc55cSDimitry Andric return false; 5142349cc55cSDimitry Andric 5143349cc55cSDimitry Andric StreamString packet; 5144349cc55cSDimitry Andric packet.PutCString("qSaveCore;path-hint:"); 5145349cc55cSDimitry Andric packet.PutStringAsRawHex8(outfile); 5146349cc55cSDimitry Andric 5147349cc55cSDimitry Andric StringExtractorGDBRemote response; 5148349cc55cSDimitry Andric if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) == 5149349cc55cSDimitry Andric GDBRemoteCommunication::PacketResult::Success) { 5150349cc55cSDimitry Andric // TODO: grab error message from the packet? StringExtractor seems to 5151349cc55cSDimitry Andric // be missing a method for that 5152349cc55cSDimitry Andric if (response.IsErrorResponse()) 5153349cc55cSDimitry Andric return llvm::createStringError( 5154349cc55cSDimitry Andric llvm::inconvertibleErrorCode(), 5155349cc55cSDimitry Andric llvm::formatv("qSaveCore returned an error")); 5156349cc55cSDimitry Andric 5157349cc55cSDimitry Andric std::string path; 5158349cc55cSDimitry Andric 5159349cc55cSDimitry Andric // process the response 5160349cc55cSDimitry Andric for (auto x : llvm::split(response.GetStringRef(), ';')) { 5161349cc55cSDimitry Andric if (x.consume_front("core-path:")) 5162349cc55cSDimitry Andric StringExtractor(x).GetHexByteString(path); 5163349cc55cSDimitry Andric } 5164349cc55cSDimitry Andric 5165349cc55cSDimitry Andric // verify that we've gotten what we need 5166349cc55cSDimitry Andric if (path.empty()) 5167349cc55cSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 5168349cc55cSDimitry Andric "qSaveCore returned no core path"); 5169349cc55cSDimitry Andric 5170349cc55cSDimitry Andric // now transfer the core file 5171349cc55cSDimitry Andric FileSpec remote_core{llvm::StringRef(path)}; 5172349cc55cSDimitry Andric Platform &platform = *GetTarget().GetPlatform(); 5173349cc55cSDimitry Andric Status error = platform.GetFile(remote_core, FileSpec(outfile)); 5174349cc55cSDimitry Andric 5175349cc55cSDimitry Andric if (platform.IsRemote()) { 5176349cc55cSDimitry Andric // NB: we unlink the file on error too 5177349cc55cSDimitry Andric platform.Unlink(remote_core); 5178349cc55cSDimitry Andric if (error.Fail()) 5179349cc55cSDimitry Andric return error.ToError(); 5180349cc55cSDimitry Andric } 5181349cc55cSDimitry Andric 5182349cc55cSDimitry Andric return true; 5183349cc55cSDimitry Andric } 5184349cc55cSDimitry Andric 5185349cc55cSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 5186349cc55cSDimitry Andric "Unable to send qSaveCore"); 5187349cc55cSDimitry Andric } 5188349cc55cSDimitry Andric 51890b57cec5SDimitry Andric static const char *const s_async_json_packet_prefix = "JSON-async:"; 51900b57cec5SDimitry Andric 51910b57cec5SDimitry Andric static StructuredData::ObjectSP 51920b57cec5SDimitry Andric ParseStructuredDataPacket(llvm::StringRef packet) { 51931fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 51940b57cec5SDimitry Andric 51950b57cec5SDimitry Andric if (!packet.consume_front(s_async_json_packet_prefix)) { 51960b57cec5SDimitry Andric if (log) { 51979dba64beSDimitry Andric LLDB_LOGF( 51989dba64beSDimitry Andric log, 51990b57cec5SDimitry Andric "GDBRemoteCommunicationClientBase::%s() received $J packet " 52000b57cec5SDimitry Andric "but was not a StructuredData packet: packet starts with " 52010b57cec5SDimitry Andric "%s", 52020b57cec5SDimitry Andric __FUNCTION__, 52030b57cec5SDimitry Andric packet.slice(0, strlen(s_async_json_packet_prefix)).str().c_str()); 52040b57cec5SDimitry Andric } 52050b57cec5SDimitry Andric return StructuredData::ObjectSP(); 52060b57cec5SDimitry Andric } 52070b57cec5SDimitry Andric 52080b57cec5SDimitry Andric // This is an asynchronous JSON packet, destined for a StructuredDataPlugin. 520906c3fb27SDimitry Andric StructuredData::ObjectSP json_sp = StructuredData::ParseJSON(packet); 52100b57cec5SDimitry Andric if (log) { 52110b57cec5SDimitry Andric if (json_sp) { 52120b57cec5SDimitry Andric StreamString json_str; 52139dba64beSDimitry Andric json_sp->Dump(json_str, true); 52140b57cec5SDimitry Andric json_str.Flush(); 52159dba64beSDimitry Andric LLDB_LOGF(log, 52169dba64beSDimitry Andric "ProcessGDBRemote::%s() " 52170b57cec5SDimitry Andric "received Async StructuredData packet: %s", 52180b57cec5SDimitry Andric __FUNCTION__, json_str.GetData()); 52190b57cec5SDimitry Andric } else { 52209dba64beSDimitry Andric LLDB_LOGF(log, 52219dba64beSDimitry Andric "ProcessGDBRemote::%s" 52220b57cec5SDimitry Andric "() received StructuredData packet:" 52230b57cec5SDimitry Andric " parse failure", 52240b57cec5SDimitry Andric __FUNCTION__); 52250b57cec5SDimitry Andric } 52260b57cec5SDimitry Andric } 52270b57cec5SDimitry Andric return json_sp; 52280b57cec5SDimitry Andric } 52290b57cec5SDimitry Andric 52300b57cec5SDimitry Andric void ProcessGDBRemote::HandleAsyncStructuredDataPacket(llvm::StringRef data) { 52310b57cec5SDimitry Andric auto structured_data_sp = ParseStructuredDataPacket(data); 52320b57cec5SDimitry Andric if (structured_data_sp) 52330b57cec5SDimitry Andric RouteAsyncStructuredData(structured_data_sp); 52340b57cec5SDimitry Andric } 52350b57cec5SDimitry Andric 52360b57cec5SDimitry Andric class CommandObjectProcessGDBRemoteSpeedTest : public CommandObjectParsed { 52370b57cec5SDimitry Andric public: 52380b57cec5SDimitry Andric CommandObjectProcessGDBRemoteSpeedTest(CommandInterpreter &interpreter) 52390b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process plugin packet speed-test", 52400b57cec5SDimitry Andric "Tests packet speeds of various sizes to determine " 52410b57cec5SDimitry Andric "the performance characteristics of the GDB remote " 52420b57cec5SDimitry Andric "connection. ", 52430b57cec5SDimitry Andric nullptr), 52440b57cec5SDimitry Andric m_option_group(), 52450b57cec5SDimitry Andric m_num_packets(LLDB_OPT_SET_1, false, "count", 'c', 0, eArgTypeCount, 52460b57cec5SDimitry Andric "The number of packets to send of each varying size " 52470b57cec5SDimitry Andric "(default is 1000).", 52480b57cec5SDimitry Andric 1000), 52490b57cec5SDimitry Andric m_max_send(LLDB_OPT_SET_1, false, "max-send", 's', 0, eArgTypeCount, 52500b57cec5SDimitry Andric "The maximum number of bytes to send in a packet. Sizes " 52510b57cec5SDimitry Andric "increase in powers of 2 while the size is less than or " 52520b57cec5SDimitry Andric "equal to this option value. (default 1024).", 52530b57cec5SDimitry Andric 1024), 52540b57cec5SDimitry Andric m_max_recv(LLDB_OPT_SET_1, false, "max-receive", 'r', 0, eArgTypeCount, 52550b57cec5SDimitry Andric "The maximum number of bytes to receive in a packet. Sizes " 52560b57cec5SDimitry Andric "increase in powers of 2 while the size is less than or " 52570b57cec5SDimitry Andric "equal to this option value. (default 1024).", 52580b57cec5SDimitry Andric 1024), 52590b57cec5SDimitry Andric m_json(LLDB_OPT_SET_1, false, "json", 'j', 52600b57cec5SDimitry Andric "Print the output as JSON data for easy parsing.", false, true) { 52610b57cec5SDimitry Andric m_option_group.Append(&m_num_packets, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 52620b57cec5SDimitry Andric m_option_group.Append(&m_max_send, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 52630b57cec5SDimitry Andric m_option_group.Append(&m_max_recv, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 52640b57cec5SDimitry Andric m_option_group.Append(&m_json, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 52650b57cec5SDimitry Andric m_option_group.Finalize(); 52660b57cec5SDimitry Andric } 52670b57cec5SDimitry Andric 5268fe6060f1SDimitry Andric ~CommandObjectProcessGDBRemoteSpeedTest() override = default; 52690b57cec5SDimitry Andric 52700b57cec5SDimitry Andric Options *GetOptions() override { return &m_option_group; } 52710b57cec5SDimitry Andric 5272*5f757f3fSDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override { 52730b57cec5SDimitry Andric const size_t argc = command.GetArgumentCount(); 52740b57cec5SDimitry Andric if (argc == 0) { 52750b57cec5SDimitry Andric ProcessGDBRemote *process = 52760b57cec5SDimitry Andric (ProcessGDBRemote *)m_interpreter.GetExecutionContext() 52770b57cec5SDimitry Andric .GetProcessPtr(); 52780b57cec5SDimitry Andric if (process) { 52790b57cec5SDimitry Andric StreamSP output_stream_sp( 52800b57cec5SDimitry Andric m_interpreter.GetDebugger().GetAsyncOutputStream()); 52810b57cec5SDimitry Andric result.SetImmediateOutputStream(output_stream_sp); 52820b57cec5SDimitry Andric 52830b57cec5SDimitry Andric const uint32_t num_packets = 52840b57cec5SDimitry Andric (uint32_t)m_num_packets.GetOptionValue().GetCurrentValue(); 52850b57cec5SDimitry Andric const uint64_t max_send = m_max_send.GetOptionValue().GetCurrentValue(); 52860b57cec5SDimitry Andric const uint64_t max_recv = m_max_recv.GetOptionValue().GetCurrentValue(); 52870b57cec5SDimitry Andric const bool json = m_json.GetOptionValue().GetCurrentValue(); 52880b57cec5SDimitry Andric const uint64_t k_recv_amount = 52890b57cec5SDimitry Andric 4 * 1024 * 1024; // Receive amount in bytes 52900b57cec5SDimitry Andric process->GetGDBRemote().TestPacketSpeed( 52910b57cec5SDimitry Andric num_packets, max_send, max_recv, k_recv_amount, json, 52920b57cec5SDimitry Andric output_stream_sp ? *output_stream_sp : result.GetOutputStream()); 52930b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 5294*5f757f3fSDimitry Andric return; 52950b57cec5SDimitry Andric } 52960b57cec5SDimitry Andric } else { 52970b57cec5SDimitry Andric result.AppendErrorWithFormat("'%s' takes no arguments", 52980b57cec5SDimitry Andric m_cmd_name.c_str()); 52990b57cec5SDimitry Andric } 53000b57cec5SDimitry Andric result.SetStatus(eReturnStatusFailed); 53010b57cec5SDimitry Andric } 53020b57cec5SDimitry Andric 53030b57cec5SDimitry Andric protected: 53040b57cec5SDimitry Andric OptionGroupOptions m_option_group; 53050b57cec5SDimitry Andric OptionGroupUInt64 m_num_packets; 53060b57cec5SDimitry Andric OptionGroupUInt64 m_max_send; 53070b57cec5SDimitry Andric OptionGroupUInt64 m_max_recv; 53080b57cec5SDimitry Andric OptionGroupBoolean m_json; 53090b57cec5SDimitry Andric }; 53100b57cec5SDimitry Andric 53110b57cec5SDimitry Andric class CommandObjectProcessGDBRemotePacketHistory : public CommandObjectParsed { 53120b57cec5SDimitry Andric private: 53130b57cec5SDimitry Andric public: 53140b57cec5SDimitry Andric CommandObjectProcessGDBRemotePacketHistory(CommandInterpreter &interpreter) 53150b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process plugin packet history", 53160b57cec5SDimitry Andric "Dumps the packet history buffer. ", nullptr) {} 53170b57cec5SDimitry Andric 5318fe6060f1SDimitry Andric ~CommandObjectProcessGDBRemotePacketHistory() override = default; 53190b57cec5SDimitry Andric 5320*5f757f3fSDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override { 53210b57cec5SDimitry Andric ProcessGDBRemote *process = 532281ad6265SDimitry Andric (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr(); 53230b57cec5SDimitry Andric if (process) { 532406c3fb27SDimitry Andric process->DumpPluginHistory(result.GetOutputStream()); 53250b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 5326*5f757f3fSDimitry Andric return; 53270b57cec5SDimitry Andric } 53280b57cec5SDimitry Andric result.SetStatus(eReturnStatusFailed); 53290b57cec5SDimitry Andric } 53300b57cec5SDimitry Andric }; 53310b57cec5SDimitry Andric 53320b57cec5SDimitry Andric class CommandObjectProcessGDBRemotePacketXferSize : public CommandObjectParsed { 53330b57cec5SDimitry Andric private: 53340b57cec5SDimitry Andric public: 53350b57cec5SDimitry Andric CommandObjectProcessGDBRemotePacketXferSize(CommandInterpreter &interpreter) 53360b57cec5SDimitry Andric : CommandObjectParsed( 53370b57cec5SDimitry Andric interpreter, "process plugin packet xfer-size", 53380b57cec5SDimitry Andric "Maximum size that lldb will try to read/write one one chunk.", 533981ad6265SDimitry Andric nullptr) { 534081ad6265SDimitry Andric CommandArgumentData max_arg{eArgTypeUnsignedInteger, eArgRepeatPlain}; 534181ad6265SDimitry Andric m_arguments.push_back({max_arg}); 534281ad6265SDimitry Andric } 53430b57cec5SDimitry Andric 5344fe6060f1SDimitry Andric ~CommandObjectProcessGDBRemotePacketXferSize() override = default; 53450b57cec5SDimitry Andric 5346*5f757f3fSDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override { 53470b57cec5SDimitry Andric const size_t argc = command.GetArgumentCount(); 53480b57cec5SDimitry Andric if (argc == 0) { 53490b57cec5SDimitry Andric result.AppendErrorWithFormat("'%s' takes an argument to specify the max " 53500b57cec5SDimitry Andric "amount to be transferred when " 53510b57cec5SDimitry Andric "reading/writing", 53520b57cec5SDimitry Andric m_cmd_name.c_str()); 5353*5f757f3fSDimitry Andric return; 53540b57cec5SDimitry Andric } 53550b57cec5SDimitry Andric 53560b57cec5SDimitry Andric ProcessGDBRemote *process = 53570b57cec5SDimitry Andric (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr(); 53580b57cec5SDimitry Andric if (process) { 53590b57cec5SDimitry Andric const char *packet_size = command.GetArgumentAtIndex(0); 53600b57cec5SDimitry Andric errno = 0; 53610b57cec5SDimitry Andric uint64_t user_specified_max = strtoul(packet_size, nullptr, 10); 53620b57cec5SDimitry Andric if (errno == 0 && user_specified_max != 0) { 53630b57cec5SDimitry Andric process->SetUserSpecifiedMaxMemoryTransferSize(user_specified_max); 53640b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 5365*5f757f3fSDimitry Andric return; 53660b57cec5SDimitry Andric } 53670b57cec5SDimitry Andric } 53680b57cec5SDimitry Andric result.SetStatus(eReturnStatusFailed); 53690b57cec5SDimitry Andric } 53700b57cec5SDimitry Andric }; 53710b57cec5SDimitry Andric 53720b57cec5SDimitry Andric class CommandObjectProcessGDBRemotePacketSend : public CommandObjectParsed { 53730b57cec5SDimitry Andric private: 53740b57cec5SDimitry Andric public: 53750b57cec5SDimitry Andric CommandObjectProcessGDBRemotePacketSend(CommandInterpreter &interpreter) 53760b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process plugin packet send", 53770b57cec5SDimitry Andric "Send a custom packet through the GDB remote " 53780b57cec5SDimitry Andric "protocol and print the answer. " 53790b57cec5SDimitry Andric "The packet header and footer will automatically " 53800b57cec5SDimitry Andric "be added to the packet prior to sending and " 53810b57cec5SDimitry Andric "stripped from the result.", 538281ad6265SDimitry Andric nullptr) { 538381ad6265SDimitry Andric CommandArgumentData packet_arg{eArgTypeNone, eArgRepeatStar}; 538481ad6265SDimitry Andric m_arguments.push_back({packet_arg}); 538581ad6265SDimitry Andric } 53860b57cec5SDimitry Andric 5387fe6060f1SDimitry Andric ~CommandObjectProcessGDBRemotePacketSend() override = default; 53880b57cec5SDimitry Andric 5389*5f757f3fSDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override { 53900b57cec5SDimitry Andric const size_t argc = command.GetArgumentCount(); 53910b57cec5SDimitry Andric if (argc == 0) { 53920b57cec5SDimitry Andric result.AppendErrorWithFormat( 53930b57cec5SDimitry Andric "'%s' takes a one or more packet content arguments", 53940b57cec5SDimitry Andric m_cmd_name.c_str()); 5395*5f757f3fSDimitry Andric return; 53960b57cec5SDimitry Andric } 53970b57cec5SDimitry Andric 53980b57cec5SDimitry Andric ProcessGDBRemote *process = 53990b57cec5SDimitry Andric (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr(); 54000b57cec5SDimitry Andric if (process) { 54010b57cec5SDimitry Andric for (size_t i = 0; i < argc; ++i) { 54020b57cec5SDimitry Andric const char *packet_cstr = command.GetArgumentAtIndex(0); 54030b57cec5SDimitry Andric StringExtractorGDBRemote response; 54040b57cec5SDimitry Andric process->GetGDBRemote().SendPacketAndWaitForResponse( 5405fe6060f1SDimitry Andric packet_cstr, response, process->GetInterruptTimeout()); 54060b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 54070b57cec5SDimitry Andric Stream &output_strm = result.GetOutputStream(); 54080b57cec5SDimitry Andric output_strm.Printf(" packet: %s\n", packet_cstr); 54095ffd83dbSDimitry Andric std::string response_str = std::string(response.GetStringRef()); 54100b57cec5SDimitry Andric 54110b57cec5SDimitry Andric if (strstr(packet_cstr, "qGetProfileData") != nullptr) { 54120b57cec5SDimitry Andric response_str = process->HarmonizeThreadIdsForProfileData(response); 54130b57cec5SDimitry Andric } 54140b57cec5SDimitry Andric 54150b57cec5SDimitry Andric if (response_str.empty()) 54160b57cec5SDimitry Andric output_strm.PutCString("response: \nerror: UNIMPLEMENTED\n"); 54170b57cec5SDimitry Andric else 54189dba64beSDimitry Andric output_strm.Printf("response: %s\n", response.GetStringRef().data()); 54190b57cec5SDimitry Andric } 54200b57cec5SDimitry Andric } 54210b57cec5SDimitry Andric } 54220b57cec5SDimitry Andric }; 54230b57cec5SDimitry Andric 54240b57cec5SDimitry Andric class CommandObjectProcessGDBRemotePacketMonitor : public CommandObjectRaw { 54250b57cec5SDimitry Andric private: 54260b57cec5SDimitry Andric public: 54270b57cec5SDimitry Andric CommandObjectProcessGDBRemotePacketMonitor(CommandInterpreter &interpreter) 54280b57cec5SDimitry Andric : CommandObjectRaw(interpreter, "process plugin packet monitor", 54290b57cec5SDimitry Andric "Send a qRcmd packet through the GDB remote protocol " 54300b57cec5SDimitry Andric "and print the response." 54310b57cec5SDimitry Andric "The argument passed to this command will be hex " 54320b57cec5SDimitry Andric "encoded into a valid 'qRcmd' packet, sent and the " 54330b57cec5SDimitry Andric "response will be printed.") {} 54340b57cec5SDimitry Andric 5435fe6060f1SDimitry Andric ~CommandObjectProcessGDBRemotePacketMonitor() override = default; 54360b57cec5SDimitry Andric 5437*5f757f3fSDimitry Andric void DoExecute(llvm::StringRef command, 54380b57cec5SDimitry Andric CommandReturnObject &result) override { 54390b57cec5SDimitry Andric if (command.empty()) { 54400b57cec5SDimitry Andric result.AppendErrorWithFormat("'%s' takes a command string argument", 54410b57cec5SDimitry Andric m_cmd_name.c_str()); 5442*5f757f3fSDimitry Andric return; 54430b57cec5SDimitry Andric } 54440b57cec5SDimitry Andric 54450b57cec5SDimitry Andric ProcessGDBRemote *process = 54460b57cec5SDimitry Andric (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr(); 54470b57cec5SDimitry Andric if (process) { 54480b57cec5SDimitry Andric StreamString packet; 54490b57cec5SDimitry Andric packet.PutCString("qRcmd,"); 54500b57cec5SDimitry Andric packet.PutBytesAsRawHex8(command.data(), command.size()); 54510b57cec5SDimitry Andric 54520b57cec5SDimitry Andric StringExtractorGDBRemote response; 54530b57cec5SDimitry Andric Stream &output_strm = result.GetOutputStream(); 54540b57cec5SDimitry Andric process->GetGDBRemote().SendPacketAndReceiveResponseWithOutputSupport( 5455fe6060f1SDimitry Andric packet.GetString(), response, process->GetInterruptTimeout(), 54560b57cec5SDimitry Andric [&output_strm](llvm::StringRef output) { output_strm << output; }); 54570b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 54580b57cec5SDimitry Andric output_strm.Printf(" packet: %s\n", packet.GetData()); 54595ffd83dbSDimitry Andric const std::string &response_str = std::string(response.GetStringRef()); 54600b57cec5SDimitry Andric 54610b57cec5SDimitry Andric if (response_str.empty()) 54620b57cec5SDimitry Andric output_strm.PutCString("response: \nerror: UNIMPLEMENTED\n"); 54630b57cec5SDimitry Andric else 54649dba64beSDimitry Andric output_strm.Printf("response: %s\n", response.GetStringRef().data()); 54650b57cec5SDimitry Andric } 54660b57cec5SDimitry Andric } 54670b57cec5SDimitry Andric }; 54680b57cec5SDimitry Andric 54690b57cec5SDimitry Andric class CommandObjectProcessGDBRemotePacket : public CommandObjectMultiword { 54700b57cec5SDimitry Andric private: 54710b57cec5SDimitry Andric public: 54720b57cec5SDimitry Andric CommandObjectProcessGDBRemotePacket(CommandInterpreter &interpreter) 54730b57cec5SDimitry Andric : CommandObjectMultiword(interpreter, "process plugin packet", 54740b57cec5SDimitry Andric "Commands that deal with GDB remote packets.", 54750b57cec5SDimitry Andric nullptr) { 54760b57cec5SDimitry Andric LoadSubCommand( 54770b57cec5SDimitry Andric "history", 54780b57cec5SDimitry Andric CommandObjectSP( 54790b57cec5SDimitry Andric new CommandObjectProcessGDBRemotePacketHistory(interpreter))); 54800b57cec5SDimitry Andric LoadSubCommand( 54810b57cec5SDimitry Andric "send", CommandObjectSP( 54820b57cec5SDimitry Andric new CommandObjectProcessGDBRemotePacketSend(interpreter))); 54830b57cec5SDimitry Andric LoadSubCommand( 54840b57cec5SDimitry Andric "monitor", 54850b57cec5SDimitry Andric CommandObjectSP( 54860b57cec5SDimitry Andric new CommandObjectProcessGDBRemotePacketMonitor(interpreter))); 54870b57cec5SDimitry Andric LoadSubCommand( 54880b57cec5SDimitry Andric "xfer-size", 54890b57cec5SDimitry Andric CommandObjectSP( 54900b57cec5SDimitry Andric new CommandObjectProcessGDBRemotePacketXferSize(interpreter))); 54910b57cec5SDimitry Andric LoadSubCommand("speed-test", 54920b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessGDBRemoteSpeedTest( 54930b57cec5SDimitry Andric interpreter))); 54940b57cec5SDimitry Andric } 54950b57cec5SDimitry Andric 5496fe6060f1SDimitry Andric ~CommandObjectProcessGDBRemotePacket() override = default; 54970b57cec5SDimitry Andric }; 54980b57cec5SDimitry Andric 54990b57cec5SDimitry Andric class CommandObjectMultiwordProcessGDBRemote : public CommandObjectMultiword { 55000b57cec5SDimitry Andric public: 55010b57cec5SDimitry Andric CommandObjectMultiwordProcessGDBRemote(CommandInterpreter &interpreter) 55020b57cec5SDimitry Andric : CommandObjectMultiword( 55030b57cec5SDimitry Andric interpreter, "process plugin", 55040b57cec5SDimitry Andric "Commands for operating on a ProcessGDBRemote process.", 55050b57cec5SDimitry Andric "process plugin <subcommand> [<subcommand-options>]") { 55060b57cec5SDimitry Andric LoadSubCommand( 55070b57cec5SDimitry Andric "packet", 55080b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessGDBRemotePacket(interpreter))); 55090b57cec5SDimitry Andric } 55100b57cec5SDimitry Andric 5511fe6060f1SDimitry Andric ~CommandObjectMultiwordProcessGDBRemote() override = default; 55120b57cec5SDimitry Andric }; 55130b57cec5SDimitry Andric 55140b57cec5SDimitry Andric CommandObject *ProcessGDBRemote::GetPluginCommandObject() { 55150b57cec5SDimitry Andric if (!m_command_sp) 55160b57cec5SDimitry Andric m_command_sp = std::make_shared<CommandObjectMultiwordProcessGDBRemote>( 55170b57cec5SDimitry Andric GetTarget().GetDebugger().GetCommandInterpreter()); 55180b57cec5SDimitry Andric return m_command_sp.get(); 55190b57cec5SDimitry Andric } 5520349cc55cSDimitry Andric 5521349cc55cSDimitry Andric void ProcessGDBRemote::DidForkSwitchSoftwareBreakpoints(bool enable) { 5522349cc55cSDimitry Andric GetBreakpointSiteList().ForEach([this, enable](BreakpointSite *bp_site) { 5523349cc55cSDimitry Andric if (bp_site->IsEnabled() && 5524349cc55cSDimitry Andric (bp_site->GetType() == BreakpointSite::eSoftware || 5525349cc55cSDimitry Andric bp_site->GetType() == BreakpointSite::eExternal)) { 5526349cc55cSDimitry Andric m_gdb_comm.SendGDBStoppointTypePacket( 5527349cc55cSDimitry Andric eBreakpointSoftware, enable, bp_site->GetLoadAddress(), 5528349cc55cSDimitry Andric GetSoftwareBreakpointTrapOpcode(bp_site), GetInterruptTimeout()); 5529349cc55cSDimitry Andric } 5530349cc55cSDimitry Andric }); 5531349cc55cSDimitry Andric } 5532349cc55cSDimitry Andric 5533349cc55cSDimitry Andric void ProcessGDBRemote::DidForkSwitchHardwareTraps(bool enable) { 5534349cc55cSDimitry Andric if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) { 5535349cc55cSDimitry Andric GetBreakpointSiteList().ForEach([this, enable](BreakpointSite *bp_site) { 5536349cc55cSDimitry Andric if (bp_site->IsEnabled() && 5537349cc55cSDimitry Andric bp_site->GetType() == BreakpointSite::eHardware) { 5538349cc55cSDimitry Andric m_gdb_comm.SendGDBStoppointTypePacket( 5539349cc55cSDimitry Andric eBreakpointHardware, enable, bp_site->GetLoadAddress(), 5540349cc55cSDimitry Andric GetSoftwareBreakpointTrapOpcode(bp_site), GetInterruptTimeout()); 5541349cc55cSDimitry Andric } 5542349cc55cSDimitry Andric }); 5543349cc55cSDimitry Andric } 5544349cc55cSDimitry Andric 5545*5f757f3fSDimitry Andric for (const auto &wp_res_sp : m_watchpoint_resource_list.Sites()) { 5546*5f757f3fSDimitry Andric addr_t addr = wp_res_sp->GetLoadAddress(); 5547*5f757f3fSDimitry Andric size_t size = wp_res_sp->GetByteSize(); 5548*5f757f3fSDimitry Andric GDBStoppointType type = GetGDBStoppointType(wp_res_sp); 5549*5f757f3fSDimitry Andric m_gdb_comm.SendGDBStoppointTypePacket(type, enable, addr, size, 5550349cc55cSDimitry Andric GetInterruptTimeout()); 5551349cc55cSDimitry Andric } 5552349cc55cSDimitry Andric } 5553349cc55cSDimitry Andric 5554349cc55cSDimitry Andric void ProcessGDBRemote::DidFork(lldb::pid_t child_pid, lldb::tid_t child_tid) { 55551fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 5556349cc55cSDimitry Andric 5557349cc55cSDimitry Andric lldb::pid_t parent_pid = m_gdb_comm.GetCurrentProcessID(); 5558349cc55cSDimitry Andric // Any valid TID will suffice, thread-relevant actions will set a proper TID 5559349cc55cSDimitry Andric // anyway. 5560349cc55cSDimitry Andric lldb::tid_t parent_tid = m_thread_ids.front(); 5561349cc55cSDimitry Andric 5562349cc55cSDimitry Andric lldb::pid_t follow_pid, detach_pid; 5563349cc55cSDimitry Andric lldb::tid_t follow_tid, detach_tid; 5564349cc55cSDimitry Andric 5565349cc55cSDimitry Andric switch (GetFollowForkMode()) { 5566349cc55cSDimitry Andric case eFollowParent: 5567349cc55cSDimitry Andric follow_pid = parent_pid; 5568349cc55cSDimitry Andric follow_tid = parent_tid; 5569349cc55cSDimitry Andric detach_pid = child_pid; 5570349cc55cSDimitry Andric detach_tid = child_tid; 5571349cc55cSDimitry Andric break; 5572349cc55cSDimitry Andric case eFollowChild: 5573349cc55cSDimitry Andric follow_pid = child_pid; 5574349cc55cSDimitry Andric follow_tid = child_tid; 5575349cc55cSDimitry Andric detach_pid = parent_pid; 5576349cc55cSDimitry Andric detach_tid = parent_tid; 5577349cc55cSDimitry Andric break; 5578349cc55cSDimitry Andric } 5579349cc55cSDimitry Andric 5580349cc55cSDimitry Andric // Switch to the process that is going to be detached. 5581349cc55cSDimitry Andric if (!m_gdb_comm.SetCurrentThread(detach_tid, detach_pid)) { 5582349cc55cSDimitry Andric LLDB_LOG(log, "ProcessGDBRemote::DidFork() unable to set pid/tid"); 5583349cc55cSDimitry Andric return; 5584349cc55cSDimitry Andric } 5585349cc55cSDimitry Andric 5586349cc55cSDimitry Andric // Disable all software breakpoints in the forked process. 5587349cc55cSDimitry Andric if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware)) 5588349cc55cSDimitry Andric DidForkSwitchSoftwareBreakpoints(false); 5589349cc55cSDimitry Andric 5590349cc55cSDimitry Andric // Remove hardware breakpoints / watchpoints from parent process if we're 5591349cc55cSDimitry Andric // following child. 5592349cc55cSDimitry Andric if (GetFollowForkMode() == eFollowChild) 5593349cc55cSDimitry Andric DidForkSwitchHardwareTraps(false); 5594349cc55cSDimitry Andric 5595349cc55cSDimitry Andric // Switch to the process that is going to be followed 5596349cc55cSDimitry Andric if (!m_gdb_comm.SetCurrentThread(follow_tid, follow_pid) || 5597349cc55cSDimitry Andric !m_gdb_comm.SetCurrentThreadForRun(follow_tid, follow_pid)) { 5598349cc55cSDimitry Andric LLDB_LOG(log, "ProcessGDBRemote::DidFork() unable to reset pid/tid"); 5599349cc55cSDimitry Andric return; 5600349cc55cSDimitry Andric } 5601349cc55cSDimitry Andric 5602349cc55cSDimitry Andric LLDB_LOG(log, "Detaching process {0}", detach_pid); 5603349cc55cSDimitry Andric Status error = m_gdb_comm.Detach(false, detach_pid); 5604349cc55cSDimitry Andric if (error.Fail()) { 5605349cc55cSDimitry Andric LLDB_LOG(log, "ProcessGDBRemote::DidFork() detach packet send failed: {0}", 5606349cc55cSDimitry Andric error.AsCString() ? error.AsCString() : "<unknown error>"); 5607349cc55cSDimitry Andric return; 5608349cc55cSDimitry Andric } 5609349cc55cSDimitry Andric 5610349cc55cSDimitry Andric // Hardware breakpoints/watchpoints are not inherited implicitly, 5611349cc55cSDimitry Andric // so we need to readd them if we're following child. 5612fcaf7f86SDimitry Andric if (GetFollowForkMode() == eFollowChild) { 5613349cc55cSDimitry Andric DidForkSwitchHardwareTraps(true); 5614fcaf7f86SDimitry Andric // Update our PID 5615fcaf7f86SDimitry Andric SetID(child_pid); 5616fcaf7f86SDimitry Andric } 5617349cc55cSDimitry Andric } 5618349cc55cSDimitry Andric 5619349cc55cSDimitry Andric void ProcessGDBRemote::DidVFork(lldb::pid_t child_pid, lldb::tid_t child_tid) { 56201fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 5621349cc55cSDimitry Andric 5622349cc55cSDimitry Andric assert(!m_vfork_in_progress); 5623349cc55cSDimitry Andric m_vfork_in_progress = true; 5624349cc55cSDimitry Andric 5625349cc55cSDimitry Andric // Disable all software breakpoints for the duration of vfork. 5626349cc55cSDimitry Andric if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware)) 5627349cc55cSDimitry Andric DidForkSwitchSoftwareBreakpoints(false); 5628349cc55cSDimitry Andric 5629349cc55cSDimitry Andric lldb::pid_t detach_pid; 5630349cc55cSDimitry Andric lldb::tid_t detach_tid; 5631349cc55cSDimitry Andric 5632349cc55cSDimitry Andric switch (GetFollowForkMode()) { 5633349cc55cSDimitry Andric case eFollowParent: 5634349cc55cSDimitry Andric detach_pid = child_pid; 5635349cc55cSDimitry Andric detach_tid = child_tid; 5636349cc55cSDimitry Andric break; 5637349cc55cSDimitry Andric case eFollowChild: 5638349cc55cSDimitry Andric detach_pid = m_gdb_comm.GetCurrentProcessID(); 5639349cc55cSDimitry Andric // Any valid TID will suffice, thread-relevant actions will set a proper TID 5640349cc55cSDimitry Andric // anyway. 5641349cc55cSDimitry Andric detach_tid = m_thread_ids.front(); 5642349cc55cSDimitry Andric 5643349cc55cSDimitry Andric // Switch to the parent process before detaching it. 5644349cc55cSDimitry Andric if (!m_gdb_comm.SetCurrentThread(detach_tid, detach_pid)) { 5645349cc55cSDimitry Andric LLDB_LOG(log, "ProcessGDBRemote::DidFork() unable to set pid/tid"); 5646349cc55cSDimitry Andric return; 5647349cc55cSDimitry Andric } 5648349cc55cSDimitry Andric 5649349cc55cSDimitry Andric // Remove hardware breakpoints / watchpoints from the parent process. 5650349cc55cSDimitry Andric DidForkSwitchHardwareTraps(false); 5651349cc55cSDimitry Andric 5652349cc55cSDimitry Andric // Switch to the child process. 5653349cc55cSDimitry Andric if (!m_gdb_comm.SetCurrentThread(child_tid, child_pid) || 5654349cc55cSDimitry Andric !m_gdb_comm.SetCurrentThreadForRun(child_tid, child_pid)) { 5655349cc55cSDimitry Andric LLDB_LOG(log, "ProcessGDBRemote::DidFork() unable to reset pid/tid"); 5656349cc55cSDimitry Andric return; 5657349cc55cSDimitry Andric } 5658349cc55cSDimitry Andric break; 5659349cc55cSDimitry Andric } 5660349cc55cSDimitry Andric 5661349cc55cSDimitry Andric LLDB_LOG(log, "Detaching process {0}", detach_pid); 5662349cc55cSDimitry Andric Status error = m_gdb_comm.Detach(false, detach_pid); 5663349cc55cSDimitry Andric if (error.Fail()) { 5664349cc55cSDimitry Andric LLDB_LOG(log, 5665349cc55cSDimitry Andric "ProcessGDBRemote::DidFork() detach packet send failed: {0}", 5666349cc55cSDimitry Andric error.AsCString() ? error.AsCString() : "<unknown error>"); 5667349cc55cSDimitry Andric return; 5668349cc55cSDimitry Andric } 5669fcaf7f86SDimitry Andric 5670fcaf7f86SDimitry Andric if (GetFollowForkMode() == eFollowChild) { 5671fcaf7f86SDimitry Andric // Update our PID 5672fcaf7f86SDimitry Andric SetID(child_pid); 5673fcaf7f86SDimitry Andric } 5674349cc55cSDimitry Andric } 5675349cc55cSDimitry Andric 5676349cc55cSDimitry Andric void ProcessGDBRemote::DidVForkDone() { 5677349cc55cSDimitry Andric assert(m_vfork_in_progress); 5678349cc55cSDimitry Andric m_vfork_in_progress = false; 5679349cc55cSDimitry Andric 5680349cc55cSDimitry Andric // Reenable all software breakpoints that were enabled before vfork. 5681349cc55cSDimitry Andric if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware)) 5682349cc55cSDimitry Andric DidForkSwitchSoftwareBreakpoints(true); 5683349cc55cSDimitry Andric } 5684349cc55cSDimitry Andric 5685349cc55cSDimitry Andric void ProcessGDBRemote::DidExec() { 5686349cc55cSDimitry Andric // If we are following children, vfork is finished by exec (rather than 5687349cc55cSDimitry Andric // vforkdone that is submitted for parent). 5688349cc55cSDimitry Andric if (GetFollowForkMode() == eFollowChild) 5689349cc55cSDimitry Andric m_vfork_in_progress = false; 5690349cc55cSDimitry Andric Process::DidExec(); 5691349cc55cSDimitry Andric } 5692