summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/gdb-remote
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote')
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp74
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h8
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp26
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp47
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h8
5 files changed, 113 insertions, 50 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index 978daa7e9ca..eaf91eb98b1 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -39,7 +39,6 @@ GDBRemoteRegisterContext::GDBRemoteRegisterContext
RegisterContext (thread, concrete_frame_idx),
m_reg_info (reg_info),
m_reg_valid (),
- m_reg_valid_stop_id (),
m_reg_data (),
m_read_all_at_once (read_all_at_once)
{
@@ -74,7 +73,7 @@ GDBRemoteRegisterContext::GetGDBThread()
}
void
-GDBRemoteRegisterContext::Invalidate ()
+GDBRemoteRegisterContext::InvalidateAllRegisters ()
{
SetAllRegisterValid (false);
}
@@ -179,25 +178,41 @@ GDBRemoteRegisterContext::ReadRegisterValue (uint32_t reg, Scalar &value)
return false;
}
+void
+GDBRemoteRegisterContext::PrivateSetRegisterValue (uint32_t reg, StringExtractor &response)
+{
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
+ assert (reg_info);
+
+ // Invalidate if needed
+ InvalidateIfNeeded(false);
+
+ const uint32_t reg_byte_size = reg_info->byte_size;
+ const size_t bytes_copied = response.GetHexBytes (const_cast<uint8_t*>(m_reg_data.PeekData(reg_info->byte_offset, reg_byte_size)), reg_byte_size, '\xcc');
+ bool success = bytes_copied == reg_byte_size;
+ if (success)
+ {
+ m_reg_valid[reg] = true;
+ }
+ else if (bytes_copied > 0)
+ {
+ // Only set register is valid to false if we copied some bytes, else
+ // leave it as it was.
+ m_reg_valid[reg] = false;
+ }
+}
+
bool
GDBRemoteRegisterContext::ReadRegisterBytes (uint32_t reg, DataExtractor &data)
{
GDBRemoteCommunication &gdb_comm = GetGDBProcess().GetGDBRemote();
-// FIXME: This check isn't right because IsRunning checks the Public state, but this
-// is work you need to do - for instance in ShouldStop & friends - before the public
-// state has been changed.
-// if (gdb_comm.IsRunning())
-// return false;
- if (m_reg_valid_stop_id != m_thread.GetProcess().GetStopID())
- {
- Invalidate();
- m_reg_valid_stop_id = m_thread.GetProcess().GetStopID();
- }
+ InvalidateIfNeeded(false);
+
const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
assert (reg_info);
- if (m_reg_valid[reg] == false)
+ if (!m_reg_valid[reg])
{
Mutex::Locker locker;
if (gdb_comm.GetSequenceMutex (locker))
@@ -225,28 +240,27 @@ GDBRemoteRegisterContext::ReadRegisterBytes (uint32_t reg, DataExtractor &data)
packet_len = ::snprintf (packet, sizeof(packet), "p%x", reg);
assert (packet_len < (sizeof(packet) - 1));
if (gdb_comm.SendPacketAndWaitForResponse(packet, response, 1, false))
- if (response.GetHexBytes (const_cast<uint8_t*>(m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size)), reg_info->byte_size, '\xcc') == reg_info->byte_size)
- m_reg_valid[reg] = true;
+ PrivateSetRegisterValue (reg, response);
}
}
}
+
+ // Make sure we got a valid register value after reading it
+ if (!m_reg_valid[reg])
+ return false;
}
- bool reg_is_valid = m_reg_valid[reg];
- if (reg_is_valid)
+ if (&data != &m_reg_data)
{
- if (&data != &m_reg_data)
- {
- // If we aren't extracting into our own buffer (which
- // only happens when this function is called from
- // ReadRegisterValue(uint32_t, Scalar&)) then
- // we transfer bytes from our buffer into the data
- // buffer that was passed in
- data.SetByteOrder (m_reg_data.GetByteOrder());
- data.SetData (m_reg_data, reg_info->byte_offset, reg_info->byte_size);
- }
+ // If we aren't extracting into our own buffer (which
+ // only happens when this function is called from
+ // ReadRegisterValue(uint32_t, Scalar&)) then
+ // we transfer bytes from our buffer into the data
+ // buffer that was passed in
+ data.SetByteOrder (m_reg_data.GetByteOrder());
+ data.SetData (m_reg_data, reg_info->byte_offset, reg_info->byte_size);
}
- return reg_is_valid;
+ return true;
}
@@ -323,8 +337,8 @@ GDBRemoteRegisterContext::WriteRegisterBytes (uint32_t reg, DataExtractor &data,
eByteOrderHost);
// Invalidate all register values
- Invalidate ();
-
+ InvalidateIfNeeded (true);
+
if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
packet.GetString().size(),
response,
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
index e20da52527b..72c640ff7a8 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -25,6 +25,7 @@
class ThreadGDBRemote;
class ProcessGDBRemote;
+class StringExtractor;
class GDBRemoteDynamicRegisterInfo
{
@@ -189,7 +190,7 @@ public:
// Subclasses must override these functions
//------------------------------------------------------------------
virtual void
- Invalidate ();
+ InvalidateAllRegisters ();
virtual size_t
GetRegisterCount ();
@@ -225,8 +226,12 @@ public:
ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
protected:
+ friend class ThreadGDBRemote;
void
+ PrivateSetRegisterValue (uint32_t reg, StringExtractor &response);
+
+ void
SetAllRegisterValid (bool b);
ProcessGDBRemote &
@@ -237,7 +242,6 @@ protected:
GDBRemoteDynamicRegisterInfo &m_reg_info;
std::vector<bool> m_reg_valid;
- uint32_t m_reg_valid_stop_id;
lldb_private::DataExtractor m_reg_data;
bool m_read_all_at_once;
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 3775d5b9ff6..cee3e6fd8b9 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -975,9 +975,7 @@ ProcessGDBRemote::UpdateThreadListIfNeeded ()
if (tid != LLDB_INVALID_THREAD_ID)
{
ThreadSP thread_sp (GetThreadList().FindThreadByID (tid, false));
- if (thread_sp)
- thread_sp->GetRegisterContext()->Invalidate();
- else
+ if (!thread_sp)
thread_sp.reset (new ThreadGDBRemote (*this, tid));
curr_thread_list.AddThread(thread_sp);
}
@@ -1014,6 +1012,8 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
uint32_t tid = LLDB_INVALID_THREAD_ID;
addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS;
uint32_t exc_data_count = 0;
+ ThreadSP thread_sp;
+
while (stop_packet.GetNameColonValue(name, value))
{
if (name.compare("metype") == 0)
@@ -1035,6 +1035,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
{
// thread in big endian hex
tid = Args::StringToUInt32 (value.c_str(), 0, 16);
+ thread_sp = m_thread_list.FindThreadByID(tid, false);
}
else if (name.compare("hexname") == 0)
{
@@ -1053,8 +1054,25 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
{
thread_dispatch_qaddr = Args::StringToUInt64 (value.c_str(), 0, 16);
}
+ else if (name.size() == 2 && ::isxdigit(name[0]) && ::isxdigit(name[1]))
+ {
+ // We have a register number that contains an expedited
+ // register value. Lets supply this register to our thread
+ // so it won't have to go and read it.
+ if (thread_sp)
+ {
+ uint32_t reg = Args::StringToUInt32 (name.c_str(), UINT32_MAX, 16);
+
+ if (reg != UINT32_MAX)
+ {
+ StringExtractor reg_value_extractor;
+ // Swap "value" over into "reg_value_extractor"
+ reg_value_extractor.GetStringRef().swap(value);
+ static_cast<ThreadGDBRemote *> (thread_sp.get())->PrivateSetRegisterValue (reg, reg_value_extractor);
+ }
+ }
+ }
}
- ThreadSP thread_sp (m_thread_list.FindThreadByID(tid, false));
if (thread_sp)
{
diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index 091feb9e649..b8108bfd383 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -37,7 +37,8 @@ ThreadGDBRemote::ThreadGDBRemote (ProcessGDBRemote &process, lldb::tid_t tid) :
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 @@ ThreadGDBRemote::WillResume (StateType resume_state)
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 @@ ThreadGDBRemote::GetUnwinder ()
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 @@ ThreadGDBRemote::CreateRegisterContextForFrame (StackFrame *frame)
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 @@ ThreadGDBRemote::RestoreSaveFrameZero (const RegisterCheckpoint &checkpoint)
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 @@ ThreadGDBRemote::RestoreSaveFrameZero (const RegisterCheckpoint &checkpoint)
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 @@ ThreadGDBRemote::GetPrivateStopReason ()
StringExtractorGDBRemote stop_packet;
if (GetGDBProcess().GetGDBRemote().SendPacketAndWaitForResponse(packet, stop_packet, 1, false))
{
- std::string copy(stop_packet.GetStringRef());
GetGDBProcess().SetThreadStopInfo (stop_packet);
}
}
diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
index 37aae88ed34..3bf54afa9be 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
@@ -108,12 +108,20 @@ public:
}
protected:
+
+ friend class ProcessGDBRemote;
+
+ void
+ PrivateSetRegisterValue (uint32_t reg,
+ StringExtractor &response);
+
//------------------------------------------------------------------
// Member variables.
//------------------------------------------------------------------
std::string m_thread_name;
std::string m_dispatch_queue_name;
lldb::addr_t m_thread_dispatch_qaddr;
+ uint32_t m_thread_stop_reason_stop_id;
//------------------------------------------------------------------
// Member variables.
//------------------------------------------------------------------
OpenPOWER on IntegriCloud