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*0fca6ea1SDimitry Andric #include "lldb/Breakpoint/WatchpointAlgorithms.h" 285f757f3fSDimitry Andric #include "lldb/Breakpoint/WatchpointResource.h" 290b57cec5SDimitry Andric #include "lldb/Core/Debugger.h" 300b57cec5SDimitry Andric #include "lldb/Core/Module.h" 310b57cec5SDimitry Andric #include "lldb/Core/ModuleSpec.h" 320b57cec5SDimitry Andric #include "lldb/Core/PluginManager.h" 330b57cec5SDimitry Andric #include "lldb/Core/Value.h" 340b57cec5SDimitry Andric #include "lldb/DataFormatters/FormatManager.h" 350b57cec5SDimitry Andric #include "lldb/Host/ConnectionFileDescriptor.h" 360b57cec5SDimitry Andric #include "lldb/Host/FileSystem.h" 370b57cec5SDimitry Andric #include "lldb/Host/HostThread.h" 380b57cec5SDimitry Andric #include "lldb/Host/PosixApi.h" 390b57cec5SDimitry Andric #include "lldb/Host/PseudoTerminal.h" 405f757f3fSDimitry Andric #include "lldb/Host/StreamFile.h" 410b57cec5SDimitry Andric #include "lldb/Host/ThreadLauncher.h" 420b57cec5SDimitry Andric #include "lldb/Host/XML.h" 430b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h" 440b57cec5SDimitry Andric #include "lldb/Interpreter/CommandObject.h" 450b57cec5SDimitry Andric #include "lldb/Interpreter/CommandObjectMultiword.h" 460b57cec5SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h" 470b57cec5SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h" 480b57cec5SDimitry Andric #include "lldb/Interpreter/OptionGroupBoolean.h" 490b57cec5SDimitry Andric #include "lldb/Interpreter/OptionGroupUInt64.h" 500b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValueProperties.h" 510b57cec5SDimitry Andric #include "lldb/Interpreter/Options.h" 520b57cec5SDimitry Andric #include "lldb/Interpreter/Property.h" 530b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h" 540b57cec5SDimitry Andric #include "lldb/Target/ABI.h" 550b57cec5SDimitry Andric #include "lldb/Target/DynamicLoader.h" 560b57cec5SDimitry Andric #include "lldb/Target/MemoryRegionInfo.h" 5706c3fb27SDimitry Andric #include "lldb/Target/RegisterFlags.h" 580b57cec5SDimitry Andric #include "lldb/Target/SystemRuntime.h" 590b57cec5SDimitry Andric #include "lldb/Target/Target.h" 600b57cec5SDimitry Andric #include "lldb/Target/TargetList.h" 610b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanCallFunction.h" 620b57cec5SDimitry Andric #include "lldb/Utility/Args.h" 630b57cec5SDimitry Andric #include "lldb/Utility/FileSpec.h" 6481ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h" 650b57cec5SDimitry Andric #include "lldb/Utility/State.h" 660b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h" 670b57cec5SDimitry Andric #include "lldb/Utility/Timer.h" 6804eeddc0SDimitry Andric #include <algorithm> 6904eeddc0SDimitry Andric #include <csignal> 7004eeddc0SDimitry Andric #include <map> 7104eeddc0SDimitry Andric #include <memory> 7204eeddc0SDimitry Andric #include <mutex> 73bdd1243dSDimitry Andric #include <optional> 7404eeddc0SDimitry Andric #include <sstream> 7504eeddc0SDimitry Andric #include <thread> 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric #include "GDBRemoteRegisterContext.h" 7804eeddc0SDimitry Andric #include "GDBRemoteRegisterFallback.h" 790b57cec5SDimitry Andric #include "Plugins/Process/Utility/GDBRemoteSignals.h" 800b57cec5SDimitry Andric #include "Plugins/Process/Utility/InferiorCallPOSIX.h" 810b57cec5SDimitry Andric #include "Plugins/Process/Utility/StopInfoMachException.h" 820b57cec5SDimitry Andric #include "ProcessGDBRemote.h" 830b57cec5SDimitry Andric #include "ProcessGDBRemoteLog.h" 840b57cec5SDimitry Andric #include "ThreadGDBRemote.h" 850b57cec5SDimitry Andric #include "lldb/Host/Host.h" 860b57cec5SDimitry Andric #include "lldb/Utility/StringExtractorGDBRemote.h" 870b57cec5SDimitry Andric 889dba64beSDimitry Andric #include "llvm/ADT/ScopeExit.h" 8906c3fb27SDimitry Andric #include "llvm/ADT/StringMap.h" 900b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h" 91bdd1243dSDimitry Andric #include "llvm/Support/FormatAdapters.h" 920b57cec5SDimitry Andric #include "llvm/Support/Threading.h" 930b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric #define DEBUGSERVER_BASENAME "debugserver" 960b57cec5SDimitry Andric using namespace lldb; 970b57cec5SDimitry Andric using namespace lldb_private; 980b57cec5SDimitry Andric using namespace lldb_private::process_gdb_remote; 990b57cec5SDimitry Andric 1005ffd83dbSDimitry Andric LLDB_PLUGIN_DEFINE(ProcessGDBRemote) 1015ffd83dbSDimitry Andric 1020b57cec5SDimitry Andric namespace lldb { 1030b57cec5SDimitry Andric // Provide a function that can easily dump the packet history if we know a 1040b57cec5SDimitry Andric // ProcessGDBRemote * value (which we can get from logs or from debugging). We 1050b57cec5SDimitry Andric // need the function in the lldb namespace so it makes it into the final 1060b57cec5SDimitry Andric // executable since the LLDB shared library only exports stuff in the lldb 1070b57cec5SDimitry Andric // namespace. This allows you to attach with a debugger and call this function 1080b57cec5SDimitry Andric // and get the packet history dumped to a file. 1090b57cec5SDimitry Andric void DumpProcessGDBRemotePacketHistory(void *p, const char *path) { 1109dba64beSDimitry Andric auto file = FileSystem::Instance().Open( 111349cc55cSDimitry Andric FileSpec(path), File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate); 1129dba64beSDimitry Andric if (!file) { 1139dba64beSDimitry Andric llvm::consumeError(file.takeError()); 1149dba64beSDimitry Andric return; 1159dba64beSDimitry Andric } 1169dba64beSDimitry Andric StreamFile stream(std::move(file.get())); 11706c3fb27SDimitry Andric ((Process *)p)->DumpPluginHistory(stream); 1180b57cec5SDimitry Andric } 1190b57cec5SDimitry Andric } // namespace lldb 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric namespace { 1220b57cec5SDimitry Andric 1239dba64beSDimitry Andric #define LLDB_PROPERTIES_processgdbremote 1249dba64beSDimitry Andric #include "ProcessGDBRemoteProperties.inc" 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric enum { 1279dba64beSDimitry Andric #define LLDB_PROPERTIES_processgdbremote 1289dba64beSDimitry Andric #include "ProcessGDBRemotePropertiesEnum.inc" 1290b57cec5SDimitry Andric }; 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric class PluginProperties : public Properties { 1320b57cec5SDimitry Andric public: 1335f757f3fSDimitry Andric static llvm::StringRef GetSettingName() { 1345f757f3fSDimitry Andric return ProcessGDBRemote::GetPluginNameStatic(); 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric PluginProperties() : Properties() { 1380b57cec5SDimitry Andric m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); 1399dba64beSDimitry Andric m_collection_sp->Initialize(g_processgdbremote_properties); 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric 142fe6060f1SDimitry Andric ~PluginProperties() override = default; 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric uint64_t GetPacketTimeout() { 1450b57cec5SDimitry Andric const uint32_t idx = ePropertyPacketTimeout; 14606c3fb27SDimitry Andric return GetPropertyAtIndexAs<uint64_t>( 14706c3fb27SDimitry Andric idx, g_processgdbremote_properties[idx].default_uint_value); 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric bool SetPacketTimeout(uint64_t timeout) { 1510b57cec5SDimitry Andric const uint32_t idx = ePropertyPacketTimeout; 15206c3fb27SDimitry Andric return SetPropertyAtIndex(idx, timeout); 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric FileSpec GetTargetDefinitionFile() const { 1560b57cec5SDimitry Andric const uint32_t idx = ePropertyTargetDefinitionFile; 15706c3fb27SDimitry Andric return GetPropertyAtIndexAs<FileSpec>(idx, {}); 1580b57cec5SDimitry Andric } 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric bool GetUseSVR4() const { 1610b57cec5SDimitry Andric const uint32_t idx = ePropertyUseSVR4; 16206c3fb27SDimitry Andric return GetPropertyAtIndexAs<bool>( 16306c3fb27SDimitry Andric idx, g_processgdbremote_properties[idx].default_uint_value != 0); 1640b57cec5SDimitry Andric } 165480093f4SDimitry Andric 166480093f4SDimitry Andric bool GetUseGPacketForReading() const { 167480093f4SDimitry Andric const uint32_t idx = ePropertyUseGPacketForReading; 16806c3fb27SDimitry Andric return GetPropertyAtIndexAs<bool>(idx, true); 169480093f4SDimitry Andric } 1700b57cec5SDimitry Andric }; 1710b57cec5SDimitry Andric 172bdd1243dSDimitry Andric } // namespace 173bdd1243dSDimitry Andric 174349cc55cSDimitry Andric static PluginProperties &GetGlobalPluginProperties() { 175349cc55cSDimitry Andric static PluginProperties g_settings; 176349cc55cSDimitry Andric return g_settings; 1770b57cec5SDimitry Andric } 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric // TODO Randomly assigning a port is unsafe. We should get an unused 1800b57cec5SDimitry Andric // ephemeral port from the kernel and make sure we reserve it before passing it 1810b57cec5SDimitry Andric // to debugserver. 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric #if defined(__APPLE__) 1840b57cec5SDimitry Andric #define LOW_PORT (IPPORT_RESERVED) 1850b57cec5SDimitry Andric #define HIGH_PORT (IPPORT_HIFIRSTAUTO) 1860b57cec5SDimitry Andric #else 1870b57cec5SDimitry Andric #define LOW_PORT (1024u) 1880b57cec5SDimitry Andric #define HIGH_PORT (49151u) 1890b57cec5SDimitry Andric #endif 1900b57cec5SDimitry Andric 191349cc55cSDimitry Andric llvm::StringRef ProcessGDBRemote::GetPluginDescriptionStatic() { 1920b57cec5SDimitry Andric return "GDB Remote protocol based debugging plug-in."; 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric void ProcessGDBRemote::Terminate() { 1960b57cec5SDimitry Andric PluginManager::UnregisterPlugin(ProcessGDBRemote::CreateInstance); 1970b57cec5SDimitry Andric } 1980b57cec5SDimitry Andric 199bdd1243dSDimitry Andric lldb::ProcessSP ProcessGDBRemote::CreateInstance( 200bdd1243dSDimitry Andric lldb::TargetSP target_sp, ListenerSP listener_sp, 201bdd1243dSDimitry Andric const FileSpec *crash_file_path, bool can_connect) { 2020b57cec5SDimitry Andric lldb::ProcessSP process_sp; 2030b57cec5SDimitry Andric if (crash_file_path == nullptr) 204bdd1243dSDimitry Andric process_sp = std::shared_ptr<ProcessGDBRemote>( 205bdd1243dSDimitry Andric new ProcessGDBRemote(target_sp, listener_sp)); 2060b57cec5SDimitry Andric return process_sp; 2070b57cec5SDimitry Andric } 2080b57cec5SDimitry Andric 20906c3fb27SDimitry Andric void ProcessGDBRemote::DumpPluginHistory(Stream &s) { 21006c3fb27SDimitry Andric GDBRemoteCommunicationClient &gdb_comm(GetGDBRemote()); 21106c3fb27SDimitry Andric gdb_comm.DumpHistory(s); 21206c3fb27SDimitry Andric } 21306c3fb27SDimitry Andric 214fe6060f1SDimitry Andric std::chrono::seconds ProcessGDBRemote::GetPacketTimeout() { 215349cc55cSDimitry Andric return std::chrono::seconds(GetGlobalPluginProperties().GetPacketTimeout()); 216fe6060f1SDimitry Andric } 217fe6060f1SDimitry Andric 21881ad6265SDimitry Andric ArchSpec ProcessGDBRemote::GetSystemArchitecture() { 21981ad6265SDimitry Andric return m_gdb_comm.GetHostArchitecture(); 22081ad6265SDimitry Andric } 22181ad6265SDimitry Andric 2220b57cec5SDimitry Andric bool ProcessGDBRemote::CanDebug(lldb::TargetSP target_sp, 2230b57cec5SDimitry Andric bool plugin_specified_by_name) { 2240b57cec5SDimitry Andric if (plugin_specified_by_name) 2250b57cec5SDimitry Andric return true; 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric // For now we are just making sure the file exists for a given module 2280b57cec5SDimitry Andric Module *exe_module = target_sp->GetExecutableModulePointer(); 2290b57cec5SDimitry Andric if (exe_module) { 2300b57cec5SDimitry Andric ObjectFile *exe_objfile = exe_module->GetObjectFile(); 2310b57cec5SDimitry Andric // We can't debug core files... 2320b57cec5SDimitry Andric switch (exe_objfile->GetType()) { 2330b57cec5SDimitry Andric case ObjectFile::eTypeInvalid: 2340b57cec5SDimitry Andric case ObjectFile::eTypeCoreFile: 2350b57cec5SDimitry Andric case ObjectFile::eTypeDebugInfo: 2360b57cec5SDimitry Andric case ObjectFile::eTypeObjectFile: 2370b57cec5SDimitry Andric case ObjectFile::eTypeSharedLibrary: 2380b57cec5SDimitry Andric case ObjectFile::eTypeStubLibrary: 2390b57cec5SDimitry Andric case ObjectFile::eTypeJIT: 2400b57cec5SDimitry Andric return false; 2410b57cec5SDimitry Andric case ObjectFile::eTypeExecutable: 2420b57cec5SDimitry Andric case ObjectFile::eTypeDynamicLinker: 2430b57cec5SDimitry Andric case ObjectFile::eTypeUnknown: 2440b57cec5SDimitry Andric break; 2450b57cec5SDimitry Andric } 2460b57cec5SDimitry Andric return FileSystem::Instance().Exists(exe_module->GetFileSpec()); 2470b57cec5SDimitry Andric } 2480b57cec5SDimitry Andric // However, if there is no executable module, we return true since we might 2490b57cec5SDimitry Andric // be preparing to attach. 2500b57cec5SDimitry Andric return true; 2510b57cec5SDimitry Andric } 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric // ProcessGDBRemote constructor 2540b57cec5SDimitry Andric ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, 2550b57cec5SDimitry Andric ListenerSP listener_sp) 2560b57cec5SDimitry Andric : Process(target_sp, listener_sp), 257349cc55cSDimitry Andric m_debugserver_pid(LLDB_INVALID_PROCESS_ID), m_register_info_sp(nullptr), 2580b57cec5SDimitry Andric m_async_broadcaster(nullptr, "lldb.process.gdb-remote.async-broadcaster"), 2590b57cec5SDimitry Andric m_async_listener_sp( 2600b57cec5SDimitry Andric Listener::MakeListener("lldb.process.gdb-remote.async-listener")), 2610b57cec5SDimitry Andric m_async_thread_state_mutex(), m_thread_ids(), m_thread_pcs(), 2620b57cec5SDimitry Andric m_jstopinfo_sp(), m_jthreadsinfo_sp(), m_continue_c_tids(), 2630b57cec5SDimitry Andric m_continue_C_tids(), m_continue_s_tids(), m_continue_S_tids(), 2640b57cec5SDimitry Andric m_max_memory_size(0), m_remote_stub_max_memory_size(0), 2650b57cec5SDimitry Andric m_addr_to_mmap_size(), m_thread_create_bp_sp(), 266*0fca6ea1SDimitry Andric m_waiting_for_attach(false), m_command_sp(), m_breakpoint_pc_offset(0), 26704eeddc0SDimitry Andric m_initial_tid(LLDB_INVALID_THREAD_ID), m_allow_flash_writes(false), 268*0fca6ea1SDimitry Andric m_erased_flash_ranges(), m_vfork_in_progress_count(0) { 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. 3065f757f3fSDimitry 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)) { 451*0fca6ea1SDimitry Andric if (name == "name") { 452349cc55cSDimitry Andric reg_info.name.SetString(value); 453*0fca6ea1SDimitry Andric } else if (name == "alt-name") { 454349cc55cSDimitry Andric reg_info.alt_name.SetString(value); 455*0fca6ea1SDimitry Andric } else if (name == "bitsize") { 456349cc55cSDimitry Andric if (!value.getAsInteger(0, reg_info.byte_size)) 4570b57cec5SDimitry Andric reg_info.byte_size /= CHAR_BIT; 458*0fca6ea1SDimitry Andric } else if (name == "offset") { 459349cc55cSDimitry Andric value.getAsInteger(0, reg_info.byte_offset); 460*0fca6ea1SDimitry Andric } else if (name == "encoding") { 4610b57cec5SDimitry Andric const Encoding encoding = Args::StringToEncoding(value); 4620b57cec5SDimitry Andric if (encoding != eEncodingInvalid) 4630b57cec5SDimitry Andric reg_info.encoding = encoding; 464*0fca6ea1SDimitry Andric } else if (name == "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); 483*0fca6ea1SDimitry Andric } else if (name == "set") { 484349cc55cSDimitry Andric reg_info.set_name.SetString(value); 485*0fca6ea1SDimitry Andric } else if (name == "gcc" || name == "ehframe") { 486349cc55cSDimitry Andric value.getAsInteger(0, reg_info.regnum_ehframe); 487*0fca6ea1SDimitry Andric } else if (name == "dwarf") { 488349cc55cSDimitry Andric value.getAsInteger(0, reg_info.regnum_dwarf); 489*0fca6ea1SDimitry Andric } else if (name == "generic") { 490349cc55cSDimitry Andric reg_info.regnum_generic = Args::StringToGenericRegister(value); 491*0fca6ea1SDimitry Andric } else if (name == "container-regs") { 492349cc55cSDimitry Andric SplitCommaSeparatedRegisterNumberString(value, reg_info.value_regs, 16); 493*0fca6ea1SDimitry Andric } else if (name == "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 9025f757f3fSDimitry Andric AddressableBits addressable_bits = m_gdb_comm.GetAddressableBits(); 903*0fca6ea1SDimitry Andric SetAddressableBitMasks(addressable_bits); 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; 10015f757f3fSDimitry 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, 10055f757f3fSDimitry 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; 10345f757f3fSDimitry 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, 10385f757f3fSDimitry Andric force_symbol_search, notify, set_address_in_target, 10395f757f3fSDimitry 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); 1092*0fca6ea1SDimitry Andric auto data_sp = 1093*0fca6ea1SDimitry Andric std::make_shared<EventDataBytes>(llvm::StringRef(packet, packet_len)); 10947a6dacacSDimitry Andric m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue, data_sp); 10950b57cec5SDimitry Andric } else 10960b57cec5SDimitry Andric SetExitStatus(-1, error.AsCString()); 10970b57cec5SDimitry Andric } 10980b57cec5SDimitry Andric 10990b57cec5SDimitry Andric return error; 11000b57cec5SDimitry Andric } 11010b57cec5SDimitry Andric 11020b57cec5SDimitry Andric Status ProcessGDBRemote::DoAttachToProcessWithName( 11030b57cec5SDimitry Andric const char *process_name, const ProcessAttachInfo &attach_info) { 11040b57cec5SDimitry Andric Status error; 11050b57cec5SDimitry Andric // Clear out and clean up from any current state 11060b57cec5SDimitry Andric Clear(); 11070b57cec5SDimitry Andric 11080b57cec5SDimitry Andric if (process_name && process_name[0]) { 11090b57cec5SDimitry Andric error = EstablishConnectionIfNeeded(attach_info); 11100b57cec5SDimitry Andric if (error.Success()) { 11110b57cec5SDimitry Andric StreamString packet; 11120b57cec5SDimitry Andric 11130b57cec5SDimitry Andric m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError()); 11140b57cec5SDimitry Andric 11150b57cec5SDimitry Andric if (attach_info.GetWaitForLaunch()) { 11160b57cec5SDimitry Andric if (!m_gdb_comm.GetVAttachOrWaitSupported()) { 11170b57cec5SDimitry Andric packet.PutCString("vAttachWait"); 11180b57cec5SDimitry Andric } else { 11190b57cec5SDimitry Andric if (attach_info.GetIgnoreExisting()) 11200b57cec5SDimitry Andric packet.PutCString("vAttachWait"); 11210b57cec5SDimitry Andric else 11220b57cec5SDimitry Andric packet.PutCString("vAttachOrWait"); 11230b57cec5SDimitry Andric } 11240b57cec5SDimitry Andric } else 11250b57cec5SDimitry Andric packet.PutCString("vAttachName"); 11260b57cec5SDimitry Andric packet.PutChar(';'); 11270b57cec5SDimitry Andric packet.PutBytesAsRawHex8(process_name, strlen(process_name), 11280b57cec5SDimitry Andric endian::InlHostByteOrder(), 11290b57cec5SDimitry Andric endian::InlHostByteOrder()); 11300b57cec5SDimitry Andric 1131*0fca6ea1SDimitry Andric auto data_sp = std::make_shared<EventDataBytes>(packet.GetString()); 11327a6dacacSDimitry Andric m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue, data_sp); 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 1377*0fca6ea1SDimitry Andric auto data_sp = 1378*0fca6ea1SDimitry Andric std::make_shared<EventDataBytes>(continue_packet.GetString()); 13797a6dacacSDimitry Andric m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue, data_sp); 13800b57cec5SDimitry Andric 13810b57cec5SDimitry Andric if (!listener_sp->GetEvent(event_sp, std::chrono::seconds(5))) { 13820b57cec5SDimitry Andric error.SetErrorString("Resume timed out."); 13839dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::DoResume: Resume timed out."); 13840b57cec5SDimitry Andric } else if (event_sp->BroadcasterIs(&m_async_broadcaster)) { 13850b57cec5SDimitry Andric error.SetErrorString("Broadcast continue, but the async thread was " 13860b57cec5SDimitry Andric "killed before we got an ack back."); 13879dba64beSDimitry Andric LLDB_LOGF(log, 13889dba64beSDimitry Andric "ProcessGDBRemote::DoResume: Broadcast continue, but the " 13890b57cec5SDimitry Andric "async thread was killed before we got an ack back."); 13900b57cec5SDimitry Andric return error; 13910b57cec5SDimitry Andric } 13920b57cec5SDimitry Andric } 13930b57cec5SDimitry Andric } 13940b57cec5SDimitry Andric 13950b57cec5SDimitry Andric return error; 13960b57cec5SDimitry Andric } 13970b57cec5SDimitry Andric 13980b57cec5SDimitry Andric void ProcessGDBRemote::ClearThreadIDList() { 13990b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex()); 14000b57cec5SDimitry Andric m_thread_ids.clear(); 14010b57cec5SDimitry Andric m_thread_pcs.clear(); 14020b57cec5SDimitry Andric } 14030b57cec5SDimitry Andric 1404fe6060f1SDimitry Andric size_t ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue( 1405fe6060f1SDimitry Andric llvm::StringRef value) { 14060b57cec5SDimitry Andric m_thread_ids.clear(); 1407fe6060f1SDimitry Andric lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID(); 1408fe6060f1SDimitry Andric StringExtractorGDBRemote thread_ids{value}; 1409fe6060f1SDimitry Andric 1410fe6060f1SDimitry Andric do { 1411fe6060f1SDimitry Andric auto pid_tid = thread_ids.GetPidTid(pid); 1412fe6060f1SDimitry Andric if (pid_tid && pid_tid->first == pid) { 1413fe6060f1SDimitry Andric lldb::tid_t tid = pid_tid->second; 1414fe6060f1SDimitry Andric if (tid != LLDB_INVALID_THREAD_ID && 1415fe6060f1SDimitry Andric tid != StringExtractorGDBRemote::AllProcesses) 14160b57cec5SDimitry Andric m_thread_ids.push_back(tid); 14170b57cec5SDimitry Andric } 1418fe6060f1SDimitry Andric } while (thread_ids.GetChar() == ','); 1419fe6060f1SDimitry Andric 14200b57cec5SDimitry Andric return m_thread_ids.size(); 14210b57cec5SDimitry Andric } 14220b57cec5SDimitry Andric 1423349cc55cSDimitry Andric size_t ProcessGDBRemote::UpdateThreadPCsFromStopReplyThreadsValue( 1424349cc55cSDimitry Andric llvm::StringRef value) { 14250b57cec5SDimitry Andric m_thread_pcs.clear(); 1426349cc55cSDimitry Andric for (llvm::StringRef x : llvm::split(value, ',')) { 14270b57cec5SDimitry Andric lldb::addr_t pc; 1428349cc55cSDimitry Andric if (llvm::to_integer(x, pc, 16)) 14290b57cec5SDimitry Andric m_thread_pcs.push_back(pc); 14300b57cec5SDimitry Andric } 14310b57cec5SDimitry Andric return m_thread_pcs.size(); 14320b57cec5SDimitry Andric } 14330b57cec5SDimitry Andric 14340b57cec5SDimitry Andric bool ProcessGDBRemote::UpdateThreadIDList() { 14350b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex()); 14360b57cec5SDimitry Andric 14370b57cec5SDimitry Andric if (m_jthreadsinfo_sp) { 14380b57cec5SDimitry Andric // If we have the JSON threads info, we can get the thread list from that 14390b57cec5SDimitry Andric StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray(); 14400b57cec5SDimitry Andric if (thread_infos && thread_infos->GetSize() > 0) { 14410b57cec5SDimitry Andric m_thread_ids.clear(); 14420b57cec5SDimitry Andric m_thread_pcs.clear(); 14430b57cec5SDimitry Andric thread_infos->ForEach([this](StructuredData::Object *object) -> bool { 14440b57cec5SDimitry Andric StructuredData::Dictionary *thread_dict = object->GetAsDictionary(); 14450b57cec5SDimitry Andric if (thread_dict) { 14460b57cec5SDimitry Andric // Set the thread stop info from the JSON dictionary 14470b57cec5SDimitry Andric SetThreadStopInfo(thread_dict); 14480b57cec5SDimitry Andric lldb::tid_t tid = LLDB_INVALID_THREAD_ID; 14490b57cec5SDimitry Andric if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>("tid", tid)) 14500b57cec5SDimitry Andric m_thread_ids.push_back(tid); 14510b57cec5SDimitry Andric } 14520b57cec5SDimitry Andric return true; // Keep iterating through all thread_info objects 14530b57cec5SDimitry Andric }); 14540b57cec5SDimitry Andric } 14550b57cec5SDimitry Andric if (!m_thread_ids.empty()) 14560b57cec5SDimitry Andric return true; 14570b57cec5SDimitry Andric } else { 14580b57cec5SDimitry Andric // See if we can get the thread IDs from the current stop reply packets 14590b57cec5SDimitry Andric // that might contain a "threads" key/value pair 14600b57cec5SDimitry Andric 1461349cc55cSDimitry Andric if (m_last_stop_packet) { 14620b57cec5SDimitry Andric // Get the thread stop info 1463349cc55cSDimitry Andric StringExtractorGDBRemote &stop_info = *m_last_stop_packet; 1464349cc55cSDimitry Andric const std::string &stop_info_str = std::string(stop_info.GetStringRef()); 14650b57cec5SDimitry Andric 14660b57cec5SDimitry Andric m_thread_pcs.clear(); 14670b57cec5SDimitry Andric const size_t thread_pcs_pos = stop_info_str.find(";thread-pcs:"); 14680b57cec5SDimitry Andric if (thread_pcs_pos != std::string::npos) { 14690b57cec5SDimitry Andric const size_t start = thread_pcs_pos + strlen(";thread-pcs:"); 14700b57cec5SDimitry Andric const size_t end = stop_info_str.find(';', start); 14710b57cec5SDimitry Andric if (end != std::string::npos) { 14720b57cec5SDimitry Andric std::string value = stop_info_str.substr(start, end - start); 14730b57cec5SDimitry Andric UpdateThreadPCsFromStopReplyThreadsValue(value); 14740b57cec5SDimitry Andric } 14750b57cec5SDimitry Andric } 14760b57cec5SDimitry Andric 14770b57cec5SDimitry Andric const size_t threads_pos = stop_info_str.find(";threads:"); 14780b57cec5SDimitry Andric if (threads_pos != std::string::npos) { 14790b57cec5SDimitry Andric const size_t start = threads_pos + strlen(";threads:"); 14800b57cec5SDimitry Andric const size_t end = stop_info_str.find(';', start); 14810b57cec5SDimitry Andric if (end != std::string::npos) { 14820b57cec5SDimitry Andric std::string value = stop_info_str.substr(start, end - start); 14830b57cec5SDimitry Andric if (UpdateThreadIDsFromStopReplyThreadsValue(value)) 14840b57cec5SDimitry Andric return true; 14850b57cec5SDimitry Andric } 14860b57cec5SDimitry Andric } 14870b57cec5SDimitry Andric } 14880b57cec5SDimitry Andric } 14890b57cec5SDimitry Andric 14900b57cec5SDimitry Andric bool sequence_mutex_unavailable = false; 14910b57cec5SDimitry Andric m_gdb_comm.GetCurrentThreadIDs(m_thread_ids, sequence_mutex_unavailable); 14920b57cec5SDimitry Andric if (sequence_mutex_unavailable) { 14930b57cec5SDimitry Andric return false; // We just didn't get the list 14940b57cec5SDimitry Andric } 14950b57cec5SDimitry Andric return true; 14960b57cec5SDimitry Andric } 14970b57cec5SDimitry Andric 1498e8d8bef9SDimitry Andric bool ProcessGDBRemote::DoUpdateThreadList(ThreadList &old_thread_list, 14990b57cec5SDimitry Andric ThreadList &new_thread_list) { 15000b57cec5SDimitry Andric // locker will keep a mutex locked until it goes out of scope 15011fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Thread); 15020b57cec5SDimitry Andric LLDB_LOGV(log, "pid = {0}", GetID()); 15030b57cec5SDimitry Andric 15040b57cec5SDimitry Andric size_t num_thread_ids = m_thread_ids.size(); 15050b57cec5SDimitry Andric // The "m_thread_ids" thread ID list should always be updated after each stop 15060b57cec5SDimitry Andric // reply packet, but in case it isn't, update it here. 15070b57cec5SDimitry Andric if (num_thread_ids == 0) { 15080b57cec5SDimitry Andric if (!UpdateThreadIDList()) 15090b57cec5SDimitry Andric return false; 15100b57cec5SDimitry Andric num_thread_ids = m_thread_ids.size(); 15110b57cec5SDimitry Andric } 15120b57cec5SDimitry Andric 15130b57cec5SDimitry Andric ThreadList old_thread_list_copy(old_thread_list); 15140b57cec5SDimitry Andric if (num_thread_ids > 0) { 15150b57cec5SDimitry Andric for (size_t i = 0; i < num_thread_ids; ++i) { 15160b57cec5SDimitry Andric tid_t tid = m_thread_ids[i]; 15170b57cec5SDimitry Andric ThreadSP thread_sp( 15180b57cec5SDimitry Andric old_thread_list_copy.RemoveThreadByProtocolID(tid, false)); 15190b57cec5SDimitry Andric if (!thread_sp) { 15200b57cec5SDimitry Andric thread_sp = std::make_shared<ThreadGDBRemote>(*this, tid); 15210b57cec5SDimitry Andric LLDB_LOGV(log, "Making new thread: {0} for thread ID: {1:x}.", 15220b57cec5SDimitry Andric thread_sp.get(), thread_sp->GetID()); 15230b57cec5SDimitry Andric } else { 15240b57cec5SDimitry Andric LLDB_LOGV(log, "Found old thread: {0} for thread ID: {1:x}.", 15250b57cec5SDimitry Andric thread_sp.get(), thread_sp->GetID()); 15260b57cec5SDimitry Andric } 15270b57cec5SDimitry Andric 15280b57cec5SDimitry Andric SetThreadPc(thread_sp, i); 15290b57cec5SDimitry Andric new_thread_list.AddThreadSortedByIndexID(thread_sp); 15300b57cec5SDimitry Andric } 15310b57cec5SDimitry Andric } 15320b57cec5SDimitry Andric 15330b57cec5SDimitry Andric // Whatever that is left in old_thread_list_copy are not present in 15340b57cec5SDimitry Andric // new_thread_list. Remove non-existent threads from internal id table. 15350b57cec5SDimitry Andric size_t old_num_thread_ids = old_thread_list_copy.GetSize(false); 15360b57cec5SDimitry Andric for (size_t i = 0; i < old_num_thread_ids; i++) { 15370b57cec5SDimitry Andric ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex(i, false)); 15380b57cec5SDimitry Andric if (old_thread_sp) { 15390b57cec5SDimitry Andric lldb::tid_t old_thread_id = old_thread_sp->GetProtocolID(); 15400b57cec5SDimitry Andric m_thread_id_to_index_id_map.erase(old_thread_id); 15410b57cec5SDimitry Andric } 15420b57cec5SDimitry Andric } 15430b57cec5SDimitry Andric 15440b57cec5SDimitry Andric return true; 15450b57cec5SDimitry Andric } 15460b57cec5SDimitry Andric 15470b57cec5SDimitry Andric void ProcessGDBRemote::SetThreadPc(const ThreadSP &thread_sp, uint64_t index) { 15480b57cec5SDimitry Andric if (m_thread_ids.size() == m_thread_pcs.size() && thread_sp.get() && 15490b57cec5SDimitry Andric GetByteOrder() != eByteOrderInvalid) { 15500b57cec5SDimitry Andric ThreadGDBRemote *gdb_thread = 15510b57cec5SDimitry Andric static_cast<ThreadGDBRemote *>(thread_sp.get()); 15520b57cec5SDimitry Andric RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext()); 15530b57cec5SDimitry Andric if (reg_ctx_sp) { 15540b57cec5SDimitry Andric uint32_t pc_regnum = reg_ctx_sp->ConvertRegisterKindToRegisterNumber( 15550b57cec5SDimitry Andric eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 15560b57cec5SDimitry Andric if (pc_regnum != LLDB_INVALID_REGNUM) { 15570b57cec5SDimitry Andric gdb_thread->PrivateSetRegisterValue(pc_regnum, m_thread_pcs[index]); 15580b57cec5SDimitry Andric } 15590b57cec5SDimitry Andric } 15600b57cec5SDimitry Andric } 15610b57cec5SDimitry Andric } 15620b57cec5SDimitry Andric 15630b57cec5SDimitry Andric bool ProcessGDBRemote::GetThreadStopInfoFromJSON( 15640b57cec5SDimitry Andric ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp) { 15650b57cec5SDimitry Andric // See if we got thread stop infos for all threads via the "jThreadsInfo" 15660b57cec5SDimitry Andric // packet 15670b57cec5SDimitry Andric if (thread_infos_sp) { 15680b57cec5SDimitry Andric StructuredData::Array *thread_infos = thread_infos_sp->GetAsArray(); 15690b57cec5SDimitry Andric if (thread_infos) { 15700b57cec5SDimitry Andric lldb::tid_t tid; 15710b57cec5SDimitry Andric const size_t n = thread_infos->GetSize(); 15720b57cec5SDimitry Andric for (size_t i = 0; i < n; ++i) { 15730b57cec5SDimitry Andric StructuredData::Dictionary *thread_dict = 15740b57cec5SDimitry Andric thread_infos->GetItemAtIndex(i)->GetAsDictionary(); 15750b57cec5SDimitry Andric if (thread_dict) { 15760b57cec5SDimitry Andric if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>( 15770b57cec5SDimitry Andric "tid", tid, LLDB_INVALID_THREAD_ID)) { 15780b57cec5SDimitry Andric if (tid == thread->GetID()) 15790b57cec5SDimitry Andric return (bool)SetThreadStopInfo(thread_dict); 15800b57cec5SDimitry Andric } 15810b57cec5SDimitry Andric } 15820b57cec5SDimitry Andric } 15830b57cec5SDimitry Andric } 15840b57cec5SDimitry Andric } 15850b57cec5SDimitry Andric return false; 15860b57cec5SDimitry Andric } 15870b57cec5SDimitry Andric 15880b57cec5SDimitry Andric bool ProcessGDBRemote::CalculateThreadStopInfo(ThreadGDBRemote *thread) { 15890b57cec5SDimitry Andric // See if we got thread stop infos for all threads via the "jThreadsInfo" 15900b57cec5SDimitry Andric // packet 15910b57cec5SDimitry Andric if (GetThreadStopInfoFromJSON(thread, m_jthreadsinfo_sp)) 15920b57cec5SDimitry Andric return true; 15930b57cec5SDimitry Andric 15940b57cec5SDimitry Andric // See if we got thread stop info for any threads valid stop info reasons 15950b57cec5SDimitry Andric // threads via the "jstopinfo" packet stop reply packet key/value pair? 15960b57cec5SDimitry Andric if (m_jstopinfo_sp) { 15970b57cec5SDimitry Andric // If we have "jstopinfo" then we have stop descriptions for all threads 15980b57cec5SDimitry Andric // that have stop reasons, and if there is no entry for a thread, then it 15990b57cec5SDimitry Andric // has no stop reason. 16000b57cec5SDimitry Andric thread->GetRegisterContext()->InvalidateIfNeeded(true); 16010b57cec5SDimitry Andric if (!GetThreadStopInfoFromJSON(thread, m_jstopinfo_sp)) { 1602*0fca6ea1SDimitry Andric // If a thread is stopped at a breakpoint site, set that as the stop 1603*0fca6ea1SDimitry Andric // reason even if it hasn't executed the breakpoint instruction yet. 1604*0fca6ea1SDimitry Andric // We will silently step over the breakpoint when we resume execution 1605*0fca6ea1SDimitry Andric // and miss the fact that this thread hit the breakpoint. 1606*0fca6ea1SDimitry Andric const size_t num_thread_ids = m_thread_ids.size(); 1607*0fca6ea1SDimitry Andric for (size_t i = 0; i < num_thread_ids; i++) { 1608*0fca6ea1SDimitry Andric if (m_thread_ids[i] == thread->GetID() && m_thread_pcs.size() > i) { 1609*0fca6ea1SDimitry Andric addr_t pc = m_thread_pcs[i]; 1610*0fca6ea1SDimitry Andric lldb::BreakpointSiteSP bp_site_sp = 1611*0fca6ea1SDimitry Andric thread->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); 1612*0fca6ea1SDimitry Andric if (bp_site_sp) { 1613*0fca6ea1SDimitry Andric if (bp_site_sp->ValidForThisThread(*thread)) { 1614*0fca6ea1SDimitry Andric thread->SetStopInfo( 1615*0fca6ea1SDimitry Andric StopInfo::CreateStopReasonWithBreakpointSiteID( 1616*0fca6ea1SDimitry Andric *thread, bp_site_sp->GetID())); 1617*0fca6ea1SDimitry Andric return true; 1618*0fca6ea1SDimitry Andric } 1619*0fca6ea1SDimitry Andric } 1620*0fca6ea1SDimitry Andric } 1621*0fca6ea1SDimitry Andric } 16220b57cec5SDimitry Andric thread->SetStopInfo(StopInfoSP()); 16230b57cec5SDimitry Andric } 16240b57cec5SDimitry Andric return true; 16250b57cec5SDimitry Andric } 16260b57cec5SDimitry Andric 16270b57cec5SDimitry Andric // Fall back to using the qThreadStopInfo packet 16280b57cec5SDimitry Andric StringExtractorGDBRemote stop_packet; 16290b57cec5SDimitry Andric if (GetGDBRemote().GetThreadStopInfo(thread->GetProtocolID(), stop_packet)) 16300b57cec5SDimitry Andric return SetThreadStopInfo(stop_packet) == eStateStopped; 16310b57cec5SDimitry Andric return false; 16320b57cec5SDimitry Andric } 16330b57cec5SDimitry Andric 16345f757f3fSDimitry Andric void ProcessGDBRemote::ParseExpeditedRegisters( 16355f757f3fSDimitry Andric ExpeditedRegisterMap &expedited_register_map, ThreadSP thread_sp) { 16365f757f3fSDimitry Andric ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *>(thread_sp.get()); 16375f757f3fSDimitry Andric RegisterContextSP gdb_reg_ctx_sp(gdb_thread->GetRegisterContext()); 16385f757f3fSDimitry Andric 16395f757f3fSDimitry Andric for (const auto &pair : expedited_register_map) { 16405f757f3fSDimitry Andric StringExtractor reg_value_extractor(pair.second); 16415f757f3fSDimitry Andric WritableDataBufferSP buffer_sp( 16425f757f3fSDimitry Andric new DataBufferHeap(reg_value_extractor.GetStringRef().size() / 2, 0)); 16435f757f3fSDimitry Andric reg_value_extractor.GetHexBytes(buffer_sp->GetData(), '\xcc'); 16445f757f3fSDimitry Andric uint32_t lldb_regnum = gdb_reg_ctx_sp->ConvertRegisterKindToRegisterNumber( 16455f757f3fSDimitry Andric eRegisterKindProcessPlugin, pair.first); 16465f757f3fSDimitry Andric gdb_thread->PrivateSetRegisterValue(lldb_regnum, buffer_sp->GetData()); 16475f757f3fSDimitry Andric } 16485f757f3fSDimitry Andric } 16495f757f3fSDimitry Andric 16500b57cec5SDimitry Andric ThreadSP ProcessGDBRemote::SetThreadStopInfo( 16510b57cec5SDimitry Andric lldb::tid_t tid, ExpeditedRegisterMap &expedited_register_map, 16520b57cec5SDimitry Andric uint8_t signo, const std::string &thread_name, const std::string &reason, 16530b57cec5SDimitry Andric const std::string &description, uint32_t exc_type, 16540b57cec5SDimitry Andric const std::vector<addr_t> &exc_data, addr_t thread_dispatch_qaddr, 16550b57cec5SDimitry Andric bool queue_vars_valid, // Set to true if queue_name, queue_kind and 16560b57cec5SDimitry Andric // queue_serial are valid 16570b57cec5SDimitry Andric LazyBool associated_with_dispatch_queue, addr_t dispatch_queue_t, 16580b57cec5SDimitry Andric std::string &queue_name, QueueKind queue_kind, uint64_t queue_serial) { 1659bdd1243dSDimitry Andric 1660bdd1243dSDimitry Andric if (tid == LLDB_INVALID_THREAD_ID) 1661bdd1243dSDimitry Andric return nullptr; 1662bdd1243dSDimitry Andric 16630b57cec5SDimitry Andric ThreadSP thread_sp; 16640b57cec5SDimitry Andric // Scope for "locker" below 16650b57cec5SDimitry Andric { 1666bdd1243dSDimitry Andric // m_thread_list_real does have its own mutex, but we need to hold onto the 1667bdd1243dSDimitry Andric // mutex between the call to m_thread_list_real.FindThreadByID(...) and the 1668bdd1243dSDimitry Andric // m_thread_list_real.AddThread(...) so it doesn't change on us 1669bdd1243dSDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex()); 16700b57cec5SDimitry Andric thread_sp = m_thread_list_real.FindThreadByProtocolID(tid, false); 16710b57cec5SDimitry Andric 16720b57cec5SDimitry Andric if (!thread_sp) { 16730b57cec5SDimitry Andric // Create the thread if we need to 16740b57cec5SDimitry Andric thread_sp = std::make_shared<ThreadGDBRemote>(*this, tid); 16750b57cec5SDimitry Andric m_thread_list_real.AddThread(thread_sp); 16760b57cec5SDimitry Andric } 16770b57cec5SDimitry Andric } 16780b57cec5SDimitry Andric 1679bdd1243dSDimitry Andric ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *>(thread_sp.get()); 16805f757f3fSDimitry Andric RegisterContextSP reg_ctx_sp(gdb_thread->GetRegisterContext()); 1681fe6060f1SDimitry Andric 16825f757f3fSDimitry Andric reg_ctx_sp->InvalidateIfNeeded(true); 16830b57cec5SDimitry Andric 16840b57cec5SDimitry Andric auto iter = std::find(m_thread_ids.begin(), m_thread_ids.end(), tid); 1685bdd1243dSDimitry Andric if (iter != m_thread_ids.end()) 16860b57cec5SDimitry Andric SetThreadPc(thread_sp, iter - m_thread_ids.begin()); 16870b57cec5SDimitry Andric 16885f757f3fSDimitry Andric ParseExpeditedRegisters(expedited_register_map, thread_sp); 16890b57cec5SDimitry Andric 16905f757f3fSDimitry Andric if (reg_ctx_sp->ReconfigureRegisterInfo()) { 16915f757f3fSDimitry Andric // Now we have changed the offsets of all the registers, so the values 16925f757f3fSDimitry Andric // will be corrupted. 16935f757f3fSDimitry Andric reg_ctx_sp->InvalidateAllRegisters(); 16945f757f3fSDimitry Andric // Expedited registers values will never contain registers that would be 16955f757f3fSDimitry Andric // resized by a reconfigure. So we are safe to continue using these 16965f757f3fSDimitry Andric // values. 16975f757f3fSDimitry Andric ParseExpeditedRegisters(expedited_register_map, thread_sp); 1698e8d8bef9SDimitry Andric } 1699e8d8bef9SDimitry Andric 17000b57cec5SDimitry Andric thread_sp->SetName(thread_name.empty() ? nullptr : thread_name.c_str()); 17010b57cec5SDimitry Andric 17020b57cec5SDimitry Andric gdb_thread->SetThreadDispatchQAddr(thread_dispatch_qaddr); 1703bdd1243dSDimitry Andric // Check if the GDB server was able to provide the queue name, kind and serial 1704bdd1243dSDimitry Andric // number 17050b57cec5SDimitry Andric if (queue_vars_valid) 1706bdd1243dSDimitry Andric gdb_thread->SetQueueInfo(std::move(queue_name), queue_kind, queue_serial, 1707bdd1243dSDimitry Andric dispatch_queue_t, associated_with_dispatch_queue); 17080b57cec5SDimitry Andric else 17090b57cec5SDimitry Andric gdb_thread->ClearQueueInfo(); 17100b57cec5SDimitry Andric 1711bdd1243dSDimitry Andric gdb_thread->SetAssociatedWithLibdispatchQueue(associated_with_dispatch_queue); 17120b57cec5SDimitry Andric 17130b57cec5SDimitry Andric if (dispatch_queue_t != LLDB_INVALID_ADDRESS) 17140b57cec5SDimitry Andric gdb_thread->SetQueueLibdispatchQueueAddress(dispatch_queue_t); 17150b57cec5SDimitry Andric 1716bdd1243dSDimitry Andric // Make sure we update our thread stop reason just once, but don't overwrite 1717bdd1243dSDimitry Andric // the stop info for threads that haven't moved: 1718bdd1243dSDimitry Andric StopInfoSP current_stop_info_sp = thread_sp->GetPrivateStopInfo(false); 1719bdd1243dSDimitry Andric if (thread_sp->GetTemporaryResumeState() == eStateSuspended && 1720bdd1243dSDimitry Andric current_stop_info_sp) { 1721bdd1243dSDimitry Andric thread_sp->SetStopInfo(current_stop_info_sp); 1722bdd1243dSDimitry Andric return thread_sp; 1723bdd1243dSDimitry Andric } 1724bdd1243dSDimitry Andric 17250b57cec5SDimitry Andric if (!thread_sp->StopInfoIsUpToDate()) { 17260b57cec5SDimitry Andric thread_sp->SetStopInfo(StopInfoSP()); 1727bdd1243dSDimitry Andric // If there's a memory thread backed by this thread, we need to use it to 1728bdd1243dSDimitry Andric // calculate StopInfo. 1729bdd1243dSDimitry Andric if (ThreadSP memory_thread_sp = m_thread_list.GetBackingThread(thread_sp)) 17300b57cec5SDimitry Andric thread_sp = memory_thread_sp; 17310b57cec5SDimitry Andric 17320b57cec5SDimitry Andric if (exc_type != 0) { 17330b57cec5SDimitry Andric const size_t exc_data_size = exc_data.size(); 17340b57cec5SDimitry Andric 17350b57cec5SDimitry Andric thread_sp->SetStopInfo( 17360b57cec5SDimitry Andric StopInfoMachException::CreateStopReasonWithMachException( 17370b57cec5SDimitry Andric *thread_sp, exc_type, exc_data_size, 17380b57cec5SDimitry Andric exc_data_size >= 1 ? exc_data[0] : 0, 17390b57cec5SDimitry Andric exc_data_size >= 2 ? exc_data[1] : 0, 17400b57cec5SDimitry Andric exc_data_size >= 3 ? exc_data[2] : 0)); 17410b57cec5SDimitry Andric } else { 17420b57cec5SDimitry Andric bool handled = false; 17430b57cec5SDimitry Andric bool did_exec = false; 1744*0fca6ea1SDimitry Andric // debugserver can send reason = "none" which is equivalent 1745*0fca6ea1SDimitry Andric // to no reason. 1746*0fca6ea1SDimitry Andric if (!reason.empty() && reason != "none") { 17470b57cec5SDimitry Andric if (reason == "trace") { 17480b57cec5SDimitry Andric addr_t pc = thread_sp->GetRegisterContext()->GetPC(); 1749bdd1243dSDimitry Andric lldb::BreakpointSiteSP bp_site_sp = 1750bdd1243dSDimitry Andric thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress( 1751bdd1243dSDimitry Andric pc); 17520b57cec5SDimitry Andric 1753bdd1243dSDimitry Andric // If the current pc is a breakpoint site then the StopInfo should be 1754bdd1243dSDimitry Andric // set to Breakpoint Otherwise, it will be set to Trace. 1755fe6060f1SDimitry Andric if (bp_site_sp && bp_site_sp->ValidForThisThread(*thread_sp)) { 17560b57cec5SDimitry Andric thread_sp->SetStopInfo( 17570b57cec5SDimitry Andric StopInfo::CreateStopReasonWithBreakpointSiteID( 17580b57cec5SDimitry Andric *thread_sp, bp_site_sp->GetID())); 17590b57cec5SDimitry Andric } else 17600b57cec5SDimitry Andric thread_sp->SetStopInfo( 17610b57cec5SDimitry Andric StopInfo::CreateStopReasonToTrace(*thread_sp)); 17620b57cec5SDimitry Andric handled = true; 17630b57cec5SDimitry Andric } else if (reason == "breakpoint") { 17640b57cec5SDimitry Andric addr_t pc = thread_sp->GetRegisterContext()->GetPC(); 1765bdd1243dSDimitry Andric lldb::BreakpointSiteSP bp_site_sp = 1766bdd1243dSDimitry Andric thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress( 1767bdd1243dSDimitry Andric pc); 17680b57cec5SDimitry Andric if (bp_site_sp) { 1769bdd1243dSDimitry Andric // If the breakpoint is for this thread, then we'll report the hit, 1770bdd1243dSDimitry Andric // but if it is for another thread, we can just report no reason. 1771bdd1243dSDimitry Andric // We don't need to worry about stepping over the breakpoint here, 1772bdd1243dSDimitry Andric // that will be taken care of when the thread resumes and notices 1773bdd1243dSDimitry Andric // that there's a breakpoint under the pc. 17740b57cec5SDimitry Andric handled = true; 1775fe6060f1SDimitry Andric if (bp_site_sp->ValidForThisThread(*thread_sp)) { 17760b57cec5SDimitry Andric thread_sp->SetStopInfo( 17770b57cec5SDimitry Andric StopInfo::CreateStopReasonWithBreakpointSiteID( 17780b57cec5SDimitry Andric *thread_sp, bp_site_sp->GetID())); 17790b57cec5SDimitry Andric } else { 17800b57cec5SDimitry Andric StopInfoSP invalid_stop_info_sp; 17810b57cec5SDimitry Andric thread_sp->SetStopInfo(invalid_stop_info_sp); 17820b57cec5SDimitry Andric } 17830b57cec5SDimitry Andric } 17840b57cec5SDimitry Andric } else if (reason == "trap") { 17850b57cec5SDimitry Andric // Let the trap just use the standard signal stop reason below... 17860b57cec5SDimitry Andric } else if (reason == "watchpoint") { 178706c3fb27SDimitry Andric // We will have between 1 and 3 fields in the description. 178806c3fb27SDimitry Andric // 178906c3fb27SDimitry Andric // \a wp_addr which is the original start address that 179006c3fb27SDimitry Andric // lldb requested be watched, or an address that the 179106c3fb27SDimitry Andric // hardware reported. This address should be within the 179206c3fb27SDimitry Andric // range of a currently active watchpoint region - lldb 179306c3fb27SDimitry Andric // should be able to find a watchpoint with this address. 179406c3fb27SDimitry Andric // 179506c3fb27SDimitry Andric // \a wp_index is the hardware watchpoint register number. 179606c3fb27SDimitry Andric // 179706c3fb27SDimitry Andric // \a wp_hit_addr is the actual address reported by the hardware, 179806c3fb27SDimitry Andric // which may be outside the range of a region we are watching. 179906c3fb27SDimitry Andric // 180006c3fb27SDimitry Andric // On MIPS, we may get a false watchpoint exception where an 180106c3fb27SDimitry Andric // access to the same 8 byte granule as a watchpoint will trigger, 180206c3fb27SDimitry Andric // even if the access was not within the range of the watched 180306c3fb27SDimitry Andric // region. When we get a \a wp_hit_addr outside the range of any 180406c3fb27SDimitry Andric // set watchpoint, continue execution without making it visible to 180506c3fb27SDimitry Andric // the user. 180606c3fb27SDimitry Andric // 180706c3fb27SDimitry Andric // On ARM, a related issue where a large access that starts 180806c3fb27SDimitry Andric // before the watched region (and extends into the watched 180906c3fb27SDimitry Andric // region) may report a hit address before the watched region. 181006c3fb27SDimitry Andric // lldb will not find the "nearest" watchpoint to 181106c3fb27SDimitry Andric // disable/step/re-enable it, so one of the valid watchpoint 181206c3fb27SDimitry Andric // addresses should be provided as \a wp_addr. 18130b57cec5SDimitry Andric StringExtractor desc_extractor(description.c_str()); 18145f757f3fSDimitry Andric // FIXME NativeThreadLinux::SetStoppedByWatchpoint sends this 18155f757f3fSDimitry Andric // up as 18165f757f3fSDimitry Andric // <address within wp range> <wp hw index> <actual accessed addr> 18175f757f3fSDimitry Andric // but this is not reading the <wp hw index>. Seems like it 18185f757f3fSDimitry Andric // wouldn't work on MIPS, where that third field is important. 18190b57cec5SDimitry Andric addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); 18200b57cec5SDimitry Andric addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); 18210b57cec5SDimitry Andric watch_id_t watch_id = LLDB_INVALID_WATCH_ID; 182206c3fb27SDimitry Andric bool silently_continue = false; 18235f757f3fSDimitry Andric WatchpointResourceSP wp_resource_sp; 182406c3fb27SDimitry Andric if (wp_hit_addr != LLDB_INVALID_ADDRESS) { 18255f757f3fSDimitry Andric wp_resource_sp = 18265f757f3fSDimitry Andric m_watchpoint_resource_list.FindByAddress(wp_hit_addr); 182706c3fb27SDimitry Andric // On MIPS, \a wp_hit_addr outside the range of a watched 182806c3fb27SDimitry Andric // region means we should silently continue, it is a false hit. 18290b57cec5SDimitry Andric ArchSpec::Core core = GetTarget().GetArchitecture().GetCore(); 18305f757f3fSDimitry Andric if (!wp_resource_sp && core >= ArchSpec::kCore_mips_first && 183106c3fb27SDimitry Andric core <= ArchSpec::kCore_mips_last) 183206c3fb27SDimitry Andric silently_continue = true; 183306c3fb27SDimitry Andric } 18345f757f3fSDimitry Andric if (!wp_resource_sp && wp_addr != LLDB_INVALID_ADDRESS) 18355f757f3fSDimitry Andric wp_resource_sp = m_watchpoint_resource_list.FindByAddress(wp_addr); 18365f757f3fSDimitry Andric if (!wp_resource_sp) { 18371fd87a68SDimitry Andric Log *log(GetLog(GDBRLog::Watchpoints)); 18389dba64beSDimitry Andric LLDB_LOGF(log, "failed to find watchpoint"); 18395f757f3fSDimitry Andric watch_id = LLDB_INVALID_SITE_ID; 18405f757f3fSDimitry Andric } else { 18415f757f3fSDimitry Andric // LWP_TODO: This is hardcoding a single Watchpoint in a 18425f757f3fSDimitry Andric // Resource, need to add 18435f757f3fSDimitry Andric // StopInfo::CreateStopReasonWithWatchpointResource which 18445f757f3fSDimitry Andric // represents all watchpoints that were tripped at this stop. 18455f757f3fSDimitry Andric watch_id = wp_resource_sp->GetConstituentAtIndex(0)->GetID(); 18460b57cec5SDimitry Andric } 18470b57cec5SDimitry Andric thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithWatchpointID( 184806c3fb27SDimitry Andric *thread_sp, watch_id, silently_continue)); 18490b57cec5SDimitry Andric handled = true; 18500b57cec5SDimitry Andric } else if (reason == "exception") { 18510b57cec5SDimitry Andric thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithException( 18520b57cec5SDimitry Andric *thread_sp, description.c_str())); 18530b57cec5SDimitry Andric handled = true; 18540b57cec5SDimitry Andric } else if (reason == "exec") { 18550b57cec5SDimitry Andric did_exec = true; 18560b57cec5SDimitry Andric thread_sp->SetStopInfo( 18570b57cec5SDimitry Andric StopInfo::CreateStopReasonWithExec(*thread_sp)); 18580b57cec5SDimitry Andric handled = true; 1859fe6060f1SDimitry Andric } else if (reason == "processor trace") { 1860fe6060f1SDimitry Andric thread_sp->SetStopInfo(StopInfo::CreateStopReasonProcessorTrace( 1861fe6060f1SDimitry Andric *thread_sp, description.c_str())); 1862349cc55cSDimitry Andric } else if (reason == "fork") { 1863349cc55cSDimitry Andric StringExtractor desc_extractor(description.c_str()); 1864bdd1243dSDimitry Andric lldb::pid_t child_pid = 1865bdd1243dSDimitry Andric desc_extractor.GetU64(LLDB_INVALID_PROCESS_ID); 1866bdd1243dSDimitry Andric lldb::tid_t child_tid = desc_extractor.GetU64(LLDB_INVALID_THREAD_ID); 1867bdd1243dSDimitry Andric thread_sp->SetStopInfo( 1868bdd1243dSDimitry Andric StopInfo::CreateStopReasonFork(*thread_sp, child_pid, child_tid)); 1869349cc55cSDimitry Andric handled = true; 1870349cc55cSDimitry Andric } else if (reason == "vfork") { 1871349cc55cSDimitry Andric StringExtractor desc_extractor(description.c_str()); 1872bdd1243dSDimitry Andric lldb::pid_t child_pid = 1873bdd1243dSDimitry Andric desc_extractor.GetU64(LLDB_INVALID_PROCESS_ID); 1874bdd1243dSDimitry Andric lldb::tid_t child_tid = desc_extractor.GetU64(LLDB_INVALID_THREAD_ID); 1875349cc55cSDimitry Andric thread_sp->SetStopInfo(StopInfo::CreateStopReasonVFork( 1876349cc55cSDimitry Andric *thread_sp, child_pid, child_tid)); 1877349cc55cSDimitry Andric handled = true; 1878349cc55cSDimitry Andric } else if (reason == "vforkdone") { 1879349cc55cSDimitry Andric thread_sp->SetStopInfo( 1880349cc55cSDimitry Andric StopInfo::CreateStopReasonVForkDone(*thread_sp)); 1881349cc55cSDimitry Andric handled = true; 18820b57cec5SDimitry Andric } 18830b57cec5SDimitry Andric } else if (!signo) { 18840b57cec5SDimitry Andric addr_t pc = thread_sp->GetRegisterContext()->GetPC(); 18850b57cec5SDimitry Andric lldb::BreakpointSiteSP bp_site_sp = 1886bdd1243dSDimitry Andric thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); 18870b57cec5SDimitry Andric 1888*0fca6ea1SDimitry Andric // If a thread is stopped at a breakpoint site, set that as the stop 1889*0fca6ea1SDimitry Andric // reason even if it hasn't executed the breakpoint instruction yet. 1890*0fca6ea1SDimitry Andric // We will silently step over the breakpoint when we resume execution 1891*0fca6ea1SDimitry Andric // and miss the fact that this thread hit the breakpoint. 1892fe6060f1SDimitry Andric if (bp_site_sp && bp_site_sp->ValidForThisThread(*thread_sp)) { 1893bdd1243dSDimitry Andric thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID( 18940b57cec5SDimitry Andric *thread_sp, bp_site_sp->GetID())); 18950b57cec5SDimitry Andric handled = true; 18960b57cec5SDimitry Andric } 18970b57cec5SDimitry Andric } 18980b57cec5SDimitry Andric 18990b57cec5SDimitry Andric if (!handled && signo && !did_exec) { 19000b57cec5SDimitry Andric if (signo == SIGTRAP) { 19010b57cec5SDimitry Andric // Currently we are going to assume SIGTRAP means we are either 19020b57cec5SDimitry Andric // hitting a breakpoint or hardware single stepping. 19030b57cec5SDimitry Andric handled = true; 1904bdd1243dSDimitry Andric addr_t pc = 1905bdd1243dSDimitry Andric thread_sp->GetRegisterContext()->GetPC() + m_breakpoint_pc_offset; 1906bdd1243dSDimitry Andric lldb::BreakpointSiteSP bp_site_sp = 1907bdd1243dSDimitry Andric thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress( 1908bdd1243dSDimitry Andric pc); 19090b57cec5SDimitry Andric 19100b57cec5SDimitry Andric if (bp_site_sp) { 1911bdd1243dSDimitry Andric // If the breakpoint is for this thread, then we'll report the hit, 1912bdd1243dSDimitry Andric // but if it is for another thread, we can just report no reason. 1913bdd1243dSDimitry Andric // We don't need to worry about stepping over the breakpoint here, 1914bdd1243dSDimitry Andric // that will be taken care of when the thread resumes and notices 1915bdd1243dSDimitry Andric // that there's a breakpoint under the pc. 1916fe6060f1SDimitry Andric if (bp_site_sp->ValidForThisThread(*thread_sp)) { 19170b57cec5SDimitry Andric if (m_breakpoint_pc_offset != 0) 19180b57cec5SDimitry Andric thread_sp->GetRegisterContext()->SetPC(pc); 19190b57cec5SDimitry Andric thread_sp->SetStopInfo( 19200b57cec5SDimitry Andric StopInfo::CreateStopReasonWithBreakpointSiteID( 19210b57cec5SDimitry Andric *thread_sp, bp_site_sp->GetID())); 19220b57cec5SDimitry Andric } else { 19230b57cec5SDimitry Andric StopInfoSP invalid_stop_info_sp; 19240b57cec5SDimitry Andric thread_sp->SetStopInfo(invalid_stop_info_sp); 19250b57cec5SDimitry Andric } 19260b57cec5SDimitry Andric } else { 1927bdd1243dSDimitry Andric // If we were stepping then assume the stop was the result of the 1928bdd1243dSDimitry Andric // trace. If we were not stepping then report the SIGTRAP. 1929bdd1243dSDimitry Andric // FIXME: We are still missing the case where we single step over a 1930bdd1243dSDimitry Andric // trap instruction. 19310b57cec5SDimitry Andric if (thread_sp->GetTemporaryResumeState() == eStateStepping) 19320b57cec5SDimitry Andric thread_sp->SetStopInfo( 19330b57cec5SDimitry Andric StopInfo::CreateStopReasonToTrace(*thread_sp)); 19340b57cec5SDimitry Andric else 19350b57cec5SDimitry Andric thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithSignal( 19360b57cec5SDimitry Andric *thread_sp, signo, description.c_str())); 19370b57cec5SDimitry Andric } 19380b57cec5SDimitry Andric } 19390b57cec5SDimitry Andric if (!handled) 19400b57cec5SDimitry Andric thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithSignal( 19410b57cec5SDimitry Andric *thread_sp, signo, description.c_str())); 19420b57cec5SDimitry Andric } 19430b57cec5SDimitry Andric 19440b57cec5SDimitry Andric if (!description.empty()) { 19450b57cec5SDimitry Andric lldb::StopInfoSP stop_info_sp(thread_sp->GetStopInfo()); 19460b57cec5SDimitry Andric if (stop_info_sp) { 19470b57cec5SDimitry Andric const char *stop_info_desc = stop_info_sp->GetDescription(); 19480b57cec5SDimitry Andric if (!stop_info_desc || !stop_info_desc[0]) 19490b57cec5SDimitry Andric stop_info_sp->SetDescription(description.c_str()); 19500b57cec5SDimitry Andric } else { 19510b57cec5SDimitry Andric thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithException( 19520b57cec5SDimitry Andric *thread_sp, description.c_str())); 19530b57cec5SDimitry Andric } 19540b57cec5SDimitry Andric } 19550b57cec5SDimitry Andric } 19560b57cec5SDimitry Andric } 19570b57cec5SDimitry Andric return thread_sp; 19580b57cec5SDimitry Andric } 19590b57cec5SDimitry Andric 19600b57cec5SDimitry Andric lldb::ThreadSP 19610b57cec5SDimitry Andric ProcessGDBRemote::SetThreadStopInfo(StructuredData::Dictionary *thread_dict) { 19625f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_tid("tid"); 19635f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_name("name"); 19645f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_reason("reason"); 19655f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_metype("metype"); 19665f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_medata("medata"); 19675f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_qaddr("qaddr"); 19685f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_dispatch_queue_t( 19695f757f3fSDimitry Andric "dispatch_queue_t"); 19705f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_associated_with_dispatch_queue( 19710b57cec5SDimitry Andric "associated_with_dispatch_queue"); 19725f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_queue_name("qname"); 19735f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_queue_kind("qkind"); 19745f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_queue_serial_number("qserialnum"); 19755f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_registers("registers"); 19765f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_memory("memory"); 19775f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_description("description"); 19785f757f3fSDimitry Andric static constexpr llvm::StringLiteral g_key_signal("signal"); 19790b57cec5SDimitry Andric 19800b57cec5SDimitry Andric // Stop with signal and thread info 19810b57cec5SDimitry Andric lldb::tid_t tid = LLDB_INVALID_THREAD_ID; 19820b57cec5SDimitry Andric uint8_t signo = 0; 19830b57cec5SDimitry Andric std::string value; 19840b57cec5SDimitry Andric std::string thread_name; 19850b57cec5SDimitry Andric std::string reason; 19860b57cec5SDimitry Andric std::string description; 19870b57cec5SDimitry Andric uint32_t exc_type = 0; 19880b57cec5SDimitry Andric std::vector<addr_t> exc_data; 19890b57cec5SDimitry Andric addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS; 19900b57cec5SDimitry Andric ExpeditedRegisterMap expedited_register_map; 19910b57cec5SDimitry Andric bool queue_vars_valid = false; 19920b57cec5SDimitry Andric addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS; 19930b57cec5SDimitry Andric LazyBool associated_with_dispatch_queue = eLazyBoolCalculate; 19940b57cec5SDimitry Andric std::string queue_name; 19950b57cec5SDimitry Andric QueueKind queue_kind = eQueueKindUnknown; 19960b57cec5SDimitry Andric uint64_t queue_serial_number = 0; 19970b57cec5SDimitry Andric // Iterate through all of the thread dictionary key/value pairs from the 19980b57cec5SDimitry Andric // structured data dictionary 19990b57cec5SDimitry Andric 2000349cc55cSDimitry Andric // FIXME: we're silently ignoring invalid data here 20010b57cec5SDimitry Andric thread_dict->ForEach([this, &tid, &expedited_register_map, &thread_name, 20020b57cec5SDimitry Andric &signo, &reason, &description, &exc_type, &exc_data, 20030b57cec5SDimitry Andric &thread_dispatch_qaddr, &queue_vars_valid, 20040b57cec5SDimitry Andric &associated_with_dispatch_queue, &dispatch_queue_t, 20050b57cec5SDimitry Andric &queue_name, &queue_kind, &queue_serial_number]( 20065f757f3fSDimitry Andric llvm::StringRef key, 20070b57cec5SDimitry Andric StructuredData::Object *object) -> bool { 20080b57cec5SDimitry Andric if (key == g_key_tid) { 20090b57cec5SDimitry Andric // thread in big endian hex 201006c3fb27SDimitry Andric tid = object->GetUnsignedIntegerValue(LLDB_INVALID_THREAD_ID); 20110b57cec5SDimitry Andric } else if (key == g_key_metype) { 20120b57cec5SDimitry Andric // exception type in big endian hex 201306c3fb27SDimitry Andric exc_type = object->GetUnsignedIntegerValue(0); 20140b57cec5SDimitry Andric } else if (key == g_key_medata) { 20150b57cec5SDimitry Andric // exception data in big endian hex 20160b57cec5SDimitry Andric StructuredData::Array *array = object->GetAsArray(); 20170b57cec5SDimitry Andric if (array) { 20180b57cec5SDimitry Andric array->ForEach([&exc_data](StructuredData::Object *object) -> bool { 201906c3fb27SDimitry Andric exc_data.push_back(object->GetUnsignedIntegerValue()); 20200b57cec5SDimitry Andric return true; // Keep iterating through all array items 20210b57cec5SDimitry Andric }); 20220b57cec5SDimitry Andric } 20230b57cec5SDimitry Andric } else if (key == g_key_name) { 20245ffd83dbSDimitry Andric thread_name = std::string(object->GetStringValue()); 20250b57cec5SDimitry Andric } else if (key == g_key_qaddr) { 202606c3fb27SDimitry Andric thread_dispatch_qaddr = 202706c3fb27SDimitry Andric object->GetUnsignedIntegerValue(LLDB_INVALID_ADDRESS); 20280b57cec5SDimitry Andric } else if (key == g_key_queue_name) { 20290b57cec5SDimitry Andric queue_vars_valid = true; 20305ffd83dbSDimitry Andric queue_name = std::string(object->GetStringValue()); 20310b57cec5SDimitry Andric } else if (key == g_key_queue_kind) { 20325ffd83dbSDimitry Andric std::string queue_kind_str = std::string(object->GetStringValue()); 20330b57cec5SDimitry Andric if (queue_kind_str == "serial") { 20340b57cec5SDimitry Andric queue_vars_valid = true; 20350b57cec5SDimitry Andric queue_kind = eQueueKindSerial; 20360b57cec5SDimitry Andric } else if (queue_kind_str == "concurrent") { 20370b57cec5SDimitry Andric queue_vars_valid = true; 20380b57cec5SDimitry Andric queue_kind = eQueueKindConcurrent; 20390b57cec5SDimitry Andric } 20400b57cec5SDimitry Andric } else if (key == g_key_queue_serial_number) { 204106c3fb27SDimitry Andric queue_serial_number = object->GetUnsignedIntegerValue(0); 20420b57cec5SDimitry Andric if (queue_serial_number != 0) 20430b57cec5SDimitry Andric queue_vars_valid = true; 20440b57cec5SDimitry Andric } else if (key == g_key_dispatch_queue_t) { 204506c3fb27SDimitry Andric dispatch_queue_t = object->GetUnsignedIntegerValue(0); 20460b57cec5SDimitry Andric if (dispatch_queue_t != 0 && dispatch_queue_t != LLDB_INVALID_ADDRESS) 20470b57cec5SDimitry Andric queue_vars_valid = true; 20480b57cec5SDimitry Andric } else if (key == g_key_associated_with_dispatch_queue) { 20490b57cec5SDimitry Andric queue_vars_valid = true; 20500b57cec5SDimitry Andric bool associated = object->GetBooleanValue(); 20510b57cec5SDimitry Andric if (associated) 20520b57cec5SDimitry Andric associated_with_dispatch_queue = eLazyBoolYes; 20530b57cec5SDimitry Andric else 20540b57cec5SDimitry Andric associated_with_dispatch_queue = eLazyBoolNo; 20550b57cec5SDimitry Andric } else if (key == g_key_reason) { 20565ffd83dbSDimitry Andric reason = std::string(object->GetStringValue()); 20570b57cec5SDimitry Andric } else if (key == g_key_description) { 20585ffd83dbSDimitry Andric description = std::string(object->GetStringValue()); 20590b57cec5SDimitry Andric } else if (key == g_key_registers) { 20600b57cec5SDimitry Andric StructuredData::Dictionary *registers_dict = object->GetAsDictionary(); 20610b57cec5SDimitry Andric 20620b57cec5SDimitry Andric if (registers_dict) { 20630b57cec5SDimitry Andric registers_dict->ForEach( 20645f757f3fSDimitry Andric [&expedited_register_map](llvm::StringRef key, 20650b57cec5SDimitry Andric StructuredData::Object *object) -> bool { 2066349cc55cSDimitry Andric uint32_t reg; 20675f757f3fSDimitry Andric if (llvm::to_integer(key, reg)) 20685ffd83dbSDimitry Andric expedited_register_map[reg] = 20695ffd83dbSDimitry Andric std::string(object->GetStringValue()); 20700b57cec5SDimitry Andric return true; // Keep iterating through all array items 20710b57cec5SDimitry Andric }); 20720b57cec5SDimitry Andric } 20730b57cec5SDimitry Andric } else if (key == g_key_memory) { 20740b57cec5SDimitry Andric StructuredData::Array *array = object->GetAsArray(); 20750b57cec5SDimitry Andric if (array) { 20760b57cec5SDimitry Andric array->ForEach([this](StructuredData::Object *object) -> bool { 20770b57cec5SDimitry Andric StructuredData::Dictionary *mem_cache_dict = 20780b57cec5SDimitry Andric object->GetAsDictionary(); 20790b57cec5SDimitry Andric if (mem_cache_dict) { 20800b57cec5SDimitry Andric lldb::addr_t mem_cache_addr = LLDB_INVALID_ADDRESS; 20810b57cec5SDimitry Andric if (mem_cache_dict->GetValueForKeyAsInteger<lldb::addr_t>( 20820b57cec5SDimitry Andric "address", mem_cache_addr)) { 20830b57cec5SDimitry Andric if (mem_cache_addr != LLDB_INVALID_ADDRESS) { 20840b57cec5SDimitry Andric llvm::StringRef str; 20850b57cec5SDimitry Andric if (mem_cache_dict->GetValueForKeyAsString("bytes", str)) { 20860b57cec5SDimitry Andric StringExtractor bytes(str); 20870b57cec5SDimitry Andric bytes.SetFilePos(0); 20880b57cec5SDimitry Andric 20890b57cec5SDimitry Andric const size_t byte_size = bytes.GetStringRef().size() / 2; 209081ad6265SDimitry Andric WritableDataBufferSP data_buffer_sp( 209181ad6265SDimitry Andric new DataBufferHeap(byte_size, 0)); 20920b57cec5SDimitry Andric const size_t bytes_copied = 20930b57cec5SDimitry Andric bytes.GetHexBytes(data_buffer_sp->GetData(), 0); 20940b57cec5SDimitry Andric if (bytes_copied == byte_size) 20950b57cec5SDimitry Andric m_memory_cache.AddL1CacheData(mem_cache_addr, 20960b57cec5SDimitry Andric data_buffer_sp); 20970b57cec5SDimitry Andric } 20980b57cec5SDimitry Andric } 20990b57cec5SDimitry Andric } 21000b57cec5SDimitry Andric } 21010b57cec5SDimitry Andric return true; // Keep iterating through all array items 21020b57cec5SDimitry Andric }); 21030b57cec5SDimitry Andric } 21040b57cec5SDimitry Andric 21050b57cec5SDimitry Andric } else if (key == g_key_signal) 210606c3fb27SDimitry Andric signo = object->GetUnsignedIntegerValue(LLDB_INVALID_SIGNAL_NUMBER); 21070b57cec5SDimitry Andric return true; // Keep iterating through all dictionary key/value pairs 21080b57cec5SDimitry Andric }); 21090b57cec5SDimitry Andric 21100b57cec5SDimitry Andric return SetThreadStopInfo(tid, expedited_register_map, signo, thread_name, 21110b57cec5SDimitry Andric reason, description, exc_type, exc_data, 21120b57cec5SDimitry Andric thread_dispatch_qaddr, queue_vars_valid, 21130b57cec5SDimitry Andric associated_with_dispatch_queue, dispatch_queue_t, 21140b57cec5SDimitry Andric queue_name, queue_kind, queue_serial_number); 21150b57cec5SDimitry Andric } 21160b57cec5SDimitry Andric 21170b57cec5SDimitry Andric StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) { 2118fe6060f1SDimitry Andric lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID(); 21190b57cec5SDimitry Andric stop_packet.SetFilePos(0); 21200b57cec5SDimitry Andric const char stop_type = stop_packet.GetChar(); 21210b57cec5SDimitry Andric switch (stop_type) { 21220b57cec5SDimitry Andric case 'T': 21230b57cec5SDimitry Andric case 'S': { 21245f757f3fSDimitry Andric // This is a bit of a hack, but it is required. If we did exec, we need to 21250b57cec5SDimitry Andric // clear our thread lists and also know to rebuild our dynamic register 21260b57cec5SDimitry Andric // info before we lookup and threads and populate the expedited register 21270b57cec5SDimitry Andric // values so we need to know this right away so we can cleanup and update 21280b57cec5SDimitry Andric // our registers. 21290b57cec5SDimitry Andric const uint32_t stop_id = GetStopID(); 21300b57cec5SDimitry Andric if (stop_id == 0) { 21310b57cec5SDimitry Andric // Our first stop, make sure we have a process ID, and also make sure we 21320b57cec5SDimitry Andric // know about our registers 2133fe6060f1SDimitry Andric if (GetID() == LLDB_INVALID_PROCESS_ID && pid != LLDB_INVALID_PROCESS_ID) 21340b57cec5SDimitry Andric SetID(pid); 21350b57cec5SDimitry Andric BuildDynamicRegisterInfo(true); 21360b57cec5SDimitry Andric } 21370b57cec5SDimitry Andric // Stop with signal and thread info 2138fe6060f1SDimitry Andric lldb::pid_t stop_pid = LLDB_INVALID_PROCESS_ID; 21390b57cec5SDimitry Andric lldb::tid_t tid = LLDB_INVALID_THREAD_ID; 21400b57cec5SDimitry Andric const uint8_t signo = stop_packet.GetHexU8(); 21410b57cec5SDimitry Andric llvm::StringRef key; 21420b57cec5SDimitry Andric llvm::StringRef value; 21430b57cec5SDimitry Andric std::string thread_name; 21440b57cec5SDimitry Andric std::string reason; 21450b57cec5SDimitry Andric std::string description; 21460b57cec5SDimitry Andric uint32_t exc_type = 0; 21470b57cec5SDimitry Andric std::vector<addr_t> exc_data; 21480b57cec5SDimitry Andric addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS; 21490b57cec5SDimitry Andric bool queue_vars_valid = 21500b57cec5SDimitry Andric false; // says if locals below that start with "queue_" are valid 21510b57cec5SDimitry Andric addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS; 21520b57cec5SDimitry Andric LazyBool associated_with_dispatch_queue = eLazyBoolCalculate; 21530b57cec5SDimitry Andric std::string queue_name; 21540b57cec5SDimitry Andric QueueKind queue_kind = eQueueKindUnknown; 21550b57cec5SDimitry Andric uint64_t queue_serial_number = 0; 21560b57cec5SDimitry Andric ExpeditedRegisterMap expedited_register_map; 21575f757f3fSDimitry Andric AddressableBits addressable_bits; 21580b57cec5SDimitry Andric while (stop_packet.GetNameColonValue(key, value)) { 21590b57cec5SDimitry Andric if (key.compare("metype") == 0) { 21600b57cec5SDimitry Andric // exception type in big endian hex 21610b57cec5SDimitry Andric value.getAsInteger(16, exc_type); 21620b57cec5SDimitry Andric } else if (key.compare("medata") == 0) { 21630b57cec5SDimitry Andric // exception data in big endian hex 21640b57cec5SDimitry Andric uint64_t x; 21650b57cec5SDimitry Andric value.getAsInteger(16, x); 21660b57cec5SDimitry Andric exc_data.push_back(x); 21670b57cec5SDimitry Andric } else if (key.compare("thread") == 0) { 2168fe6060f1SDimitry Andric // thread-id 2169fe6060f1SDimitry Andric StringExtractorGDBRemote thread_id{value}; 2170fe6060f1SDimitry Andric auto pid_tid = thread_id.GetPidTid(pid); 2171fe6060f1SDimitry Andric if (pid_tid) { 2172fe6060f1SDimitry Andric stop_pid = pid_tid->first; 2173fe6060f1SDimitry Andric tid = pid_tid->second; 2174fe6060f1SDimitry Andric } else 21750b57cec5SDimitry Andric tid = LLDB_INVALID_THREAD_ID; 21760b57cec5SDimitry Andric } else if (key.compare("threads") == 0) { 21770b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard( 21780b57cec5SDimitry Andric m_thread_list_real.GetMutex()); 2179fe6060f1SDimitry Andric UpdateThreadIDsFromStopReplyThreadsValue(value); 21800b57cec5SDimitry Andric } else if (key.compare("thread-pcs") == 0) { 21810b57cec5SDimitry Andric m_thread_pcs.clear(); 21820b57cec5SDimitry Andric // A comma separated list of all threads in the current 21830b57cec5SDimitry Andric // process that includes the thread for this stop reply packet 21840b57cec5SDimitry Andric lldb::addr_t pc; 21850b57cec5SDimitry Andric while (!value.empty()) { 21860b57cec5SDimitry Andric llvm::StringRef pc_str; 21870b57cec5SDimitry Andric std::tie(pc_str, value) = value.split(','); 21880b57cec5SDimitry Andric if (pc_str.getAsInteger(16, pc)) 21890b57cec5SDimitry Andric pc = LLDB_INVALID_ADDRESS; 21900b57cec5SDimitry Andric m_thread_pcs.push_back(pc); 21910b57cec5SDimitry Andric } 21920b57cec5SDimitry Andric } else if (key.compare("jstopinfo") == 0) { 21930b57cec5SDimitry Andric StringExtractor json_extractor(value); 21940b57cec5SDimitry Andric std::string json; 21950b57cec5SDimitry Andric // Now convert the HEX bytes into a string value 21960b57cec5SDimitry Andric json_extractor.GetHexByteString(json); 21970b57cec5SDimitry Andric 21980b57cec5SDimitry Andric // This JSON contains thread IDs and thread stop info for all threads. 21990b57cec5SDimitry Andric // It doesn't contain expedited registers, memory or queue info. 22000b57cec5SDimitry Andric m_jstopinfo_sp = StructuredData::ParseJSON(json); 22010b57cec5SDimitry Andric } else if (key.compare("hexname") == 0) { 22020b57cec5SDimitry Andric StringExtractor name_extractor(value); 22030b57cec5SDimitry Andric std::string name; 22040b57cec5SDimitry Andric // Now convert the HEX bytes into a string value 22050b57cec5SDimitry Andric name_extractor.GetHexByteString(thread_name); 22060b57cec5SDimitry Andric } else if (key.compare("name") == 0) { 22075ffd83dbSDimitry Andric thread_name = std::string(value); 22080b57cec5SDimitry Andric } else if (key.compare("qaddr") == 0) { 22090b57cec5SDimitry Andric value.getAsInteger(16, thread_dispatch_qaddr); 22100b57cec5SDimitry Andric } else if (key.compare("dispatch_queue_t") == 0) { 22110b57cec5SDimitry Andric queue_vars_valid = true; 22120b57cec5SDimitry Andric value.getAsInteger(16, dispatch_queue_t); 22130b57cec5SDimitry Andric } else if (key.compare("qname") == 0) { 22140b57cec5SDimitry Andric queue_vars_valid = true; 22150b57cec5SDimitry Andric StringExtractor name_extractor(value); 22160b57cec5SDimitry Andric // Now convert the HEX bytes into a string value 22170b57cec5SDimitry Andric name_extractor.GetHexByteString(queue_name); 22180b57cec5SDimitry Andric } else if (key.compare("qkind") == 0) { 22190b57cec5SDimitry Andric queue_kind = llvm::StringSwitch<QueueKind>(value) 22200b57cec5SDimitry Andric .Case("serial", eQueueKindSerial) 22210b57cec5SDimitry Andric .Case("concurrent", eQueueKindConcurrent) 22220b57cec5SDimitry Andric .Default(eQueueKindUnknown); 22230b57cec5SDimitry Andric queue_vars_valid = queue_kind != eQueueKindUnknown; 22240b57cec5SDimitry Andric } else if (key.compare("qserialnum") == 0) { 22250b57cec5SDimitry Andric if (!value.getAsInteger(0, queue_serial_number)) 22260b57cec5SDimitry Andric queue_vars_valid = true; 22270b57cec5SDimitry Andric } else if (key.compare("reason") == 0) { 22285ffd83dbSDimitry Andric reason = std::string(value); 22290b57cec5SDimitry Andric } else if (key.compare("description") == 0) { 22300b57cec5SDimitry Andric StringExtractor desc_extractor(value); 22310b57cec5SDimitry Andric // Now convert the HEX bytes into a string value 22320b57cec5SDimitry Andric desc_extractor.GetHexByteString(description); 22330b57cec5SDimitry Andric } else if (key.compare("memory") == 0) { 22340b57cec5SDimitry Andric // Expedited memory. GDB servers can choose to send back expedited 22350b57cec5SDimitry Andric // memory that can populate the L1 memory cache in the process so that 22360b57cec5SDimitry Andric // things like the frame pointer backchain can be expedited. This will 22370b57cec5SDimitry Andric // help stack backtracing be more efficient by not having to send as 22380b57cec5SDimitry Andric // many memory read requests down the remote GDB server. 22390b57cec5SDimitry Andric 22400b57cec5SDimitry Andric // Key/value pair format: memory:<addr>=<bytes>; 22410b57cec5SDimitry Andric // <addr> is a number whose base will be interpreted by the prefix: 22420b57cec5SDimitry Andric // "0x[0-9a-fA-F]+" for hex 22430b57cec5SDimitry Andric // "0[0-7]+" for octal 22440b57cec5SDimitry Andric // "[1-9]+" for decimal 22450b57cec5SDimitry Andric // <bytes> is native endian ASCII hex bytes just like the register 22460b57cec5SDimitry Andric // values 22470b57cec5SDimitry Andric llvm::StringRef addr_str, bytes_str; 22480b57cec5SDimitry Andric std::tie(addr_str, bytes_str) = value.split('='); 22490b57cec5SDimitry Andric if (!addr_str.empty() && !bytes_str.empty()) { 22500b57cec5SDimitry Andric lldb::addr_t mem_cache_addr = LLDB_INVALID_ADDRESS; 22510b57cec5SDimitry Andric if (!addr_str.getAsInteger(0, mem_cache_addr)) { 22520b57cec5SDimitry Andric StringExtractor bytes(bytes_str); 22530b57cec5SDimitry Andric const size_t byte_size = bytes.GetBytesLeft() / 2; 225481ad6265SDimitry Andric WritableDataBufferSP data_buffer_sp( 225581ad6265SDimitry Andric new DataBufferHeap(byte_size, 0)); 22560b57cec5SDimitry Andric const size_t bytes_copied = 22570b57cec5SDimitry Andric bytes.GetHexBytes(data_buffer_sp->GetData(), 0); 22580b57cec5SDimitry Andric if (bytes_copied == byte_size) 22590b57cec5SDimitry Andric m_memory_cache.AddL1CacheData(mem_cache_addr, data_buffer_sp); 22600b57cec5SDimitry Andric } 22610b57cec5SDimitry Andric } 22620b57cec5SDimitry Andric } else if (key.compare("watch") == 0 || key.compare("rwatch") == 0 || 22630b57cec5SDimitry Andric key.compare("awatch") == 0) { 22640b57cec5SDimitry Andric // Support standard GDB remote stop reply packet 'TAAwatch:addr' 22650b57cec5SDimitry Andric lldb::addr_t wp_addr = LLDB_INVALID_ADDRESS; 22660b57cec5SDimitry Andric value.getAsInteger(16, wp_addr); 22670b57cec5SDimitry Andric 22685f757f3fSDimitry Andric WatchpointResourceSP wp_resource_sp = 22695f757f3fSDimitry Andric m_watchpoint_resource_list.FindByAddress(wp_addr); 22700b57cec5SDimitry Andric 227106c3fb27SDimitry Andric // Rewrite gdb standard watch/rwatch/awatch to 227206c3fb27SDimitry Andric // "reason:watchpoint" + "description:ADDR", 227306c3fb27SDimitry Andric // which is parsed in SetThreadStopInfo. 22740b57cec5SDimitry Andric reason = "watchpoint"; 22750b57cec5SDimitry Andric StreamString ostr; 22765f757f3fSDimitry Andric ostr.Printf("%" PRIu64, wp_addr); 22775ffd83dbSDimitry Andric description = std::string(ostr.GetString()); 22780b57cec5SDimitry Andric } else if (key.compare("library") == 0) { 22799dba64beSDimitry Andric auto error = LoadModules(); 22809dba64beSDimitry Andric if (error) { 22811fd87a68SDimitry Andric Log *log(GetLog(GDBRLog::Process)); 22829dba64beSDimitry Andric LLDB_LOG_ERROR(log, std::move(error), "Failed to load modules: {0}"); 22839dba64beSDimitry Andric } 2284349cc55cSDimitry Andric } else if (key.compare("fork") == 0 || key.compare("vfork") == 0) { 2285349cc55cSDimitry Andric // fork includes child pid/tid in thread-id format 2286349cc55cSDimitry Andric StringExtractorGDBRemote thread_id{value}; 2287349cc55cSDimitry Andric auto pid_tid = thread_id.GetPidTid(LLDB_INVALID_PROCESS_ID); 2288349cc55cSDimitry Andric if (!pid_tid) { 22891fd87a68SDimitry Andric Log *log(GetLog(GDBRLog::Process)); 2290349cc55cSDimitry Andric LLDB_LOG(log, "Invalid PID/TID to fork: {0}", value); 2291349cc55cSDimitry Andric pid_tid = {{LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID}}; 2292349cc55cSDimitry Andric } 2293349cc55cSDimitry Andric 2294349cc55cSDimitry Andric reason = key.str(); 2295349cc55cSDimitry Andric StreamString ostr; 2296349cc55cSDimitry Andric ostr.Printf("%" PRIu64 " %" PRIu64, pid_tid->first, pid_tid->second); 2297349cc55cSDimitry Andric description = std::string(ostr.GetString()); 229806c3fb27SDimitry Andric } else if (key.compare("addressing_bits") == 0) { 229906c3fb27SDimitry Andric uint64_t addressing_bits; 230006c3fb27SDimitry Andric if (!value.getAsInteger(0, addressing_bits)) { 23015f757f3fSDimitry Andric addressable_bits.SetAddressableBits(addressing_bits); 23025f757f3fSDimitry Andric } 23035f757f3fSDimitry Andric } else if (key.compare("low_mem_addressing_bits") == 0) { 23045f757f3fSDimitry Andric uint64_t addressing_bits; 23055f757f3fSDimitry Andric if (!value.getAsInteger(0, addressing_bits)) { 23065f757f3fSDimitry Andric addressable_bits.SetLowmemAddressableBits(addressing_bits); 23075f757f3fSDimitry Andric } 23085f757f3fSDimitry Andric } else if (key.compare("high_mem_addressing_bits") == 0) { 23095f757f3fSDimitry Andric uint64_t addressing_bits; 23105f757f3fSDimitry Andric if (!value.getAsInteger(0, addressing_bits)) { 23115f757f3fSDimitry Andric addressable_bits.SetHighmemAddressableBits(addressing_bits); 231206c3fb27SDimitry Andric } 23130b57cec5SDimitry Andric } else if (key.size() == 2 && ::isxdigit(key[0]) && ::isxdigit(key[1])) { 23140b57cec5SDimitry Andric uint32_t reg = UINT32_MAX; 23150b57cec5SDimitry Andric if (!key.getAsInteger(16, reg)) 23165ffd83dbSDimitry Andric expedited_register_map[reg] = std::string(std::move(value)); 23170b57cec5SDimitry Andric } 23180b57cec5SDimitry Andric } 23190b57cec5SDimitry Andric 2320fe6060f1SDimitry Andric if (stop_pid != LLDB_INVALID_PROCESS_ID && stop_pid != pid) { 23211fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 2322fe6060f1SDimitry Andric LLDB_LOG(log, 2323fe6060f1SDimitry Andric "Received stop for incorrect PID = {0} (inferior PID = {1})", 2324fe6060f1SDimitry Andric stop_pid, pid); 2325fe6060f1SDimitry Andric return eStateInvalid; 2326fe6060f1SDimitry Andric } 2327fe6060f1SDimitry Andric 23280b57cec5SDimitry Andric if (tid == LLDB_INVALID_THREAD_ID) { 23290b57cec5SDimitry Andric // A thread id may be invalid if the response is old style 'S' packet 23300b57cec5SDimitry Andric // which does not provide the 23310b57cec5SDimitry Andric // thread information. So update the thread list and choose the first 23320b57cec5SDimitry Andric // one. 23330b57cec5SDimitry Andric UpdateThreadIDList(); 23340b57cec5SDimitry Andric 23350b57cec5SDimitry Andric if (!m_thread_ids.empty()) { 23360b57cec5SDimitry Andric tid = m_thread_ids.front(); 23370b57cec5SDimitry Andric } 23380b57cec5SDimitry Andric } 23390b57cec5SDimitry Andric 2340*0fca6ea1SDimitry Andric SetAddressableBitMasks(addressable_bits); 23415f757f3fSDimitry Andric 23420b57cec5SDimitry Andric ThreadSP thread_sp = SetThreadStopInfo( 23430b57cec5SDimitry Andric tid, expedited_register_map, signo, thread_name, reason, description, 23440b57cec5SDimitry Andric exc_type, exc_data, thread_dispatch_qaddr, queue_vars_valid, 23450b57cec5SDimitry Andric associated_with_dispatch_queue, dispatch_queue_t, queue_name, 23460b57cec5SDimitry Andric queue_kind, queue_serial_number); 23470b57cec5SDimitry Andric 23480b57cec5SDimitry Andric return eStateStopped; 23490b57cec5SDimitry Andric } break; 23500b57cec5SDimitry Andric 23510b57cec5SDimitry Andric case 'W': 23520b57cec5SDimitry Andric case 'X': 23530b57cec5SDimitry Andric // process exited 23540b57cec5SDimitry Andric return eStateExited; 23550b57cec5SDimitry Andric 23560b57cec5SDimitry Andric default: 23570b57cec5SDimitry Andric break; 23580b57cec5SDimitry Andric } 23590b57cec5SDimitry Andric return eStateInvalid; 23600b57cec5SDimitry Andric } 23610b57cec5SDimitry Andric 23620b57cec5SDimitry Andric void ProcessGDBRemote::RefreshStateAfterStop() { 23630b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex()); 23640b57cec5SDimitry Andric 23650b57cec5SDimitry Andric m_thread_ids.clear(); 23660b57cec5SDimitry Andric m_thread_pcs.clear(); 2367480093f4SDimitry Andric 23680b57cec5SDimitry Andric // Set the thread stop info. It might have a "threads" key whose value is a 23690b57cec5SDimitry Andric // list of all thread IDs in the current process, so m_thread_ids might get 23700b57cec5SDimitry Andric // set. 23710b57cec5SDimitry Andric // Check to see if SetThreadStopInfo() filled in m_thread_ids? 23720b57cec5SDimitry Andric if (m_thread_ids.empty()) { 23730b57cec5SDimitry Andric // No, we need to fetch the thread list manually 23740b57cec5SDimitry Andric UpdateThreadIDList(); 23750b57cec5SDimitry Andric } 2376480093f4SDimitry Andric 23770b57cec5SDimitry Andric // We might set some stop info's so make sure the thread list is up to 23780b57cec5SDimitry Andric // date before we do that or we might overwrite what was computed here. 23790b57cec5SDimitry Andric UpdateThreadListIfNeeded(); 23800b57cec5SDimitry Andric 2381349cc55cSDimitry Andric if (m_last_stop_packet) 2382349cc55cSDimitry Andric SetThreadStopInfo(*m_last_stop_packet); 2383349cc55cSDimitry Andric m_last_stop_packet.reset(); 23840b57cec5SDimitry Andric 23850b57cec5SDimitry Andric // If we have queried for a default thread id 23860b57cec5SDimitry Andric if (m_initial_tid != LLDB_INVALID_THREAD_ID) { 23870b57cec5SDimitry Andric m_thread_list.SetSelectedThreadByID(m_initial_tid); 23880b57cec5SDimitry Andric m_initial_tid = LLDB_INVALID_THREAD_ID; 23890b57cec5SDimitry Andric } 23900b57cec5SDimitry Andric 23910b57cec5SDimitry Andric // Let all threads recover from stopping and do any clean up based on the 23920b57cec5SDimitry Andric // previous thread state (if any). 23930b57cec5SDimitry Andric m_thread_list_real.RefreshStateAfterStop(); 23940b57cec5SDimitry Andric } 23950b57cec5SDimitry Andric 23960b57cec5SDimitry Andric Status ProcessGDBRemote::DoHalt(bool &caused_stop) { 23970b57cec5SDimitry Andric Status error; 23980b57cec5SDimitry Andric 23990b57cec5SDimitry Andric if (m_public_state.GetValue() == eStateAttaching) { 24005f757f3fSDimitry Andric // We are being asked to halt during an attach. We used to just close our 24015f757f3fSDimitry Andric // file handle and debugserver will go away, but with remote proxies, it 24025f757f3fSDimitry Andric // is better to send a positive signal, so let's send the interrupt first... 24035f757f3fSDimitry Andric caused_stop = m_gdb_comm.Interrupt(GetInterruptTimeout()); 24040b57cec5SDimitry Andric m_gdb_comm.Disconnect(); 24050b57cec5SDimitry Andric } else 2406fe6060f1SDimitry Andric caused_stop = m_gdb_comm.Interrupt(GetInterruptTimeout()); 24070b57cec5SDimitry Andric return error; 24080b57cec5SDimitry Andric } 24090b57cec5SDimitry Andric 24100b57cec5SDimitry Andric Status ProcessGDBRemote::DoDetach(bool keep_stopped) { 24110b57cec5SDimitry Andric Status error; 24121fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 24139dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::DoDetach(keep_stopped: %i)", keep_stopped); 24140b57cec5SDimitry Andric 24150b57cec5SDimitry Andric error = m_gdb_comm.Detach(keep_stopped); 24160b57cec5SDimitry Andric if (log) { 24170b57cec5SDimitry Andric if (error.Success()) 24180b57cec5SDimitry Andric log->PutCString( 24190b57cec5SDimitry Andric "ProcessGDBRemote::DoDetach() detach packet sent successfully"); 24200b57cec5SDimitry Andric else 24219dba64beSDimitry Andric LLDB_LOGF(log, 24229dba64beSDimitry Andric "ProcessGDBRemote::DoDetach() detach packet send failed: %s", 24230b57cec5SDimitry Andric error.AsCString() ? error.AsCString() : "<unknown error>"); 24240b57cec5SDimitry Andric } 24250b57cec5SDimitry Andric 24260b57cec5SDimitry Andric if (!error.Success()) 24270b57cec5SDimitry Andric return error; 24280b57cec5SDimitry Andric 24290b57cec5SDimitry Andric // Sleep for one second to let the process get all detached... 24300b57cec5SDimitry Andric StopAsyncThread(); 24310b57cec5SDimitry Andric 24320b57cec5SDimitry Andric SetPrivateState(eStateDetached); 24330b57cec5SDimitry Andric ResumePrivateStateThread(); 24340b57cec5SDimitry Andric 24350b57cec5SDimitry Andric // KillDebugserverProcess (); 24360b57cec5SDimitry Andric return error; 24370b57cec5SDimitry Andric } 24380b57cec5SDimitry Andric 24390b57cec5SDimitry Andric Status ProcessGDBRemote::DoDestroy() { 24401fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 24419dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::DoDestroy()"); 24420b57cec5SDimitry Andric 24430b57cec5SDimitry Andric // Interrupt if our inferior is running... 24440b57cec5SDimitry Andric int exit_status = SIGABRT; 24450b57cec5SDimitry Andric std::string exit_string; 24460b57cec5SDimitry Andric 24470b57cec5SDimitry Andric if (m_gdb_comm.IsConnected()) { 24480b57cec5SDimitry Andric if (m_public_state.GetValue() != eStateAttaching) { 2449972a253aSDimitry Andric llvm::Expected<int> kill_res = m_gdb_comm.KillProcess(GetID()); 24500b57cec5SDimitry Andric 2451972a253aSDimitry Andric if (kill_res) { 2452972a253aSDimitry Andric exit_status = kill_res.get(); 24530b57cec5SDimitry Andric #if defined(__APPLE__) 24540b57cec5SDimitry Andric // For Native processes on Mac OS X, we launch through the Host 24550b57cec5SDimitry Andric // Platform, then hand the process off to debugserver, which becomes 24560b57cec5SDimitry Andric // the parent process through "PT_ATTACH". Then when we go to kill 24570b57cec5SDimitry Andric // the process on Mac OS X we call ptrace(PT_KILL) to kill it, then 24580b57cec5SDimitry Andric // we call waitpid which returns with no error and the correct 24590b57cec5SDimitry Andric // status. But amusingly enough that doesn't seem to actually reap 24600b57cec5SDimitry Andric // the process, but instead it is left around as a Zombie. Probably 24610b57cec5SDimitry Andric // the kernel is in the process of switching ownership back to lldb 24620b57cec5SDimitry Andric // which was the original parent, and gets confused in the handoff. 24630b57cec5SDimitry Andric // Anyway, so call waitpid here to finally reap it. 24640b57cec5SDimitry Andric PlatformSP platform_sp(GetTarget().GetPlatform()); 24650b57cec5SDimitry Andric if (platform_sp && platform_sp->IsHost()) { 24660b57cec5SDimitry Andric int status; 24670b57cec5SDimitry Andric ::pid_t reap_pid; 24680b57cec5SDimitry Andric reap_pid = waitpid(GetID(), &status, WNOHANG); 24699dba64beSDimitry Andric LLDB_LOGF(log, "Reaped pid: %d, status: %d.\n", reap_pid, status); 24700b57cec5SDimitry Andric } 24710b57cec5SDimitry Andric #endif 24720b57cec5SDimitry Andric ClearThreadIDList(); 2473972a253aSDimitry Andric exit_string.assign("killed"); 24740b57cec5SDimitry Andric } else { 2475972a253aSDimitry Andric exit_string.assign(llvm::toString(kill_res.takeError())); 24760b57cec5SDimitry Andric } 24770b57cec5SDimitry Andric } else { 24780b57cec5SDimitry Andric exit_string.assign("killed or interrupted while attaching."); 24790b57cec5SDimitry Andric } 24800b57cec5SDimitry Andric } else { 24810b57cec5SDimitry Andric // If we missed setting the exit status on the way out, do it here. 24820b57cec5SDimitry Andric // NB set exit status can be called multiple times, the first one sets the 24830b57cec5SDimitry Andric // status. 24840b57cec5SDimitry Andric exit_string.assign("destroying when not connected to debugserver"); 24850b57cec5SDimitry Andric } 24860b57cec5SDimitry Andric 24870b57cec5SDimitry Andric SetExitStatus(exit_status, exit_string.c_str()); 24880b57cec5SDimitry Andric 24890b57cec5SDimitry Andric StopAsyncThread(); 24900b57cec5SDimitry Andric KillDebugserverProcess(); 2491972a253aSDimitry Andric return Status(); 24920b57cec5SDimitry Andric } 24930b57cec5SDimitry Andric 24940b57cec5SDimitry Andric void ProcessGDBRemote::SetLastStopPacket( 24950b57cec5SDimitry Andric const StringExtractorGDBRemote &response) { 24960b57cec5SDimitry Andric const bool did_exec = 24970b57cec5SDimitry Andric response.GetStringRef().find(";reason:exec;") != std::string::npos; 24980b57cec5SDimitry Andric if (did_exec) { 24991fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 25009dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::SetLastStopPacket () - detected exec"); 25010b57cec5SDimitry Andric 25020b57cec5SDimitry Andric m_thread_list_real.Clear(); 25030b57cec5SDimitry Andric m_thread_list.Clear(); 25040b57cec5SDimitry Andric BuildDynamicRegisterInfo(true); 25050b57cec5SDimitry Andric m_gdb_comm.ResetDiscoverableSettings(did_exec); 25060b57cec5SDimitry Andric } 25070b57cec5SDimitry Andric 2508349cc55cSDimitry Andric m_last_stop_packet = response; 25090b57cec5SDimitry Andric } 25100b57cec5SDimitry Andric 25110b57cec5SDimitry Andric void ProcessGDBRemote::SetUnixSignals(const UnixSignalsSP &signals_sp) { 25120b57cec5SDimitry Andric Process::SetUnixSignals(std::make_shared<GDBRemoteSignals>(signals_sp)); 25130b57cec5SDimitry Andric } 25140b57cec5SDimitry Andric 25150b57cec5SDimitry Andric // Process Queries 25160b57cec5SDimitry Andric 25170b57cec5SDimitry Andric bool ProcessGDBRemote::IsAlive() { 25180b57cec5SDimitry Andric return m_gdb_comm.IsConnected() && Process::IsAlive(); 25190b57cec5SDimitry Andric } 25200b57cec5SDimitry Andric 25210b57cec5SDimitry Andric addr_t ProcessGDBRemote::GetImageInfoAddress() { 25220b57cec5SDimitry Andric // request the link map address via the $qShlibInfoAddr packet 25230b57cec5SDimitry Andric lldb::addr_t addr = m_gdb_comm.GetShlibInfoAddr(); 25240b57cec5SDimitry Andric 25250b57cec5SDimitry Andric // the loaded module list can also provides a link map address 25260b57cec5SDimitry Andric if (addr == LLDB_INVALID_ADDRESS) { 25279dba64beSDimitry Andric llvm::Expected<LoadedModuleInfoList> list = GetLoadedModuleList(); 25289dba64beSDimitry Andric if (!list) { 25291fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 2530e8d8bef9SDimitry Andric LLDB_LOG_ERROR(log, list.takeError(), "Failed to read module list: {0}."); 25319dba64beSDimitry Andric } else { 25329dba64beSDimitry Andric addr = list->m_link_map; 25339dba64beSDimitry Andric } 25340b57cec5SDimitry Andric } 25350b57cec5SDimitry Andric 25360b57cec5SDimitry Andric return addr; 25370b57cec5SDimitry Andric } 25380b57cec5SDimitry Andric 25390b57cec5SDimitry Andric void ProcessGDBRemote::WillPublicStop() { 25400b57cec5SDimitry Andric // See if the GDB remote client supports the JSON threads info. If so, we 25410b57cec5SDimitry Andric // gather stop info for all threads, expedited registers, expedited memory, 25420b57cec5SDimitry Andric // runtime queue information (iOS and MacOSX only), and more. Expediting 25430b57cec5SDimitry Andric // memory will help stack backtracing be much faster. Expediting registers 25440b57cec5SDimitry Andric // will make sure we don't have to read the thread registers for GPRs. 25450b57cec5SDimitry Andric m_jthreadsinfo_sp = m_gdb_comm.GetThreadsInfo(); 25460b57cec5SDimitry Andric 25470b57cec5SDimitry Andric if (m_jthreadsinfo_sp) { 25480b57cec5SDimitry Andric // Now set the stop info for each thread and also expedite any registers 25490b57cec5SDimitry Andric // and memory that was in the jThreadsInfo response. 25500b57cec5SDimitry Andric StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray(); 25510b57cec5SDimitry Andric if (thread_infos) { 25520b57cec5SDimitry Andric const size_t n = thread_infos->GetSize(); 25530b57cec5SDimitry Andric for (size_t i = 0; i < n; ++i) { 25540b57cec5SDimitry Andric StructuredData::Dictionary *thread_dict = 25550b57cec5SDimitry Andric thread_infos->GetItemAtIndex(i)->GetAsDictionary(); 25560b57cec5SDimitry Andric if (thread_dict) 25570b57cec5SDimitry Andric SetThreadStopInfo(thread_dict); 25580b57cec5SDimitry Andric } 25590b57cec5SDimitry Andric } 25600b57cec5SDimitry Andric } 25610b57cec5SDimitry Andric } 25620b57cec5SDimitry Andric 25630b57cec5SDimitry Andric // Process Memory 25640b57cec5SDimitry Andric size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size, 25650b57cec5SDimitry Andric Status &error) { 25660b57cec5SDimitry Andric GetMaxMemorySize(); 25670b57cec5SDimitry Andric bool binary_memory_read = m_gdb_comm.GetxPacketSupported(); 25680b57cec5SDimitry Andric // M and m packets take 2 bytes for 1 byte of memory 25690b57cec5SDimitry Andric size_t max_memory_size = 25700b57cec5SDimitry Andric binary_memory_read ? m_max_memory_size : m_max_memory_size / 2; 25710b57cec5SDimitry Andric if (size > max_memory_size) { 25720b57cec5SDimitry Andric // Keep memory read sizes down to a sane limit. This function will be 25730b57cec5SDimitry Andric // called multiple times in order to complete the task by 25740b57cec5SDimitry Andric // lldb_private::Process so it is ok to do this. 25750b57cec5SDimitry Andric size = max_memory_size; 25760b57cec5SDimitry Andric } 25770b57cec5SDimitry Andric 25780b57cec5SDimitry Andric char packet[64]; 25790b57cec5SDimitry Andric int packet_len; 25800b57cec5SDimitry Andric packet_len = ::snprintf(packet, sizeof(packet), "%c%" PRIx64 ",%" PRIx64, 25810b57cec5SDimitry Andric binary_memory_read ? 'x' : 'm', (uint64_t)addr, 25820b57cec5SDimitry Andric (uint64_t)size); 25830b57cec5SDimitry Andric assert(packet_len + 1 < (int)sizeof(packet)); 25840b57cec5SDimitry Andric UNUSED_IF_ASSERT_DISABLED(packet_len); 25850b57cec5SDimitry Andric StringExtractorGDBRemote response; 2586fe6060f1SDimitry Andric if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response, 2587fe6060f1SDimitry Andric GetInterruptTimeout()) == 25880b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult::Success) { 25890b57cec5SDimitry Andric if (response.IsNormalResponse()) { 25900b57cec5SDimitry Andric error.Clear(); 25910b57cec5SDimitry Andric if (binary_memory_read) { 25920b57cec5SDimitry Andric // The lower level GDBRemoteCommunication packet receive layer has 25930b57cec5SDimitry Andric // already de-quoted any 0x7d character escaping that was present in 25940b57cec5SDimitry Andric // the packet 25950b57cec5SDimitry Andric 25960b57cec5SDimitry Andric size_t data_received_size = response.GetBytesLeft(); 25970b57cec5SDimitry Andric if (data_received_size > size) { 25980b57cec5SDimitry Andric // Don't write past the end of BUF if the remote debug server gave us 25990b57cec5SDimitry Andric // too much data for some reason. 26000b57cec5SDimitry Andric data_received_size = size; 26010b57cec5SDimitry Andric } 26020b57cec5SDimitry Andric memcpy(buf, response.GetStringRef().data(), data_received_size); 26030b57cec5SDimitry Andric return data_received_size; 26040b57cec5SDimitry Andric } else { 26050b57cec5SDimitry Andric return response.GetHexBytes( 26060b57cec5SDimitry Andric llvm::MutableArrayRef<uint8_t>((uint8_t *)buf, size), '\xdd'); 26070b57cec5SDimitry Andric } 26080b57cec5SDimitry Andric } else if (response.IsErrorResponse()) 26090b57cec5SDimitry Andric error.SetErrorStringWithFormat("memory read failed for 0x%" PRIx64, addr); 26100b57cec5SDimitry Andric else if (response.IsUnsupportedResponse()) 26110b57cec5SDimitry Andric error.SetErrorStringWithFormat( 26120b57cec5SDimitry Andric "GDB server does not support reading memory"); 26130b57cec5SDimitry Andric else 26140b57cec5SDimitry Andric error.SetErrorStringWithFormat( 26150b57cec5SDimitry Andric "unexpected response to GDB server memory read packet '%s': '%s'", 26169dba64beSDimitry Andric packet, response.GetStringRef().data()); 26170b57cec5SDimitry Andric } else { 26180b57cec5SDimitry Andric error.SetErrorStringWithFormat("failed to send packet: '%s'", packet); 26190b57cec5SDimitry Andric } 26200b57cec5SDimitry Andric return 0; 26210b57cec5SDimitry Andric } 26220b57cec5SDimitry Andric 2623fe6060f1SDimitry Andric bool ProcessGDBRemote::SupportsMemoryTagging() { 2624fe6060f1SDimitry Andric return m_gdb_comm.GetMemoryTaggingSupported(); 2625fe6060f1SDimitry Andric } 2626fe6060f1SDimitry Andric 2627fe6060f1SDimitry Andric llvm::Expected<std::vector<uint8_t>> 2628fe6060f1SDimitry Andric ProcessGDBRemote::DoReadMemoryTags(lldb::addr_t addr, size_t len, 2629fe6060f1SDimitry Andric int32_t type) { 2630fe6060f1SDimitry Andric // By this point ReadMemoryTags has validated that tagging is enabled 2631fe6060f1SDimitry Andric // for this target/process/address. 2632fe6060f1SDimitry Andric DataBufferSP buffer_sp = m_gdb_comm.ReadMemoryTags(addr, len, type); 2633fe6060f1SDimitry Andric if (!buffer_sp) { 2634fe6060f1SDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 2635fe6060f1SDimitry Andric "Error reading memory tags from remote"); 2636fe6060f1SDimitry Andric } 2637fe6060f1SDimitry Andric 2638fe6060f1SDimitry Andric // Return the raw tag data 2639fe6060f1SDimitry Andric llvm::ArrayRef<uint8_t> tag_data = buffer_sp->GetData(); 2640fe6060f1SDimitry Andric std::vector<uint8_t> got; 2641fe6060f1SDimitry Andric got.reserve(tag_data.size()); 2642fe6060f1SDimitry Andric std::copy(tag_data.begin(), tag_data.end(), std::back_inserter(got)); 2643fe6060f1SDimitry Andric return got; 2644fe6060f1SDimitry Andric } 2645fe6060f1SDimitry Andric 2646fe6060f1SDimitry Andric Status ProcessGDBRemote::DoWriteMemoryTags(lldb::addr_t addr, size_t len, 2647fe6060f1SDimitry Andric int32_t type, 2648fe6060f1SDimitry Andric const std::vector<uint8_t> &tags) { 2649fe6060f1SDimitry Andric // By now WriteMemoryTags should have validated that tagging is enabled 2650fe6060f1SDimitry Andric // for this target/process. 2651fe6060f1SDimitry Andric return m_gdb_comm.WriteMemoryTags(addr, len, type, tags); 2652fe6060f1SDimitry Andric } 2653fe6060f1SDimitry Andric 26540b57cec5SDimitry Andric Status ProcessGDBRemote::WriteObjectFile( 26550b57cec5SDimitry Andric std::vector<ObjectFile::LoadableData> entries) { 26560b57cec5SDimitry Andric Status error; 26570b57cec5SDimitry Andric // Sort the entries by address because some writes, like those to flash 26580b57cec5SDimitry Andric // memory, must happen in order of increasing address. 26590b57cec5SDimitry Andric std::stable_sort( 26600b57cec5SDimitry Andric std::begin(entries), std::end(entries), 26610b57cec5SDimitry Andric [](const ObjectFile::LoadableData a, const ObjectFile::LoadableData b) { 26620b57cec5SDimitry Andric return a.Dest < b.Dest; 26630b57cec5SDimitry Andric }); 26640b57cec5SDimitry Andric m_allow_flash_writes = true; 26650b57cec5SDimitry Andric error = Process::WriteObjectFile(entries); 26660b57cec5SDimitry Andric if (error.Success()) 26670b57cec5SDimitry Andric error = FlashDone(); 26680b57cec5SDimitry Andric else 26690b57cec5SDimitry Andric // Even though some of the writing failed, try to send a flash done if some 26700b57cec5SDimitry Andric // of the writing succeeded so the flash state is reset to normal, but 26710b57cec5SDimitry Andric // don't stomp on the error status that was set in the write failure since 26720b57cec5SDimitry Andric // that's the one we want to report back. 26730b57cec5SDimitry Andric FlashDone(); 26740b57cec5SDimitry Andric m_allow_flash_writes = false; 26750b57cec5SDimitry Andric return error; 26760b57cec5SDimitry Andric } 26770b57cec5SDimitry Andric 26780b57cec5SDimitry Andric bool ProcessGDBRemote::HasErased(FlashRange range) { 26790b57cec5SDimitry Andric auto size = m_erased_flash_ranges.GetSize(); 26800b57cec5SDimitry Andric for (size_t i = 0; i < size; ++i) 26810b57cec5SDimitry Andric if (m_erased_flash_ranges.GetEntryAtIndex(i)->Contains(range)) 26820b57cec5SDimitry Andric return true; 26830b57cec5SDimitry Andric return false; 26840b57cec5SDimitry Andric } 26850b57cec5SDimitry Andric 26860b57cec5SDimitry Andric Status ProcessGDBRemote::FlashErase(lldb::addr_t addr, size_t size) { 26870b57cec5SDimitry Andric Status status; 26880b57cec5SDimitry Andric 26890b57cec5SDimitry Andric MemoryRegionInfo region; 26900b57cec5SDimitry Andric status = GetMemoryRegionInfo(addr, region); 26910b57cec5SDimitry Andric if (!status.Success()) 26920b57cec5SDimitry Andric return status; 26930b57cec5SDimitry Andric 26940b57cec5SDimitry Andric // The gdb spec doesn't say if erasures are allowed across multiple regions, 26950b57cec5SDimitry Andric // but we'll disallow it to be safe and to keep the logic simple by worring 26960b57cec5SDimitry Andric // about only one region's block size. DoMemoryWrite is this function's 26970b57cec5SDimitry Andric // primary user, and it can easily keep writes within a single memory region 26980b57cec5SDimitry Andric if (addr + size > region.GetRange().GetRangeEnd()) { 26990b57cec5SDimitry Andric status.SetErrorString("Unable to erase flash in multiple regions"); 27000b57cec5SDimitry Andric return status; 27010b57cec5SDimitry Andric } 27020b57cec5SDimitry Andric 27030b57cec5SDimitry Andric uint64_t blocksize = region.GetBlocksize(); 27040b57cec5SDimitry Andric if (blocksize == 0) { 27050b57cec5SDimitry Andric status.SetErrorString("Unable to erase flash because blocksize is 0"); 27060b57cec5SDimitry Andric return status; 27070b57cec5SDimitry Andric } 27080b57cec5SDimitry Andric 27090b57cec5SDimitry Andric // Erasures can only be done on block boundary adresses, so round down addr 27100b57cec5SDimitry Andric // and round up size 27110b57cec5SDimitry Andric lldb::addr_t block_start_addr = addr - (addr % blocksize); 27120b57cec5SDimitry Andric size += (addr - block_start_addr); 27130b57cec5SDimitry Andric if ((size % blocksize) != 0) 27140b57cec5SDimitry Andric size += (blocksize - size % blocksize); 27150b57cec5SDimitry Andric 27160b57cec5SDimitry Andric FlashRange range(block_start_addr, size); 27170b57cec5SDimitry Andric 27180b57cec5SDimitry Andric if (HasErased(range)) 27190b57cec5SDimitry Andric return status; 27200b57cec5SDimitry Andric 27210b57cec5SDimitry Andric // We haven't erased the entire range, but we may have erased part of it. 27220b57cec5SDimitry Andric // (e.g., block A is already erased and range starts in A and ends in B). So, 27230b57cec5SDimitry Andric // adjust range if necessary to exclude already erased blocks. 27240b57cec5SDimitry Andric if (!m_erased_flash_ranges.IsEmpty()) { 27250b57cec5SDimitry Andric // Assuming that writes and erasures are done in increasing addr order, 27260b57cec5SDimitry Andric // because that is a requirement of the vFlashWrite command. Therefore, we 27270b57cec5SDimitry Andric // only need to look at the last range in the list for overlap. 27280b57cec5SDimitry Andric const auto &last_range = *m_erased_flash_ranges.Back(); 27290b57cec5SDimitry Andric if (range.GetRangeBase() < last_range.GetRangeEnd()) { 27300b57cec5SDimitry Andric auto overlap = last_range.GetRangeEnd() - range.GetRangeBase(); 27310b57cec5SDimitry Andric // overlap will be less than range.GetByteSize() or else HasErased() 27320b57cec5SDimitry Andric // would have been true 27330b57cec5SDimitry Andric range.SetByteSize(range.GetByteSize() - overlap); 27340b57cec5SDimitry Andric range.SetRangeBase(range.GetRangeBase() + overlap); 27350b57cec5SDimitry Andric } 27360b57cec5SDimitry Andric } 27370b57cec5SDimitry Andric 27380b57cec5SDimitry Andric StreamString packet; 27390b57cec5SDimitry Andric packet.Printf("vFlashErase:%" PRIx64 ",%" PRIx64, range.GetRangeBase(), 27400b57cec5SDimitry Andric (uint64_t)range.GetByteSize()); 27410b57cec5SDimitry Andric 27420b57cec5SDimitry Andric StringExtractorGDBRemote response; 27430b57cec5SDimitry Andric if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response, 2744fe6060f1SDimitry Andric GetInterruptTimeout()) == 27450b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult::Success) { 27460b57cec5SDimitry Andric if (response.IsOKResponse()) { 27470b57cec5SDimitry Andric m_erased_flash_ranges.Insert(range, true); 27480b57cec5SDimitry Andric } else { 27490b57cec5SDimitry Andric if (response.IsErrorResponse()) 27500b57cec5SDimitry Andric status.SetErrorStringWithFormat("flash erase failed for 0x%" PRIx64, 27510b57cec5SDimitry Andric addr); 27520b57cec5SDimitry Andric else if (response.IsUnsupportedResponse()) 27530b57cec5SDimitry Andric status.SetErrorStringWithFormat("GDB server does not support flashing"); 27540b57cec5SDimitry Andric else 27550b57cec5SDimitry Andric status.SetErrorStringWithFormat( 27560b57cec5SDimitry Andric "unexpected response to GDB server flash erase packet '%s': '%s'", 27579dba64beSDimitry Andric packet.GetData(), response.GetStringRef().data()); 27580b57cec5SDimitry Andric } 27590b57cec5SDimitry Andric } else { 27600b57cec5SDimitry Andric status.SetErrorStringWithFormat("failed to send packet: '%s'", 27610b57cec5SDimitry Andric packet.GetData()); 27620b57cec5SDimitry Andric } 27630b57cec5SDimitry Andric return status; 27640b57cec5SDimitry Andric } 27650b57cec5SDimitry Andric 27660b57cec5SDimitry Andric Status ProcessGDBRemote::FlashDone() { 27670b57cec5SDimitry Andric Status status; 27680b57cec5SDimitry Andric // If we haven't erased any blocks, then we must not have written anything 27690b57cec5SDimitry Andric // either, so there is no need to actually send a vFlashDone command 27700b57cec5SDimitry Andric if (m_erased_flash_ranges.IsEmpty()) 27710b57cec5SDimitry Andric return status; 27720b57cec5SDimitry Andric StringExtractorGDBRemote response; 2773fe6060f1SDimitry Andric if (m_gdb_comm.SendPacketAndWaitForResponse("vFlashDone", response, 2774fe6060f1SDimitry Andric GetInterruptTimeout()) == 27750b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult::Success) { 27760b57cec5SDimitry Andric if (response.IsOKResponse()) { 27770b57cec5SDimitry Andric m_erased_flash_ranges.Clear(); 27780b57cec5SDimitry Andric } else { 27790b57cec5SDimitry Andric if (response.IsErrorResponse()) 27800b57cec5SDimitry Andric status.SetErrorStringWithFormat("flash done failed"); 27810b57cec5SDimitry Andric else if (response.IsUnsupportedResponse()) 27820b57cec5SDimitry Andric status.SetErrorStringWithFormat("GDB server does not support flashing"); 27830b57cec5SDimitry Andric else 27840b57cec5SDimitry Andric status.SetErrorStringWithFormat( 27850b57cec5SDimitry Andric "unexpected response to GDB server flash done packet: '%s'", 27869dba64beSDimitry Andric response.GetStringRef().data()); 27870b57cec5SDimitry Andric } 27880b57cec5SDimitry Andric } else { 27890b57cec5SDimitry Andric status.SetErrorStringWithFormat("failed to send flash done packet"); 27900b57cec5SDimitry Andric } 27910b57cec5SDimitry Andric return status; 27920b57cec5SDimitry Andric } 27930b57cec5SDimitry Andric 27940b57cec5SDimitry Andric size_t ProcessGDBRemote::DoWriteMemory(addr_t addr, const void *buf, 27950b57cec5SDimitry Andric size_t size, Status &error) { 27960b57cec5SDimitry Andric GetMaxMemorySize(); 27970b57cec5SDimitry Andric // M and m packets take 2 bytes for 1 byte of memory 27980b57cec5SDimitry Andric size_t max_memory_size = m_max_memory_size / 2; 27990b57cec5SDimitry Andric if (size > max_memory_size) { 28000b57cec5SDimitry Andric // Keep memory read sizes down to a sane limit. This function will be 28010b57cec5SDimitry Andric // called multiple times in order to complete the task by 28020b57cec5SDimitry Andric // lldb_private::Process so it is ok to do this. 28030b57cec5SDimitry Andric size = max_memory_size; 28040b57cec5SDimitry Andric } 28050b57cec5SDimitry Andric 28060b57cec5SDimitry Andric StreamGDBRemote packet; 28070b57cec5SDimitry Andric 28080b57cec5SDimitry Andric MemoryRegionInfo region; 28090b57cec5SDimitry Andric Status region_status = GetMemoryRegionInfo(addr, region); 28100b57cec5SDimitry Andric 28110b57cec5SDimitry Andric bool is_flash = 28120b57cec5SDimitry Andric region_status.Success() && region.GetFlash() == MemoryRegionInfo::eYes; 28130b57cec5SDimitry Andric 28140b57cec5SDimitry Andric if (is_flash) { 28150b57cec5SDimitry Andric if (!m_allow_flash_writes) { 28160b57cec5SDimitry Andric error.SetErrorString("Writing to flash memory is not allowed"); 28170b57cec5SDimitry Andric return 0; 28180b57cec5SDimitry Andric } 28190b57cec5SDimitry Andric // Keep the write within a flash memory region 28200b57cec5SDimitry Andric if (addr + size > region.GetRange().GetRangeEnd()) 28210b57cec5SDimitry Andric size = region.GetRange().GetRangeEnd() - addr; 28220b57cec5SDimitry Andric // Flash memory must be erased before it can be written 28230b57cec5SDimitry Andric error = FlashErase(addr, size); 28240b57cec5SDimitry Andric if (!error.Success()) 28250b57cec5SDimitry Andric return 0; 28260b57cec5SDimitry Andric packet.Printf("vFlashWrite:%" PRIx64 ":", addr); 28270b57cec5SDimitry Andric packet.PutEscapedBytes(buf, size); 28280b57cec5SDimitry Andric } else { 28290b57cec5SDimitry Andric packet.Printf("M%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size); 28300b57cec5SDimitry Andric packet.PutBytesAsRawHex8(buf, size, endian::InlHostByteOrder(), 28310b57cec5SDimitry Andric endian::InlHostByteOrder()); 28320b57cec5SDimitry Andric } 28330b57cec5SDimitry Andric StringExtractorGDBRemote response; 28340b57cec5SDimitry Andric if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response, 2835fe6060f1SDimitry Andric GetInterruptTimeout()) == 28360b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult::Success) { 28370b57cec5SDimitry Andric if (response.IsOKResponse()) { 28380b57cec5SDimitry Andric error.Clear(); 28390b57cec5SDimitry Andric return size; 28400b57cec5SDimitry Andric } else if (response.IsErrorResponse()) 28410b57cec5SDimitry Andric error.SetErrorStringWithFormat("memory write failed for 0x%" PRIx64, 28420b57cec5SDimitry Andric addr); 28430b57cec5SDimitry Andric else if (response.IsUnsupportedResponse()) 28440b57cec5SDimitry Andric error.SetErrorStringWithFormat( 28450b57cec5SDimitry Andric "GDB server does not support writing memory"); 28460b57cec5SDimitry Andric else 28470b57cec5SDimitry Andric error.SetErrorStringWithFormat( 28480b57cec5SDimitry Andric "unexpected response to GDB server memory write packet '%s': '%s'", 28499dba64beSDimitry Andric packet.GetData(), response.GetStringRef().data()); 28500b57cec5SDimitry Andric } else { 28510b57cec5SDimitry Andric error.SetErrorStringWithFormat("failed to send packet: '%s'", 28520b57cec5SDimitry Andric packet.GetData()); 28530b57cec5SDimitry Andric } 28540b57cec5SDimitry Andric return 0; 28550b57cec5SDimitry Andric } 28560b57cec5SDimitry Andric 28570b57cec5SDimitry Andric lldb::addr_t ProcessGDBRemote::DoAllocateMemory(size_t size, 28580b57cec5SDimitry Andric uint32_t permissions, 28590b57cec5SDimitry Andric Status &error) { 286081ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process | LLDBLog::Expressions); 28610b57cec5SDimitry Andric addr_t allocated_addr = LLDB_INVALID_ADDRESS; 28620b57cec5SDimitry Andric 28630b57cec5SDimitry Andric if (m_gdb_comm.SupportsAllocDeallocMemory() != eLazyBoolNo) { 28640b57cec5SDimitry Andric allocated_addr = m_gdb_comm.AllocateMemory(size, permissions); 28650b57cec5SDimitry Andric if (allocated_addr != LLDB_INVALID_ADDRESS || 28660b57cec5SDimitry Andric m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolYes) 28670b57cec5SDimitry Andric return allocated_addr; 28680b57cec5SDimitry Andric } 28690b57cec5SDimitry Andric 28700b57cec5SDimitry Andric if (m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolNo) { 28710b57cec5SDimitry Andric // Call mmap() to create memory in the inferior.. 28720b57cec5SDimitry Andric unsigned prot = 0; 28730b57cec5SDimitry Andric if (permissions & lldb::ePermissionsReadable) 28740b57cec5SDimitry Andric prot |= eMmapProtRead; 28750b57cec5SDimitry Andric if (permissions & lldb::ePermissionsWritable) 28760b57cec5SDimitry Andric prot |= eMmapProtWrite; 28770b57cec5SDimitry Andric if (permissions & lldb::ePermissionsExecutable) 28780b57cec5SDimitry Andric prot |= eMmapProtExec; 28790b57cec5SDimitry Andric 28800b57cec5SDimitry Andric if (InferiorCallMmap(this, allocated_addr, 0, size, prot, 28810b57cec5SDimitry Andric eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) 28820b57cec5SDimitry Andric m_addr_to_mmap_size[allocated_addr] = size; 28830b57cec5SDimitry Andric else { 28840b57cec5SDimitry Andric allocated_addr = LLDB_INVALID_ADDRESS; 28859dba64beSDimitry Andric LLDB_LOGF(log, 28869dba64beSDimitry Andric "ProcessGDBRemote::%s no direct stub support for memory " 28870b57cec5SDimitry Andric "allocation, and InferiorCallMmap also failed - is stub " 28880b57cec5SDimitry Andric "missing register context save/restore capability?", 28890b57cec5SDimitry Andric __FUNCTION__); 28900b57cec5SDimitry Andric } 28910b57cec5SDimitry Andric } 28920b57cec5SDimitry Andric 28930b57cec5SDimitry Andric if (allocated_addr == LLDB_INVALID_ADDRESS) 28940b57cec5SDimitry Andric error.SetErrorStringWithFormat( 28950b57cec5SDimitry Andric "unable to allocate %" PRIu64 " bytes of memory with permissions %s", 28960b57cec5SDimitry Andric (uint64_t)size, GetPermissionsAsCString(permissions)); 28970b57cec5SDimitry Andric else 28980b57cec5SDimitry Andric error.Clear(); 28990b57cec5SDimitry Andric return allocated_addr; 29000b57cec5SDimitry Andric } 29010b57cec5SDimitry Andric 2902d56accc7SDimitry Andric Status ProcessGDBRemote::DoGetMemoryRegionInfo(addr_t load_addr, 29030b57cec5SDimitry Andric MemoryRegionInfo ®ion_info) { 29040b57cec5SDimitry Andric 29050b57cec5SDimitry Andric Status error(m_gdb_comm.GetMemoryRegionInfo(load_addr, region_info)); 29060b57cec5SDimitry Andric return error; 29070b57cec5SDimitry Andric } 29080b57cec5SDimitry Andric 290906c3fb27SDimitry Andric std::optional<uint32_t> ProcessGDBRemote::GetWatchpointSlotCount() { 291006c3fb27SDimitry Andric return m_gdb_comm.GetWatchpointSlotCount(); 29110b57cec5SDimitry Andric } 29120b57cec5SDimitry Andric 291306c3fb27SDimitry Andric std::optional<bool> ProcessGDBRemote::DoGetWatchpointReportedAfter() { 291406c3fb27SDimitry Andric return m_gdb_comm.GetWatchpointReportedAfter(); 29150b57cec5SDimitry Andric } 29160b57cec5SDimitry Andric 29170b57cec5SDimitry Andric Status ProcessGDBRemote::DoDeallocateMemory(lldb::addr_t addr) { 29180b57cec5SDimitry Andric Status error; 29190b57cec5SDimitry Andric LazyBool supported = m_gdb_comm.SupportsAllocDeallocMemory(); 29200b57cec5SDimitry Andric 29210b57cec5SDimitry Andric switch (supported) { 29220b57cec5SDimitry Andric case eLazyBoolCalculate: 29230b57cec5SDimitry Andric // We should never be deallocating memory without allocating memory first 29240b57cec5SDimitry Andric // so we should never get eLazyBoolCalculate 29250b57cec5SDimitry Andric error.SetErrorString( 29260b57cec5SDimitry Andric "tried to deallocate memory without ever allocating memory"); 29270b57cec5SDimitry Andric break; 29280b57cec5SDimitry Andric 29290b57cec5SDimitry Andric case eLazyBoolYes: 29300b57cec5SDimitry Andric if (!m_gdb_comm.DeallocateMemory(addr)) 29310b57cec5SDimitry Andric error.SetErrorStringWithFormat( 29320b57cec5SDimitry Andric "unable to deallocate memory at 0x%" PRIx64, addr); 29330b57cec5SDimitry Andric break; 29340b57cec5SDimitry Andric 29350b57cec5SDimitry Andric case eLazyBoolNo: 29360b57cec5SDimitry Andric // Call munmap() to deallocate memory in the inferior.. 29370b57cec5SDimitry Andric { 29380b57cec5SDimitry Andric MMapMap::iterator pos = m_addr_to_mmap_size.find(addr); 29390b57cec5SDimitry Andric if (pos != m_addr_to_mmap_size.end() && 29400b57cec5SDimitry Andric InferiorCallMunmap(this, addr, pos->second)) 29410b57cec5SDimitry Andric m_addr_to_mmap_size.erase(pos); 29420b57cec5SDimitry Andric else 29430b57cec5SDimitry Andric error.SetErrorStringWithFormat( 29440b57cec5SDimitry Andric "unable to deallocate memory at 0x%" PRIx64, addr); 29450b57cec5SDimitry Andric } 29460b57cec5SDimitry Andric break; 29470b57cec5SDimitry Andric } 29480b57cec5SDimitry Andric 29490b57cec5SDimitry Andric return error; 29500b57cec5SDimitry Andric } 29510b57cec5SDimitry Andric 29520b57cec5SDimitry Andric // Process STDIO 29530b57cec5SDimitry Andric size_t ProcessGDBRemote::PutSTDIN(const char *src, size_t src_len, 29540b57cec5SDimitry Andric Status &error) { 29550b57cec5SDimitry Andric if (m_stdio_communication.IsConnected()) { 29560b57cec5SDimitry Andric ConnectionStatus status; 2957bdd1243dSDimitry Andric m_stdio_communication.WriteAll(src, src_len, status, nullptr); 29580b57cec5SDimitry Andric } else if (m_stdin_forward) { 29590b57cec5SDimitry Andric m_gdb_comm.SendStdinNotification(src, src_len); 29600b57cec5SDimitry Andric } 29610b57cec5SDimitry Andric return 0; 29620b57cec5SDimitry Andric } 29630b57cec5SDimitry Andric 29640b57cec5SDimitry Andric Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) { 29650b57cec5SDimitry Andric Status error; 29660b57cec5SDimitry Andric assert(bp_site != nullptr); 29670b57cec5SDimitry Andric 29680b57cec5SDimitry Andric // Get logging info 29691fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Breakpoints); 29700b57cec5SDimitry Andric user_id_t site_id = bp_site->GetID(); 29710b57cec5SDimitry Andric 29720b57cec5SDimitry Andric // Get the breakpoint address 29730b57cec5SDimitry Andric const addr_t addr = bp_site->GetLoadAddress(); 29740b57cec5SDimitry Andric 29750b57cec5SDimitry Andric // Log that a breakpoint was requested 29769dba64beSDimitry Andric LLDB_LOGF(log, 29779dba64beSDimitry Andric "ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 29780b57cec5SDimitry Andric ") address = 0x%" PRIx64, 29790b57cec5SDimitry Andric site_id, (uint64_t)addr); 29800b57cec5SDimitry Andric 29810b57cec5SDimitry Andric // Breakpoint already exists and is enabled 29820b57cec5SDimitry Andric if (bp_site->IsEnabled()) { 29839dba64beSDimitry Andric LLDB_LOGF(log, 29849dba64beSDimitry Andric "ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 29850b57cec5SDimitry Andric ") address = 0x%" PRIx64 " -- SUCCESS (already enabled)", 29860b57cec5SDimitry Andric site_id, (uint64_t)addr); 29870b57cec5SDimitry Andric return error; 29880b57cec5SDimitry Andric } 29890b57cec5SDimitry Andric 29900b57cec5SDimitry Andric // Get the software breakpoint trap opcode size 29910b57cec5SDimitry Andric const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site); 29920b57cec5SDimitry Andric 29930b57cec5SDimitry Andric // SupportsGDBStoppointPacket() simply checks a boolean, indicating if this 29940b57cec5SDimitry Andric // breakpoint type is supported by the remote stub. These are set to true by 29950b57cec5SDimitry Andric // default, and later set to false only after we receive an unimplemented 29960b57cec5SDimitry Andric // response when sending a breakpoint packet. This means initially that 29970b57cec5SDimitry Andric // unless we were specifically instructed to use a hardware breakpoint, LLDB 29980b57cec5SDimitry Andric // will attempt to set a software breakpoint. HardwareRequired() also queries 29990b57cec5SDimitry Andric // a boolean variable which indicates if the user specifically asked for 30000b57cec5SDimitry Andric // hardware breakpoints. If true then we will skip over software 30010b57cec5SDimitry Andric // breakpoints. 30020b57cec5SDimitry Andric if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware) && 30030b57cec5SDimitry Andric (!bp_site->HardwareRequired())) { 30040b57cec5SDimitry Andric // Try to send off a software breakpoint packet ($Z0) 30050b57cec5SDimitry Andric uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket( 3006fe6060f1SDimitry Andric eBreakpointSoftware, true, addr, bp_op_size, GetInterruptTimeout()); 30070b57cec5SDimitry Andric if (error_no == 0) { 30080b57cec5SDimitry Andric // The breakpoint was placed successfully 30090b57cec5SDimitry Andric bp_site->SetEnabled(true); 30100b57cec5SDimitry Andric bp_site->SetType(BreakpointSite::eExternal); 30110b57cec5SDimitry Andric return error; 30120b57cec5SDimitry Andric } 30130b57cec5SDimitry Andric 30140b57cec5SDimitry Andric // SendGDBStoppointTypePacket() will return an error if it was unable to 30150b57cec5SDimitry Andric // set this breakpoint. We need to differentiate between a error specific 30160b57cec5SDimitry Andric // to placing this breakpoint or if we have learned that this breakpoint 30170b57cec5SDimitry Andric // type is unsupported. To do this, we must test the support boolean for 30180b57cec5SDimitry Andric // this breakpoint type to see if it now indicates that this breakpoint 30190b57cec5SDimitry Andric // type is unsupported. If they are still supported then we should return 30200b57cec5SDimitry Andric // with the error code. If they are now unsupported, then we would like to 30210b57cec5SDimitry Andric // fall through and try another form of breakpoint. 30220b57cec5SDimitry Andric if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware)) { 30230b57cec5SDimitry Andric if (error_no != UINT8_MAX) 30240b57cec5SDimitry Andric error.SetErrorStringWithFormat( 30255ffd83dbSDimitry Andric "error: %d sending the breakpoint request", error_no); 30260b57cec5SDimitry Andric else 30270b57cec5SDimitry Andric error.SetErrorString("error sending the breakpoint request"); 30280b57cec5SDimitry Andric return error; 30290b57cec5SDimitry Andric } 30300b57cec5SDimitry Andric 30310b57cec5SDimitry Andric // We reach here when software breakpoints have been found to be 30320b57cec5SDimitry Andric // unsupported. For future calls to set a breakpoint, we will not attempt 30330b57cec5SDimitry Andric // to set a breakpoint with a type that is known not to be supported. 30349dba64beSDimitry Andric LLDB_LOGF(log, "Software breakpoints are unsupported"); 30350b57cec5SDimitry Andric 30360b57cec5SDimitry Andric // So we will fall through and try a hardware breakpoint 30370b57cec5SDimitry Andric } 30380b57cec5SDimitry Andric 30390b57cec5SDimitry Andric // The process of setting a hardware breakpoint is much the same as above. 30400b57cec5SDimitry Andric // We check the supported boolean for this breakpoint type, and if it is 30410b57cec5SDimitry Andric // thought to be supported then we will try to set this breakpoint with a 30420b57cec5SDimitry Andric // hardware breakpoint. 30430b57cec5SDimitry Andric if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) { 30440b57cec5SDimitry Andric // Try to send off a hardware breakpoint packet ($Z1) 30450b57cec5SDimitry Andric uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket( 3046fe6060f1SDimitry Andric eBreakpointHardware, true, addr, bp_op_size, GetInterruptTimeout()); 30470b57cec5SDimitry Andric if (error_no == 0) { 30480b57cec5SDimitry Andric // The breakpoint was placed successfully 30490b57cec5SDimitry Andric bp_site->SetEnabled(true); 30500b57cec5SDimitry Andric bp_site->SetType(BreakpointSite::eHardware); 30510b57cec5SDimitry Andric return error; 30520b57cec5SDimitry Andric } 30530b57cec5SDimitry Andric 30540b57cec5SDimitry Andric // Check if the error was something other then an unsupported breakpoint 30550b57cec5SDimitry Andric // type 30560b57cec5SDimitry Andric if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) { 30570b57cec5SDimitry Andric // Unable to set this hardware breakpoint 30580b57cec5SDimitry Andric if (error_no != UINT8_MAX) 30590b57cec5SDimitry Andric error.SetErrorStringWithFormat( 30600b57cec5SDimitry Andric "error: %d sending the hardware breakpoint request " 30610b57cec5SDimitry Andric "(hardware breakpoint resources might be exhausted or unavailable)", 30620b57cec5SDimitry Andric error_no); 30630b57cec5SDimitry Andric else 30640b57cec5SDimitry Andric error.SetErrorString("error sending the hardware breakpoint request " 30650b57cec5SDimitry Andric "(hardware breakpoint resources " 30660b57cec5SDimitry Andric "might be exhausted or unavailable)"); 30670b57cec5SDimitry Andric return error; 30680b57cec5SDimitry Andric } 30690b57cec5SDimitry Andric 30700b57cec5SDimitry Andric // We will reach here when the stub gives an unsupported response to a 30710b57cec5SDimitry Andric // hardware breakpoint 30729dba64beSDimitry Andric LLDB_LOGF(log, "Hardware breakpoints are unsupported"); 30730b57cec5SDimitry Andric 30740b57cec5SDimitry Andric // Finally we will falling through to a #trap style breakpoint 30750b57cec5SDimitry Andric } 30760b57cec5SDimitry Andric 30770b57cec5SDimitry Andric // Don't fall through when hardware breakpoints were specifically requested 30780b57cec5SDimitry Andric if (bp_site->HardwareRequired()) { 30790b57cec5SDimitry Andric error.SetErrorString("hardware breakpoints are not supported"); 30800b57cec5SDimitry Andric return error; 30810b57cec5SDimitry Andric } 30820b57cec5SDimitry Andric 30830b57cec5SDimitry Andric // As a last resort we want to place a manual breakpoint. An instruction is 30840b57cec5SDimitry Andric // placed into the process memory using memory write packets. 30850b57cec5SDimitry Andric return EnableSoftwareBreakpoint(bp_site); 30860b57cec5SDimitry Andric } 30870b57cec5SDimitry Andric 30880b57cec5SDimitry Andric Status ProcessGDBRemote::DisableBreakpointSite(BreakpointSite *bp_site) { 30890b57cec5SDimitry Andric Status error; 30900b57cec5SDimitry Andric assert(bp_site != nullptr); 30910b57cec5SDimitry Andric addr_t addr = bp_site->GetLoadAddress(); 30920b57cec5SDimitry Andric user_id_t site_id = bp_site->GetID(); 30931fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Breakpoints); 30949dba64beSDimitry Andric LLDB_LOGF(log, 30959dba64beSDimitry Andric "ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 30960b57cec5SDimitry Andric ") addr = 0x%8.8" PRIx64, 30970b57cec5SDimitry Andric site_id, (uint64_t)addr); 30980b57cec5SDimitry Andric 30990b57cec5SDimitry Andric if (bp_site->IsEnabled()) { 31000b57cec5SDimitry Andric const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site); 31010b57cec5SDimitry Andric 31020b57cec5SDimitry Andric BreakpointSite::Type bp_type = bp_site->GetType(); 31030b57cec5SDimitry Andric switch (bp_type) { 31040b57cec5SDimitry Andric case BreakpointSite::eSoftware: 31050b57cec5SDimitry Andric error = DisableSoftwareBreakpoint(bp_site); 31060b57cec5SDimitry Andric break; 31070b57cec5SDimitry Andric 31080b57cec5SDimitry Andric case BreakpointSite::eHardware: 31090b57cec5SDimitry Andric if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, false, 3110fe6060f1SDimitry Andric addr, bp_op_size, 3111fe6060f1SDimitry Andric GetInterruptTimeout())) 31120b57cec5SDimitry Andric error.SetErrorToGenericError(); 31130b57cec5SDimitry Andric break; 31140b57cec5SDimitry Andric 31150b57cec5SDimitry Andric case BreakpointSite::eExternal: { 3116e8d8bef9SDimitry Andric if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false, 3117fe6060f1SDimitry Andric addr, bp_op_size, 3118fe6060f1SDimitry Andric GetInterruptTimeout())) 31190b57cec5SDimitry Andric error.SetErrorToGenericError(); 31200b57cec5SDimitry Andric } break; 31210b57cec5SDimitry Andric } 31220b57cec5SDimitry Andric if (error.Success()) 31230b57cec5SDimitry Andric bp_site->SetEnabled(false); 31240b57cec5SDimitry Andric } else { 31259dba64beSDimitry Andric LLDB_LOGF(log, 31269dba64beSDimitry Andric "ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 31270b57cec5SDimitry Andric ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", 31280b57cec5SDimitry Andric site_id, (uint64_t)addr); 31290b57cec5SDimitry Andric return error; 31300b57cec5SDimitry Andric } 31310b57cec5SDimitry Andric 31320b57cec5SDimitry Andric if (error.Success()) 31330b57cec5SDimitry Andric error.SetErrorToGenericError(); 31340b57cec5SDimitry Andric return error; 31350b57cec5SDimitry Andric } 31360b57cec5SDimitry Andric 31370b57cec5SDimitry Andric // Pre-requisite: wp != NULL. 31385f757f3fSDimitry Andric static GDBStoppointType 31395f757f3fSDimitry Andric GetGDBStoppointType(const WatchpointResourceSP &wp_res_sp) { 31405f757f3fSDimitry Andric assert(wp_res_sp); 31415f757f3fSDimitry Andric bool read = wp_res_sp->WatchpointResourceRead(); 31425f757f3fSDimitry Andric bool write = wp_res_sp->WatchpointResourceWrite(); 31430b57cec5SDimitry Andric 31445f757f3fSDimitry Andric assert((read || write) && 31455f757f3fSDimitry Andric "WatchpointResource type is neither read nor write"); 31465f757f3fSDimitry Andric if (read && write) 31470b57cec5SDimitry Andric return eWatchpointReadWrite; 31485f757f3fSDimitry Andric else if (read) 31490b57cec5SDimitry Andric return eWatchpointRead; 31505f757f3fSDimitry Andric else 31510b57cec5SDimitry Andric return eWatchpointWrite; 31520b57cec5SDimitry Andric } 31530b57cec5SDimitry Andric 31545f757f3fSDimitry Andric Status ProcessGDBRemote::EnableWatchpoint(WatchpointSP wp_sp, bool notify) { 31550b57cec5SDimitry Andric Status error; 31565f757f3fSDimitry Andric if (!wp_sp) { 31575f757f3fSDimitry Andric error.SetErrorString("No watchpoint specified"); 31585f757f3fSDimitry Andric return error; 31595f757f3fSDimitry Andric } 31605f757f3fSDimitry Andric user_id_t watchID = wp_sp->GetID(); 31615f757f3fSDimitry Andric addr_t addr = wp_sp->GetLoadAddress(); 31621fd87a68SDimitry Andric Log *log(GetLog(GDBRLog::Watchpoints)); 31639dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ")", 31640b57cec5SDimitry Andric watchID); 31655f757f3fSDimitry Andric if (wp_sp->IsEnabled()) { 31669dba64beSDimitry Andric LLDB_LOGF(log, 31679dba64beSDimitry Andric "ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 31680b57cec5SDimitry Andric ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", 31690b57cec5SDimitry Andric watchID, (uint64_t)addr); 31700b57cec5SDimitry Andric return error; 31710b57cec5SDimitry Andric } 31720b57cec5SDimitry Andric 31735f757f3fSDimitry Andric bool read = wp_sp->WatchpointRead(); 31745f757f3fSDimitry Andric bool write = wp_sp->WatchpointWrite() || wp_sp->WatchpointModify(); 31755f757f3fSDimitry Andric size_t size = wp_sp->GetByteSize(); 31765f757f3fSDimitry Andric 3177*0fca6ea1SDimitry Andric ArchSpec target_arch = GetTarget().GetArchitecture(); 3178*0fca6ea1SDimitry Andric WatchpointHardwareFeature supported_features = 3179*0fca6ea1SDimitry Andric m_gdb_comm.GetSupportedWatchpointTypes(); 31805f757f3fSDimitry Andric 3181*0fca6ea1SDimitry Andric std::vector<WatchpointResourceSP> resources = 3182*0fca6ea1SDimitry Andric WatchpointAlgorithms::AtomizeWatchpointRequest( 3183*0fca6ea1SDimitry Andric addr, size, read, write, supported_features, target_arch); 31845f757f3fSDimitry Andric 31855f757f3fSDimitry Andric // LWP_TODO: Now that we know the WP Resources needed to implement this 31865f757f3fSDimitry Andric // Watchpoint, we need to look at currently allocated Resources in the 31875f757f3fSDimitry Andric // Process and if they match, or are within the same memory granule, or 31885f757f3fSDimitry Andric // overlapping memory ranges, then we need to combine them. e.g. one 31895f757f3fSDimitry Andric // Watchpoint watching 1 byte at 0x1002 and a second watchpoint watching 1 31905f757f3fSDimitry Andric // byte at 0x1003, they must use the same hardware watchpoint register 31915f757f3fSDimitry Andric // (Resource) to watch them. 31925f757f3fSDimitry Andric 31935f757f3fSDimitry Andric // This may mean that an existing resource changes its type (read to 31945f757f3fSDimitry Andric // read+write) or address range it is watching, in which case the old 31955f757f3fSDimitry Andric // watchpoint needs to be disabled and the new Resource addr/size/type 31965f757f3fSDimitry Andric // watchpoint enabled. 31975f757f3fSDimitry Andric 31985f757f3fSDimitry Andric // If we modify a shared Resource to accomodate this newly added Watchpoint, 31995f757f3fSDimitry Andric // and we are unable to set all of the Resources for it in the inferior, we 32005f757f3fSDimitry Andric // will return an error for this Watchpoint and the shared Resource should 32015f757f3fSDimitry Andric // be restored. e.g. this Watchpoint requires three Resources, one which 32025f757f3fSDimitry Andric // is shared with another Watchpoint. We extend the shared Resouce to 32035f757f3fSDimitry Andric // handle both Watchpoints and we try to set two new ones. But if we don't 32045f757f3fSDimitry Andric // have sufficient watchpoint register for all 3, we need to show an error 32055f757f3fSDimitry Andric // for creating this Watchpoint and we should reset the shared Resource to 32065f757f3fSDimitry Andric // its original configuration because it is no longer shared. 32075f757f3fSDimitry Andric 32085f757f3fSDimitry Andric bool set_all_resources = true; 32095f757f3fSDimitry Andric std::vector<WatchpointResourceSP> succesfully_set_resources; 32105f757f3fSDimitry Andric for (const auto &wp_res_sp : resources) { 32115f757f3fSDimitry Andric addr_t addr = wp_res_sp->GetLoadAddress(); 32125f757f3fSDimitry Andric size_t size = wp_res_sp->GetByteSize(); 32135f757f3fSDimitry Andric GDBStoppointType type = GetGDBStoppointType(wp_res_sp); 32145f757f3fSDimitry Andric if (!m_gdb_comm.SupportsGDBStoppointPacket(type) || 32155f757f3fSDimitry Andric m_gdb_comm.SendGDBStoppointTypePacket(type, true, addr, size, 32165f757f3fSDimitry Andric GetInterruptTimeout())) { 32175f757f3fSDimitry Andric set_all_resources = false; 32185f757f3fSDimitry Andric break; 32190b57cec5SDimitry Andric } else { 32205f757f3fSDimitry Andric succesfully_set_resources.push_back(wp_res_sp); 32210b57cec5SDimitry Andric } 32225f757f3fSDimitry Andric } 32235f757f3fSDimitry Andric if (set_all_resources) { 32245f757f3fSDimitry Andric wp_sp->SetEnabled(true, notify); 32255f757f3fSDimitry Andric for (const auto &wp_res_sp : resources) { 32265f757f3fSDimitry Andric // LWP_TODO: If we expanded/reused an existing Resource, 32275f757f3fSDimitry Andric // it's already in the WatchpointResourceList. 32285f757f3fSDimitry Andric wp_res_sp->AddConstituent(wp_sp); 32295f757f3fSDimitry Andric m_watchpoint_resource_list.Add(wp_res_sp); 32305f757f3fSDimitry Andric } 32315f757f3fSDimitry Andric return error; 32325f757f3fSDimitry Andric } else { 32335f757f3fSDimitry Andric // We failed to allocate one of the resources. Unset all 32345f757f3fSDimitry Andric // of the new resources we did successfully set in the 32355f757f3fSDimitry Andric // process. 32365f757f3fSDimitry Andric for (const auto &wp_res_sp : succesfully_set_resources) { 32375f757f3fSDimitry Andric addr_t addr = wp_res_sp->GetLoadAddress(); 32385f757f3fSDimitry Andric size_t size = wp_res_sp->GetByteSize(); 32395f757f3fSDimitry Andric GDBStoppointType type = GetGDBStoppointType(wp_res_sp); 32405f757f3fSDimitry Andric m_gdb_comm.SendGDBStoppointTypePacket(type, false, addr, size, 32415f757f3fSDimitry Andric GetInterruptTimeout()); 32425f757f3fSDimitry Andric } 32435f757f3fSDimitry Andric error.SetErrorString("Setting one of the watchpoint resources failed"); 32445f757f3fSDimitry Andric } 32450b57cec5SDimitry Andric return error; 32460b57cec5SDimitry Andric } 32470b57cec5SDimitry Andric 32485f757f3fSDimitry Andric Status ProcessGDBRemote::DisableWatchpoint(WatchpointSP wp_sp, bool notify) { 32490b57cec5SDimitry Andric Status error; 32505f757f3fSDimitry Andric if (!wp_sp) { 32515f757f3fSDimitry Andric error.SetErrorString("Watchpoint argument was NULL."); 32525f757f3fSDimitry Andric return error; 32535f757f3fSDimitry Andric } 32545f757f3fSDimitry Andric 32555f757f3fSDimitry Andric user_id_t watchID = wp_sp->GetID(); 32560b57cec5SDimitry Andric 32571fd87a68SDimitry Andric Log *log(GetLog(GDBRLog::Watchpoints)); 32580b57cec5SDimitry Andric 32595f757f3fSDimitry Andric addr_t addr = wp_sp->GetLoadAddress(); 32600b57cec5SDimitry Andric 32619dba64beSDimitry Andric LLDB_LOGF(log, 32629dba64beSDimitry Andric "ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 32630b57cec5SDimitry Andric ") addr = 0x%8.8" PRIx64, 32640b57cec5SDimitry Andric watchID, (uint64_t)addr); 32650b57cec5SDimitry Andric 32665f757f3fSDimitry Andric if (!wp_sp->IsEnabled()) { 32679dba64beSDimitry Andric LLDB_LOGF(log, 32689dba64beSDimitry Andric "ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 32690b57cec5SDimitry Andric ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", 32700b57cec5SDimitry Andric watchID, (uint64_t)addr); 32710b57cec5SDimitry Andric // See also 'class WatchpointSentry' within StopInfo.cpp. This disabling 32720b57cec5SDimitry Andric // attempt might come from the user-supplied actions, we'll route it in 32730b57cec5SDimitry Andric // order for the watchpoint object to intelligently process this action. 32745f757f3fSDimitry Andric wp_sp->SetEnabled(false, notify); 32750b57cec5SDimitry Andric return error; 32760b57cec5SDimitry Andric } 32770b57cec5SDimitry Andric 32785f757f3fSDimitry Andric if (wp_sp->IsHardware()) { 32795f757f3fSDimitry Andric bool disabled_all = true; 32805f757f3fSDimitry Andric 32815f757f3fSDimitry Andric std::vector<WatchpointResourceSP> unused_resources; 32825f757f3fSDimitry Andric for (const auto &wp_res_sp : m_watchpoint_resource_list.Sites()) { 32835f757f3fSDimitry Andric if (wp_res_sp->ConstituentsContains(wp_sp)) { 32845f757f3fSDimitry Andric GDBStoppointType type = GetGDBStoppointType(wp_res_sp); 32855f757f3fSDimitry Andric addr_t addr = wp_res_sp->GetLoadAddress(); 32865f757f3fSDimitry Andric size_t size = wp_res_sp->GetByteSize(); 32875f757f3fSDimitry Andric if (m_gdb_comm.SendGDBStoppointTypePacket(type, false, addr, size, 32885f757f3fSDimitry Andric GetInterruptTimeout())) { 32895f757f3fSDimitry Andric disabled_all = false; 32900b57cec5SDimitry Andric } else { 32915f757f3fSDimitry Andric wp_res_sp->RemoveConstituent(wp_sp); 32925f757f3fSDimitry Andric if (wp_res_sp->GetNumberOfConstituents() == 0) 32935f757f3fSDimitry Andric unused_resources.push_back(wp_res_sp); 32940b57cec5SDimitry Andric } 32955f757f3fSDimitry Andric } 32965f757f3fSDimitry Andric } 32975f757f3fSDimitry Andric for (auto &wp_res_sp : unused_resources) 32985f757f3fSDimitry Andric m_watchpoint_resource_list.Remove(wp_res_sp->GetID()); 32995f757f3fSDimitry Andric 33005f757f3fSDimitry Andric wp_sp->SetEnabled(false, notify); 33015f757f3fSDimitry Andric if (!disabled_all) 33025f757f3fSDimitry Andric error.SetErrorString("Failure disabling one of the watchpoint locations"); 33035f757f3fSDimitry Andric } 33040b57cec5SDimitry Andric return error; 33050b57cec5SDimitry Andric } 33060b57cec5SDimitry Andric 33070b57cec5SDimitry Andric void ProcessGDBRemote::Clear() { 33080b57cec5SDimitry Andric m_thread_list_real.Clear(); 33090b57cec5SDimitry Andric m_thread_list.Clear(); 33100b57cec5SDimitry Andric } 33110b57cec5SDimitry Andric 33120b57cec5SDimitry Andric Status ProcessGDBRemote::DoSignal(int signo) { 33130b57cec5SDimitry Andric Status error; 33141fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 33159dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::DoSignal (signal = %d)", signo); 33160b57cec5SDimitry Andric 3317fe6060f1SDimitry Andric if (!m_gdb_comm.SendAsyncSignal(signo, GetInterruptTimeout())) 33180b57cec5SDimitry Andric error.SetErrorStringWithFormat("failed to send signal %i", signo); 33190b57cec5SDimitry Andric return error; 33200b57cec5SDimitry Andric } 33210b57cec5SDimitry Andric 33220b57cec5SDimitry Andric Status 33230b57cec5SDimitry Andric ProcessGDBRemote::EstablishConnectionIfNeeded(const ProcessInfo &process_info) { 33240b57cec5SDimitry Andric // Make sure we aren't already connected? 33250b57cec5SDimitry Andric if (m_gdb_comm.IsConnected()) 33260b57cec5SDimitry Andric return Status(); 33270b57cec5SDimitry Andric 33280b57cec5SDimitry Andric PlatformSP platform_sp(GetTarget().GetPlatform()); 33290b57cec5SDimitry Andric if (platform_sp && !platform_sp->IsHost()) 33300b57cec5SDimitry Andric return Status("Lost debug server connection"); 33310b57cec5SDimitry Andric 33320b57cec5SDimitry Andric auto error = LaunchAndConnectToDebugserver(process_info); 33330b57cec5SDimitry Andric if (error.Fail()) { 33340b57cec5SDimitry Andric const char *error_string = error.AsCString(); 33350b57cec5SDimitry Andric if (error_string == nullptr) 33360b57cec5SDimitry Andric error_string = "unable to launch " DEBUGSERVER_BASENAME; 33370b57cec5SDimitry Andric } 33380b57cec5SDimitry Andric return error; 33390b57cec5SDimitry Andric } 33400b57cec5SDimitry Andric #if !defined(_WIN32) 33410b57cec5SDimitry Andric #define USE_SOCKETPAIR_FOR_LOCAL_CONNECTION 1 33420b57cec5SDimitry Andric #endif 33430b57cec5SDimitry Andric 33440b57cec5SDimitry Andric #ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION 33450b57cec5SDimitry Andric static bool SetCloexecFlag(int fd) { 33460b57cec5SDimitry Andric #if defined(FD_CLOEXEC) 33470b57cec5SDimitry Andric int flags = ::fcntl(fd, F_GETFD); 33480b57cec5SDimitry Andric if (flags == -1) 33490b57cec5SDimitry Andric return false; 33500b57cec5SDimitry Andric return (::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == 0); 33510b57cec5SDimitry Andric #else 33520b57cec5SDimitry Andric return false; 33530b57cec5SDimitry Andric #endif 33540b57cec5SDimitry Andric } 33550b57cec5SDimitry Andric #endif 33560b57cec5SDimitry Andric 33570b57cec5SDimitry Andric Status ProcessGDBRemote::LaunchAndConnectToDebugserver( 33580b57cec5SDimitry Andric const ProcessInfo &process_info) { 33590b57cec5SDimitry Andric using namespace std::placeholders; // For _1, _2, etc. 33600b57cec5SDimitry Andric 33610b57cec5SDimitry Andric Status error; 33620b57cec5SDimitry Andric if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID) { 33630b57cec5SDimitry Andric // If we locate debugserver, keep that located version around 33640b57cec5SDimitry Andric static FileSpec g_debugserver_file_spec; 33650b57cec5SDimitry Andric 33660b57cec5SDimitry Andric ProcessLaunchInfo debugserver_launch_info; 33670b57cec5SDimitry Andric // Make debugserver run in its own session so signals generated by special 33680b57cec5SDimitry Andric // terminal key sequences (^C) don't affect debugserver. 33690b57cec5SDimitry Andric debugserver_launch_info.SetLaunchInSeparateProcessGroup(true); 33700b57cec5SDimitry Andric 33710b57cec5SDimitry Andric const std::weak_ptr<ProcessGDBRemote> this_wp = 33720b57cec5SDimitry Andric std::static_pointer_cast<ProcessGDBRemote>(shared_from_this()); 33730b57cec5SDimitry Andric debugserver_launch_info.SetMonitorProcessCallback( 337481ad6265SDimitry Andric std::bind(MonitorDebugserverProcess, this_wp, _1, _2, _3)); 33750b57cec5SDimitry Andric debugserver_launch_info.SetUserID(process_info.GetUserID()); 33760b57cec5SDimitry Andric 33775ffd83dbSDimitry Andric #if defined(__APPLE__) 33785ffd83dbSDimitry Andric // On macOS 11, we need to support x86_64 applications translated to 33795ffd83dbSDimitry Andric // arm64. We check whether a binary is translated and spawn the correct 33805ffd83dbSDimitry Andric // debugserver accordingly. 33815ffd83dbSDimitry Andric int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, 33825ffd83dbSDimitry Andric static_cast<int>(process_info.GetProcessID()) }; 33835ffd83dbSDimitry Andric struct kinfo_proc processInfo; 33845ffd83dbSDimitry Andric size_t bufsize = sizeof(processInfo); 33855ffd83dbSDimitry Andric if (sysctl(mib, (unsigned)(sizeof(mib)/sizeof(int)), &processInfo, 33865ffd83dbSDimitry Andric &bufsize, NULL, 0) == 0 && bufsize > 0) { 33875ffd83dbSDimitry Andric if (processInfo.kp_proc.p_flag & P_TRANSLATED) { 33885ffd83dbSDimitry Andric FileSpec rosetta_debugserver("/Library/Apple/usr/libexec/oah/debugserver"); 33895ffd83dbSDimitry Andric debugserver_launch_info.SetExecutableFile(rosetta_debugserver, false); 33905ffd83dbSDimitry Andric } 33915ffd83dbSDimitry Andric } 33925ffd83dbSDimitry Andric #endif 33935ffd83dbSDimitry Andric 33940b57cec5SDimitry Andric int communication_fd = -1; 33950b57cec5SDimitry Andric #ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION 33960b57cec5SDimitry Andric // Use a socketpair on non-Windows systems for security and performance 33970b57cec5SDimitry Andric // reasons. 33980b57cec5SDimitry Andric int sockets[2]; /* the pair of socket descriptors */ 33990b57cec5SDimitry Andric if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) { 34000b57cec5SDimitry Andric error.SetErrorToErrno(); 34010b57cec5SDimitry Andric return error; 34020b57cec5SDimitry Andric } 34030b57cec5SDimitry Andric 34040b57cec5SDimitry Andric int our_socket = sockets[0]; 34050b57cec5SDimitry Andric int gdb_socket = sockets[1]; 34069dba64beSDimitry Andric auto cleanup_our = llvm::make_scope_exit([&]() { close(our_socket); }); 34079dba64beSDimitry Andric auto cleanup_gdb = llvm::make_scope_exit([&]() { close(gdb_socket); }); 34080b57cec5SDimitry Andric 34090b57cec5SDimitry Andric // Don't let any child processes inherit our communication socket 34100b57cec5SDimitry Andric SetCloexecFlag(our_socket); 34110b57cec5SDimitry Andric communication_fd = gdb_socket; 34120b57cec5SDimitry Andric #endif 34130b57cec5SDimitry Andric 34140b57cec5SDimitry Andric error = m_gdb_comm.StartDebugserverProcess( 34150b57cec5SDimitry Andric nullptr, GetTarget().GetPlatform().get(), debugserver_launch_info, 34160b57cec5SDimitry Andric nullptr, nullptr, communication_fd); 34170b57cec5SDimitry Andric 34180b57cec5SDimitry Andric if (error.Success()) 34190b57cec5SDimitry Andric m_debugserver_pid = debugserver_launch_info.GetProcessID(); 34200b57cec5SDimitry Andric else 34210b57cec5SDimitry Andric m_debugserver_pid = LLDB_INVALID_PROCESS_ID; 34220b57cec5SDimitry Andric 34230b57cec5SDimitry Andric if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID) { 34240b57cec5SDimitry Andric #ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION 34250b57cec5SDimitry Andric // Our process spawned correctly, we can now set our connection to use 34260b57cec5SDimitry Andric // our end of the socket pair 34279dba64beSDimitry Andric cleanup_our.release(); 34285ffd83dbSDimitry Andric m_gdb_comm.SetConnection( 34295ffd83dbSDimitry Andric std::make_unique<ConnectionFileDescriptor>(our_socket, true)); 34300b57cec5SDimitry Andric #endif 34310b57cec5SDimitry Andric StartAsyncThread(); 34320b57cec5SDimitry Andric } 34330b57cec5SDimitry Andric 34340b57cec5SDimitry Andric if (error.Fail()) { 34351fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 34360b57cec5SDimitry Andric 34379dba64beSDimitry Andric LLDB_LOGF(log, "failed to start debugserver process: %s", 34380b57cec5SDimitry Andric error.AsCString()); 34390b57cec5SDimitry Andric return error; 34400b57cec5SDimitry Andric } 34410b57cec5SDimitry Andric 34420b57cec5SDimitry Andric if (m_gdb_comm.IsConnected()) { 34430b57cec5SDimitry Andric // Finish the connection process by doing the handshake without 34440b57cec5SDimitry Andric // connecting (send NULL URL) 34450b57cec5SDimitry Andric error = ConnectToDebugserver(""); 34460b57cec5SDimitry Andric } else { 34470b57cec5SDimitry Andric error.SetErrorString("connection failed"); 34480b57cec5SDimitry Andric } 34490b57cec5SDimitry Andric } 34500b57cec5SDimitry Andric return error; 34510b57cec5SDimitry Andric } 34520b57cec5SDimitry Andric 345381ad6265SDimitry Andric void ProcessGDBRemote::MonitorDebugserverProcess( 34540b57cec5SDimitry Andric std::weak_ptr<ProcessGDBRemote> process_wp, lldb::pid_t debugserver_pid, 34550b57cec5SDimitry Andric int signo, // Zero for no signal 34560b57cec5SDimitry Andric int exit_status // Exit value of process if signal is zero 34570b57cec5SDimitry Andric ) { 34580b57cec5SDimitry Andric // "debugserver_pid" argument passed in is the process ID for debugserver 34590b57cec5SDimitry Andric // that we are tracking... 34601fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 34610b57cec5SDimitry Andric 34629dba64beSDimitry Andric LLDB_LOGF(log, 34639dba64beSDimitry Andric "ProcessGDBRemote::%s(process_wp, pid=%" PRIu64 34640b57cec5SDimitry Andric ", signo=%i (0x%x), exit_status=%i)", 34650b57cec5SDimitry Andric __FUNCTION__, debugserver_pid, signo, signo, exit_status); 34660b57cec5SDimitry Andric 34670b57cec5SDimitry Andric std::shared_ptr<ProcessGDBRemote> process_sp = process_wp.lock(); 34689dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::%s(process = %p)", __FUNCTION__, 34690b57cec5SDimitry Andric static_cast<void *>(process_sp.get())); 34700b57cec5SDimitry Andric if (!process_sp || process_sp->m_debugserver_pid != debugserver_pid) 347181ad6265SDimitry Andric return; 34720b57cec5SDimitry Andric 34730b57cec5SDimitry Andric // Sleep for a half a second to make sure our inferior process has time to 34740b57cec5SDimitry Andric // set its exit status before we set it incorrectly when both the debugserver 34750b57cec5SDimitry Andric // and the inferior process shut down. 34769dba64beSDimitry Andric std::this_thread::sleep_for(std::chrono::milliseconds(500)); 34779dba64beSDimitry Andric 34780b57cec5SDimitry Andric // If our process hasn't yet exited, debugserver might have died. If the 34790b57cec5SDimitry Andric // process did exit, then we are reaping it. 34800b57cec5SDimitry Andric const StateType state = process_sp->GetState(); 34810b57cec5SDimitry Andric 34820b57cec5SDimitry Andric if (state != eStateInvalid && state != eStateUnloaded && 34830b57cec5SDimitry Andric state != eStateExited && state != eStateDetached) { 34845f757f3fSDimitry Andric StreamString stream; 34855f757f3fSDimitry Andric if (signo == 0) 34865f757f3fSDimitry Andric stream.Format(DEBUGSERVER_BASENAME " died with an exit status of {0:x8}", 34870b57cec5SDimitry Andric exit_status); 34885f757f3fSDimitry Andric else { 34895f757f3fSDimitry Andric llvm::StringRef signal_name = 34905f757f3fSDimitry Andric process_sp->GetUnixSignals()->GetSignalAsStringRef(signo); 34915f757f3fSDimitry Andric const char *format_str = DEBUGSERVER_BASENAME " died with signal {0}"; 34925f757f3fSDimitry Andric if (!signal_name.empty()) 34935f757f3fSDimitry Andric stream.Format(format_str, signal_name); 34945f757f3fSDimitry Andric else 34955f757f3fSDimitry Andric stream.Format(format_str, signo); 34960b57cec5SDimitry Andric } 34975f757f3fSDimitry Andric process_sp->SetExitStatus(-1, stream.GetString()); 34980b57cec5SDimitry Andric } 34990b57cec5SDimitry Andric // Debugserver has exited we need to let our ProcessGDBRemote know that it no 35000b57cec5SDimitry Andric // longer has a debugserver instance 35010b57cec5SDimitry Andric process_sp->m_debugserver_pid = LLDB_INVALID_PROCESS_ID; 35020b57cec5SDimitry Andric } 35030b57cec5SDimitry Andric 35040b57cec5SDimitry Andric void ProcessGDBRemote::KillDebugserverProcess() { 35050b57cec5SDimitry Andric m_gdb_comm.Disconnect(); 35060b57cec5SDimitry Andric if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID) { 35070b57cec5SDimitry Andric Host::Kill(m_debugserver_pid, SIGINT); 35080b57cec5SDimitry Andric m_debugserver_pid = LLDB_INVALID_PROCESS_ID; 35090b57cec5SDimitry Andric } 35100b57cec5SDimitry Andric } 35110b57cec5SDimitry Andric 35120b57cec5SDimitry Andric void ProcessGDBRemote::Initialize() { 35130b57cec5SDimitry Andric static llvm::once_flag g_once_flag; 35140b57cec5SDimitry Andric 35150b57cec5SDimitry Andric llvm::call_once(g_once_flag, []() { 35160b57cec5SDimitry Andric PluginManager::RegisterPlugin(GetPluginNameStatic(), 35170b57cec5SDimitry Andric GetPluginDescriptionStatic(), CreateInstance, 35180b57cec5SDimitry Andric DebuggerInitialize); 35190b57cec5SDimitry Andric }); 35200b57cec5SDimitry Andric } 35210b57cec5SDimitry Andric 35220b57cec5SDimitry Andric void ProcessGDBRemote::DebuggerInitialize(Debugger &debugger) { 35230b57cec5SDimitry Andric if (!PluginManager::GetSettingForProcessPlugin( 35240b57cec5SDimitry Andric debugger, PluginProperties::GetSettingName())) { 35250b57cec5SDimitry Andric const bool is_global_setting = true; 35260b57cec5SDimitry Andric PluginManager::CreateSettingForProcessPlugin( 3527349cc55cSDimitry Andric debugger, GetGlobalPluginProperties().GetValueProperties(), 352806c3fb27SDimitry Andric "Properties for the gdb-remote process plug-in.", is_global_setting); 35290b57cec5SDimitry Andric } 35300b57cec5SDimitry Andric } 35310b57cec5SDimitry Andric 35320b57cec5SDimitry Andric bool ProcessGDBRemote::StartAsyncThread() { 35331fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 35340b57cec5SDimitry Andric 35359dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::%s ()", __FUNCTION__); 35360b57cec5SDimitry Andric 35370b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex); 35380b57cec5SDimitry Andric if (!m_async_thread.IsJoinable()) { 35390b57cec5SDimitry Andric // Create a thread that watches our internal state and controls which 35400b57cec5SDimitry Andric // events make it to clients (into the DCProcess event queue). 35410b57cec5SDimitry Andric 354281ad6265SDimitry Andric llvm::Expected<HostThread> async_thread = 354381ad6265SDimitry Andric ThreadLauncher::LaunchThread("<lldb.process.gdb-remote.async>", [this] { 354481ad6265SDimitry Andric return ProcessGDBRemote::AsyncThread(); 354581ad6265SDimitry Andric }); 35460b57cec5SDimitry Andric if (!async_thread) { 354781ad6265SDimitry Andric LLDB_LOG_ERROR(GetLog(LLDBLog::Host), async_thread.takeError(), 354806c3fb27SDimitry Andric "failed to launch host thread: {0}"); 35490b57cec5SDimitry Andric return false; 35500b57cec5SDimitry Andric } 35510b57cec5SDimitry Andric m_async_thread = *async_thread; 35529dba64beSDimitry Andric } else 35539dba64beSDimitry Andric LLDB_LOGF(log, 35549dba64beSDimitry Andric "ProcessGDBRemote::%s () - Called when Async thread was " 35550b57cec5SDimitry Andric "already running.", 35560b57cec5SDimitry Andric __FUNCTION__); 35570b57cec5SDimitry Andric 35580b57cec5SDimitry Andric return m_async_thread.IsJoinable(); 35590b57cec5SDimitry Andric } 35600b57cec5SDimitry Andric 35610b57cec5SDimitry Andric void ProcessGDBRemote::StopAsyncThread() { 35621fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 35630b57cec5SDimitry Andric 35649dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::%s ()", __FUNCTION__); 35650b57cec5SDimitry Andric 35660b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex); 35670b57cec5SDimitry Andric if (m_async_thread.IsJoinable()) { 35680b57cec5SDimitry Andric m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit); 35690b57cec5SDimitry Andric 35700b57cec5SDimitry Andric // This will shut down the async thread. 35710b57cec5SDimitry Andric m_gdb_comm.Disconnect(); // Disconnect from the debug server. 35720b57cec5SDimitry Andric 35730b57cec5SDimitry Andric // Stop the stdio thread 35740b57cec5SDimitry Andric m_async_thread.Join(nullptr); 35750b57cec5SDimitry Andric m_async_thread.Reset(); 35769dba64beSDimitry Andric } else 35779dba64beSDimitry Andric LLDB_LOGF( 35789dba64beSDimitry Andric log, 35790b57cec5SDimitry Andric "ProcessGDBRemote::%s () - Called when Async thread was not running.", 35800b57cec5SDimitry Andric __FUNCTION__); 35810b57cec5SDimitry Andric } 35820b57cec5SDimitry Andric 358381ad6265SDimitry Andric thread_result_t ProcessGDBRemote::AsyncThread() { 35841fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 358581ad6265SDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::%s(pid = %" PRIu64 ") thread starting...", 358681ad6265SDimitry Andric __FUNCTION__, GetID()); 35870b57cec5SDimitry Andric 35880b57cec5SDimitry Andric EventSP event_sp; 3589fe6060f1SDimitry Andric 3590fe6060f1SDimitry Andric // We need to ignore any packets that come in after we have 3591fe6060f1SDimitry Andric // have decided the process has exited. There are some 3592fe6060f1SDimitry Andric // situations, for instance when we try to interrupt a running 3593fe6060f1SDimitry Andric // process and the interrupt fails, where another packet might 3594fe6060f1SDimitry Andric // get delivered after we've decided to give up on the process. 3595fe6060f1SDimitry Andric // But once we've decided we are done with the process we will 3596fe6060f1SDimitry Andric // not be in a state to do anything useful with new packets. 3597fe6060f1SDimitry Andric // So it is safer to simply ignore any remaining packets by 3598fe6060f1SDimitry Andric // explicitly checking for eStateExited before reentering the 3599fe6060f1SDimitry Andric // fetch loop. 3600fe6060f1SDimitry Andric 36010b57cec5SDimitry Andric bool done = false; 360281ad6265SDimitry Andric while (!done && GetPrivateState() != eStateExited) { 36039dba64beSDimitry Andric LLDB_LOGF(log, 360481ad6265SDimitry Andric "ProcessGDBRemote::%s(pid = %" PRIu64 36050b57cec5SDimitry Andric ") listener.WaitForEvent (NULL, event_sp)...", 360681ad6265SDimitry Andric __FUNCTION__, GetID()); 3607fe6060f1SDimitry Andric 3608bdd1243dSDimitry Andric if (m_async_listener_sp->GetEvent(event_sp, std::nullopt)) { 36090b57cec5SDimitry Andric const uint32_t event_type = event_sp->GetType(); 361081ad6265SDimitry Andric if (event_sp->BroadcasterIs(&m_async_broadcaster)) { 36119dba64beSDimitry Andric LLDB_LOGF(log, 361281ad6265SDimitry Andric "ProcessGDBRemote::%s(pid = %" PRIu64 36130b57cec5SDimitry Andric ") Got an event of type: %d...", 361481ad6265SDimitry Andric __FUNCTION__, GetID(), event_type); 36150b57cec5SDimitry Andric 36160b57cec5SDimitry Andric switch (event_type) { 36170b57cec5SDimitry Andric case eBroadcastBitAsyncContinue: { 36180b57cec5SDimitry Andric const EventDataBytes *continue_packet = 36190b57cec5SDimitry Andric EventDataBytes::GetEventDataFromEvent(event_sp.get()); 36200b57cec5SDimitry Andric 36210b57cec5SDimitry Andric if (continue_packet) { 36220b57cec5SDimitry Andric const char *continue_cstr = 36230b57cec5SDimitry Andric (const char *)continue_packet->GetBytes(); 36240b57cec5SDimitry Andric const size_t continue_cstr_len = continue_packet->GetByteSize(); 36259dba64beSDimitry Andric LLDB_LOGF(log, 362681ad6265SDimitry Andric "ProcessGDBRemote::%s(pid = %" PRIu64 36270b57cec5SDimitry Andric ") got eBroadcastBitAsyncContinue: %s", 362881ad6265SDimitry Andric __FUNCTION__, GetID(), continue_cstr); 36290b57cec5SDimitry Andric 36300b57cec5SDimitry Andric if (::strstr(continue_cstr, "vAttach") == nullptr) 363181ad6265SDimitry Andric SetPrivateState(eStateRunning); 36320b57cec5SDimitry Andric StringExtractorGDBRemote response; 36330b57cec5SDimitry Andric 36340b57cec5SDimitry Andric StateType stop_state = 363581ad6265SDimitry Andric GetGDBRemote().SendContinuePacketAndWaitForResponse( 363681ad6265SDimitry Andric *this, *GetUnixSignals(), 36370b57cec5SDimitry Andric llvm::StringRef(continue_cstr, continue_cstr_len), 363881ad6265SDimitry Andric GetInterruptTimeout(), response); 36390b57cec5SDimitry Andric 36400b57cec5SDimitry Andric // We need to immediately clear the thread ID list so we are sure 36410b57cec5SDimitry Andric // to get a valid list of threads. The thread ID list might be 36420b57cec5SDimitry Andric // contained within the "response", or the stop reply packet that 36430b57cec5SDimitry Andric // caused the stop. So clear it now before we give the stop reply 36440b57cec5SDimitry Andric // packet to the process using the 364581ad6265SDimitry Andric // SetLastStopPacket()... 364681ad6265SDimitry Andric ClearThreadIDList(); 36470b57cec5SDimitry Andric 36480b57cec5SDimitry Andric switch (stop_state) { 36490b57cec5SDimitry Andric case eStateStopped: 36500b57cec5SDimitry Andric case eStateCrashed: 36510b57cec5SDimitry Andric case eStateSuspended: 365281ad6265SDimitry Andric SetLastStopPacket(response); 365381ad6265SDimitry Andric SetPrivateState(stop_state); 36540b57cec5SDimitry Andric break; 36550b57cec5SDimitry Andric 36560b57cec5SDimitry Andric case eStateExited: { 365781ad6265SDimitry Andric SetLastStopPacket(response); 365881ad6265SDimitry Andric ClearThreadIDList(); 36590b57cec5SDimitry Andric response.SetFilePos(1); 36600b57cec5SDimitry Andric 36610b57cec5SDimitry Andric int exit_status = response.GetHexU8(); 36620b57cec5SDimitry Andric std::string desc_string; 3663349cc55cSDimitry Andric if (response.GetBytesLeft() > 0 && response.GetChar('-') == ';') { 36640b57cec5SDimitry Andric llvm::StringRef desc_str; 36650b57cec5SDimitry Andric llvm::StringRef desc_token; 36660b57cec5SDimitry Andric while (response.GetNameColonValue(desc_token, desc_str)) { 36670b57cec5SDimitry Andric if (desc_token != "description") 36680b57cec5SDimitry Andric continue; 36690b57cec5SDimitry Andric StringExtractor extractor(desc_str); 36700b57cec5SDimitry Andric extractor.GetHexByteString(desc_string); 36710b57cec5SDimitry Andric } 36720b57cec5SDimitry Andric } 367381ad6265SDimitry Andric SetExitStatus(exit_status, desc_string.c_str()); 36740b57cec5SDimitry Andric done = true; 36750b57cec5SDimitry Andric break; 36760b57cec5SDimitry Andric } 36770b57cec5SDimitry Andric case eStateInvalid: { 36780b57cec5SDimitry Andric // Check to see if we were trying to attach and if we got back 36790b57cec5SDimitry Andric // the "E87" error code from debugserver -- this indicates that 36800b57cec5SDimitry Andric // the process is not debuggable. Return a slightly more 36810b57cec5SDimitry Andric // helpful error message about why the attach failed. 36820b57cec5SDimitry Andric if (::strstr(continue_cstr, "vAttach") != nullptr && 36830b57cec5SDimitry Andric response.GetError() == 0x87) { 368481ad6265SDimitry Andric SetExitStatus(-1, "cannot attach to process due to " 36850b57cec5SDimitry Andric "System Integrity Protection"); 36860b57cec5SDimitry Andric } else if (::strstr(continue_cstr, "vAttach") != nullptr && 36870b57cec5SDimitry Andric response.GetStatus().Fail()) { 368881ad6265SDimitry Andric SetExitStatus(-1, response.GetStatus().AsCString()); 36890b57cec5SDimitry Andric } else { 369081ad6265SDimitry Andric SetExitStatus(-1, "lost connection"); 36910b57cec5SDimitry Andric } 3692fe6060f1SDimitry Andric done = true; 36930b57cec5SDimitry Andric break; 36940b57cec5SDimitry Andric } 36950b57cec5SDimitry Andric 36960b57cec5SDimitry Andric default: 369781ad6265SDimitry Andric SetPrivateState(stop_state); 36980b57cec5SDimitry Andric break; 36990b57cec5SDimitry Andric } // switch(stop_state) 37000b57cec5SDimitry Andric } // if (continue_packet) 37015ffd83dbSDimitry Andric } // case eBroadcastBitAsyncContinue 37020b57cec5SDimitry Andric break; 37030b57cec5SDimitry Andric 37040b57cec5SDimitry Andric case eBroadcastBitAsyncThreadShouldExit: 37059dba64beSDimitry Andric LLDB_LOGF(log, 370681ad6265SDimitry Andric "ProcessGDBRemote::%s(pid = %" PRIu64 37070b57cec5SDimitry Andric ") got eBroadcastBitAsyncThreadShouldExit...", 370881ad6265SDimitry Andric __FUNCTION__, GetID()); 37090b57cec5SDimitry Andric done = true; 37100b57cec5SDimitry Andric break; 37110b57cec5SDimitry Andric 37120b57cec5SDimitry Andric default: 37139dba64beSDimitry Andric LLDB_LOGF(log, 371481ad6265SDimitry Andric "ProcessGDBRemote::%s(pid = %" PRIu64 37150b57cec5SDimitry Andric ") got unknown event 0x%8.8x", 371681ad6265SDimitry Andric __FUNCTION__, GetID(), event_type); 37170b57cec5SDimitry Andric done = true; 37180b57cec5SDimitry Andric break; 37190b57cec5SDimitry Andric } 37200b57cec5SDimitry Andric } 37210b57cec5SDimitry Andric } else { 37229dba64beSDimitry Andric LLDB_LOGF(log, 372381ad6265SDimitry Andric "ProcessGDBRemote::%s(pid = %" PRIu64 37240b57cec5SDimitry Andric ") listener.WaitForEvent (NULL, event_sp) => false", 372581ad6265SDimitry Andric __FUNCTION__, GetID()); 37260b57cec5SDimitry Andric done = true; 37270b57cec5SDimitry Andric } 37280b57cec5SDimitry Andric } 37290b57cec5SDimitry Andric 373081ad6265SDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::%s(pid = %" PRIu64 ") thread exiting...", 373181ad6265SDimitry Andric __FUNCTION__, GetID()); 37320b57cec5SDimitry Andric 37330b57cec5SDimitry Andric return {}; 37340b57cec5SDimitry Andric } 37350b57cec5SDimitry Andric 37360b57cec5SDimitry Andric // uint32_t 37370b57cec5SDimitry Andric // ProcessGDBRemote::ListProcessesMatchingName (const char *name, StringList 37380b57cec5SDimitry Andric // &matches, std::vector<lldb::pid_t> &pids) 37390b57cec5SDimitry Andric //{ 37400b57cec5SDimitry Andric // // If we are planning to launch the debugserver remotely, then we need to 37410b57cec5SDimitry Andric // fire up a debugserver 37420b57cec5SDimitry Andric // // process and ask it for the list of processes. But if we are local, we 37430b57cec5SDimitry Andric // can let the Host do it. 37440b57cec5SDimitry Andric // if (m_local_debugserver) 37450b57cec5SDimitry Andric // { 37460b57cec5SDimitry Andric // return Host::ListProcessesMatchingName (name, matches, pids); 37470b57cec5SDimitry Andric // } 37480b57cec5SDimitry Andric // else 37490b57cec5SDimitry Andric // { 37500b57cec5SDimitry Andric // // FIXME: Implement talking to the remote debugserver. 37510b57cec5SDimitry Andric // return 0; 37520b57cec5SDimitry Andric // } 37530b57cec5SDimitry Andric // 37540b57cec5SDimitry Andric //} 37550b57cec5SDimitry Andric // 37560b57cec5SDimitry Andric bool ProcessGDBRemote::NewThreadNotifyBreakpointHit( 37570b57cec5SDimitry Andric void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, 37580b57cec5SDimitry Andric lldb::user_id_t break_loc_id) { 37590b57cec5SDimitry Andric // I don't think I have to do anything here, just make sure I notice the new 37600b57cec5SDimitry Andric // thread when it starts to 37610b57cec5SDimitry Andric // run so I can stop it if that's what I want to do. 376281ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Step); 37639dba64beSDimitry Andric LLDB_LOGF(log, "Hit New Thread Notification breakpoint."); 37640b57cec5SDimitry Andric return false; 37650b57cec5SDimitry Andric } 37660b57cec5SDimitry Andric 37670b57cec5SDimitry Andric Status ProcessGDBRemote::UpdateAutomaticSignalFiltering() { 37681fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 37690b57cec5SDimitry Andric LLDB_LOG(log, "Check if need to update ignored signals"); 37700b57cec5SDimitry Andric 37710b57cec5SDimitry Andric // QPassSignals package is not supported by the server, there is no way we 37720b57cec5SDimitry Andric // can ignore any signals on server side. 37730b57cec5SDimitry Andric if (!m_gdb_comm.GetQPassSignalsSupported()) 37740b57cec5SDimitry Andric return Status(); 37750b57cec5SDimitry Andric 37760b57cec5SDimitry Andric // No signals, nothing to send. 37770b57cec5SDimitry Andric if (m_unix_signals_sp == nullptr) 37780b57cec5SDimitry Andric return Status(); 37790b57cec5SDimitry Andric 37800b57cec5SDimitry Andric // Signals' version hasn't changed, no need to send anything. 37810b57cec5SDimitry Andric uint64_t new_signals_version = m_unix_signals_sp->GetVersion(); 37820b57cec5SDimitry Andric if (new_signals_version == m_last_signals_version) { 37830b57cec5SDimitry Andric LLDB_LOG(log, "Signals' version hasn't changed. version={0}", 37840b57cec5SDimitry Andric m_last_signals_version); 37850b57cec5SDimitry Andric return Status(); 37860b57cec5SDimitry Andric } 37870b57cec5SDimitry Andric 37880b57cec5SDimitry Andric auto signals_to_ignore = 37890b57cec5SDimitry Andric m_unix_signals_sp->GetFilteredSignals(false, false, false); 37900b57cec5SDimitry Andric Status error = m_gdb_comm.SendSignalsToIgnore(signals_to_ignore); 37910b57cec5SDimitry Andric 37920b57cec5SDimitry Andric LLDB_LOG(log, 37930b57cec5SDimitry Andric "Signals' version changed. old version={0}, new version={1}, " 37940b57cec5SDimitry Andric "signals ignored={2}, update result={3}", 37950b57cec5SDimitry Andric m_last_signals_version, new_signals_version, 37960b57cec5SDimitry Andric signals_to_ignore.size(), error); 37970b57cec5SDimitry Andric 37980b57cec5SDimitry Andric if (error.Success()) 37990b57cec5SDimitry Andric m_last_signals_version = new_signals_version; 38000b57cec5SDimitry Andric 38010b57cec5SDimitry Andric return error; 38020b57cec5SDimitry Andric } 38030b57cec5SDimitry Andric 38040b57cec5SDimitry Andric bool ProcessGDBRemote::StartNoticingNewThreads() { 380581ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Step); 38060b57cec5SDimitry Andric if (m_thread_create_bp_sp) { 38070b57cec5SDimitry Andric if (log && log->GetVerbose()) 38089dba64beSDimitry Andric LLDB_LOGF(log, "Enabled noticing new thread breakpoint."); 38090b57cec5SDimitry Andric m_thread_create_bp_sp->SetEnabled(true); 38100b57cec5SDimitry Andric } else { 38110b57cec5SDimitry Andric PlatformSP platform_sp(GetTarget().GetPlatform()); 38120b57cec5SDimitry Andric if (platform_sp) { 38130b57cec5SDimitry Andric m_thread_create_bp_sp = 38140b57cec5SDimitry Andric platform_sp->SetThreadCreationBreakpoint(GetTarget()); 38150b57cec5SDimitry Andric if (m_thread_create_bp_sp) { 38160b57cec5SDimitry Andric if (log && log->GetVerbose()) 38179dba64beSDimitry Andric LLDB_LOGF( 38189dba64beSDimitry Andric log, "Successfully created new thread notification breakpoint %i", 38190b57cec5SDimitry Andric m_thread_create_bp_sp->GetID()); 38200b57cec5SDimitry Andric m_thread_create_bp_sp->SetCallback( 38210b57cec5SDimitry Andric ProcessGDBRemote::NewThreadNotifyBreakpointHit, this, true); 38220b57cec5SDimitry Andric } else { 38239dba64beSDimitry Andric LLDB_LOGF(log, "Failed to create new thread notification breakpoint."); 38240b57cec5SDimitry Andric } 38250b57cec5SDimitry Andric } 38260b57cec5SDimitry Andric } 38270b57cec5SDimitry Andric return m_thread_create_bp_sp.get() != nullptr; 38280b57cec5SDimitry Andric } 38290b57cec5SDimitry Andric 38300b57cec5SDimitry Andric bool ProcessGDBRemote::StopNoticingNewThreads() { 383181ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Step); 38320b57cec5SDimitry Andric if (log && log->GetVerbose()) 38339dba64beSDimitry Andric LLDB_LOGF(log, "Disabling new thread notification breakpoint."); 38340b57cec5SDimitry Andric 38350b57cec5SDimitry Andric if (m_thread_create_bp_sp) 38360b57cec5SDimitry Andric m_thread_create_bp_sp->SetEnabled(false); 38370b57cec5SDimitry Andric 38380b57cec5SDimitry Andric return true; 38390b57cec5SDimitry Andric } 38400b57cec5SDimitry Andric 38410b57cec5SDimitry Andric DynamicLoader *ProcessGDBRemote::GetDynamicLoader() { 38420b57cec5SDimitry Andric if (m_dyld_up.get() == nullptr) 3843349cc55cSDimitry Andric m_dyld_up.reset(DynamicLoader::FindPlugin(this, "")); 38440b57cec5SDimitry Andric return m_dyld_up.get(); 38450b57cec5SDimitry Andric } 38460b57cec5SDimitry Andric 38470b57cec5SDimitry Andric Status ProcessGDBRemote::SendEventData(const char *data) { 38480b57cec5SDimitry Andric int return_value; 38490b57cec5SDimitry Andric bool was_supported; 38500b57cec5SDimitry Andric 38510b57cec5SDimitry Andric Status error; 38520b57cec5SDimitry Andric 38530b57cec5SDimitry Andric return_value = m_gdb_comm.SendLaunchEventDataPacket(data, &was_supported); 38540b57cec5SDimitry Andric if (return_value != 0) { 38550b57cec5SDimitry Andric if (!was_supported) 38560b57cec5SDimitry Andric error.SetErrorString("Sending events is not supported for this process."); 38570b57cec5SDimitry Andric else 38580b57cec5SDimitry Andric error.SetErrorStringWithFormat("Error sending event data: %d.", 38590b57cec5SDimitry Andric return_value); 38600b57cec5SDimitry Andric } 38610b57cec5SDimitry Andric return error; 38620b57cec5SDimitry Andric } 38630b57cec5SDimitry Andric 38640b57cec5SDimitry Andric DataExtractor ProcessGDBRemote::GetAuxvData() { 38650b57cec5SDimitry Andric DataBufferSP buf; 38660b57cec5SDimitry Andric if (m_gdb_comm.GetQXferAuxvReadSupported()) { 3867349cc55cSDimitry Andric llvm::Expected<std::string> response = m_gdb_comm.ReadExtFeature("auxv", ""); 3868349cc55cSDimitry Andric if (response) 3869349cc55cSDimitry Andric buf = std::make_shared<DataBufferHeap>(response->c_str(), 3870349cc55cSDimitry Andric response->length()); 3871349cc55cSDimitry Andric else 38721fd87a68SDimitry Andric LLDB_LOG_ERROR(GetLog(GDBRLog::Process), response.takeError(), "{0}"); 38730b57cec5SDimitry Andric } 38740b57cec5SDimitry Andric return DataExtractor(buf, GetByteOrder(), GetAddressByteSize()); 38750b57cec5SDimitry Andric } 38760b57cec5SDimitry Andric 38770b57cec5SDimitry Andric StructuredData::ObjectSP 38780b57cec5SDimitry Andric ProcessGDBRemote::GetExtendedInfoForThread(lldb::tid_t tid) { 38790b57cec5SDimitry Andric StructuredData::ObjectSP object_sp; 38800b57cec5SDimitry Andric 38810b57cec5SDimitry Andric if (m_gdb_comm.GetThreadExtendedInfoSupported()) { 38820b57cec5SDimitry Andric StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); 38830b57cec5SDimitry Andric SystemRuntime *runtime = GetSystemRuntime(); 38840b57cec5SDimitry Andric if (runtime) { 38850b57cec5SDimitry Andric runtime->AddThreadExtendedInfoPacketHints(args_dict); 38860b57cec5SDimitry Andric } 38870b57cec5SDimitry Andric args_dict->GetAsDictionary()->AddIntegerItem("thread", tid); 38880b57cec5SDimitry Andric 38890b57cec5SDimitry Andric StreamString packet; 38900b57cec5SDimitry Andric packet << "jThreadExtendedInfo:"; 38910b57cec5SDimitry Andric args_dict->Dump(packet, false); 38920b57cec5SDimitry Andric 38930b57cec5SDimitry Andric // FIXME the final character of a JSON dictionary, '}', is the escape 38940b57cec5SDimitry Andric // character in gdb-remote binary mode. lldb currently doesn't escape 38950b57cec5SDimitry Andric // these characters in its packet output -- so we add the quoted version of 38960b57cec5SDimitry Andric // the } character here manually in case we talk to a debugserver which un- 38970b57cec5SDimitry Andric // escapes the characters at packet read time. 38980b57cec5SDimitry Andric packet << (char)(0x7d ^ 0x20); 38990b57cec5SDimitry Andric 39000b57cec5SDimitry Andric StringExtractorGDBRemote response; 39010b57cec5SDimitry Andric response.SetResponseValidatorToJSON(); 3902fe6060f1SDimitry Andric if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) == 39030b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult::Success) { 39040b57cec5SDimitry Andric StringExtractorGDBRemote::ResponseType response_type = 39050b57cec5SDimitry Andric response.GetResponseType(); 39060b57cec5SDimitry Andric if (response_type == StringExtractorGDBRemote::eResponse) { 39070b57cec5SDimitry Andric if (!response.Empty()) { 390806c3fb27SDimitry Andric object_sp = StructuredData::ParseJSON(response.GetStringRef()); 39090b57cec5SDimitry Andric } 39100b57cec5SDimitry Andric } 39110b57cec5SDimitry Andric } 39120b57cec5SDimitry Andric } 39130b57cec5SDimitry Andric return object_sp; 39140b57cec5SDimitry Andric } 39150b57cec5SDimitry Andric 39160b57cec5SDimitry Andric StructuredData::ObjectSP ProcessGDBRemote::GetLoadedDynamicLibrariesInfos( 39170b57cec5SDimitry Andric lldb::addr_t image_list_address, lldb::addr_t image_count) { 39180b57cec5SDimitry Andric 39190b57cec5SDimitry Andric StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); 39200b57cec5SDimitry Andric args_dict->GetAsDictionary()->AddIntegerItem("image_list_address", 39210b57cec5SDimitry Andric image_list_address); 39220b57cec5SDimitry Andric args_dict->GetAsDictionary()->AddIntegerItem("image_count", image_count); 39230b57cec5SDimitry Andric 39240b57cec5SDimitry Andric return GetLoadedDynamicLibrariesInfos_sender(args_dict); 39250b57cec5SDimitry Andric } 39260b57cec5SDimitry Andric 39270b57cec5SDimitry Andric StructuredData::ObjectSP ProcessGDBRemote::GetLoadedDynamicLibrariesInfos() { 39280b57cec5SDimitry Andric StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); 39290b57cec5SDimitry Andric 39300b57cec5SDimitry Andric args_dict->GetAsDictionary()->AddBooleanItem("fetch_all_solibs", true); 39310b57cec5SDimitry Andric 39320b57cec5SDimitry Andric return GetLoadedDynamicLibrariesInfos_sender(args_dict); 39330b57cec5SDimitry Andric } 39340b57cec5SDimitry Andric 39350b57cec5SDimitry Andric StructuredData::ObjectSP ProcessGDBRemote::GetLoadedDynamicLibrariesInfos( 39360b57cec5SDimitry Andric const std::vector<lldb::addr_t> &load_addresses) { 39370b57cec5SDimitry Andric StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); 39380b57cec5SDimitry Andric StructuredData::ArraySP addresses(new StructuredData::Array); 39390b57cec5SDimitry Andric 394006c3fb27SDimitry Andric for (auto addr : load_addresses) 394106c3fb27SDimitry Andric addresses->AddIntegerItem(addr); 39420b57cec5SDimitry Andric 39430b57cec5SDimitry Andric args_dict->GetAsDictionary()->AddItem("solib_addresses", addresses); 39440b57cec5SDimitry Andric 39450b57cec5SDimitry Andric return GetLoadedDynamicLibrariesInfos_sender(args_dict); 39460b57cec5SDimitry Andric } 39470b57cec5SDimitry Andric 39480b57cec5SDimitry Andric StructuredData::ObjectSP 39490b57cec5SDimitry Andric ProcessGDBRemote::GetLoadedDynamicLibrariesInfos_sender( 39500b57cec5SDimitry Andric StructuredData::ObjectSP args_dict) { 39510b57cec5SDimitry Andric StructuredData::ObjectSP object_sp; 39520b57cec5SDimitry Andric 39530b57cec5SDimitry Andric if (m_gdb_comm.GetLoadedDynamicLibrariesInfosSupported()) { 39540b57cec5SDimitry Andric // Scope for the scoped timeout object 39550b57cec5SDimitry Andric GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_comm, 39560b57cec5SDimitry Andric std::chrono::seconds(10)); 39570b57cec5SDimitry Andric 39580b57cec5SDimitry Andric StreamString packet; 39590b57cec5SDimitry Andric packet << "jGetLoadedDynamicLibrariesInfos:"; 39600b57cec5SDimitry Andric args_dict->Dump(packet, false); 39610b57cec5SDimitry Andric 39620b57cec5SDimitry Andric // FIXME the final character of a JSON dictionary, '}', is the escape 39630b57cec5SDimitry Andric // character in gdb-remote binary mode. lldb currently doesn't escape 39640b57cec5SDimitry Andric // these characters in its packet output -- so we add the quoted version of 39650b57cec5SDimitry Andric // the } character here manually in case we talk to a debugserver which un- 39660b57cec5SDimitry Andric // escapes the characters at packet read time. 39670b57cec5SDimitry Andric packet << (char)(0x7d ^ 0x20); 39680b57cec5SDimitry Andric 39690b57cec5SDimitry Andric StringExtractorGDBRemote response; 39700b57cec5SDimitry Andric response.SetResponseValidatorToJSON(); 3971fe6060f1SDimitry Andric if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) == 39720b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult::Success) { 39730b57cec5SDimitry Andric StringExtractorGDBRemote::ResponseType response_type = 39740b57cec5SDimitry Andric response.GetResponseType(); 39750b57cec5SDimitry Andric if (response_type == StringExtractorGDBRemote::eResponse) { 39760b57cec5SDimitry Andric if (!response.Empty()) { 397706c3fb27SDimitry Andric object_sp = StructuredData::ParseJSON(response.GetStringRef()); 39780b57cec5SDimitry Andric } 39790b57cec5SDimitry Andric } 39800b57cec5SDimitry Andric } 39810b57cec5SDimitry Andric } 39820b57cec5SDimitry Andric return object_sp; 39830b57cec5SDimitry Andric } 39840b57cec5SDimitry Andric 3985bdd1243dSDimitry Andric StructuredData::ObjectSP ProcessGDBRemote::GetDynamicLoaderProcessState() { 3986bdd1243dSDimitry Andric StructuredData::ObjectSP object_sp; 3987bdd1243dSDimitry Andric StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); 3988bdd1243dSDimitry Andric 3989bdd1243dSDimitry Andric if (m_gdb_comm.GetDynamicLoaderProcessStateSupported()) { 3990bdd1243dSDimitry Andric StringExtractorGDBRemote response; 3991bdd1243dSDimitry Andric response.SetResponseValidatorToJSON(); 3992bdd1243dSDimitry Andric if (m_gdb_comm.SendPacketAndWaitForResponse("jGetDyldProcessState", 3993bdd1243dSDimitry Andric response) == 3994bdd1243dSDimitry Andric GDBRemoteCommunication::PacketResult::Success) { 3995bdd1243dSDimitry Andric StringExtractorGDBRemote::ResponseType response_type = 3996bdd1243dSDimitry Andric response.GetResponseType(); 3997bdd1243dSDimitry Andric if (response_type == StringExtractorGDBRemote::eResponse) { 3998bdd1243dSDimitry Andric if (!response.Empty()) { 399906c3fb27SDimitry Andric object_sp = StructuredData::ParseJSON(response.GetStringRef()); 4000bdd1243dSDimitry Andric } 4001bdd1243dSDimitry Andric } 4002bdd1243dSDimitry Andric } 4003bdd1243dSDimitry Andric } 4004bdd1243dSDimitry Andric return object_sp; 4005bdd1243dSDimitry Andric } 4006bdd1243dSDimitry Andric 40070b57cec5SDimitry Andric StructuredData::ObjectSP ProcessGDBRemote::GetSharedCacheInfo() { 40080b57cec5SDimitry Andric StructuredData::ObjectSP object_sp; 40090b57cec5SDimitry Andric StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); 40100b57cec5SDimitry Andric 40110b57cec5SDimitry Andric if (m_gdb_comm.GetSharedCacheInfoSupported()) { 40120b57cec5SDimitry Andric StreamString packet; 40130b57cec5SDimitry Andric packet << "jGetSharedCacheInfo:"; 40140b57cec5SDimitry Andric args_dict->Dump(packet, false); 40150b57cec5SDimitry Andric 40160b57cec5SDimitry Andric // FIXME the final character of a JSON dictionary, '}', is the escape 40170b57cec5SDimitry Andric // character in gdb-remote binary mode. lldb currently doesn't escape 40180b57cec5SDimitry Andric // these characters in its packet output -- so we add the quoted version of 40190b57cec5SDimitry Andric // the } character here manually in case we talk to a debugserver which un- 40200b57cec5SDimitry Andric // escapes the characters at packet read time. 40210b57cec5SDimitry Andric packet << (char)(0x7d ^ 0x20); 40220b57cec5SDimitry Andric 40230b57cec5SDimitry Andric StringExtractorGDBRemote response; 40240b57cec5SDimitry Andric response.SetResponseValidatorToJSON(); 4025fe6060f1SDimitry Andric if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) == 40260b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult::Success) { 40270b57cec5SDimitry Andric StringExtractorGDBRemote::ResponseType response_type = 40280b57cec5SDimitry Andric response.GetResponseType(); 40290b57cec5SDimitry Andric if (response_type == StringExtractorGDBRemote::eResponse) { 40300b57cec5SDimitry Andric if (!response.Empty()) { 403106c3fb27SDimitry Andric object_sp = StructuredData::ParseJSON(response.GetStringRef()); 40320b57cec5SDimitry Andric } 40330b57cec5SDimitry Andric } 40340b57cec5SDimitry Andric } 40350b57cec5SDimitry Andric } 40360b57cec5SDimitry Andric return object_sp; 40370b57cec5SDimitry Andric } 40380b57cec5SDimitry Andric 40390b57cec5SDimitry Andric Status ProcessGDBRemote::ConfigureStructuredData( 404006c3fb27SDimitry Andric llvm::StringRef type_name, const StructuredData::ObjectSP &config_sp) { 40410b57cec5SDimitry Andric return m_gdb_comm.ConfigureRemoteStructuredData(type_name, config_sp); 40420b57cec5SDimitry Andric } 40430b57cec5SDimitry Andric 40440b57cec5SDimitry Andric // Establish the largest memory read/write payloads we should use. If the 40450b57cec5SDimitry Andric // remote stub has a max packet size, stay under that size. 40460b57cec5SDimitry Andric // 40470b57cec5SDimitry Andric // If the remote stub's max packet size is crazy large, use a reasonable 40480b57cec5SDimitry Andric // largeish default. 40490b57cec5SDimitry Andric // 40500b57cec5SDimitry Andric // If the remote stub doesn't advertise a max packet size, use a conservative 40510b57cec5SDimitry Andric // default. 40520b57cec5SDimitry Andric 40530b57cec5SDimitry Andric void ProcessGDBRemote::GetMaxMemorySize() { 40540b57cec5SDimitry Andric const uint64_t reasonable_largeish_default = 128 * 1024; 40550b57cec5SDimitry Andric const uint64_t conservative_default = 512; 40560b57cec5SDimitry Andric 40570b57cec5SDimitry Andric if (m_max_memory_size == 0) { 40580b57cec5SDimitry Andric uint64_t stub_max_size = m_gdb_comm.GetRemoteMaxPacketSize(); 40590b57cec5SDimitry Andric if (stub_max_size != UINT64_MAX && stub_max_size != 0) { 40600b57cec5SDimitry Andric // Save the stub's claimed maximum packet size 40610b57cec5SDimitry Andric m_remote_stub_max_memory_size = stub_max_size; 40620b57cec5SDimitry Andric 40630b57cec5SDimitry Andric // Even if the stub says it can support ginormous packets, don't exceed 40640b57cec5SDimitry Andric // our reasonable largeish default packet size. 40650b57cec5SDimitry Andric if (stub_max_size > reasonable_largeish_default) { 40660b57cec5SDimitry Andric stub_max_size = reasonable_largeish_default; 40670b57cec5SDimitry Andric } 40680b57cec5SDimitry Andric 40690b57cec5SDimitry Andric // Memory packet have other overheads too like Maddr,size:#NN Instead of 40700b57cec5SDimitry Andric // calculating the bytes taken by size and addr every time, we take a 40710b57cec5SDimitry Andric // maximum guess here. 40720b57cec5SDimitry Andric if (stub_max_size > 70) 40730b57cec5SDimitry Andric stub_max_size -= 32 + 32 + 6; 40740b57cec5SDimitry Andric else { 40750b57cec5SDimitry Andric // In unlikely scenario that max packet size is less then 70, we will 40760b57cec5SDimitry Andric // hope that data being written is small enough to fit. 40771fd87a68SDimitry Andric Log *log(GetLog(GDBRLog::Comm | GDBRLog::Memory)); 40780b57cec5SDimitry Andric if (log) 40790b57cec5SDimitry Andric log->Warning("Packet size is too small. " 40800b57cec5SDimitry Andric "LLDB may face problems while writing memory"); 40810b57cec5SDimitry Andric } 40820b57cec5SDimitry Andric 40830b57cec5SDimitry Andric m_max_memory_size = stub_max_size; 40840b57cec5SDimitry Andric } else { 40850b57cec5SDimitry Andric m_max_memory_size = conservative_default; 40860b57cec5SDimitry Andric } 40870b57cec5SDimitry Andric } 40880b57cec5SDimitry Andric } 40890b57cec5SDimitry Andric 40900b57cec5SDimitry Andric void ProcessGDBRemote::SetUserSpecifiedMaxMemoryTransferSize( 40910b57cec5SDimitry Andric uint64_t user_specified_max) { 40920b57cec5SDimitry Andric if (user_specified_max != 0) { 40930b57cec5SDimitry Andric GetMaxMemorySize(); 40940b57cec5SDimitry Andric 40950b57cec5SDimitry Andric if (m_remote_stub_max_memory_size != 0) { 40960b57cec5SDimitry Andric if (m_remote_stub_max_memory_size < user_specified_max) { 40970b57cec5SDimitry Andric m_max_memory_size = m_remote_stub_max_memory_size; // user specified a 40980b57cec5SDimitry Andric // packet size too 40990b57cec5SDimitry Andric // big, go as big 41000b57cec5SDimitry Andric // as the remote stub says we can go. 41010b57cec5SDimitry Andric } else { 41020b57cec5SDimitry Andric m_max_memory_size = user_specified_max; // user's packet size is good 41030b57cec5SDimitry Andric } 41040b57cec5SDimitry Andric } else { 41050b57cec5SDimitry Andric m_max_memory_size = 41060b57cec5SDimitry Andric user_specified_max; // user's packet size is probably fine 41070b57cec5SDimitry Andric } 41080b57cec5SDimitry Andric } 41090b57cec5SDimitry Andric } 41100b57cec5SDimitry Andric 41110b57cec5SDimitry Andric bool ProcessGDBRemote::GetModuleSpec(const FileSpec &module_file_spec, 41120b57cec5SDimitry Andric const ArchSpec &arch, 41130b57cec5SDimitry Andric ModuleSpec &module_spec) { 411481ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Platform); 41150b57cec5SDimitry Andric 41160b57cec5SDimitry Andric const ModuleCacheKey key(module_file_spec.GetPath(), 41170b57cec5SDimitry Andric arch.GetTriple().getTriple()); 41180b57cec5SDimitry Andric auto cached = m_cached_module_specs.find(key); 41190b57cec5SDimitry Andric if (cached != m_cached_module_specs.end()) { 41200b57cec5SDimitry Andric module_spec = cached->second; 41210b57cec5SDimitry Andric return bool(module_spec); 41220b57cec5SDimitry Andric } 41230b57cec5SDimitry Andric 41240b57cec5SDimitry Andric if (!m_gdb_comm.GetModuleInfo(module_file_spec, arch, module_spec)) { 41259dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::%s - failed to get module info for %s:%s", 41260b57cec5SDimitry Andric __FUNCTION__, module_file_spec.GetPath().c_str(), 41270b57cec5SDimitry Andric arch.GetTriple().getTriple().c_str()); 41280b57cec5SDimitry Andric return false; 41290b57cec5SDimitry Andric } 41300b57cec5SDimitry Andric 41310b57cec5SDimitry Andric if (log) { 41320b57cec5SDimitry Andric StreamString stream; 41330b57cec5SDimitry Andric module_spec.Dump(stream); 41349dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::%s - got module info for (%s:%s) : %s", 41350b57cec5SDimitry Andric __FUNCTION__, module_file_spec.GetPath().c_str(), 41360b57cec5SDimitry Andric arch.GetTriple().getTriple().c_str(), stream.GetData()); 41370b57cec5SDimitry Andric } 41380b57cec5SDimitry Andric 41390b57cec5SDimitry Andric m_cached_module_specs[key] = module_spec; 41400b57cec5SDimitry Andric return true; 41410b57cec5SDimitry Andric } 41420b57cec5SDimitry Andric 41430b57cec5SDimitry Andric void ProcessGDBRemote::PrefetchModuleSpecs( 41440b57cec5SDimitry Andric llvm::ArrayRef<FileSpec> module_file_specs, const llvm::Triple &triple) { 41450b57cec5SDimitry Andric auto module_specs = m_gdb_comm.GetModulesInfo(module_file_specs, triple); 41460b57cec5SDimitry Andric if (module_specs) { 41470b57cec5SDimitry Andric for (const FileSpec &spec : module_file_specs) 41480b57cec5SDimitry Andric m_cached_module_specs[ModuleCacheKey(spec.GetPath(), 41490b57cec5SDimitry Andric triple.getTriple())] = ModuleSpec(); 41500b57cec5SDimitry Andric for (const ModuleSpec &spec : *module_specs) 41510b57cec5SDimitry Andric m_cached_module_specs[ModuleCacheKey(spec.GetFileSpec().GetPath(), 41520b57cec5SDimitry Andric triple.getTriple())] = spec; 41530b57cec5SDimitry Andric } 41540b57cec5SDimitry Andric } 41550b57cec5SDimitry Andric 41560b57cec5SDimitry Andric llvm::VersionTuple ProcessGDBRemote::GetHostOSVersion() { 41570b57cec5SDimitry Andric return m_gdb_comm.GetOSVersion(); 41580b57cec5SDimitry Andric } 41590b57cec5SDimitry Andric 41609dba64beSDimitry Andric llvm::VersionTuple ProcessGDBRemote::GetHostMacCatalystVersion() { 41619dba64beSDimitry Andric return m_gdb_comm.GetMacCatalystVersion(); 41629dba64beSDimitry Andric } 41639dba64beSDimitry Andric 41640b57cec5SDimitry Andric namespace { 41650b57cec5SDimitry Andric 41660b57cec5SDimitry Andric typedef std::vector<std::string> stringVec; 41670b57cec5SDimitry Andric 41680b57cec5SDimitry Andric typedef std::vector<struct GdbServerRegisterInfo> GDBServerRegisterVec; 41690b57cec5SDimitry Andric struct RegisterSetInfo { 41700b57cec5SDimitry Andric ConstString name; 41710b57cec5SDimitry Andric }; 41720b57cec5SDimitry Andric 41730b57cec5SDimitry Andric typedef std::map<uint32_t, RegisterSetInfo> RegisterSetMap; 41740b57cec5SDimitry Andric 41750b57cec5SDimitry Andric struct GdbServerTargetInfo { 41760b57cec5SDimitry Andric std::string arch; 41770b57cec5SDimitry Andric std::string osabi; 41780b57cec5SDimitry Andric stringVec includes; 41790b57cec5SDimitry Andric RegisterSetMap reg_set_map; 41800b57cec5SDimitry Andric }; 41810b57cec5SDimitry Andric 4182*0fca6ea1SDimitry Andric static FieldEnum::Enumerators ParseEnumEvalues(const XMLNode &enum_node) { 4183*0fca6ea1SDimitry Andric Log *log(GetLog(GDBRLog::Process)); 4184*0fca6ea1SDimitry Andric // We will use the last instance of each value. Also we preserve the order 4185*0fca6ea1SDimitry Andric // of declaration in the XML, as it may not be numerical. 4186*0fca6ea1SDimitry Andric // For example, hardware may intially release with two states that softwware 4187*0fca6ea1SDimitry Andric // can read from a register field: 4188*0fca6ea1SDimitry Andric // 0 = startup, 1 = running 4189*0fca6ea1SDimitry Andric // If in a future hardware release, the designers added a pre-startup state: 4190*0fca6ea1SDimitry Andric // 0 = startup, 1 = running, 2 = pre-startup 4191*0fca6ea1SDimitry Andric // Now it makes more sense to list them in this logical order as opposed to 4192*0fca6ea1SDimitry Andric // numerical order: 4193*0fca6ea1SDimitry Andric // 2 = pre-startup, 1 = startup, 0 = startup 4194*0fca6ea1SDimitry Andric // This only matters for "register info" but let's trust what the server 4195*0fca6ea1SDimitry Andric // chose regardless. 4196*0fca6ea1SDimitry Andric std::map<uint64_t, FieldEnum::Enumerator> enumerators; 4197*0fca6ea1SDimitry Andric 4198*0fca6ea1SDimitry Andric enum_node.ForEachChildElementWithName( 4199*0fca6ea1SDimitry Andric "evalue", [&enumerators, &log](const XMLNode &enumerator_node) { 4200*0fca6ea1SDimitry Andric std::optional<llvm::StringRef> name; 4201*0fca6ea1SDimitry Andric std::optional<uint64_t> value; 4202*0fca6ea1SDimitry Andric 4203*0fca6ea1SDimitry Andric enumerator_node.ForEachAttribute( 4204*0fca6ea1SDimitry Andric [&name, &value, &log](const llvm::StringRef &attr_name, 4205*0fca6ea1SDimitry Andric const llvm::StringRef &attr_value) { 4206*0fca6ea1SDimitry Andric if (attr_name == "name") { 4207*0fca6ea1SDimitry Andric if (attr_value.size()) 4208*0fca6ea1SDimitry Andric name = attr_value; 4209*0fca6ea1SDimitry Andric else 4210*0fca6ea1SDimitry Andric LLDB_LOG(log, "ProcessGDBRemote::ParseEnumEvalues " 4211*0fca6ea1SDimitry Andric "Ignoring empty name in evalue"); 4212*0fca6ea1SDimitry Andric } else if (attr_name == "value") { 4213*0fca6ea1SDimitry Andric uint64_t parsed_value = 0; 4214*0fca6ea1SDimitry Andric if (llvm::to_integer(attr_value, parsed_value)) 4215*0fca6ea1SDimitry Andric value = parsed_value; 4216*0fca6ea1SDimitry Andric else 4217*0fca6ea1SDimitry Andric LLDB_LOG(log, 4218*0fca6ea1SDimitry Andric "ProcessGDBRemote::ParseEnumEvalues " 4219*0fca6ea1SDimitry Andric "Invalid value \"{0}\" in " 4220*0fca6ea1SDimitry Andric "evalue", 4221*0fca6ea1SDimitry Andric attr_value.data()); 4222*0fca6ea1SDimitry Andric } else 4223*0fca6ea1SDimitry Andric LLDB_LOG(log, 4224*0fca6ea1SDimitry Andric "ProcessGDBRemote::ParseEnumEvalues Ignoring " 4225*0fca6ea1SDimitry Andric "unknown attribute " 4226*0fca6ea1SDimitry Andric "\"{0}\" in evalue", 4227*0fca6ea1SDimitry Andric attr_name.data()); 4228*0fca6ea1SDimitry Andric 4229*0fca6ea1SDimitry Andric // Keep walking attributes. 4230*0fca6ea1SDimitry Andric return true; 4231*0fca6ea1SDimitry Andric }); 4232*0fca6ea1SDimitry Andric 4233*0fca6ea1SDimitry Andric if (value && name) 4234*0fca6ea1SDimitry Andric enumerators.insert_or_assign( 4235*0fca6ea1SDimitry Andric *value, FieldEnum::Enumerator(*value, name->str())); 4236*0fca6ea1SDimitry Andric 4237*0fca6ea1SDimitry Andric // Find all evalue elements. 4238*0fca6ea1SDimitry Andric return true; 4239*0fca6ea1SDimitry Andric }); 4240*0fca6ea1SDimitry Andric 4241*0fca6ea1SDimitry Andric FieldEnum::Enumerators final_enumerators; 4242*0fca6ea1SDimitry Andric for (auto [_, enumerator] : enumerators) 4243*0fca6ea1SDimitry Andric final_enumerators.push_back(enumerator); 4244*0fca6ea1SDimitry Andric 4245*0fca6ea1SDimitry Andric return final_enumerators; 4246*0fca6ea1SDimitry Andric } 4247*0fca6ea1SDimitry Andric 4248*0fca6ea1SDimitry Andric static void 4249*0fca6ea1SDimitry Andric ParseEnums(XMLNode feature_node, 4250*0fca6ea1SDimitry Andric llvm::StringMap<std::unique_ptr<FieldEnum>> ®isters_enum_types) { 4251*0fca6ea1SDimitry Andric Log *log(GetLog(GDBRLog::Process)); 4252*0fca6ea1SDimitry Andric 4253*0fca6ea1SDimitry Andric // The top level element is "<enum...". 4254*0fca6ea1SDimitry Andric feature_node.ForEachChildElementWithName( 4255*0fca6ea1SDimitry Andric "enum", [log, ®isters_enum_types](const XMLNode &enum_node) { 4256*0fca6ea1SDimitry Andric std::string id; 4257*0fca6ea1SDimitry Andric 4258*0fca6ea1SDimitry Andric enum_node.ForEachAttribute([&id](const llvm::StringRef &attr_name, 4259*0fca6ea1SDimitry Andric const llvm::StringRef &attr_value) { 4260*0fca6ea1SDimitry Andric if (attr_name == "id") 4261*0fca6ea1SDimitry Andric id = attr_value; 4262*0fca6ea1SDimitry Andric 4263*0fca6ea1SDimitry Andric // There is also a "size" attribute that is supposed to be the size in 4264*0fca6ea1SDimitry Andric // bytes of the register this applies to. However: 4265*0fca6ea1SDimitry Andric // * LLDB doesn't need this information. 4266*0fca6ea1SDimitry Andric // * It is difficult to verify because you have to wait until the 4267*0fca6ea1SDimitry Andric // enum is applied to a field. 4268*0fca6ea1SDimitry Andric // 4269*0fca6ea1SDimitry Andric // So we will emit this attribute in XML for GDB's sake, but will not 4270*0fca6ea1SDimitry Andric // bother ingesting it. 4271*0fca6ea1SDimitry Andric 4272*0fca6ea1SDimitry Andric // Walk all attributes. 4273*0fca6ea1SDimitry Andric return true; 4274*0fca6ea1SDimitry Andric }); 4275*0fca6ea1SDimitry Andric 4276*0fca6ea1SDimitry Andric if (!id.empty()) { 4277*0fca6ea1SDimitry Andric FieldEnum::Enumerators enumerators = ParseEnumEvalues(enum_node); 4278*0fca6ea1SDimitry Andric if (!enumerators.empty()) { 4279*0fca6ea1SDimitry Andric LLDB_LOG(log, 4280*0fca6ea1SDimitry Andric "ProcessGDBRemote::ParseEnums Found enum type \"{0}\"", 4281*0fca6ea1SDimitry Andric id); 4282*0fca6ea1SDimitry Andric registers_enum_types.insert_or_assign( 4283*0fca6ea1SDimitry Andric id, std::make_unique<FieldEnum>(id, enumerators)); 4284*0fca6ea1SDimitry Andric } 4285*0fca6ea1SDimitry Andric } 4286*0fca6ea1SDimitry Andric 4287*0fca6ea1SDimitry Andric // Find all <enum> elements. 4288*0fca6ea1SDimitry Andric return true; 4289*0fca6ea1SDimitry Andric }); 4290*0fca6ea1SDimitry Andric } 4291*0fca6ea1SDimitry Andric 4292*0fca6ea1SDimitry Andric static std::vector<RegisterFlags::Field> ParseFlagsFields( 4293*0fca6ea1SDimitry Andric XMLNode flags_node, unsigned size, 4294*0fca6ea1SDimitry Andric const llvm::StringMap<std::unique_ptr<FieldEnum>> ®isters_enum_types) { 429506c3fb27SDimitry Andric Log *log(GetLog(GDBRLog::Process)); 429606c3fb27SDimitry Andric const unsigned max_start_bit = size * 8 - 1; 429706c3fb27SDimitry Andric 429806c3fb27SDimitry Andric // Process the fields of this set of flags. 429906c3fb27SDimitry Andric std::vector<RegisterFlags::Field> fields; 4300*0fca6ea1SDimitry Andric flags_node.ForEachChildElementWithName("field", [&fields, max_start_bit, &log, 4301*0fca6ea1SDimitry Andric ®isters_enum_types]( 4302*0fca6ea1SDimitry Andric const XMLNode 430306c3fb27SDimitry Andric &field_node) { 430406c3fb27SDimitry Andric std::optional<llvm::StringRef> name; 430506c3fb27SDimitry Andric std::optional<unsigned> start; 430606c3fb27SDimitry Andric std::optional<unsigned> end; 4307*0fca6ea1SDimitry Andric std::optional<llvm::StringRef> type; 430806c3fb27SDimitry Andric 4309*0fca6ea1SDimitry Andric field_node.ForEachAttribute([&name, &start, &end, &type, max_start_bit, 431006c3fb27SDimitry Andric &log](const llvm::StringRef &attr_name, 431106c3fb27SDimitry Andric const llvm::StringRef &attr_value) { 431206c3fb27SDimitry Andric // Note that XML in general requires that each of these attributes only 431306c3fb27SDimitry Andric // appears once, so we don't have to handle that here. 431406c3fb27SDimitry Andric if (attr_name == "name") { 43157a6dacacSDimitry Andric LLDB_LOG( 43167a6dacacSDimitry Andric log, 43177a6dacacSDimitry Andric "ProcessGDBRemote::ParseFlagsFields Found field node name \"{0}\"", 431806c3fb27SDimitry Andric attr_value.data()); 431906c3fb27SDimitry Andric name = attr_value; 432006c3fb27SDimitry Andric } else if (attr_name == "start") { 432106c3fb27SDimitry Andric unsigned parsed_start = 0; 432206c3fb27SDimitry Andric if (llvm::to_integer(attr_value, parsed_start)) { 432306c3fb27SDimitry Andric if (parsed_start > max_start_bit) { 43247a6dacacSDimitry Andric LLDB_LOG(log, 43257a6dacacSDimitry Andric "ProcessGDBRemote::ParseFlagsFields Invalid start {0} in " 43267a6dacacSDimitry Andric "field node, " 432706c3fb27SDimitry Andric "cannot be > {1}", 432806c3fb27SDimitry Andric parsed_start, max_start_bit); 432906c3fb27SDimitry Andric } else 433006c3fb27SDimitry Andric start = parsed_start; 433106c3fb27SDimitry Andric } else { 43327a6dacacSDimitry Andric LLDB_LOG( 43337a6dacacSDimitry Andric log, 43347a6dacacSDimitry Andric "ProcessGDBRemote::ParseFlagsFields Invalid start \"{0}\" in " 433506c3fb27SDimitry Andric "field node", 433606c3fb27SDimitry Andric attr_value.data()); 433706c3fb27SDimitry Andric } 433806c3fb27SDimitry Andric } else if (attr_name == "end") { 433906c3fb27SDimitry Andric unsigned parsed_end = 0; 434006c3fb27SDimitry Andric if (llvm::to_integer(attr_value, parsed_end)) 434106c3fb27SDimitry Andric if (parsed_end > max_start_bit) { 43427a6dacacSDimitry Andric LLDB_LOG(log, 43437a6dacacSDimitry Andric "ProcessGDBRemote::ParseFlagsFields Invalid end {0} in " 43447a6dacacSDimitry Andric "field node, " 434506c3fb27SDimitry Andric "cannot be > {1}", 434606c3fb27SDimitry Andric parsed_end, max_start_bit); 434706c3fb27SDimitry Andric } else 434806c3fb27SDimitry Andric end = parsed_end; 434906c3fb27SDimitry Andric else { 43507a6dacacSDimitry Andric LLDB_LOG(log, 43517a6dacacSDimitry Andric "ProcessGDBRemote::ParseFlagsFields Invalid end \"{0}\" in " 43527a6dacacSDimitry Andric "field node", 435306c3fb27SDimitry Andric attr_value.data()); 435406c3fb27SDimitry Andric } 435506c3fb27SDimitry Andric } else if (attr_name == "type") { 4356*0fca6ea1SDimitry Andric type = attr_value; 435706c3fb27SDimitry Andric } else { 43587a6dacacSDimitry Andric LLDB_LOG( 43597a6dacacSDimitry Andric log, 43607a6dacacSDimitry Andric "ProcessGDBRemote::ParseFlagsFields Ignoring unknown attribute " 436106c3fb27SDimitry Andric "\"{0}\" in field node", 436206c3fb27SDimitry Andric attr_name.data()); 436306c3fb27SDimitry Andric } 436406c3fb27SDimitry Andric 436506c3fb27SDimitry Andric return true; // Walk all attributes of the field. 436606c3fb27SDimitry Andric }); 436706c3fb27SDimitry Andric 436806c3fb27SDimitry Andric if (name && start && end) { 4369*0fca6ea1SDimitry Andric if (*start > *end) 43707a6dacacSDimitry Andric LLDB_LOG( 43717a6dacacSDimitry Andric log, 43727a6dacacSDimitry Andric "ProcessGDBRemote::ParseFlagsFields Start {0} > end {1} in field " 437306c3fb27SDimitry Andric "\"{2}\", ignoring", 437406c3fb27SDimitry Andric *start, *end, name->data()); 4375*0fca6ea1SDimitry Andric else { 4376*0fca6ea1SDimitry Andric if (RegisterFlags::Field::GetSizeInBits(*start, *end) > 64) 4377*0fca6ea1SDimitry Andric LLDB_LOG(log, 4378*0fca6ea1SDimitry Andric "ProcessGDBRemote::ParseFlagsFields Ignoring field \"{2}\" " 4379*0fca6ea1SDimitry Andric "that has " 4380*0fca6ea1SDimitry Andric "size > 64 bits, this is not supported", 4381*0fca6ea1SDimitry Andric name->data()); 4382*0fca6ea1SDimitry Andric else { 4383*0fca6ea1SDimitry Andric // A field's type may be set to the name of an enum type. 4384*0fca6ea1SDimitry Andric const FieldEnum *enum_type = nullptr; 4385*0fca6ea1SDimitry Andric if (type && !type->empty()) { 4386*0fca6ea1SDimitry Andric auto found = registers_enum_types.find(*type); 4387*0fca6ea1SDimitry Andric if (found != registers_enum_types.end()) { 4388*0fca6ea1SDimitry Andric enum_type = found->second.get(); 4389*0fca6ea1SDimitry Andric 4390*0fca6ea1SDimitry Andric // No enumerator can exceed the range of the field itself. 4391*0fca6ea1SDimitry Andric uint64_t max_value = 4392*0fca6ea1SDimitry Andric RegisterFlags::Field::GetMaxValue(*start, *end); 4393*0fca6ea1SDimitry Andric for (const auto &enumerator : enum_type->GetEnumerators()) { 4394*0fca6ea1SDimitry Andric if (enumerator.m_value > max_value) { 4395*0fca6ea1SDimitry Andric enum_type = nullptr; 4396*0fca6ea1SDimitry Andric LLDB_LOG( 4397*0fca6ea1SDimitry Andric log, 4398*0fca6ea1SDimitry Andric "ProcessGDBRemote::ParseFlagsFields In enum \"{0}\" " 4399*0fca6ea1SDimitry Andric "evalue \"{1}\" with value {2} exceeds the maximum value " 4400*0fca6ea1SDimitry Andric "of field \"{3}\" ({4}), ignoring enum", 4401*0fca6ea1SDimitry Andric type->data(), enumerator.m_name, enumerator.m_value, 4402*0fca6ea1SDimitry Andric name->data(), max_value); 4403*0fca6ea1SDimitry Andric break; 4404*0fca6ea1SDimitry Andric } 4405*0fca6ea1SDimitry Andric } 440606c3fb27SDimitry Andric } else { 4407*0fca6ea1SDimitry Andric LLDB_LOG(log, 4408*0fca6ea1SDimitry Andric "ProcessGDBRemote::ParseFlagsFields Could not find type " 4409*0fca6ea1SDimitry Andric "\"{0}\" " 4410*0fca6ea1SDimitry Andric "for field \"{1}\", ignoring", 4411*0fca6ea1SDimitry Andric type->data(), name->data()); 4412*0fca6ea1SDimitry Andric } 4413*0fca6ea1SDimitry Andric } 4414*0fca6ea1SDimitry Andric 4415*0fca6ea1SDimitry Andric fields.push_back( 4416*0fca6ea1SDimitry Andric RegisterFlags::Field(name->str(), *start, *end, enum_type)); 4417*0fca6ea1SDimitry Andric } 441806c3fb27SDimitry Andric } 441906c3fb27SDimitry Andric } 442006c3fb27SDimitry Andric 442106c3fb27SDimitry Andric return true; // Iterate all "field" nodes. 442206c3fb27SDimitry Andric }); 442306c3fb27SDimitry Andric return fields; 442406c3fb27SDimitry Andric } 442506c3fb27SDimitry Andric 442606c3fb27SDimitry Andric void ParseFlags( 442706c3fb27SDimitry Andric XMLNode feature_node, 4428*0fca6ea1SDimitry Andric llvm::StringMap<std::unique_ptr<RegisterFlags>> ®isters_flags_types, 4429*0fca6ea1SDimitry Andric const llvm::StringMap<std::unique_ptr<FieldEnum>> ®isters_enum_types) { 443006c3fb27SDimitry Andric Log *log(GetLog(GDBRLog::Process)); 443106c3fb27SDimitry Andric 443206c3fb27SDimitry Andric feature_node.ForEachChildElementWithName( 443306c3fb27SDimitry Andric "flags", 4434*0fca6ea1SDimitry Andric [&log, ®isters_flags_types, 4435*0fca6ea1SDimitry Andric ®isters_enum_types](const XMLNode &flags_node) -> bool { 443606c3fb27SDimitry Andric LLDB_LOG(log, "ProcessGDBRemote::ParseFlags Found flags node \"{0}\"", 443706c3fb27SDimitry Andric flags_node.GetAttributeValue("id").c_str()); 443806c3fb27SDimitry Andric 443906c3fb27SDimitry Andric std::optional<llvm::StringRef> id; 444006c3fb27SDimitry Andric std::optional<unsigned> size; 444106c3fb27SDimitry Andric flags_node.ForEachAttribute( 444206c3fb27SDimitry Andric [&id, &size, &log](const llvm::StringRef &name, 444306c3fb27SDimitry Andric const llvm::StringRef &value) { 444406c3fb27SDimitry Andric if (name == "id") { 444506c3fb27SDimitry Andric id = value; 444606c3fb27SDimitry Andric } else if (name == "size") { 444706c3fb27SDimitry Andric unsigned parsed_size = 0; 444806c3fb27SDimitry Andric if (llvm::to_integer(value, parsed_size)) 444906c3fb27SDimitry Andric size = parsed_size; 445006c3fb27SDimitry Andric else { 445106c3fb27SDimitry Andric LLDB_LOG(log, 445206c3fb27SDimitry Andric "ProcessGDBRemote::ParseFlags Invalid size \"{0}\" " 445306c3fb27SDimitry Andric "in flags node", 445406c3fb27SDimitry Andric value.data()); 445506c3fb27SDimitry Andric } 445606c3fb27SDimitry Andric } else { 445706c3fb27SDimitry Andric LLDB_LOG(log, 445806c3fb27SDimitry Andric "ProcessGDBRemote::ParseFlags Ignoring unknown " 445906c3fb27SDimitry Andric "attribute \"{0}\" in flags node", 446006c3fb27SDimitry Andric name.data()); 446106c3fb27SDimitry Andric } 446206c3fb27SDimitry Andric return true; // Walk all attributes. 446306c3fb27SDimitry Andric }); 446406c3fb27SDimitry Andric 446506c3fb27SDimitry Andric if (id && size) { 446606c3fb27SDimitry Andric // Process the fields of this set of flags. 446706c3fb27SDimitry Andric std::vector<RegisterFlags::Field> fields = 4468*0fca6ea1SDimitry Andric ParseFlagsFields(flags_node, *size, registers_enum_types); 446906c3fb27SDimitry Andric if (fields.size()) { 447006c3fb27SDimitry Andric // Sort so that the fields with the MSBs are first. 447106c3fb27SDimitry Andric std::sort(fields.rbegin(), fields.rend()); 447206c3fb27SDimitry Andric std::vector<RegisterFlags::Field>::const_iterator overlap = 447306c3fb27SDimitry Andric std::adjacent_find(fields.begin(), fields.end(), 447406c3fb27SDimitry Andric [](const RegisterFlags::Field &lhs, 447506c3fb27SDimitry Andric const RegisterFlags::Field &rhs) { 447606c3fb27SDimitry Andric return lhs.Overlaps(rhs); 447706c3fb27SDimitry Andric }); 447806c3fb27SDimitry Andric 447906c3fb27SDimitry Andric // If no fields overlap, use them. 448006c3fb27SDimitry Andric if (overlap == fields.end()) { 448106c3fb27SDimitry Andric if (registers_flags_types.contains(*id)) { 448206c3fb27SDimitry Andric // In theory you could define some flag set, use it with a 448306c3fb27SDimitry Andric // register then redefine it. We do not know if anyone does 448406c3fb27SDimitry Andric // that, or what they would expect to happen in that case. 448506c3fb27SDimitry Andric // 448606c3fb27SDimitry Andric // LLDB chooses to take the first definition and ignore the rest 448706c3fb27SDimitry Andric // as waiting until everything has been processed is more 448806c3fb27SDimitry Andric // expensive and difficult. This means that pointers to flag 448906c3fb27SDimitry Andric // sets in the register info remain valid if later the flag set 449006c3fb27SDimitry Andric // is redefined. If we allowed redefinitions, LLDB would crash 449106c3fb27SDimitry Andric // when you tried to print a register that used the original 449206c3fb27SDimitry Andric // definition. 449306c3fb27SDimitry Andric LLDB_LOG( 449406c3fb27SDimitry Andric log, 449506c3fb27SDimitry Andric "ProcessGDBRemote::ParseFlags Definition of flags " 449606c3fb27SDimitry Andric "\"{0}\" shadows " 449706c3fb27SDimitry Andric "previous definition, using original definition instead.", 449806c3fb27SDimitry Andric id->data()); 449906c3fb27SDimitry Andric } else { 450006c3fb27SDimitry Andric registers_flags_types.insert_or_assign( 450106c3fb27SDimitry Andric *id, std::make_unique<RegisterFlags>(id->str(), *size, 450206c3fb27SDimitry Andric std::move(fields))); 450306c3fb27SDimitry Andric } 450406c3fb27SDimitry Andric } else { 450506c3fb27SDimitry Andric // If any fields overlap, ignore the whole set of flags. 450606c3fb27SDimitry Andric std::vector<RegisterFlags::Field>::const_iterator next = 450706c3fb27SDimitry Andric std::next(overlap); 450806c3fb27SDimitry Andric LLDB_LOG( 450906c3fb27SDimitry Andric log, 451006c3fb27SDimitry Andric "ProcessGDBRemote::ParseFlags Ignoring flags because fields " 451106c3fb27SDimitry Andric "{0} (start: {1} end: {2}) and {3} (start: {4} end: {5}) " 451206c3fb27SDimitry Andric "overlap.", 451306c3fb27SDimitry Andric overlap->GetName().c_str(), overlap->GetStart(), 451406c3fb27SDimitry Andric overlap->GetEnd(), next->GetName().c_str(), next->GetStart(), 451506c3fb27SDimitry Andric next->GetEnd()); 451606c3fb27SDimitry Andric } 451706c3fb27SDimitry Andric } else { 451806c3fb27SDimitry Andric LLDB_LOG( 451906c3fb27SDimitry Andric log, 452006c3fb27SDimitry Andric "ProcessGDBRemote::ParseFlags Ignoring definition of flags " 452106c3fb27SDimitry Andric "\"{0}\" because it contains no fields.", 452206c3fb27SDimitry Andric id->data()); 452306c3fb27SDimitry Andric } 452406c3fb27SDimitry Andric } 452506c3fb27SDimitry Andric 452606c3fb27SDimitry Andric return true; // Keep iterating through all "flags" elements. 452706c3fb27SDimitry Andric }); 452806c3fb27SDimitry Andric } 452906c3fb27SDimitry Andric 453006c3fb27SDimitry Andric bool ParseRegisters( 453106c3fb27SDimitry Andric XMLNode feature_node, GdbServerTargetInfo &target_info, 453206c3fb27SDimitry Andric std::vector<DynamicRegisterInfo::Register> ®isters, 4533*0fca6ea1SDimitry Andric llvm::StringMap<std::unique_ptr<RegisterFlags>> ®isters_flags_types, 4534*0fca6ea1SDimitry Andric llvm::StringMap<std::unique_ptr<FieldEnum>> ®isters_enum_types) { 45350b57cec5SDimitry Andric if (!feature_node) 45360b57cec5SDimitry Andric return false; 45370b57cec5SDimitry Andric 4538bdd1243dSDimitry Andric Log *log(GetLog(GDBRLog::Process)); 4539bdd1243dSDimitry Andric 4540*0fca6ea1SDimitry Andric // Enums first because they are referenced by fields in the flags. 4541*0fca6ea1SDimitry Andric ParseEnums(feature_node, registers_enum_types); 4542*0fca6ea1SDimitry Andric for (const auto &enum_type : registers_enum_types) 4543*0fca6ea1SDimitry Andric enum_type.second->DumpToLog(log); 4544*0fca6ea1SDimitry Andric 4545*0fca6ea1SDimitry Andric ParseFlags(feature_node, registers_flags_types, registers_enum_types); 454606c3fb27SDimitry Andric for (const auto &flags : registers_flags_types) 4547*0fca6ea1SDimitry Andric flags.second->DumpToLog(log); 454806c3fb27SDimitry Andric 45490b57cec5SDimitry Andric feature_node.ForEachChildElementWithName( 455006c3fb27SDimitry Andric "reg", 455106c3fb27SDimitry Andric [&target_info, ®isters, ®isters_flags_types, 455206c3fb27SDimitry Andric log](const XMLNode ®_node) -> bool { 45530b57cec5SDimitry Andric std::string gdb_group; 45540b57cec5SDimitry Andric std::string gdb_type; 4555349cc55cSDimitry Andric DynamicRegisterInfo::Register reg_info; 45560b57cec5SDimitry Andric bool encoding_set = false; 45570b57cec5SDimitry Andric bool format_set = false; 45580b57cec5SDimitry Andric 4559349cc55cSDimitry Andric // FIXME: we're silently ignoring invalid data here 45600b57cec5SDimitry Andric reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, 4561bdd1243dSDimitry Andric &encoding_set, &format_set, ®_info, 4562bdd1243dSDimitry Andric log](const llvm::StringRef &name, 45630b57cec5SDimitry Andric const llvm::StringRef &value) -> bool { 45640b57cec5SDimitry Andric if (name == "name") { 4565349cc55cSDimitry Andric reg_info.name.SetString(value); 45660b57cec5SDimitry Andric } else if (name == "bitsize") { 4567349cc55cSDimitry Andric if (llvm::to_integer(value, reg_info.byte_size)) 45680b57cec5SDimitry Andric reg_info.byte_size = 4569349cc55cSDimitry Andric llvm::divideCeil(reg_info.byte_size, CHAR_BIT); 45700b57cec5SDimitry Andric } else if (name == "type") { 45710b57cec5SDimitry Andric gdb_type = value.str(); 45720b57cec5SDimitry Andric } else if (name == "group") { 45730b57cec5SDimitry Andric gdb_group = value.str(); 45740b57cec5SDimitry Andric } else if (name == "regnum") { 4575349cc55cSDimitry Andric llvm::to_integer(value, reg_info.regnum_remote); 45760b57cec5SDimitry Andric } else if (name == "offset") { 4577349cc55cSDimitry Andric llvm::to_integer(value, reg_info.byte_offset); 45780b57cec5SDimitry Andric } else if (name == "altname") { 4579349cc55cSDimitry Andric reg_info.alt_name.SetString(value); 45800b57cec5SDimitry Andric } else if (name == "encoding") { 45810b57cec5SDimitry Andric encoding_set = true; 45820b57cec5SDimitry Andric reg_info.encoding = Args::StringToEncoding(value, eEncodingUint); 45830b57cec5SDimitry Andric } else if (name == "format") { 45840b57cec5SDimitry Andric format_set = true; 4585349cc55cSDimitry Andric if (!OptionArgParser::ToFormat(value.data(), reg_info.format, 4586349cc55cSDimitry Andric nullptr) 45870b57cec5SDimitry Andric .Success()) 4588349cc55cSDimitry Andric reg_info.format = 4589349cc55cSDimitry Andric llvm::StringSwitch<lldb::Format>(value) 4590349cc55cSDimitry Andric .Case("vector-sint8", eFormatVectorOfSInt8) 4591349cc55cSDimitry Andric .Case("vector-uint8", eFormatVectorOfUInt8) 4592349cc55cSDimitry Andric .Case("vector-sint16", eFormatVectorOfSInt16) 4593349cc55cSDimitry Andric .Case("vector-uint16", eFormatVectorOfUInt16) 4594349cc55cSDimitry Andric .Case("vector-sint32", eFormatVectorOfSInt32) 4595349cc55cSDimitry Andric .Case("vector-uint32", eFormatVectorOfUInt32) 4596349cc55cSDimitry Andric .Case("vector-float32", eFormatVectorOfFloat32) 4597349cc55cSDimitry Andric .Case("vector-uint64", eFormatVectorOfUInt64) 4598349cc55cSDimitry Andric .Case("vector-uint128", eFormatVectorOfUInt128) 4599349cc55cSDimitry Andric .Default(eFormatInvalid); 46000b57cec5SDimitry Andric } else if (name == "group_id") { 4601349cc55cSDimitry Andric uint32_t set_id = UINT32_MAX; 4602349cc55cSDimitry Andric llvm::to_integer(value, set_id); 46030b57cec5SDimitry Andric RegisterSetMap::const_iterator pos = 46040b57cec5SDimitry Andric target_info.reg_set_map.find(set_id); 46050b57cec5SDimitry Andric if (pos != target_info.reg_set_map.end()) 4606349cc55cSDimitry Andric reg_info.set_name = pos->second.name; 46070b57cec5SDimitry Andric } else if (name == "gcc_regnum" || name == "ehframe_regnum") { 4608349cc55cSDimitry Andric llvm::to_integer(value, reg_info.regnum_ehframe); 46090b57cec5SDimitry Andric } else if (name == "dwarf_regnum") { 4610349cc55cSDimitry Andric llvm::to_integer(value, reg_info.regnum_dwarf); 46110b57cec5SDimitry Andric } else if (name == "generic") { 4612349cc55cSDimitry Andric reg_info.regnum_generic = Args::StringToGenericRegister(value); 46130b57cec5SDimitry Andric } else if (name == "value_regnums") { 4614349cc55cSDimitry Andric SplitCommaSeparatedRegisterNumberString(value, reg_info.value_regs, 4615349cc55cSDimitry Andric 0); 46160b57cec5SDimitry Andric } else if (name == "invalidate_regnums") { 4617349cc55cSDimitry Andric SplitCommaSeparatedRegisterNumberString( 4618349cc55cSDimitry Andric value, reg_info.invalidate_regs, 0); 46190b57cec5SDimitry Andric } else { 4620349cc55cSDimitry Andric LLDB_LOGF(log, 4621bdd1243dSDimitry Andric "ProcessGDBRemote::ParseRegisters unhandled reg " 4622bdd1243dSDimitry Andric "attribute %s = %s", 4623bdd1243dSDimitry Andric name.data(), value.data()); 46240b57cec5SDimitry Andric } 46250b57cec5SDimitry Andric return true; // Keep iterating through all attributes 46260b57cec5SDimitry Andric }); 46270b57cec5SDimitry Andric 462806c3fb27SDimitry Andric if (!gdb_type.empty()) { 462906c3fb27SDimitry Andric // gdb_type could reference some flags type defined in XML. 463006c3fb27SDimitry Andric llvm::StringMap<std::unique_ptr<RegisterFlags>>::iterator it = 463106c3fb27SDimitry Andric registers_flags_types.find(gdb_type); 463206c3fb27SDimitry Andric if (it != registers_flags_types.end()) { 463306c3fb27SDimitry Andric auto flags_type = it->second.get(); 463406c3fb27SDimitry Andric if (reg_info.byte_size == flags_type->GetSize()) 463506c3fb27SDimitry Andric reg_info.flags_type = flags_type; 463606c3fb27SDimitry Andric else 463706c3fb27SDimitry Andric LLDB_LOGF(log, 463806c3fb27SDimitry Andric "ProcessGDBRemote::ParseRegisters Size of register " 463906c3fb27SDimitry Andric "flags %s (%d bytes) for " 464006c3fb27SDimitry Andric "register %s does not match the register size (%d " 464106c3fb27SDimitry Andric "bytes). Ignoring this set of flags.", 464206c3fb27SDimitry Andric flags_type->GetID().c_str(), flags_type->GetSize(), 464306c3fb27SDimitry Andric reg_info.name.AsCString(), reg_info.byte_size); 464406c3fb27SDimitry Andric } 464506c3fb27SDimitry Andric 464606c3fb27SDimitry Andric // There's a slim chance that the gdb_type name is both a flags type 464706c3fb27SDimitry Andric // and a simple type. Just in case, look for that too (setting both 464806c3fb27SDimitry Andric // does no harm). 46490b57cec5SDimitry Andric if (!gdb_type.empty() && !(encoding_set || format_set)) { 46505f757f3fSDimitry Andric if (llvm::StringRef(gdb_type).starts_with("int")) { 46510b57cec5SDimitry Andric reg_info.format = eFormatHex; 46520b57cec5SDimitry Andric reg_info.encoding = eEncodingUint; 46530b57cec5SDimitry Andric } else if (gdb_type == "data_ptr" || gdb_type == "code_ptr") { 46540b57cec5SDimitry Andric reg_info.format = eFormatAddressInfo; 46550b57cec5SDimitry Andric reg_info.encoding = eEncodingUint; 4656349cc55cSDimitry Andric } else if (gdb_type == "float") { 46570b57cec5SDimitry Andric reg_info.format = eFormatFloat; 46580b57cec5SDimitry Andric reg_info.encoding = eEncodingIEEE754; 4659349cc55cSDimitry Andric } else if (gdb_type == "aarch64v" || 46605f757f3fSDimitry Andric llvm::StringRef(gdb_type).starts_with("vec") || 4661349cc55cSDimitry Andric gdb_type == "i387_ext" || gdb_type == "uint128") { 466206c3fb27SDimitry Andric // lldb doesn't handle 128-bit uints correctly (for ymm*h), so 466306c3fb27SDimitry Andric // treat them as vector (similarly to xmm/ymm) 4664349cc55cSDimitry Andric reg_info.format = eFormatVectorOfUInt8; 4665349cc55cSDimitry Andric reg_info.encoding = eEncodingVector; 4666bdd1243dSDimitry Andric } else { 4667bdd1243dSDimitry Andric LLDB_LOGF( 4668bdd1243dSDimitry Andric log, 4669bdd1243dSDimitry Andric "ProcessGDBRemote::ParseRegisters Could not determine lldb" 4670bdd1243dSDimitry Andric "format and encoding for gdb type %s", 4671bdd1243dSDimitry Andric gdb_type.c_str()); 46720b57cec5SDimitry Andric } 46730b57cec5SDimitry Andric } 467406c3fb27SDimitry Andric } 46750b57cec5SDimitry Andric 46760b57cec5SDimitry Andric // Only update the register set name if we didn't get a "reg_set" 46770b57cec5SDimitry Andric // attribute. "set_name" will be empty if we didn't have a "reg_set" 46780b57cec5SDimitry Andric // attribute. 4679349cc55cSDimitry Andric if (!reg_info.set_name) { 46800b57cec5SDimitry Andric if (!gdb_group.empty()) { 4681349cc55cSDimitry Andric reg_info.set_name.SetCString(gdb_group.c_str()); 46820b57cec5SDimitry Andric } else { 46830b57cec5SDimitry Andric // If no register group name provided anywhere, 46840b57cec5SDimitry Andric // we'll create a 'general' register set 4685349cc55cSDimitry Andric reg_info.set_name.SetCString("general"); 46860b57cec5SDimitry Andric } 46870b57cec5SDimitry Andric } 46880b57cec5SDimitry Andric 4689349cc55cSDimitry Andric if (reg_info.byte_size == 0) { 4690349cc55cSDimitry Andric LLDB_LOGF(log, 4691349cc55cSDimitry Andric "ProcessGDBRemote::%s Skipping zero bitsize register %s", 4692349cc55cSDimitry Andric __FUNCTION__, reg_info.name.AsCString()); 4693349cc55cSDimitry Andric } else 4694349cc55cSDimitry Andric registers.push_back(reg_info); 46950b57cec5SDimitry Andric 46960b57cec5SDimitry Andric return true; // Keep iterating through all "reg" elements 46970b57cec5SDimitry Andric }); 46980b57cec5SDimitry Andric return true; 46990b57cec5SDimitry Andric } 47000b57cec5SDimitry Andric 47010b57cec5SDimitry Andric } // namespace 47020b57cec5SDimitry Andric 47030b57cec5SDimitry Andric // This method fetches a register description feature xml file from 47040b57cec5SDimitry Andric // the remote stub and adds registers/register groupsets/architecture 47050b57cec5SDimitry Andric // information to the current process. It will call itself recursively 47060b57cec5SDimitry Andric // for nested register definition files. It returns true if it was able 47070b57cec5SDimitry Andric // to fetch and parse an xml file. 47089dba64beSDimitry Andric bool ProcessGDBRemote::GetGDBServerRegisterInfoXMLAndProcess( 4709349cc55cSDimitry Andric ArchSpec &arch_to_use, std::string xml_filename, 4710349cc55cSDimitry Andric std::vector<DynamicRegisterInfo::Register> ®isters) { 47110b57cec5SDimitry Andric // request the target xml file 4712349cc55cSDimitry Andric llvm::Expected<std::string> raw = m_gdb_comm.ReadExtFeature("features", xml_filename); 4713349cc55cSDimitry Andric if (errorToBool(raw.takeError())) 47140b57cec5SDimitry Andric return false; 47150b57cec5SDimitry Andric 47160b57cec5SDimitry Andric XMLDocument xml_document; 47170b57cec5SDimitry Andric 4718349cc55cSDimitry Andric if (xml_document.ParseMemory(raw->c_str(), raw->size(), 4719349cc55cSDimitry Andric xml_filename.c_str())) { 47200b57cec5SDimitry Andric GdbServerTargetInfo target_info; 47210b57cec5SDimitry Andric std::vector<XMLNode> feature_nodes; 47220b57cec5SDimitry Andric 47230b57cec5SDimitry Andric // The top level feature XML file will start with a <target> tag. 47240b57cec5SDimitry Andric XMLNode target_node = xml_document.GetRootElement("target"); 47250b57cec5SDimitry Andric if (target_node) { 47260b57cec5SDimitry Andric target_node.ForEachChildElement([&target_info, &feature_nodes]( 47270b57cec5SDimitry Andric const XMLNode &node) -> bool { 47280b57cec5SDimitry Andric llvm::StringRef name = node.GetName(); 47290b57cec5SDimitry Andric if (name == "architecture") { 47300b57cec5SDimitry Andric node.GetElementText(target_info.arch); 47310b57cec5SDimitry Andric } else if (name == "osabi") { 47320b57cec5SDimitry Andric node.GetElementText(target_info.osabi); 47330b57cec5SDimitry Andric } else if (name == "xi:include" || name == "include") { 473404eeddc0SDimitry Andric std::string href = node.GetAttributeValue("href"); 47350b57cec5SDimitry Andric if (!href.empty()) 473604eeddc0SDimitry Andric target_info.includes.push_back(href); 47370b57cec5SDimitry Andric } else if (name == "feature") { 47380b57cec5SDimitry Andric feature_nodes.push_back(node); 47390b57cec5SDimitry Andric } else if (name == "groups") { 47400b57cec5SDimitry Andric node.ForEachChildElementWithName( 47410b57cec5SDimitry Andric "group", [&target_info](const XMLNode &node) -> bool { 47420b57cec5SDimitry Andric uint32_t set_id = UINT32_MAX; 47430b57cec5SDimitry Andric RegisterSetInfo set_info; 47440b57cec5SDimitry Andric 47450b57cec5SDimitry Andric node.ForEachAttribute( 47460b57cec5SDimitry Andric [&set_id, &set_info](const llvm::StringRef &name, 47470b57cec5SDimitry Andric const llvm::StringRef &value) -> bool { 4748349cc55cSDimitry Andric // FIXME: we're silently ignoring invalid data here 47490b57cec5SDimitry Andric if (name == "id") 4750349cc55cSDimitry Andric llvm::to_integer(value, set_id); 47510b57cec5SDimitry Andric if (name == "name") 47520b57cec5SDimitry Andric set_info.name = ConstString(value); 47530b57cec5SDimitry Andric return true; // Keep iterating through all attributes 47540b57cec5SDimitry Andric }); 47550b57cec5SDimitry Andric 47560b57cec5SDimitry Andric if (set_id != UINT32_MAX) 47570b57cec5SDimitry Andric target_info.reg_set_map[set_id] = set_info; 47580b57cec5SDimitry Andric return true; // Keep iterating through all "group" elements 47590b57cec5SDimitry Andric }); 47600b57cec5SDimitry Andric } 47610b57cec5SDimitry Andric return true; // Keep iterating through all children of the target_node 47620b57cec5SDimitry Andric }); 47630b57cec5SDimitry Andric } else { 47640b57cec5SDimitry Andric // In an included XML feature file, we're already "inside" the <target> 47650b57cec5SDimitry Andric // tag of the initial XML file; this included file will likely only have 47660b57cec5SDimitry Andric // a <feature> tag. Need to check for any more included files in this 47670b57cec5SDimitry Andric // <feature> element. 47680b57cec5SDimitry Andric XMLNode feature_node = xml_document.GetRootElement("feature"); 47690b57cec5SDimitry Andric if (feature_node) { 47700b57cec5SDimitry Andric feature_nodes.push_back(feature_node); 47710b57cec5SDimitry Andric feature_node.ForEachChildElement([&target_info]( 47720b57cec5SDimitry Andric const XMLNode &node) -> bool { 47730b57cec5SDimitry Andric llvm::StringRef name = node.GetName(); 47740b57cec5SDimitry Andric if (name == "xi:include" || name == "include") { 477504eeddc0SDimitry Andric std::string href = node.GetAttributeValue("href"); 47760b57cec5SDimitry Andric if (!href.empty()) 477704eeddc0SDimitry Andric target_info.includes.push_back(href); 47780b57cec5SDimitry Andric } 47790b57cec5SDimitry Andric return true; 47800b57cec5SDimitry Andric }); 47810b57cec5SDimitry Andric } 47820b57cec5SDimitry Andric } 47830b57cec5SDimitry Andric 4784349cc55cSDimitry Andric // gdbserver does not implement the LLDB packets used to determine host 4785349cc55cSDimitry Andric // or process architecture. If that is the case, attempt to use 4786349cc55cSDimitry Andric // the <architecture/> field from target.xml, e.g.: 4787349cc55cSDimitry Andric // 47880b57cec5SDimitry Andric // <architecture>i386:x86-64</architecture> (seen from VMWare ESXi) 4789349cc55cSDimitry Andric // <architecture>arm</architecture> (seen from Segger JLink on unspecified 4790349cc55cSDimitry Andric // arm board) 47910b57cec5SDimitry Andric if (!arch_to_use.IsValid() && !target_info.arch.empty()) { 47920b57cec5SDimitry Andric // We don't have any information about vendor or OS. 4793349cc55cSDimitry Andric arch_to_use.SetTriple(llvm::StringSwitch<std::string>(target_info.arch) 4794349cc55cSDimitry Andric .Case("i386:x86-64", "x86_64") 4795*0fca6ea1SDimitry Andric .Case("riscv:rv64", "riscv64") 4796*0fca6ea1SDimitry Andric .Case("riscv:rv32", "riscv32") 4797349cc55cSDimitry Andric .Default(target_info.arch) + 4798349cc55cSDimitry Andric "--"); 47990b57cec5SDimitry Andric 4800349cc55cSDimitry Andric if (arch_to_use.IsValid()) 48010b57cec5SDimitry Andric GetTarget().MergeArchitecture(arch_to_use); 48020b57cec5SDimitry Andric } 48030b57cec5SDimitry Andric 48040b57cec5SDimitry Andric if (arch_to_use.IsValid()) { 48050b57cec5SDimitry Andric for (auto &feature_node : feature_nodes) { 480606c3fb27SDimitry Andric ParseRegisters(feature_node, target_info, registers, 4807*0fca6ea1SDimitry Andric m_registers_flags_types, m_registers_enum_types); 48080b57cec5SDimitry Andric } 48090b57cec5SDimitry Andric 48100b57cec5SDimitry Andric for (const auto &include : target_info.includes) { 4811e8d8bef9SDimitry Andric GetGDBServerRegisterInfoXMLAndProcess(arch_to_use, include, 4812349cc55cSDimitry Andric registers); 48130b57cec5SDimitry Andric } 48140b57cec5SDimitry Andric } 48150b57cec5SDimitry Andric } else { 48160b57cec5SDimitry Andric return false; 48170b57cec5SDimitry Andric } 48180b57cec5SDimitry Andric return true; 48190b57cec5SDimitry Andric } 48200b57cec5SDimitry Andric 4821349cc55cSDimitry Andric void ProcessGDBRemote::AddRemoteRegisters( 4822349cc55cSDimitry Andric std::vector<DynamicRegisterInfo::Register> ®isters, 4823349cc55cSDimitry Andric const ArchSpec &arch_to_use) { 4824349cc55cSDimitry Andric std::map<uint32_t, uint32_t> remote_to_local_map; 4825349cc55cSDimitry Andric uint32_t remote_regnum = 0; 4826349cc55cSDimitry Andric for (auto it : llvm::enumerate(registers)) { 4827349cc55cSDimitry Andric DynamicRegisterInfo::Register &remote_reg_info = it.value(); 4828349cc55cSDimitry Andric 4829349cc55cSDimitry Andric // Assign successive remote regnums if missing. 4830349cc55cSDimitry Andric if (remote_reg_info.regnum_remote == LLDB_INVALID_REGNUM) 4831349cc55cSDimitry Andric remote_reg_info.regnum_remote = remote_regnum; 4832349cc55cSDimitry Andric 4833349cc55cSDimitry Andric // Create a mapping from remote to local regnos. 4834349cc55cSDimitry Andric remote_to_local_map[remote_reg_info.regnum_remote] = it.index(); 4835349cc55cSDimitry Andric 4836349cc55cSDimitry Andric remote_regnum = remote_reg_info.regnum_remote + 1; 4837349cc55cSDimitry Andric } 4838349cc55cSDimitry Andric 4839349cc55cSDimitry Andric for (DynamicRegisterInfo::Register &remote_reg_info : registers) { 4840349cc55cSDimitry Andric auto proc_to_lldb = [&remote_to_local_map](uint32_t process_regnum) { 4841349cc55cSDimitry Andric auto lldb_regit = remote_to_local_map.find(process_regnum); 4842349cc55cSDimitry Andric return lldb_regit != remote_to_local_map.end() ? lldb_regit->second 4843349cc55cSDimitry Andric : LLDB_INVALID_REGNUM; 4844349cc55cSDimitry Andric }; 4845349cc55cSDimitry Andric 4846349cc55cSDimitry Andric llvm::transform(remote_reg_info.value_regs, 4847349cc55cSDimitry Andric remote_reg_info.value_regs.begin(), proc_to_lldb); 4848349cc55cSDimitry Andric llvm::transform(remote_reg_info.invalidate_regs, 4849349cc55cSDimitry Andric remote_reg_info.invalidate_regs.begin(), proc_to_lldb); 4850349cc55cSDimitry Andric } 4851349cc55cSDimitry Andric 4852349cc55cSDimitry Andric // Don't use Process::GetABI, this code gets called from DidAttach, and 4853349cc55cSDimitry Andric // in that context we haven't set the Target's architecture yet, so the 4854349cc55cSDimitry Andric // ABI is also potentially incorrect. 4855349cc55cSDimitry Andric if (ABISP abi_sp = ABI::FindPlugin(shared_from_this(), arch_to_use)) 4856349cc55cSDimitry Andric abi_sp->AugmentRegisterInfo(registers); 4857349cc55cSDimitry Andric 4858349cc55cSDimitry Andric m_register_info_sp->SetRegisterInfo(std::move(registers), arch_to_use); 4859349cc55cSDimitry Andric } 4860349cc55cSDimitry Andric 48610b57cec5SDimitry Andric // query the target of gdb-remote for extended target information returns 48620b57cec5SDimitry Andric // true on success (got register definitions), false on failure (did not). 48630b57cec5SDimitry Andric bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) { 48640b57cec5SDimitry Andric // Make sure LLDB has an XML parser it can use first 48650b57cec5SDimitry Andric if (!XMLDocument::XMLEnabled()) 48660b57cec5SDimitry Andric return false; 48670b57cec5SDimitry Andric 48680b57cec5SDimitry Andric // check that we have extended feature read support 48690b57cec5SDimitry Andric if (!m_gdb_comm.GetQXferFeaturesReadSupported()) 48700b57cec5SDimitry Andric return false; 48710b57cec5SDimitry Andric 4872*0fca6ea1SDimitry Andric // These hold register type information for the whole of target.xml. 487306c3fb27SDimitry Andric // target.xml may include further documents that 487406c3fb27SDimitry Andric // GetGDBServerRegisterInfoXMLAndProcess will recurse to fetch and process. 487506c3fb27SDimitry Andric // That's why we clear the cache here, and not in 487606c3fb27SDimitry Andric // GetGDBServerRegisterInfoXMLAndProcess. To prevent it being cleared on every 487706c3fb27SDimitry Andric // include read. 487806c3fb27SDimitry Andric m_registers_flags_types.clear(); 4879*0fca6ea1SDimitry Andric m_registers_enum_types.clear(); 4880349cc55cSDimitry Andric std::vector<DynamicRegisterInfo::Register> registers; 4881e8d8bef9SDimitry Andric if (GetGDBServerRegisterInfoXMLAndProcess(arch_to_use, "target.xml", 4882*0fca6ea1SDimitry Andric registers) && 4883*0fca6ea1SDimitry Andric // Target XML is not required to include register information. 4884*0fca6ea1SDimitry Andric !registers.empty()) 4885349cc55cSDimitry Andric AddRemoteRegisters(registers, arch_to_use); 48860b57cec5SDimitry Andric 4887e8d8bef9SDimitry Andric return m_register_info_sp->GetNumRegisters() > 0; 48880b57cec5SDimitry Andric } 48890b57cec5SDimitry Andric 48909dba64beSDimitry Andric llvm::Expected<LoadedModuleInfoList> ProcessGDBRemote::GetLoadedModuleList() { 48910b57cec5SDimitry Andric // Make sure LLDB has an XML parser it can use first 48920b57cec5SDimitry Andric if (!XMLDocument::XMLEnabled()) 48939dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 48949dba64beSDimitry Andric "XML parsing not available"); 48950b57cec5SDimitry Andric 489681ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 48979dba64beSDimitry Andric LLDB_LOGF(log, "ProcessGDBRemote::%s", __FUNCTION__); 48980b57cec5SDimitry Andric 48999dba64beSDimitry Andric LoadedModuleInfoList list; 49000b57cec5SDimitry Andric GDBRemoteCommunicationClient &comm = m_gdb_comm; 4901349cc55cSDimitry Andric bool can_use_svr4 = GetGlobalPluginProperties().GetUseSVR4(); 49020b57cec5SDimitry Andric 49030b57cec5SDimitry Andric // check that we have extended feature read support 49040b57cec5SDimitry Andric if (can_use_svr4 && comm.GetQXferLibrariesSVR4ReadSupported()) { 49050b57cec5SDimitry Andric // request the loaded library list 4906349cc55cSDimitry Andric llvm::Expected<std::string> raw = comm.ReadExtFeature("libraries-svr4", ""); 4907349cc55cSDimitry Andric if (!raw) 4908349cc55cSDimitry Andric return raw.takeError(); 49090b57cec5SDimitry Andric 49100b57cec5SDimitry Andric // parse the xml file in memory 4911349cc55cSDimitry Andric LLDB_LOGF(log, "parsing: %s", raw->c_str()); 49120b57cec5SDimitry Andric XMLDocument doc; 49130b57cec5SDimitry Andric 4914349cc55cSDimitry Andric if (!doc.ParseMemory(raw->c_str(), raw->size(), "noname.xml")) 49159dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 49169dba64beSDimitry Andric "Error reading noname.xml"); 49170b57cec5SDimitry Andric 49180b57cec5SDimitry Andric XMLNode root_element = doc.GetRootElement("library-list-svr4"); 49190b57cec5SDimitry Andric if (!root_element) 49209dba64beSDimitry Andric return llvm::createStringError( 49219dba64beSDimitry Andric llvm::inconvertibleErrorCode(), 49229dba64beSDimitry Andric "Error finding library-list-svr4 xml element"); 49230b57cec5SDimitry Andric 49240b57cec5SDimitry Andric // main link map structure 492504eeddc0SDimitry Andric std::string main_lm = root_element.GetAttributeValue("main-lm"); 4926349cc55cSDimitry Andric // FIXME: we're silently ignoring invalid data here 4927349cc55cSDimitry Andric if (!main_lm.empty()) 4928349cc55cSDimitry Andric llvm::to_integer(main_lm, list.m_link_map); 49290b57cec5SDimitry Andric 49300b57cec5SDimitry Andric root_element.ForEachChildElementWithName( 49310b57cec5SDimitry Andric "library", [log, &list](const XMLNode &library) -> bool { 49320b57cec5SDimitry Andric LoadedModuleInfoList::LoadedModuleInfo module; 49330b57cec5SDimitry Andric 4934349cc55cSDimitry Andric // FIXME: we're silently ignoring invalid data here 49350b57cec5SDimitry Andric library.ForEachAttribute( 49360b57cec5SDimitry Andric [&module](const llvm::StringRef &name, 49370b57cec5SDimitry Andric const llvm::StringRef &value) -> bool { 4938349cc55cSDimitry Andric uint64_t uint_value = LLDB_INVALID_ADDRESS; 49390b57cec5SDimitry Andric if (name == "name") 49400b57cec5SDimitry Andric module.set_name(value.str()); 49410b57cec5SDimitry Andric else if (name == "lm") { 49420b57cec5SDimitry Andric // the address of the link_map struct. 4943349cc55cSDimitry Andric llvm::to_integer(value, uint_value); 4944349cc55cSDimitry Andric module.set_link_map(uint_value); 49450b57cec5SDimitry Andric } else if (name == "l_addr") { 49460b57cec5SDimitry Andric // the displacement as read from the field 'l_addr' of the 49470b57cec5SDimitry Andric // link_map struct. 4948349cc55cSDimitry Andric llvm::to_integer(value, uint_value); 4949349cc55cSDimitry Andric module.set_base(uint_value); 49500b57cec5SDimitry Andric // base address is always a displacement, not an absolute 49510b57cec5SDimitry Andric // value. 49520b57cec5SDimitry Andric module.set_base_is_offset(true); 49530b57cec5SDimitry Andric } else if (name == "l_ld") { 49545ffd83dbSDimitry Andric // the memory address of the libraries PT_DYNAMIC section. 4955349cc55cSDimitry Andric llvm::to_integer(value, uint_value); 4956349cc55cSDimitry Andric module.set_dynamic(uint_value); 49570b57cec5SDimitry Andric } 49580b57cec5SDimitry Andric 49590b57cec5SDimitry Andric return true; // Keep iterating over all properties of "library" 49600b57cec5SDimitry Andric }); 49610b57cec5SDimitry Andric 49620b57cec5SDimitry Andric if (log) { 49630b57cec5SDimitry Andric std::string name; 49640b57cec5SDimitry Andric lldb::addr_t lm = 0, base = 0, ld = 0; 49650b57cec5SDimitry Andric bool base_is_offset; 49660b57cec5SDimitry Andric 49670b57cec5SDimitry Andric module.get_name(name); 49680b57cec5SDimitry Andric module.get_link_map(lm); 49690b57cec5SDimitry Andric module.get_base(base); 49700b57cec5SDimitry Andric module.get_base_is_offset(base_is_offset); 49710b57cec5SDimitry Andric module.get_dynamic(ld); 49720b57cec5SDimitry Andric 49739dba64beSDimitry Andric LLDB_LOGF(log, 49749dba64beSDimitry Andric "found (link_map:0x%08" PRIx64 ", base:0x%08" PRIx64 49750b57cec5SDimitry Andric "[%s], ld:0x%08" PRIx64 ", name:'%s')", 49760b57cec5SDimitry Andric lm, base, (base_is_offset ? "offset" : "absolute"), ld, 49770b57cec5SDimitry Andric name.c_str()); 49780b57cec5SDimitry Andric } 49790b57cec5SDimitry Andric 49800b57cec5SDimitry Andric list.add(module); 49810b57cec5SDimitry Andric return true; // Keep iterating over all "library" elements in the root 49820b57cec5SDimitry Andric // node 49830b57cec5SDimitry Andric }); 49840b57cec5SDimitry Andric 49850b57cec5SDimitry Andric if (log) 49869dba64beSDimitry Andric LLDB_LOGF(log, "found %" PRId32 " modules in total", 49870b57cec5SDimitry Andric (int)list.m_list.size()); 49889dba64beSDimitry Andric return list; 49890b57cec5SDimitry Andric } else if (comm.GetQXferLibrariesReadSupported()) { 49900b57cec5SDimitry Andric // request the loaded library list 4991349cc55cSDimitry Andric llvm::Expected<std::string> raw = comm.ReadExtFeature("libraries", ""); 49920b57cec5SDimitry Andric 4993349cc55cSDimitry Andric if (!raw) 4994349cc55cSDimitry Andric return raw.takeError(); 49950b57cec5SDimitry Andric 4996349cc55cSDimitry Andric LLDB_LOGF(log, "parsing: %s", raw->c_str()); 49970b57cec5SDimitry Andric XMLDocument doc; 49980b57cec5SDimitry Andric 4999349cc55cSDimitry Andric if (!doc.ParseMemory(raw->c_str(), raw->size(), "noname.xml")) 50009dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 50019dba64beSDimitry Andric "Error reading noname.xml"); 50020b57cec5SDimitry Andric 50030b57cec5SDimitry Andric XMLNode root_element = doc.GetRootElement("library-list"); 50040b57cec5SDimitry Andric if (!root_element) 50059dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 50069dba64beSDimitry Andric "Error finding library-list xml element"); 50070b57cec5SDimitry Andric 5008349cc55cSDimitry Andric // FIXME: we're silently ignoring invalid data here 50090b57cec5SDimitry Andric root_element.ForEachChildElementWithName( 50100b57cec5SDimitry Andric "library", [log, &list](const XMLNode &library) -> bool { 50110b57cec5SDimitry Andric LoadedModuleInfoList::LoadedModuleInfo module; 50120b57cec5SDimitry Andric 501304eeddc0SDimitry Andric std::string name = library.GetAttributeValue("name"); 501404eeddc0SDimitry Andric module.set_name(name); 50150b57cec5SDimitry Andric 50160b57cec5SDimitry Andric // The base address of a given library will be the address of its 50170b57cec5SDimitry Andric // first section. Most remotes send only one section for Windows 50180b57cec5SDimitry Andric // targets for example. 50190b57cec5SDimitry Andric const XMLNode §ion = 50200b57cec5SDimitry Andric library.FindFirstChildElementWithName("section"); 502104eeddc0SDimitry Andric std::string address = section.GetAttributeValue("address"); 5022349cc55cSDimitry Andric uint64_t address_value = LLDB_INVALID_ADDRESS; 5023349cc55cSDimitry Andric llvm::to_integer(address, address_value); 5024349cc55cSDimitry Andric module.set_base(address_value); 50250b57cec5SDimitry Andric // These addresses are absolute values. 50260b57cec5SDimitry Andric module.set_base_is_offset(false); 50270b57cec5SDimitry Andric 50280b57cec5SDimitry Andric if (log) { 50290b57cec5SDimitry Andric std::string name; 50300b57cec5SDimitry Andric lldb::addr_t base = 0; 50310b57cec5SDimitry Andric bool base_is_offset; 50320b57cec5SDimitry Andric module.get_name(name); 50330b57cec5SDimitry Andric module.get_base(base); 50340b57cec5SDimitry Andric module.get_base_is_offset(base_is_offset); 50350b57cec5SDimitry Andric 50369dba64beSDimitry Andric LLDB_LOGF(log, "found (base:0x%08" PRIx64 "[%s], name:'%s')", base, 50370b57cec5SDimitry Andric (base_is_offset ? "offset" : "absolute"), name.c_str()); 50380b57cec5SDimitry Andric } 50390b57cec5SDimitry Andric 50400b57cec5SDimitry Andric list.add(module); 50410b57cec5SDimitry Andric return true; // Keep iterating over all "library" elements in the root 50420b57cec5SDimitry Andric // node 50430b57cec5SDimitry Andric }); 50440b57cec5SDimitry Andric 50450b57cec5SDimitry Andric if (log) 50469dba64beSDimitry Andric LLDB_LOGF(log, "found %" PRId32 " modules in total", 50470b57cec5SDimitry Andric (int)list.m_list.size()); 50489dba64beSDimitry Andric return list; 50490b57cec5SDimitry Andric } else { 50509dba64beSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 50519dba64beSDimitry Andric "Remote libraries not supported"); 50520b57cec5SDimitry Andric } 50530b57cec5SDimitry Andric } 50540b57cec5SDimitry Andric 50550b57cec5SDimitry Andric lldb::ModuleSP ProcessGDBRemote::LoadModuleAtAddress(const FileSpec &file, 50560b57cec5SDimitry Andric lldb::addr_t link_map, 50570b57cec5SDimitry Andric lldb::addr_t base_addr, 50580b57cec5SDimitry Andric bool value_is_offset) { 50590b57cec5SDimitry Andric DynamicLoader *loader = GetDynamicLoader(); 50600b57cec5SDimitry Andric if (!loader) 50610b57cec5SDimitry Andric return nullptr; 50620b57cec5SDimitry Andric 50630b57cec5SDimitry Andric return loader->LoadModuleAtAddress(file, link_map, base_addr, 50640b57cec5SDimitry Andric value_is_offset); 50650b57cec5SDimitry Andric } 50660b57cec5SDimitry Andric 50679dba64beSDimitry Andric llvm::Error ProcessGDBRemote::LoadModules() { 50680b57cec5SDimitry Andric using lldb_private::process_gdb_remote::ProcessGDBRemote; 50690b57cec5SDimitry Andric 50700b57cec5SDimitry Andric // request a list of loaded libraries from GDBServer 50719dba64beSDimitry Andric llvm::Expected<LoadedModuleInfoList> module_list = GetLoadedModuleList(); 50729dba64beSDimitry Andric if (!module_list) 50739dba64beSDimitry Andric return module_list.takeError(); 50740b57cec5SDimitry Andric 50750b57cec5SDimitry Andric // get a list of all the modules 50760b57cec5SDimitry Andric ModuleList new_modules; 50770b57cec5SDimitry Andric 50789dba64beSDimitry Andric for (LoadedModuleInfoList::LoadedModuleInfo &modInfo : module_list->m_list) { 50790b57cec5SDimitry Andric std::string mod_name; 50800b57cec5SDimitry Andric lldb::addr_t mod_base; 50810b57cec5SDimitry Andric lldb::addr_t link_map; 50820b57cec5SDimitry Andric bool mod_base_is_offset; 50830b57cec5SDimitry Andric 50840b57cec5SDimitry Andric bool valid = true; 50850b57cec5SDimitry Andric valid &= modInfo.get_name(mod_name); 50860b57cec5SDimitry Andric valid &= modInfo.get_base(mod_base); 50870b57cec5SDimitry Andric valid &= modInfo.get_base_is_offset(mod_base_is_offset); 50880b57cec5SDimitry Andric if (!valid) 50890b57cec5SDimitry Andric continue; 50900b57cec5SDimitry Andric 50910b57cec5SDimitry Andric if (!modInfo.get_link_map(link_map)) 50920b57cec5SDimitry Andric link_map = LLDB_INVALID_ADDRESS; 50930b57cec5SDimitry Andric 50940b57cec5SDimitry Andric FileSpec file(mod_name); 50950b57cec5SDimitry Andric FileSystem::Instance().Resolve(file); 50960b57cec5SDimitry Andric lldb::ModuleSP module_sp = 50970b57cec5SDimitry Andric LoadModuleAtAddress(file, link_map, mod_base, mod_base_is_offset); 50980b57cec5SDimitry Andric 50990b57cec5SDimitry Andric if (module_sp.get()) 51000b57cec5SDimitry Andric new_modules.Append(module_sp); 51010b57cec5SDimitry Andric } 51020b57cec5SDimitry Andric 51030b57cec5SDimitry Andric if (new_modules.GetSize() > 0) { 51040b57cec5SDimitry Andric ModuleList removed_modules; 51050b57cec5SDimitry Andric Target &target = GetTarget(); 51060b57cec5SDimitry Andric ModuleList &loaded_modules = m_process->GetTarget().GetImages(); 51070b57cec5SDimitry Andric 51080b57cec5SDimitry Andric for (size_t i = 0; i < loaded_modules.GetSize(); ++i) { 51090b57cec5SDimitry Andric const lldb::ModuleSP loaded_module = loaded_modules.GetModuleAtIndex(i); 51100b57cec5SDimitry Andric 51110b57cec5SDimitry Andric bool found = false; 51120b57cec5SDimitry Andric for (size_t j = 0; j < new_modules.GetSize(); ++j) { 51130b57cec5SDimitry Andric if (new_modules.GetModuleAtIndex(j).get() == loaded_module.get()) 51140b57cec5SDimitry Andric found = true; 51150b57cec5SDimitry Andric } 51160b57cec5SDimitry Andric 51170b57cec5SDimitry Andric // The main executable will never be included in libraries-svr4, don't 51180b57cec5SDimitry Andric // remove it 51190b57cec5SDimitry Andric if (!found && 51200b57cec5SDimitry Andric loaded_module.get() != target.GetExecutableModulePointer()) { 51210b57cec5SDimitry Andric removed_modules.Append(loaded_module); 51220b57cec5SDimitry Andric } 51230b57cec5SDimitry Andric } 51240b57cec5SDimitry Andric 51250b57cec5SDimitry Andric loaded_modules.Remove(removed_modules); 51260b57cec5SDimitry Andric m_process->GetTarget().ModulesDidUnload(removed_modules, false); 51270b57cec5SDimitry Andric 51280b57cec5SDimitry Andric new_modules.ForEach([&target](const lldb::ModuleSP module_sp) -> bool { 51290b57cec5SDimitry Andric lldb_private::ObjectFile *obj = module_sp->GetObjectFile(); 51300b57cec5SDimitry Andric if (!obj) 51310b57cec5SDimitry Andric return true; 51320b57cec5SDimitry Andric 51330b57cec5SDimitry Andric if (obj->GetType() != ObjectFile::Type::eTypeExecutable) 51340b57cec5SDimitry Andric return true; 51350b57cec5SDimitry Andric 51360b57cec5SDimitry Andric lldb::ModuleSP module_copy_sp = module_sp; 51370b57cec5SDimitry Andric target.SetExecutableModule(module_copy_sp, eLoadDependentsNo); 51380b57cec5SDimitry Andric return false; 51390b57cec5SDimitry Andric }); 51400b57cec5SDimitry Andric 51410b57cec5SDimitry Andric loaded_modules.AppendIfNeeded(new_modules); 51420b57cec5SDimitry Andric m_process->GetTarget().ModulesDidLoad(new_modules); 51430b57cec5SDimitry Andric } 51440b57cec5SDimitry Andric 51459dba64beSDimitry Andric return llvm::ErrorSuccess(); 51460b57cec5SDimitry Andric } 51470b57cec5SDimitry Andric 51480b57cec5SDimitry Andric Status ProcessGDBRemote::GetFileLoadAddress(const FileSpec &file, 51490b57cec5SDimitry Andric bool &is_loaded, 51500b57cec5SDimitry Andric lldb::addr_t &load_addr) { 51510b57cec5SDimitry Andric is_loaded = false; 51520b57cec5SDimitry Andric load_addr = LLDB_INVALID_ADDRESS; 51530b57cec5SDimitry Andric 51540b57cec5SDimitry Andric std::string file_path = file.GetPath(false); 51550b57cec5SDimitry Andric if (file_path.empty()) 51560b57cec5SDimitry Andric return Status("Empty file name specified"); 51570b57cec5SDimitry Andric 51580b57cec5SDimitry Andric StreamString packet; 51590b57cec5SDimitry Andric packet.PutCString("qFileLoadAddress:"); 51600b57cec5SDimitry Andric packet.PutStringAsRawHex8(file_path); 51610b57cec5SDimitry Andric 51620b57cec5SDimitry Andric StringExtractorGDBRemote response; 5163fe6060f1SDimitry Andric if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) != 51640b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult::Success) 51650b57cec5SDimitry Andric return Status("Sending qFileLoadAddress packet failed"); 51660b57cec5SDimitry Andric 51670b57cec5SDimitry Andric if (response.IsErrorResponse()) { 51680b57cec5SDimitry Andric if (response.GetError() == 1) { 51690b57cec5SDimitry Andric // The file is not loaded into the inferior 51700b57cec5SDimitry Andric is_loaded = false; 51710b57cec5SDimitry Andric load_addr = LLDB_INVALID_ADDRESS; 51720b57cec5SDimitry Andric return Status(); 51730b57cec5SDimitry Andric } 51740b57cec5SDimitry Andric 51750b57cec5SDimitry Andric return Status( 51760b57cec5SDimitry Andric "Fetching file load address from remote server returned an error"); 51770b57cec5SDimitry Andric } 51780b57cec5SDimitry Andric 51790b57cec5SDimitry Andric if (response.IsNormalResponse()) { 51800b57cec5SDimitry Andric is_loaded = true; 51810b57cec5SDimitry Andric load_addr = response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); 51820b57cec5SDimitry Andric return Status(); 51830b57cec5SDimitry Andric } 51840b57cec5SDimitry Andric 51850b57cec5SDimitry Andric return Status( 51860b57cec5SDimitry Andric "Unknown error happened during sending the load address packet"); 51870b57cec5SDimitry Andric } 51880b57cec5SDimitry Andric 51890b57cec5SDimitry Andric void ProcessGDBRemote::ModulesDidLoad(ModuleList &module_list) { 51900b57cec5SDimitry Andric // We must call the lldb_private::Process::ModulesDidLoad () first before we 51910b57cec5SDimitry Andric // do anything 51920b57cec5SDimitry Andric Process::ModulesDidLoad(module_list); 51930b57cec5SDimitry Andric 51940b57cec5SDimitry Andric // After loading shared libraries, we can ask our remote GDB server if it 51950b57cec5SDimitry Andric // needs any symbols. 51960b57cec5SDimitry Andric m_gdb_comm.ServeSymbolLookups(this); 51970b57cec5SDimitry Andric } 51980b57cec5SDimitry Andric 51990b57cec5SDimitry Andric void ProcessGDBRemote::HandleAsyncStdout(llvm::StringRef out) { 52000b57cec5SDimitry Andric AppendSTDOUT(out.data(), out.size()); 52010b57cec5SDimitry Andric } 52020b57cec5SDimitry Andric 52030b57cec5SDimitry Andric static const char *end_delimiter = "--end--;"; 52040b57cec5SDimitry Andric static const int end_delimiter_len = 8; 52050b57cec5SDimitry Andric 52060b57cec5SDimitry Andric void ProcessGDBRemote::HandleAsyncMisc(llvm::StringRef data) { 52070b57cec5SDimitry Andric std::string input = data.str(); // '1' to move beyond 'A' 52080b57cec5SDimitry Andric if (m_partial_profile_data.length() > 0) { 52090b57cec5SDimitry Andric m_partial_profile_data.append(input); 52100b57cec5SDimitry Andric input = m_partial_profile_data; 52110b57cec5SDimitry Andric m_partial_profile_data.clear(); 52120b57cec5SDimitry Andric } 52130b57cec5SDimitry Andric 52140b57cec5SDimitry Andric size_t found, pos = 0, len = input.length(); 52150b57cec5SDimitry Andric while ((found = input.find(end_delimiter, pos)) != std::string::npos) { 52160b57cec5SDimitry Andric StringExtractorGDBRemote profileDataExtractor( 52170b57cec5SDimitry Andric input.substr(pos, found).c_str()); 52180b57cec5SDimitry Andric std::string profile_data = 52190b57cec5SDimitry Andric HarmonizeThreadIdsForProfileData(profileDataExtractor); 52200b57cec5SDimitry Andric BroadcastAsyncProfileData(profile_data); 52210b57cec5SDimitry Andric 52220b57cec5SDimitry Andric pos = found + end_delimiter_len; 52230b57cec5SDimitry Andric } 52240b57cec5SDimitry Andric 52250b57cec5SDimitry Andric if (pos < len) { 52260b57cec5SDimitry Andric // Last incomplete chunk. 52270b57cec5SDimitry Andric m_partial_profile_data = input.substr(pos); 52280b57cec5SDimitry Andric } 52290b57cec5SDimitry Andric } 52300b57cec5SDimitry Andric 52310b57cec5SDimitry Andric std::string ProcessGDBRemote::HarmonizeThreadIdsForProfileData( 52320b57cec5SDimitry Andric StringExtractorGDBRemote &profileDataExtractor) { 52330b57cec5SDimitry Andric std::map<uint64_t, uint32_t> new_thread_id_to_used_usec_map; 52340b57cec5SDimitry Andric std::string output; 52350b57cec5SDimitry Andric llvm::raw_string_ostream output_stream(output); 52360b57cec5SDimitry Andric llvm::StringRef name, value; 52370b57cec5SDimitry Andric 52380b57cec5SDimitry Andric // Going to assuming thread_used_usec comes first, else bail out. 52390b57cec5SDimitry Andric while (profileDataExtractor.GetNameColonValue(name, value)) { 52400b57cec5SDimitry Andric if (name.compare("thread_used_id") == 0) { 52410b57cec5SDimitry Andric StringExtractor threadIDHexExtractor(value); 52420b57cec5SDimitry Andric uint64_t thread_id = threadIDHexExtractor.GetHexMaxU64(false, 0); 52430b57cec5SDimitry Andric 52440b57cec5SDimitry Andric bool has_used_usec = false; 52450b57cec5SDimitry Andric uint32_t curr_used_usec = 0; 52460b57cec5SDimitry Andric llvm::StringRef usec_name, usec_value; 52470b57cec5SDimitry Andric uint32_t input_file_pos = profileDataExtractor.GetFilePos(); 52480b57cec5SDimitry Andric if (profileDataExtractor.GetNameColonValue(usec_name, usec_value)) { 5249*0fca6ea1SDimitry Andric if (usec_name == "thread_used_usec") { 52500b57cec5SDimitry Andric has_used_usec = true; 52510b57cec5SDimitry Andric usec_value.getAsInteger(0, curr_used_usec); 52520b57cec5SDimitry Andric } else { 52530b57cec5SDimitry Andric // We didn't find what we want, it is probably an older version. Bail 52540b57cec5SDimitry Andric // out. 52550b57cec5SDimitry Andric profileDataExtractor.SetFilePos(input_file_pos); 52560b57cec5SDimitry Andric } 52570b57cec5SDimitry Andric } 52580b57cec5SDimitry Andric 52590b57cec5SDimitry Andric if (has_used_usec) { 52600b57cec5SDimitry Andric uint32_t prev_used_usec = 0; 52610b57cec5SDimitry Andric std::map<uint64_t, uint32_t>::iterator iterator = 52620b57cec5SDimitry Andric m_thread_id_to_used_usec_map.find(thread_id); 52630b57cec5SDimitry Andric if (iterator != m_thread_id_to_used_usec_map.end()) { 52640b57cec5SDimitry Andric prev_used_usec = m_thread_id_to_used_usec_map[thread_id]; 52650b57cec5SDimitry Andric } 52660b57cec5SDimitry Andric 52670b57cec5SDimitry Andric uint32_t real_used_usec = curr_used_usec - prev_used_usec; 52680b57cec5SDimitry Andric // A good first time record is one that runs for at least 0.25 sec 52690b57cec5SDimitry Andric bool good_first_time = 52700b57cec5SDimitry Andric (prev_used_usec == 0) && (real_used_usec > 250000); 52710b57cec5SDimitry Andric bool good_subsequent_time = 52720b57cec5SDimitry Andric (prev_used_usec > 0) && 52730b57cec5SDimitry Andric ((real_used_usec > 0) || (HasAssignedIndexIDToThread(thread_id))); 52740b57cec5SDimitry Andric 52750b57cec5SDimitry Andric if (good_first_time || good_subsequent_time) { 52760b57cec5SDimitry Andric // We try to avoid doing too many index id reservation, resulting in 52770b57cec5SDimitry Andric // fast increase of index ids. 52780b57cec5SDimitry Andric 52790b57cec5SDimitry Andric output_stream << name << ":"; 52800b57cec5SDimitry Andric int32_t index_id = AssignIndexIDToThread(thread_id); 52810b57cec5SDimitry Andric output_stream << index_id << ";"; 52820b57cec5SDimitry Andric 52830b57cec5SDimitry Andric output_stream << usec_name << ":" << usec_value << ";"; 52840b57cec5SDimitry Andric } else { 52850b57cec5SDimitry Andric // Skip past 'thread_used_name'. 52860b57cec5SDimitry Andric llvm::StringRef local_name, local_value; 52870b57cec5SDimitry Andric profileDataExtractor.GetNameColonValue(local_name, local_value); 52880b57cec5SDimitry Andric } 52890b57cec5SDimitry Andric 52900b57cec5SDimitry Andric // Store current time as previous time so that they can be compared 52910b57cec5SDimitry Andric // later. 52920b57cec5SDimitry Andric new_thread_id_to_used_usec_map[thread_id] = curr_used_usec; 52930b57cec5SDimitry Andric } else { 52940b57cec5SDimitry Andric // Bail out and use old string. 52950b57cec5SDimitry Andric output_stream << name << ":" << value << ";"; 52960b57cec5SDimitry Andric } 52970b57cec5SDimitry Andric } else { 52980b57cec5SDimitry Andric output_stream << name << ":" << value << ";"; 52990b57cec5SDimitry Andric } 53000b57cec5SDimitry Andric } 53010b57cec5SDimitry Andric output_stream << end_delimiter; 53020b57cec5SDimitry Andric m_thread_id_to_used_usec_map = new_thread_id_to_used_usec_map; 53030b57cec5SDimitry Andric 53040b57cec5SDimitry Andric return output_stream.str(); 53050b57cec5SDimitry Andric } 53060b57cec5SDimitry Andric 53070b57cec5SDimitry Andric void ProcessGDBRemote::HandleStopReply() { 53080b57cec5SDimitry Andric if (GetStopID() != 0) 53090b57cec5SDimitry Andric return; 53100b57cec5SDimitry Andric 53110b57cec5SDimitry Andric if (GetID() == LLDB_INVALID_PROCESS_ID) { 53120b57cec5SDimitry Andric lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID(); 53130b57cec5SDimitry Andric if (pid != LLDB_INVALID_PROCESS_ID) 53140b57cec5SDimitry Andric SetID(pid); 53150b57cec5SDimitry Andric } 53160b57cec5SDimitry Andric BuildDynamicRegisterInfo(true); 53170b57cec5SDimitry Andric } 53180b57cec5SDimitry Andric 5319349cc55cSDimitry Andric llvm::Expected<bool> ProcessGDBRemote::SaveCore(llvm::StringRef outfile) { 5320349cc55cSDimitry Andric if (!m_gdb_comm.GetSaveCoreSupported()) 5321349cc55cSDimitry Andric return false; 5322349cc55cSDimitry Andric 5323349cc55cSDimitry Andric StreamString packet; 5324349cc55cSDimitry Andric packet.PutCString("qSaveCore;path-hint:"); 5325349cc55cSDimitry Andric packet.PutStringAsRawHex8(outfile); 5326349cc55cSDimitry Andric 5327349cc55cSDimitry Andric StringExtractorGDBRemote response; 5328349cc55cSDimitry Andric if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) == 5329349cc55cSDimitry Andric GDBRemoteCommunication::PacketResult::Success) { 5330349cc55cSDimitry Andric // TODO: grab error message from the packet? StringExtractor seems to 5331349cc55cSDimitry Andric // be missing a method for that 5332349cc55cSDimitry Andric if (response.IsErrorResponse()) 5333349cc55cSDimitry Andric return llvm::createStringError( 5334349cc55cSDimitry Andric llvm::inconvertibleErrorCode(), 5335349cc55cSDimitry Andric llvm::formatv("qSaveCore returned an error")); 5336349cc55cSDimitry Andric 5337349cc55cSDimitry Andric std::string path; 5338349cc55cSDimitry Andric 5339349cc55cSDimitry Andric // process the response 5340349cc55cSDimitry Andric for (auto x : llvm::split(response.GetStringRef(), ';')) { 5341349cc55cSDimitry Andric if (x.consume_front("core-path:")) 5342349cc55cSDimitry Andric StringExtractor(x).GetHexByteString(path); 5343349cc55cSDimitry Andric } 5344349cc55cSDimitry Andric 5345349cc55cSDimitry Andric // verify that we've gotten what we need 5346349cc55cSDimitry Andric if (path.empty()) 5347349cc55cSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 5348349cc55cSDimitry Andric "qSaveCore returned no core path"); 5349349cc55cSDimitry Andric 5350349cc55cSDimitry Andric // now transfer the core file 5351349cc55cSDimitry Andric FileSpec remote_core{llvm::StringRef(path)}; 5352349cc55cSDimitry Andric Platform &platform = *GetTarget().GetPlatform(); 5353349cc55cSDimitry Andric Status error = platform.GetFile(remote_core, FileSpec(outfile)); 5354349cc55cSDimitry Andric 5355349cc55cSDimitry Andric if (platform.IsRemote()) { 5356349cc55cSDimitry Andric // NB: we unlink the file on error too 5357349cc55cSDimitry Andric platform.Unlink(remote_core); 5358349cc55cSDimitry Andric if (error.Fail()) 5359349cc55cSDimitry Andric return error.ToError(); 5360349cc55cSDimitry Andric } 5361349cc55cSDimitry Andric 5362349cc55cSDimitry Andric return true; 5363349cc55cSDimitry Andric } 5364349cc55cSDimitry Andric 5365349cc55cSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 5366349cc55cSDimitry Andric "Unable to send qSaveCore"); 5367349cc55cSDimitry Andric } 5368349cc55cSDimitry Andric 53690b57cec5SDimitry Andric static const char *const s_async_json_packet_prefix = "JSON-async:"; 53700b57cec5SDimitry Andric 53710b57cec5SDimitry Andric static StructuredData::ObjectSP 53720b57cec5SDimitry Andric ParseStructuredDataPacket(llvm::StringRef packet) { 53731fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 53740b57cec5SDimitry Andric 53750b57cec5SDimitry Andric if (!packet.consume_front(s_async_json_packet_prefix)) { 53760b57cec5SDimitry Andric if (log) { 53779dba64beSDimitry Andric LLDB_LOGF( 53789dba64beSDimitry Andric log, 53790b57cec5SDimitry Andric "GDBRemoteCommunicationClientBase::%s() received $J packet " 53800b57cec5SDimitry Andric "but was not a StructuredData packet: packet starts with " 53810b57cec5SDimitry Andric "%s", 53820b57cec5SDimitry Andric __FUNCTION__, 53830b57cec5SDimitry Andric packet.slice(0, strlen(s_async_json_packet_prefix)).str().c_str()); 53840b57cec5SDimitry Andric } 53850b57cec5SDimitry Andric return StructuredData::ObjectSP(); 53860b57cec5SDimitry Andric } 53870b57cec5SDimitry Andric 53880b57cec5SDimitry Andric // This is an asynchronous JSON packet, destined for a StructuredDataPlugin. 538906c3fb27SDimitry Andric StructuredData::ObjectSP json_sp = StructuredData::ParseJSON(packet); 53900b57cec5SDimitry Andric if (log) { 53910b57cec5SDimitry Andric if (json_sp) { 53920b57cec5SDimitry Andric StreamString json_str; 53939dba64beSDimitry Andric json_sp->Dump(json_str, true); 53940b57cec5SDimitry Andric json_str.Flush(); 53959dba64beSDimitry Andric LLDB_LOGF(log, 53969dba64beSDimitry Andric "ProcessGDBRemote::%s() " 53970b57cec5SDimitry Andric "received Async StructuredData packet: %s", 53980b57cec5SDimitry Andric __FUNCTION__, json_str.GetData()); 53990b57cec5SDimitry Andric } else { 54009dba64beSDimitry Andric LLDB_LOGF(log, 54019dba64beSDimitry Andric "ProcessGDBRemote::%s" 54020b57cec5SDimitry Andric "() received StructuredData packet:" 54030b57cec5SDimitry Andric " parse failure", 54040b57cec5SDimitry Andric __FUNCTION__); 54050b57cec5SDimitry Andric } 54060b57cec5SDimitry Andric } 54070b57cec5SDimitry Andric return json_sp; 54080b57cec5SDimitry Andric } 54090b57cec5SDimitry Andric 54100b57cec5SDimitry Andric void ProcessGDBRemote::HandleAsyncStructuredDataPacket(llvm::StringRef data) { 54110b57cec5SDimitry Andric auto structured_data_sp = ParseStructuredDataPacket(data); 54120b57cec5SDimitry Andric if (structured_data_sp) 54130b57cec5SDimitry Andric RouteAsyncStructuredData(structured_data_sp); 54140b57cec5SDimitry Andric } 54150b57cec5SDimitry Andric 54160b57cec5SDimitry Andric class CommandObjectProcessGDBRemoteSpeedTest : public CommandObjectParsed { 54170b57cec5SDimitry Andric public: 54180b57cec5SDimitry Andric CommandObjectProcessGDBRemoteSpeedTest(CommandInterpreter &interpreter) 54190b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process plugin packet speed-test", 54200b57cec5SDimitry Andric "Tests packet speeds of various sizes to determine " 54210b57cec5SDimitry Andric "the performance characteristics of the GDB remote " 54220b57cec5SDimitry Andric "connection. ", 54230b57cec5SDimitry Andric nullptr), 54240b57cec5SDimitry Andric m_option_group(), 54250b57cec5SDimitry Andric m_num_packets(LLDB_OPT_SET_1, false, "count", 'c', 0, eArgTypeCount, 54260b57cec5SDimitry Andric "The number of packets to send of each varying size " 54270b57cec5SDimitry Andric "(default is 1000).", 54280b57cec5SDimitry Andric 1000), 54290b57cec5SDimitry Andric m_max_send(LLDB_OPT_SET_1, false, "max-send", 's', 0, eArgTypeCount, 54300b57cec5SDimitry Andric "The maximum number of bytes to send in a packet. Sizes " 54310b57cec5SDimitry Andric "increase in powers of 2 while the size is less than or " 54320b57cec5SDimitry Andric "equal to this option value. (default 1024).", 54330b57cec5SDimitry Andric 1024), 54340b57cec5SDimitry Andric m_max_recv(LLDB_OPT_SET_1, false, "max-receive", 'r', 0, eArgTypeCount, 54350b57cec5SDimitry Andric "The maximum number of bytes to receive in a packet. Sizes " 54360b57cec5SDimitry Andric "increase in powers of 2 while the size is less than or " 54370b57cec5SDimitry Andric "equal to this option value. (default 1024).", 54380b57cec5SDimitry Andric 1024), 54390b57cec5SDimitry Andric m_json(LLDB_OPT_SET_1, false, "json", 'j', 54400b57cec5SDimitry Andric "Print the output as JSON data for easy parsing.", false, true) { 54410b57cec5SDimitry Andric m_option_group.Append(&m_num_packets, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 54420b57cec5SDimitry Andric m_option_group.Append(&m_max_send, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 54430b57cec5SDimitry Andric m_option_group.Append(&m_max_recv, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 54440b57cec5SDimitry Andric m_option_group.Append(&m_json, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 54450b57cec5SDimitry Andric m_option_group.Finalize(); 54460b57cec5SDimitry Andric } 54470b57cec5SDimitry Andric 5448fe6060f1SDimitry Andric ~CommandObjectProcessGDBRemoteSpeedTest() override = default; 54490b57cec5SDimitry Andric 54500b57cec5SDimitry Andric Options *GetOptions() override { return &m_option_group; } 54510b57cec5SDimitry Andric 54525f757f3fSDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override { 54530b57cec5SDimitry Andric const size_t argc = command.GetArgumentCount(); 54540b57cec5SDimitry Andric if (argc == 0) { 54550b57cec5SDimitry Andric ProcessGDBRemote *process = 54560b57cec5SDimitry Andric (ProcessGDBRemote *)m_interpreter.GetExecutionContext() 54570b57cec5SDimitry Andric .GetProcessPtr(); 54580b57cec5SDimitry Andric if (process) { 5459*0fca6ea1SDimitry Andric StreamSP output_stream_sp = result.GetImmediateOutputStream(); 5460*0fca6ea1SDimitry Andric if (!output_stream_sp) 5461*0fca6ea1SDimitry Andric output_stream_sp = 5462*0fca6ea1SDimitry Andric StreamSP(m_interpreter.GetDebugger().GetAsyncOutputStream()); 54630b57cec5SDimitry Andric result.SetImmediateOutputStream(output_stream_sp); 54640b57cec5SDimitry Andric 54650b57cec5SDimitry Andric const uint32_t num_packets = 54660b57cec5SDimitry Andric (uint32_t)m_num_packets.GetOptionValue().GetCurrentValue(); 54670b57cec5SDimitry Andric const uint64_t max_send = m_max_send.GetOptionValue().GetCurrentValue(); 54680b57cec5SDimitry Andric const uint64_t max_recv = m_max_recv.GetOptionValue().GetCurrentValue(); 54690b57cec5SDimitry Andric const bool json = m_json.GetOptionValue().GetCurrentValue(); 54700b57cec5SDimitry Andric const uint64_t k_recv_amount = 54710b57cec5SDimitry Andric 4 * 1024 * 1024; // Receive amount in bytes 54720b57cec5SDimitry Andric process->GetGDBRemote().TestPacketSpeed( 54730b57cec5SDimitry Andric num_packets, max_send, max_recv, k_recv_amount, json, 54740b57cec5SDimitry Andric output_stream_sp ? *output_stream_sp : result.GetOutputStream()); 54750b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 54765f757f3fSDimitry Andric return; 54770b57cec5SDimitry Andric } 54780b57cec5SDimitry Andric } else { 54790b57cec5SDimitry Andric result.AppendErrorWithFormat("'%s' takes no arguments", 54800b57cec5SDimitry Andric m_cmd_name.c_str()); 54810b57cec5SDimitry Andric } 54820b57cec5SDimitry Andric result.SetStatus(eReturnStatusFailed); 54830b57cec5SDimitry Andric } 54840b57cec5SDimitry Andric 54850b57cec5SDimitry Andric protected: 54860b57cec5SDimitry Andric OptionGroupOptions m_option_group; 54870b57cec5SDimitry Andric OptionGroupUInt64 m_num_packets; 54880b57cec5SDimitry Andric OptionGroupUInt64 m_max_send; 54890b57cec5SDimitry Andric OptionGroupUInt64 m_max_recv; 54900b57cec5SDimitry Andric OptionGroupBoolean m_json; 54910b57cec5SDimitry Andric }; 54920b57cec5SDimitry Andric 54930b57cec5SDimitry Andric class CommandObjectProcessGDBRemotePacketHistory : public CommandObjectParsed { 54940b57cec5SDimitry Andric private: 54950b57cec5SDimitry Andric public: 54960b57cec5SDimitry Andric CommandObjectProcessGDBRemotePacketHistory(CommandInterpreter &interpreter) 54970b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process plugin packet history", 54980b57cec5SDimitry Andric "Dumps the packet history buffer. ", nullptr) {} 54990b57cec5SDimitry Andric 5500fe6060f1SDimitry Andric ~CommandObjectProcessGDBRemotePacketHistory() override = default; 55010b57cec5SDimitry Andric 55025f757f3fSDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override { 55030b57cec5SDimitry Andric ProcessGDBRemote *process = 550481ad6265SDimitry Andric (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr(); 55050b57cec5SDimitry Andric if (process) { 550606c3fb27SDimitry Andric process->DumpPluginHistory(result.GetOutputStream()); 55070b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 55085f757f3fSDimitry Andric return; 55090b57cec5SDimitry Andric } 55100b57cec5SDimitry Andric result.SetStatus(eReturnStatusFailed); 55110b57cec5SDimitry Andric } 55120b57cec5SDimitry Andric }; 55130b57cec5SDimitry Andric 55140b57cec5SDimitry Andric class CommandObjectProcessGDBRemotePacketXferSize : public CommandObjectParsed { 55150b57cec5SDimitry Andric private: 55160b57cec5SDimitry Andric public: 55170b57cec5SDimitry Andric CommandObjectProcessGDBRemotePacketXferSize(CommandInterpreter &interpreter) 55180b57cec5SDimitry Andric : CommandObjectParsed( 55190b57cec5SDimitry Andric interpreter, "process plugin packet xfer-size", 55200b57cec5SDimitry Andric "Maximum size that lldb will try to read/write one one chunk.", 552181ad6265SDimitry Andric nullptr) { 5522*0fca6ea1SDimitry Andric AddSimpleArgumentList(eArgTypeUnsignedInteger); 552381ad6265SDimitry Andric } 55240b57cec5SDimitry Andric 5525fe6060f1SDimitry Andric ~CommandObjectProcessGDBRemotePacketXferSize() override = default; 55260b57cec5SDimitry Andric 55275f757f3fSDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override { 55280b57cec5SDimitry Andric const size_t argc = command.GetArgumentCount(); 55290b57cec5SDimitry Andric if (argc == 0) { 55300b57cec5SDimitry Andric result.AppendErrorWithFormat("'%s' takes an argument to specify the max " 55310b57cec5SDimitry Andric "amount to be transferred when " 55320b57cec5SDimitry Andric "reading/writing", 55330b57cec5SDimitry Andric m_cmd_name.c_str()); 55345f757f3fSDimitry Andric return; 55350b57cec5SDimitry Andric } 55360b57cec5SDimitry Andric 55370b57cec5SDimitry Andric ProcessGDBRemote *process = 55380b57cec5SDimitry Andric (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr(); 55390b57cec5SDimitry Andric if (process) { 55400b57cec5SDimitry Andric const char *packet_size = command.GetArgumentAtIndex(0); 55410b57cec5SDimitry Andric errno = 0; 55420b57cec5SDimitry Andric uint64_t user_specified_max = strtoul(packet_size, nullptr, 10); 55430b57cec5SDimitry Andric if (errno == 0 && user_specified_max != 0) { 55440b57cec5SDimitry Andric process->SetUserSpecifiedMaxMemoryTransferSize(user_specified_max); 55450b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 55465f757f3fSDimitry Andric return; 55470b57cec5SDimitry Andric } 55480b57cec5SDimitry Andric } 55490b57cec5SDimitry Andric result.SetStatus(eReturnStatusFailed); 55500b57cec5SDimitry Andric } 55510b57cec5SDimitry Andric }; 55520b57cec5SDimitry Andric 55530b57cec5SDimitry Andric class CommandObjectProcessGDBRemotePacketSend : public CommandObjectParsed { 55540b57cec5SDimitry Andric private: 55550b57cec5SDimitry Andric public: 55560b57cec5SDimitry Andric CommandObjectProcessGDBRemotePacketSend(CommandInterpreter &interpreter) 55570b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process plugin packet send", 55580b57cec5SDimitry Andric "Send a custom packet through the GDB remote " 55590b57cec5SDimitry Andric "protocol and print the answer. " 55600b57cec5SDimitry Andric "The packet header and footer will automatically " 55610b57cec5SDimitry Andric "be added to the packet prior to sending and " 55620b57cec5SDimitry Andric "stripped from the result.", 556381ad6265SDimitry Andric nullptr) { 5564*0fca6ea1SDimitry Andric AddSimpleArgumentList(eArgTypeNone, eArgRepeatStar); 556581ad6265SDimitry Andric } 55660b57cec5SDimitry Andric 5567fe6060f1SDimitry Andric ~CommandObjectProcessGDBRemotePacketSend() override = default; 55680b57cec5SDimitry Andric 55695f757f3fSDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override { 55700b57cec5SDimitry Andric const size_t argc = command.GetArgumentCount(); 55710b57cec5SDimitry Andric if (argc == 0) { 55720b57cec5SDimitry Andric result.AppendErrorWithFormat( 55730b57cec5SDimitry Andric "'%s' takes a one or more packet content arguments", 55740b57cec5SDimitry Andric m_cmd_name.c_str()); 55755f757f3fSDimitry Andric return; 55760b57cec5SDimitry Andric } 55770b57cec5SDimitry Andric 55780b57cec5SDimitry Andric ProcessGDBRemote *process = 55790b57cec5SDimitry Andric (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr(); 55800b57cec5SDimitry Andric if (process) { 55810b57cec5SDimitry Andric for (size_t i = 0; i < argc; ++i) { 55820b57cec5SDimitry Andric const char *packet_cstr = command.GetArgumentAtIndex(0); 55830b57cec5SDimitry Andric StringExtractorGDBRemote response; 55840b57cec5SDimitry Andric process->GetGDBRemote().SendPacketAndWaitForResponse( 5585fe6060f1SDimitry Andric packet_cstr, response, process->GetInterruptTimeout()); 55860b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 55870b57cec5SDimitry Andric Stream &output_strm = result.GetOutputStream(); 55880b57cec5SDimitry Andric output_strm.Printf(" packet: %s\n", packet_cstr); 55895ffd83dbSDimitry Andric std::string response_str = std::string(response.GetStringRef()); 55900b57cec5SDimitry Andric 55910b57cec5SDimitry Andric if (strstr(packet_cstr, "qGetProfileData") != nullptr) { 55920b57cec5SDimitry Andric response_str = process->HarmonizeThreadIdsForProfileData(response); 55930b57cec5SDimitry Andric } 55940b57cec5SDimitry Andric 55950b57cec5SDimitry Andric if (response_str.empty()) 55960b57cec5SDimitry Andric output_strm.PutCString("response: \nerror: UNIMPLEMENTED\n"); 55970b57cec5SDimitry Andric else 55989dba64beSDimitry Andric output_strm.Printf("response: %s\n", response.GetStringRef().data()); 55990b57cec5SDimitry Andric } 56000b57cec5SDimitry Andric } 56010b57cec5SDimitry Andric } 56020b57cec5SDimitry Andric }; 56030b57cec5SDimitry Andric 56040b57cec5SDimitry Andric class CommandObjectProcessGDBRemotePacketMonitor : public CommandObjectRaw { 56050b57cec5SDimitry Andric private: 56060b57cec5SDimitry Andric public: 56070b57cec5SDimitry Andric CommandObjectProcessGDBRemotePacketMonitor(CommandInterpreter &interpreter) 56080b57cec5SDimitry Andric : CommandObjectRaw(interpreter, "process plugin packet monitor", 56090b57cec5SDimitry Andric "Send a qRcmd packet through the GDB remote protocol " 56100b57cec5SDimitry Andric "and print the response." 56110b57cec5SDimitry Andric "The argument passed to this command will be hex " 56120b57cec5SDimitry Andric "encoded into a valid 'qRcmd' packet, sent and the " 56130b57cec5SDimitry Andric "response will be printed.") {} 56140b57cec5SDimitry Andric 5615fe6060f1SDimitry Andric ~CommandObjectProcessGDBRemotePacketMonitor() override = default; 56160b57cec5SDimitry Andric 56175f757f3fSDimitry Andric void DoExecute(llvm::StringRef command, 56180b57cec5SDimitry Andric CommandReturnObject &result) override { 56190b57cec5SDimitry Andric if (command.empty()) { 56200b57cec5SDimitry Andric result.AppendErrorWithFormat("'%s' takes a command string argument", 56210b57cec5SDimitry Andric m_cmd_name.c_str()); 56225f757f3fSDimitry Andric return; 56230b57cec5SDimitry Andric } 56240b57cec5SDimitry Andric 56250b57cec5SDimitry Andric ProcessGDBRemote *process = 56260b57cec5SDimitry Andric (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr(); 56270b57cec5SDimitry Andric if (process) { 56280b57cec5SDimitry Andric StreamString packet; 56290b57cec5SDimitry Andric packet.PutCString("qRcmd,"); 56300b57cec5SDimitry Andric packet.PutBytesAsRawHex8(command.data(), command.size()); 56310b57cec5SDimitry Andric 56320b57cec5SDimitry Andric StringExtractorGDBRemote response; 56330b57cec5SDimitry Andric Stream &output_strm = result.GetOutputStream(); 56340b57cec5SDimitry Andric process->GetGDBRemote().SendPacketAndReceiveResponseWithOutputSupport( 5635fe6060f1SDimitry Andric packet.GetString(), response, process->GetInterruptTimeout(), 56360b57cec5SDimitry Andric [&output_strm](llvm::StringRef output) { output_strm << output; }); 56370b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 56380b57cec5SDimitry Andric output_strm.Printf(" packet: %s\n", packet.GetData()); 56395ffd83dbSDimitry Andric const std::string &response_str = std::string(response.GetStringRef()); 56400b57cec5SDimitry Andric 56410b57cec5SDimitry Andric if (response_str.empty()) 56420b57cec5SDimitry Andric output_strm.PutCString("response: \nerror: UNIMPLEMENTED\n"); 56430b57cec5SDimitry Andric else 56449dba64beSDimitry Andric output_strm.Printf("response: %s\n", response.GetStringRef().data()); 56450b57cec5SDimitry Andric } 56460b57cec5SDimitry Andric } 56470b57cec5SDimitry Andric }; 56480b57cec5SDimitry Andric 56490b57cec5SDimitry Andric class CommandObjectProcessGDBRemotePacket : public CommandObjectMultiword { 56500b57cec5SDimitry Andric private: 56510b57cec5SDimitry Andric public: 56520b57cec5SDimitry Andric CommandObjectProcessGDBRemotePacket(CommandInterpreter &interpreter) 56530b57cec5SDimitry Andric : CommandObjectMultiword(interpreter, "process plugin packet", 56540b57cec5SDimitry Andric "Commands that deal with GDB remote packets.", 56550b57cec5SDimitry Andric nullptr) { 56560b57cec5SDimitry Andric LoadSubCommand( 56570b57cec5SDimitry Andric "history", 56580b57cec5SDimitry Andric CommandObjectSP( 56590b57cec5SDimitry Andric new CommandObjectProcessGDBRemotePacketHistory(interpreter))); 56600b57cec5SDimitry Andric LoadSubCommand( 56610b57cec5SDimitry Andric "send", CommandObjectSP( 56620b57cec5SDimitry Andric new CommandObjectProcessGDBRemotePacketSend(interpreter))); 56630b57cec5SDimitry Andric LoadSubCommand( 56640b57cec5SDimitry Andric "monitor", 56650b57cec5SDimitry Andric CommandObjectSP( 56660b57cec5SDimitry Andric new CommandObjectProcessGDBRemotePacketMonitor(interpreter))); 56670b57cec5SDimitry Andric LoadSubCommand( 56680b57cec5SDimitry Andric "xfer-size", 56690b57cec5SDimitry Andric CommandObjectSP( 56700b57cec5SDimitry Andric new CommandObjectProcessGDBRemotePacketXferSize(interpreter))); 56710b57cec5SDimitry Andric LoadSubCommand("speed-test", 56720b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessGDBRemoteSpeedTest( 56730b57cec5SDimitry Andric interpreter))); 56740b57cec5SDimitry Andric } 56750b57cec5SDimitry Andric 5676fe6060f1SDimitry Andric ~CommandObjectProcessGDBRemotePacket() override = default; 56770b57cec5SDimitry Andric }; 56780b57cec5SDimitry Andric 56790b57cec5SDimitry Andric class CommandObjectMultiwordProcessGDBRemote : public CommandObjectMultiword { 56800b57cec5SDimitry Andric public: 56810b57cec5SDimitry Andric CommandObjectMultiwordProcessGDBRemote(CommandInterpreter &interpreter) 56820b57cec5SDimitry Andric : CommandObjectMultiword( 56830b57cec5SDimitry Andric interpreter, "process plugin", 56840b57cec5SDimitry Andric "Commands for operating on a ProcessGDBRemote process.", 56850b57cec5SDimitry Andric "process plugin <subcommand> [<subcommand-options>]") { 56860b57cec5SDimitry Andric LoadSubCommand( 56870b57cec5SDimitry Andric "packet", 56880b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessGDBRemotePacket(interpreter))); 56890b57cec5SDimitry Andric } 56900b57cec5SDimitry Andric 5691fe6060f1SDimitry Andric ~CommandObjectMultiwordProcessGDBRemote() override = default; 56920b57cec5SDimitry Andric }; 56930b57cec5SDimitry Andric 56940b57cec5SDimitry Andric CommandObject *ProcessGDBRemote::GetPluginCommandObject() { 56950b57cec5SDimitry Andric if (!m_command_sp) 56960b57cec5SDimitry Andric m_command_sp = std::make_shared<CommandObjectMultiwordProcessGDBRemote>( 56970b57cec5SDimitry Andric GetTarget().GetDebugger().GetCommandInterpreter()); 56980b57cec5SDimitry Andric return m_command_sp.get(); 56990b57cec5SDimitry Andric } 5700349cc55cSDimitry Andric 5701349cc55cSDimitry Andric void ProcessGDBRemote::DidForkSwitchSoftwareBreakpoints(bool enable) { 5702349cc55cSDimitry Andric GetBreakpointSiteList().ForEach([this, enable](BreakpointSite *bp_site) { 5703349cc55cSDimitry Andric if (bp_site->IsEnabled() && 5704349cc55cSDimitry Andric (bp_site->GetType() == BreakpointSite::eSoftware || 5705349cc55cSDimitry Andric bp_site->GetType() == BreakpointSite::eExternal)) { 5706349cc55cSDimitry Andric m_gdb_comm.SendGDBStoppointTypePacket( 5707349cc55cSDimitry Andric eBreakpointSoftware, enable, bp_site->GetLoadAddress(), 5708349cc55cSDimitry Andric GetSoftwareBreakpointTrapOpcode(bp_site), GetInterruptTimeout()); 5709349cc55cSDimitry Andric } 5710349cc55cSDimitry Andric }); 5711349cc55cSDimitry Andric } 5712349cc55cSDimitry Andric 5713349cc55cSDimitry Andric void ProcessGDBRemote::DidForkSwitchHardwareTraps(bool enable) { 5714349cc55cSDimitry Andric if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) { 5715349cc55cSDimitry Andric GetBreakpointSiteList().ForEach([this, enable](BreakpointSite *bp_site) { 5716349cc55cSDimitry Andric if (bp_site->IsEnabled() && 5717349cc55cSDimitry Andric bp_site->GetType() == BreakpointSite::eHardware) { 5718349cc55cSDimitry Andric m_gdb_comm.SendGDBStoppointTypePacket( 5719349cc55cSDimitry Andric eBreakpointHardware, enable, bp_site->GetLoadAddress(), 5720349cc55cSDimitry Andric GetSoftwareBreakpointTrapOpcode(bp_site), GetInterruptTimeout()); 5721349cc55cSDimitry Andric } 5722349cc55cSDimitry Andric }); 5723349cc55cSDimitry Andric } 5724349cc55cSDimitry Andric 57255f757f3fSDimitry Andric for (const auto &wp_res_sp : m_watchpoint_resource_list.Sites()) { 57265f757f3fSDimitry Andric addr_t addr = wp_res_sp->GetLoadAddress(); 57275f757f3fSDimitry Andric size_t size = wp_res_sp->GetByteSize(); 57285f757f3fSDimitry Andric GDBStoppointType type = GetGDBStoppointType(wp_res_sp); 57295f757f3fSDimitry Andric m_gdb_comm.SendGDBStoppointTypePacket(type, enable, addr, size, 5730349cc55cSDimitry Andric GetInterruptTimeout()); 5731349cc55cSDimitry Andric } 5732349cc55cSDimitry Andric } 5733349cc55cSDimitry Andric 5734349cc55cSDimitry Andric void ProcessGDBRemote::DidFork(lldb::pid_t child_pid, lldb::tid_t child_tid) { 57351fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 5736349cc55cSDimitry Andric 5737349cc55cSDimitry Andric lldb::pid_t parent_pid = m_gdb_comm.GetCurrentProcessID(); 5738349cc55cSDimitry Andric // Any valid TID will suffice, thread-relevant actions will set a proper TID 5739349cc55cSDimitry Andric // anyway. 5740349cc55cSDimitry Andric lldb::tid_t parent_tid = m_thread_ids.front(); 5741349cc55cSDimitry Andric 5742349cc55cSDimitry Andric lldb::pid_t follow_pid, detach_pid; 5743349cc55cSDimitry Andric lldb::tid_t follow_tid, detach_tid; 5744349cc55cSDimitry Andric 5745349cc55cSDimitry Andric switch (GetFollowForkMode()) { 5746349cc55cSDimitry Andric case eFollowParent: 5747349cc55cSDimitry Andric follow_pid = parent_pid; 5748349cc55cSDimitry Andric follow_tid = parent_tid; 5749349cc55cSDimitry Andric detach_pid = child_pid; 5750349cc55cSDimitry Andric detach_tid = child_tid; 5751349cc55cSDimitry Andric break; 5752349cc55cSDimitry Andric case eFollowChild: 5753349cc55cSDimitry Andric follow_pid = child_pid; 5754349cc55cSDimitry Andric follow_tid = child_tid; 5755349cc55cSDimitry Andric detach_pid = parent_pid; 5756349cc55cSDimitry Andric detach_tid = parent_tid; 5757349cc55cSDimitry Andric break; 5758349cc55cSDimitry Andric } 5759349cc55cSDimitry Andric 5760349cc55cSDimitry Andric // Switch to the process that is going to be detached. 5761349cc55cSDimitry Andric if (!m_gdb_comm.SetCurrentThread(detach_tid, detach_pid)) { 5762349cc55cSDimitry Andric LLDB_LOG(log, "ProcessGDBRemote::DidFork() unable to set pid/tid"); 5763349cc55cSDimitry Andric return; 5764349cc55cSDimitry Andric } 5765349cc55cSDimitry Andric 5766349cc55cSDimitry Andric // Disable all software breakpoints in the forked process. 5767349cc55cSDimitry Andric if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware)) 5768349cc55cSDimitry Andric DidForkSwitchSoftwareBreakpoints(false); 5769349cc55cSDimitry Andric 5770349cc55cSDimitry Andric // Remove hardware breakpoints / watchpoints from parent process if we're 5771349cc55cSDimitry Andric // following child. 5772349cc55cSDimitry Andric if (GetFollowForkMode() == eFollowChild) 5773349cc55cSDimitry Andric DidForkSwitchHardwareTraps(false); 5774349cc55cSDimitry Andric 5775349cc55cSDimitry Andric // Switch to the process that is going to be followed 5776349cc55cSDimitry Andric if (!m_gdb_comm.SetCurrentThread(follow_tid, follow_pid) || 5777349cc55cSDimitry Andric !m_gdb_comm.SetCurrentThreadForRun(follow_tid, follow_pid)) { 5778349cc55cSDimitry Andric LLDB_LOG(log, "ProcessGDBRemote::DidFork() unable to reset pid/tid"); 5779349cc55cSDimitry Andric return; 5780349cc55cSDimitry Andric } 5781349cc55cSDimitry Andric 5782349cc55cSDimitry Andric LLDB_LOG(log, "Detaching process {0}", detach_pid); 5783349cc55cSDimitry Andric Status error = m_gdb_comm.Detach(false, detach_pid); 5784349cc55cSDimitry Andric if (error.Fail()) { 5785349cc55cSDimitry Andric LLDB_LOG(log, "ProcessGDBRemote::DidFork() detach packet send failed: {0}", 5786349cc55cSDimitry Andric error.AsCString() ? error.AsCString() : "<unknown error>"); 5787349cc55cSDimitry Andric return; 5788349cc55cSDimitry Andric } 5789349cc55cSDimitry Andric 5790349cc55cSDimitry Andric // Hardware breakpoints/watchpoints are not inherited implicitly, 5791349cc55cSDimitry Andric // so we need to readd them if we're following child. 5792fcaf7f86SDimitry Andric if (GetFollowForkMode() == eFollowChild) { 5793349cc55cSDimitry Andric DidForkSwitchHardwareTraps(true); 5794fcaf7f86SDimitry Andric // Update our PID 5795fcaf7f86SDimitry Andric SetID(child_pid); 5796fcaf7f86SDimitry Andric } 5797349cc55cSDimitry Andric } 5798349cc55cSDimitry Andric 5799349cc55cSDimitry Andric void ProcessGDBRemote::DidVFork(lldb::pid_t child_pid, lldb::tid_t child_tid) { 58001fd87a68SDimitry Andric Log *log = GetLog(GDBRLog::Process); 5801349cc55cSDimitry Andric 5802*0fca6ea1SDimitry Andric LLDB_LOG( 5803*0fca6ea1SDimitry Andric log, 5804*0fca6ea1SDimitry Andric "ProcessGDBRemote::DidFork() called for child_pid: {0}, child_tid {1}", 5805*0fca6ea1SDimitry Andric child_pid, child_tid); 5806*0fca6ea1SDimitry Andric ++m_vfork_in_progress_count; 5807349cc55cSDimitry Andric 5808349cc55cSDimitry Andric // Disable all software breakpoints for the duration of vfork. 5809349cc55cSDimitry Andric if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware)) 5810349cc55cSDimitry Andric DidForkSwitchSoftwareBreakpoints(false); 5811349cc55cSDimitry Andric 5812349cc55cSDimitry Andric lldb::pid_t detach_pid; 5813349cc55cSDimitry Andric lldb::tid_t detach_tid; 5814349cc55cSDimitry Andric 5815349cc55cSDimitry Andric switch (GetFollowForkMode()) { 5816349cc55cSDimitry Andric case eFollowParent: 5817349cc55cSDimitry Andric detach_pid = child_pid; 5818349cc55cSDimitry Andric detach_tid = child_tid; 5819349cc55cSDimitry Andric break; 5820349cc55cSDimitry Andric case eFollowChild: 5821349cc55cSDimitry Andric detach_pid = m_gdb_comm.GetCurrentProcessID(); 5822349cc55cSDimitry Andric // Any valid TID will suffice, thread-relevant actions will set a proper TID 5823349cc55cSDimitry Andric // anyway. 5824349cc55cSDimitry Andric detach_tid = m_thread_ids.front(); 5825349cc55cSDimitry Andric 5826349cc55cSDimitry Andric // Switch to the parent process before detaching it. 5827349cc55cSDimitry Andric if (!m_gdb_comm.SetCurrentThread(detach_tid, detach_pid)) { 5828349cc55cSDimitry Andric LLDB_LOG(log, "ProcessGDBRemote::DidFork() unable to set pid/tid"); 5829349cc55cSDimitry Andric return; 5830349cc55cSDimitry Andric } 5831349cc55cSDimitry Andric 5832349cc55cSDimitry Andric // Remove hardware breakpoints / watchpoints from the parent process. 5833349cc55cSDimitry Andric DidForkSwitchHardwareTraps(false); 5834349cc55cSDimitry Andric 5835349cc55cSDimitry Andric // Switch to the child process. 5836349cc55cSDimitry Andric if (!m_gdb_comm.SetCurrentThread(child_tid, child_pid) || 5837349cc55cSDimitry Andric !m_gdb_comm.SetCurrentThreadForRun(child_tid, child_pid)) { 5838349cc55cSDimitry Andric LLDB_LOG(log, "ProcessGDBRemote::DidFork() unable to reset pid/tid"); 5839349cc55cSDimitry Andric return; 5840349cc55cSDimitry Andric } 5841349cc55cSDimitry Andric break; 5842349cc55cSDimitry Andric } 5843349cc55cSDimitry Andric 5844349cc55cSDimitry Andric LLDB_LOG(log, "Detaching process {0}", detach_pid); 5845349cc55cSDimitry Andric Status error = m_gdb_comm.Detach(false, detach_pid); 5846349cc55cSDimitry Andric if (error.Fail()) { 5847349cc55cSDimitry Andric LLDB_LOG(log, 5848349cc55cSDimitry Andric "ProcessGDBRemote::DidFork() detach packet send failed: {0}", 5849349cc55cSDimitry Andric error.AsCString() ? error.AsCString() : "<unknown error>"); 5850349cc55cSDimitry Andric return; 5851349cc55cSDimitry Andric } 5852fcaf7f86SDimitry Andric 5853fcaf7f86SDimitry Andric if (GetFollowForkMode() == eFollowChild) { 5854fcaf7f86SDimitry Andric // Update our PID 5855fcaf7f86SDimitry Andric SetID(child_pid); 5856fcaf7f86SDimitry Andric } 5857349cc55cSDimitry Andric } 5858349cc55cSDimitry Andric 5859349cc55cSDimitry Andric void ProcessGDBRemote::DidVForkDone() { 5860*0fca6ea1SDimitry Andric assert(m_vfork_in_progress_count > 0); 5861*0fca6ea1SDimitry Andric --m_vfork_in_progress_count; 5862349cc55cSDimitry Andric 5863349cc55cSDimitry Andric // Reenable all software breakpoints that were enabled before vfork. 5864349cc55cSDimitry Andric if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware)) 5865349cc55cSDimitry Andric DidForkSwitchSoftwareBreakpoints(true); 5866349cc55cSDimitry Andric } 5867349cc55cSDimitry Andric 5868349cc55cSDimitry Andric void ProcessGDBRemote::DidExec() { 5869349cc55cSDimitry Andric // If we are following children, vfork is finished by exec (rather than 5870349cc55cSDimitry Andric // vforkdone that is submitted for parent). 5871*0fca6ea1SDimitry Andric if (GetFollowForkMode() == eFollowChild) { 5872*0fca6ea1SDimitry Andric if (m_vfork_in_progress_count > 0) 5873*0fca6ea1SDimitry Andric --m_vfork_in_progress_count; 5874*0fca6ea1SDimitry Andric } 5875349cc55cSDimitry Andric Process::DidExec(); 5876349cc55cSDimitry Andric } 5877