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