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