summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/lldb-enumerations.h12
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp237
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h67
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp259
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h8
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp10
-rw-r--r--lldb/tools/debugserver/source/DNBLog.cpp13
7 files changed, 475 insertions, 131 deletions
diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h
index c609deb5b7b..8303be8d937 100644
--- a/lldb/include/lldb/lldb-enumerations.h
+++ b/lldb/include/lldb/lldb-enumerations.h
@@ -606,6 +606,18 @@ typedef enum ObjCRuntimeVersions {
eAppleObjC_V2 = 2
} ObjCRuntimeVersions;
+
+//----------------------------------------------------------------------
+// LazyBool is for boolean values that need to be calculated lazily.
+// Values start off set to eLazyBoolCalculate, and then they can be
+// calculated once and set to eLazyBoolNo or eLazyBoolYes.
+//----------------------------------------------------------------------
+typedef enum LazyBool {
+ eLazyBoolCalculate = -1,
+ eLazyBoolNo = 0,
+ eLazyBoolYes = 1
+} LazyBool;
+
} // namespace lldb
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 6442e21b224..9ebb143a150 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -34,8 +34,15 @@ using namespace lldb_private;
//----------------------------------------------------------------------
GDBRemoteCommunication::GDBRemoteCommunication() :
Communication("gdb-remote.packets"),
- m_send_acks (true),
- m_thread_suffix_supported (false),
+ m_supports_not_sending_acks (eLazyBoolCalculate),
+ m_supports_thread_suffix (eLazyBoolCalculate),
+ m_supports_qHostInfo (eLazyBoolCalculate),
+ m_supports_vCont_all (eLazyBoolCalculate),
+ m_supports_vCont_any (eLazyBoolCalculate),
+ m_supports_vCont_c (eLazyBoolCalculate),
+ m_supports_vCont_C (eLazyBoolCalculate),
+ m_supports_vCont_s (eLazyBoolCalculate),
+ m_supports_vCont_S (eLazyBoolCalculate),
m_rx_packet_listener ("gdbremote.rx_packet"),
m_sequence_mutex (Mutex::eMutexTypeRecursive),
m_public_is_running (false),
@@ -79,7 +86,7 @@ GDBRemoteCommunication::CalculcateChecksum (const char *payload, size_t payload_
int checksum = 0;
// We only need to compute the checksum if we are sending acks
- if (m_send_acks)
+ if (GetSendAcks ())
{
for (size_t i = 0; i < payload_length; ++i)
checksum += payload[i];
@@ -109,6 +116,112 @@ GDBRemoteCommunication::SendNack ()
return Write (&nack_char, 1, status, NULL) == 1;
}
+bool
+GDBRemoteCommunication::GetSendAcks ()
+{
+ if (m_supports_not_sending_acks == eLazyBoolCalculate)
+ {
+ StringExtractorGDBRemote response;
+ m_supports_not_sending_acks = eLazyBoolNo;
+ if (SendPacketAndWaitForResponse("QStartNoAckMode", response, 1, false))
+ {
+ if (response.IsOKPacket())
+ m_supports_not_sending_acks = eLazyBoolYes;
+ }
+ }
+ return m_supports_not_sending_acks != eLazyBoolYes;
+}
+
+void
+GDBRemoteCommunication::ResetDiscoverableSettings()
+{
+ m_supports_not_sending_acks = eLazyBoolCalculate;
+ m_supports_thread_suffix = eLazyBoolCalculate;
+ m_supports_qHostInfo = eLazyBoolCalculate;
+ m_supports_vCont_c = eLazyBoolCalculate;
+ m_supports_vCont_C = eLazyBoolCalculate;
+ m_supports_vCont_s = eLazyBoolCalculate;
+ m_supports_vCont_S = eLazyBoolCalculate;
+ m_arch.Clear();
+ m_os.Clear();
+ m_vendor.Clear();
+ m_byte_order = lldb::endian::InlHostByteOrder();
+ m_pointer_byte_size = 0;
+}
+
+
+bool
+GDBRemoteCommunication::GetThreadSuffixSupported ()
+{
+ if (m_supports_thread_suffix == eLazyBoolCalculate)
+ {
+ StringExtractorGDBRemote response;
+ m_supports_thread_suffix = eLazyBoolNo;
+ if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response, 1, false))
+ {
+ if (response.IsOKPacket())
+ m_supports_thread_suffix = eLazyBoolYes;
+ }
+ }
+ return m_supports_thread_suffix;
+}
+bool
+GDBRemoteCommunication::GetVContSupported (char flavor)
+{
+ if (m_supports_vCont_c == eLazyBoolCalculate)
+ {
+ StringExtractorGDBRemote response;
+ m_supports_vCont_c = eLazyBoolNo;
+ m_supports_vCont_C = eLazyBoolNo;
+ m_supports_vCont_s = eLazyBoolNo;
+ m_supports_vCont_S = eLazyBoolNo;
+ if (SendPacketAndWaitForResponse("vCont?", response, 1, false))
+ {
+ const char *response_cstr = response.GetStringRef().c_str();
+ if (::strstr (response_cstr, ";c"))
+ m_supports_vCont_c = eLazyBoolYes;
+
+ if (::strstr (response_cstr, ";C"))
+ m_supports_vCont_C = eLazyBoolYes;
+
+ if (::strstr (response_cstr, ";s"))
+ m_supports_vCont_s = eLazyBoolYes;
+
+ if (::strstr (response_cstr, ";S"))
+ m_supports_vCont_S = eLazyBoolYes;
+
+ if (m_supports_vCont_c == eLazyBoolYes &&
+ m_supports_vCont_C == eLazyBoolYes &&
+ m_supports_vCont_s == eLazyBoolYes &&
+ m_supports_vCont_S == eLazyBoolYes)
+ {
+ m_supports_vCont_all = eLazyBoolYes;
+ }
+
+ if (m_supports_vCont_c == eLazyBoolYes ||
+ m_supports_vCont_C == eLazyBoolYes ||
+ m_supports_vCont_s == eLazyBoolYes ||
+ m_supports_vCont_S == eLazyBoolYes)
+ {
+ m_supports_vCont_any = eLazyBoolYes;
+ }
+ }
+ }
+
+ switch (flavor)
+ {
+ case 'a': return m_supports_vCont_any;
+ case 'A': return m_supports_vCont_all;
+ case 'c': return m_supports_vCont_c;
+ case 'C': return m_supports_vCont_C;
+ case 's': return m_supports_vCont_s;
+ case 'S': return m_supports_vCont_S;
+ default: break;
+ }
+ return false;
+}
+
+
size_t
GDBRemoteCommunication::SendPacketAndWaitForResponse
(
@@ -451,7 +564,7 @@ GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_le
size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL);
if (bytes_written == packet.GetSize())
{
- if (m_send_acks)
+ if (GetSendAcks ())
{
if (GetAck (1) != '+')
return 0;
@@ -643,7 +756,7 @@ GDBRemoteCommunication::WaitForPacketNoLock (StringExtractorGDBRemote &response,
if (success)
response_str.assign (packet_data + 1, packet_size - 4);
- if (m_send_acks)
+ if (GetSendAcks ())
{
char packet_checksum = strtol (&packet_data[packet_size-2], NULL, 16);
char actual_checksum = CalculcateChecksum (&response_str[0], response_str.size());
@@ -829,66 +942,66 @@ GDBRemoteCommunication::SendEnvironmentPacket (char const *name_equal_value, uin
}
bool
-GDBRemoteCommunication::GetHostInfo (uint32_t timeout_seconds)
+GDBRemoteCommunication::GetHostInfo ()
{
- m_arch.Clear();
- m_os.Clear();
- m_vendor.Clear();
- m_byte_order = lldb::endian::InlHostByteOrder();
- m_pointer_byte_size = 0;
-
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse ("qHostInfo", response, timeout_seconds, false))
+ if (m_supports_qHostInfo == eLazyBoolCalculate)
{
- if (response.IsUnsupportedPacket())
- return false;
+ m_supports_qHostInfo = eLazyBoolNo;
-
- std::string name;
- std::string value;
- uint32_t cpu = LLDB_INVALID_CPUTYPE;
- uint32_t sub = 0;
-
- while (response.GetNameColonValue(name, value))
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse ("qHostInfo", response, 1, false))
{
- if (name.compare("cputype") == 0)
- {
- // exception type in big endian hex
- cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0);
- }
- else if (name.compare("cpusubtype") == 0)
- {
- // exception count in big endian hex
- sub = Args::StringToUInt32 (value.c_str(), 0, 0);
- }
- else if (name.compare("ostype") == 0)
- {
- // exception data in big endian hex
- m_os.SetCString(value.c_str());
- }
- else if (name.compare("vendor") == 0)
- {
- m_vendor.SetCString(value.c_str());
- }
- else if (name.compare("endian") == 0)
- {
- if (value.compare("little") == 0)
- m_byte_order = eByteOrderLittle;
- else if (value.compare("big") == 0)
- m_byte_order = eByteOrderBig;
- else if (value.compare("pdp") == 0)
- m_byte_order = eByteOrderPDP;
- }
- else if (name.compare("ptrsize") == 0)
+ if (response.IsUnsupportedPacket())
+ return false;
+
+ m_supports_qHostInfo = eLazyBoolYes;
+
+ std::string name;
+ std::string value;
+ uint32_t cpu = LLDB_INVALID_CPUTYPE;
+ uint32_t sub = 0;
+
+ while (response.GetNameColonValue(name, value))
{
- m_pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0);
+ if (name.compare("cputype") == 0)
+ {
+ // exception type in big endian hex
+ cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0);
+ }
+ else if (name.compare("cpusubtype") == 0)
+ {
+ // exception count in big endian hex
+ sub = Args::StringToUInt32 (value.c_str(), 0, 0);
+ }
+ else if (name.compare("ostype") == 0)
+ {
+ // exception data in big endian hex
+ m_os.SetCString(value.c_str());
+ }
+ else if (name.compare("vendor") == 0)
+ {
+ m_vendor.SetCString(value.c_str());
+ }
+ else if (name.compare("endian") == 0)
+ {
+ if (value.compare("little") == 0)
+ m_byte_order = eByteOrderLittle;
+ else if (value.compare("big") == 0)
+ m_byte_order = eByteOrderBig;
+ else if (value.compare("pdp") == 0)
+ m_byte_order = eByteOrderPDP;
+ }
+ else if (name.compare("ptrsize") == 0)
+ {
+ m_pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0);
+ }
}
+
+ if (cpu != LLDB_INVALID_CPUTYPE)
+ m_arch.SetMachOArch (cpu, sub);
}
-
- if (cpu != LLDB_INVALID_CPUTYPE)
- m_arch.SetMachOArch (cpu, sub);
}
- return HostInfoIsValid();
+ return m_supports_qHostInfo == eLazyBoolYes;
}
int
@@ -918,7 +1031,7 @@ const lldb_private::ArchSpec &
GDBRemoteCommunication::GetHostArchitecture ()
{
if (!HostInfoIsValid ())
- GetHostInfo (1);
+ GetHostInfo ();
return m_arch;
}
@@ -926,7 +1039,7 @@ const lldb_private::ConstString &
GDBRemoteCommunication::GetOSString ()
{
if (!HostInfoIsValid ())
- GetHostInfo (1);
+ GetHostInfo ();
return m_os;
}
@@ -934,7 +1047,7 @@ const lldb_private::ConstString &
GDBRemoteCommunication::GetVendorString()
{
if (!HostInfoIsValid ())
- GetHostInfo (1);
+ GetHostInfo ();
return m_vendor;
}
@@ -942,7 +1055,7 @@ lldb::ByteOrder
GDBRemoteCommunication::GetByteOrder ()
{
if (!HostInfoIsValid ())
- GetHostInfo (1);
+ GetHostInfo ();
return m_byte_order;
}
@@ -950,7 +1063,7 @@ uint32_t
GDBRemoteCommunication::GetAddressByteSize ()
{
if (!HostInfoIsValid ())
- GetHostInfo (1);
+ GetHostInfo ();
return m_pointer_byte_size;
}
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index 3ebabeb7085..1499ba90443 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -97,23 +97,8 @@ public:
CalculcateChecksum (const char *payload,
size_t payload_length);
- void
- SetAckMode (bool enabled)
- {
- m_send_acks = enabled;
- }
-
bool
- GetThreadSuffixSupported () const
- {
- return m_thread_suffix_supported;
- }
-
- void
- SetThreadSuffixSupported (bool enabled)
- {
- m_thread_suffix_supported = enabled;
- }
+ GetThreadSuffixSupported ();
bool
SendAsyncSignal (int signo);
@@ -229,12 +214,6 @@ public:
bool
GetHostInfo (uint32_t timeout_seconds);
- bool
- HostInfoIsValid () const
- {
- return m_pointer_byte_size != 0;
- }
-
const lldb_private::ArchSpec &
GetHostArchitecture ();
@@ -250,6 +229,33 @@ public:
uint32_t
GetAddressByteSize ();
+ bool
+ GetVContSupported (char flavor);
+
+ void
+ ResetDiscoverableSettings();
+
+ bool
+ GetHostInfo ();
+
+ bool
+ GetSendAcks ();
+
+ bool
+ GetSupportsThreadSuffix ();
+
+ bool
+ HasFullVContSupport ()
+ {
+ return GetVContSupported ('A');
+ }
+
+ bool
+ HasAnyVContSupport ()
+ {
+ return GetVContSupported ('a');
+ }
+
protected:
typedef std::list<std::string> packet_collection;
@@ -264,11 +270,24 @@ protected:
bool
WaitForNotRunningPrivate (const lldb_private::TimeValue *timeout_ptr);
+ bool
+ HostInfoIsValid () const
+ {
+ return m_supports_qHostInfo != lldb::eLazyBoolCalculate;
+ }
+
//------------------------------------------------------------------
// Classes that inherit from GDBRemoteCommunication can see and modify these
//------------------------------------------------------------------
- bool m_send_acks:1,
- m_thread_suffix_supported:1;
+ lldb::LazyBool m_supports_not_sending_acks;
+ lldb::LazyBool m_supports_thread_suffix;
+ lldb::LazyBool m_supports_qHostInfo;
+ lldb::LazyBool m_supports_vCont_all;
+ lldb::LazyBool m_supports_vCont_any;
+ lldb::LazyBool m_supports_vCont_c;
+ lldb::LazyBool m_supports_vCont_C;
+ lldb::LazyBool m_supports_vCont_s;
+ lldb::LazyBool m_supports_vCont_S;
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_public_is_running;
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 1c9b6ff5009..87bc0b9a67f 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -114,7 +114,10 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
m_curr_tid (LLDB_INVALID_THREAD_ID),
m_curr_tid_run (LLDB_INVALID_THREAD_ID),
m_z0_supported (1),
- m_continue_packet(),
+ m_continue_c_tids (),
+ m_continue_C_tids (),
+ m_continue_s_tids (),
+ m_continue_S_tids (),
m_dispatch_queue_offsets_addr (LLDB_INVALID_ADDRESS),
m_packet_timeout (1),
m_max_memory_size (512),
@@ -599,7 +602,6 @@ ProcessGDBRemote::ConnectToDebugserver (const char *connect_url)
return error;
}
- m_gdb_comm.SetAckMode (true);
if (m_gdb_comm.StartReadThread(&error))
{
// Send an initial ack
@@ -611,19 +613,11 @@ ProcessGDBRemote::ConnectToDebugserver (const char *connect_url)
m_debugserver_pid,
false);
- StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse("QStartNoAckMode", response, 1, false))
- {
- 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);
- }
-
+ m_gdb_comm.ResetDiscoverableSettings();
+ m_gdb_comm.GetSendAcks ();
+ m_gdb_comm.GetThreadSuffixSupported ();
+ m_gdb_comm.GetHostInfo ();
+ m_gdb_comm.GetVContSupported ('c');
}
return error;
}
@@ -847,12 +841,10 @@ ProcessGDBRemote::DidAttach ()
Error
ProcessGDBRemote::WillResume ()
{
- m_continue_packet.Clear();
- // Start the continue packet we will use to run the target. Each thread
- // will append what it is supposed to be doing to this packet when the
- // ThreadList::WillResume() is called. If a thread it supposed
- // to stay stopped, then don't append anything to this string.
- m_continue_packet.Printf("vCont");
+ m_continue_c_tids.clear();
+ m_continue_C_tids.clear();
+ m_continue_s_tids.clear();
+ m_continue_S_tids.clear();
return Error();
}
@@ -867,14 +859,210 @@ ProcessGDBRemote::DoResume ()
Listener listener ("gdb-remote.resume-packet-sent");
if (listener.StartListeningForEvents (&m_gdb_comm, GDBRemoteCommunication::eBroadcastBitRunPacketSent))
{
- EventSP event_sp;
- TimeValue timeout;
- timeout = TimeValue::Now();
- timeout.OffsetWithSeconds (5);
- m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (m_continue_packet.GetData(), m_continue_packet.GetSize()));
-
- if (listener.WaitForEvent (&timeout, event_sp) == false)
- error.SetErrorString("Resume timed out.");
+ StreamString continue_packet;
+ bool continue_packet_error = false;
+ if (m_gdb_comm.HasAnyVContSupport ())
+ {
+ continue_packet.PutCString ("vCont");
+
+ if (!m_continue_c_tids.empty())
+ {
+ if (m_gdb_comm.GetVContSupported ('c'))
+ {
+ for (tid_collection::const_iterator t_pos = m_continue_c_tids.begin(), t_end = m_continue_c_tids.end(); t_pos != t_end; ++t_pos)
+ continue_packet.Printf(";c:%4.4x", *t_pos);
+ }
+ else
+ continue_packet_error = true;
+ }
+
+ if (!continue_packet_error && !m_continue_C_tids.empty())
+ {
+ if (m_gdb_comm.GetVContSupported ('C'))
+ {
+ for (tid_sig_collection::const_iterator s_pos = m_continue_C_tids.begin(), s_end = m_continue_C_tids.end(); s_pos != s_end; ++s_pos)
+ continue_packet.Printf(";C%2.2x:%4.4x", s_pos->second, s_pos->first);
+ }
+ else
+ continue_packet_error = true;
+ }
+
+ if (!continue_packet_error && !m_continue_s_tids.empty())
+ {
+ if (m_gdb_comm.GetVContSupported ('s'))
+ {
+ for (tid_collection::const_iterator t_pos = m_continue_s_tids.begin(), t_end = m_continue_s_tids.end(); t_pos != t_end; ++t_pos)
+ continue_packet.Printf(";s:%4.4x", *t_pos);
+ }
+ else
+ continue_packet_error = true;
+ }
+
+ if (!continue_packet_error && !m_continue_S_tids.empty())
+ {
+ if (m_gdb_comm.GetVContSupported ('S'))
+ {
+ for (tid_sig_collection::const_iterator s_pos = m_continue_S_tids.begin(), s_end = m_continue_S_tids.end(); s_pos != s_end; ++s_pos)
+ continue_packet.Printf(";S%2.2x:%4.4x", s_pos->second, s_pos->first);
+ }
+ else
+ continue_packet_error = true;
+ }
+
+ if (continue_packet_error)
+ continue_packet.GetString().clear();
+ }
+ else
+ continue_packet_error = true;
+
+ if (continue_packet_error)
+ {
+ continue_packet_error = false;
+ // Either no vCont support, or we tried to use part of the vCont
+ // packet that wasn't supported by the remote GDB server.
+ // We need to try and make a simple packet that can do our continue
+ const size_t num_threads = GetThreadList().GetSize();
+ const size_t num_continue_c_tids = m_continue_c_tids.size();
+ const size_t num_continue_C_tids = m_continue_C_tids.size();
+ const size_t num_continue_s_tids = m_continue_s_tids.size();
+ const size_t num_continue_S_tids = m_continue_S_tids.size();
+ if (num_continue_c_tids > 0)
+ {
+ if (num_continue_c_tids == num_threads)
+ {
+ // All threads are resuming...
+ SetCurrentGDBRemoteThreadForRun (-1);
+ continue_packet.PutChar ('c');
+ }
+ else if (num_continue_c_tids == 1 &&
+ num_continue_C_tids == 0 &&
+ num_continue_s_tids == 0 &&
+ num_continue_S_tids == 0 )
+ {
+ // Only one thread is continuing
+ SetCurrentGDBRemoteThreadForRun (m_continue_c_tids.front());
+ continue_packet.PutChar ('c');
+ }
+ else
+ {
+ // We can't represent this continue packet....
+ continue_packet_error = true;
+ }
+ }
+
+ if (!continue_packet_error && num_continue_C_tids > 0)
+ {
+ if (num_continue_C_tids == num_threads)
+ {
+ const int continue_signo = m_continue_C_tids.front().second;
+ if (num_continue_C_tids > 1)
+ {
+ for (size_t i=1; i<num_threads; ++i)
+ {
+ if (m_continue_C_tids[i].second != continue_signo)
+ continue_packet_error = true;
+ }
+ }
+ if (!continue_packet_error)
+ {
+ // Add threads continuing with the same signo...
+ SetCurrentGDBRemoteThreadForRun (-1);
+ continue_packet.Printf("C%2.2x", continue_signo);
+ }
+ }
+ else if (num_continue_c_tids == 0 &&
+ num_continue_C_tids == 1 &&
+ num_continue_s_tids == 0 &&
+ num_continue_S_tids == 0 )
+ {
+ // Only one thread is continuing with signal
+ SetCurrentGDBRemoteThreadForRun (m_continue_C_tids.front().first);
+ continue_packet.Printf("C%2.2x", m_continue_C_tids.front().second);
+ }
+ else
+ {
+ // We can't represent this continue packet....
+ continue_packet_error = true;
+ }
+ }
+
+ if (!continue_packet_error && num_continue_s_tids > 0)
+ {
+ if (num_continue_s_tids == num_threads)
+ {
+ // All threads are resuming...
+ SetCurrentGDBRemoteThreadForRun (-1);
+ continue_packet.PutChar ('s');
+ }
+ else if (num_continue_c_tids == 0 &&
+ num_continue_C_tids == 0 &&
+ num_continue_s_tids == 1 &&
+ num_continue_S_tids == 0 )
+ {
+ // Only one thread is stepping
+ SetCurrentGDBRemoteThreadForRun (m_continue_s_tids.front());
+ continue_packet.PutChar ('s');
+ }
+ else
+ {
+ // We can't represent this continue packet....
+ continue_packet_error = true;
+ }
+ }
+
+ if (!continue_packet_error && num_continue_S_tids > 0)
+ {
+ if (num_continue_S_tids == num_threads)
+ {
+ const int step_signo = m_continue_S_tids.front().second;
+ // Are all threads trying to step with the same signal?
+ if (num_continue_S_tids > 1)
+ {
+ for (size_t i=1; i<num_threads; ++i)
+ {
+ if (m_continue_S_tids[i].second != step_signo)
+ continue_packet_error = true;
+ }
+ }
+ if (!continue_packet_error)
+ {
+ // Add threads stepping with the same signo...
+ SetCurrentGDBRemoteThreadForRun (-1);
+ continue_packet.Printf("S%2.2x", step_signo);
+ }
+ }
+ else if (num_continue_c_tids == 0 &&
+ num_continue_C_tids == 0 &&
+ num_continue_s_tids == 0 &&
+ num_continue_S_tids == 1 )
+ {
+ // Only one thread is stepping with signal
+ SetCurrentGDBRemoteThreadForRun (m_continue_S_tids.front().first);
+ continue_packet.Printf("S%2.2x", m_continue_S_tids.front().second);
+ }
+ else
+ {
+ // We can't represent this continue packet....
+ continue_packet_error = true;
+ }
+ }
+ }
+
+ if (continue_packet_error)
+ {
+ error.SetErrorString ("can't make continue packet for this resume");
+ }
+ else
+ {
+ EventSP event_sp;
+ TimeValue timeout;
+ timeout = TimeValue::Now();
+ timeout.OffsetWithSeconds (5);
+ m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (continue_packet.GetData(), continue_packet.GetSize()));
+
+ if (listener.WaitForEvent (&timeout, event_sp) == false)
+ error.SetErrorString("Resume timed out.");
+ }
}
return error;
@@ -2118,7 +2306,11 @@ ProcessGDBRemote::SetCurrentGDBRemoteThread (int tid)
return true;
char packet[32];
- const int packet_len = ::snprintf (packet, sizeof(packet), "Hg%x", tid);
+ int packet_len;
+ if (tid <= 0)
+ packet_len = ::snprintf (packet, sizeof(packet), "Hg%i", tid);
+ else
+ packet_len = ::snprintf (packet, sizeof(packet), "Hg%x", tid);
assert (packet_len + 1 < sizeof(packet));
StringExtractorGDBRemote response;
if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, 2, false))
@@ -2139,7 +2331,12 @@ ProcessGDBRemote::SetCurrentGDBRemoteThreadForRun (int tid)
return true;
char packet[32];
- const int packet_len = ::snprintf (packet, sizeof(packet), "Hc%x", tid);
+ int packet_len;
+ if (tid <= 0)
+ packet_len = ::snprintf (packet, sizeof(packet), "Hc%i", tid);
+ else
+ 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/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 8db580b53f9..3e61ac6b840 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -14,6 +14,7 @@
// C++ Includes
#include <list>
+#include <vector>
// Other libraries and framework includes
#include "lldb/Core/ArchSpec.h"
@@ -343,7 +344,12 @@ protected:
lldb::tid_t m_curr_tid; // Current gdb remote protocol thread index for all other operations
lldb::tid_t m_curr_tid_run; // Current gdb remote protocol thread index for continue, step, etc
uint32_t m_z0_supported:1; // Set to non-zero if Z0 and z0 packets are supported
- lldb_private::StreamString m_continue_packet;
+ typedef std::vector<lldb::tid_t> tid_collection;
+ typedef std::vector< std::pair<lldb::tid_t,int> > tid_sig_collection;
+ tid_collection m_continue_c_tids; // 'c' for continue
+ tid_sig_collection m_continue_C_tids; // 'C' for continue with signal
+ tid_collection m_continue_s_tids; // 's' for step
+ tid_sig_collection m_continue_S_tids; // 'S' for step with signal
lldb::addr_t m_dispatch_queue_offsets_addr;
uint32_t m_packet_timeout;
size_t m_max_memory_size; // The maximum number of bytes to read/write when reading and writing memory
diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index 37084072e78..6acefff3216 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -93,25 +93,25 @@ ThreadGDBRemote::WillResume (StateType resume_state)
if (log)
log->Printf ("Resuming thread: %4.4x with state: %s.", GetID(), StateAsCString(resume_state));
+ ProcessGDBRemote &process = GetGDBProcess();
switch (resume_state)
{
case eStateSuspended:
case eStateStopped:
- // Don't append anything for threads that should stay stopped.
break;
case eStateRunning:
if (m_process.GetUnixSignals().SignalIsValid (signo))
- GetGDBProcess().m_continue_packet.Printf(";C%2.2x:%4.4x", signo, GetID());
+ process.m_continue_C_tids.push_back(std::make_pair(GetID(), signo));
else
- GetGDBProcess().m_continue_packet.Printf(";c:%4.4x", GetID());
+ process.m_continue_c_tids.push_back(GetID());
break;
case eStateStepping:
if (m_process.GetUnixSignals().SignalIsValid (signo))
- GetGDBProcess().m_continue_packet.Printf(";S%2.2x:%4.4x", signo, GetID());
+ process.m_continue_S_tids.push_back(std::make_pair(GetID(), signo));
else
- GetGDBProcess().m_continue_packet.Printf(";s:%4.4x", GetID());
+ process.m_continue_s_tids.push_back(GetID());
break;
default:
diff --git a/lldb/tools/debugserver/source/DNBLog.cpp b/lldb/tools/debugserver/source/DNBLog.cpp
index 52aa0815275..21661f1dcaf 100644
--- a/lldb/tools/debugserver/source/DNBLog.cpp
+++ b/lldb/tools/debugserver/source/DNBLog.cpp
@@ -93,6 +93,9 @@ DNBLogEnabled ()
static inline void
_DNBLogVAPrintf(uint32_t flags, const char *format, va_list args)
{
+ static PThreadMutex g_LogThreadedMutex(PTHREAD_MUTEX_RECURSIVE);
+ PTHREAD_MUTEX_LOCKER(locker, g_LogThreadedMutex);
+
if (g_log_callback)
g_log_callback(g_log_baton, flags, format, args);
}
@@ -140,12 +143,6 @@ _DNBLogDebugVerbose (const char *format, ...)
}
-static pthread_mutex_t *
-GetLogThreadedMutex()
-{
- static PThreadMutex g_LogThreadedMutex(PTHREAD_MUTEX_RECURSIVE);
- return g_LogThreadedMutex.Mutex();
-}
static uint32_t g_message_id = 0;
//----------------------------------------------------------------------
@@ -157,7 +154,7 @@ _DNBLogThreaded (const char *format, ...)
{
if (DNBLogEnabled ())
{
- PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex());
+ //PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex());
char *arg_msg = NULL;
va_list args;
@@ -202,7 +199,7 @@ _DNBLogThreadedIf (uint32_t log_bit, const char *format, ...)
{
if (DNBLogEnabled () && (log_bit & g_log_bits) == log_bit)
{
- PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex());
+ //PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex());
char *arg_msg = NULL;
va_list args;
OpenPOWER on IntegriCloud