Author: jmolenda
Date: Thu Dec 17 18:45:35 2015
New Revision: 255942

URL: http://llvm.org/viewvc/llvm-project?rev=255942&view=rev
Log:
The lldb side changes to go along with r255711 where a new
"thread-pcs" key is added to the T (questionmark) packet in
gdb-remote protocol so that lldb doesn't need to query the
pc values of every thread before it resumes a process.

The only odd part with this is that I'm sending the pc 
values in big endian order, so we need to know the endianness
of the remote process before we can use them.  All other
register values in gdb-remote protocol are sent in native-endian
format so this requirement doesn't exist.  This addition is a
performance enhancement -- lldb will fall back to querying the
pc of each thread individually if it needs to -- so when
we don't have the byte order for the process yet, we don't
use these values.  Practically speaking, the only way I've 
been able to elicit this condition is for the first
T packet when we attach to a process.

<rdar://problem/21963031> 

Modified:
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
    lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
    lldb/trunk/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h

Modified: 
lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp?rev=255942&r1=255941&r2=255942&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp 
(original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp 
Thu Dec 17 18:45:35 2015
@@ -147,6 +147,52 @@ GDBRemoteRegisterContext::PrivateSetRegi
     return success;
 }
 
+bool
+GDBRemoteRegisterContext::PrivateSetRegisterValue (uint32_t reg, uint64_t 
new_reg_val)
+{
+    const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
+    if (reg_info == NULL)
+        return false;
+
+    // Early in process startup, we can get a thread that has an invalid byte 
order
+    // because the process hasn't been completely set up yet (see the ctor 
where the
+    // byte order is setfrom the process).  If that's the case, we can't set 
the
+    // value here.
+    if (m_reg_data.GetByteOrder() == eByteOrderInvalid)
+    {
+        return false;
+    }
+
+    // Invalidate if needed
+    InvalidateIfNeeded (false);
+
+    DataBufferSP buffer_sp (new DataBufferHeap (&new_reg_val, sizeof 
(new_reg_val)));
+    DataExtractor data (buffer_sp, endian::InlHostByteOrder(), sizeof (void*));
+
+    // If our register context and our register info disagree, which should 
never happen, don't
+    // overwrite past the end of the buffer.
+    if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
+        return false;
+
+    // Grab a pointer to where we are going to put this register
+    uint8_t *dst = 
const_cast<uint8_t*>(m_reg_data.PeekData(reg_info->byte_offset, 
reg_info->byte_size));
+
+    if (dst == NULL)
+        return false;
+
+
+    if (data.CopyByteOrderedData (0,                            // src offset
+                                  reg_info->byte_size,          // src length
+                                  dst,                          // dst
+                                  reg_info->byte_size,          // dst length
+                                  m_reg_data.GetByteOrder()))   // dst byte 
order
+    {
+        SetRegisterIsValid (reg, true);
+        return true;
+    }
+    return false;
+}
+
 // Helper function for GDBRemoteRegisterContext::ReadRegisterBytes().
 bool
 GDBRemoteRegisterContext::GetPrimordialRegister(const RegisterInfo *reg_info,

Modified: 
lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h?rev=255942&r1=255941&r2=255942&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h 
(original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h Thu 
Dec 17 18:45:35 2015
@@ -109,6 +109,9 @@ protected:
     bool
     PrivateSetRegisterValue (uint32_t reg, StringExtractor &response);
     
+    bool
+    PrivateSetRegisterValue (uint32_t reg, uint64_t val);
+
     void
     SetAllRegisterValid (bool b);
 

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=255942&r1=255941&r2=255942&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Thu Dec 
17 18:45:35 2015
@@ -390,6 +390,7 @@ ProcessGDBRemote::ProcessGDBRemote(lldb:
     m_async_listener("lldb.process.gdb-remote.async-listener"),
     m_async_thread_state_mutex(Mutex::eMutexTypeRecursive),
     m_thread_ids (),
+    m_thread_pcs (),
     m_jstopinfo_sp (),
     m_jthreadsinfo_sp (),
     m_continue_c_tids (),
@@ -1751,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)
@@ -1774,6 +1777,26 @@ ProcessGDBRemote::UpdateThreadIDsFromSto
     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 ()
 {
@@ -1786,6 +1809,7 @@ ProcessGDBRemote::UpdateThreadIDList ()
         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)
@@ -1820,6 +1844,20 @@ ProcessGDBRemote::UpdateThreadIDList ()
                 // 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)
                 {
@@ -1887,6 +1925,25 @@ ProcessGDBRemote::UpdateThreadList (Thre
                            __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);
         }
     }
@@ -2447,6 +2504,27 @@ ProcessGDBRemote::SetThreadStopInfo (Str
                     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;
@@ -2624,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.

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h?rev=255942&r1=255941&r2=255942&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h Thu Dec 17 
18:45:35 2015
@@ -288,6 +288,7 @@ protected:
     typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;
     typedef std::map<uint32_t, std::string> ExpeditedRegisterMap;
     tid_collection m_thread_ids; // Thread IDs for all threads. This list gets 
updated after stopping
+    std::vector<lldb::addr_t> m_thread_pcs; // PC values for all the threads.
     StructuredData::ObjectSP m_jstopinfo_sp; // Stop info only for any threads 
that have valid stop infos
     StructuredData::ObjectSP m_jthreadsinfo_sp; // Full stop info, expedited 
registers and memory for all threads if "jThreadsInfo" packet is supported
     tid_collection m_continue_c_tids;                  // 'c' for continue
@@ -384,6 +385,9 @@ protected:
     CalculateThreadStopInfo (ThreadGDBRemote *thread);
 
     size_t
+    UpdateThreadPCsFromStopReplyThreadsValue (std::string &value);
+
+    size_t
     UpdateThreadIDsFromStopReplyThreadsValue (std::string &value);
 
     bool

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp?rev=255942&r1=255941&r2=255942&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp Thu Dec 17 
18:45:35 2015
@@ -313,6 +313,14 @@ ThreadGDBRemote::PrivateSetRegisterValue
 }
 
 bool
+ThreadGDBRemote::PrivateSetRegisterValue (uint32_t reg, uint64_t regval)
+{
+    GDBRemoteRegisterContext *gdb_reg_ctx = 
static_cast<GDBRemoteRegisterContext *>(GetRegisterContext ().get());
+    assert (gdb_reg_ctx);
+    return gdb_reg_ctx->PrivateSetRegisterValue (reg, regval);
+}
+
+bool
 ThreadGDBRemote::CalculateStopInfo ()
 {
     ProcessSP process_sp (GetProcess());

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h?rev=255942&r1=255941&r2=255942&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h Thu Dec 17 
18:45:35 2015
@@ -117,6 +117,10 @@ protected:
                              StringExtractor &response);
 
     bool
+    PrivateSetRegisterValue (uint32_t reg, 
+                             uint64_t regval);
+
+    bool
     CachedQueueInfoIsValid() const
     {
         return m_queue_kind != lldb::eQueueKindUnknown;


_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to