diff options
Diffstat (limited to 'source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp')
| -rw-r--r-- | source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp | 1080 | 
1 files changed, 681 insertions, 399 deletions
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 1e150b1dda9fd..2e7a5b5384f46 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -40,6 +40,7 @@  #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" @@ -56,6 +57,7 @@  #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" @@ -192,7 +194,7 @@ public:          {              for (uint32_t i = 0; i < e_num; ++i)                  m_has[i] = false; -        }; +        }          void set_name (const std::string & name)          { @@ -216,6 +218,16 @@ public:              return m_has[e_has_base];          } +        void set_base_is_offset (bool is_offset) +        { +            m_base_is_offset = is_offset; +        } +        bool get_base_is_offset(bool & out) const +        { +            out = m_base_is_offset; +            return m_has[e_has_base]; +        } +          void set_link_map (const lldb::addr_t addr)          {              m_link_map = addr; @@ -250,6 +262,7 @@ public:          std::string m_name;          lldb::addr_t m_link_map;          lldb::addr_t m_base; +        bool m_base_is_offset;          lldb::addr_t m_dynamic;      }; @@ -322,22 +335,22 @@ ProcessGDBRemote::Terminate()  lldb::ProcessSP -ProcessGDBRemote::CreateInstance (Target &target, Listener &listener, const FileSpec *crash_file_path) +ProcessGDBRemote::CreateInstance (lldb::TargetSP target_sp, Listener &listener, const FileSpec *crash_file_path)  {      lldb::ProcessSP process_sp;      if (crash_file_path == NULL) -        process_sp.reset (new ProcessGDBRemote (target, listener)); +        process_sp.reset (new ProcessGDBRemote (target_sp, listener));      return process_sp;  }  bool -ProcessGDBRemote::CanDebug (Target &target, bool plugin_specified_by_name) +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.GetExecutableModulePointer(); +    Module *exe_module = target_sp->GetExecutableModulePointer();      if (exe_module)      {          ObjectFile *exe_objfile = exe_module->GetObjectFile(); @@ -366,17 +379,20 @@ ProcessGDBRemote::CanDebug (Target &target, bool plugin_specified_by_name)  //----------------------------------------------------------------------  // ProcessGDBRemote constructor  //---------------------------------------------------------------------- -ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) : -    Process (target, listener), +ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, Listener &listener) : +    Process (target_sp, listener),      m_flags (0),      m_gdb_comm (),      m_debugserver_pid (LLDB_INVALID_PROCESS_ID),      m_last_stop_packet_mutex (Mutex::eMutexTypeRecursive),      m_register_info (),      m_async_broadcaster (NULL, "lldb.process.gdb-remote.async-broadcaster"), +    m_async_listener("lldb.process.gdb-remote.async-listener"),      m_async_thread_state_mutex(Mutex::eMutexTypeRecursive),      m_thread_ids (), -    m_threads_info_sp (), +    m_thread_pcs (), +    m_jstopinfo_sp (), +    m_jthreadsinfo_sp (),      m_continue_c_tids (),      m_continue_C_tids (),      m_continue_s_tids (), @@ -394,6 +410,25 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :      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.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.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); @@ -481,6 +516,40 @@ ProcessGDBRemote::ParsePythonTargetDefinition(const FileSpec &target_definition_      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 ®_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> ®nums, int base)  { @@ -524,11 +593,23 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)      //     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()); +        }      }      if (GetGDBServerRegisterInfo ()) @@ -561,12 +642,12 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)                      0,                    // byte size                      reg_offset,           // offset                      eEncodingUint,        // encoding -                    eFormatHex,           // formate +                    eFormatHex,           // format                      { -                        LLDB_INVALID_REGNUM, // GCC reg num +                        LLDB_INVALID_REGNUM, // eh_frame reg num                          LLDB_INVALID_REGNUM, // DWARF reg num                          LLDB_INVALID_REGNUM, // generic reg num -                        reg_num,             // GDB reg num +                        reg_num,             // process plugin reg num                          reg_num           // native register number                      },                      NULL, @@ -635,9 +716,9 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)                      {                          set_name.SetCString(value.c_str());                      } -                    else if (name.compare("gcc") == 0) +                    else if (name.compare("gcc") == 0 || name.compare("ehframe") == 0)                      { -                        reg_info.kinds[eRegisterKindGCC] = StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0); +                        reg_info.kinds[eRegisterKindEHFrame] = StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0);                      }                      else if (name.compare("dwarf") == 0)                      { @@ -671,6 +752,8 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)                      reg_info.invalidate_regs = invalidate_regs.data();                  } +                AugmentRegisterInfoViaABI (reg_info, reg_name, GetABI ()); +                  m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name);              }              else @@ -711,11 +794,12 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)      if (!target_arch.IsValid())      {          if (remote_arch.IsValid() -              && remote_arch.GetMachine() == llvm::Triple::arm +              && (remote_arch.GetMachine() == llvm::Triple::arm || remote_arch.GetMachine() == llvm::Triple::thumb)                && remote_arch.GetTriple().getVendor() == llvm::Triple::Apple)              m_register_info.HardcodeARMRegisters(from_scratch);      } -    else if (target_arch.GetMachine() == llvm::Triple::arm) +    else if (target_arch.GetMachine() == llvm::Triple::arm +            || target_arch.GetMachine() == llvm::Triple::thumb)      {          m_register_info.HardcodeARMRegisters(from_scratch);      } @@ -779,20 +863,21 @@ ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url)              if (GetTarget().GetNonStopModeEnabled())                  HandleStopReplySequence(); -            if (!m_target.GetArchitecture().IsValid())  +            Target &target = GetTarget(); +            if (!target.GetArchitecture().IsValid())               {                  if (m_gdb_comm.GetProcessArchitecture().IsValid())                  { -                    m_target.SetArchitecture(m_gdb_comm.GetProcessArchitecture()); +                    target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());                  }                  else                  { -                    m_target.SetArchitecture(m_gdb_comm.GetHostArchitecture()); +                    target.SetArchitecture(m_gdb_comm.GetHostArchitecture());                  }              }              const StateType state = SetThreadStopInfo (response); -            if (state == eStateStopped) +            if (state != eStateInvalid)              {                  SetPrivateState (state);              } @@ -910,27 +995,22 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)      ObjectFile * object_file = exe_module->GetObjectFile();      if (object_file)      { -        // Make sure we aren't already connected? -        if (!m_gdb_comm.IsConnected()) -        { -            error = LaunchAndConnectToDebugserver (launch_info); -        } -         +        error = EstablishConnectionIfNeeded (launch_info);          if (error.Success())          {              lldb_utility::PseudoTerminal pty;              const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0; -            PlatformSP platform_sp (m_target.GetPlatform()); +            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("/dev/null", false); +                    stdin_file_spec.SetFile(FileSystem::DEV_NULL, false);                  if (!stdout_file_spec) -                    stdout_file_spec.SetFile("/dev/null", false); +                    stdout_file_spec.SetFile(FileSystem::DEV_NULL, false);                  if (!stderr_file_spec) -                    stderr_file_spec.SetFile("/dev/null", false); +                    stderr_file_spec.SetFile(FileSystem::DEV_NULL, false);              }              else if (platform_sp && platform_sp->IsHost())              { @@ -977,7 +1057,7 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)              m_gdb_comm.SetDisableASLR (launch_flags & eLaunchFlagDisableASLR);              m_gdb_comm.SetDetachOnError (launch_flags & eLaunchFlagDetachOnError); -            m_gdb_comm.SendLaunchArchPacket (m_target.GetArchitecture().GetArchitectureName()); +            m_gdb_comm.SendLaunchArchPacket (GetTarget().GetArchitecture().GetArchitectureName());              const char * launch_event_data = launch_info.GetLaunchEventData();              if (launch_event_data != NULL && *launch_event_data != '\0') @@ -1044,13 +1124,13 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)                  if (process_arch.IsValid())                  { -                    m_target.MergeArchitecture(process_arch); +                    GetTarget().MergeArchitecture(process_arch);                  }                  else                  {                      const ArchSpec &host_arch = m_gdb_comm.GetHostArchitecture();                      if (host_arch.IsValid()) -                        m_target.MergeArchitecture(host_arch); +                        GetTarget().MergeArchitecture(host_arch);                  }                  SetPrivateState (SetThreadStopInfo (response)); @@ -1226,8 +1306,8 @@ ProcessGDBRemote::DidLaunchOrAttach (ArchSpec& process_arch)                  // 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.GetTriple().getVendor() == llvm::Triple::Apple) +                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) @@ -1295,21 +1375,7 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const Process      Clear();      if (attach_pid != LLDB_INVALID_PROCESS_ID)      { -        // Make sure we aren't already connected? -        if (!m_gdb_comm.IsConnected()) -        { -            error = LaunchAndConnectToDebugserver (attach_info); -             -            if (error.Fail()) -            { -                const char *error_string = error.AsCString(); -                if (error_string == NULL) -                    error_string = "unable to launch " DEBUGSERVER_BASENAME; - -                SetExitStatus (-1, error_string); -            } -        } -     +        error = EstablishConnectionIfNeeded (attach_info);          if (error.Success())          {              m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError()); @@ -1319,6 +1385,8 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const Process              SetID (attach_pid);                          m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet, packet_len));          } +        else +            SetExitStatus (-1, error.AsCString());      }      return error; @@ -1333,21 +1401,7 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, const Pro      if (process_name && process_name[0])      { -        // Make sure we aren't already connected? -        if (!m_gdb_comm.IsConnected()) -        { -            error = LaunchAndConnectToDebugserver (attach_info); - -            if (error.Fail()) -            { -                const char *error_string = error.AsCString(); -                if (error_string == NULL) -                    error_string = "unable to launch " DEBUGSERVER_BASENAME; - -                SetExitStatus (-1, error_string); -            } -        } - +        error = EstablishConnectionIfNeeded (attach_info);          if (error.Success())          {              StreamString packet; @@ -1371,11 +1425,13 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, const Pro              else                  packet.PutCString("vAttachName");              packet.PutChar(';'); -            packet.PutBytesAsRawHex8(process_name, strlen(process_name), lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder()); +            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;  } @@ -1403,6 +1459,8 @@ ProcessGDBRemote::WillResume ()      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();  } @@ -1694,12 +1752,14 @@ ProcessGDBRemote::ClearThreadIDList ()  {      Mutex::Locker locker(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) @@ -1717,18 +1777,39 @@ ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue (std::string &value)      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 ()  {      Mutex::Locker locker(m_thread_list_real.GetMutex()); -    if (m_threads_info_sp) +    if (m_jthreadsinfo_sp)      {          // If we have the JSON threads info, we can get the thread list from that -        StructuredData::Array *thread_infos = m_threads_info_sp->GetAsArray(); +        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) @@ -1751,25 +1832,43 @@ ProcessGDBRemote::UpdateThreadIDList ()          // 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); -        // 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++) +        //Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex); +        Mutex::Locker stop_stack_lock; +        if (stop_stack_lock.TryLock(m_last_stop_packet_mutex))          { -            // Get the thread stop info -            StringExtractorGDBRemote &stop_info = m_stop_packet_stack[i]; -            const std::string &stop_info_str = stop_info.GetStringRef(); -            const size_t threads_pos = stop_info_str.find(";threads:"); -            if (threads_pos != std::string::npos) +            // 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++)              { -                const size_t start = threads_pos + strlen(";threads:"); -                const size_t end = stop_info_str.find(';', start); -                if (end != std::string::npos) +                // 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)                  { -                    std::string value = stop_info_str.substr(start, end - start); -                    if (UpdateThreadIDsFromStopReplyThreadsValue(value)) -                        return true; +                    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; +                    }                  }              }          } @@ -1826,6 +1925,25 @@ ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new                             __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.AddThread(thread_sp);          }      } @@ -1846,13 +1964,14 @@ ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new      return true;  } +  bool -ProcessGDBRemote::CalculateThreadStopInfo (ThreadGDBRemote *thread) +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 (m_threads_info_sp) +    if (thread_infos_sp)      { -        StructuredData::Array *thread_infos = m_threads_info_sp->GetAsArray(); +        StructuredData::Array *thread_infos = thread_infos_sp->GetAsArray();          if (thread_infos)          {              lldb::tid_t tid; @@ -1865,12 +1984,36 @@ ProcessGDBRemote::CalculateThreadStopInfo (ThreadGDBRemote *thread)                      if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>("tid", tid, LLDB_INVALID_THREAD_ID))                      {                          if (tid == thread->GetID()) -                            return SetThreadStopInfo(thread_dict); +                            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; @@ -1926,8 +2069,6 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid,                  gdb_thread->PrivateSetRegisterValue (pair.first, reg_value_extractor);              } -            // Clear the stop info just in case we don't set it to anything -            thread_sp->SetStopInfo (StopInfoSP());              thread_sp->SetName (thread_name.empty() ? NULL : thread_name.c_str());              gdb_thread->SetThreadDispatchQAddr (thread_dispatch_qaddr); @@ -1937,145 +2078,159 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid,              else                  gdb_thread->ClearQueueInfo(); - -            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 +            // Make sure we update our thread stop reason just once +            if (!thread_sp->StopInfoIsUpToDate())              { -                bool handled = false; -                bool did_exec = false; -                if (!reason.empty()) +                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)                  { -                    if (reason.compare("trace") == 0) -                    { -                        thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp)); -                        handled = true; -                    } -                    else if (reason.compare("breakpoint") == 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())                      { -                        addr_t pc = thread_sp->GetRegisterContext()->GetPC(); -                        lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); -                        if (bp_site_sp) +                        if (reason.compare("trace") == 0)                          { -                            // 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. +                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));                              handled = true; -                            if (bp_site_sp->ValidForThisThread (thread_sp.get())) -                            { -                                thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID())); -                            } -                            else +                        } +                        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)                              { -                                StopInfoSP invalid_stop_info_sp; -                                thread_sp->SetStopInfo (invalid_stop_info_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) +                        else if (reason.compare("trap") == 0)                          { -                            WatchpointSP wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr); -                            if (wp_sp) +                            // 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) +                                    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)                              { -                                wp_sp->SetHardwareIndex(wp_index); -                                watch_id = wp_sp->GetID(); +                                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;                          } -                        if (watch_id == LLDB_INVALID_WATCH_ID) +                        else if (reason.compare("exception") == 0)                          { -                            Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_WATCHPOINTS)); -                            if (log) log->Printf ("failed to find watchpoint"); +                            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;                          } -                        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;                      } -                } -                if (!handled && signo && did_exec == false) -                { -                    if (signo == SIGTRAP) +                    if (!handled && signo && did_exec == false)                      { -                        // 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 (signo == SIGTRAP)                          { -                            // 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())) +                            // 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(m_breakpoint_pc_offset != 0) -                                    thread_sp->GetRegisterContext()->SetPC(pc); -                                thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID())); +                                // 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                              { -                                StopInfoSP invalid_stop_info_sp; -                                thread_sp->SetStopInfo (invalid_stop_info_sp); +                                // 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()));                              }                          } -                        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 (!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 +                    if (!description.empty())                      { -                        thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException (*thread_sp, description.c_str())); +                        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())); +                        }                      }                  }              } @@ -2084,7 +2239,7 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid,      return thread_sp;  } -StateType +lldb::ThreadSP  ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)  {      static ConstString g_key_tid("tid"); @@ -2101,6 +2256,7 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)      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; @@ -2159,7 +2315,7 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)          }          else if (key == g_key_name)          { -            thread_name = std::move(object->GetStringValue()); +            thread_name = object->GetStringValue();          }          else if (key == g_key_qaddr)          { @@ -2168,7 +2324,7 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)          else if (key == g_key_queue_name)          {              queue_vars_valid = true; -            queue_name = std::move(object->GetStringValue()); +            queue_name = object->GetStringValue();          }          else if (key == g_key_queue_kind)          { @@ -2192,11 +2348,11 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)          }          else if (key == g_key_reason)          { -            reason = std::move(object->GetStringValue()); +            reason = object->GetStringValue();          }          else if (key == g_key_description)          { -            description = std::move(object->GetStringValue()); +            description = object->GetStringValue();          }          else if (key == g_key_registers)          { @@ -2207,7 +2363,7 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_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] = std::move(object->GetStringValue()); +                        expedited_register_map[reg] = object->GetStringValue();                      return true; // Keep iterating through all array items                  });              } @@ -2245,24 +2401,24 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)              }          } +        else if (key == g_key_signal) +            signo = object->GetIntegerValue(LLDB_INVALID_SIGNAL_NUMBER);          return true; // Keep iterating through all dictionary key/value pairs      }); -    SetThreadStopInfo (tid, -                       expedited_register_map, -                       signo, -                       thread_name, -                       reason, -                       description, -                       exc_type, -                       exc_data, -                       thread_dispatch_qaddr, -                       queue_vars_valid, -                       queue_name, -                       queue_kind, -                       queue_serial); - -    return eStateExited; +    return SetThreadStopInfo (tid, +                              expedited_register_map, +                              signo, +                              thread_name, +                              reason, +                              description, +                              exc_type, +                              exc_data, +                              thread_dispatch_qaddr, +                              queue_vars_valid, +                              queue_name, +                              queue_kind, +                              queue_serial);  }  StateType @@ -2348,6 +2504,39 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)                      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; @@ -2431,7 +2620,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)                          if (mem_cache_addr != LLDB_INVALID_ADDRESS)                          {                              StringExtractor bytes; -                            bytes.GetStringRef() = std::move(pair.second.str()); +                            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); @@ -2455,6 +2644,10 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)                      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); @@ -2509,6 +2702,7 @@ ProcessGDBRemote::RefreshStateAfterStop ()  {      Mutex::Locker locker(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. @@ -2545,11 +2739,6 @@ ProcessGDBRemote::RefreshStateAfterStop ()          m_initial_tid = LLDB_INVALID_THREAD_ID;      } -    // Fetch the threads via an efficient packet that gets stop infos for all threads -    // only if we have more than one thread -    if (m_thread_ids.size() > 1) -        m_threads_info_sp = m_gdb_comm.GetThreadsInfo(); -      // Let all threads recover from stopping and do any clean up based      // on the previous thread state (if any).      m_thread_list_real.RefreshStateAfterStop(); @@ -2824,6 +3013,12 @@ ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response)      {          // Lock the thread stack while we access it          Mutex::Locker stop_stack_lock(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 @@ -2831,6 +3026,11 @@ ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response)      }  } +void +ProcessGDBRemote::SetUnixSignals(const UnixSignalsSP &signals_sp) +{ +    Process::SetUnixSignals(std::make_shared<GDBRemoteSignals>(signals_sp)); +}  //------------------------------------------------------------------  // Process Queries @@ -2839,7 +3039,7 @@ ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response)  bool  ProcessGDBRemote::IsAlive ()  { -    return m_gdb_comm.IsConnected() && m_private_state.GetValue() != eStateExited; +    return m_gdb_comm.IsConnected() && Process::IsAlive();  }  addr_t @@ -2859,6 +3059,35 @@ ProcessGDBRemote::GetImageInfoAddress()      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  //------------------------------------------------------------------ @@ -2877,14 +3106,8 @@ ProcessGDBRemote::DoReadMemory (addr_t addr, void *buf, size_t size, Error &erro      char packet[64];      int packet_len;      bool binary_memory_read = m_gdb_comm.GetxPacketSupported(); -    if (binary_memory_read) -    { -        packet_len = ::snprintf (packet, sizeof(packet), "x0x%" PRIx64 ",0x%" PRIx64, (uint64_t)addr, (uint64_t)size); -    } -    else -    { -        packet_len = ::snprintf (packet, sizeof(packet), "m%" PRIx64 ",%" PRIx64, (uint64_t)addr, (uint64_t)size); -    } +    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) @@ -2940,7 +3163,7 @@ ProcessGDBRemote::DoWriteMemory (addr_t addr, const void *buf, size_t size, Erro      StreamString packet;      packet.Printf("M%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size); -    packet.PutBytesAsRawHex8(buf, size, lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder()); +    packet.PutBytesAsRawHex8(buf, size, endian::InlHostByteOrder(), endian::InlHostByteOrder());      StringExtractorGDBRemote response;      if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, true) == GDBRemoteCommunication::PacketResult::Success)      { @@ -3377,6 +3600,27 @@ ProcessGDBRemote::DoSignal (int signo)  }  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)  {      Error error; @@ -3401,14 +3645,22 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info          // 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 = NULL; +        const char *hostname = nullptr;          uint16_t port = 0;  #endif -        error = m_gdb_comm.StartDebugserverProcess (hostname, -                                                    port, +        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); +                                                    &port);          if (error.Success ())              m_debugserver_pid = debugserver_launch_info.GetProcessID(); @@ -3653,164 +3905,174 @@ ProcessGDBRemote::AsyncThread (void *arg)      if (log)          log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") thread starting...", __FUNCTION__, arg, process->GetID()); -    Listener listener ("ProcessGDBRemote::AsyncThread");      EventSP event_sp; -    const uint32_t desired_event_mask = eBroadcastBitAsyncContinue | -                                        eBroadcastBitAsyncThreadShouldExit; - -    if (listener.StartListeningForEvents (&process->m_async_broadcaster, desired_event_mask) == desired_event_mask) +    bool done = false; +    while (!done)      { -        listener.StartListeningForEvents (&process->m_gdb_comm, Communication::eBroadcastBitReadThreadDidExit | -                                                                GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify); - -        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.WaitForEvent (NULL, event_sp))          { -            if (log) -                log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID()); -            if (listener.WaitForEvent (NULL, event_sp)) +            const uint32_t event_type = event_sp->GetType(); +            if (event_sp->BroadcasterIs (&process->m_async_broadcaster))              { -                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)                  { -                    if (log) -                        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") Got an event of type: %d...", __FUNCTION__, arg, process->GetID(), event_type); +                    case eBroadcastBitAsyncContinue: +                        { +                            const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event_sp.get()); -                    switch (event_type) -                    { -                        case eBroadcastBitAsyncContinue: +                            if (continue_packet)                              { -                                const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event_sp.get()); +                                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 (continue_packet) +                                if (::strstr (continue_cstr, "vAttach") == NULL) +                                    process->SetPrivateState(eStateRunning); +                                StringExtractorGDBRemote response; + +                                // If in Non-Stop-Mode +                                if (process->GetTarget().GetNonStopModeEnabled())                                  { -                                    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))                                      { -                                        // send the vCont packet -                                        if (!process->GetGDBRemote().SendvContPacket(process, continue_cstr, continue_cstr_len, response)) -                                        { -                                            // Something went wrong -                                            done = true; -                                            break; -                                        } +                                        // 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 (); +                                } +                                // If in All-Stop-Mode +                                else +                                { +                                    StateType stop_state = process->GetGDBRemote().SendContinuePacketAndWaitForResponse (process, continue_cstr, continue_cstr_len, response); -                                        switch (stop_state) -                                        { -                                        case eStateStopped: -                                        case eStateCrashed: -                                        case eStateSuspended: -                                            process->SetLastStopPacket (response); -                                            process->SetPrivateState (stop_state); -                                            break; +                                    // 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 (); -                                        case eStateExited: +                                    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('-') == ';')                                          { -                                            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))                                              { -                                                std::string desc_token; -                                                while (response.GetNameColonValue (desc_token, desc_string)) +                                                if (desc_token == "description")                                                  { -                                                    if (desc_token == "description") -                                                    { -                                                        extractor.GetStringRef().swap(desc_string); -                                                        extractor.SetFilePos(0); -                                                        extractor.GetHexByteString (desc_string); -                                                        desc_cstr = desc_string.c_str(); -                                                    } +                                                    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: +                                        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; +                                    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; +                    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; -                    } +                    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)) +            } +            else if (event_sp->BroadcasterIs (&process->m_gdb_comm)) +            { +                switch (event_type)                  { -                    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; -                        } +                    case Communication::eBroadcastBitReadThreadDidExit: +                        process->SetExitStatus (-1, "lost connection"); +                        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; +                    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; -            } +        } +        else +        { +            if (log) +                log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp) => false", __FUNCTION__, arg, process->GetID()); +            done = true;          }      } @@ -3864,10 +4126,10 @@ ProcessGDBRemote::StartNoticingNewThreads()      }      else      { -        PlatformSP platform_sp (m_target.GetPlatform()); +        PlatformSP platform_sp (GetTarget().GetPlatform());          if (platform_sp)          { -            m_thread_create_bp_sp = platform_sp->SetThreadCreationBreakpoint(m_target); +            m_thread_create_bp_sp = platform_sp->SetThreadCreationBreakpoint(GetTarget());              if (m_thread_create_bp_sp)              {                  if (log && log->GetVerbose()) @@ -3986,6 +4248,9 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_addres      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); @@ -4009,8 +4274,6 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_addres              {                  if (!response.Empty())                  { -                    // The packet has already had the 0x7d xor quoting stripped out at the -                    // GDBRemoteCommunication packet receive level.                      object_sp = StructuredData::ParseJSON (response.GetStringRef());                  }              } @@ -4019,7 +4282,6 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_addres      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.  //  @@ -4113,6 +4375,18 @@ ProcessGDBRemote::GetModuleSpec(const FileSpec& module_file_spec,      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; @@ -4135,15 +4409,15 @@ struct GdbServerTargetInfo  };  bool -ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info) +ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info, ABISP abi_sp)  {      if (!feature_node)          return false; -    uint32_t prev_reg_num = 0; +    uint32_t cur_reg_num = 0;      uint32_t reg_offset = 0; -    feature_node.ForEachChildElementWithName("reg", [&target_info, &dyn_reg_info, &prev_reg_num, ®_offset](const XMLNode ®_node) -> bool { +    feature_node.ForEachChildElementWithName("reg", [&target_info, &dyn_reg_info, &cur_reg_num, ®_offset, &abi_sp](const XMLNode ®_node) -> bool {          std::string gdb_group;          std::string gdb_type;          ConstString reg_name; @@ -4158,19 +4432,19 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot              0,                    // byte size              reg_offset,           // offset              eEncodingUint,        // encoding -            eFormatHex,           // formate +            eFormatHex,           // format              { -                LLDB_INVALID_REGNUM, // GCC reg num +                LLDB_INVALID_REGNUM, // eh_frame reg num                  LLDB_INVALID_REGNUM, // DWARF reg num                  LLDB_INVALID_REGNUM, // generic reg num -                prev_reg_num,        // GDB reg num -                prev_reg_num         // native register number +                cur_reg_num,        // process plugin reg num +                cur_reg_num         // native register number              },              NULL,              NULL          }; -        reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, ®_name, &alt_name, &set_name, &value_regs, &invalidate_regs, &encoding_set, &format_set, ®_info, &prev_reg_num, ®_offset](const llvm::StringRef &name, const llvm::StringRef &value) -> bool { +        reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, ®_name, &alt_name, &set_name, &value_regs, &invalidate_regs, &encoding_set, &format_set, ®_info, &cur_reg_num, ®_offset](const llvm::StringRef &name, const llvm::StringRef &value) -> bool {              if (name == "name")              {                  reg_name.SetString(value); @@ -4192,9 +4466,7 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot                  const uint32_t regnum = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);                  if (regnum != LLDB_INVALID_REGNUM)                  { -                    reg_info.kinds[eRegisterKindGDB] = regnum; -                    reg_info.kinds[eRegisterKindLLDB] = regnum; -                    prev_reg_num = regnum; +                    reg_info.kinds[eRegisterKindProcessPlugin] = regnum;                  }              }              else if (name == "offset") @@ -4240,9 +4512,9 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot                  if (pos != target_info.reg_set_map.end())                      set_name = pos->second.name;              } -            else if (name == "gcc_regnum") +            else if (name == "gcc_regnum" || name == "ehframe_regnum")              { -                reg_info.kinds[eRegisterKindGCC] = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0); +                reg_info.kinds[eRegisterKindEHFrame] = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);              }              else if (name == "dwarf_regnum")              { @@ -4305,7 +4577,8 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot              reg_info.invalidate_regs = invalidate_regs.data();          } -        ++prev_reg_num; +        ++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 @@ -4401,7 +4674,7 @@ ProcessGDBRemote::GetGDBServerRegisterInfo ()              if (feature_node)              { -                ParseRegisters(feature_node, target_info, this->m_register_info); +                ParseRegisters(feature_node, target_info, this->m_register_info, GetABI());              }              for (const auto &include : target_info.includes) @@ -4419,7 +4692,7 @@ ProcessGDBRemote::GetGDBServerRegisterInfo ()                  XMLNode include_feature_node = include_xml_document.GetRootElement("feature");                  if (include_feature_node)                  { -                    ParseRegisters(include_feature_node, target_info, this->m_register_info); +                    ParseRegisters(include_feature_node, target_info, this->m_register_info, GetABI());                  }              }              this->m_register_info.Finalize(GetTarget().GetArchitecture()); @@ -4489,7 +4762,8 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)                  {                      // 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")                  { @@ -4504,13 +4778,15 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)              {                  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:0x08%" PRIx64 ", base:0x08%" PRIx64 ", ld:0x08%" PRIx64 ", name:'%s')", lm, base, ld, name.c_str()); +                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); @@ -4552,15 +4828,19 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)              const XMLNode §ion = 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%" PRIx64 ", name:'%s')", base, name.c_str()); +                log->Printf ("found (base:0x%08" PRIx64 "[%s], name:'%s')", base, (base_is_offset ? "offset" : "absolute"), name.c_str());              }              list.add (module); @@ -4577,7 +4857,7 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)  }  lldb::ModuleSP -ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr) +ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr, bool value_is_offset)  {      Target &target = m_process->GetTarget();      ModuleList &modules = target.GetImages(); @@ -4588,11 +4868,11 @@ ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_a      ModuleSpec module_spec (file, target.GetArchitecture());      if ((module_sp = modules.FindFirstModule (module_spec)))      { -        module_sp->SetLoadAddress (target, base_addr, true, changed); +        module_sp->SetLoadAddress (target, base_addr, value_is_offset, changed);      }      else if ((module_sp = target.GetSharedModule (module_spec)))      { -        module_sp->SetLoadAddress (target, base_addr, true, changed); +        module_sp->SetLoadAddress (target, base_addr, value_is_offset, changed);      }      return module_sp; @@ -4615,10 +4895,12 @@ ProcessGDBRemote::LoadModules ()      {          std::string  mod_name;          lldb::addr_t mod_base; +        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; @@ -4630,7 +4912,7 @@ ProcessGDBRemote::LoadModules ()              marker += 1;          FileSpec file (mod_name.c_str()+marker, true); -        lldb::ModuleSP module_sp = LoadModuleAtAddress (file, mod_base); +        lldb::ModuleSP module_sp = LoadModuleAtAddress (file, mod_base, mod_base_is_offset);          if (module_sp.get())              new_modules.Append (module_sp); @@ -4638,7 +4920,7 @@ ProcessGDBRemote::LoadModules ()      if (new_modules.GetSize() > 0)      { -        Target & target = m_target; +        Target &target = GetTarget();          new_modules.ForEach ([&target](const lldb::ModuleSP module_sp) -> bool          {  | 
