//===-- ProcessGDBRemote.cpp ------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Host/Config.h"

// C Includes
#include <errno.h>
#include <stdlib.h>
#ifndef LLDB_DISABLE_POSIX
#include <netinet/in.h>
#include <sys/mman.h>       // for mmap
#endif
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>

// C++ Includes
#include <algorithm>
#include <map>
#include <mutex>

#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/Timer.h"
#include "lldb/Core/Value.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Host/Symbols.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/TimeValue.h"
#include "lldb/Host/XML.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/OptionGroupBoolean.h"
#include "lldb/Interpreter/OptionGroupUInt64.h"
#include "lldb/Interpreter/Property.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/TargetList.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Utility/PseudoTerminal.h"

// Project includes
#include "lldb/Host/Host.h"
#include "Plugins/Process/Utility/GDBRemoteSignals.h"
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
#include "Plugins/Process/Utility/StopInfoMachException.h"
#include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h"
#include "Utility/StringExtractorGDBRemote.h"
#include "GDBRemoteRegisterContext.h"
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
#include "ThreadGDBRemote.h"

#define DEBUGSERVER_BASENAME    "debugserver"
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;

namespace lldb
{
    // Provide a function that can easily dump the packet history if we know a
    // ProcessGDBRemote * value (which we can get from logs or from debugging).
    // We need the function in the lldb namespace so it makes it into the final
    // executable since the LLDB shared library only exports stuff in the lldb
    // namespace. This allows you to attach with a debugger and call this
    // function and get the packet history dumped to a file.
    void
    DumpProcessGDBRemotePacketHistory (void *p, const char *path)
    {
        StreamFile strm;
        Error error (strm.GetFile().Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate));
        if (error.Success())
            ((ProcessGDBRemote *)p)->GetGDBRemote().DumpHistory (strm);
    }
}

namespace {

    static PropertyDefinition
    g_properties[] =
    {
        { "packet-timeout" , OptionValue::eTypeUInt64 , true , 1, NULL, NULL, "Specify the default packet timeout in seconds." },
        { "target-definition-file" , OptionValue::eTypeFileSpec , true, 0 , NULL, NULL, "The file that provides the description for remote target registers." },
        {  NULL            , OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL  }
    };

    enum
    {
        ePropertyPacketTimeout,
        ePropertyTargetDefinitionFile
    };

    class PluginProperties : public Properties
    {
    public:

        static ConstString
        GetSettingName ()
        {
            return ProcessGDBRemote::GetPluginNameStatic();
        }

        PluginProperties() :
        Properties ()
        {
            m_collection_sp.reset (new OptionValueProperties(GetSettingName()));
            m_collection_sp->Initialize(g_properties);
        }

        virtual
        ~PluginProperties()
        {
        }

        uint64_t
        GetPacketTimeout()
        {
            const uint32_t idx = ePropertyPacketTimeout;
            return m_collection_sp->GetPropertyAtIndexAsUInt64(NULL, idx, g_properties[idx].default_uint_value);
        }

        bool
        SetPacketTimeout(uint64_t timeout)
        {
            const uint32_t idx = ePropertyPacketTimeout;
            return m_collection_sp->SetPropertyAtIndexAsUInt64(NULL, idx, timeout);
        }

        FileSpec
        GetTargetDefinitionFile () const
        {
            const uint32_t idx = ePropertyTargetDefinitionFile;
            return m_collection_sp->GetPropertyAtIndexAsFileSpec (NULL, idx);
        }
    };

    typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP;

    static const ProcessKDPPropertiesSP &
    GetGlobalPluginProperties()
    {
        static ProcessKDPPropertiesSP g_settings_sp;
        if (!g_settings_sp)
            g_settings_sp.reset (new PluginProperties ());
        return g_settings_sp;
    }

} // anonymous namespace end

// TODO Randomly assigning a port is unsafe.  We should get an unused
// ephemeral port from the kernel and make sure we reserve it before passing
// it to debugserver.

#if defined (__APPLE__)
#define LOW_PORT    (IPPORT_RESERVED)
#define HIGH_PORT   (IPPORT_HIFIRSTAUTO)
#else
#define LOW_PORT    (1024u)
#define HIGH_PORT   (49151u)
#endif

#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__) || defined(__aarch64__))
static bool rand_initialized = false;

static inline uint16_t
get_random_port ()
{
    if (!rand_initialized)
    {
        time_t seed = time(NULL);

        rand_initialized = true;
        srand(seed);
    }
    return (rand() % (HIGH_PORT - LOW_PORT)) + LOW_PORT;
}
#endif

ConstString
ProcessGDBRemote::GetPluginNameStatic()
{
    static ConstString g_name("gdb-remote");
    return g_name;
}

const char *
ProcessGDBRemote::GetPluginDescriptionStatic()
{
    return "GDB Remote protocol based debugging plug-in.";
}

void
ProcessGDBRemote::Terminate()
{
    PluginManager::UnregisterPlugin (ProcessGDBRemote::CreateInstance);
}


lldb::ProcessSP
ProcessGDBRemote::CreateInstance (lldb::TargetSP target_sp, ListenerSP listener_sp, const FileSpec *crash_file_path)
{
    lldb::ProcessSP process_sp;
    if (crash_file_path == NULL)
        process_sp.reset (new ProcessGDBRemote (target_sp, listener_sp));
    return process_sp;
}

bool
ProcessGDBRemote::CanDebug (lldb::TargetSP target_sp, bool plugin_specified_by_name)
{
    if (plugin_specified_by_name)
        return true;

    // For now we are just making sure the file exists for a given module
    Module *exe_module = target_sp->GetExecutableModulePointer();
    if (exe_module)
    {
        ObjectFile *exe_objfile = exe_module->GetObjectFile();
        // We can't debug core files...
        switch (exe_objfile->GetType())
        {
            case ObjectFile::eTypeInvalid:
            case ObjectFile::eTypeCoreFile:
            case ObjectFile::eTypeDebugInfo:
            case ObjectFile::eTypeObjectFile:
            case ObjectFile::eTypeSharedLibrary:
            case ObjectFile::eTypeStubLibrary:
            case ObjectFile::eTypeJIT:
                return false;
            case ObjectFile::eTypeExecutable:
            case ObjectFile::eTypeDynamicLinker:
            case ObjectFile::eTypeUnknown:
                break;
        }
        return exe_module->GetFileSpec().Exists();
    }
    // However, if there is no executable module, we return true since we might be preparing to attach.
    return true;
}

//----------------------------------------------------------------------
// ProcessGDBRemote constructor
//----------------------------------------------------------------------
ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, ListenerSP listener_sp)
    : Process(target_sp, listener_sp),
      m_flags(0),
      m_gdb_comm(),
      m_debugserver_pid(LLDB_INVALID_PROCESS_ID),
      m_last_stop_packet_mutex(),
      m_register_info(),
      m_async_broadcaster(NULL, "lldb.process.gdb-remote.async-broadcaster"),
      m_async_listener_sp(Listener::MakeListener("lldb.process.gdb-remote.async-listener")),
      m_async_thread_state_mutex(),
      m_thread_ids(),
      m_thread_pcs(),
      m_jstopinfo_sp(),
      m_jthreadsinfo_sp(),
      m_continue_c_tids(),
      m_continue_C_tids(),
      m_continue_s_tids(),
      m_continue_S_tids(),
      m_max_memory_size(0),
      m_remote_stub_max_memory_size(0),
      m_addr_to_mmap_size(),
      m_thread_create_bp_sp(),
      m_waiting_for_attach(false),
      m_destroy_tried_resuming(false),
      m_command_sp(),
      m_breakpoint_pc_offset(0),
      m_initial_tid(LLDB_INVALID_THREAD_ID)
{
    m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, "async thread should exit");
    m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, "async thread continue");
    m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadDidExit, "async thread did exit");

    Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_ASYNC));

    const uint32_t async_event_mask = eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit;

    if (m_async_listener_sp->StartListeningForEvents(&m_async_broadcaster, async_event_mask) != async_event_mask)
    {
        if (log)
            log->Printf("ProcessGDBRemote::%s failed to listen for m_async_broadcaster events", __FUNCTION__);
    }

    const uint32_t gdb_event_mask =
        Communication::eBroadcastBitReadThreadDidExit | GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify;
    if (m_async_listener_sp->StartListeningForEvents(&m_gdb_comm, gdb_event_mask) != gdb_event_mask)
    {
        if (log)
            log->Printf("ProcessGDBRemote::%s failed to listen for m_gdb_comm events", __FUNCTION__);
    }

    const uint64_t timeout_seconds = GetGlobalPluginProperties()->GetPacketTimeout();
    if (timeout_seconds > 0)
        m_gdb_comm.SetPacketTimeout(timeout_seconds);
}

//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
ProcessGDBRemote::~ProcessGDBRemote()
{
    //  m_mach_process.UnregisterNotificationCallbacks (this);
    Clear();
    // We need to call finalize on the process before destroying ourselves
    // to make sure all of the broadcaster cleanup goes as planned. If we
    // destruct this class, then Process::~Process() might have problems
    // trying to fully destroy the broadcaster.
    Finalize();

    // The general Finalize is going to try to destroy the process and that SHOULD
    // shut down the async thread.  However, if we don't kill it it will get stranded and
    // its connection will go away so when it wakes up it will crash.  So kill it for sure here.
    StopAsyncThread();
    KillDebugserverProcess();
}

//----------------------------------------------------------------------
// PluginInterface
//----------------------------------------------------------------------
ConstString
ProcessGDBRemote::GetPluginName()
{
    return GetPluginNameStatic();
}

uint32_t
ProcessGDBRemote::GetPluginVersion()
{
    return 1;
}

bool
ProcessGDBRemote::ParsePythonTargetDefinition(const FileSpec &target_definition_fspec)
{
    ScriptInterpreter *interpreter = GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
    Error error;
    StructuredData::ObjectSP module_object_sp(interpreter->LoadPluginModule(target_definition_fspec, error));
    if (module_object_sp)
    {
        StructuredData::DictionarySP target_definition_sp(
            interpreter->GetDynamicSettings(module_object_sp, &GetTarget(), "gdb-server-target-definition", error));

        if (target_definition_sp)
        {
            StructuredData::ObjectSP target_object(target_definition_sp->GetValueForKey("host-info"));
            if (target_object)
            {
                if (auto host_info_dict = target_object->GetAsDictionary())
                {
                    StructuredData::ObjectSP triple_value = host_info_dict->GetValueForKey("triple");
                    if (auto triple_string_value = triple_value->GetAsString())
                    {
                        std::string triple_string = triple_string_value->GetValue();
                        ArchSpec host_arch(triple_string.c_str());
                        if (!host_arch.IsCompatibleMatch(GetTarget().GetArchitecture()))
                        {
                            GetTarget().SetArchitecture(host_arch);
                        }
                    }
                }
            }
            m_breakpoint_pc_offset = 0;
            StructuredData::ObjectSP breakpoint_pc_offset_value = target_definition_sp->GetValueForKey("breakpoint-pc-offset");
            if (breakpoint_pc_offset_value)
            {
                if (auto breakpoint_pc_int_value = breakpoint_pc_offset_value->GetAsInteger())
                    m_breakpoint_pc_offset = breakpoint_pc_int_value->GetValue();
            }

            if (m_register_info.SetRegisterInfo(*target_definition_sp, GetTarget().GetArchitecture()) > 0)
            {
                return true;
            }
        }
    }
    return false;
}

// If the remote stub didn't give us eh_frame or DWARF register numbers for a register,
// see if the ABI can provide them.
// DWARF and eh_frame register numbers are defined as a part of the ABI.
static void
AugmentRegisterInfoViaABI (RegisterInfo &reg_info, ConstString reg_name, ABISP abi_sp)
{
    if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM
        || reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM)
    {
        if (abi_sp)
        {
            RegisterInfo abi_reg_info;
            if (abi_sp->GetRegisterInfoByName (reg_name, abi_reg_info))
            {
                if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM &&
                    abi_reg_info.kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM)
                {
                    reg_info.kinds[eRegisterKindEHFrame] = abi_reg_info.kinds[eRegisterKindEHFrame];
                }
                if (reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM &&
                    abi_reg_info.kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM)
                {
                    reg_info.kinds[eRegisterKindDWARF] = abi_reg_info.kinds[eRegisterKindDWARF];
                }
                if (reg_info.kinds[eRegisterKindGeneric] == LLDB_INVALID_REGNUM &&
                    abi_reg_info.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM)
                {
                    reg_info.kinds[eRegisterKindGeneric] = abi_reg_info.kinds[eRegisterKindGeneric];
                }
            }
        }
    }
}

static size_t
SplitCommaSeparatedRegisterNumberString(const llvm::StringRef &comma_separated_regiter_numbers, std::vector<uint32_t> &regnums, int base)
{
    regnums.clear();
    std::pair<llvm::StringRef, llvm::StringRef> value_pair;
    value_pair.second = comma_separated_regiter_numbers;
    do
    {
        value_pair = value_pair.second.split(',');
        if (!value_pair.first.empty())
        {
            uint32_t reg = StringConvert::ToUInt32 (value_pair.first.str().c_str(), LLDB_INVALID_REGNUM, base);
            if (reg != LLDB_INVALID_REGNUM)
                regnums.push_back (reg);
        }
    } while (!value_pair.second.empty());
    return regnums.size();
}


void
ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
{
    if (!force && m_register_info.GetNumRegisters() > 0)
        return;

    m_register_info.Clear();

    // Check if qHostInfo specified a specific packet timeout for this connection.
    // If so then lets update our setting so the user knows what the timeout is
    // and can see it.
    const uint32_t host_packet_timeout = m_gdb_comm.GetHostDefaultPacketTimeout();
    if (host_packet_timeout)
    {
        GetGlobalPluginProperties()->SetPacketTimeout(host_packet_timeout);
    }

    // Register info search order:
    //     1 - Use the target definition python file if one is specified.
    //     2 - If the target definition doesn't have any of the info from the target.xml (registers) then proceed to read the target.xml.
    //     3 - Fall back on the qRegisterInfo packets.

    FileSpec target_definition_fspec = GetGlobalPluginProperties()->GetTargetDefinitionFile ();
    if (!target_definition_fspec.Exists())
    {
        // If the filename doesn't exist, it may be a ~ not having been expanded - try to resolve it.
        target_definition_fspec.ResolvePath();
    }
    if (target_definition_fspec)
    {
        // See if we can get register definitions from a python file
        if (ParsePythonTargetDefinition (target_definition_fspec))
        {
            return;
        }
        else
        {
            StreamSP stream_sp = GetTarget().GetDebugger().GetAsyncOutputStream();
            stream_sp->Printf ("ERROR: target description file %s failed to parse.\n", target_definition_fspec.GetPath().c_str());
        }
    }

    const ArchSpec &target_arch = GetTarget().GetArchitecture();
    const ArchSpec &remote_host_arch = m_gdb_comm.GetHostArchitecture();
    const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture();

    // Use the process' architecture instead of the host arch, if available
    ArchSpec arch_to_use;
    if (remote_process_arch.IsValid ())
        arch_to_use = remote_process_arch;
    else
        arch_to_use = remote_host_arch;
    
    if (!arch_to_use.IsValid())
        arch_to_use = target_arch;

    if (GetGDBServerRegisterInfo (arch_to_use))
        return;

    char packet[128];
    uint32_t reg_offset = 0;
    uint32_t reg_num = 0;
    for (StringExtractorGDBRemote::ResponseType response_type = StringExtractorGDBRemote::eResponse;
         response_type == StringExtractorGDBRemote::eResponse;
         ++reg_num)
    {
        const int packet_len = ::snprintf (packet, sizeof(packet), "qRegisterInfo%x", reg_num);
        assert (packet_len < (int)sizeof(packet));
        StringExtractorGDBRemote response;
        if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false) == GDBRemoteCommunication::PacketResult::Success)
        {
            response_type = response.GetResponseType();
            if (response_type == StringExtractorGDBRemote::eResponse)
            {
                std::string name;
                std::string value;
                ConstString reg_name;
                ConstString alt_name;
                ConstString set_name;
                std::vector<uint32_t> value_regs;
                std::vector<uint32_t> invalidate_regs;
                std::vector<uint8_t> dwarf_opcode_bytes;
                RegisterInfo reg_info = { NULL,                 // Name
                    NULL,                 // Alt name
                    0,                    // byte size
                    reg_offset,           // offset
                    eEncodingUint,        // encoding
                    eFormatHex,           // format
                    {
                        LLDB_INVALID_REGNUM, // eh_frame reg num
                        LLDB_INVALID_REGNUM, // DWARF reg num
                        LLDB_INVALID_REGNUM, // generic reg num
                        reg_num,             // process plugin reg num
                        reg_num           // native register number
                    },
                    NULL,
                    NULL,
                    NULL, // Dwarf expression opcode bytes pointer
                    0     // Dwarf expression opcode bytes length
                };

                while (response.GetNameColonValue(name, value))
                {
                    if (name.compare("name") == 0)
                    {
                        reg_name.SetCString(value.c_str());
                    }
                    else if (name.compare("alt-name") == 0)
                    {
                        alt_name.SetCString(value.c_str());
                    }
                    else if (name.compare("bitsize") == 0)
                    {
                        reg_info.byte_size = StringConvert::ToUInt32(value.c_str(), 0, 0) / CHAR_BIT;
                    }
                    else if (name.compare("offset") == 0)
                    {
                        uint32_t offset = StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0);
                        if (reg_offset != offset)
                        {
                            reg_offset = offset;
                        }
                    }
                    else if (name.compare("encoding") == 0)
                    {
                        const Encoding encoding = Args::StringToEncoding (value.c_str());
                        if (encoding != eEncodingInvalid)
                            reg_info.encoding = encoding;
                    }
                    else if (name.compare("format") == 0)
                    {
                        Format format = eFormatInvalid;
                        if (Args::StringToFormat (value.c_str(), format, NULL).Success())
                            reg_info.format = format;
                        else if (value.compare("binary") == 0)
                            reg_info.format = eFormatBinary;
                        else if (value.compare("decimal") == 0)
                            reg_info.format = eFormatDecimal;
                        else if (value.compare("hex") == 0)
                            reg_info.format = eFormatHex;
                        else if (value.compare("float") == 0)
                            reg_info.format = eFormatFloat;
                        else if (value.compare("vector-sint8") == 0)
                            reg_info.format = eFormatVectorOfSInt8;
                        else if (value.compare("vector-uint8") == 0)
                            reg_info.format = eFormatVectorOfUInt8;
                        else if (value.compare("vector-sint16") == 0)
                            reg_info.format = eFormatVectorOfSInt16;
                        else if (value.compare("vector-uint16") == 0)
                            reg_info.format = eFormatVectorOfUInt16;
                        else if (value.compare("vector-sint32") == 0)
                            reg_info.format = eFormatVectorOfSInt32;
                        else if (value.compare("vector-uint32") == 0)
                            reg_info.format = eFormatVectorOfUInt32;
                        else if (value.compare("vector-float32") == 0)
                            reg_info.format = eFormatVectorOfFloat32;
                        else if (value.compare("vector-uint128") == 0)
                            reg_info.format = eFormatVectorOfUInt128;
                    }
                    else if (name.compare("set") == 0)
                    {
                        set_name.SetCString(value.c_str());
                    }
                    else if (name.compare("gcc") == 0 || name.compare("ehframe") == 0)
                    {
                        reg_info.kinds[eRegisterKindEHFrame] = StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0);
                    }
                    else if (name.compare("dwarf") == 0)
                    {
                        reg_info.kinds[eRegisterKindDWARF] = StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0);
                    }
                    else if (name.compare("generic") == 0)
                    {
                        reg_info.kinds[eRegisterKindGeneric] = Args::StringToGenericRegister (value.c_str());
                    }
                    else if (name.compare("container-regs") == 0)
                    {
                        SplitCommaSeparatedRegisterNumberString(value, value_regs, 16);
                    }
                    else if (name.compare("invalidate-regs") == 0)
                    {
                        SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 16);
                    }
                    else if (name.compare("dynamic_size_dwarf_expr_bytes") == 0)
                    {
                       size_t dwarf_opcode_len = value.length () / 2;
                       assert (dwarf_opcode_len > 0);

                       dwarf_opcode_bytes.resize (dwarf_opcode_len);
                       StringExtractor opcode_extractor;
                       reg_info.dynamic_size_dwarf_len = dwarf_opcode_len; 

                       // Swap "value" over into "opcode_extractor"
                       opcode_extractor.GetStringRef ().swap (value);
                       uint32_t ret_val = opcode_extractor.GetHexBytesAvail (dwarf_opcode_bytes.data (),
                                                                           dwarf_opcode_len);
                       assert (dwarf_opcode_len == ret_val);

                       reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data ();
                    }
                }

                reg_info.byte_offset = reg_offset;
                assert (reg_info.byte_size != 0);
                reg_offset += reg_info.byte_size;
                if (!value_regs.empty())
                {
                    value_regs.push_back(LLDB_INVALID_REGNUM);
                    reg_info.value_regs = value_regs.data();
                }
                if (!invalidate_regs.empty())
                {
                    invalidate_regs.push_back(LLDB_INVALID_REGNUM);
                    reg_info.invalidate_regs = invalidate_regs.data();
                }

                // We have to make a temporary ABI here, and not use the GetABI because this code
                // gets called in DidAttach, when the target architecture (and consequently the ABI we'll get from
                // the process) may be wrong.
                ABISP abi_to_use = ABI::FindPlugin(arch_to_use);

                AugmentRegisterInfoViaABI (reg_info, reg_name, abi_to_use);

                m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name);
            }
            else
            {
                break;  // ensure exit before reg_num is incremented
            }
        }
        else
        {
            break;
        }
    }

    if (m_register_info.GetNumRegisters() > 0)
    {
        m_register_info.Finalize(GetTarget().GetArchitecture());
        return;
    }

    // We didn't get anything if the accumulated reg_num is zero.  See if we are
    // debugging ARM and fill with a hard coded register set until we can get an
    // updated debugserver down on the devices.
    // On the other hand, if the accumulated reg_num is positive, see if we can
    // add composite registers to the existing primordial ones.
    bool from_scratch = (m_register_info.GetNumRegisters() == 0);

    if (!target_arch.IsValid())
    {
        if (arch_to_use.IsValid()
              && (arch_to_use.GetMachine() == llvm::Triple::arm || arch_to_use.GetMachine() == llvm::Triple::thumb)
              && arch_to_use.GetTriple().getVendor() == llvm::Triple::Apple)
            m_register_info.HardcodeARMRegisters(from_scratch);
    }
    else if (target_arch.GetMachine() == llvm::Triple::arm
            || target_arch.GetMachine() == llvm::Triple::thumb)
    {
        m_register_info.HardcodeARMRegisters(from_scratch);
    }

    // At this point, we can finalize our register info.
    m_register_info.Finalize (GetTarget().GetArchitecture());
}

Error
ProcessGDBRemote::WillLaunch (Module* module)
{
    return WillLaunchOrAttach ();
}

Error
ProcessGDBRemote::WillAttachToProcessWithID (lldb::pid_t pid)
{
    return WillLaunchOrAttach ();
}

Error
ProcessGDBRemote::WillAttachToProcessWithName (const char *process_name, bool wait_for_launch)
{
    return WillLaunchOrAttach ();
}

Error
ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url)
{
    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
    Error error (WillLaunchOrAttach ());

    if (error.Fail())
        return error;

    error = ConnectToDebugserver (remote_url);

    if (error.Fail())
        return error;
    StartAsyncThread ();

    lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID ();
    if (pid == LLDB_INVALID_PROCESS_ID)
    {
        // We don't have a valid process ID, so note that we are connected
        // and could now request to launch or attach, or get remote process
        // listings...
        SetPrivateState (eStateConnected);
    }
    else
    {
        // We have a valid process
        SetID (pid);
        GetThreadList();
        StringExtractorGDBRemote response;
        if (m_gdb_comm.GetStopReply(response))
        {
            SetLastStopPacket(response);

            // '?' Packets must be handled differently in non-stop mode
            if (GetTarget().GetNonStopModeEnabled())
                HandleStopReplySequence();

            Target &target = GetTarget();
            if (!target.GetArchitecture().IsValid())
            {
                if (m_gdb_comm.GetProcessArchitecture().IsValid())
                {
                    target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());
                }
                else
                {
                    target.SetArchitecture(m_gdb_comm.GetHostArchitecture());
                }
            }

            const StateType state = SetThreadStopInfo (response);
            if (state != eStateInvalid)
            {
                SetPrivateState (state);
            }
            else
                error.SetErrorStringWithFormat ("Process %" PRIu64 " was reported after connecting to '%s', but state was not stopped: %s", pid, remote_url, StateAsCString (state));
        }
        else
            error.SetErrorStringWithFormat ("Process %" PRIu64 " was reported after connecting to '%s', but no stop reply packet was received", pid, remote_url);
    }

    if (log)
        log->Printf ("ProcessGDBRemote::%s pid %" PRIu64 ": normalizing target architecture initial triple: %s (GetTarget().GetArchitecture().IsValid() %s, m_gdb_comm.GetHostArchitecture().IsValid(): %s)", __FUNCTION__, GetID (), GetTarget ().GetArchitecture ().GetTriple ().getTriple ().c_str (), GetTarget ().GetArchitecture ().IsValid () ? "true" : "false", m_gdb_comm.GetHostArchitecture ().IsValid () ? "true" : "false");


    if (error.Success()
        && !GetTarget().GetArchitecture().IsValid()
        && m_gdb_comm.GetHostArchitecture().IsValid())
    {
        // Prefer the *process'* architecture over that of the *host*, if available.
        if (m_gdb_comm.GetProcessArchitecture().IsValid())
            GetTarget().SetArchitecture(m_gdb_comm.GetProcessArchitecture());
        else
            GetTarget().SetArchitecture(m_gdb_comm.GetHostArchitecture());
    }

    if (log)
        log->Printf ("ProcessGDBRemote::%s pid %" PRIu64 ": normalized target architecture triple: %s", __FUNCTION__, GetID (), GetTarget ().GetArchitecture ().GetTriple ().getTriple ().c_str ());

    if (error.Success())
    {
        PlatformSP platform_sp = GetTarget().GetPlatform();
        if (platform_sp && platform_sp->IsConnected())
            SetUnixSignals(platform_sp->GetUnixSignals());
        else
            SetUnixSignals(UnixSignals::Create(GetTarget().GetArchitecture()));
    }

    return error;
}

Error
ProcessGDBRemote::WillLaunchOrAttach ()
{
    Error error;
    m_stdio_communication.Clear ();
    return error;
}

//----------------------------------------------------------------------
// Process Control
//----------------------------------------------------------------------
Error
ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)
{
    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
    Error error;

    if (log)
        log->Printf ("ProcessGDBRemote::%s() entered", __FUNCTION__);

    uint32_t launch_flags = launch_info.GetFlags().Get();
    FileSpec stdin_file_spec{};
    FileSpec stdout_file_spec{};
    FileSpec stderr_file_spec{};
    FileSpec working_dir = launch_info.GetWorkingDirectory();

    const FileAction *file_action;
    file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
    if (file_action)
    {
        if (file_action->GetAction() == FileAction::eFileActionOpen)
            stdin_file_spec = file_action->GetFileSpec();
    }
    file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
    if (file_action)
    {
        if (file_action->GetAction() == FileAction::eFileActionOpen)
            stdout_file_spec = file_action->GetFileSpec();
    }
    file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
    if (file_action)
    {
        if (file_action->GetAction() == FileAction::eFileActionOpen)
            stderr_file_spec = file_action->GetFileSpec();
    }

    if (log)
    {
        if (stdin_file_spec || stdout_file_spec || stderr_file_spec)
            log->Printf ("ProcessGDBRemote::%s provided with STDIO paths via launch_info: stdin=%s, stdout=%s, stderr=%s",
                         __FUNCTION__,
                          stdin_file_spec ?  stdin_file_spec.GetCString() : "<null>",
                         stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
                         stderr_file_spec ? stderr_file_spec.GetCString() : "<null>");
        else
            log->Printf ("ProcessGDBRemote::%s no STDIO paths given via launch_info", __FUNCTION__);
    }

    const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;
    if (stdin_file_spec || disable_stdio)
    {
        // the inferior will be reading stdin from the specified file
        // or stdio is completely disabled
        m_stdin_forward = false;
    }
    else
    {
        m_stdin_forward = true;
    }

    //  ::LogSetBitMask (GDBR_LOG_DEFAULT);
    //  ::LogSetOptions (LLDB_LOG_OPTION_THREADSAFE | LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD);
    //  ::LogSetLogFile ("/dev/stdout");

    ObjectFile * object_file = exe_module->GetObjectFile();
    if (object_file)
    {
        error = EstablishConnectionIfNeeded (launch_info);
        if (error.Success())
        {
            lldb_utility::PseudoTerminal pty;
            const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;

            PlatformSP platform_sp (GetTarget().GetPlatform());
            if (disable_stdio)
            {
                // set to /dev/null unless redirected to a file above
                if (!stdin_file_spec)
                    stdin_file_spec.SetFile(FileSystem::DEV_NULL, false);
                if (!stdout_file_spec)
                    stdout_file_spec.SetFile(FileSystem::DEV_NULL, false);
                if (!stderr_file_spec)
                    stderr_file_spec.SetFile(FileSystem::DEV_NULL, false);
            }
            else if (platform_sp && platform_sp->IsHost())
            {
                // If the debugserver is local and we aren't disabling STDIO, lets use
                // a pseudo terminal to instead of relying on the 'O' packets for stdio
                // since 'O' packets can really slow down debugging if the inferior
                // does a lot of output.
                if ((!stdin_file_spec || !stdout_file_spec || !stderr_file_spec) &&
                        pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, NULL, 0))
                {
                    FileSpec slave_name{pty.GetSlaveName(NULL, 0), false};

                    if (!stdin_file_spec)
                        stdin_file_spec = slave_name;

                    if (!stdout_file_spec)
                        stdout_file_spec = slave_name;

                    if (!stderr_file_spec)
                        stderr_file_spec = slave_name;
                }
                if (log)
                    log->Printf ("ProcessGDBRemote::%s adjusted STDIO paths for local platform (IsHost() is true) using slave: stdin=%s, stdout=%s, stderr=%s",
                                 __FUNCTION__,
                                  stdin_file_spec ?  stdin_file_spec.GetCString() : "<null>",
                                 stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
                                 stderr_file_spec ? stderr_file_spec.GetCString() : "<null>");
            }

            if (log)
                log->Printf ("ProcessGDBRemote::%s final STDIO paths after all adjustments: stdin=%s, stdout=%s, stderr=%s",
                             __FUNCTION__,
                              stdin_file_spec ?  stdin_file_spec.GetCString() : "<null>",
                             stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
                             stderr_file_spec ? stderr_file_spec.GetCString() : "<null>");

            if (stdin_file_spec)
                m_gdb_comm.SetSTDIN(stdin_file_spec);
            if (stdout_file_spec)
                m_gdb_comm.SetSTDOUT(stdout_file_spec);
            if (stderr_file_spec)
                m_gdb_comm.SetSTDERR(stderr_file_spec);

            m_gdb_comm.SetDisableASLR (launch_flags & eLaunchFlagDisableASLR);
            m_gdb_comm.SetDetachOnError (launch_flags & eLaunchFlagDetachOnError);

            m_gdb_comm.SendLaunchArchPacket (GetTarget().GetArchitecture().GetArchitectureName());

            const char * launch_event_data = launch_info.GetLaunchEventData();
            if (launch_event_data != NULL && *launch_event_data != '\0')
                m_gdb_comm.SendLaunchEventDataPacket (launch_event_data);

            if (working_dir)
            {
                m_gdb_comm.SetWorkingDir (working_dir);
            }

            // Send the environment and the program + arguments after we connect
            const Args &environment = launch_info.GetEnvironmentEntries();
            if (environment.GetArgumentCount())
            {
                size_t num_environment_entries = environment.GetArgumentCount();
                for (size_t i=0; i<num_environment_entries; ++i)
                {
                    const char *env_entry = environment.GetArgumentAtIndex(i);
                    if (env_entry == NULL || m_gdb_comm.SendEnvironmentPacket(env_entry) != 0)
                        break;
                }
            }

            {
                // Scope for the scoped timeout object
                GDBRemoteCommunication::ScopedTimeout timeout (m_gdb_comm, 10);

                int arg_packet_err = m_gdb_comm.SendArgumentsPacket (launch_info);
                if (arg_packet_err == 0)
                {
                    std::string error_str;
                    if (m_gdb_comm.GetLaunchSuccess (error_str))
                    {
                        SetID (m_gdb_comm.GetCurrentProcessID ());
                    }
                    else
                    {
                        error.SetErrorString (error_str.c_str());
                    }
                }
                else
                {
                    error.SetErrorStringWithFormat("'A' packet returned an error: %i", arg_packet_err);
                }
            }

            if (GetID() == LLDB_INVALID_PROCESS_ID)
            {
                if (log)
                    log->Printf("failed to connect to debugserver: %s", error.AsCString());
                KillDebugserverProcess ();
                return error;
            }

            StringExtractorGDBRemote response;
            if (m_gdb_comm.GetStopReply(response))
            {
                SetLastStopPacket(response);
                // '?' Packets must be handled differently in non-stop mode
                if (GetTarget().GetNonStopModeEnabled())
                    HandleStopReplySequence();

                const ArchSpec &process_arch = m_gdb_comm.GetProcessArchitecture();

                if (process_arch.IsValid())
                {
                    GetTarget().MergeArchitecture(process_arch);
                }
                else
                {
                    const ArchSpec &host_arch = m_gdb_comm.GetHostArchitecture();
                    if (host_arch.IsValid())
                        GetTarget().MergeArchitecture(host_arch);
                }

                SetPrivateState (SetThreadStopInfo (response));

                if (!disable_stdio)
                {
                    if (pty.GetMasterFileDescriptor() != lldb_utility::PseudoTerminal::invalid_fd)
                        SetSTDIOFileDescriptor (pty.ReleaseMasterFileDescriptor());
                }
            }
        }
        else
        {
            if (log)
                log->Printf("failed to connect to debugserver: %s", error.AsCString());
        }
    }
    else
    {
        // Set our user ID to an invalid process ID.
        SetID(LLDB_INVALID_PROCESS_ID);
        error.SetErrorStringWithFormat ("failed to get object file from '%s' for arch %s",
                                        exe_module->GetFileSpec().GetFilename().AsCString(),
                                        exe_module->GetArchitecture().GetArchitectureName());
    }
    return error;

}


Error
ProcessGDBRemote::ConnectToDebugserver (const char *connect_url)
{
    Error error;
    // Only connect if we have a valid connect URL
    Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));

    if (connect_url && connect_url[0])
    {
        if (log)
            log->Printf("ProcessGDBRemote::%s Connecting to %s", __FUNCTION__, connect_url);
        std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
        if (conn_ap.get())
        {
            const uint32_t max_retry_count = 50;
            uint32_t retry_count = 0;
            while (!m_gdb_comm.IsConnected())
            {
                if (conn_ap->Connect(connect_url, &error) == eConnectionStatusSuccess)
                {
                    m_gdb_comm.SetConnection (conn_ap.release());
                    break;
                }
                else if (error.WasInterrupted())
                {
                    // If we were interrupted, don't keep retrying.
                    break;
                }

                retry_count++;

                if (retry_count >= max_retry_count)
                    break;

                usleep (100000);
            }
        }
    }

    if (!m_gdb_comm.IsConnected())
    {
        if (error.Success())
            error.SetErrorString("not connected to remote gdb server");
        return error;
    }


    // Start the communications read thread so all incoming data can be
    // parsed into packets and queued as they arrive.
    if (GetTarget().GetNonStopModeEnabled())
        m_gdb_comm.StartReadThread();

    // We always seem to be able to open a connection to a local port
    // so we need to make sure we can then send data to it. If we can't
    // then we aren't actually connected to anything, so try and do the
    // handshake with the remote GDB server and make sure that goes
    // alright.
    if (!m_gdb_comm.HandshakeWithServer (&error))
    {
        m_gdb_comm.Disconnect();
        if (error.Success())
            error.SetErrorString("not connected to remote gdb server");
        return error;
    }

    // Send $QNonStop:1 packet on startup if required
    if (GetTarget().GetNonStopModeEnabled())
        GetTarget().SetNonStopModeEnabled (m_gdb_comm.SetNonStopMode(true));

    m_gdb_comm.GetEchoSupported ();
    m_gdb_comm.GetThreadSuffixSupported ();
    m_gdb_comm.GetListThreadsInStopReplySupported ();
    m_gdb_comm.GetHostInfo ();
    m_gdb_comm.GetVContSupported ('c');
    m_gdb_comm.GetVAttachOrWaitSupported();

    // Ask the remote server for the default thread id
    if (GetTarget().GetNonStopModeEnabled())
        m_gdb_comm.GetDefaultThreadId(m_initial_tid);


    size_t num_cmds = GetExtraStartupCommands().GetArgumentCount();
    for (size_t idx = 0; idx < num_cmds; idx++)
    {
        StringExtractorGDBRemote response;
        m_gdb_comm.SendPacketAndWaitForResponse (GetExtraStartupCommands().GetArgumentAtIndex(idx), response, false);
    }
    return error;
}

void
ProcessGDBRemote::DidLaunchOrAttach (ArchSpec& process_arch)
{
    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
    if (log)
        log->Printf ("ProcessGDBRemote::DidLaunch()");
    if (GetID() != LLDB_INVALID_PROCESS_ID)
    {
        BuildDynamicRegisterInfo (false);

        // See if the GDB server supports the qHostInfo information


        // See if the GDB server supports the qProcessInfo packet, if so
        // prefer that over the Host information as it will be more specific
        // to our process.

        const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture();
        if (remote_process_arch.IsValid())
        {
            process_arch = remote_process_arch;
            if (log)
                log->Printf ("ProcessGDBRemote::%s gdb-remote had process architecture, using %s %s",
                             __FUNCTION__,
                             process_arch.GetArchitectureName () ? process_arch.GetArchitectureName () : "<null>",
                             process_arch.GetTriple().getTriple ().c_str() ? process_arch.GetTriple().getTriple ().c_str() : "<null>");
        }
        else
        {
            process_arch = m_gdb_comm.GetHostArchitecture();
            if (log)
                log->Printf ("ProcessGDBRemote::%s gdb-remote did not have process architecture, using gdb-remote host architecture %s %s",
                             __FUNCTION__,
                             process_arch.GetArchitectureName () ? process_arch.GetArchitectureName () : "<null>",
                             process_arch.GetTriple().getTriple ().c_str() ? process_arch.GetTriple().getTriple ().c_str() : "<null>");
        }

        if (process_arch.IsValid())
        {
            const ArchSpec &target_arch = GetTarget().GetArchitecture();
            if (target_arch.IsValid())
            {
                if (log)
                    log->Printf ("ProcessGDBRemote::%s analyzing target arch, currently %s %s",
                                 __FUNCTION__,
                                 target_arch.GetArchitectureName () ? target_arch.GetArchitectureName () : "<null>",
                                 target_arch.GetTriple().getTriple ().c_str() ? target_arch.GetTriple().getTriple ().c_str() : "<null>");

                // If the remote host is ARM and we have apple as the vendor, then
                // ARM executables and shared libraries can have mixed ARM architectures.
                // You can have an armv6 executable, and if the host is armv7, then the
                // system will load the best possible architecture for all shared libraries
                // it has, so we really need to take the remote host architecture as our
                // defacto architecture in this case.

                if ((process_arch.GetMachine() == llvm::Triple::arm || process_arch.GetMachine() == llvm::Triple::thumb)
                    && process_arch.GetTriple().getVendor() == llvm::Triple::Apple)
                {
                    GetTarget().SetArchitecture (process_arch);
                    if (log)
                        log->Printf ("ProcessGDBRemote::%s remote process is ARM/Apple, setting target arch to %s %s",
                                     __FUNCTION__,
                                     process_arch.GetArchitectureName () ? process_arch.GetArchitectureName () : "<null>",
                                     process_arch.GetTriple().getTriple ().c_str() ? process_arch.GetTriple().getTriple ().c_str() : "<null>");
                }
                else
                {
                    // Fill in what is missing in the triple
                    const llvm::Triple &remote_triple = process_arch.GetTriple();
                    llvm::Triple new_target_triple = target_arch.GetTriple();
                    if (new_target_triple.getVendorName().size() == 0)
                    {
                        new_target_triple.setVendor (remote_triple.getVendor());

                        if (new_target_triple.getOSName().size() == 0)
                        {
                            new_target_triple.setOS (remote_triple.getOS());

                            if (new_target_triple.getEnvironmentName().size() == 0)
                                new_target_triple.setEnvironment (remote_triple.getEnvironment());
                        }

                        ArchSpec new_target_arch = target_arch;
                        new_target_arch.SetTriple(new_target_triple);
                        GetTarget().SetArchitecture(new_target_arch);
                    }
                }

                if (log)
                    log->Printf ("ProcessGDBRemote::%s final target arch after adjustments for remote architecture: %s %s",
                                 __FUNCTION__,
                                 target_arch.GetArchitectureName () ? target_arch.GetArchitectureName () : "<null>",
                                 target_arch.GetTriple().getTriple ().c_str() ? target_arch.GetTriple().getTriple ().c_str() : "<null>");
            }
            else
            {
                // The target doesn't have a valid architecture yet, set it from
                // the architecture we got from the remote GDB server
                GetTarget().SetArchitecture (process_arch);
            }
        }
    }
}

void
ProcessGDBRemote::DidLaunch ()
{
    ArchSpec process_arch;
    DidLaunchOrAttach (process_arch);
}

Error
ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const ProcessAttachInfo &attach_info)
{
    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
    Error error;

    if (log)
        log->Printf ("ProcessGDBRemote::%s()", __FUNCTION__);

    // Clear out and clean up from any current state
    Clear();
    if (attach_pid != LLDB_INVALID_PROCESS_ID)
    {
        error = EstablishConnectionIfNeeded (attach_info);
        if (error.Success())
        {
            m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError());

            char packet[64];
            const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%" PRIx64, attach_pid);
            SetID (attach_pid);
            m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet, packet_len));
        }
        else
            SetExitStatus (-1, error.AsCString());
    }

    return error;
}

Error
ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, const ProcessAttachInfo &attach_info)
{
    Error error;
    // Clear out and clean up from any current state
    Clear();

    if (process_name && process_name[0])
    {
        error = EstablishConnectionIfNeeded (attach_info);
        if (error.Success())
        {
            StreamString packet;

            m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError());

            if (attach_info.GetWaitForLaunch())
            {
                if (!m_gdb_comm.GetVAttachOrWaitSupported())
                {
                    packet.PutCString ("vAttachWait");
                }
                else
                {
                    if (attach_info.GetIgnoreExisting())
                        packet.PutCString("vAttachWait");
                    else
                        packet.PutCString ("vAttachOrWait");
                }
            }
            else
                packet.PutCString("vAttachName");
            packet.PutChar(';');
            packet.PutBytesAsRawHex8(process_name, strlen(process_name), endian::InlHostByteOrder(), endian::InlHostByteOrder());

            m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet.GetData(), packet.GetSize()));

        }
        else
            SetExitStatus (-1, error.AsCString());
    }
    return error;
}

void
ProcessGDBRemote::DidExit ()
{
    // When we exit, disconnect from the GDB server communications
    m_gdb_comm.Disconnect();
}

void
ProcessGDBRemote::DidAttach (ArchSpec &process_arch)
{
    // If you can figure out what the architecture is, fill it in here.
    process_arch.Clear();
    DidLaunchOrAttach (process_arch);
}


Error
ProcessGDBRemote::WillResume ()
{
    m_continue_c_tids.clear();
    m_continue_C_tids.clear();
    m_continue_s_tids.clear();
    m_continue_S_tids.clear();
    m_jstopinfo_sp.reset();
    m_jthreadsinfo_sp.reset();
    return Error();
}

Error
ProcessGDBRemote::DoResume ()
{
    Error error;
    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
    if (log)
        log->Printf ("ProcessGDBRemote::Resume()");

    ListenerSP listener_sp (Listener::MakeListener("gdb-remote.resume-packet-sent"));
    if (listener_sp->StartListeningForEvents (&m_gdb_comm, GDBRemoteCommunication::eBroadcastBitRunPacketSent))
    {
        listener_sp->StartListeningForEvents (&m_async_broadcaster, ProcessGDBRemote::eBroadcastBitAsyncThreadDidExit);

        const size_t num_threads = GetThreadList().GetSize();

        StreamString continue_packet;
        bool continue_packet_error = false;
        if (m_gdb_comm.HasAnyVContSupport ())
        {
            if (!GetTarget().GetNonStopModeEnabled() &&
                (m_continue_c_tids.size() == num_threads ||
                (m_continue_c_tids.empty() &&
                 m_continue_C_tids.empty() &&
                 m_continue_s_tids.empty() &&
                 m_continue_S_tids.empty())))
            {
                // All threads are continuing, just send a "c" packet
                continue_packet.PutCString ("c");
            }
            else
            {
                continue_packet.PutCString ("vCont");

                if (!m_continue_c_tids.empty())
                {
                    if (m_gdb_comm.GetVContSupported ('c'))
                    {
                        for (tid_collection::const_iterator t_pos = m_continue_c_tids.begin(), t_end = m_continue_c_tids.end(); t_pos != t_end; ++t_pos)
                            continue_packet.Printf(";c:%4.4" PRIx64, *t_pos);
                    }
                    else
                        continue_packet_error = true;
                }

                if (!continue_packet_error && !m_continue_C_tids.empty())
                {
                    if (m_gdb_comm.GetVContSupported ('C'))
                    {
                        for (tid_sig_collection::const_iterator s_pos = m_continue_C_tids.begin(), s_end = m_continue_C_tids.end(); s_pos != s_end; ++s_pos)
                            continue_packet.Printf(";C%2.2x:%4.4" PRIx64, s_pos->second, s_pos->first);
                    }
                    else
                        continue_packet_error = true;
                }

                if (!continue_packet_error && !m_continue_s_tids.empty())
                {
                    if (m_gdb_comm.GetVContSupported ('s'))
                    {
                        for (tid_collection::const_iterator t_pos = m_continue_s_tids.begin(), t_end = m_continue_s_tids.end(); t_pos != t_end; ++t_pos)
                            continue_packet.Printf(";s:%4.4" PRIx64, *t_pos);
                    }
                    else
                        continue_packet_error = true;
                }

                if (!continue_packet_error && !m_continue_S_tids.empty())
                {
                    if (m_gdb_comm.GetVContSupported ('S'))
                    {
                        for (tid_sig_collection::const_iterator s_pos = m_continue_S_tids.begin(), s_end = m_continue_S_tids.end(); s_pos != s_end; ++s_pos)
                            continue_packet.Printf(";S%2.2x:%4.4" PRIx64, s_pos->second, s_pos->first);
                    }
                    else
                        continue_packet_error = true;
                }

                if (continue_packet_error)
                    continue_packet.GetString().clear();
            }
        }
        else
            continue_packet_error = true;

        if (continue_packet_error)
        {
            // Either no vCont support, or we tried to use part of the vCont
            // packet that wasn't supported by the remote GDB server.
            // We need to try and make a simple packet that can do our continue
            const size_t num_continue_c_tids = m_continue_c_tids.size();
            const size_t num_continue_C_tids = m_continue_C_tids.size();
            const size_t num_continue_s_tids = m_continue_s_tids.size();
            const size_t num_continue_S_tids = m_continue_S_tids.size();
            if (num_continue_c_tids > 0)
            {
                if (num_continue_c_tids == num_threads)
                {
                    // All threads are resuming...
                    m_gdb_comm.SetCurrentThreadForRun (-1);
                    continue_packet.PutChar ('c');
                    continue_packet_error = false;
                }
                else if (num_continue_c_tids == 1 &&
                         num_continue_C_tids == 0 &&
                         num_continue_s_tids == 0 &&
                         num_continue_S_tids == 0 )
                {
                    // Only one thread is continuing
                    m_gdb_comm.SetCurrentThreadForRun (m_continue_c_tids.front());
                    continue_packet.PutChar ('c');
                    continue_packet_error = false;
                }
            }

            if (continue_packet_error && num_continue_C_tids > 0)
            {
                if ((num_continue_C_tids + num_continue_c_tids) == num_threads &&
                    num_continue_C_tids > 0 &&
                    num_continue_s_tids == 0 &&
                    num_continue_S_tids == 0 )
                {
                    const int continue_signo = m_continue_C_tids.front().second;
                    // Only one thread is continuing
                    if (num_continue_C_tids > 1)
                    {
                        // More that one thread with a signal, yet we don't have
                        // vCont support and we are being asked to resume each
                        // thread with a signal, we need to make sure they are
                        // all the same signal, or we can't issue the continue
                        // accurately with the current support...
                        if (num_continue_C_tids > 1)
                        {
                            continue_packet_error = false;
                            for (size_t i=1; i<m_continue_C_tids.size(); ++i)
                            {
                                if (m_continue_C_tids[i].second != continue_signo)
                                    continue_packet_error = true;
                            }
                        }
                        if (!continue_packet_error)
                            m_gdb_comm.SetCurrentThreadForRun (-1);
                    }
                    else
                    {
                        // Set the continue thread ID
                        continue_packet_error = false;
                        m_gdb_comm.SetCurrentThreadForRun (m_continue_C_tids.front().first);
                    }
                    if (!continue_packet_error)
                    {
                        // Add threads continuing with the same signo...
                        continue_packet.Printf("C%2.2x", continue_signo);
                    }
                }
            }

            if (continue_packet_error && num_continue_s_tids > 0)
            {
                if (num_continue_s_tids == num_threads)
                {
                    // All threads are resuming...
                    m_gdb_comm.SetCurrentThreadForRun (-1);

                    // If in Non-Stop-Mode use vCont when stepping
                    if (GetTarget().GetNonStopModeEnabled())
                    {
                        if (m_gdb_comm.GetVContSupported('s'))
                            continue_packet.PutCString("vCont;s");
                        else
                            continue_packet.PutChar('s');
                    }
                    else
                        continue_packet.PutChar('s');

                    continue_packet_error = false;
                }
                else if (num_continue_c_tids == 0 &&
                         num_continue_C_tids == 0 &&
                         num_continue_s_tids == 1 &&
                         num_continue_S_tids == 0 )
                {
                    // Only one thread is stepping
                    m_gdb_comm.SetCurrentThreadForRun (m_continue_s_tids.front());
                    continue_packet.PutChar ('s');
                    continue_packet_error = false;
                }
            }

            if (!continue_packet_error && num_continue_S_tids > 0)
            {
                if (num_continue_S_tids == num_threads)
                {
                    const int step_signo = m_continue_S_tids.front().second;
                    // Are all threads trying to step with the same signal?
                    continue_packet_error = false;
                    if (num_continue_S_tids > 1)
                    {
                        for (size_t i=1; i<num_threads; ++i)
                        {
                            if (m_continue_S_tids[i].second != step_signo)
                                continue_packet_error = true;
                        }
                    }
                    if (!continue_packet_error)
                    {
                        // Add threads stepping with the same signo...
                        m_gdb_comm.SetCurrentThreadForRun (-1);
                        continue_packet.Printf("S%2.2x", step_signo);
                    }
                }
                else if (num_continue_c_tids == 0 &&
                         num_continue_C_tids == 0 &&
                         num_continue_s_tids == 0 &&
                         num_continue_S_tids == 1 )
                {
                    // Only one thread is stepping with signal
                    m_gdb_comm.SetCurrentThreadForRun (m_continue_S_tids.front().first);
                    continue_packet.Printf("S%2.2x", m_continue_S_tids.front().second);
                    continue_packet_error = false;
                }
            }
        }

        if (continue_packet_error)
        {
            error.SetErrorString ("can't make continue packet for this resume");
        }
        else
        {
            EventSP event_sp;
            TimeValue timeout;
            timeout = TimeValue::Now();
            timeout.OffsetWithSeconds (5);
            if (!m_async_thread.IsJoinable())
            {
                error.SetErrorString ("Trying to resume but the async thread is dead.");
                if (log)
                    log->Printf ("ProcessGDBRemote::DoResume: Trying to resume but the async thread is dead.");
                return error;
            }

            m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (continue_packet.GetData(), continue_packet.GetSize()));

            if (listener_sp->WaitForEvent (&timeout, event_sp) == false)
            {
                error.SetErrorString("Resume timed out.");
                if (log)
                    log->Printf ("ProcessGDBRemote::DoResume: Resume timed out.");
            }
            else if (event_sp->BroadcasterIs (&m_async_broadcaster))
            {
                error.SetErrorString ("Broadcast continue, but the async thread was killed before we got an ack back.");
                if (log)
                    log->Printf ("ProcessGDBRemote::DoResume: Broadcast continue, but the async thread was killed before we got an ack back.");
                return error;
            }
        }
    }

    return error;
}

void
ProcessGDBRemote::HandleStopReplySequence ()
{
    while(true)
    {
        // Send vStopped
        StringExtractorGDBRemote response;
        m_gdb_comm.SendPacketAndWaitForResponse("vStopped", response, false);

        // OK represents end of signal list
        if (response.IsOKResponse())
            break;

        // If not OK or a normal packet we have a problem
        if (!response.IsNormalResponse())
            break;

        SetLastStopPacket(response);
    }
}

void
ProcessGDBRemote::ClearThreadIDList ()
{
    std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());
    m_thread_ids.clear();
    m_thread_pcs.clear();
}

size_t
ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue (std::string &value)
{
    m_thread_ids.clear();
    m_thread_pcs.clear();
    size_t comma_pos;
    lldb::tid_t tid;
    while ((comma_pos = value.find(',')) != std::string::npos)
    {
        value[comma_pos] = '\0';
        // thread in big endian hex
        tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16);
        if (tid != LLDB_INVALID_THREAD_ID)
            m_thread_ids.push_back (tid);
        value.erase(0, comma_pos + 1);
    }
    tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16);
    if (tid != LLDB_INVALID_THREAD_ID)
        m_thread_ids.push_back (tid);
    return m_thread_ids.size();
}

size_t
ProcessGDBRemote::UpdateThreadPCsFromStopReplyThreadsValue (std::string &value)
{
    m_thread_pcs.clear();
    size_t comma_pos;
    lldb::addr_t pc;
    while ((comma_pos = value.find(',')) != std::string::npos)
    {
        value[comma_pos] = '\0';
        pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16);
        if (pc != LLDB_INVALID_ADDRESS)
            m_thread_pcs.push_back (pc);
        value.erase(0, comma_pos + 1);
    }
    pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16);
    if (pc != LLDB_INVALID_THREAD_ID)
        m_thread_pcs.push_back (pc);
    return m_thread_pcs.size();
}

bool
ProcessGDBRemote::UpdateThreadIDList ()
{
    std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());

    if (m_jthreadsinfo_sp)
    {
        // If we have the JSON threads info, we can get the thread list from that
        StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray();
        if (thread_infos && thread_infos->GetSize() > 0)
        {
            m_thread_ids.clear();
            m_thread_pcs.clear();
            thread_infos->ForEach([this](StructuredData::Object* object) -> bool {
                StructuredData::Dictionary *thread_dict = object->GetAsDictionary();
                if (thread_dict)
                {
                    // Set the thread stop info from the JSON dictionary
                    SetThreadStopInfo (thread_dict);
                    lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
                    if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>("tid", tid))
                        m_thread_ids.push_back(tid);
                }
                return true; // Keep iterating through all thread_info objects
            });
        }
        if (!m_thread_ids.empty())
            return true;
    }
    else
    {
        // See if we can get the thread IDs from the current stop reply packets
        // that might contain a "threads" key/value pair

        // Lock the thread stack while we access it
        //Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex);
        std::unique_lock<std::recursive_mutex> stop_stack_lock(m_last_stop_packet_mutex, std::defer_lock);
        if (stop_stack_lock.try_lock())
        {
            // Get the number of stop packets on the stack
            int nItems = m_stop_packet_stack.size();
            // Iterate over them
            for (int i = 0; i < nItems; i++)
            {
                // Get the thread stop info
                StringExtractorGDBRemote &stop_info = m_stop_packet_stack[i];
                const std::string &stop_info_str = stop_info.GetStringRef();

                m_thread_pcs.clear();
                const size_t thread_pcs_pos = stop_info_str.find(";thread-pcs:");
                if (thread_pcs_pos != std::string::npos)
                {
                    const size_t start = thread_pcs_pos + strlen(";thread-pcs:");
                    const size_t end = stop_info_str.find(';', start);
                    if (end != std::string::npos)
                    {
                        std::string value = stop_info_str.substr(start, end - start);
                        UpdateThreadPCsFromStopReplyThreadsValue(value);
                    }
                }

                const size_t threads_pos = stop_info_str.find(";threads:");
                if (threads_pos != std::string::npos)
                {
                    const size_t start = threads_pos + strlen(";threads:");
                    const size_t end = stop_info_str.find(';', start);
                    if (end != std::string::npos)
                    {
                        std::string value = stop_info_str.substr(start, end - start);
                        if (UpdateThreadIDsFromStopReplyThreadsValue(value))
                            return true;
                    }
                }
            }
        }
    }

    bool sequence_mutex_unavailable = false;
    m_gdb_comm.GetCurrentThreadIDs (m_thread_ids, sequence_mutex_unavailable);
    if (sequence_mutex_unavailable)
    {
        return false; // We just didn't get the list
    }
    return true;
}

bool
ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
{
    // locker will keep a mutex locked until it goes out of scope
    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_THREAD));
    if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
        log->Printf ("ProcessGDBRemote::%s (pid = %" PRIu64 ")", __FUNCTION__, GetID());

    size_t num_thread_ids = m_thread_ids.size();
    // The "m_thread_ids" thread ID list should always be updated after each stop
    // reply packet, but in case it isn't, update it here.
    if (num_thread_ids == 0)
    {
        if (!UpdateThreadIDList ())
            return false;
        num_thread_ids = m_thread_ids.size();
    }

    ThreadList old_thread_list_copy(old_thread_list);
    if (num_thread_ids > 0)
    {
        for (size_t i=0; i<num_thread_ids; ++i)
        {
            tid_t tid = m_thread_ids[i];
            ThreadSP thread_sp (old_thread_list_copy.RemoveThreadByProtocolID(tid, false));
            if (!thread_sp)
            {
                thread_sp.reset (new ThreadGDBRemote (*this, tid));
                if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
                    log->Printf(
                            "ProcessGDBRemote::%s Making new thread: %p for thread ID: 0x%" PRIx64 ".\n",
                            __FUNCTION__, static_cast<void*>(thread_sp.get()),
                            thread_sp->GetID());
            }
            else
            {
                if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
                    log->Printf(
                           "ProcessGDBRemote::%s Found old thread: %p for thread ID: 0x%" PRIx64 ".\n",
                           __FUNCTION__, static_cast<void*>(thread_sp.get()),
                           thread_sp->GetID());
            }
            // The m_thread_pcs vector has pc values in big-endian order, not target-endian, unlike most
            // of the register read/write packets in gdb-remote protocol.
            // Early in the process startup, we may not yet have set the process ByteOrder so we ignore these;
            // they are a performance improvement over fetching thread register values individually, the
            // method we will fall back to if needed.
            if (m_thread_ids.size() == m_thread_pcs.size() && thread_sp.get() && GetByteOrder() != eByteOrderInvalid)
            {
                ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get());
                RegisterContextSP reg_ctx_sp (thread_sp->GetRegisterContext());
                if (reg_ctx_sp)
                {
                    uint32_t pc_regnum = reg_ctx_sp->ConvertRegisterKindToRegisterNumber
                                                                   (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
                    if (pc_regnum != LLDB_INVALID_REGNUM)
                    {
                        gdb_thread->PrivateSetRegisterValue (pc_regnum, m_thread_pcs[i]);
                    }
                }
            }
            new_thread_list.AddThreadSortedByIndexID (thread_sp);
        }
    }

    // Whatever that is left in old_thread_list_copy are not
    // present in new_thread_list. Remove non-existent threads from internal id table.
    size_t old_num_thread_ids = old_thread_list_copy.GetSize(false);
    for (size_t i=0; i<old_num_thread_ids; i++)
    {
        ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex (i, false));
        if (old_thread_sp)
        {
            lldb::tid_t old_thread_id = old_thread_sp->GetProtocolID();
            m_thread_id_to_index_id_map.erase(old_thread_id);
        }
    }

    return true;
}


bool
ProcessGDBRemote::GetThreadStopInfoFromJSON (ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp)
{
    // See if we got thread stop infos for all threads via the "jThreadsInfo" packet
    if (thread_infos_sp)
    {
        StructuredData::Array *thread_infos = thread_infos_sp->GetAsArray();
        if (thread_infos)
        {
            lldb::tid_t tid;
            const size_t n = thread_infos->GetSize();
            for (size_t i=0; i<n; ++i)
            {
                StructuredData::Dictionary *thread_dict = thread_infos->GetItemAtIndex(i)->GetAsDictionary();
                if (thread_dict)
                {
                    if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>("tid", tid, LLDB_INVALID_THREAD_ID))
                    {
                        if (tid == thread->GetID())
                            return (bool)SetThreadStopInfo(thread_dict);
                    }
                }
            }
        }
    }
    return false;
}

bool
ProcessGDBRemote::CalculateThreadStopInfo (ThreadGDBRemote *thread)
{
    // See if we got thread stop infos for all threads via the "jThreadsInfo" packet
    if (GetThreadStopInfoFromJSON (thread, m_jthreadsinfo_sp))
        return true;

    // See if we got thread stop info for any threads valid stop info reasons threads
    // via the "jstopinfo" packet stop reply packet key/value pair?
    if (m_jstopinfo_sp)
    {
        // If we have "jstopinfo" then we have stop descriptions for all threads
        // that have stop reasons, and if there is no entry for a thread, then
        // it has no stop reason.
        thread->GetRegisterContext()->InvalidateIfNeeded(true);
        if (!GetThreadStopInfoFromJSON (thread, m_jstopinfo_sp))
        {
            thread->SetStopInfo (StopInfoSP());
        }
        return true;
    }

    // Fall back to using the qThreadStopInfo packet
    StringExtractorGDBRemote stop_packet;
    if (GetGDBRemote().GetThreadStopInfo(thread->GetProtocolID(), stop_packet))
        return SetThreadStopInfo (stop_packet) == eStateStopped;
    return false;
}


ThreadSP
ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid,
                                     ExpeditedRegisterMap &expedited_register_map,
                                     uint8_t signo,
                                     const std::string &thread_name,
                                     const std::string &reason,
                                     const std::string &description,
                                     uint32_t exc_type,
                                     const std::vector<addr_t> &exc_data,
                                     addr_t thread_dispatch_qaddr,
                                     bool queue_vars_valid, // Set to true if queue_name, queue_kind and queue_serial are valid
                                     LazyBool associated_with_dispatch_queue,
                                     addr_t dispatch_queue_t,
                                     std::string &queue_name,
                                     QueueKind queue_kind,
                                     uint64_t queue_serial)
{
    ThreadSP thread_sp;
    if (tid != LLDB_INVALID_THREAD_ID)
    {
        // Scope for "locker" below
        {
            // m_thread_list_real does have its own mutex, but we need to
            // hold onto the mutex between the call to m_thread_list_real.FindThreadByID(...)
            // and the m_thread_list_real.AddThread(...) so it doesn't change on us
            std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());
            thread_sp = m_thread_list_real.FindThreadByProtocolID(tid, false);

            if (!thread_sp)
            {
                // Create the thread if we need to
                thread_sp.reset (new ThreadGDBRemote (*this, tid));
                m_thread_list_real.AddThread(thread_sp);
            }
        }

        if (thread_sp)
        {
            ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get());
            gdb_thread->GetRegisterContext()->InvalidateIfNeeded(true);

            for (const auto &pair : expedited_register_map)
            {
                StringExtractor reg_value_extractor;
                reg_value_extractor.GetStringRef() = pair.second;
                gdb_thread->PrivateSetRegisterValue (pair.first, reg_value_extractor);
            }

            thread_sp->SetName (thread_name.empty() ? NULL : thread_name.c_str());

            gdb_thread->SetThreadDispatchQAddr (thread_dispatch_qaddr);
            // Check if the GDB server was able to provide the queue name, kind and serial number
            if (queue_vars_valid)
                gdb_thread->SetQueueInfo(std::move(queue_name), queue_kind, queue_serial, dispatch_queue_t, associated_with_dispatch_queue);
            else
                gdb_thread->ClearQueueInfo();

            gdb_thread->SetAssociatedWithLibdispatchQueue (associated_with_dispatch_queue);

            if (dispatch_queue_t != LLDB_INVALID_ADDRESS)
                gdb_thread->SetQueueLibdispatchQueueAddress (dispatch_queue_t);

            // Make sure we update our thread stop reason just once
            if (!thread_sp->StopInfoIsUpToDate())
            {
                thread_sp->SetStopInfo (StopInfoSP());
                // If there's a memory thread backed by this thread, we need to use it to calcualte StopInfo.
                ThreadSP memory_thread_sp = m_thread_list.FindThreadByProtocolID(thread_sp->GetProtocolID());
                if (memory_thread_sp)
                    thread_sp = memory_thread_sp;

                if (exc_type != 0)
                {
                    const size_t exc_data_size = exc_data.size();

                    thread_sp->SetStopInfo (StopInfoMachException::CreateStopReasonWithMachException (*thread_sp,
                                                                                                      exc_type,
                                                                                                      exc_data_size,
                                                                                                      exc_data_size >= 1 ? exc_data[0] : 0,
                                                                                                      exc_data_size >= 2 ? exc_data[1] : 0,
                                                                                                      exc_data_size >= 3 ? exc_data[2] : 0));
                }
                else
                {
                    bool handled = false;
                    bool did_exec = false;
                    if (!reason.empty())
                    {
                        if (reason.compare("trace") == 0)
                        {
                            addr_t pc = thread_sp->GetRegisterContext()->GetPC();
                            lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);

                            // If the current pc is a breakpoint site then the StopInfo should be set to Breakpoint
                            // Otherwise, it will be set to Trace.
                            if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get()))
                            {
                                thread_sp->SetStopInfo(
                                    StopInfo::CreateStopReasonWithBreakpointSiteID(*thread_sp, bp_site_sp->GetID()));
                            }
                            else
                              thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));
                            handled = true;
                        }
                        else if (reason.compare("breakpoint") == 0)
                        {
                            addr_t pc = thread_sp->GetRegisterContext()->GetPC();
                            lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
                            if (bp_site_sp)
                            {
                                // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
                                // we can just report no reason.  We don't need to worry about stepping over the breakpoint here, that
                                // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
                                handled = true;
                                if (bp_site_sp->ValidForThisThread (thread_sp.get()))
                                {
                                    thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
                                }
                                else
                                {
                                    StopInfoSP invalid_stop_info_sp;
                                    thread_sp->SetStopInfo (invalid_stop_info_sp);
                                }
                            }
                        }
                        else if (reason.compare("trap") == 0)
                        {
                            // Let the trap just use the standard signal stop reason below...
                        }
                        else if (reason.compare("watchpoint") == 0)
                        {
                            StringExtractor desc_extractor(description.c_str());
                            addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
                            uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32);
                            addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
                            watch_id_t watch_id = LLDB_INVALID_WATCH_ID;
                            if (wp_addr != LLDB_INVALID_ADDRESS)
                            {
                                WatchpointSP wp_sp;
                                ArchSpec::Core core = GetTarget().GetArchitecture().GetCore();
                                if ((core >= ArchSpec::kCore_mips_first && core <= ArchSpec::kCore_mips_last) ||
                                    (core >= ArchSpec::eCore_arm_generic && core <= ArchSpec::eCore_arm_aarch64))
                                    wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_hit_addr);
                                if (!wp_sp)
                                    wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr);
                                if (wp_sp)
                                {
                                    wp_sp->SetHardwareIndex(wp_index);
                                    watch_id = wp_sp->GetID();
                                }
                            }
                            if (watch_id == LLDB_INVALID_WATCH_ID)
                            {
                                Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_WATCHPOINTS));
                                if (log) log->Printf ("failed to find watchpoint");
                            }
                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID (*thread_sp, watch_id, wp_hit_addr));
                            handled = true;
                        }
                        else if (reason.compare("exception") == 0)
                        {
                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException(*thread_sp, description.c_str()));
                            handled = true;
                        }
                        else if (reason.compare("exec") == 0)
                        {
                            did_exec = true;
                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithExec(*thread_sp));
                            handled = true;
                        }
                    }
                    else if (!signo)
                    {
                        addr_t pc = thread_sp->GetRegisterContext()->GetPC();
                        lldb::BreakpointSiteSP bp_site_sp =
                            thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);

                        // If the current pc is a breakpoint site then the StopInfo should be set to Breakpoint
                        // even though the remote stub did not set it as such. This can happen when
                        // the thread is involuntarily interrupted (e.g. due to stops on other
                        // threads) just as it is about to execute the breakpoint instruction.
                        if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get()))
                        {
                            thread_sp->SetStopInfo(
                                StopInfo::CreateStopReasonWithBreakpointSiteID(*thread_sp, bp_site_sp->GetID()));
                            handled = true;
                        }
                    }

                    if (!handled && signo && did_exec == false)
                    {
                        if (signo == SIGTRAP)
                        {
                            // Currently we are going to assume SIGTRAP means we are either
                            // hitting a breakpoint or hardware single stepping.
                            handled = true;
                            addr_t pc = thread_sp->GetRegisterContext()->GetPC() + m_breakpoint_pc_offset;
                            lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);

                            if (bp_site_sp)
                            {
                                // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
                                // we can just report no reason.  We don't need to worry about stepping over the breakpoint here, that
                                // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
                                if (bp_site_sp->ValidForThisThread (thread_sp.get()))
                                {
                                    if(m_breakpoint_pc_offset != 0)
                                        thread_sp->GetRegisterContext()->SetPC(pc);
                                    thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
                                }
                                else
                                {
                                    StopInfoSP invalid_stop_info_sp;
                                    thread_sp->SetStopInfo (invalid_stop_info_sp);
                                }
                            }
                            else
                            {
                                // If we were stepping then assume the stop was the result of the trace.  If we were
                                // not stepping then report the SIGTRAP.
                                // FIXME: We are still missing the case where we single step over a trap instruction.
                                if (thread_sp->GetTemporaryResumeState() == eStateStepping)
                                    thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));
                                else
                                    thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal(*thread_sp, signo, description.c_str()));
                            }
                        }
                        if (!handled)
                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo, description.c_str()));
                    }

                    if (!description.empty())
                    {
                        lldb::StopInfoSP stop_info_sp (thread_sp->GetStopInfo ());
                        if (stop_info_sp)
                        {
                            const char *stop_info_desc = stop_info_sp->GetDescription();
                            if (!stop_info_desc || !stop_info_desc[0])
                                stop_info_sp->SetDescription (description.c_str());
                        }
                        else
                        {
                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException (*thread_sp, description.c_str()));
                        }
                    }
                }
            }
        }
    }
    return thread_sp;
}

lldb::ThreadSP
ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
{
    static ConstString g_key_tid("tid");
    static ConstString g_key_name("name");
    static ConstString g_key_reason("reason");
    static ConstString g_key_metype("metype");
    static ConstString g_key_medata("medata");
    static ConstString g_key_qaddr("qaddr");
    static ConstString g_key_dispatch_queue_t("dispatch_queue_t");
    static ConstString g_key_associated_with_dispatch_queue("associated_with_dispatch_queue");
    static ConstString g_key_queue_name("qname");
    static ConstString g_key_queue_kind("qkind");
    static ConstString g_key_queue_serial_number("qserialnum");
    static ConstString g_key_registers("registers");
    static ConstString g_key_memory("memory");
    static ConstString g_key_address("address");
    static ConstString g_key_bytes("bytes");
    static ConstString g_key_description("description");
    static ConstString g_key_signal("signal");

    // Stop with signal and thread info
    lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
    uint8_t signo = 0;
    std::string value;
    std::string thread_name;
    std::string reason;
    std::string description;
    uint32_t exc_type = 0;
    std::vector<addr_t> exc_data;
    addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS;
    ExpeditedRegisterMap expedited_register_map;
    bool queue_vars_valid = false;
    addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS;
    LazyBool associated_with_dispatch_queue = eLazyBoolCalculate;
    std::string queue_name;
    QueueKind queue_kind = eQueueKindUnknown;
    uint64_t queue_serial_number = 0;
    // Iterate through all of the thread dictionary key/value pairs from the structured data dictionary

    thread_dict->ForEach([this,
                          &tid,
                          &expedited_register_map,
                          &thread_name,
                          &signo,
                          &reason,
                          &description,
                          &exc_type,
                          &exc_data,
                          &thread_dispatch_qaddr,
                          &queue_vars_valid,
                          &associated_with_dispatch_queue,
                          &dispatch_queue_t,
                          &queue_name,
                          &queue_kind,
                          &queue_serial_number]
                          (ConstString key, StructuredData::Object* object) -> bool
    {
        if (key == g_key_tid)
        {
            // thread in big endian hex
            tid = object->GetIntegerValue(LLDB_INVALID_THREAD_ID);
        }
        else if (key == g_key_metype)
        {
            // exception type in big endian hex
            exc_type = object->GetIntegerValue(0);
        }
        else if (key == g_key_medata)
        {
            // exception data in big endian hex
            StructuredData::Array *array = object->GetAsArray();
            if (array)
            {
                array->ForEach([&exc_data](StructuredData::Object* object) -> bool {
                    exc_data.push_back(object->GetIntegerValue());
                    return true; // Keep iterating through all array items
                });
            }
        }
        else if (key == g_key_name)
        {
            thread_name = object->GetStringValue();
        }
        else if (key == g_key_qaddr)
        {
            thread_dispatch_qaddr = object->GetIntegerValue(LLDB_INVALID_ADDRESS);
        }
        else if (key == g_key_queue_name)
        {
            queue_vars_valid = true;
            queue_name = object->GetStringValue();
        }
        else if (key == g_key_queue_kind)
        {
            std::string queue_kind_str = object->GetStringValue();
            if (queue_kind_str == "serial")
            {
                queue_vars_valid = true;
                queue_kind = eQueueKindSerial;
            }
            else if (queue_kind_str == "concurrent")
            {
                queue_vars_valid = true;
                queue_kind = eQueueKindConcurrent;
            }
        }
        else if (key == g_key_queue_serial_number)
        {
            queue_serial_number = object->GetIntegerValue(0);
            if (queue_serial_number != 0)
                queue_vars_valid = true;
        }
        else if (key == g_key_dispatch_queue_t)
        {
            dispatch_queue_t = object->GetIntegerValue(0);
            if (dispatch_queue_t != 0 && dispatch_queue_t != LLDB_INVALID_ADDRESS)
                queue_vars_valid = true;
        }
        else if (key == g_key_associated_with_dispatch_queue)
        {
            queue_vars_valid = true;
            bool associated = object->GetBooleanValue ();
            if (associated)
                associated_with_dispatch_queue = eLazyBoolYes;
            else
                associated_with_dispatch_queue = eLazyBoolNo;
        }
        else if (key == g_key_reason)
        {
            reason = object->GetStringValue();
        }
        else if (key == g_key_description)
        {
            description = object->GetStringValue();
        }
        else if (key == g_key_registers)
        {
            StructuredData::Dictionary *registers_dict = object->GetAsDictionary();

            if (registers_dict)
            {
                registers_dict->ForEach([&expedited_register_map](ConstString key, StructuredData::Object* object) -> bool {
                    const uint32_t reg = StringConvert::ToUInt32 (key.GetCString(), UINT32_MAX, 10);
                    if (reg != UINT32_MAX)
                        expedited_register_map[reg] = object->GetStringValue();
                    return true; // Keep iterating through all array items
                });
            }
        }
        else if (key == g_key_memory)
        {
            StructuredData::Array *array = object->GetAsArray();
            if (array)
            {
                array->ForEach([this](StructuredData::Object* object) -> bool {
                    StructuredData::Dictionary *mem_cache_dict = object->GetAsDictionary();
                    if (mem_cache_dict)
                    {
                        lldb::addr_t mem_cache_addr = LLDB_INVALID_ADDRESS;
                        if (mem_cache_dict->GetValueForKeyAsInteger<lldb::addr_t>("address", mem_cache_addr))
                        {
                            if (mem_cache_addr != LLDB_INVALID_ADDRESS)
                            {
                                StringExtractor bytes;
                                if (mem_cache_dict->GetValueForKeyAsString("bytes", bytes.GetStringRef()))
                                {
                                    bytes.SetFilePos(0);

                                    const size_t byte_size = bytes.GetStringRef().size()/2;
                                    DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0));
                                    const size_t bytes_copied = bytes.GetHexBytes (data_buffer_sp->GetBytes(), byte_size, 0);
                                    if (bytes_copied == byte_size)
                                        m_memory_cache.AddL1CacheData(mem_cache_addr, data_buffer_sp);
                                }
                            }
                        }
                    }
                    return true; // Keep iterating through all array items
                });
            }

        }
        else if (key == g_key_signal)
            signo = object->GetIntegerValue(LLDB_INVALID_SIGNAL_NUMBER);
        return true; // Keep iterating through all dictionary key/value pairs
    });

    return SetThreadStopInfo (tid,
                              expedited_register_map,
                              signo,
                              thread_name,
                              reason,
                              description,
                              exc_type,
                              exc_data,
                              thread_dispatch_qaddr,
                              queue_vars_valid,
                              associated_with_dispatch_queue,
                              dispatch_queue_t,
                              queue_name,
                              queue_kind,
                              queue_serial_number);
}

StateType
ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
{
    stop_packet.SetFilePos (0);
    const char stop_type = stop_packet.GetChar();
    switch (stop_type)
    {
    case 'T':
    case 'S':
        {
            // This is a bit of a hack, but is is required. If we did exec, we
            // need to clear our thread lists and also know to rebuild our dynamic
            // register info before we lookup and threads and populate the expedited
            // register values so we need to know this right away so we can cleanup
            // and update our registers.
            const uint32_t stop_id = GetStopID();
            if (stop_id == 0)
            {
                // Our first stop, make sure we have a process ID, and also make
                // sure we know about our registers
                if (GetID() == LLDB_INVALID_PROCESS_ID)
                {
                    lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID ();
                    if (pid != LLDB_INVALID_PROCESS_ID)
                        SetID (pid);
                }
                BuildDynamicRegisterInfo (true);
            }
            // Stop with signal and thread info
            lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
            const uint8_t signo = stop_packet.GetHexU8();
            std::string key;
            std::string value;
            std::string thread_name;
            std::string reason;
            std::string description;
            uint32_t exc_type = 0;
            std::vector<addr_t> exc_data;
            addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS;
            bool queue_vars_valid = false; // says if locals below that start with "queue_" are valid
            addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS;
            LazyBool associated_with_dispatch_queue = eLazyBoolCalculate;
            std::string queue_name;
            QueueKind queue_kind = eQueueKindUnknown;
            uint64_t queue_serial_number = 0;
            ExpeditedRegisterMap expedited_register_map;
            while (stop_packet.GetNameColonValue(key, value))
            {
                if (key.compare("metype") == 0)
                {
                    // exception type in big endian hex
                    exc_type = StringConvert::ToUInt32 (value.c_str(), 0, 16);
                }
                else if (key.compare("medata") == 0)
                {
                    // exception data in big endian hex
                    exc_data.push_back(StringConvert::ToUInt64 (value.c_str(), 0, 16));
                }
                else if (key.compare("thread") == 0)
                {
                    // thread in big endian hex
                    tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16);
                }
                else if (key.compare("threads") == 0)
                {
                    std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());

                    m_thread_ids.clear();
                    // A comma separated list of all threads in the current
                    // process that includes the thread for this stop reply
                    // packet
                    size_t comma_pos;
                    lldb::tid_t tid;
                    while ((comma_pos = value.find(',')) != std::string::npos)
                    {
                        value[comma_pos] = '\0';
                        // thread in big endian hex
                        tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16);
                        if (tid != LLDB_INVALID_THREAD_ID)
                            m_thread_ids.push_back (tid);
                        value.erase(0, comma_pos + 1);
                    }
                    tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16);
                    if (tid != LLDB_INVALID_THREAD_ID)
                        m_thread_ids.push_back (tid);
                }
                else if (key.compare("thread-pcs") == 0)
                {
                    m_thread_pcs.clear();
                    // A comma separated list of all threads in the current
                    // process that includes the thread for this stop reply
                    // packet
                    size_t comma_pos;
                    lldb::addr_t pc;
                    while ((comma_pos = value.find(',')) != std::string::npos)
                    {
                        value[comma_pos] = '\0';
                        // thread in big endian hex
                        pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16);
                        if (pc != LLDB_INVALID_ADDRESS)
                            m_thread_pcs.push_back (pc);
                        value.erase(0, comma_pos + 1);
                    }
                    pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16);
                    if (pc != LLDB_INVALID_ADDRESS)
                        m_thread_pcs.push_back (pc);
                }
                else if (key.compare("jstopinfo") == 0)
                {
                    StringExtractor json_extractor;
                    // Swap "value" over into "name_extractor"
                    json_extractor.GetStringRef().swap(value);
                    // Now convert the HEX bytes into a string value
                    json_extractor.GetHexByteString (value);

                    // This JSON contains thread IDs and thread stop info for all threads.
                    // It doesn't contain expedited registers, memory or queue info.
                    m_jstopinfo_sp = StructuredData::ParseJSON (value);
                }
                else if (key.compare("hexname") == 0)
                {
                    StringExtractor name_extractor;
                    // Swap "value" over into "name_extractor"
                    name_extractor.GetStringRef().swap(value);
                    // Now convert the HEX bytes into a string value
                    name_extractor.GetHexByteString (value);
                    thread_name.swap (value);
                }
                else if (key.compare("name") == 0)
                {
                    thread_name.swap (value);
                }
                else if (key.compare("qaddr") == 0)
                {
                    thread_dispatch_qaddr = StringConvert::ToUInt64 (value.c_str(), 0, 16);
                }
                else if (key.compare("dispatch_queue_t") == 0)
                {
                    queue_vars_valid = true;
                    dispatch_queue_t = StringConvert::ToUInt64 (value.c_str(), 0, 16);
                }
                else if (key.compare("qname") == 0)
                {
                    queue_vars_valid = true;
                    StringExtractor name_extractor;
                    // Swap "value" over into "name_extractor"
                    name_extractor.GetStringRef().swap(value);
                    // Now convert the HEX bytes into a string value
                    name_extractor.GetHexByteString (value);
                    queue_name.swap (value);
                }
                else if (key.compare("qkind") == 0)
                {
                    if (value == "serial")
                    {
                        queue_vars_valid = true;
                        queue_kind = eQueueKindSerial;
                    }
                    else if (value == "concurrent")
                    {
                        queue_vars_valid = true;
                        queue_kind = eQueueKindConcurrent;
                    }
                }
                else if (key.compare("qserialnum") == 0)
                {
                    queue_serial_number = StringConvert::ToUInt64 (value.c_str(), 0, 0);
                    if (queue_serial_number != 0)
                        queue_vars_valid = true;
                }
                else if (key.compare("reason") == 0)
                {
                    reason.swap(value);
                }
                else if (key.compare("description") == 0)
                {
                    StringExtractor desc_extractor;
                    // Swap "value" over into "name_extractor"
                    desc_extractor.GetStringRef().swap(value);
                    // Now convert the HEX bytes into a string value
                    desc_extractor.GetHexByteString (value);
                    description.swap(value);
                }
                else if (key.compare("memory") == 0)
                {
                    // Expedited memory. GDB servers can choose to send back expedited memory
                    // that can populate the L1 memory cache in the process so that things like
                    // the frame pointer backchain can be expedited. This will help stack
                    // backtracing be more efficient by not having to send as many memory read
                    // requests down the remote GDB server.

                    // Key/value pair format: memory:<addr>=<bytes>;
                    // <addr> is a number whose base will be interpreted by the prefix:
                    //      "0x[0-9a-fA-F]+" for hex
                    //      "0[0-7]+" for octal
                    //      "[1-9]+" for decimal
                    // <bytes> is native endian ASCII hex bytes just like the register values
                    llvm::StringRef value_ref(value);
                    std::pair<llvm::StringRef, llvm::StringRef> pair;
                    pair = value_ref.split('=');
                    if (!pair.first.empty() && !pair.second.empty())
                    {
                        std::string addr_str(pair.first.str());
                        const lldb::addr_t mem_cache_addr = StringConvert::ToUInt64(addr_str.c_str(), LLDB_INVALID_ADDRESS, 0);
                        if (mem_cache_addr != LLDB_INVALID_ADDRESS)
                        {
                            StringExtractor bytes;
                            bytes.GetStringRef() = pair.second.str();
                            const size_t byte_size = bytes.GetStringRef().size()/2;
                            DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0));
                            const size_t bytes_copied = bytes.GetHexBytes (data_buffer_sp->GetBytes(), byte_size, 0);
                            if (bytes_copied == byte_size)
                                m_memory_cache.AddL1CacheData(mem_cache_addr, data_buffer_sp);
                        }
                    }
                }
                else if (key.compare("watch") == 0 || key.compare("rwatch") == 0 || key.compare("awatch") == 0)
                {
                    // Support standard GDB remote stop reply packet 'TAAwatch:addr'
                    lldb::addr_t wp_addr = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16);
                    WatchpointSP wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr);
                    uint32_t wp_index = LLDB_INVALID_INDEX32;

                    if (wp_sp)
                        wp_index = wp_sp->GetHardwareIndex();

                    reason = "watchpoint";
                    StreamString ostr;
                    ostr.Printf("%" PRIu64 " %" PRIu32, wp_addr, wp_index);
                    description = ostr.GetString().c_str();
                }
                else if (key.compare("library") == 0)
                {
                    LoadModules();
                }
                else if (key.size() == 2 && ::isxdigit(key[0]) && ::isxdigit(key[1]))
                {
                    uint32_t reg = StringConvert::ToUInt32 (key.c_str(), UINT32_MAX, 16);
                    if (reg != UINT32_MAX)
                        expedited_register_map[reg] = std::move(value);
                }
            }

            if (tid == LLDB_INVALID_THREAD_ID)
            {
                // A thread id may be invalid if the response is old style 'S' packet which does not provide the
                // thread information. So update the thread list and choose the first one.
                UpdateThreadIDList ();

                if (!m_thread_ids.empty ())
                {
                    tid = m_thread_ids.front ();
                }
            }

            ThreadSP thread_sp = SetThreadStopInfo (tid,
                                                    expedited_register_map,
                                                    signo,
                                                    thread_name,
                                                    reason,
                                                    description,
                                                    exc_type,
                                                    exc_data,
                                                    thread_dispatch_qaddr,
                                                    queue_vars_valid,
                                                    associated_with_dispatch_queue,
                                                    dispatch_queue_t,
                                                    queue_name,
                                                    queue_kind,
                                                    queue_serial_number);

            return eStateStopped;
        }
        break;

    case 'W':
    case 'X':
        // process exited
        return eStateExited;

    default:
        break;
    }
    return eStateInvalid;
}

void
ProcessGDBRemote::RefreshStateAfterStop ()
{
    std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());

    m_thread_ids.clear();
    m_thread_pcs.clear();
    // Set the thread stop info. It might have a "threads" key whose value is
    // a list of all thread IDs in the current process, so m_thread_ids might
    // get set.

    // Scope for the lock
    {
        // Lock the thread stack while we access it
        std::lock_guard<std::recursive_mutex> guard(m_last_stop_packet_mutex);
        // Get the number of stop packets on the stack
        int nItems = m_stop_packet_stack.size();
        // Iterate over them
        for (int i = 0; i < nItems; i++)
        {
            // Get the thread stop info
            StringExtractorGDBRemote stop_info = m_stop_packet_stack[i];
            // Process thread stop info
            SetThreadStopInfo(stop_info);
        }
        // Clear the thread stop stack
        m_stop_packet_stack.clear();
    }

    // Check to see if SetThreadStopInfo() filled in m_thread_ids?
    if (m_thread_ids.empty())
    {
        // No, we need to fetch the thread list manually
        UpdateThreadIDList();
    }

    // If we have queried for a default thread id
    if (m_initial_tid != LLDB_INVALID_THREAD_ID)
    {
        m_thread_list.SetSelectedThreadByID(m_initial_tid);
        m_initial_tid = LLDB_INVALID_THREAD_ID;
    }

    // Let all threads recover from stopping and do any clean up based
    // on the previous thread state (if any).
    m_thread_list_real.RefreshStateAfterStop();

}

Error
ProcessGDBRemote::DoHalt (bool &caused_stop)
{
    Error error;

    bool timed_out = false;
    Mutex::Locker locker;

    if (m_public_state.GetValue() == eStateAttaching)
    {
        // We are being asked to halt during an attach. We need to just close
        // our file handle and debugserver will go away, and we can be done...
        m_gdb_comm.Disconnect();
    }
    else
    {
        if (!m_gdb_comm.SendInterrupt (locker, 2, timed_out))
        {
            if (timed_out)
                error.SetErrorString("timed out sending interrupt packet");
            else
                error.SetErrorString("unknown error sending interrupt packet");
        }

        caused_stop = m_gdb_comm.GetInterruptWasSent ();
    }
    return error;
}

Error
ProcessGDBRemote::DoDetach(bool keep_stopped)
{
    Error error;
    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
    if (log)
        log->Printf ("ProcessGDBRemote::DoDetach(keep_stopped: %i)", keep_stopped);

    error = m_gdb_comm.Detach (keep_stopped);
    if (log)
    {
        if (error.Success())
            log->PutCString ("ProcessGDBRemote::DoDetach() detach packet sent successfully");
        else
            log->Printf ("ProcessGDBRemote::DoDetach() detach packet send failed: %s", error.AsCString() ? error.AsCString() : "<unknown error>");
    }

    if (!error.Success())
        return error;

    // Sleep for one second to let the process get all detached...
    StopAsyncThread ();

    SetPrivateState (eStateDetached);
    ResumePrivateStateThread();

    //KillDebugserverProcess ();
    return error;
}


Error
ProcessGDBRemote::DoDestroy ()
{
    Error error;
    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
    if (log)
        log->Printf ("ProcessGDBRemote::DoDestroy()");

    // There is a bug in older iOS debugservers where they don't shut down the process
    // they are debugging properly.  If the process is sitting at a breakpoint or an exception,
    // this can cause problems with restarting.  So we check to see if any of our threads are stopped
    // at a breakpoint, and if so we remove all the breakpoints, resume the process, and THEN
    // destroy it again.
    //
    // Note, we don't have a good way to test the version of debugserver, but I happen to know that
    // the set of all the iOS debugservers which don't support GetThreadSuffixSupported() and that of
    // the debugservers with this bug are equal.  There really should be a better way to test this!
    //
    // We also use m_destroy_tried_resuming to make sure we only do this once, if we resume and then halt and
    // get called here to destroy again and we're still at a breakpoint or exception, then we should
    // just do the straight-forward kill.
    //
    // And of course, if we weren't able to stop the process by the time we get here, it isn't
    // necessary (or helpful) to do any of this.

    if (!m_gdb_comm.GetThreadSuffixSupported() && m_public_state.GetValue() != eStateRunning)
    {
        PlatformSP platform_sp = GetTarget().GetPlatform();

        // FIXME: These should be ConstStrings so we aren't doing strcmp'ing.
        if (platform_sp
            && platform_sp->GetName()
            && platform_sp->GetName() == PlatformRemoteiOS::GetPluginNameStatic())
        {
            if (m_destroy_tried_resuming)
            {
                if (log)
                    log->PutCString ("ProcessGDBRemote::DoDestroy() - Tried resuming to destroy once already, not doing it again.");
            }
            else
            {
                // At present, the plans are discarded and the breakpoints disabled Process::Destroy,
                // but we really need it to happen here and it doesn't matter if we do it twice.
                m_thread_list.DiscardThreadPlans();
                DisableAllBreakpointSites();

                bool stop_looks_like_crash = false;
                ThreadList &threads = GetThreadList();

                {
                    std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());

                    size_t num_threads = threads.GetSize();
                    for (size_t i = 0; i < num_threads; i++)
                    {
                        ThreadSP thread_sp = threads.GetThreadAtIndex(i);
                        StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo();
                        StopReason reason = eStopReasonInvalid;
                        if (stop_info_sp)
                            reason = stop_info_sp->GetStopReason();
                        if (reason == eStopReasonBreakpoint
                            || reason == eStopReasonException)
                        {
                            if (log)
                                log->Printf ("ProcessGDBRemote::DoDestroy() - thread: 0x%4.4" PRIx64 " stopped with reason: %s.",
                                             thread_sp->GetProtocolID(),
                                             stop_info_sp->GetDescription());
                            stop_looks_like_crash = true;
                            break;
                        }
                    }
                }

                if (stop_looks_like_crash)
                {
                    if (log)
                        log->PutCString ("ProcessGDBRemote::DoDestroy() - Stopped at a breakpoint, continue and then kill.");
                    m_destroy_tried_resuming = true;

                    // If we are going to run again before killing, it would be good to suspend all the threads
                    // before resuming so they won't get into more trouble.  Sadly, for the threads stopped with
                    // the breakpoint or exception, the exception doesn't get cleared if it is suspended, so we do
                    // have to run the risk of letting those threads proceed a bit.

                    {
                        std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());

                        size_t num_threads = threads.GetSize();
                        for (size_t i = 0; i < num_threads; i++)
                        {
                            ThreadSP thread_sp = threads.GetThreadAtIndex(i);
                            StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo();
                            StopReason reason = eStopReasonInvalid;
                            if (stop_info_sp)
                                reason = stop_info_sp->GetStopReason();
                            if (reason != eStopReasonBreakpoint
                                && reason != eStopReasonException)
                            {
                                if (log)
                                    log->Printf ("ProcessGDBRemote::DoDestroy() - Suspending thread: 0x%4.4" PRIx64 " before running.",
                                                 thread_sp->GetProtocolID());
                                thread_sp->SetResumeState(eStateSuspended);
                            }
                        }
                    }
                    Resume ();
                    return Destroy(false);
                }
            }
        }
    }

    // Interrupt if our inferior is running...
    int exit_status = SIGABRT;
    std::string exit_string;

    if (m_gdb_comm.IsConnected())
    {
        if (m_public_state.GetValue() != eStateAttaching)
        {
            StringExtractorGDBRemote response;
            bool send_async = true;
            GDBRemoteCommunication::ScopedTimeout (m_gdb_comm, 3);

            if (m_gdb_comm.SendPacketAndWaitForResponse("k", 1, response, send_async) == GDBRemoteCommunication::PacketResult::Success)
            {
                char packet_cmd = response.GetChar(0);

                if (packet_cmd == 'W' || packet_cmd == 'X')
                {
#if defined(__APPLE__)
                    // For Native processes on Mac OS X, we launch through the Host Platform, then hand the process off
                    // to debugserver, which becomes the parent process through "PT_ATTACH".  Then when we go to kill
                    // the process on Mac OS X we call ptrace(PT_KILL) to kill it, then we call waitpid which returns
                    // with no error and the correct status.  But amusingly enough that doesn't seem to actually reap
                    // the process, but instead it is left around as a Zombie.  Probably the kernel is in the process of
                    // switching ownership back to lldb which was the original parent, and gets confused in the handoff.
                    // Anyway, so call waitpid here to finally reap it.
                    PlatformSP platform_sp(GetTarget().GetPlatform());
                    if (platform_sp && platform_sp->IsHost())
                    {
                        int status;
                        ::pid_t reap_pid;
                        reap_pid = waitpid (GetID(), &status, WNOHANG);
                        if (log)
                            log->Printf ("Reaped pid: %d, status: %d.\n", reap_pid, status);
                    }
#endif
                    SetLastStopPacket (response);
                    ClearThreadIDList ();
                    exit_status = response.GetHexU8();
                }
                else
                {
                    if (log)
                        log->Printf ("ProcessGDBRemote::DoDestroy - got unexpected response to k packet: %s", response.GetStringRef().c_str());
                    exit_string.assign("got unexpected response to k packet: ");
                    exit_string.append(response.GetStringRef());
                }
            }
            else
            {
                if (log)
                    log->Printf ("ProcessGDBRemote::DoDestroy - failed to send k packet");
                exit_string.assign("failed to send the k packet");
            }
        }
        else
        {
            if (log)
                log->Printf ("ProcessGDBRemote::DoDestroy - killed or interrupted while attaching");
            exit_string.assign ("killed or interrupted while attaching.");
        }
    }
    else
    {
        // If we missed setting the exit status on the way out, do it here.
        // NB set exit status can be called multiple times, the first one sets the status.
        exit_string.assign("destroying when not connected to debugserver");
    }

    SetExitStatus(exit_status, exit_string.c_str());

    StopAsyncThread ();
    KillDebugserverProcess ();
    return error;
}

void
ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response)
{
    const bool did_exec = response.GetStringRef().find(";reason:exec;") != std::string::npos;
    if (did_exec)
    {
        Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
        if (log)
            log->Printf ("ProcessGDBRemote::SetLastStopPacket () - detected exec");

        m_thread_list_real.Clear();
        m_thread_list.Clear();
        BuildDynamicRegisterInfo (true);
        m_gdb_comm.ResetDiscoverableSettings (did_exec);
    }

    // Scope the lock
    {
        // Lock the thread stack while we access it
        std::lock_guard<std::recursive_mutex> guard(m_last_stop_packet_mutex);

        // We are are not using non-stop mode, there can only be one last stop
        // reply packet, so clear the list.
        if (GetTarget().GetNonStopModeEnabled() == false)
            m_stop_packet_stack.clear();

        // Add this stop packet to the stop packet stack
        // This stack will get popped and examined when we switch to the
        // Stopped state
        m_stop_packet_stack.push_back(response);
    }
}

void
ProcessGDBRemote::SetUnixSignals(const UnixSignalsSP &signals_sp)
{
    Process::SetUnixSignals(std::make_shared<GDBRemoteSignals>(signals_sp));
}

//------------------------------------------------------------------
// Process Queries
//------------------------------------------------------------------

bool
ProcessGDBRemote::IsAlive ()
{
    return m_gdb_comm.IsConnected() && Process::IsAlive();
}

addr_t
ProcessGDBRemote::GetImageInfoAddress()
{
    // request the link map address via the $qShlibInfoAddr packet
    lldb::addr_t addr = m_gdb_comm.GetShlibInfoAddr();

    // the loaded module list can also provides a link map address
    if (addr == LLDB_INVALID_ADDRESS)
    {
        LoadedModuleInfoList list;
        if (GetLoadedModuleList (list).Success())
            addr = list.m_link_map;
    }

    return addr;
}

void
ProcessGDBRemote::WillPublicStop ()
{
    // See if the GDB remote client supports the JSON threads info.
    // If so, we gather stop info for all threads, expedited registers,
    // expedited memory, runtime queue information (iOS and MacOSX only),
    // and more. Expediting memory will help stack backtracing be much
    // faster. Expediting registers will make sure we don't have to read
    // the thread registers for GPRs.
    m_jthreadsinfo_sp = m_gdb_comm.GetThreadsInfo();

    if (m_jthreadsinfo_sp)
    {
        // Now set the stop info for each thread and also expedite any registers
        // and memory that was in the jThreadsInfo response.
        StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray();
        if (thread_infos)
        {
            const size_t n = thread_infos->GetSize();
            for (size_t i=0; i<n; ++i)
            {
                StructuredData::Dictionary *thread_dict = thread_infos->GetItemAtIndex(i)->GetAsDictionary();
                if (thread_dict)
                    SetThreadStopInfo(thread_dict);
            }
        }
    }
}

//------------------------------------------------------------------
// Process Memory
//------------------------------------------------------------------
size_t
ProcessGDBRemote::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error)
{
    GetMaxMemorySize ();
    if (size > m_max_memory_size)
    {
        // Keep memory read sizes down to a sane limit. This function will be
        // called multiple times in order to complete the task by
        // lldb_private::Process so it is ok to do this.
        size = m_max_memory_size;
    }

    char packet[64];
    int packet_len;
    bool binary_memory_read = m_gdb_comm.GetxPacketSupported();
    packet_len = ::snprintf(packet, sizeof(packet), "%c%" PRIx64 ",%" PRIx64,
                            binary_memory_read ? 'x' : 'm', (uint64_t)addr, (uint64_t)size);
    assert (packet_len + 1 < (int)sizeof(packet));
    StringExtractorGDBRemote response;
    if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, true) == GDBRemoteCommunication::PacketResult::Success)
    {
        if (response.IsNormalResponse())
        {
            error.Clear();
            if (binary_memory_read)
            {
                // The lower level GDBRemoteCommunication packet receive layer has already de-quoted any
                // 0x7d character escaping that was present in the packet

                size_t data_received_size = response.GetBytesLeft();
                if (data_received_size > size)
                {
                    // Don't write past the end of BUF if the remote debug server gave us too
                    // much data for some reason.
                    data_received_size = size;
                }
                memcpy (buf, response.GetStringRef().data(), data_received_size);
                return data_received_size;
            }
            else
            {
                return response.GetHexBytes(buf, size, '\xdd');
            }
        }
        else if (response.IsErrorResponse())
            error.SetErrorStringWithFormat("memory read failed for 0x%" PRIx64, addr);
        else if (response.IsUnsupportedResponse())
            error.SetErrorStringWithFormat("GDB server does not support reading memory");
        else
            error.SetErrorStringWithFormat("unexpected response to GDB server memory read packet '%s': '%s'", packet, response.GetStringRef().c_str());
    }
    else
    {
        error.SetErrorStringWithFormat("failed to send packet: '%s'", packet);
    }
    return 0;
}

size_t
ProcessGDBRemote::DoWriteMemory (addr_t addr, const void *buf, size_t size, Error &error)
{
    GetMaxMemorySize ();
    if (size > m_max_memory_size)
    {
        // Keep memory read sizes down to a sane limit. This function will be
        // called multiple times in order to complete the task by
        // lldb_private::Process so it is ok to do this.
        size = m_max_memory_size;
    }

    StreamString packet;
    packet.Printf("M%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size);
    packet.PutBytesAsRawHex8(buf, size, endian::InlHostByteOrder(), endian::InlHostByteOrder());
    StringExtractorGDBRemote response;
    if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, true) == GDBRemoteCommunication::PacketResult::Success)
    {
        if (response.IsOKResponse())
        {
            error.Clear();
            return size;
        }
        else if (response.IsErrorResponse())
            error.SetErrorStringWithFormat("memory write failed for 0x%" PRIx64, addr);
        else if (response.IsUnsupportedResponse())
            error.SetErrorStringWithFormat("GDB server does not support writing memory");
        else
            error.SetErrorStringWithFormat("unexpected response to GDB server memory write packet '%s': '%s'", packet.GetString().c_str(), response.GetStringRef().c_str());
    }
    else
    {
        error.SetErrorStringWithFormat("failed to send packet: '%s'", packet.GetString().c_str());
    }
    return 0;
}

lldb::addr_t
ProcessGDBRemote::DoAllocateMemory (size_t size, uint32_t permissions, Error &error)
{
    Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS|LIBLLDB_LOG_EXPRESSIONS));
    addr_t allocated_addr = LLDB_INVALID_ADDRESS;

    if (m_gdb_comm.SupportsAllocDeallocMemory() != eLazyBoolNo)
    {
        allocated_addr = m_gdb_comm.AllocateMemory (size, permissions);
        if (allocated_addr != LLDB_INVALID_ADDRESS || m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolYes)
            return allocated_addr;
    }

    if (m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolNo)
    {
        // Call mmap() to create memory in the inferior..
        unsigned prot = 0;
        if (permissions & lldb::ePermissionsReadable)
            prot |= eMmapProtRead;
        if (permissions & lldb::ePermissionsWritable)
            prot |= eMmapProtWrite;
        if (permissions & lldb::ePermissionsExecutable)
            prot |= eMmapProtExec;

        if (InferiorCallMmap(this, allocated_addr, 0, size, prot,
                             eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0))
            m_addr_to_mmap_size[allocated_addr] = size;
        else
        {
            allocated_addr = LLDB_INVALID_ADDRESS;
            if (log)
                log->Printf ("ProcessGDBRemote::%s no direct stub support for memory allocation, and InferiorCallMmap also failed - is stub missing register context save/restore capability?", __FUNCTION__);
        }
    }

    if (allocated_addr == LLDB_INVALID_ADDRESS)
        error.SetErrorStringWithFormat("unable to allocate %" PRIu64 " bytes of memory with permissions %s", (uint64_t)size, GetPermissionsAsCString (permissions));
    else
        error.Clear();
    return allocated_addr;
}

Error
ProcessGDBRemote::GetMemoryRegionInfo (addr_t load_addr,
                                       MemoryRegionInfo &region_info)
{

    Error error (m_gdb_comm.GetMemoryRegionInfo (load_addr, region_info));
    return error;
}

Error
ProcessGDBRemote::GetWatchpointSupportInfo (uint32_t &num)
{

    Error error (m_gdb_comm.GetWatchpointSupportInfo (num));
    return error;
}

Error
ProcessGDBRemote::GetWatchpointSupportInfo (uint32_t &num, bool& after)
{
    Error error (m_gdb_comm.GetWatchpointSupportInfo (num, after, GetTarget().GetArchitecture()));
    return error;
}

Error
ProcessGDBRemote::DoDeallocateMemory (lldb::addr_t addr)
{
    Error error;
    LazyBool supported = m_gdb_comm.SupportsAllocDeallocMemory();

    switch (supported)
    {
        case eLazyBoolCalculate:
            // We should never be deallocating memory without allocating memory
            // first so we should never get eLazyBoolCalculate
            error.SetErrorString ("tried to deallocate memory without ever allocating memory");
            break;

        case eLazyBoolYes:
            if (!m_gdb_comm.DeallocateMemory (addr))
                error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr);
            break;

        case eLazyBoolNo:
            // Call munmap() to deallocate memory in the inferior..
            {
                MMapMap::iterator pos = m_addr_to_mmap_size.find(addr);
                if (pos != m_addr_to_mmap_size.end() &&
                    InferiorCallMunmap(this, addr, pos->second))
                    m_addr_to_mmap_size.erase (pos);
                else
                    error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr);
            }
            break;
    }

    return error;
}


//------------------------------------------------------------------
// Process STDIO
//------------------------------------------------------------------
size_t
ProcessGDBRemote::PutSTDIN (const char *src, size_t src_len, Error &error)
{
    if (m_stdio_communication.IsConnected())
    {
        ConnectionStatus status;
        m_stdio_communication.Write(src, src_len, status, NULL);
    }
    else if (m_stdin_forward)
    {
        m_gdb_comm.SendStdinNotification(src, src_len);
    }
    return 0;
}

Error
ProcessGDBRemote::EnableBreakpointSite (BreakpointSite *bp_site)
{
    Error error;
    assert(bp_site != NULL);

    // Get logging info
    Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS));
    user_id_t site_id = bp_site->GetID();

    // Get the breakpoint address
    const addr_t addr = bp_site->GetLoadAddress();

    // Log that a breakpoint was requested
    if (log)
        log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 ") address = 0x%" PRIx64, site_id, (uint64_t)addr);

    // Breakpoint already exists and is enabled
    if (bp_site->IsEnabled())
    {
        if (log)
            log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 ") address = 0x%" PRIx64 " -- SUCCESS (already enabled)", site_id, (uint64_t)addr);
        return error;
    }

    // Get the software breakpoint trap opcode size
    const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site);

    // SupportsGDBStoppointPacket() simply checks a boolean, indicating if this breakpoint type
    // is supported by the remote stub. These are set to true by default, and later set to false
    // only after we receive an unimplemented response when sending a breakpoint packet. This means
    // initially that unless we were specifically instructed to use a hardware breakpoint, LLDB will
    // attempt to set a software breakpoint. HardwareRequired() also queries a boolean variable which
    // indicates if the user specifically asked for hardware breakpoints.  If true then we will
    // skip over software breakpoints.
    if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware) && (!bp_site->HardwareRequired()))
    {
        // Try to send off a software breakpoint packet ($Z0)
        uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, true, addr, bp_op_size);
        if (error_no == 0)
        {
            // The breakpoint was placed successfully
            bp_site->SetEnabled(true);
            bp_site->SetType(BreakpointSite::eExternal);
            return error;
        }

        // SendGDBStoppointTypePacket() will return an error if it was unable to set this
        // breakpoint. We need to differentiate between a error specific to placing this breakpoint
        // or if we have learned that this breakpoint type is unsupported. To do this, we
        // must test the support boolean for this breakpoint type to see if it now indicates that
        // this breakpoint type is unsupported.  If they are still supported then we should return
        // with the error code.  If they are now unsupported, then we would like to fall through
        // and try another form of breakpoint.
        if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware))
        {
            if (error_no != UINT8_MAX)
                error.SetErrorStringWithFormat("error: %d sending the breakpoint request", errno);
            else
                error.SetErrorString("error sending the breakpoint request");
            return error;
        }

        // We reach here when software breakpoints have been found to be unsupported. For future
        // calls to set a breakpoint, we will not attempt to set a breakpoint with a type that is
        // known not to be supported.
        if (log)
            log->Printf("Software breakpoints are unsupported");

        // So we will fall through and try a hardware breakpoint
    }

    // The process of setting a hardware breakpoint is much the same as above.  We check the
    // supported boolean for this breakpoint type, and if it is thought to be supported then we
    // will try to set this breakpoint with a hardware breakpoint.
    if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware))
    {
        // Try to send off a hardware breakpoint packet ($Z1)
        uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, true, addr, bp_op_size);
        if (error_no == 0)
        {
            // The breakpoint was placed successfully
            bp_site->SetEnabled(true);
            bp_site->SetType(BreakpointSite::eHardware);
            return error;
        }

        // Check if the error was something other then an unsupported breakpoint type
        if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware))
        {
            // Unable to set this hardware breakpoint
            if (error_no != UINT8_MAX)
                error.SetErrorStringWithFormat("error: %d sending the hardware breakpoint request "
                                               "(hardware breakpoint resources might be exhausted or unavailable)",
                                               error_no);
            else
                error.SetErrorString("error sending the hardware breakpoint request (hardware breakpoint resources "
                                     "might be exhausted or unavailable)");
            return error;
        }

        // We will reach here when the stub gives an unsupported response to a hardware breakpoint
        if (log)
            log->Printf("Hardware breakpoints are unsupported");

        // Finally we will falling through to a #trap style breakpoint
    }

    // Don't fall through when hardware breakpoints were specifically requested
    if (bp_site->HardwareRequired())
    {
        error.SetErrorString("hardware breakpoints are not supported");
        return error;
    }

    // As a last resort we want to place a manual breakpoint. An instruction
    // is placed into the process memory using memory write packets.
    return EnableSoftwareBreakpoint(bp_site);
}

Error
ProcessGDBRemote::DisableBreakpointSite (BreakpointSite *bp_site)
{
    Error error;
    assert (bp_site != NULL);
    addr_t addr = bp_site->GetLoadAddress();
    user_id_t site_id = bp_site->GetID();
    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS));
    if (log)
        log->Printf ("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 ") addr = 0x%8.8" PRIx64, site_id, (uint64_t)addr);

    if (bp_site->IsEnabled())
    {
        const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site);

        BreakpointSite::Type bp_type = bp_site->GetType();
        switch (bp_type)
        {
        case BreakpointSite::eSoftware:
            error = DisableSoftwareBreakpoint (bp_site);
            break;

        case BreakpointSite::eHardware:
            if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, false, addr, bp_op_size))
                error.SetErrorToGenericError();
            break;

        case BreakpointSite::eExternal:
            {
                GDBStoppointType stoppoint_type;
                if (bp_site->IsHardware())
                    stoppoint_type = eBreakpointHardware;
                else
                    stoppoint_type = eBreakpointSoftware;

                if (m_gdb_comm.SendGDBStoppointTypePacket(stoppoint_type, false, addr, bp_op_size))
                error.SetErrorToGenericError();
            }
            break;
        }
        if (error.Success())
            bp_site->SetEnabled(false);
    }
    else
    {
        if (log)
            log->Printf ("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", site_id, (uint64_t)addr);
        return error;
    }

    if (error.Success())
        error.SetErrorToGenericError();
    return error;
}

// Pre-requisite: wp != NULL.
static GDBStoppointType
GetGDBStoppointType (Watchpoint *wp)
{
    assert(wp);
    bool watch_read = wp->WatchpointRead();
    bool watch_write = wp->WatchpointWrite();

    // watch_read and watch_write cannot both be false.
    assert(watch_read || watch_write);
    if (watch_read && watch_write)
        return eWatchpointReadWrite;
    else if (watch_read)
        return eWatchpointRead;
    else // Must be watch_write, then.
        return eWatchpointWrite;
}

Error
ProcessGDBRemote::EnableWatchpoint (Watchpoint *wp, bool notify)
{
    Error error;
    if (wp)
    {
        user_id_t watchID = wp->GetID();
        addr_t addr = wp->GetLoadAddress();
        Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS));
        if (log)
            log->Printf ("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ")", watchID);
        if (wp->IsEnabled())
        {
            if (log)
                log->Printf("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", watchID, (uint64_t)addr);
            return error;
        }

        GDBStoppointType type = GetGDBStoppointType(wp);
        // Pass down an appropriate z/Z packet...
        if (m_gdb_comm.SupportsGDBStoppointPacket (type))
        {
            if (m_gdb_comm.SendGDBStoppointTypePacket(type, true, addr, wp->GetByteSize()) == 0)
            {
                wp->SetEnabled(true, notify);
                return error;
            }
            else
                error.SetErrorString("sending gdb watchpoint packet failed");
        }
        else
            error.SetErrorString("watchpoints not supported");
    }
    else
    {
        error.SetErrorString("Watchpoint argument was NULL.");
    }
    if (error.Success())
        error.SetErrorToGenericError();
    return error;
}

Error
ProcessGDBRemote::DisableWatchpoint (Watchpoint *wp, bool notify)
{
    Error error;
    if (wp)
    {
        user_id_t watchID = wp->GetID();

        Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS));

        addr_t addr = wp->GetLoadAddress();

        if (log)
            log->Printf ("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 ") addr = 0x%8.8" PRIx64, watchID, (uint64_t)addr);

        if (!wp->IsEnabled())
        {
            if (log)
                log->Printf ("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", watchID, (uint64_t)addr);
            // See also 'class WatchpointSentry' within StopInfo.cpp.
            // This disabling attempt might come from the user-supplied actions, we'll route it in order for
            // the watchpoint object to intelligently process this action.
            wp->SetEnabled(false, notify);
            return error;
        }

        if (wp->IsHardware())
        {
            GDBStoppointType type = GetGDBStoppointType(wp);
            // Pass down an appropriate z/Z packet...
            if (m_gdb_comm.SendGDBStoppointTypePacket(type, false, addr, wp->GetByteSize()) == 0)
            {
                wp->SetEnabled(false, notify);
                return error;
            }
            else
                error.SetErrorString("sending gdb watchpoint packet failed");
        }
        // TODO: clear software watchpoints if we implement them
    }
    else
    {
        error.SetErrorString("Watchpoint argument was NULL.");
    }
    if (error.Success())
        error.SetErrorToGenericError();
    return error;
}

void
ProcessGDBRemote::Clear()
{
    m_flags = 0;
    m_thread_list_real.Clear();
    m_thread_list.Clear();
}

Error
ProcessGDBRemote::DoSignal (int signo)
{
    Error error;
    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
    if (log)
        log->Printf ("ProcessGDBRemote::DoSignal (signal = %d)", signo);

    if (!m_gdb_comm.SendAsyncSignal (signo))
        error.SetErrorStringWithFormat("failed to send signal %i", signo);
    return error;
}

Error
ProcessGDBRemote::EstablishConnectionIfNeeded (const ProcessInfo &process_info)
{
    // Make sure we aren't already connected?
    if (m_gdb_comm.IsConnected())
        return Error();

    PlatformSP platform_sp (GetTarget ().GetPlatform ());
    if (platform_sp && !platform_sp->IsHost ())
        return Error("Lost debug server connection");

    auto error = LaunchAndConnectToDebugserver (process_info);
    if (error.Fail())
    {
        const char *error_string = error.AsCString();
        if (error_string == nullptr)
            error_string = "unable to launch " DEBUGSERVER_BASENAME;
    }
    return error;
}

Error
ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info)
{
    using namespace std::placeholders; // For _1, _2, etc.

    Error error;
    if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID)
    {
        // If we locate debugserver, keep that located version around
        static FileSpec g_debugserver_file_spec;

        ProcessLaunchInfo debugserver_launch_info;
        // Make debugserver run in its own session so signals generated by
        // special terminal key sequences (^C) don't affect debugserver.
        debugserver_launch_info.SetLaunchInSeparateProcessGroup(true);

        const std::weak_ptr<ProcessGDBRemote> this_wp = std::static_pointer_cast<ProcessGDBRemote>(shared_from_this());
        debugserver_launch_info.SetMonitorProcessCallback(std::bind(MonitorDebugserverProcess, this_wp, _1, _2, _3, _4),
                                                          false);
        debugserver_launch_info.SetUserID(process_info.GetUserID());

#if defined (__APPLE__) && (defined (__arm__) || defined (__arm64__) || defined (__aarch64__))
        // On iOS, still do a local connection using a random port
        const char *hostname = "127.0.0.1";
        uint16_t port = get_random_port ();
#else
        // Set hostname being NULL to do the reverse connect where debugserver
        // will bind to port zero and it will communicate back to us the port
        // that we will connect to
        const char *hostname = nullptr;
        uint16_t port = 0;
#endif

        StreamString url_str;
        const char* url = nullptr;
        if (hostname != nullptr)
        {
            url_str.Printf("%s:%u", hostname, port);
            url = url_str.GetData();
        }

        error = m_gdb_comm.StartDebugserverProcess (url,
                                                    GetTarget().GetPlatform().get(),
                                                    debugserver_launch_info,
                                                    &port);

        if (error.Success ())
            m_debugserver_pid = debugserver_launch_info.GetProcessID();
        else
            m_debugserver_pid = LLDB_INVALID_PROCESS_ID;

        if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
            StartAsyncThread ();

        if (error.Fail())
        {
            Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));

            if (log)
                log->Printf("failed to start debugserver process: %s", error.AsCString());
            return error;
        }

        if (m_gdb_comm.IsConnected())
        {
            // Finish the connection process by doing the handshake without connecting (send NULL URL)
            ConnectToDebugserver (NULL);
        }
        else
        {
            StreamString connect_url;
            connect_url.Printf("connect://%s:%u", hostname, port);
            error = ConnectToDebugserver (connect_url.GetString().c_str());
        }

    }
    return error;
}

bool
ProcessGDBRemote::MonitorDebugserverProcess(std::weak_ptr<ProcessGDBRemote> process_wp, lldb::pid_t debugserver_pid,
                                            bool exited,    // True if the process did exit
                                            int signo,      // Zero for no signal
                                            int exit_status // Exit value of process if signal is zero
                                            )
{
    // "debugserver_pid" argument passed in is the process ID for
    // debugserver that we are tracking...
    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
    const bool handled = true;

    if (log)
        log->Printf("ProcessGDBRemote::%s(process_wp, pid=%" PRIu64 ", signo=%i (0x%x), exit_status=%i)", __FUNCTION__,
                    debugserver_pid, signo, signo, exit_status);

    std::shared_ptr<ProcessGDBRemote> process_sp = process_wp.lock();
    if (log)
        log->Printf("ProcessGDBRemote::%s(process = %p)", __FUNCTION__, static_cast<void *>(process_sp.get()));
    if (!process_sp || process_sp->m_debugserver_pid != debugserver_pid)
        return handled;

    // Sleep for a half a second to make sure our inferior process has
    // time to set its exit status before we set it incorrectly when
    // both the debugserver and the inferior process shut down.
    usleep(500000);
    // If our process hasn't yet exited, debugserver might have died.
    // If the process did exit, then we are reaping it.
    const StateType state = process_sp->GetState();

    if (state != eStateInvalid && state != eStateUnloaded && state != eStateExited && state != eStateDetached)
    {
        char error_str[1024];
        if (signo)
        {
            const char *signal_cstr = process_sp->GetUnixSignals()->GetSignalAsCString(signo);
            if (signal_cstr)
                ::snprintf(error_str, sizeof(error_str), DEBUGSERVER_BASENAME " died with signal %s", signal_cstr);
            else
                ::snprintf(error_str, sizeof(error_str), DEBUGSERVER_BASENAME " died with signal %i", signo);
        }
        else
        {
            ::snprintf(error_str, sizeof(error_str), DEBUGSERVER_BASENAME " died with an exit status of 0x%8.8x",
                       exit_status);
        }

        process_sp->SetExitStatus(-1, error_str);
    }
    // Debugserver has exited we need to let our ProcessGDBRemote
    // know that it no longer has a debugserver instance
    process_sp->m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
    return handled;
}

void
ProcessGDBRemote::KillDebugserverProcess ()
{
    m_gdb_comm.Disconnect();
    if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
    {
        Host::Kill (m_debugserver_pid, SIGINT);
        m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
    }
}

void
ProcessGDBRemote::Initialize()
{
    static std::once_flag g_once_flag;

    std::call_once(g_once_flag, []()
    {
        PluginManager::RegisterPlugin (GetPluginNameStatic(),
                                       GetPluginDescriptionStatic(),
                                       CreateInstance,
                                       DebuggerInitialize);
    });
}

void
ProcessGDBRemote::DebuggerInitialize (Debugger &debugger)
{
    if (!PluginManager::GetSettingForProcessPlugin(debugger, PluginProperties::GetSettingName()))
    {
        const bool is_global_setting = true;
        PluginManager::CreateSettingForProcessPlugin (debugger,
                                                      GetGlobalPluginProperties()->GetValueProperties(),
                                                      ConstString ("Properties for the gdb-remote process plug-in."),
                                                      is_global_setting);
    }
}

bool
ProcessGDBRemote::StartAsyncThread ()
{
    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));

    if (log)
        log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__);

    std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex);
    if (!m_async_thread.IsJoinable())
    {
        // Create a thread that watches our internal state and controls which
        // events make it to clients (into the DCProcess event queue).

        m_async_thread = ThreadLauncher::LaunchThread("<lldb.process.gdb-remote.async>", ProcessGDBRemote::AsyncThread, this, NULL);
    }
    else if (log)
        log->Printf("ProcessGDBRemote::%s () - Called when Async thread was already running.", __FUNCTION__);

    return m_async_thread.IsJoinable();
}

void
ProcessGDBRemote::StopAsyncThread ()
{
    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));

    if (log)
        log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__);

    std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex);
    if (m_async_thread.IsJoinable())
    {
        m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit);

        //  This will shut down the async thread.
        m_gdb_comm.Disconnect();    // Disconnect from the debug server.

        // Stop the stdio thread
        m_async_thread.Join(nullptr);
        m_async_thread.Reset();
    }
    else if (log)
        log->Printf("ProcessGDBRemote::%s () - Called when Async thread was not running.", __FUNCTION__);
}

bool
ProcessGDBRemote::HandleNotifyPacket (StringExtractorGDBRemote &packet)
{
    // get the packet at a string
    const std::string &pkt = packet.GetStringRef();
    // skip %stop:
    StringExtractorGDBRemote stop_info(pkt.c_str() + 5);

    // pass as a thread stop info packet
    SetLastStopPacket(stop_info);

    // check for more stop reasons
    HandleStopReplySequence();

    // if the process is stopped then we need to fake a resume
    // so that we can stop properly with the new break. This
    // is possible due to SetPrivateState() broadcasting the
    // state change as a side effect.
    if (GetPrivateState() == lldb::StateType::eStateStopped)
    {
        SetPrivateState(lldb::StateType::eStateRunning);
    }

    // since we have some stopped packets we can halt the process
    SetPrivateState(lldb::StateType::eStateStopped);

    return true;
}

thread_result_t
ProcessGDBRemote::AsyncThread (void *arg)
{
    ProcessGDBRemote *process = (ProcessGDBRemote*) arg;

    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
    if (log)
        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") thread starting...", __FUNCTION__, arg, process->GetID());

    EventSP event_sp;
    bool done = false;
    while (!done)
    {
        if (log)
            log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID());
        if (process->m_async_listener_sp->WaitForEvent (NULL, event_sp))
        {
            const uint32_t event_type = event_sp->GetType();
            if (event_sp->BroadcasterIs (&process->m_async_broadcaster))
            {
                if (log)
                    log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") Got an event of type: %d...", __FUNCTION__, arg, process->GetID(), event_type);

                switch (event_type)
                {
                    case eBroadcastBitAsyncContinue:
                        {
                            const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event_sp.get());

                            if (continue_packet)
                            {
                                const char *continue_cstr = (const char *)continue_packet->GetBytes ();
                                const size_t continue_cstr_len = continue_packet->GetByteSize ();
                                if (log)
                                    log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr);

                                if (::strstr (continue_cstr, "vAttach") == NULL)
                                    process->SetPrivateState(eStateRunning);
                                StringExtractorGDBRemote response;

                                // If in Non-Stop-Mode
                                if (process->GetTarget().GetNonStopModeEnabled())
                                {
                                    // send the vCont packet
                                    if (!process->GetGDBRemote().SendvContPacket(process, continue_cstr, continue_cstr_len, response))
                                    {
                                        // Something went wrong
                                        done = true;
                                        break;
                                    }
                                }
                                // If in All-Stop-Mode
                                else
                                {
                                    StateType stop_state = process->GetGDBRemote().SendContinuePacketAndWaitForResponse (process, continue_cstr, continue_cstr_len, response);

                                    // We need to immediately clear the thread ID list so we are sure to get a valid list of threads.
                                    // The thread ID list might be contained within the "response", or the stop reply packet that
                                    // caused the stop. So clear it now before we give the stop reply packet to the process
                                    // using the process->SetLastStopPacket()...
                                    process->ClearThreadIDList ();

                                    switch (stop_state)
                                    {
                                    case eStateStopped:
                                    case eStateCrashed:
                                    case eStateSuspended:
                                        process->SetLastStopPacket (response);
                                        process->SetPrivateState (stop_state);
                                        break;

                                    case eStateExited:
                                    {
                                        process->SetLastStopPacket (response);
                                        process->ClearThreadIDList();
                                        response.SetFilePos(1);

                                        int exit_status = response.GetHexU8();
                                        const char *desc_cstr = NULL;
                                        StringExtractor extractor;
                                        std::string desc_string;
                                        if (response.GetBytesLeft() > 0 && response.GetChar('-') == ';')
                                        {
                                            std::string desc_token;
                                            while (response.GetNameColonValue (desc_token, desc_string))
                                            {
                                                if (desc_token == "description")
                                                {
                                                    extractor.GetStringRef().swap(desc_string);
                                                    extractor.SetFilePos(0);
                                                    extractor.GetHexByteString (desc_string);
                                                    desc_cstr = desc_string.c_str();
                                                }
                                            }
                                        }
                                        process->SetExitStatus(exit_status, desc_cstr);
                                        done = true;
                                        break;
                                    }
                                    case eStateInvalid:
                                    {
                                        // Check to see if we were trying to attach and if we got back
                                        // the "E87" error code from debugserver -- this indicates that
                                        // the process is not debuggable.  Return a slightly more helpful
                                        // error message about why the attach failed.
                                        if (::strstr (continue_cstr, "vAttach") != NULL
                                            && response.GetError() == 0x87)
                                        {
                                            process->SetExitStatus(-1, "cannot attach to process due to System Integrity Protection");
                                        }
                                        // E01 code from vAttach means that the attach failed
                                        if (::strstr (continue_cstr, "vAttach") != NULL
                                            && response.GetError() == 0x1)
                                        {
                                            process->SetExitStatus(-1, "unable to attach");
                                        }
                                        else
                                        {
                                            process->SetExitStatus(-1, "lost connection");
                                        }
                                            break;
                                    }

                                    default:
                                        process->SetPrivateState (stop_state);
                                        break;
                                    } // switch(stop_state)
                                } // else // if in All-stop-mode
                            } // if (continue_packet)
                        } // case eBroadcastBitAysncContinue
                        break;

                    case eBroadcastBitAsyncThreadShouldExit:
                        if (log)
                            log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncThreadShouldExit...", __FUNCTION__, arg, process->GetID());
                        done = true;
                        break;

                    default:
                        if (log)
                            log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type);
                        done = true;
                        break;
                }
            }
            else if (event_sp->BroadcasterIs (&process->m_gdb_comm))
            {
                switch (event_type)
                {
                    case Communication::eBroadcastBitReadThreadDidExit:
                        process->SetExitStatus (-1, "lost connection");
                        done = true;
                        break;

                    case GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify:
                    {
                        lldb_private::Event *event = event_sp.get();
                        const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event);
                        StringExtractorGDBRemote notify((const char*)continue_packet->GetBytes());
                        // Hand this over to the process to handle
                        process->HandleNotifyPacket(notify);
                        break;
                    }

                    default:
                        if (log)
                            log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type);
                        done = true;
                        break;
                }
            }
        }
        else
        {
            if (log)
                log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp) => false", __FUNCTION__, arg, process->GetID());
            done = true;
        }
    }

    if (log)
        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") thread exiting...", __FUNCTION__, arg, process->GetID());

    return NULL;
}

//uint32_t
//ProcessGDBRemote::ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids)
//{
//    // If we are planning to launch the debugserver remotely, then we need to fire up a debugserver
//    // process and ask it for the list of processes. But if we are local, we can let the Host do it.
//    if (m_local_debugserver)
//    {
//        return Host::ListProcessesMatchingName (name, matches, pids);
//    }
//    else
//    {
//        // FIXME: Implement talking to the remote debugserver.
//        return 0;
//    }
//
//}
//
bool
ProcessGDBRemote::NewThreadNotifyBreakpointHit (void *baton,
                             StoppointCallbackContext *context,
                             lldb::user_id_t break_id,
                             lldb::user_id_t break_loc_id)
{
    // I don't think I have to do anything here, just make sure I notice the new thread when it starts to
    // run so I can stop it if that's what I want to do.
    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
    if (log)
        log->Printf("Hit New Thread Notification breakpoint.");
    return false;
}


bool
ProcessGDBRemote::StartNoticingNewThreads()
{
    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
    if (m_thread_create_bp_sp)
    {
        if (log && log->GetVerbose())
            log->Printf("Enabled noticing new thread breakpoint.");
        m_thread_create_bp_sp->SetEnabled(true);
    }
    else
    {
        PlatformSP platform_sp (GetTarget().GetPlatform());
        if (platform_sp)
        {
            m_thread_create_bp_sp = platform_sp->SetThreadCreationBreakpoint(GetTarget());
            if (m_thread_create_bp_sp)
            {
                if (log && log->GetVerbose())
                    log->Printf("Successfully created new thread notification breakpoint %i", m_thread_create_bp_sp->GetID());
                m_thread_create_bp_sp->SetCallback (ProcessGDBRemote::NewThreadNotifyBreakpointHit, this, true);
            }
            else
            {
                if (log)
                    log->Printf("Failed to create new thread notification breakpoint.");
            }
        }
    }
    return m_thread_create_bp_sp.get() != NULL;
}

bool
ProcessGDBRemote::StopNoticingNewThreads()
{
    Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
    if (log && log->GetVerbose())
        log->Printf ("Disabling new thread notification breakpoint.");

    if (m_thread_create_bp_sp)
        m_thread_create_bp_sp->SetEnabled(false);

    return true;
}

DynamicLoader *
ProcessGDBRemote::GetDynamicLoader ()
{
    if (m_dyld_ap.get() == NULL)
        m_dyld_ap.reset (DynamicLoader::FindPlugin(this, NULL));
    return m_dyld_ap.get();
}

Error
ProcessGDBRemote::SendEventData(const char *data)
{
    int return_value;
    bool was_supported;

    Error error;

    return_value = m_gdb_comm.SendLaunchEventDataPacket (data, &was_supported);
    if (return_value != 0)
    {
        if (!was_supported)
            error.SetErrorString("Sending events is not supported for this process.");
        else
            error.SetErrorStringWithFormat("Error sending event data: %d.", return_value);
    }
    return error;
}

const DataBufferSP
ProcessGDBRemote::GetAuxvData()
{
    DataBufferSP buf;
    if (m_gdb_comm.GetQXferAuxvReadSupported())
    {
        std::string response_string;
        if (m_gdb_comm.SendPacketsAndConcatenateResponses("qXfer:auxv:read::", response_string) == GDBRemoteCommunication::PacketResult::Success)
            buf.reset(new DataBufferHeap(response_string.c_str(), response_string.length()));
    }
    return buf;
}

StructuredData::ObjectSP
ProcessGDBRemote::GetExtendedInfoForThread (lldb::tid_t tid)
{
    StructuredData::ObjectSP object_sp;

    if (m_gdb_comm.GetThreadExtendedInfoSupported())
    {
        StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
        SystemRuntime *runtime = GetSystemRuntime();
        if (runtime)
        {
            runtime->AddThreadExtendedInfoPacketHints (args_dict);
        }
        args_dict->GetAsDictionary()->AddIntegerItem ("thread", tid);

        StreamString packet;
        packet << "jThreadExtendedInfo:";
        args_dict->Dump (packet);

        // FIXME the final character of a JSON dictionary, '}', is the escape
        // character in gdb-remote binary mode.  lldb currently doesn't escape
        // these characters in its packet output -- so we add the quoted version
        // of the } character here manually in case we talk to a debugserver which
        // un-escapes the characters at packet read time.
        packet << (char) (0x7d ^ 0x20);

        StringExtractorGDBRemote response;
        response.SetResponseValidatorToJSON();
        if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, false) == GDBRemoteCommunication::PacketResult::Success)
        {
            StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType();
            if (response_type == StringExtractorGDBRemote::eResponse)
            {
                if (!response.Empty())
                {
                    object_sp = StructuredData::ParseJSON (response.GetStringRef());
                }
            }
        }
    }
    return object_sp;
}

StructuredData::ObjectSP
ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_address, lldb::addr_t image_count)
{
    StructuredData::ObjectSP object_sp;

    if (m_gdb_comm.GetLoadedDynamicLibrariesInfosSupported())
    {
        // Scope for the scoped timeout object
        GDBRemoteCommunication::ScopedTimeout timeout (m_gdb_comm, 10);

        StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
        args_dict->GetAsDictionary()->AddIntegerItem ("image_list_address", image_list_address);
        args_dict->GetAsDictionary()->AddIntegerItem ("image_count", image_count);

        StreamString packet;
        packet << "jGetLoadedDynamicLibrariesInfos:";
        args_dict->Dump (packet);

        // FIXME the final character of a JSON dictionary, '}', is the escape
        // character in gdb-remote binary mode.  lldb currently doesn't escape
        // these characters in its packet output -- so we add the quoted version
        // of the } character here manually in case we talk to a debugserver which
        // un-escapes the characters at packet read time.
        packet << (char) (0x7d ^ 0x20);

        StringExtractorGDBRemote response;
        response.SetResponseValidatorToJSON();
        if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, false) == GDBRemoteCommunication::PacketResult::Success)
        {
            StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType();
            if (response_type == StringExtractorGDBRemote::eResponse)
            {
                if (!response.Empty())
                {
                    object_sp = StructuredData::ParseJSON (response.GetStringRef());
                }
            }
        }
    }
    return object_sp;
}

// Establish the largest memory read/write payloads we should use.
// If the remote stub has a max packet size, stay under that size.
//
// If the remote stub's max packet size is crazy large, use a
// reasonable largeish default.
//
// If the remote stub doesn't advertise a max packet size, use a
// conservative default.

void
ProcessGDBRemote::GetMaxMemorySize()
{
    const uint64_t reasonable_largeish_default = 128 * 1024;
    const uint64_t conservative_default = 512;

    if (m_max_memory_size == 0)
    {
        uint64_t stub_max_size = m_gdb_comm.GetRemoteMaxPacketSize();
        if (stub_max_size != UINT64_MAX && stub_max_size != 0)
        {
            // Save the stub's claimed maximum packet size
            m_remote_stub_max_memory_size = stub_max_size;

            // Even if the stub says it can support ginormous packets,
            // don't exceed our reasonable largeish default packet size.
            if (stub_max_size > reasonable_largeish_default)
            {
                stub_max_size = reasonable_largeish_default;
            }

            m_max_memory_size = stub_max_size;
        }
        else
        {
            m_max_memory_size = conservative_default;
        }
    }
}

void
ProcessGDBRemote::SetUserSpecifiedMaxMemoryTransferSize (uint64_t user_specified_max)
{
    if (user_specified_max != 0)
    {
        GetMaxMemorySize ();

        if (m_remote_stub_max_memory_size != 0)
        {
            if (m_remote_stub_max_memory_size < user_specified_max)
            {
                m_max_memory_size = m_remote_stub_max_memory_size;   // user specified a packet size too big, go as big
                                                                     // as the remote stub says we can go.
            }
            else
            {
                m_max_memory_size = user_specified_max;             // user's packet size is good
            }
        }
        else
        {
            m_max_memory_size = user_specified_max;                 // user's packet size is probably fine
        }
    }
}

bool
ProcessGDBRemote::GetModuleSpec(const FileSpec& module_file_spec,
                                const ArchSpec& arch,
                                ModuleSpec &module_spec)
{
    Log *log = GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PLATFORM);

    if (!m_gdb_comm.GetModuleInfo (module_file_spec, arch, module_spec))
    {
        if (log)
            log->Printf ("ProcessGDBRemote::%s - failed to get module info for %s:%s",
                         __FUNCTION__, module_file_spec.GetPath ().c_str (),
                         arch.GetTriple ().getTriple ().c_str ());
        return false;
    }

    if (log)
    {
        StreamString stream;
        module_spec.Dump (stream);
        log->Printf ("ProcessGDBRemote::%s - got module info for (%s:%s) : %s",
                     __FUNCTION__, module_file_spec.GetPath ().c_str (),
                     arch.GetTriple ().getTriple ().c_str (), stream.GetString ().c_str ());
    }

    return true;
}

bool
ProcessGDBRemote::GetHostOSVersion(uint32_t &major,
                                   uint32_t &minor,
                                   uint32_t &update)
{
    if (m_gdb_comm.GetOSVersion(major, minor, update))
        return true;
    // We failed to get the host OS version, defer to the base
    // implementation to correctly invalidate the arguments.
    return Process::GetHostOSVersion(major, minor, update);
}

namespace {

typedef std::vector<std::string> stringVec;

typedef std::vector<struct GdbServerRegisterInfo> GDBServerRegisterVec;
struct RegisterSetInfo
{
    ConstString name;
};

typedef std::map<uint32_t, RegisterSetInfo> RegisterSetMap;

struct GdbServerTargetInfo
{
    std::string arch;
    std::string osabi;
    stringVec includes;
    RegisterSetMap reg_set_map;
    XMLNode feature_node;
};

bool
ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info, ABISP abi_sp, uint32_t &cur_reg_num, uint32_t &reg_offset)
{
    if (!feature_node)
        return false;

    feature_node.ForEachChildElementWithName("reg", [&target_info, &dyn_reg_info, &cur_reg_num, &reg_offset, &abi_sp](const XMLNode &reg_node) -> bool {
        std::string gdb_group;
        std::string gdb_type;
        ConstString reg_name;
        ConstString alt_name;
        ConstString set_name;
        std::vector<uint32_t> value_regs;
        std::vector<uint32_t> invalidate_regs;
        std::vector<uint8_t> dwarf_opcode_bytes;
        bool encoding_set = false;
        bool format_set = false;
        RegisterInfo reg_info = { NULL,                 // Name
            NULL,                 // Alt name
            0,                    // byte size
            reg_offset,           // offset
            eEncodingUint,        // encoding
            eFormatHex,           // format
            {
                LLDB_INVALID_REGNUM, // eh_frame reg num
                LLDB_INVALID_REGNUM, // DWARF reg num
                LLDB_INVALID_REGNUM, // generic reg num
                cur_reg_num,        // process plugin reg num
                cur_reg_num         // native register number
            },
            NULL,
            NULL,
            NULL,  // Dwarf Expression opcode bytes pointer
            0      // Dwarf Expression opcode bytes length 
        };

        reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, &reg_name, &alt_name, &set_name, &value_regs, &invalidate_regs, &encoding_set, &format_set, &reg_info, &cur_reg_num, &reg_offset, &dwarf_opcode_bytes](const llvm::StringRef &name, const llvm::StringRef &value) -> bool {
            if (name == "name")
            {
                reg_name.SetString(value);
            }
            else if (name == "bitsize")
            {
                reg_info.byte_size = StringConvert::ToUInt32(value.data(), 0, 0) / CHAR_BIT;
            }
            else if (name == "type")
            {
                gdb_type = value.str();
            }
            else if (name == "group")
            {
                gdb_group = value.str();
            }
            else if (name == "regnum")
            {
                const uint32_t regnum = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
                if (regnum != LLDB_INVALID_REGNUM)
                {
                    reg_info.kinds[eRegisterKindProcessPlugin] = regnum;
                }
            }
            else if (name == "offset")
            {
                reg_offset = StringConvert::ToUInt32(value.data(), UINT32_MAX, 0);
            }
            else if (name == "altname")
            {
                alt_name.SetString(value);
            }
            else if (name == "encoding")
            {
                encoding_set = true;
                reg_info.encoding = Args::StringToEncoding (value.data(), eEncodingUint);
            }
            else if (name == "format")
            {
                format_set = true;
                Format format = eFormatInvalid;
                if (Args::StringToFormat (value.data(), format, NULL).Success())
                    reg_info.format = format;
                else if (value == "vector-sint8")
                    reg_info.format = eFormatVectorOfSInt8;
                else if (value == "vector-uint8")
                    reg_info.format = eFormatVectorOfUInt8;
                else if (value == "vector-sint16")
                    reg_info.format = eFormatVectorOfSInt16;
                else if (value == "vector-uint16")
                    reg_info.format = eFormatVectorOfUInt16;
                else if (value == "vector-sint32")
                    reg_info.format = eFormatVectorOfSInt32;
                else if (value == "vector-uint32")
                    reg_info.format = eFormatVectorOfUInt32;
                else if (value == "vector-float32")
                    reg_info.format = eFormatVectorOfFloat32;
                else if (value == "vector-uint128")
                    reg_info.format = eFormatVectorOfUInt128;
            }
            else if (name == "group_id")
            {
                const uint32_t set_id = StringConvert::ToUInt32(value.data(), UINT32_MAX, 0);
                RegisterSetMap::const_iterator pos = target_info.reg_set_map.find(set_id);
                if (pos != target_info.reg_set_map.end())
                    set_name = pos->second.name;
            }
            else if (name == "gcc_regnum" || name == "ehframe_regnum")
            {
                reg_info.kinds[eRegisterKindEHFrame] = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
            }
            else if (name == "dwarf_regnum")
            {
                reg_info.kinds[eRegisterKindDWARF] = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
            }
            else if (name == "generic")
            {
                reg_info.kinds[eRegisterKindGeneric] = Args::StringToGenericRegister(value.data());
            }
            else if (name == "value_regnums")
            {
                SplitCommaSeparatedRegisterNumberString(value, value_regs, 0);
            }
            else if (name == "invalidate_regnums")
            {
                SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 0);
            }
            else if (name == "dynamic_size_dwarf_expr_bytes")
            {
                StringExtractor opcode_extractor;
                std::string opcode_string = value.str ();
                size_t dwarf_opcode_len = opcode_string.length () / 2;
                assert (dwarf_opcode_len > 0);

                dwarf_opcode_bytes.resize (dwarf_opcode_len);
                reg_info.dynamic_size_dwarf_len = dwarf_opcode_len;
                opcode_extractor.GetStringRef ().swap (opcode_string);
                uint32_t ret_val = opcode_extractor.GetHexBytesAvail (dwarf_opcode_bytes.data (),
                                                                    dwarf_opcode_len);
                assert (dwarf_opcode_len == ret_val);

                reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data ();
            }
            else
            {
                printf("unhandled attribute %s = %s\n", name.data(), value.data());
            }
            return true; // Keep iterating through all attributes
        });

        if (!gdb_type.empty() && !(encoding_set || format_set))
        {
            if (gdb_type.find("int") == 0)
            {
                reg_info.format = eFormatHex;
                reg_info.encoding = eEncodingUint;
            }
            else if (gdb_type == "data_ptr" || gdb_type == "code_ptr")
            {
                reg_info.format = eFormatAddressInfo;
                reg_info.encoding = eEncodingUint;
            }
            else if (gdb_type == "i387_ext" || gdb_type == "float")
            {
                reg_info.format = eFormatFloat;
                reg_info.encoding = eEncodingIEEE754;
            }
        }

        // Only update the register set name if we didn't get a "reg_set" attribute.
        // "set_name" will be empty if we didn't have a "reg_set" attribute.
        if (!set_name && !gdb_group.empty())
            set_name.SetCString(gdb_group.c_str());

        reg_info.byte_offset = reg_offset;
        assert (reg_info.byte_size != 0);
        reg_offset += reg_info.byte_size;
        if (!value_regs.empty())
        {
            value_regs.push_back(LLDB_INVALID_REGNUM);
            reg_info.value_regs = value_regs.data();
        }
        if (!invalidate_regs.empty())
        {
            invalidate_regs.push_back(LLDB_INVALID_REGNUM);
            reg_info.invalidate_regs = invalidate_regs.data();
        }

        ++cur_reg_num;
        AugmentRegisterInfoViaABI (reg_info, reg_name, abi_sp);
        dyn_reg_info.AddRegister(reg_info, reg_name, alt_name, set_name);

        return true; // Keep iterating through all "reg" elements
    });
    return true;
}

} // namespace {}


// query the target of gdb-remote for extended target information
// return:  'true'  on success
//          'false' on failure
bool
ProcessGDBRemote::GetGDBServerRegisterInfo (ArchSpec &arch_to_use)
{
    // Make sure LLDB has an XML parser it can use first
    if (!XMLDocument::XMLEnabled())
        return false;

    // redirect libxml2's error handler since the default prints to stdout

    GDBRemoteCommunicationClient & comm = m_gdb_comm;

    // check that we have extended feature read support
    if ( !comm.GetQXferFeaturesReadSupported( ) )
        return false;

    // request the target xml file
    std::string raw;
    lldb_private::Error lldberr;
    if (!comm.ReadExtFeature(ConstString("features"),
                             ConstString("target.xml"),
                             raw,
                             lldberr))
    {
        return false;
    }


    XMLDocument xml_document;

    if (xml_document.ParseMemory(raw.c_str(), raw.size(), "target.xml"))
    {
        GdbServerTargetInfo target_info;

        XMLNode target_node = xml_document.GetRootElement("target");
        if (target_node)
        {
            XMLNode feature_node;
            target_node.ForEachChildElement([&target_info, this, &feature_node](const XMLNode &node) -> bool
            {
                llvm::StringRef name = node.GetName();
                if (name == "architecture")
                {
                    node.GetElementText(target_info.arch);
                }
                else if (name == "osabi")
                {
                    node.GetElementText(target_info.osabi);
                }
                else if (name == "xi:include" || name == "include")
                {
                    llvm::StringRef href = node.GetAttributeValue("href");
                    if (!href.empty())
                        target_info.includes.push_back(href.str());
                }
                else if (name == "feature")
                {
                    feature_node = node;
                }
                else if (name == "groups")
                {
                    node.ForEachChildElementWithName("group", [&target_info](const XMLNode &node) -> bool {
                        uint32_t set_id = UINT32_MAX;
                        RegisterSetInfo set_info;

                        node.ForEachAttribute([&set_id, &set_info](const llvm::StringRef &name, const llvm::StringRef &value) -> bool {
                            if (name == "id")
                                set_id = StringConvert::ToUInt32(value.data(), UINT32_MAX, 0);
                            if (name == "name")
                                set_info.name = ConstString(value);
                            return true; // Keep iterating through all attributes
                        });

                        if (set_id != UINT32_MAX)
                            target_info.reg_set_map[set_id] = set_info;
                        return true; // Keep iterating through all "group" elements
                    });
                }
                return true; // Keep iterating through all children of the target_node
            });

            // Initialize these outside of ParseRegisters, since they should not be reset inside each include feature
            uint32_t cur_reg_num = 0;
            uint32_t reg_offset = 0;

            // Don't use Process::GetABI, this code gets called from DidAttach, and in that context we haven't
            // set the Target's architecture yet, so the ABI is also potentially incorrect.
            ABISP abi_to_use_sp = ABI::FindPlugin(arch_to_use);
            if (feature_node)
            {
                ParseRegisters(feature_node, target_info, this->m_register_info, abi_to_use_sp, cur_reg_num, reg_offset);
            }

            for (const auto &include : target_info.includes)
            {
                // request register file
                std::string xml_data;
                if (!comm.ReadExtFeature(ConstString("features"),
                                         ConstString(include),
                                         xml_data,
                                         lldberr))
                    continue;

                XMLDocument include_xml_document;
                include_xml_document.ParseMemory(xml_data.data(), xml_data.size(), include.c_str());
                XMLNode include_feature_node = include_xml_document.GetRootElement("feature");
                if (include_feature_node)
                {
                    ParseRegisters(include_feature_node, target_info, this->m_register_info, abi_to_use_sp, cur_reg_num, reg_offset);
                }
            }
            this->m_register_info.Finalize(arch_to_use);
        }
    }

    return m_register_info.GetNumRegisters() > 0;
}

Error
ProcessGDBRemote::GetLoadedModuleList (LoadedModuleInfoList & list)
{
    // Make sure LLDB has an XML parser it can use first
    if (!XMLDocument::XMLEnabled())
        return Error (0, ErrorType::eErrorTypeGeneric);

    Log *log = GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS);
    if (log)
        log->Printf ("ProcessGDBRemote::%s", __FUNCTION__);

    GDBRemoteCommunicationClient & comm = m_gdb_comm;

    // check that we have extended feature read support
    if (comm.GetQXferLibrariesSVR4ReadSupported ()) {
        list.clear ();

        // request the loaded library list
        std::string raw;
        lldb_private::Error lldberr;

        if (!comm.ReadExtFeature (ConstString ("libraries-svr4"), ConstString (""), raw, lldberr))
          return Error (0, ErrorType::eErrorTypeGeneric);

        // parse the xml file in memory
        if (log)
            log->Printf ("parsing: %s", raw.c_str());
        XMLDocument doc;

        if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml"))
            return Error (0, ErrorType::eErrorTypeGeneric);

        XMLNode root_element = doc.GetRootElement("library-list-svr4");
        if (!root_element)
            return Error();

        // main link map structure
        llvm::StringRef main_lm = root_element.GetAttributeValue("main-lm");
        if (!main_lm.empty())
        {
            list.m_link_map = StringConvert::ToUInt64(main_lm.data(), LLDB_INVALID_ADDRESS, 0);
        }

        root_element.ForEachChildElementWithName("library", [log, &list](const XMLNode &library) -> bool {

            LoadedModuleInfoList::LoadedModuleInfo module;

            library.ForEachAttribute([log, &module](const llvm::StringRef &name, const llvm::StringRef &value) -> bool {

                if (name == "name")
                    module.set_name (value.str());
                else if (name == "lm")
                {
                    // the address of the link_map struct.
                    module.set_link_map(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0));
                }
                else if (name == "l_addr")
                {
                    // the displacement as read from the field 'l_addr' of the link_map struct.
                    module.set_base(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0));
                    // base address is always a displacement, not an absolute value.
                    module.set_base_is_offset(true);
                }
                else if (name == "l_ld")
                {
                    // the memory address of the libraries PT_DYAMIC section.
                    module.set_dynamic(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0));
                }

                return true; // Keep iterating over all properties of "library"
            });

            if (log)
            {
                std::string name;
                lldb::addr_t lm=0, base=0, ld=0;
                bool base_is_offset;

                module.get_name (name);
                module.get_link_map (lm);
                module.get_base (base);
                module.get_base_is_offset (base_is_offset);
                module.get_dynamic (ld);

                log->Printf ("found (link_map:0x%08" PRIx64 ", base:0x%08" PRIx64 "[%s], ld:0x%08" PRIx64 ", name:'%s')", lm, base, (base_is_offset ? "offset" : "absolute"), ld, name.c_str());
            }

            list.add (module);
            return true; // Keep iterating over all "library" elements in the root node
        });

        if (log)
            log->Printf ("found %" PRId32 " modules in total", (int) list.m_list.size());
    } else if (comm.GetQXferLibrariesReadSupported ()) {
        list.clear ();

        // request the loaded library list
        std::string raw;
        lldb_private::Error lldberr;

        if (!comm.ReadExtFeature (ConstString ("libraries"), ConstString (""), raw, lldberr))
          return Error (0, ErrorType::eErrorTypeGeneric);

        if (log)
            log->Printf ("parsing: %s", raw.c_str());
        XMLDocument doc;

        if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml"))
            return Error (0, ErrorType::eErrorTypeGeneric);

        XMLNode root_element = doc.GetRootElement("library-list");
        if (!root_element)
            return Error();

        root_element.ForEachChildElementWithName("library", [log, &list](const XMLNode &library) -> bool {
            LoadedModuleInfoList::LoadedModuleInfo module;

            llvm::StringRef name = library.GetAttributeValue("name");
            module.set_name(name.str());

            // The base address of a given library will be the address of its
            // first section. Most remotes send only one section for Windows
            // targets for example.
            const XMLNode &section = library.FindFirstChildElementWithName("section");
            llvm::StringRef address = section.GetAttributeValue("address");
            module.set_base(StringConvert::ToUInt64(address.data(), LLDB_INVALID_ADDRESS, 0));
            // These addresses are absolute values.
            module.set_base_is_offset(false);

            if (log)
            {
                std::string name;
                lldb::addr_t base = 0;
                bool base_is_offset;
                module.get_name (name);
                module.get_base (base);
                module.get_base_is_offset (base_is_offset);

                log->Printf ("found (base:0x%08" PRIx64 "[%s], name:'%s')", base, (base_is_offset ? "offset" : "absolute"), name.c_str());
            }

            list.add (module);
            return true; // Keep iterating over all "library" elements in the root node
        });

        if (log)
            log->Printf ("found %" PRId32 " modules in total", (int) list.m_list.size());
    } else {
        return Error (0, ErrorType::eErrorTypeGeneric);
    }

    return Error();
}

lldb::ModuleSP
ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t link_map,
                                       lldb::addr_t base_addr, bool value_is_offset)
{
    DynamicLoader *loader = GetDynamicLoader();
    if (!loader)
        return nullptr;

    return loader->LoadModuleAtAddress(file, link_map, base_addr, value_is_offset);
}

size_t
ProcessGDBRemote::LoadModules (LoadedModuleInfoList &module_list)
{
    using lldb_private::process_gdb_remote::ProcessGDBRemote;

    // request a list of loaded libraries from GDBServer
    if (GetLoadedModuleList (module_list).Fail())
        return 0;

    // get a list of all the modules
    ModuleList new_modules;

    for (LoadedModuleInfoList::LoadedModuleInfo & modInfo : module_list.m_list)
    {
        std::string  mod_name;
        lldb::addr_t mod_base;
        lldb::addr_t link_map;
        bool         mod_base_is_offset;

        bool valid = true;
        valid &= modInfo.get_name (mod_name);
        valid &= modInfo.get_base (mod_base);
        valid &= modInfo.get_base_is_offset (mod_base_is_offset);
        if (!valid)
            continue;

        if (!modInfo.get_link_map (link_map))
            link_map = LLDB_INVALID_ADDRESS;

        FileSpec file (mod_name.c_str(), true);
        lldb::ModuleSP module_sp = LoadModuleAtAddress (file, link_map, mod_base,
                                                        mod_base_is_offset);

        if (module_sp.get())
            new_modules.Append (module_sp);
    }

    if (new_modules.GetSize() > 0)
    {
        ModuleList removed_modules;
        Target &target = GetTarget();
        ModuleList &loaded_modules = m_process->GetTarget().GetImages();

        for (size_t i = 0; i < loaded_modules.GetSize(); ++i)
        {
            const lldb::ModuleSP loaded_module = loaded_modules.GetModuleAtIndex(i);

            bool found = false;
            for (size_t j = 0; j < new_modules.GetSize(); ++j)
            {
                if (new_modules.GetModuleAtIndex(j).get() == loaded_module.get())
                    found = true;
            }

            // The main executable will never be included in libraries-svr4, don't remove it
            if (!found && loaded_module.get() != target.GetExecutableModulePointer())
            {
                removed_modules.Append (loaded_module);
            }
        }

        loaded_modules.Remove (removed_modules);
        m_process->GetTarget().ModulesDidUnload (removed_modules, false);

        new_modules.ForEach ([&target](const lldb::ModuleSP module_sp) -> bool
        {
            lldb_private::ObjectFile * obj = module_sp->GetObjectFile ();
            if (!obj)
                return true;

            if (obj->GetType () != ObjectFile::Type::eTypeExecutable)
                return true;

            lldb::ModuleSP module_copy_sp = module_sp;
            target.SetExecutableModule (module_copy_sp, false);
            return false;
        });

        loaded_modules.AppendIfNeeded (new_modules);
        m_process->GetTarget().ModulesDidLoad (new_modules);
    }

    return new_modules.GetSize();
}

size_t
ProcessGDBRemote::LoadModules ()
{
    LoadedModuleInfoList module_list;
    return LoadModules (module_list);
}

Error
ProcessGDBRemote::GetFileLoadAddress(const FileSpec& file, bool& is_loaded, lldb::addr_t& load_addr)
{
    is_loaded = false;
    load_addr = LLDB_INVALID_ADDRESS;

    std::string file_path = file.GetPath(false);
    if (file_path.empty ())
        return Error("Empty file name specified");

    StreamString packet;
    packet.PutCString("qFileLoadAddress:");
    packet.PutCStringAsRawHex8(file_path.c_str());

    StringExtractorGDBRemote response;
    if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(), response, false) != GDBRemoteCommunication::PacketResult::Success)
        return Error("Sending qFileLoadAddress packet failed");

    if (response.IsErrorResponse())
    {
        if (response.GetError() == 1)
        {
            // The file is not loaded into the inferior
            is_loaded = false;
            load_addr = LLDB_INVALID_ADDRESS;
            return Error();
        }

        return Error("Fetching file load address from remote server returned an error");
    }

    if (response.IsNormalResponse())
    {
        is_loaded = true;
        load_addr = response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
        return Error();
    }

    return Error("Unknown error happened during sending the load address packet");
}


void
ProcessGDBRemote::ModulesDidLoad (ModuleList &module_list)
{
    // We must call the lldb_private::Process::ModulesDidLoad () first before we do anything
    Process::ModulesDidLoad (module_list);

    // After loading shared libraries, we can ask our remote GDB server if
    // it needs any symbols.
    m_gdb_comm.ServeSymbolLookups(this);
}


class CommandObjectProcessGDBRemoteSpeedTest: public CommandObjectParsed
{
public:
    CommandObjectProcessGDBRemoteSpeedTest(CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "process plugin packet speed-test",
                             "Tests packet speeds of various sizes to determine the performance characteristics of the GDB remote connection. ",
                             NULL),
        m_option_group (interpreter),
        m_num_packets (LLDB_OPT_SET_1, false, "count",       'c', 0, eArgTypeCount, "The number of packets to send of each varying size (default is 1000).", 1000),
        m_max_send    (LLDB_OPT_SET_1, false, "max-send",    's', 0, eArgTypeCount, "The maximum number of bytes to send in a packet. Sizes increase in powers of 2 while the size is less than or equal to this option value. (default 1024).", 1024),
        m_max_recv    (LLDB_OPT_SET_1, false, "max-receive", 'r', 0, eArgTypeCount, "The maximum number of bytes to receive in a packet. Sizes increase in powers of 2 while the size is less than or equal to this option value. (default 1024).", 1024),
        m_json        (LLDB_OPT_SET_1, false, "json",        'j', "Print the output as JSON data for easy parsing.", false, true)
    {
        m_option_group.Append (&m_num_packets, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
        m_option_group.Append (&m_max_send, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
        m_option_group.Append (&m_max_recv, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
        m_option_group.Append (&m_json, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
        m_option_group.Finalize();
    }

    ~CommandObjectProcessGDBRemoteSpeedTest ()
    {
    }


    Options *
    GetOptions () override
    {
        return &m_option_group;
    }

    bool
    DoExecute (Args& command, CommandReturnObject &result) override
    {
        const size_t argc = command.GetArgumentCount();
        if (argc == 0)
        {
            ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
            if (process)
            {
                StreamSP output_stream_sp (m_interpreter.GetDebugger().GetAsyncOutputStream());
                result.SetImmediateOutputStream (output_stream_sp);

                const uint32_t num_packets = (uint32_t)m_num_packets.GetOptionValue().GetCurrentValue();
                const uint64_t max_send = m_max_send.GetOptionValue().GetCurrentValue();
                const uint64_t max_recv = m_max_recv.GetOptionValue().GetCurrentValue();
                const bool json = m_json.GetOptionValue().GetCurrentValue();
                if (output_stream_sp)
                    process->GetGDBRemote().TestPacketSpeed (num_packets, max_send, max_recv, json, *output_stream_sp);
                else
                {
                    process->GetGDBRemote().TestPacketSpeed (num_packets, max_send, max_recv, json, result.GetOutputStream());
                }
                result.SetStatus (eReturnStatusSuccessFinishResult);
                return true;
            }
        }
        else
        {
            result.AppendErrorWithFormat ("'%s' takes no arguments", m_cmd_name.c_str());
        }
        result.SetStatus (eReturnStatusFailed);
        return false;
    }
protected:
    OptionGroupOptions m_option_group;
    OptionGroupUInt64 m_num_packets;
    OptionGroupUInt64 m_max_send;
    OptionGroupUInt64 m_max_recv;
    OptionGroupBoolean m_json;

};

class CommandObjectProcessGDBRemotePacketHistory : public CommandObjectParsed
{
private:

public:
    CommandObjectProcessGDBRemotePacketHistory(CommandInterpreter &interpreter) :
    CommandObjectParsed (interpreter,
                         "process plugin packet history",
                         "Dumps the packet history buffer. ",
                         NULL)
    {
    }

    ~CommandObjectProcessGDBRemotePacketHistory ()
    {
    }

    bool
    DoExecute (Args& command, CommandReturnObject &result) override
    {
        const size_t argc = command.GetArgumentCount();
        if (argc == 0)
        {
            ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
            if (process)
            {
                process->GetGDBRemote().DumpHistory(result.GetOutputStream());
                result.SetStatus (eReturnStatusSuccessFinishResult);
                return true;
            }
        }
        else
        {
            result.AppendErrorWithFormat ("'%s' takes no arguments", m_cmd_name.c_str());
        }
        result.SetStatus (eReturnStatusFailed);
        return false;
    }
};

class CommandObjectProcessGDBRemotePacketXferSize : public CommandObjectParsed
{
private:

public:
    CommandObjectProcessGDBRemotePacketXferSize(CommandInterpreter &interpreter) :
    CommandObjectParsed (interpreter,
                         "process plugin packet xfer-size",
                         "Maximum size that lldb will try to read/write one one chunk.",
                         NULL)
    {
    }

    ~CommandObjectProcessGDBRemotePacketXferSize ()
    {
    }

    bool
    DoExecute (Args& command, CommandReturnObject &result) override
    {
        const size_t argc = command.GetArgumentCount();
        if (argc == 0)
        {
            result.AppendErrorWithFormat ("'%s' takes an argument to specify the max amount to be transferred when reading/writing", m_cmd_name.c_str());
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
        if (process)
        {
            const char *packet_size = command.GetArgumentAtIndex(0);
            errno = 0;
            uint64_t user_specified_max = strtoul (packet_size, NULL, 10);
            if (errno == 0 && user_specified_max != 0)
            {
                process->SetUserSpecifiedMaxMemoryTransferSize (user_specified_max);
                result.SetStatus (eReturnStatusSuccessFinishResult);
                return true;
            }
        }
        result.SetStatus (eReturnStatusFailed);
        return false;
    }
};


class CommandObjectProcessGDBRemotePacketSend : public CommandObjectParsed
{
private:

public:
    CommandObjectProcessGDBRemotePacketSend(CommandInterpreter &interpreter) :
        CommandObjectParsed (interpreter,
                             "process plugin packet send",
                             "Send a custom packet through the GDB remote protocol and print the answer. "
                             "The packet header and footer will automatically be added to the packet prior to sending and stripped from the result.",
                             NULL)
    {
    }

    ~CommandObjectProcessGDBRemotePacketSend ()
    {
    }

    bool
    DoExecute (Args& command, CommandReturnObject &result) override
    {
        const size_t argc = command.GetArgumentCount();
        if (argc == 0)
        {
            result.AppendErrorWithFormat ("'%s' takes a one or more packet content arguments", m_cmd_name.c_str());
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
        if (process)
        {
            for (size_t i=0; i<argc; ++ i)
            {
                const char *packet_cstr = command.GetArgumentAtIndex(0);
                bool send_async = true;
                StringExtractorGDBRemote response;
                process->GetGDBRemote().SendPacketAndWaitForResponse(packet_cstr, response, send_async);
                result.SetStatus (eReturnStatusSuccessFinishResult);
                Stream &output_strm = result.GetOutputStream();
                output_strm.Printf ("  packet: %s\n", packet_cstr);
                std::string &response_str = response.GetStringRef();

                if (strstr(packet_cstr, "qGetProfileData") != NULL)
                {
                    response_str = process->GetGDBRemote().HarmonizeThreadIdsForProfileData(process, response);
                }

                if (response_str.empty())
                    output_strm.PutCString ("response: \nerror: UNIMPLEMENTED\n");
                else
                    output_strm.Printf ("response: %s\n", response.GetStringRef().c_str());
            }
        }
        return true;
    }
};

class CommandObjectProcessGDBRemotePacketMonitor : public CommandObjectRaw
{
private:

public:
    CommandObjectProcessGDBRemotePacketMonitor(CommandInterpreter &interpreter) :
        CommandObjectRaw (interpreter,
                         "process plugin packet monitor",
                         "Send a qRcmd packet through the GDB remote protocol and print the response."
                         "The argument passed to this command will be hex encoded into a valid 'qRcmd' packet, sent and the response will be printed.",
                         NULL)
    {
    }

    ~CommandObjectProcessGDBRemotePacketMonitor ()
    {
    }

    bool
    DoExecute (const char *command, CommandReturnObject &result) override
    {
        if (command == NULL || command[0] == '\0')
        {
            result.AppendErrorWithFormat ("'%s' takes a command string argument", m_cmd_name.c_str());
            result.SetStatus (eReturnStatusFailed);
            return false;
        }

        ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
        if (process)
        {
            StreamString packet;
            packet.PutCString("qRcmd,");
            packet.PutBytesAsRawHex8(command, strlen(command));
            const char *packet_cstr = packet.GetString().c_str();

            bool send_async = true;
            StringExtractorGDBRemote response;
            process->GetGDBRemote().SendPacketAndWaitForResponse(packet_cstr, response, send_async);
            result.SetStatus (eReturnStatusSuccessFinishResult);
            Stream &output_strm = result.GetOutputStream();
            output_strm.Printf ("  packet: %s\n", packet_cstr);
            const std::string &response_str = response.GetStringRef();

            if (response_str.empty())
                output_strm.PutCString ("response: \nerror: UNIMPLEMENTED\n");
            else
                output_strm.Printf ("response: %s\n", response.GetStringRef().c_str());
        }
        return true;
    }
};

class CommandObjectProcessGDBRemotePacket : public CommandObjectMultiword
{
private:

public:
    CommandObjectProcessGDBRemotePacket(CommandInterpreter &interpreter) :
        CommandObjectMultiword (interpreter,
                                "process plugin packet",
                                "Commands that deal with GDB remote packets.",
                                NULL)
    {
        LoadSubCommand ("history", CommandObjectSP (new CommandObjectProcessGDBRemotePacketHistory (interpreter)));
        LoadSubCommand ("send", CommandObjectSP (new CommandObjectProcessGDBRemotePacketSend (interpreter)));
        LoadSubCommand ("monitor", CommandObjectSP (new CommandObjectProcessGDBRemotePacketMonitor (interpreter)));
        LoadSubCommand ("xfer-size", CommandObjectSP (new CommandObjectProcessGDBRemotePacketXferSize (interpreter)));
        LoadSubCommand ("speed-test", CommandObjectSP (new CommandObjectProcessGDBRemoteSpeedTest (interpreter)));
    }

    ~CommandObjectProcessGDBRemotePacket ()
    {
    }
};

class CommandObjectMultiwordProcessGDBRemote : public CommandObjectMultiword
{
public:
    CommandObjectMultiwordProcessGDBRemote(CommandInterpreter &interpreter)
        : CommandObjectMultiword(interpreter, "process plugin", "Commands for operating on a ProcessGDBRemote process.",
                                 "process plugin <subcommand> [<subcommand-options>]")
    {
        LoadSubCommand ("packet", CommandObjectSP (new CommandObjectProcessGDBRemotePacket    (interpreter)));
    }

    ~CommandObjectMultiwordProcessGDBRemote ()
    {
    }
};

CommandObject *
ProcessGDBRemote::GetPluginCommandObject()
{
    if (!m_command_sp)
        m_command_sp.reset (new CommandObjectMultiwordProcessGDBRemote (GetTarget().GetDebugger().GetCommandInterpreter()));
    return m_command_sp.get();
}
