Put more smarts into the RegisterContext base class. Now the base class has
a method:
void RegisterContext::InvalidateIfNeeded (bool force);
Each time this function is called, when "force" is false, it will only call
the pure virtual "virtual void RegisterContext::InvalideAllRegisters()" if
the register context's stop ID doesn't match that of the process. When the
stop ID doesn't match, or "force" is true, the base class will clear its
cached registers and the RegisterContext will update its stop ID to match
that of the process. This helps make it easier to correctly flush the register
context (possibly from multiple locations depending on when and where new
registers are availabe) without inadvertently clearing the register cache
when it doesn't need to be.
Modified the ProcessGDBRemote plug-in to be much more efficient when it comes
to:
- caching the expedited registers in the stop reply packets (we were ignoring
these before and it was causing us to read at least three registers every
time we stopped that were already supplied in the stop reply packet).
- When a thread has no stop reason, don't keep asking for the thread stopped
info. Prior to this fix we would continually send a qThreadStopInfo packet
over and over when any thread stop info was requested. We now note the stop
ID that the stop info was requested for and avoid multiple requests.
Cleaned up some of the expression code to not look for ClangExpressionVariable
objects up by name since they are now shared pointers and we can just look for
the exact pointer match and avoid possible errors.
Fixed an bug in the ValueObject code that would cause children to not be
displayed.
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@123127 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index 091feb9..b8108bf 100644
--- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -37,7 +37,8 @@
Thread(process, tid),
m_thread_name (),
m_dispatch_queue_name (),
- m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS)
+ m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS),
+ m_thread_stop_reason_stop_id (0)
{
// ProcessGDBRemoteLog::LogIf(GDBR_LOG_THREAD | GDBR_LOG_VERBOSE, "ThreadGDBRemote::ThreadGDBRemote ( pid = %i, tid = 0x%4.4x, )", m_process.GetID(), GetID());
ProcessGDBRemoteLog::LogIf(GDBR_LOG_THREAD, "%p: ThreadGDBRemote::ThreadGDBRemote (pid = %i, tid = 0x%4.4x)", this, m_process.GetID(), GetID());
@@ -116,14 +117,18 @@
void
ThreadGDBRemote::RefreshStateAfterStop()
{
- // Invalidate all registers in our register context
- GetRegisterContext()->Invalidate();
+ // Invalidate all registers in our register context. We don't set "force" to
+ // true because the stop reply packet might have had some register values
+ // that were expedited and these will already be copied into the register
+ // context by the time this function gets called. The GDBRemoteRegisterContext
+ // class has been made smart enough to detect when it needs to invalidate
+ // which registers are valid by putting hooks in the register read and
+ // register supply functions where they check the process stop ID and do
+ // the right thing.
+ const bool force = false;
+ GetRegisterContext()->InvalidateIfNeeded (force);
}
-// Whether to use the new native unwinder (UnwindLLDB) or the libunwind-remote based unwinder for
-// stack walks on i386/x86_64
-#define USE_NATIVE_UNWINDER
-
Unwind *
ThreadGDBRemote::GetUnwinder ()
{
@@ -132,11 +137,7 @@
const ArchSpec target_arch (GetProcess().GetTarget().GetArchitecture ());
if (target_arch == ArchSpec("x86_64") || target_arch == ArchSpec("i386"))
{
-#if defined (USE_NATIVE_UNWINDER)
m_unwinder_ap.reset (new UnwindLLDB (*this));
-#else
- m_unwinder_ap.reset (new UnwindLibUnwind (*this, GetGDBProcess().GetLibUnwindAddressSpace()));
-#endif
}
else
{
@@ -198,6 +199,14 @@
return reg_ctx_sp;
}
+void
+ThreadGDBRemote::PrivateSetRegisterValue (uint32_t reg, StringExtractor &response)
+{
+ GDBRemoteRegisterContext *gdb_reg_ctx = static_cast<GDBRemoteRegisterContext *>(GetRegisterContext ().get());
+ assert (gdb_reg_ctx);
+ gdb_reg_ctx->PrivateSetRegisterValue (reg, response);
+}
+
bool
ThreadGDBRemote::SaveFrameZeroState (RegisterCheckpoint &checkpoint)
{
@@ -217,7 +226,7 @@
if (frame_sp)
{
bool ret = frame_sp->GetRegisterContext()->WriteAllRegisterValues (checkpoint.GetData());
- frame_sp->GetRegisterContext()->Invalidate();
+ frame_sp->GetRegisterContext()->InvalidateIfNeeded(true);
ClearStackFrames();
return ret;
}
@@ -227,8 +236,19 @@
lldb::StopInfoSP
ThreadGDBRemote::GetPrivateStopReason ()
{
- if (m_actual_stop_info_sp.get() == NULL || m_actual_stop_info_sp->IsValid() == false)
+ const uint32_t process_stop_id = GetProcess().GetStopID();
+ if (m_thread_stop_reason_stop_id != process_stop_id ||
+ (m_actual_stop_info_sp && !m_actual_stop_info_sp->IsValid()))
{
+ // If GetGDBProcess().SetThreadStopInfo() doesn't find a stop reason
+ // for this thread, then m_actual_stop_info_sp will not ever contain
+ // a valid stop reason and the "m_actual_stop_info_sp->IsValid() == false"
+ // check will never be able to tell us if we have the correct stop info
+ // for this thread and we will continually send qThreadStopInfo packets
+ // down to the remote GDB server, so we need to keep our own notion
+ // of the stop ID that m_actual_stop_info_sp is valid for (even if it
+ // contains nothing). We use m_thread_stop_reason_stop_id for this below.
+ m_thread_stop_reason_stop_id = process_stop_id;
m_actual_stop_info_sp.reset();
char packet[256];
@@ -236,7 +256,6 @@
StringExtractorGDBRemote stop_packet;
if (GetGDBProcess().GetGDBRemote().SendPacketAndWaitForResponse(packet, stop_packet, 1, false))
{
- std::string copy(stop_packet.GetStringRef());
GetGDBProcess().SetThreadStopInfo (stop_packet);
}
}