summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/source/Expression/ClangUserExpression.cpp7
-rw-r--r--lldb/source/Expression/ClangUtilityFunction.cpp10
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp1
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h15
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp54
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp9
-rw-r--r--lldb/source/Target/ThreadList.cpp2
-rw-r--r--lldb/source/Utility/StringExtractor.h8
-rw-r--r--lldb/tools/debugserver/source/DNBThreadResumeActions.h7
-rw-r--r--lldb/tools/debugserver/source/MacOSX/MachProcess.cpp35
-rw-r--r--lldb/tools/debugserver/source/MacOSX/MachProcess.h6
-rw-r--r--lldb/tools/debugserver/source/MacOSX/MachThread.cpp91
-rw-r--r--lldb/tools/debugserver/source/MacOSX/MachThread.h7
-rw-r--r--lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp2
-rw-r--r--lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp2
-rw-r--r--lldb/tools/debugserver/source/RNBRemote.cpp196
-rw-r--r--lldb/tools/debugserver/source/RNBRemote.h21
17 files changed, 301 insertions, 172 deletions
diff --git a/lldb/source/Expression/ClangUserExpression.cpp b/lldb/source/Expression/ClangUserExpression.cpp
index 13d5ab9c96b..c435136e2e6 100644
--- a/lldb/source/Expression/ClangUserExpression.cpp
+++ b/lldb/source/Expression/ClangUserExpression.cpp
@@ -20,6 +20,7 @@
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Expression/ASTResultSynthesizer.h"
@@ -365,6 +366,12 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString());
return false;
}
+
+#if 0
+ // jingham: look here
+ StreamFile logfile ("/tmp/exprs.txt", "a");
+ logfile.Printf("0x%16.16llx: thread = 0x%4.4x, expr = '%s'\n", m_jit_addr, exe_ctx.thread ? exe_ctx.thread->GetID() : -1, m_expr_text.c_str());
+#endif
if (log)
{
diff --git a/lldb/source/Expression/ClangUtilityFunction.cpp b/lldb/source/Expression/ClangUtilityFunction.cpp
index f682e360778..d3ede6b4a34 100644
--- a/lldb/source/Expression/ClangUtilityFunction.cpp
+++ b/lldb/source/Expression/ClangUtilityFunction.cpp
@@ -17,6 +17,7 @@
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
#include "lldb/Expression/ClangExpressionDeclMap.h"
#include "lldb/Expression/ClangExpressionParser.h"
#include "lldb/Expression/ClangUtilityFunction.h"
@@ -124,6 +125,15 @@ ClangUtilityFunction::Install (Stream &error_stream,
Error jit_error = parser.MakeJIT (m_jit_begin, m_jit_end, exe_ctx);
+#if 0
+ // jingham: look here
+ StreamFile logfile ("/tmp/exprs.txt", "a");
+ logfile.Printf ("0x%16.16llx: func = %s, source =\n%s\n",
+ m_jit_begin,
+ m_function_name.c_str(),
+ m_function_text.c_str());
+#endif
+
m_expr_decl_map->DidParse();
m_expr_decl_map.reset();
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 5925812f7f3..1a7b27b40f9 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -34,6 +34,7 @@ using namespace lldb_private;
GDBRemoteCommunication::GDBRemoteCommunication() :
Communication("gdb-remote.packets"),
m_send_acks (true),
+ m_thread_suffix_supported (false),
m_rx_packet_listener ("gdbremote.rx_packet"),
m_sequence_mutex (Mutex::eMutexTypeRecursive),
m_is_running (false),
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index 7bc795dcf7a..c0d8685db39 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -100,6 +100,18 @@ public:
}
bool
+ GetThreadSuffixSupported () const
+ {
+ return m_thread_suffix_supported;
+ }
+
+ void
+ SetThreadSuffixSupported (bool enabled)
+ {
+ m_thread_suffix_supported = enabled;
+ }
+
+ bool
SendAsyncSignal (int signo);
bool
@@ -244,7 +256,8 @@ protected:
//------------------------------------------------------------------
// Classes that inherit from GDBRemoteCommunication can see and modify these
//------------------------------------------------------------------
- bool m_send_acks;
+ bool m_send_acks:1,
+ m_thread_suffix_supported:1;
lldb_private::Listener m_rx_packet_listener;
lldb_private::Mutex m_sequence_mutex; // Restrict access to sending/receiving packets to a single thread at a time
lldb_private::Predicate<bool> m_is_running;
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index eaf91eb98b1..2c00b9a8431 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -217,15 +217,19 @@ GDBRemoteRegisterContext::ReadRegisterBytes (uint32_t reg, DataExtractor &data)
Mutex::Locker locker;
if (gdb_comm.GetSequenceMutex (locker))
{
- if (GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
+ const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
+ if (thread_suffix_supported || GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
{
- char packet[32];
+ char packet[64];
StringExtractorGDBRemote response;
- int packet_len;
+ int packet_len = 0;
if (m_read_all_at_once)
{
// Get all registers in one packet
- packet_len = ::snprintf (packet, sizeof(packet), "g");
+ if (thread_suffix_supported)
+ packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4x;", m_thread.GetID());
+ else
+ packet_len = ::snprintf (packet, sizeof(packet), "g");
assert (packet_len < (sizeof(packet) - 1));
if (gdb_comm.SendPacketAndWaitForResponse(packet, response, 1, false))
{
@@ -237,7 +241,10 @@ GDBRemoteRegisterContext::ReadRegisterBytes (uint32_t reg, DataExtractor &data)
else
{
// Get each register individually
- packet_len = ::snprintf (packet, sizeof(packet), "p%x", reg);
+ if (thread_suffix_supported)
+ packet_len = ::snprintf (packet, sizeof(packet), "p%x;thread:%4.4x;", reg, m_thread.GetID());
+ else
+ packet_len = ::snprintf (packet, sizeof(packet), "p%x", reg);
assert (packet_len < (sizeof(packet) - 1));
if (gdb_comm.SendPacketAndWaitForResponse(packet, response, 1, false))
PrivateSetRegisterValue (reg, response);
@@ -319,7 +326,8 @@ GDBRemoteRegisterContext::WriteRegisterBytes (uint32_t reg, DataExtractor &data,
Mutex::Locker locker;
if (gdb_comm.GetSequenceMutex (locker))
{
- if (GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
+ const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
+ if (thread_suffix_supported || GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
{
uint32_t offset, end_offset;
StreamString packet;
@@ -336,6 +344,9 @@ GDBRemoteRegisterContext::WriteRegisterBytes (uint32_t reg, DataExtractor &data,
eByteOrderHost,
eByteOrderHost);
+ if (thread_suffix_supported)
+ packet.Printf (";thread:%4.4x;", m_thread.GetID());
+
// Invalidate all register values
InvalidateIfNeeded (true);
@@ -361,6 +372,9 @@ GDBRemoteRegisterContext::WriteRegisterBytes (uint32_t reg, DataExtractor &data,
eByteOrderHost,
eByteOrderHost);
+ if (thread_suffix_supported)
+ packet.Printf (";thread:%4.4x;", m_thread.GetID());
+
// Invalidate just this register
m_reg_valid[reg] = false;
if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
@@ -391,16 +405,31 @@ GDBRemoteRegisterContext::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
Mutex::Locker locker;
if (gdb_comm.GetSequenceMutex (locker))
{
- if (GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
+ char packet[32];
+ const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
+ if (thread_suffix_supported || GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
{
- if (gdb_comm.SendPacketAndWaitForResponse("g", response, 1, false))
+ int packet_len = 0;
+ if (thread_suffix_supported)
+ packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4x", m_thread.GetID());
+ else
+ packet_len = ::snprintf (packet, sizeof(packet), "g");
+ assert (packet_len < (sizeof(packet) - 1));
+
+ if (gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, 1, false))
{
if (response.IsErrorPacket())
return false;
-
+
response.GetStringRef().insert(0, 1, 'G');
- data_sp.reset (new DataBufferHeap(response.GetStringRef().c_str(),
- response.GetStringRef().size()));
+ if (thread_suffix_supported)
+ {
+ char thread_id_cstr[64];
+ ::snprintf (thread_id_cstr, sizeof(thread_id_cstr), ";thread:%4.4x;", m_thread.GetID());
+ response.GetStringRef().append (thread_id_cstr);
+ }
+ data_sp.reset (new DataBufferHeap (response.GetStringRef().c_str(),
+ response.GetStringRef().size()));
return true;
}
}
@@ -419,7 +448,8 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data
Mutex::Locker locker;
if (gdb_comm.GetSequenceMutex (locker))
{
- if (GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
+ const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
+ if (thread_suffix_supported || GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
{
if (gdb_comm.SendPacketAndWaitForResponse((const char *)data_sp->GetBytes(),
data_sp->GetByteSize(),
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 80580f8dddc..26aa4564281 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -554,6 +554,13 @@ ProcessGDBRemote::ConnectToDebugserver (const char *host_port)
if (response.IsOKPacket())
m_gdb_comm.SetAckMode (false);
}
+
+ if (m_gdb_comm.SendPacketAndWaitForResponse("QThreadSuffixSupported", response, 1, false))
+ {
+ if (response.IsOKPacket())
+ m_gdb_comm.SetThreadSuffixSupported (true);
+ }
+
}
return error;
}
@@ -2021,7 +2028,7 @@ ProcessGDBRemote::SetCurrentGDBRemoteThreadForRun (int tid)
return true;
char packet[32];
- const int packet_len = ::snprintf (packet, sizeof(packet), "Hg%x", tid);
+ const int packet_len = ::snprintf (packet, sizeof(packet), "Hc%x", tid);
assert (packet_len + 1 < sizeof(packet));
StringExtractorGDBRemote response;
if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, 2, false))
diff --git a/lldb/source/Target/ThreadList.cpp b/lldb/source/Target/ThreadList.cpp
index a4004ea9ee2..e5056326b1c 100644
--- a/lldb/source/Target/ThreadList.cpp
+++ b/lldb/source/Target/ThreadList.cpp
@@ -340,6 +340,7 @@ ThreadList::ShouldReportRun (Event *event_ptr)
void
ThreadList::Clear()
{
+ Mutex::Locker locker(m_threads_mutex);
m_stop_id = 0;
m_threads.clear();
m_selected_tid = LLDB_INVALID_THREAD_ID;
@@ -504,6 +505,7 @@ ThreadList::WillResume ()
void
ThreadList::DidResume ()
{
+ Mutex::Locker locker(m_threads_mutex);
collection::iterator pos, end = m_threads.end();
for (pos = m_threads.begin(); pos != end; ++pos)
{
diff --git a/lldb/source/Utility/StringExtractor.h b/lldb/source/Utility/StringExtractor.h
index ed67b926c2a..bb65f707f7d 100644
--- a/lldb/source/Utility/StringExtractor.h
+++ b/lldb/source/Utility/StringExtractor.h
@@ -113,6 +113,14 @@ public:
size_t
GetHexByteString (std::string &str);
+ const char *
+ Peek ()
+ {
+ if (m_index < m_packet.size())
+ return m_packet.c_str() + m_index;
+ return NULL;
+ }
+
protected:
//------------------------------------------------------------------
// For StringExtractor only
diff --git a/lldb/tools/debugserver/source/DNBThreadResumeActions.h b/lldb/tools/debugserver/source/DNBThreadResumeActions.h
index f3fb8de6a82..81c7c43b722 100644
--- a/lldb/tools/debugserver/source/DNBThreadResumeActions.h
+++ b/lldb/tools/debugserver/source/DNBThreadResumeActions.h
@@ -85,6 +85,13 @@ public:
{
return m_actions.size();
}
+
+ void
+ Clear()
+ {
+ m_actions.clear();
+ m_signal_handled.clear();
+ }
protected:
std::vector<DNBThreadResumeAction> m_actions;
diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp b/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp
index 10f86f91225..05298168037 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp
+++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp
@@ -101,6 +101,7 @@ MachProcess::MachProcess() :
m_stdio_thread (0),
m_stdio_mutex (PTHREAD_MUTEX_RECURSIVE),
m_stdout_data (),
+ m_thread_actions (),
m_thread_list (),
m_exception_messages (),
m_exception_messages_mutex (PTHREAD_MUTEX_RECURSIVE),
@@ -314,7 +315,8 @@ MachProcess::Resume (const DNBThreadResumeActions& thread_actions)
if (CanResume(state))
{
- PrivateResume(thread_actions);
+ m_thread_actions = thread_actions;
+ PrivateResume();
return true;
}
else if (state == eStateRunning)
@@ -337,7 +339,8 @@ MachProcess::Kill (const struct timespec *timeout_abstime)
DNBError err;
err.SetErrorToErrno();
DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Kill() DoSIGSTOP() ::ptrace (PT_KILL, pid=%u, 0, 0) => 0x%8.8x (%s)", err.Error(), err.AsString());
- PrivateResume (DNBThreadResumeActions (eStateRunning, 0));
+ m_thread_actions = DNBThreadResumeActions (eStateRunning, 0);
+ PrivateResume ();
return true;
}
@@ -392,7 +395,8 @@ MachProcess::DoSIGSTOP (bool clear_bps_and_wps, uint32_t *thread_idx_ptr)
// No threads were stopped with a SIGSTOP, we need to run and halt the
// process with a signal
DNBLogThreadedIf(LOG_PROCESS, "MachProcess::DoSIGSTOP() state = %s -- resuming process", DNBStateAsString (state));
- PrivateResume (DNBThreadResumeActions (eStateRunning, 0));
+ m_thread_actions = DNBThreadResumeActions (eStateRunning, 0);
+ PrivateResume ();
// Reset the event that says we were indeed running
m_events.ResetEvents(eEventProcessRunningStateChanged);
@@ -428,20 +432,19 @@ MachProcess::Detach()
DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Detach() DoSIGSTOP() returned %s", DNBStateAsString(state));
{
- DNBThreadResumeActions thread_actions;
+ m_thread_actions.Clear();
DNBThreadResumeAction thread_action;
thread_action.tid = m_thread_list.ThreadIDAtIndex (thread_idx);
thread_action.state = eStateRunning;
thread_action.signal = -1;
thread_action.addr = INVALID_NUB_ADDRESS;
- thread_actions.Append (thread_action);
-
- thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, 0);
+ m_thread_actions.Append (thread_action);
+ m_thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, 0);
PTHREAD_MUTEX_LOCKER (locker, m_exception_messages_mutex);
- ReplyToAllExceptions (thread_actions);
+ ReplyToAllExceptions ();
}
@@ -597,7 +600,7 @@ MachProcess::WriteMemory (nub_addr_t addr, nub_size_t size, const void *buf)
void
-MachProcess::ReplyToAllExceptions (const DNBThreadResumeActions& thread_actions)
+MachProcess::ReplyToAllExceptions ()
{
PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex);
if (m_exception_messages.empty() == false)
@@ -610,13 +613,13 @@ MachProcess::ReplyToAllExceptions (const DNBThreadResumeActions& thread_actions)
DNBLogThreadedIf(LOG_EXCEPTIONS, "Replying to exception %d...", std::distance(begin, pos));
int thread_reply_signal = 0;
- const DNBThreadResumeAction *action = thread_actions.GetActionForThread (pos->state.thread_port, false);
+ const DNBThreadResumeAction *action = m_thread_actions.GetActionForThread (pos->state.thread_port, false);
if (action)
{
thread_reply_signal = action->signal;
if (thread_reply_signal)
- thread_actions.SetSignalHandledForThread (pos->state.thread_port);
+ m_thread_actions.SetSignalHandledForThread (pos->state.thread_port);
}
DNBError err (pos->Reply(this, thread_reply_signal));
@@ -630,20 +633,20 @@ MachProcess::ReplyToAllExceptions (const DNBThreadResumeActions& thread_actions)
}
}
void
-MachProcess::PrivateResume (const DNBThreadResumeActions& thread_actions)
+MachProcess::PrivateResume ()
{
PTHREAD_MUTEX_LOCKER (locker, m_exception_messages_mutex);
- ReplyToAllExceptions (thread_actions);
+ ReplyToAllExceptions ();
// bool stepOverBreakInstruction = step;
// Let the thread prepare to resume and see if any threads want us to
// step over a breakpoint instruction (ProcessWillResume will modify
// the value of stepOverBreakInstruction).
- m_thread_list.ProcessWillResume (this, thread_actions);
+ m_thread_list.ProcessWillResume (this, m_thread_actions);
// Set our state accordingly
- if (thread_actions.NumActionsWithState(eStateStepping))
+ if (m_thread_actions.NumActionsWithState(eStateStepping))
SetState (eStateStepping);
else
SetState (eStateRunning);
@@ -1100,7 +1103,7 @@ MachProcess::ExceptionMessageBundleComplete()
else
{
// Resume without checking our current state.
- PrivateResume (DNBThreadResumeActions (eStateRunning, 0));
+ PrivateResume ();
}
}
else
diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.h b/lldb/tools/debugserver/source/MacOSX/MachProcess.h
index 04ad02eb634..8866187b56a 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachProcess.h
+++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.h
@@ -17,6 +17,7 @@
#include "DNBDefs.h"
#include "DNBBreakpoint.h"
#include "DNBError.h"
+#include "DNBThreadResumeActions.h"
//#include "MachDYLD.h"
#include "MachException.h"
#include "MachVMMemory.h"
@@ -219,8 +220,8 @@ private:
eMachProcessFlagsUsingSBS = (1 << 1)
};
void Clear ();
- void ReplyToAllExceptions (const DNBThreadResumeActions& thread_actions);
- void PrivateResume (const DNBThreadResumeActions& thread_actions);
+ void ReplyToAllExceptions ();
+ void PrivateResume ();
nub_size_t RemoveTrapsFromBuffer (nub_addr_t addr, nub_size_t size, uint8_t *buf) const;
uint32_t Flags () const { return m_flags; }
@@ -239,6 +240,7 @@ private:
pthread_t m_stdio_thread; // Thread ID for the thread that watches for child process stdio
PThreadMutex m_stdio_mutex; // Multithreaded protection for stdio
std::string m_stdout_data;
+ DNBThreadResumeActions m_thread_actions; // The thread actions for the current MachProcess::Resume() call
MachException::Message::collection
m_exception_messages; // A collection of exception messages caught when listening to the exception port
PThreadMutex m_exception_messages_mutex; // Multithreaded protection for m_exception_messages
diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp
index 7890c069a77..003a58b79d6 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp
+++ b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp
@@ -339,6 +339,12 @@ MachThread::ThreadWillResume(const DNBThreadResumeAction *thread_action)
m_stop_exception.Clear();
}
+nub_break_t
+MachThread::CurrentBreakpoint()
+{
+ return m_process->Breakpoints().FindIDByAddress(GetPC());
+}
+
bool
MachThread::ShouldStop(bool &step_more)
{
@@ -394,14 +400,18 @@ MachThread::ShouldStop(bool &step_more)
bool
MachThread::IsStepping()
{
+#if ENABLE_AUTO_STEPPING_OVER_BP
// Return true if this thread is currently being stepped.
// MachThread::ThreadWillResume currently determines this by looking if we
// have been asked to single step, or if we are at a breakpoint instruction
// and have been asked to resume. In the latter case we need to disable the
// breakpoint we are at, single step, re-enable and continue.
nub_state_t state = GetState();
- return (state == eStateStepping) ||
- (state == eStateRunning && NUB_BREAK_ID_IS_VALID(CurrentBreakpoint()));
+ return ((state == eStateStepping) ||
+ (state == eStateRunning && NUB_BREAK_ID_IS_VALID(CurrentBreakpoint())));
+#else
+ return GetState() == eStateStepping;
+#endif
}
@@ -430,6 +440,7 @@ MachThread::ThreadDidStop()
// Update the basic information for a thread
MachThread::GetBasicInfo(m_tid, &m_basicInfo);
+#if ENABLE_AUTO_STEPPING_OVER_BP
// See if we were at a breakpoint when we last resumed that we disabled,
// re-enable it.
nub_break_t breakID = CurrentBreakpoint();
@@ -469,10 +480,12 @@ MachThread::ThreadDidStop()
SetState(eStateStopped);
}
}
-
-
- SetCurrentBreakpoint(INVALID_NUB_BREAK_ID);
-
+#else
+ if (m_basicInfo.suspend_count > 0)
+ SetState(eStateSuspended);
+ else
+ SetState(eStateStopped);
+#endif
return true;
}
@@ -496,30 +509,27 @@ MachThread::NotifyException(MachException::Data& exc)
if (!handled)
{
handled = true;
- nub_addr_t pc = GetPC();
- nub_break_t breakID = m_process->Breakpoints().FindIDByAddress(pc);
- SetCurrentBreakpoint(breakID);
- switch (exc.exc_type)
- {
- case EXC_BAD_ACCESS:
- break;
- case EXC_BAD_INSTRUCTION:
- break;
- case EXC_ARITHMETIC:
- break;
- case EXC_EMULATION:
- break;
- case EXC_SOFTWARE:
- break;
- case EXC_BREAKPOINT:
- break;
- case EXC_SYSCALL:
- break;
- case EXC_MACH_SYSCALL:
- break;
- case EXC_RPC_ALERT:
- break;
- }
+// switch (exc.exc_type)
+// {
+// case EXC_BAD_ACCESS:
+// break;
+// case EXC_BAD_INSTRUCTION:
+// break;
+// case EXC_ARITHMETIC:
+// break;
+// case EXC_EMULATION:
+// break;
+// case EXC_SOFTWARE:
+// break;
+// case EXC_BREAKPOINT:
+// break;
+// case EXC_SYSCALL:
+// break;
+// case EXC_MACH_SYSCALL:
+// break;
+// case EXC_RPC_ALERT:
+// break;
+// }
}
return handled;
}
@@ -658,27 +668,6 @@ MachThread::DisableHardwareWatchpoint (const DNBBreakpoint *wp)
return false;
}
-
-void
-MachThread::NotifyBreakpointChanged (const DNBBreakpoint *bp)
-{
- nub_break_t breakID = bp->GetID();
- if (bp->IsEnabled())
- {
- if (bp->Address() == GetPC())
- {
- SetCurrentBreakpoint(breakID);
- }
- }
- else
- {
- if (CurrentBreakpoint() == breakID)
- {
- SetCurrentBreakpoint(INVALID_NUB_BREAK_ID);
- }
- }
-}
-
bool
MachThread::GetIdentifierInfo ()
{
diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.h b/lldb/tools/debugserver/source/MacOSX/MachThread.h
index 0b2a8bf1ff9..e7e18fe262c 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachThread.h
+++ b/lldb/tools/debugserver/source/MacOSX/MachThread.h
@@ -60,8 +60,7 @@ public:
bool SetPC(uint64_t value); // Set program counter
uint64_t GetSP(uint64_t failValue = INVALID_NUB_ADDRESS); // Get stack pointer
- nub_break_t CurrentBreakpoint() const { return m_breakID; }
- void SetCurrentBreakpoint(nub_break_t breakID) { m_breakID = breakID; }
+ nub_break_t CurrentBreakpoint();
uint32_t EnableHardwareBreakpoint (const DNBBreakpoint *breakpoint);
uint32_t EnableHardwareWatchpoint (const DNBBreakpoint *watchpoint);
bool DisableHardwareBreakpoint (const DNBBreakpoint *breakpoint);
@@ -88,7 +87,9 @@ public:
bool SetRegisterValue ( uint32_t reg_set_idx, uint32_t reg_idx, const DNBRegisterValue *reg_value );
nub_size_t GetRegisterContext (void *buf, nub_size_t buf_len);
nub_size_t SetRegisterContext (const void *buf, nub_size_t buf_len);
- void NotifyBreakpointChanged (const DNBBreakpoint *bp);
+ void NotifyBreakpointChanged (const DNBBreakpoint *bp)
+ {
+ }
bool IsUserReady();
struct thread_basic_info *
diff --git a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp
index 1222b809904..411e91426e1 100644
--- a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp
+++ b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp
@@ -428,8 +428,6 @@ DNBArchImplI386::NotifyException(MachException::Data& exc)
// Write the new PC back out
SetGPRState ();
}
-
- m_thread->SetCurrentBreakpoint(breakID);
}
return true;
}
diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp
index fde3be6ab5d..ce0e9c2c579 100644
--- a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp
+++ b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp
@@ -355,8 +355,6 @@ DNBArchImplX86_64::NotifyException(MachException::Data& exc)
// Write the new PC back out
SetGPRState ();
}
-
- m_thread->SetCurrentBreakpoint(breakID);
}
return true;
}
diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp
index 7fa05073d72..7ce808dbab4 100644
--- a/lldb/tools/debugserver/source/RNBRemote.cpp
+++ b/lldb/tools/debugserver/source/RNBRemote.cpp
@@ -76,6 +76,7 @@ RNBRemote::RNBRemote (bool use_native_regs, const char *arch) :
m_max_payload_size(DEFAULT_GDB_REMOTE_PROTOCOL_BUFSIZE - 4),
m_extended_mode(false),
m_noack_mode(false),
+ m_thread_suffix_supported (false),
m_use_native_regs (use_native_regs)
{
DNBLogThreadedIf (LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__);
@@ -170,12 +171,13 @@ RNBRemote::CreatePacketTable ()
t.push_back (Packet (query_step_packet_supported, &RNBRemote::HandlePacket_qStepPacketSupported,NULL, "qStepPacketSupported", "Replys with OK if the 's' packet is supported."));
t.push_back (Packet (query_host_info, &RNBRemote::HandlePacket_qHostInfo, NULL, "qHostInfo", "Replies with multiple 'key:value;' tuples appended to each other."));
// t.push_back (Packet (query_symbol_lookup, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "qSymbol", "Notify that host debugger is ready to do symbol lookups"));
- t.push_back (Packet (start_noack_mode, &RNBRemote::HandlePacket_Q , NULL, "QStartNoAckMode", "Request that " DEBUGSERVER_PROGRAM_NAME " stop acking remote protocol packets"));
- t.push_back (Packet (set_logging_mode, &RNBRemote::HandlePacket_Q , NULL, "QSetLogging:", "Request that the " DEBUGSERVER_PROGRAM_NAME " set its logging mode bits"));
- t.push_back (Packet (set_max_packet_size, &RNBRemote::HandlePacket_Q , NULL, "QSetMaxPacketSize:", "Tell " DEBUGSERVER_PROGRAM_NAME " the max sized packet gdb can handle"));
- t.push_back (Packet (set_max_payload_size, &RNBRemote::HandlePacket_Q , NULL, "QSetMaxPayloadSize:", "Tell " DEBUGSERVER_PROGRAM_NAME " the max sized payload gdb can handle"));
- t.push_back (Packet (set_environment_variable, &RNBRemote::HandlePacket_Q , NULL, "QEnvironment:", "Add an environment variable to the inferior's environment"));
- t.push_back (Packet (set_disable_aslr, &RNBRemote::HandlePacket_Q , NULL, "QSetDisableASLR:", "Set wether to disable ASLR when launching the process with the set argv ('A') packet"));
+ t.push_back (Packet (start_noack_mode, &RNBRemote::HandlePacket_QStartNoAckMode , NULL, "QStartNoAckMode", "Request that " DEBUGSERVER_PROGRAM_NAME " stop acking remote protocol packets"));
+ t.push_back (Packet (prefix_reg_packets_with_tid, &RNBRemote::HandlePacket_QThreadSuffixSupported , NULL, "QThreadSuffixSupported", "Check if thread specifc packets (register packets 'g', 'G', 'p', and 'P') support having the thread ID appended to the end of the command"));
+ t.push_back (Packet (set_logging_mode, &RNBRemote::HandlePacket_QSetLogging , NULL, "QSetLogging:", "Check if register packets ('g', 'G', 'p', and 'P' support having the thread ID prefix"));
+ t.push_back (Packet (set_max_packet_size, &RNBRemote::HandlePacket_QSetMaxPacketSize , NULL, "QSetMaxPacketSize:", "Tell " DEBUGSERVER_PROGRAM_NAME " the max sized packet gdb can handle"));
+ t.push_back (Packet (set_max_payload_size, &RNBRemote::HandlePacket_QSetMaxPayloadSize , NULL, "QSetMaxPayloadSize:", "Tell " DEBUGSERVER_PROGRAM_NAME " the max sized payload gdb can handle"));
+ t.push_back (Packet (set_environment_variable, &RNBRemote::HandlePacket_QEnvironment , NULL, "QEnvironment:", "Add an environment variable to the inferior's environment"));
+ t.push_back (Packet (set_disable_aslr, &RNBRemote::HandlePacket_QSetDisableASLR , NULL, "QSetDisableASLR:", "Set wether to disable ASLR when launching the process with the set argv ('A') packet"));
// t.push_back (Packet (pass_signals_to_inferior, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "QPassSignals:", "Specify which signals are passed to the inferior"));
t.push_back (Packet (allocate_memory, &RNBRemote::HandlePacket_AllocateMemory, NULL, "_M", "Allocate memory in the inferior process."));
t.push_back (Packet (deallocate_memory, &RNBRemote::HandlePacket_DeallocateMemory, NULL, "_m", "Deallocate memory in the inferior process."));
@@ -1702,104 +1704,105 @@ set_logging (const char *p)
return rnb_success;
}
-
+rnb_err_t
+RNBRemote::HandlePacket_QThreadSuffixSupported (const char *p)
+{
+ m_thread_suffix_supported = true;
+ return SendPacket ("OK");
+}
rnb_err_t
-RNBRemote::HandlePacket_Q (const char *p)
+RNBRemote::HandlePacket_QStartNoAckMode (const char *p)
{
- if (p == NULL || strlen (p) <= 1)
- {
- return HandlePacket_ILLFORMED ("No subtype specified in Q packet");
- }
+ // Send the OK packet first so the correct checksum is appended...
+ rnb_err_t result = SendPacket ("OK");
+ m_noack_mode = true;
+ return result;
+}
- /* Switch to no-ack protocol mode after the "OK" packet is sent
- and the ack for that comes back from gdb. */
- if (strcmp (p, "QStartNoAckMode") == 0)
- {
- rnb_err_t result = SendPacket ("OK");
- m_noack_mode = true;
- return result;
- }
+rnb_err_t
+RNBRemote::HandlePacket_QSetLogging (const char *p)
+{
+ p += sizeof ("QSetLogging:") - 1;
+ rnb_err_t result = set_logging (p);
+ if (result == rnb_success)
+ return SendPacket ("OK");
+ else
+ return SendPacket ("E35");
+}
- if (strncmp (p, "QSetLogging:", sizeof ("QSetLogging:") - 1) == 0)
+rnb_err_t
+RNBRemote::HandlePacket_QSetDisableASLR (const char *p)
+{
+ extern int g_disable_aslr;
+ p += sizeof ("QSetDisableASLR:") - 1;
+ switch (*p)
{
- p += sizeof ("QSetLogging:") - 1;
- rnb_err_t result = set_logging (p);
- if (result == rnb_success)
- return SendPacket ("OK");
- else
- return SendPacket ("E35");
+ case '0': g_disable_aslr = 0; break;
+ case '1': g_disable_aslr = 1; break;
+ default:
+ return SendPacket ("E56");
}
+ return SendPacket ("OK");
+}
- if (strncmp (p, "QSetDisableASLR:", sizeof ("QSetDisableASLR:") - 1) == 0)
- {
- extern int g_disable_aslr;
- p += sizeof ("QSetDisableASLR:") - 1;
- switch (*p)
- {
- case '0': g_disable_aslr = 0; break;
- case '1': g_disable_aslr = 1; break;
- default:
- return SendPacket ("E56");
- }
- return SendPacket ("OK");
- }
+rnb_err_t
+RNBRemote::HandlePacket_QSetMaxPayloadSize (const char *p)
+{
/* The number of characters in a packet payload that gdb is
prepared to accept. The packet-start char, packet-end char,
2 checksum chars and terminating null character are not included
in this size. */
- if (strncmp (p, "QSetMaxPayloadSize:", sizeof ("QSetMaxPayloadSize:") - 1) == 0)
+ p += sizeof ("QSetMaxPayloadSize:") - 1;
+ errno = 0;
+ uint32_t size = strtoul (p, NULL, 16);
+ if (errno != 0 && size == 0)
{
- p += sizeof ("QSetMaxPayloadSize:") - 1;
- errno = 0;
- uint32_t size = strtoul (p, NULL, 16);
- if (errno != 0 && size == 0)
- {
- return HandlePacket_ILLFORMED ("Invalid length in QSetMaxPayloadSize packet");
- }
- m_max_payload_size = size;
- return SendPacket ("OK");
+ return HandlePacket_ILLFORMED ("Invalid length in QSetMaxPayloadSize packet");
}
+ m_max_payload_size = size;
+ return SendPacket ("OK");
+}
+rnb_err_t
+RNBRemote::HandlePacket_QSetMaxPacketSize (const char *p)
+{
/* This tells us the largest packet that gdb can handle.
i.e. the size of gdb's packet-reading buffer.
QSetMaxPayloadSize is preferred because it is less ambiguous. */
-
- if (strncmp (p, "QSetMaxPacketSize:", sizeof ("QSetMaxPacketSize:") - 1) == 0)
+ p += sizeof ("QSetMaxPacketSize:") - 1;
+ errno = 0;
+ uint32_t size = strtoul (p, NULL, 16);
+ if (errno != 0 && size == 0)
{
- p += sizeof ("QSetMaxPacketSize:") - 1;
- errno = 0;
- uint32_t size = strtoul (p, NULL, 16);
- if (errno != 0 && size == 0)
- {
- return HandlePacket_ILLFORMED ("Invalid length in QSetMaxPacketSize packet");
- }
- m_max_payload_size = size - 5;
- return SendPacket ("OK");
+ return HandlePacket_ILLFORMED ("Invalid length in QSetMaxPacketSize packet");
}
+ m_max_payload_size = size - 5;
+ return SendPacket ("OK");
+}
+
+
+
+rnb_err_t
+RNBRemote::HandlePacket_QEnvironment (const char *p)
+{
/* This sets the environment for the target program. The packet is of the form:
QEnvironment:VARIABLE=VALUE
*/
- if (strncmp (p, "QEnvironment:", sizeof ("QEnvironment:") - 1) == 0)
- {
- DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s Handling QEnvironment: \"%s\"",
- (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p);
+ DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s Handling QEnvironment: \"%s\"",
+ (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p);
- p += sizeof ("QEnvironment:") - 1;
- RNBContext& ctx = Context();
-
- ctx.PushEnvironment (p);
- return SendPacket ("OK");
- }
+ p += sizeof ("QEnvironment:") - 1;
+ RNBContext& ctx = Context();
- // Unrecognized Q packet
- return SendPacket ("");
+ ctx.PushEnvironment (p);
+ return SendPacket ("OK");
}
void
@@ -2245,7 +2248,9 @@ RNBRemote::HandlePacket_g (const char *p)
InitializeRegisters ();
nub_process_t pid = m_ctx.ProcessID ();
- nub_thread_t tid = GetCurrentThread();
+ nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p + 1);
+ if (tid == INVALID_NUB_THREAD)
+ return HandlePacket_ILLFORMED ("No thread specified in p packet");
if (m_use_native_regs)
{
@@ -2291,7 +2296,9 @@ RNBRemote::HandlePacket_G (const char *p)
packet.SetFilePos(1); // Skip the 'G'
nub_process_t pid = m_ctx.ProcessID();
- nub_thread_t tid = GetCurrentThread();
+ nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p);
+ if (tid == INVALID_NUB_THREAD)
+ return HandlePacket_ILLFORMED ("No thread specified in p packet");
if (m_use_native_regs)
{
@@ -2870,6 +2877,30 @@ RNBRemote::HandlePacket_z (const char *p)
return HandlePacket_UNIMPLEMENTED(p);
}
+// Extract the thread number from the thread suffix that might be appended to
+// thread specific packets. This will only be enabled if m_thread_suffix_supported
+// is true.
+nub_thread_t
+RNBRemote::ExtractThreadIDFromThreadSuffix (const char *p)
+{
+ if (m_thread_suffix_supported)
+ {
+ nub_thread_t tid = INVALID_NUB_THREAD;
+ if (p)
+ {
+ const char *tid_cstr = strstr (p, "thread:");
+ if (tid_cstr)
+ {
+ tid_cstr += strlen ("thread:");
+ tid = strtoul(tid_cstr, NULL, 16);
+ }
+ DNBLogThreadedIf (LOG_RNB_PACKETS, "RNBRemote::ExtractThreadIDFromThreadSuffix(%s) got thread 0x%4.4x", p, tid);
+ }
+ }
+ return GetCurrentThread();
+
+}
+
/* `p XX'
print the contents of register X */
@@ -2889,12 +2920,17 @@ RNBRemote::HandlePacket_p (const char *p)
}
nub_process_t pid = m_ctx.ProcessID();
errno = 0;
- uint32_t reg = strtoul (p + 1, NULL, 16);
+ char *tid_cstr = NULL;
+ uint32_t reg = strtoul (p + 1, &tid_cstr, 16);
if (errno != 0 && reg == 0)
{
- return HandlePacket_ILLFORMED ("Could not parse thread number in p packet");
+ return HandlePacket_ILLFORMED ("Could not parse register number in p packet");
}
+ nub_thread_t tid = ExtractThreadIDFromThreadSuffix (tid_cstr);
+ if (tid == INVALID_NUB_THREAD)
+ return HandlePacket_ILLFORMED ("No thread specified in p packet");
+
const register_map_entry_t *reg_entry;
if (reg < g_num_reg_entries)
@@ -2925,7 +2961,6 @@ RNBRemote::HandlePacket_p (const char *p)
}
else
{
- nub_thread_t tid = GetCurrentThread();
register_value_in_hex_fixed_width (ostrm, pid, tid, reg_entry);
}
return SendPacket (ostrm.str());
@@ -2985,8 +3020,9 @@ RNBRemote::HandlePacket_P (const char *p)
reg_value.info = reg_entry->nub_info;
packet.GetHexBytes (reg_value.value.v_sint8, reg_entry->gdb_size, 0xcc);
- nub_thread_t tid;
- tid = GetCurrentThread ();
+ nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p);
+ if (tid == INVALID_NUB_THREAD)
+ return HandlePacket_ILLFORMED ("No thread specified in p packet");
if (!DNBThreadSetRegisterValueByID (pid, tid, reg_entry->nub_info.set, reg_entry->nub_info.reg, &reg_value))
{
diff --git a/lldb/tools/debugserver/source/RNBRemote.h b/lldb/tools/debugserver/source/RNBRemote.h
index fab42bc9693..82febf7d226 100644
--- a/lldb/tools/debugserver/source/RNBRemote.h
+++ b/lldb/tools/debugserver/source/RNBRemote.h
@@ -93,6 +93,7 @@ public:
query_host_info, // 'qHostInfo'
pass_signals_to_inferior, // 'QPassSignals'
start_noack_mode, // 'QStartNoAckMode'
+ prefix_reg_packets_with_tid, // 'QPrefixRegisterPacketsWithThreadID
set_logging_mode, // 'QSetLogging:'
set_max_packet_size, // 'QSetMaxPacketSize:'
set_max_payload_size, // 'QSetMaxPayloadSize:'
@@ -156,7 +157,14 @@ public:
rnb_err_t HandlePacket_qThreadExtraInfo (const char *p);
rnb_err_t HandlePacket_qThreadStopInfo (const char *p);
rnb_err_t HandlePacket_qHostInfo (const char *p);
- rnb_err_t HandlePacket_Q (const char *p);
+ rnb_err_t HandlePacket_QStartNoAckMode (const char *p);
+ rnb_err_t HandlePacket_QThreadSuffixSupported (const char *p);
+ rnb_err_t HandlePacket_QSetLogging (const char *p);
+ rnb_err_t HandlePacket_QSetDisableASLR (const char *p);
+ rnb_err_t HandlePacket_QSetMaxPayloadSize (const char *p);
+ rnb_err_t HandlePacket_QSetMaxPacketSize (const char *p);
+ rnb_err_t HandlePacket_QEnvironment (const char *p);
+ rnb_err_t HandlePacket_QPrefixRegisterPacketsWithThreadID (const char *p);
rnb_err_t HandlePacket_last_signal (const char *p);
rnb_err_t HandlePacket_m (const char *p);
rnb_err_t HandlePacket_M (const char *p);
@@ -237,6 +245,9 @@ protected:
void CreatePacketTable ();
rnb_err_t GetPacketPayload (std::string &);
+ nub_thread_t
+ ExtractThreadIDFromThreadSuffix (const char *p);
+
// gdb can send multiple Z/z packets for the same address and
// these calls must be ref counted.
struct Breakpoint
@@ -286,7 +297,13 @@ protected:
uint32_t m_max_payload_size; // the maximum sized payload we should send to gdb
bool m_extended_mode:1, // are we in extended mode?
m_noack_mode:1, // are we in no-ack mode?
- m_use_native_regs:1; // Use native registers by querying DNB layer for register definitions?
+ m_noack_mode_just_enabled:1, // Did we just enable this and need to compute one more checksum?
+ m_use_native_regs:1, // Use native registers by querying DNB layer for register definitions?
+ m_thread_suffix_supported:1; // Set to true if the 'p', 'P', 'g', and 'G' packets should be prefixed with the thread ID and colon:
+ // "$pRR;thread:TTTT;" instead of "$pRR"
+ // "$PRR=VVVVVVVV;thread:TTTT;" instead of "$PRR=VVVVVVVV"
+ // "$g;thread:TTTT" instead of "$g"
+ // "$GVVVVVVVVVVVVVV;thread:TTTT;#00 instead of "$GVVVVVVVVVVVVVV"
};
/* We translate the /usr/include/mach/exception_types.h exception types
OpenPOWER on IntegriCloud