summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote
diff options
context:
space:
mode:
authoremaste <emaste@FreeBSD.org>2013-11-12 17:25:33 +0000
committeremaste <emaste@FreeBSD.org>2013-11-12 17:25:33 +0000
commit9dd6dd992f8bed9a53bf0653fc1eff3fb4ccd46e (patch)
treeb9aa1d1064fb25a0f2313d9a7964c862c0b7b354 /contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote
parent4372cfee12af5dfa890561beb0fecc90957ba058 (diff)
parentc727fe695d28799acb499e9961f11ec07d4f9fe2 (diff)
downloadFreeBSD-src-9dd6dd992f8bed9a53bf0653fc1eff3fb4ccd46e.zip
FreeBSD-src-9dd6dd992f8bed9a53bf0653fc1eff3fb4ccd46e.tar.gz
Update LLDB to upstream r194122 snapshot
ludes minor changes relative to upstream, for compatibility with FreeBSD's in-tree LLVM 3.3: - Reverted LLDB r191806, restoring use of previous API. - Reverted part of LLDB r189317, restoring previous enum names. - Work around missing LLVM r192504, using previous registerEHFrames API (limited functionality). - Removed PlatformWindows header include and init/terminate calls. Sponsored by: DARPA, AFRL
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote')
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp41
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp497
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h70
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp623
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h75
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp6
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h156
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp219
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h10
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp37
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h3
11 files changed, 1374 insertions, 363 deletions
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index d7efdf2..f67e1b5 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -133,7 +133,11 @@ GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name,
const char *listener_name,
bool is_platform) :
Communication(comm_name),
+#ifdef LLDB_CONFIGURATION_DEBUG
+ m_packet_timeout (1000),
+#else
m_packet_timeout (1),
+#endif
m_sequence_mutex (Mutex::eMutexTypeRecursive),
m_public_is_running (false),
m_private_is_running (false),
@@ -173,7 +177,7 @@ GDBRemoteCommunication::SendAck ()
char ch = '+';
const size_t bytes_written = Write (&ch, 1, status, NULL);
if (log)
- log->Printf ("<%4zu> send packet: %c", bytes_written, ch);
+ log->Printf ("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch);
m_history.AddPacket (ch, History::ePacketTypeSend, bytes_written);
return bytes_written;
}
@@ -186,7 +190,7 @@ GDBRemoteCommunication::SendNack ()
char ch = '-';
const size_t bytes_written = Write (&ch, 1, status, NULL);
if (log)
- log->Printf ("<%4zu> send packet: %c", bytes_written, ch);
+ log->Printf("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch);
m_history.AddPacket (ch, History::ePacketTypeSend, bytes_written);
return bytes_written;
}
@@ -222,7 +226,7 @@ GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_le
if (!m_history.DidDumpToLog ())
m_history.Dump (log);
- log->Printf ("<%4zu> send packet: %.*s", bytes_written, (int)packet.GetSize(), packet.GetData());
+ log->Printf("<%4" PRIu64 "> send packet: %.*s", (uint64_t)bytes_written, (int)packet.GetSize(), packet.GetData());
}
m_history.AddPacket (packet.GetString(), packet.GetSize(), History::ePacketTypeSend, bytes_written);
@@ -456,13 +460,38 @@ GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, Stri
if (!m_history.DidDumpToLog ())
m_history.Dump (log);
- log->Printf ("<%4zu> read packet: %.*s", total_length, (int)(total_length), m_bytes.c_str());
+ log->Printf("<%4" PRIu64 "> read packet: %.*s", (uint64_t)total_length, (int)(total_length), m_bytes.c_str());
}
m_history.AddPacket (m_bytes.c_str(), total_length, History::ePacketTypeRecv, total_length);
- packet_str.assign (m_bytes, content_start, content_length);
-
+ // Clear packet_str in case there is some existing data in it.
+ packet_str.clear();
+ // Copy the packet from m_bytes to packet_str expanding the
+ // run-length encoding in the process.
+ // Reserve enough byte for the most common case (no RLE used)
+ packet_str.reserve(m_bytes.length());
+ for (std::string::const_iterator c = m_bytes.begin() + content_start; c != m_bytes.begin() + content_start + content_length; ++c)
+ {
+ if (*c == '*')
+ {
+ // '*' indicates RLE. Next character will give us the
+ // repeat count and previous character is what is to be
+ // repeated.
+ char char_to_repeat = packet_str.back();
+ // Number of time the previous character is repeated
+ int repeat_count = *++c + 3 - ' ';
+ // We have the char_to_repeat and repeat_count. Now push
+ // it in the packet.
+ for (int i = 0; i < repeat_count; ++i)
+ packet_str.push_back(char_to_repeat);
+ }
+ else
+ {
+ packet_str.push_back(*c);
+ }
+ }
+
if (m_bytes[0] == '$')
{
assert (checksum_idx < m_bytes.size());
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index ca594a8..2ac7d20 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -11,6 +11,8 @@
#include "GDBRemoteCommunicationClient.h"
// C Includes
+#include <sys/stat.h>
+
// C++ Includes
#include <sstream>
@@ -20,6 +22,7 @@
#include "lldb/Core/ConnectionFileDescriptor.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/State.h"
+#include "lldb/Core/StreamGDBRemote.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/Endian.h"
#include "lldb/Host/Host.h"
@@ -29,10 +32,15 @@
#include "Utility/StringExtractorGDBRemote.h"
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
+#include "lldb/Host/Config.h"
using namespace lldb;
using namespace lldb_private;
+#ifdef LLDB_DISABLE_POSIX
+#define SIGSTOP 17
+#endif
+
//----------------------------------------------------------------------
// GDBRemoteCommunicationClient constructor
//----------------------------------------------------------------------
@@ -56,6 +64,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
m_watchpoints_trigger_after_instruction(eLazyBoolCalculate),
m_attach_or_wait_reply(eLazyBoolCalculate),
m_prepare_for_reg_writing_reply (eLazyBoolCalculate),
+ m_supports_p (eLazyBoolCalculate),
m_supports_qProcessInfoPID (true),
m_supports_qfProcessInfo (true),
m_supports_qUserName (true),
@@ -66,6 +75,8 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
m_supports_z2 (true),
m_supports_z3 (true),
m_supports_z4 (true),
+ m_supports_QEnvironment (true),
+ m_supports_QEnvironmentHexEncoded (true),
m_curr_tid (LLDB_INVALID_THREAD_ID),
m_curr_tid_run (LLDB_INVALID_THREAD_ID),
m_num_supported_hardware_watchpoints (0),
@@ -79,7 +90,11 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
m_process_arch(),
m_os_version_major (UINT32_MAX),
m_os_version_minor (UINT32_MAX),
- m_os_version_update (UINT32_MAX)
+ m_os_version_update (UINT32_MAX),
+ m_os_build (),
+ m_os_kernel (),
+ m_hostname (),
+ m_default_packet_timeout (0)
{
}
@@ -192,6 +207,7 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings()
m_supports_vCont_C = eLazyBoolCalculate;
m_supports_vCont_s = eLazyBoolCalculate;
m_supports_vCont_S = eLazyBoolCalculate;
+ m_supports_p = eLazyBoolCalculate;
m_qHostInfo_is_valid = eLazyBoolCalculate;
m_qProcessInfo_is_valid = eLazyBoolCalculate;
m_supports_alloc_dealloc_memory = eLazyBoolCalculate;
@@ -209,6 +225,8 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings()
m_supports_z2 = true;
m_supports_z3 = true;
m_supports_z4 = true;
+ m_supports_QEnvironment = true;
+ m_supports_QEnvironmentHexEncoded = true;
m_host_arch.Clear();
m_process_arch.Clear();
}
@@ -287,6 +305,32 @@ GDBRemoteCommunicationClient::GetVContSupported (char flavor)
return false;
}
+// Check if the target supports 'p' packet. It sends out a 'p'
+// packet and checks the response. A normal packet will tell us
+// that support is available.
+//
+// Takes a valid thread ID because p needs to apply to a thread.
+bool
+GDBRemoteCommunicationClient::GetpPacketSupported (lldb::tid_t tid)
+{
+ if (m_supports_p == eLazyBoolCalculate)
+ {
+ StringExtractorGDBRemote response;
+ m_supports_p = eLazyBoolNo;
+ char packet[256];
+ if (GetThreadSuffixSupported())
+ snprintf(packet, sizeof(packet), "p0;thread:%" PRIx64 ";", tid);
+ else
+ snprintf(packet, sizeof(packet), "p0");
+
+ if (SendPacketAndWaitForResponse(packet, response, false))
+ {
+ if (response.IsNormalResponse())
+ m_supports_p = eLazyBoolYes;
+ }
+ }
+ return m_supports_p;
+}
size_t
GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
@@ -978,15 +1022,61 @@ GDBRemoteCommunicationClient::SendEnvironmentPacket (char const *name_equal_valu
if (name_equal_value && name_equal_value[0])
{
StreamString packet;
- packet.Printf("QEnvironment:%s", name_equal_value);
+ bool send_hex_encoding = false;
+ for (const char *p = name_equal_value; *p != '\0' && send_hex_encoding == false; ++p)
+ {
+ if (isprint(*p))
+ {
+ switch (*p)
+ {
+ case '$':
+ case '#':
+ send_hex_encoding = true;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ // We have non printable characters, lets hex encode this...
+ send_hex_encoding = true;
+ }
+ }
+
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+ if (send_hex_encoding)
{
- if (response.IsOKResponse())
- return 0;
- uint8_t error = response.GetError();
- if (error)
- return error;
+ if (m_supports_QEnvironmentHexEncoded)
+ {
+ packet.PutCString("QEnvironmentHexEncoded:");
+ packet.PutBytesAsRawHex8 (name_equal_value, strlen(name_equal_value));
+ if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+ {
+ if (response.IsOKResponse())
+ return 0;
+ uint8_t error = response.GetError();
+ if (error)
+ return error;
+ if (response.IsUnsupportedResponse())
+ m_supports_QEnvironmentHexEncoded = false;
+ }
+ }
+
+ }
+ else if (m_supports_QEnvironment)
+ {
+ packet.Printf("QEnvironment:%s", name_equal_value);
+ if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+ {
+ if (response.IsOKResponse())
+ return 0;
+ uint8_t error = response.GetError();
+ if (error)
+ return error;
+ if (response.IsUnsupportedResponse())
+ m_supports_QEnvironment = false;
+ }
}
}
return -1;
@@ -1213,6 +1303,15 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force)
else
--num_keys_decoded;
}
+ else if (name.compare("default_packet_timeout") == 0)
+ {
+ m_default_packet_timeout = Args::StringToUInt32(value.c_str(), 0);
+ if (m_default_packet_timeout > 0)
+ {
+ SetPacketTimeout(m_default_packet_timeout);
+ ++num_keys_decoded;
+ }
+ }
}
@@ -1347,6 +1446,14 @@ GDBRemoteCommunicationClient::GetHostArchitecture ()
return m_host_arch;
}
+uint32_t
+GDBRemoteCommunicationClient::GetHostDefaultPacketTimeout ()
+{
+ if (m_qHostInfo_is_valid == eLazyBoolCalculate)
+ GetHostInfo ();
+ return m_default_packet_timeout;
+}
+
addr_t
GDBRemoteCommunicationClient::AllocateMemory (size_t size, uint32_t permissions)
{
@@ -2132,21 +2239,37 @@ GDBRemoteCommunicationClient::SendSpeedTestPacket (uint32_t send_size, uint32_t
}
uint16_t
-GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort ()
+GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid)
{
+ pid = LLDB_INVALID_PROCESS_ID;
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qLaunchGDBServer", strlen("qLaunchGDBServer"), response, false))
+ StreamString stream;
+ stream.PutCString("qLaunchGDBServer:port:0;");
+ std::string hostname;
+ if (Host::GetHostname (hostname))
+ {
+ // Make the GDB server we launch only accept connections from this host
+ stream.Printf("host:%s;", hostname.c_str());
+ }
+ else
+ {
+ // Make the GDB server we launch accept connections from any host since we can't figure out the hostname
+ stream.Printf("host:*;");
+ }
+ const char *packet = stream.GetData();
+ int packet_len = stream.GetSize();
+
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
{
std::string name;
std::string value;
uint16_t port = 0;
- //lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
while (response.GetNameColonValue(name, value))
{
- if (name.size() == 4 && name.compare("port") == 0)
+ if (name.compare("port") == 0)
port = Args::StringToUInt32(value.c_str(), 0, 0);
-// if (name.size() == 3 && name.compare("pid") == 0)
-// pid = Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0);
+ else if (name.compare("pid") == 0)
+ pid = Args::StringToUInt64(value.c_str(), LLDB_INVALID_PROCESS_ID, 0);
}
return port;
}
@@ -2154,6 +2277,23 @@ GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort ()
}
bool
+GDBRemoteCommunicationClient::KillSpawnedProcess (lldb::pid_t pid)
+{
+ StreamString stream;
+ stream.Printf ("qKillSpawnedProcess:%" PRId64 , pid);
+ const char *packet = stream.GetData();
+ int packet_len = stream.GetSize();
+
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.IsOKResponse())
+ return true;
+ }
+ return false;
+}
+
+bool
GDBRemoteCommunicationClient::SetCurrentThread (uint64_t tid)
{
if (m_curr_tid == tid)
@@ -2222,7 +2362,9 @@ GDBRemoteCommunicationClient::GetThreadStopInfo (lldb::tid_t tid, StringExtracto
assert (packet_len < (int)sizeof(packet));
if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
{
- if (response.IsNormalResponse())
+ if (response.IsUnsupportedResponse())
+ m_supports_qThreadStopInfo = false;
+ else if (response.IsNormalResponse())
return true;
else
return false;
@@ -2232,8 +2374,6 @@ GDBRemoteCommunicationClient::GetThreadStopInfo (lldb::tid_t tid, StringExtracto
m_supports_qThreadStopInfo = false;
}
}
-// if (SetCurrentThread (tid))
-// return GetStopReply (response);
return false;
}
@@ -2346,3 +2486,326 @@ GDBRemoteCommunicationClient::GetShlibInfoAddr()
return LLDB_INVALID_ADDRESS;
}
+lldb_private::Error
+GDBRemoteCommunicationClient::RunShellCommand (const char *command, // Shouldn't be NULL
+ const char *working_dir, // Pass NULL to use the current working directory
+ int *status_ptr, // Pass NULL if you don't want the process exit status
+ int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
+ std::string *command_output, // Pass NULL if you don't want the command output
+ uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish
+{
+ lldb_private::StreamString stream;
+ stream.PutCString("qPlatform_RunCommand:");
+ stream.PutBytesAsRawHex8(command, strlen(command));
+ stream.PutChar(',');
+ stream.PutHex32(timeout_sec);
+ if (working_dir && *working_dir)
+ {
+ stream.PutChar(',');
+ stream.PutBytesAsRawHex8(working_dir, strlen(working_dir));
+ }
+ const char *packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() != 'F')
+ return Error("malformed reply");
+ if (response.GetChar() != ',')
+ return Error("malformed reply");
+ uint32_t exitcode = response.GetHexMaxU32(false, UINT32_MAX);
+ if (exitcode == UINT32_MAX)
+ return Error("unable to run remote process");
+ else if (status_ptr)
+ *status_ptr = exitcode;
+ if (response.GetChar() != ',')
+ return Error("malformed reply");
+ uint32_t signo = response.GetHexMaxU32(false, UINT32_MAX);
+ if (signo_ptr)
+ *signo_ptr = signo;
+ if (response.GetChar() != ',')
+ return Error("malformed reply");
+ std::string output;
+ response.GetEscapedBinaryData(output);
+ if (command_output)
+ command_output->assign(output);
+ return Error();
+ }
+ return Error("unable to send packet");
+}
+
+uint32_t
+GDBRemoteCommunicationClient::MakeDirectory (const std::string &path,
+ mode_t mode)
+{
+ lldb_private::StreamString stream;
+ stream.PutCString("qPlatform_IO_MkDir:");
+ stream.PutHex32(mode);
+ stream.PutChar(',');
+ stream.PutBytesAsRawHex8(path.c_str(), path.size());
+ const char *packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ return response.GetHexMaxU32(false, UINT32_MAX);
+ }
+ return UINT32_MAX;
+
+}
+
+static uint64_t
+ParseHostIOPacketResponse (StringExtractorGDBRemote &response,
+ uint64_t fail_result,
+ Error &error)
+{
+ response.SetFilePos(0);
+ if (response.GetChar() != 'F')
+ return fail_result;
+ int32_t result = response.GetS32 (-2);
+ if (result == -2)
+ return fail_result;
+ if (response.GetChar() == ',')
+ {
+ int result_errno = response.GetS32 (-2);
+ if (result_errno != -2)
+ error.SetError(result_errno, eErrorTypePOSIX);
+ else
+ error.SetError(-1, eErrorTypeGeneric);
+ }
+ else
+ error.Clear();
+ return result;
+}
+lldb::user_id_t
+GDBRemoteCommunicationClient::OpenFile (const lldb_private::FileSpec& file_spec,
+ uint32_t flags,
+ mode_t mode,
+ Error &error)
+{
+ lldb_private::StreamString stream;
+ stream.PutCString("vFile:open:");
+ std::string path (file_spec.GetPath());
+ if (path.empty())
+ return UINT64_MAX;
+ stream.PutCStringAsRawHex8(path.c_str());
+ stream.PutChar(',');
+ const uint32_t posix_open_flags = File::ConvertOpenOptionsForPOSIXOpen(flags);
+ stream.PutHex32(posix_open_flags);
+ stream.PutChar(',');
+ stream.PutHex32(mode);
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ return ParseHostIOPacketResponse (response, UINT64_MAX, error);
+ }
+ return UINT64_MAX;
+}
+
+bool
+GDBRemoteCommunicationClient::CloseFile (lldb::user_id_t fd,
+ Error &error)
+{
+ lldb_private::StreamString stream;
+ stream.Printf("vFile:close:%i", (int)fd);
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ return ParseHostIOPacketResponse (response, -1, error) == 0;
+ }
+ return false;
+}
+
+// Extension of host I/O packets to get the file size.
+lldb::user_id_t
+GDBRemoteCommunicationClient::GetFileSize (const lldb_private::FileSpec& file_spec)
+{
+ lldb_private::StreamString stream;
+ stream.PutCString("vFile:size:");
+ std::string path (file_spec.GetPath());
+ stream.PutCStringAsRawHex8(path.c_str());
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() != 'F')
+ return UINT64_MAX;
+ uint32_t retcode = response.GetHexMaxU64(false, UINT64_MAX);
+ return retcode;
+ }
+ return UINT64_MAX;
+}
+
+uint32_t
+GDBRemoteCommunicationClient::GetFilePermissions(const lldb_private::FileSpec& file_spec, Error &error)
+{
+ lldb_private::StreamString stream;
+ stream.PutCString("vFile:mode:");
+ std::string path (file_spec.GetPath());
+ stream.PutCStringAsRawHex8(path.c_str());
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() != 'F')
+ {
+ error.SetErrorStringWithFormat ("invalid response to '%s' packet", packet);
+ return 0;
+ }
+ const uint32_t mode = response.GetS32(-1);
+ if (mode == -1)
+ {
+ if (response.GetChar() == ',')
+ {
+ int response_errno = response.GetS32(-1);
+ if (response_errno > 0)
+ error.SetError(response_errno, lldb::eErrorTypePOSIX);
+ else
+ error.SetErrorToGenericError();
+ }
+ }
+ else
+ error.Clear();
+ return mode & (S_IRWXU|S_IRWXG|S_IRWXO);
+ }
+ else
+ {
+ error.SetErrorStringWithFormat ("failed to send '%s' packet", packet);
+ }
+ return 0;
+}
+
+uint64_t
+GDBRemoteCommunicationClient::ReadFile (lldb::user_id_t fd,
+ uint64_t offset,
+ void *dst,
+ uint64_t dst_len,
+ Error &error)
+{
+ lldb_private::StreamString stream;
+ stream.Printf("vFile:pread:%i,%" PRId64 ",%" PRId64, (int)fd, dst_len, offset);
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() != 'F')
+ return 0;
+ uint32_t retcode = response.GetHexMaxU32(false, UINT32_MAX);
+ if (retcode == UINT32_MAX)
+ return retcode;
+ const char next = (response.Peek() ? *response.Peek() : 0);
+ if (next == ',')
+ return 0;
+ if (next == ';')
+ {
+ response.GetChar(); // skip the semicolon
+ std::string buffer;
+ if (response.GetEscapedBinaryData(buffer))
+ {
+ const uint64_t data_to_write = std::min<uint64_t>(dst_len, buffer.size());
+ if (data_to_write > 0)
+ memcpy(dst, &buffer[0], data_to_write);
+ return data_to_write;
+ }
+ }
+ }
+ return 0;
+}
+
+uint64_t
+GDBRemoteCommunicationClient::WriteFile (lldb::user_id_t fd,
+ uint64_t offset,
+ const void* src,
+ uint64_t src_len,
+ Error &error)
+{
+ lldb_private::StreamGDBRemote stream;
+ stream.Printf("vFile:pwrite:%i,%" PRId64 ",", (int)fd, offset);
+ stream.PutEscapedBytes(src, src_len);
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() != 'F')
+ {
+ error.SetErrorStringWithFormat("write file failed");
+ return 0;
+ }
+ uint64_t bytes_written = response.GetU64(UINT64_MAX);
+ if (bytes_written == UINT64_MAX)
+ {
+ error.SetErrorToGenericError();
+ if (response.GetChar() == ',')
+ {
+ int response_errno = response.GetS32(-1);
+ if (response_errno > 0)
+ error.SetError(response_errno, lldb::eErrorTypePOSIX);
+ }
+ return 0;
+ }
+ return bytes_written;
+ }
+ else
+ {
+ error.SetErrorString ("failed to send vFile:pwrite packet");
+ }
+ return 0;
+}
+
+// Extension of host I/O packets to get whether a file exists.
+bool
+GDBRemoteCommunicationClient::GetFileExists (const lldb_private::FileSpec& file_spec)
+{
+ lldb_private::StreamString stream;
+ stream.PutCString("vFile:exists:");
+ std::string path (file_spec.GetPath());
+ stream.PutCStringAsRawHex8(path.c_str());
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() != 'F')
+ return false;
+ if (response.GetChar() != ',')
+ return false;
+ bool retcode = (response.GetChar() != '0');
+ return retcode;
+ }
+ return false;
+}
+
+bool
+GDBRemoteCommunicationClient::CalculateMD5 (const lldb_private::FileSpec& file_spec,
+ uint64_t &high,
+ uint64_t &low)
+{
+ lldb_private::StreamString stream;
+ stream.PutCString("vFile:MD5:");
+ std::string path (file_spec.GetPath());
+ stream.PutCStringAsRawHex8(path.c_str());
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() != 'F')
+ return false;
+ if (response.GetChar() != ',')
+ return false;
+ if (response.Peek() && *response.Peek() == 'x')
+ return false;
+ low = response.GetHexMaxU64(false, UINT64_MAX);
+ high = response.GetHexMaxU64(false, UINT64_MAX);
+ return true;
+ }
+ return false;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index 5bb8387..d5535bb 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -89,7 +89,10 @@ public:
GetLaunchSuccess (std::string &error_str);
uint16_t
- LaunchGDBserverAndGetPort ();
+ LaunchGDBserverAndGetPort (lldb::pid_t &pid);
+
+ bool
+ KillSpawnedProcess (lldb::pid_t pid);
//------------------------------------------------------------------
/// Sends a GDB remote protocol 'A' packet that delivers program
@@ -217,6 +220,9 @@ public:
const lldb_private::ArchSpec &
GetHostArchitecture ();
+
+ uint32_t
+ GetHostDefaultPacketTimeout();
const lldb_private::ArchSpec &
GetProcessArchitecture ();
@@ -225,6 +231,9 @@ public:
GetVContSupported (char flavor);
bool
+ GetpPacketSupported (lldb::tid_t tid);
+
+ bool
GetVAttachOrWaitSupported ();
bool
@@ -347,10 +356,61 @@ public:
return m_interrupt_sent;
}
+ virtual lldb::user_id_t
+ OpenFile (const lldb_private::FileSpec& file_spec,
+ uint32_t flags,
+ mode_t mode,
+ lldb_private::Error &error);
+
+ virtual bool
+ CloseFile (lldb::user_id_t fd,
+ lldb_private::Error &error);
+
+ virtual lldb::user_id_t
+ GetFileSize (const lldb_private::FileSpec& file_spec);
+
+ virtual uint32_t
+ GetFilePermissions(const lldb_private::FileSpec& file_spec,
+ lldb_private::Error &error);
+
+ virtual uint64_t
+ ReadFile (lldb::user_id_t fd,
+ uint64_t offset,
+ void *dst,
+ uint64_t dst_len,
+ lldb_private::Error &error);
+
+ virtual uint64_t
+ WriteFile (lldb::user_id_t fd,
+ uint64_t offset,
+ const void* src,
+ uint64_t src_len,
+ lldb_private::Error &error);
+
+ virtual uint32_t
+ MakeDirectory (const std::string &path,
+ mode_t mode);
+
+ virtual bool
+ GetFileExists (const lldb_private::FileSpec& file_spec);
+
+ virtual lldb_private::Error
+ RunShellCommand (const char *command, // Shouldn't be NULL
+ const char *working_dir, // Pass NULL to use the current working directory
+ int *status_ptr, // Pass NULL if you don't want the process exit status
+ int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
+ std::string *command_output, // Pass NULL if you don't want the command output
+ uint32_t timeout_sec); // Timeout in seconds to wait for shell program to finish
+
+ virtual bool
+ CalculateMD5 (const lldb_private::FileSpec& file_spec,
+ uint64_t &high,
+ uint64_t &low);
+
std::string
HarmonizeThreadIdsForProfileData (ProcessGDBRemote *process,
StringExtractorGDBRemote &inputStringExtractor);
-
+
protected:
bool
@@ -377,6 +437,7 @@ protected:
lldb_private::LazyBool m_watchpoints_trigger_after_instruction;
lldb_private::LazyBool m_attach_or_wait_reply;
lldb_private::LazyBool m_prepare_for_reg_writing_reply;
+ lldb_private::LazyBool m_supports_p;
bool
m_supports_qProcessInfoPID:1,
@@ -388,7 +449,9 @@ protected:
m_supports_z1:1,
m_supports_z2:1,
m_supports_z3:1,
- m_supports_z4:1;
+ m_supports_z4:1,
+ m_supports_QEnvironment:1,
+ m_supports_QEnvironmentHexEncoded:1;
lldb::tid_t m_curr_tid; // Current gdb remote protocol thread index for all other operations
@@ -416,6 +479,7 @@ protected:
std::string m_os_build;
std::string m_os_kernel;
std::string m_hostname;
+ uint32_t m_default_packet_timeout;
bool
DecodeProcessInfoResponse (StringExtractorGDBRemote &response,
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index 3a14e9f..df036cd 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -7,8 +7,10 @@
//
//===----------------------------------------------------------------------===//
+#include <errno.h>
#include "GDBRemoteCommunicationServer.h"
+#include "lldb/Core/StreamGDBRemote.h"
// C Includes
// C++ Includes
@@ -20,6 +22,7 @@
#include "lldb/Core/State.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/Endian.h"
+#include "lldb/Host/File.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/TimeValue.h"
#include "lldb/Target/Process.h"
@@ -40,11 +43,31 @@ GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) :
m_async_thread (LLDB_INVALID_HOST_THREAD),
m_process_launch_info (),
m_process_launch_error (),
+ m_spawned_pids (),
+ m_spawned_pids_mutex (Mutex::eMutexTypeRecursive),
m_proc_infos (),
m_proc_infos_index (0),
m_lo_port_num (0),
- m_hi_port_num (0)
+ m_hi_port_num (0),
+ m_next_port (0),
+ m_use_port_range (false)
{
+ // We seldom need to override the port number that the debugserver process
+ // starts with. We just pass in 0 to let the system choose a random port.
+ // In rare situation where the need arises, use two environment variables
+ // to override.
+ uint16_t lo_port_num = 0;
+ uint16_t hi_port_num = 0;
+ const char *lo_port_c_str = getenv("LLDB_PLATFORM_START_DEBUG_SERVER_LO_PORT");
+ if (lo_port_c_str)
+ lo_port_num = ::atoi(lo_port_c_str);
+ const char *hi_port_c_str = getenv("LLDB_PLATFORM_START_DEBUG_SERVER_HI_PORT");
+ if (hi_port_c_str)
+ hi_port_num = ::atoi(hi_port_c_str);
+ if (lo_port_num && hi_port_num && lo_port_num < hi_port_num)
+ {
+ SetPortRange(lo_port_num, hi_port_num);
+ }
}
//----------------------------------------------------------------------
@@ -65,7 +88,7 @@ GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer()
// log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID());
//
// StringExtractorGDBRemote packet;
-//
+//
// while ()
// {
// if (packet.
@@ -79,9 +102,9 @@ GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer()
//}
//
bool
-GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
+GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
Error &error,
- bool &interrupt,
+ bool &interrupt,
bool &quit)
{
StringExtractorGDBRemote packet;
@@ -103,7 +126,7 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
error.SetErrorString("interrupt received");
interrupt = true;
break;
-
+
case StringExtractorGDBRemote::eServerPacketType_unimplemented:
return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0;
@@ -112,22 +135,25 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo:
return Handle_qfProcessInfo (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo:
return Handle_qsProcessInfo (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_qC:
return Handle_qC (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_qHostInfo:
return Handle_qHostInfo (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer:
return Handle_qLaunchGDBServer (packet);
-
+
+ case StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess:
+ return Handle_qKillSpawnedProcess (packet);
+
case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess:
return Handle_qLaunchSuccess (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_qGroupName:
return Handle_qGroupName (packet);
@@ -142,24 +168,60 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
case StringExtractorGDBRemote::eServerPacketType_QEnvironment:
return Handle_QEnvironment (packet);
-
+
+ case StringExtractorGDBRemote::eServerPacketType_QLaunchArch:
+ return Handle_QLaunchArch (packet);
+
case StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR:
return Handle_QSetDisableASLR (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN:
return Handle_QSetSTDIN (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT:
return Handle_QSetSTDOUT (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_QSetSTDERR:
return Handle_QSetSTDERR (packet);
-
+
case StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir:
return Handle_QSetWorkingDir (packet);
case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
return Handle_QStartNoAckMode (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_qPlatform_IO_MkDir:
+ return Handle_qPlatform_IO_MkDir (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_qPlatform_RunCommand:
+ return Handle_qPlatform_RunCommand (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_Open:
+ return Handle_vFile_Open (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_Close:
+ return Handle_vFile_Close (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_pRead:
+ return Handle_vFile_pRead (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_pWrite:
+ return Handle_vFile_pWrite (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_Size:
+ return Handle_vFile_Size (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_Mode:
+ return Handle_vFile_Mode (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_Exists:
+ return Handle_vFile_Exists (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_Stat:
+ return Handle_vFile_Stat (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_MD5:
+ return Handle_vFile_MD5 (packet);
}
return true;
}
@@ -207,7 +269,7 @@ bool
GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet)
{
StreamString response;
-
+
// $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00
ArchSpec host_arch (Host::GetArchitecture ());
@@ -222,12 +284,12 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet
response.Printf ("cputype:%u;", cpu);
if (sub != LLDB_INVALID_CPUTYPE)
response.Printf ("cpusubtype:%u;", sub);
-
+
if (cpu == ArchSpec::kCore_arm_any)
response.Printf("watchpoint_exceptions_received:before;"); // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
else
response.Printf("watchpoint_exceptions_received:after;");
-
+
switch (lldb::endian::InlHostByteOrder())
{
case eByteOrderBig: response.PutCString ("endian:big;"); break;
@@ -235,7 +297,7 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet
case eByteOrderPDP: response.PutCString ("endian:pdp;"); break;
default: response.PutCString ("endian:unknown;"); break;
}
-
+
uint32_t major = UINT32_MAX;
uint32_t minor = UINT32_MAX;
uint32_t update = UINT32_MAX;
@@ -273,7 +335,7 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet
response.PutCStringAsRawHex8(s.c_str());
response.PutChar(';');
}
-
+
return SendPacketNoLock (response.GetData(), response.GetSize()) > 0;
}
@@ -319,7 +381,7 @@ GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &
return SendErrorResponse (1);
}
-bool
+bool
GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet)
{
m_proc_infos_index = 0;
@@ -329,7 +391,7 @@ GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &pa
packet.SetFilePos(::strlen ("qfProcessInfo"));
if (packet.GetChar() == ':')
{
-
+
std::string key;
std::string value;
while (packet.GetNameColonValue(key, value))
@@ -360,11 +422,11 @@ GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &pa
{
match_info.SetNameMatchType (eNameMatchContains);
}
- else if (value.compare("regex") == 0)
+ else if (value.compare("regex") == 0)
{
match_info.SetNameMatchType (eNameMatchRegularExpression);
}
- else
+ else
{
success = false;
}
@@ -405,7 +467,7 @@ GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &pa
{
success = false;
}
-
+
if (!success)
return SendErrorResponse (2);
}
@@ -420,7 +482,7 @@ GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &pa
return SendErrorResponse (3);
}
-bool
+bool
GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet)
{
if (m_proc_infos_index < m_proc_infos.GetSize())
@@ -433,7 +495,7 @@ GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &pa
return SendErrorResponse (4);
}
-bool
+bool
GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet)
{
// Packet format: "qUserName:%i" where %i is the uid
@@ -450,10 +512,10 @@ GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet
}
}
return SendErrorResponse (5);
-
+
}
-bool
+bool
GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet)
{
// Packet format: "qGroupName:%i" where %i is the gid
@@ -539,11 +601,11 @@ AcceptPortFromInferior (void *arg)
// for (int i=0; i<num_retries; i++)
// {
// struct proc_bsdinfo bsd_info;
-// int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO,
-// (uint64_t) 0,
-// &bsd_info,
+// int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO,
+// (uint64_t) 0,
+// &bsd_info,
// PROC_PIDTBSDINFO_SIZE);
-//
+//
// switch (error)
// {
// case EINVAL:
@@ -551,10 +613,10 @@ AcceptPortFromInferior (void *arg)
// case ESRCH:
// case EPERM:
// return false;
-//
+//
// default:
// break;
-//
+//
// case 0:
// if (bsd_info.pbi_status == SSTOP)
// return true;
@@ -567,9 +629,9 @@ AcceptPortFromInferior (void *arg)
bool
GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
{
- // The 'A' packet is the most over designed packet ever here with
- // redundant argument indexes, redundant argument lengths and needed hex
- // encoded argument string values. Really all that is needed is a comma
+ // The 'A' packet is the most over designed packet ever here with
+ // redundant argument indexes, redundant argument lengths and needed hex
+ // encoded argument string values. Really all that is needed is a comma
// separated hex encoded argument value list, but we will stay true to the
// documented version of the 'A' packet here...
@@ -615,7 +677,7 @@ GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
if (packet.GetChar() != ',')
success = false;
}
-
+
if (success)
{
if (arg_idx == 0)
@@ -649,11 +711,11 @@ GDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet)
response.Printf("QC%" PRIx64, pid);
if (m_is_platform)
{
- // If we launch a process and this GDB server is acting as a platform,
- // then we need to clear the process launch state so we can start
+ // If we launch a process and this GDB server is acting as a platform,
+ // then we need to clear the process launch state so we can start
// launching another process. In order to launch a process a bunch or
// packets need to be sent: environment packets, working directory,
- // disable ASLR, and many more settings. When we launch a process we
+ // disable ASLR, and many more settings. When we launch a process we
// then need to know when to clear this information. Currently we are
// selecting the 'qC' packet as that packet which seems to make the most
// sense.
@@ -666,8 +728,30 @@ GDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet)
}
bool
+GDBRemoteCommunicationServer::DebugserverProcessReaped (lldb::pid_t pid)
+{
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ return m_spawned_pids.erase(pid) > 0;
+}
+bool
+GDBRemoteCommunicationServer::ReapDebugserverProcess (void *callback_baton,
+ lldb::pid_t pid,
+ bool exited,
+ int signal, // Zero for no signal
+ int status) // Exit value of process if signal is zero
+{
+ GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer *)callback_baton;
+ server->DebugserverProcessReaped (pid);
+ return true;
+}
+
+bool
GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
{
+#ifdef _WIN32
+ // No unix sockets on windows
+ return false;
+#else
// Spawn a local debugserver as a platform so we can then attach or launch
// a process...
@@ -677,49 +761,101 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote
ConnectionFileDescriptor file_conn;
char connect_url[PATH_MAX];
Error error;
- char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX";
- if (::mktemp (unix_socket_name) == NULL)
+ std::string hostname;
+ // TODO: /tmp/ should not be hardcoded. User might want to override /tmp
+ // with the TMPDIR environnement variable
+ char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX";
+ if (::mkstemp (unix_socket_name) == -1)
{
- error.SetErrorString ("failed to make temporary path for a unix socket");
+ error.SetErrorStringWithFormat("failed to make temporary path for a unix socket: %s", strerror(errno));
}
else
{
+ packet.SetFilePos(::strlen ("qLaunchGDBServer:"));
+ std::string name;
+ std::string value;
+ uint16_t port = UINT16_MAX;
+ while (packet.GetNameColonValue(name, value))
+ {
+ if (name.compare ("host") == 0)
+ hostname.swap(value);
+ else if (name.compare ("port") == 0)
+ port = Args::StringToUInt32(value.c_str(), 0, 0);
+ }
+ if (port == UINT16_MAX)
+ port = GetAndUpdateNextPort();
+
::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name);
// Spawn a new thread to accept the port that gets bound after
// binding to port 0 (zero).
- lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name,
- AcceptPortFromInferior,
- connect_url,
- &error);
-
+ lldb::thread_t accept_thread = LLDB_INVALID_HOST_THREAD;
+
+ if (port == 0)
+ {
+ accept_thread = Host::ThreadCreate (unix_socket_name,
+ AcceptPortFromInferior,
+ connect_url,
+ &error);
+ }
+
if (IS_VALID_LLDB_HOST_THREAD(accept_thread))
{
- // Spawn a debugserver and try to get
+ // Spawn a debugserver and try to get the port it listens to.
ProcessLaunchInfo debugserver_launch_info;
- error = StartDebugserverProcess ("localhost:0",
- unix_socket_name,
+ StreamString host_and_port;
+ if (hostname.empty())
+ hostname = "localhost";
+ host_and_port.Printf("%s:%u", hostname.c_str(), port);
+ const char *host_and_port_cstr = host_and_port.GetString().c_str();
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf("Launching debugserver with: %s...\n", host_and_port_cstr);
+ error = StartDebugserverProcess (host_and_port_cstr,
+ unix_socket_name,
debugserver_launch_info);
-
+
lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
+
+ if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
+ {
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ m_spawned_pids.insert(debugserver_pid);
+ }
+ Host::StartMonitoringChildProcess (ReapDebugserverProcess, this, debugserver_pid, false);
+ }
+
if (error.Success())
{
bool success = false;
-
- thread_result_t accept_thread_result = NULL;
- if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
+
+ if (accept_thread)
{
- if (accept_thread_result)
+ thread_result_t accept_thread_result = NULL;
+ if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
{
- uint16_t port = (intptr_t)accept_thread_result;
- char response[256];
- const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port);
- assert (response_len < (int)sizeof(response));
- //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
- success = SendPacketNoLock (response, response_len) > 0;
+ if (accept_thread_result)
+ {
+ port = (intptr_t)accept_thread_result;
+ char response[256];
+ const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port);
+ assert (response_len < sizeof(response));
+ //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
+ success = SendPacketNoLock (response, response_len) > 0;
+ }
}
}
+ else
+ {
+ char response[256];
+ const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port);
+ assert (response_len < sizeof(response));
+ //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
+ success = SendPacketNoLock (response, response_len) > 0;
+
+ }
::unlink (unix_socket_name);
-
+
if (!success)
{
if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
@@ -730,7 +866,61 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote
}
}
}
- return SendErrorResponse (13);
+ return SendErrorResponse (9);
+#endif
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
+{
+ // Spawn a local debugserver as a platform so we can then attach or launch
+ // a process...
+
+ if (m_is_platform)
+ {
+ packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
+
+ lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
+
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return SendErrorResponse (10);
+ }
+ Host::Kill (pid, SIGTERM);
+
+ for (size_t i=0; i<10; ++i)
+ {
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return true;
+ }
+ usleep (10000);
+ }
+
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return true;
+ }
+ Host::Kill (pid, SIGKILL);
+
+ for (size_t i=0; i<10; ++i)
+ {
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return true;
+ }
+ usleep (10000);
+ }
+ }
+ return SendErrorResponse (10);
}
bool
@@ -738,7 +928,7 @@ GDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &p
{
if (m_process_launch_error.Success())
return SendOKResponse();
- StreamString response;
+ StreamString response;
response.PutChar('E');
response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
return SendPacketNoLock (response.GetData(), response.GetSize());
@@ -754,7 +944,22 @@ GDBRemoteCommunicationServer::Handle_QEnvironment (StringExtractorGDBRemote &pa
m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
return SendOKResponse ();
}
- return SendErrorResponse (9);
+ return SendErrorResponse (11);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_QLaunchArch (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen ("QLaunchArch:"));
+ const uint32_t bytes_left = packet.GetBytesLeft();
+ if (bytes_left > 0)
+ {
+ const char* arch_triple = packet.Peek();
+ ArchSpec arch_spec(arch_triple,NULL);
+ m_process_launch_info.SetArchitecture(arch_spec);
+ return SendOKResponse();
+ }
+ return SendErrorResponse(12);
}
bool
@@ -792,7 +997,7 @@ GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet
m_process_launch_info.AppendFileAction(file_action);
return SendOKResponse ();
}
- return SendErrorResponse (10);
+ return SendErrorResponse (13);
}
bool
@@ -809,7 +1014,7 @@ GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packe
m_process_launch_info.AppendFileAction(file_action);
return SendOKResponse ();
}
- return SendErrorResponse (11);
+ return SendErrorResponse (14);
}
bool
@@ -826,7 +1031,7 @@ GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packe
m_process_launch_info.AppendFileAction(file_action);
return SendOKResponse ();
}
- return SendErrorResponse (12);
+ return SendErrorResponse (15);
}
bool
@@ -837,3 +1042,277 @@ GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &
m_send_acks = false;
return true;
}
+
+bool
+GDBRemoteCommunicationServer::Handle_qPlatform_IO_MkDir (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("qPlatform_IO_MkDir:"));
+ mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
+ if (packet.GetChar() != ',')
+ return false;
+ std::string path;
+ packet.GetHexByteString(path);
+ uint32_t retcode = Host::MakeDirectory(path.c_str(),mode);
+ StreamString response;
+ response.PutHex32(retcode);
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_Open (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("vFile:open:"));
+ std::string path;
+ packet.GetHexByteStringTerminatedBy(path,',');
+ if (path.size() == 0)
+ return false;
+ if (packet.GetChar() != ',')
+ return false;
+ uint32_t flags = packet.GetHexMaxU32(false, UINT32_MAX);
+ if (packet.GetChar() != ',')
+ return false;
+ mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
+ Error error;
+ int fd = ::open (path.c_str(), flags, mode);
+ const int save_errno = fd == -1 ? errno : 0;
+ StreamString response;
+ response.PutChar('F');
+ response.Printf("%i", fd);
+ if (save_errno)
+ response.Printf(",%i", save_errno);
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_Close (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("vFile:close:"));
+ int fd = packet.GetS32(-1);
+ Error error;
+ int err = -1;
+ int save_errno = 0;
+ if (fd >= 0)
+ {
+ err = close(fd);
+ save_errno = err == -1 ? errno : 0;
+ }
+ else
+ {
+ save_errno = EINVAL;
+ }
+ StreamString response;
+ response.PutChar('F');
+ response.Printf("%i", err);
+ if (save_errno)
+ response.Printf(",%i", save_errno);
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_pRead (StringExtractorGDBRemote &packet)
+{
+#ifdef _WIN32
+ // Not implemented on Windows
+ return false;
+#else
+ StreamGDBRemote response;
+ packet.SetFilePos(::strlen("vFile:pread:"));
+ int fd = packet.GetS32(-1);
+ if (packet.GetChar() != ',')
+ return false;
+ uint64_t count = packet.GetU64(UINT64_MAX);
+ if (packet.GetChar() != ',')
+ return false;
+ uint64_t offset = packet.GetU64(UINT32_MAX);
+ if (count == UINT64_MAX)
+ {
+ response.Printf("F-1:%i", EINVAL);
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+ }
+ std::string buffer(count, 0);
+ const ssize_t bytes_read = ::pread (fd, &buffer[0], buffer.size(), offset);
+ const int save_errno = bytes_read == -1 ? errno : 0;
+ response.PutChar('F');
+ response.Printf("%zi", bytes_read);
+ if (save_errno)
+ response.Printf(",%i", save_errno);
+ else
+ {
+ response.PutChar(';');
+ response.PutEscapedBytes(&buffer[0], bytes_read);
+ }
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+#endif
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_pWrite (StringExtractorGDBRemote &packet)
+{
+#ifdef _WIN32
+ // Not implemented on Windows
+ return false;
+#else
+ packet.SetFilePos(::strlen("vFile:pwrite:"));
+
+ StreamGDBRemote response;
+ response.PutChar('F');
+
+ int fd = packet.GetU32(UINT32_MAX);
+ if (packet.GetChar() != ',')
+ return false;
+ off_t offset = packet.GetU64(UINT32_MAX);
+ if (packet.GetChar() != ',')
+ return false;
+ std::string buffer;
+ if (packet.GetEscapedBinaryData(buffer))
+ {
+ const ssize_t bytes_written = ::pwrite (fd, buffer.data(), buffer.size(), offset);
+ const int save_errno = bytes_written == -1 ? errno : 0;
+ response.Printf("%zi", bytes_written);
+ if (save_errno)
+ response.Printf(",%i", save_errno);
+ }
+ else
+ {
+ response.Printf ("-1,%i", EINVAL);
+ }
+
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+#endif
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_Size (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("vFile:size:"));
+ std::string path;
+ packet.GetHexByteString(path);
+ if (path.empty())
+ return false;
+ lldb::user_id_t retcode = Host::GetFileSize(FileSpec(path.c_str(), false));
+ StreamString response;
+ response.PutChar('F');
+ response.PutHex64(retcode);
+ if (retcode == UINT64_MAX)
+ {
+ response.PutChar(',');
+ response.PutHex64(retcode); // TODO: replace with Host::GetSyswideErrorCode()
+ }
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_Mode (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("vFile:mode:"));
+ std::string path;
+ packet.GetHexByteString(path);
+ if (path.empty())
+ return false;
+ Error error;
+ const uint32_t mode = File::GetPermissions(path.c_str(), error);
+ StreamString response;
+ response.Printf("F%u", mode);
+ if (mode == 0 || error.Fail())
+ response.Printf(",%i", (int)error.GetError());
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_Exists (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("vFile:exists:"));
+ std::string path;
+ packet.GetHexByteString(path);
+ if (path.empty())
+ return false;
+ bool retcode = Host::GetFileExists(FileSpec(path.c_str(), false));
+ StreamString response;
+ response.PutChar('F');
+ response.PutChar(',');
+ if (retcode)
+ response.PutChar('1');
+ else
+ response.PutChar('0');
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_qPlatform_RunCommand (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("qPlatform_RunCommand:"));
+ std::string path;
+ std::string working_dir;
+ packet.GetHexByteStringTerminatedBy(path,',');
+ if (path.size() == 0)
+ return false;
+ if (packet.GetChar() != ',')
+ return false;
+ // FIXME: add timeout to qPlatform_RunCommand packet
+ // uint32_t timeout = packet.GetHexMaxU32(false, 32);
+ uint32_t timeout = 10;
+ if (packet.GetChar() == ',')
+ packet.GetHexByteString(working_dir);
+ int status, signo;
+ std::string output;
+ Error err = Host::RunShellCommand(path.c_str(),
+ working_dir.empty() ? NULL : working_dir.c_str(),
+ &status, &signo, &output, timeout);
+ StreamGDBRemote response;
+ if (err.Fail())
+ {
+ response.PutCString("F,");
+ response.PutHex32(UINT32_MAX);
+ }
+ else
+ {
+ response.PutCString("F,");
+ response.PutHex32(status);
+ response.PutChar(',');
+ response.PutHex32(signo);
+ response.PutChar(',');
+ response.PutEscapedBytes(output.c_str(), output.size());
+ }
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_Stat (StringExtractorGDBRemote &packet)
+{
+ return false;
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_MD5 (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("vFile:exists:"));
+ std::string path;
+ packet.GetHexByteString(path);
+ if (path.size() == 0)
+ return false;
+ uint64_t a,b;
+ StreamGDBRemote response;
+ if (Host::CalculateMD5(FileSpec(path.c_str(),false),a,b) == false)
+ {
+ response.PutCString("F,");
+ response.PutCString("x");
+ }
+ else
+ {
+ response.PutCString("F,");
+ response.PutHex64(a);
+ response.PutHex64(b);
+ }
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
index cce0e4e..64f6f8d 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -12,10 +12,12 @@
// C Includes
// C++ Includes
+#include <vector>
+#include <set>
// Other libraries and framework includes
// Project includes
+#include "lldb/Host/Mutex.h"
#include "lldb/Target/Process.h"
-
#include "GDBRemoteCommunication.h"
class ProcessGDBRemote;
@@ -60,6 +62,21 @@ public:
{
m_lo_port_num = lo_port_num;
m_hi_port_num = hi_port_num;
+ m_next_port = m_lo_port_num;
+ m_use_port_range = true;
+ }
+
+ // If we are using a port range, get and update the next port to be used variable.
+ // Otherwise, just return 0.
+ uint16_t
+ GetAndUpdateNextPort ()
+ {
+ if (!m_use_port_range)
+ return 0;
+ uint16_t val = m_next_port;
+ if (++m_next_port > m_hi_port_num)
+ m_next_port = m_lo_port_num;
+ return val;
}
protected:
@@ -68,11 +85,16 @@ protected:
lldb::thread_t m_async_thread;
lldb_private::ProcessLaunchInfo m_process_launch_info;
lldb_private::Error m_process_launch_error;
+ std::set<lldb::pid_t> m_spawned_pids;
+ lldb_private::Mutex m_spawned_pids_mutex;
lldb_private::ProcessInstanceInfoList m_proc_infos;
uint32_t m_proc_infos_index;
uint16_t m_lo_port_num;
uint16_t m_hi_port_num;
//PortToPIDMap m_port_to_pid_map;
+ uint16_t m_next_port;
+ bool m_use_port_range;
+
size_t
SendUnimplementedResponse (const char *packet);
@@ -85,7 +107,7 @@ protected:
bool
Handle_A (StringExtractorGDBRemote &packet);
-
+
bool
Handle_qLaunchSuccess (StringExtractorGDBRemote &packet);
@@ -94,8 +116,14 @@ protected:
bool
Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet);
bool
+ Handle_qPlatform_IO_MkDir (StringExtractorGDBRemote &packet);
+
+ bool
Handle_qProcessInfoPID (StringExtractorGDBRemote &packet);
bool
@@ -120,6 +148,9 @@ protected:
Handle_QEnvironment (StringExtractorGDBRemote &packet);
bool
+ Handle_QLaunchArch (StringExtractorGDBRemote &packet);
+
+ bool
Handle_QSetDisableASLR (StringExtractorGDBRemote &packet);
bool
@@ -137,7 +168,47 @@ protected:
bool
Handle_QSetSTDERR (StringExtractorGDBRemote &packet);
+ bool
+ Handle_vFile_Open (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_Close (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_pRead (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_pWrite (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_Size (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_Mode (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_Exists (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_Stat (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_MD5 (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_qPlatform_RunCommand (StringExtractorGDBRemote &packet);
+
private:
+ bool
+ DebugserverProcessReaped (lldb::pid_t pid);
+
+ static bool
+ ReapDebugserverProcess (void *callback_baton,
+ lldb::pid_t pid,
+ bool exited,
+ int signal,
+ int status);
+
//------------------------------------------------------------------
// For GDBRemoteCommunicationServer only
//------------------------------------------------------------------
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index b1612a5..c4e468f 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -17,6 +17,9 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/StreamString.h"
+#ifndef LLDB_DISABLE_PYTHON
+#include "lldb/Interpreter/PythonDataObjects.h"
+#endif
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Utility/Utils.h"
// Project includes
@@ -54,7 +57,7 @@ GDBRemoteRegisterContext::GDBRemoteRegisterContext
// Make a heap based buffer that is big enough to store all registers
DataBufferSP reg_data_sp(new DataBufferHeap (reg_info.GetRegisterDataByteSize(), 0));
m_reg_data.SetData (reg_data_sp);
-
+ m_reg_data.SetByteOrder(thread.GetProcess()->GetByteOrder());
}
//----------------------------------------------------------------------
@@ -696,6 +699,7 @@ GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber (uint32_t kind, ui
return m_reg_info.ConvertRegisterKindToRegisterNumber (kind, num);
}
+
void
GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch)
{
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
index 3110ddf..7a49d69 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -21,23 +21,20 @@
#include "lldb/Core/ConstString.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Target/RegisterContext.h"
+#include "Plugins/Process/Utility/DynamicRegisterInfo.h"
+
#include "GDBRemoteCommunicationClient.h"
class ThreadGDBRemote;
class ProcessGDBRemote;
class StringExtractor;
-class GDBRemoteDynamicRegisterInfo
+class GDBRemoteDynamicRegisterInfo :
+ public DynamicRegisterInfo
{
public:
GDBRemoteDynamicRegisterInfo () :
- m_regs (),
- m_sets (),
- m_set_reg_nums (),
- m_reg_names (),
- m_reg_alt_names (),
- m_set_names (),
- m_reg_data_byte_size (0)
+ DynamicRegisterInfo()
{
}
@@ -46,151 +43,8 @@ public:
}
void
- AddRegister (lldb_private::RegisterInfo reg_info,
- lldb_private::ConstString &reg_name,
- lldb_private::ConstString &reg_alt_name,
- lldb_private::ConstString &set_name)
- {
- const uint32_t reg_num = (uint32_t)m_regs.size();
- m_reg_names.push_back (reg_name);
- m_reg_alt_names.push_back (reg_alt_name);
- reg_info.name = reg_name.AsCString();
- assert (reg_info.name);
- reg_info.alt_name = reg_alt_name.AsCString(NULL);
- uint32_t i;
- if (reg_info.value_regs)
- {
- for (i=0; reg_info.value_regs[i] != LLDB_INVALID_REGNUM; ++i)
- m_value_regs_map[reg_num].push_back(reg_info.value_regs[i]);
- m_value_regs_map[reg_num].push_back(LLDB_INVALID_REGNUM);
- reg_info.value_regs = m_value_regs_map[reg_num].data();
- }
- if (reg_info.invalidate_regs)
- {
- for (i=0; reg_info.invalidate_regs[i] != LLDB_INVALID_REGNUM; ++i)
- m_invalidate_regs_map[reg_num].push_back(reg_info.invalidate_regs[i]);
- m_invalidate_regs_map[reg_num].push_back(LLDB_INVALID_REGNUM);
- reg_info.invalidate_regs = m_invalidate_regs_map[reg_num].data();
- }
- m_regs.push_back (reg_info);
- uint32_t set = GetRegisterSetIndexByName (set_name);
- assert (set < m_sets.size());
- assert (set < m_set_reg_nums.size());
- assert (set < m_set_names.size());
- m_set_reg_nums[set].push_back(reg_num);
- size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size;
- if (m_reg_data_byte_size < end_reg_offset)
- m_reg_data_byte_size = end_reg_offset;
- }
-
- void
- Finalize ()
- {
- for (uint32_t set = 0; set < m_sets.size(); ++set)
- {
- assert (m_sets.size() == m_set_reg_nums.size());
- m_sets[set].num_registers = m_set_reg_nums[set].size();
- m_sets[set].registers = &m_set_reg_nums[set][0];
- }
- }
-
- size_t
- GetNumRegisters() const
- {
- return m_regs.size();
- }
-
- size_t
- GetNumRegisterSets() const
- {
- return m_sets.size();
- }
-
- size_t
- GetRegisterDataByteSize() const
- {
- return m_reg_data_byte_size;
- }
-
- const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (uint32_t i) const
- {
- if (i < m_regs.size())
- return &m_regs[i];
- return NULL;
- }
-
- const lldb_private::RegisterSet *
- GetRegisterSet (uint32_t i) const
- {
- if (i < m_sets.size())
- return &m_sets[i];
- return NULL;
- }
-
- uint32_t
- GetRegisterSetIndexByName (lldb_private::ConstString &set_name)
- {
- name_collection::iterator pos, end = m_set_names.end();
- for (pos = m_set_names.begin(); pos != end; ++pos)
- {
- if (*pos == set_name)
- return static_cast<uint32_t>(std::distance (m_set_names.begin(), pos));
- }
-
- m_set_names.push_back(set_name);
- m_set_reg_nums.resize(m_set_reg_nums.size()+1);
- lldb_private::RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL };
- m_sets.push_back (new_set);
- return static_cast<uint32_t>(m_sets.size() - 1);
- }
-
- uint32_t
- ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const
- {
- reg_collection::const_iterator pos, end = m_regs.end();
- for (pos = m_regs.begin(); pos != end; ++pos)
- {
- if (pos->kinds[kind] == num)
- return static_cast<uint32_t>(std::distance (m_regs.begin(), pos));
- }
-
- return LLDB_INVALID_REGNUM;
- }
- void
- Clear()
- {
- m_regs.clear();
- m_sets.clear();
- m_set_reg_nums.clear();
- m_reg_names.clear();
- m_reg_alt_names.clear();
- m_set_names.clear();
- }
-
- void
HardcodeARMRegisters(bool from_scratch);
-protected:
- //------------------------------------------------------------------
- // Classes that inherit from GDBRemoteRegisterContext can see and modify these
- //------------------------------------------------------------------
- typedef std::vector <lldb_private::RegisterInfo> reg_collection;
- typedef std::vector <lldb_private::RegisterSet> set_collection;
- typedef std::vector <uint32_t> reg_num_collection;
- typedef std::vector <reg_num_collection> set_reg_num_collection;
- typedef std::vector <lldb_private::ConstString> name_collection;
- typedef std::map<uint32_t, reg_num_collection> reg_to_regs_map;
-
- reg_collection m_regs;
- set_collection m_sets;
- set_reg_num_collection m_set_reg_nums;
- name_collection m_reg_names;
- name_collection m_reg_alt_names;
- name_collection m_set_names;
- reg_to_regs_map m_value_regs_map;
- reg_to_regs_map m_invalidate_regs_map;
- size_t m_reg_data_byte_size; // The number of bytes required to store all registers
};
class GDBRemoteRegisterContext : public lldb_private::RegisterContext
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 89da55a..4aa1864 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -8,13 +8,16 @@
//===----------------------------------------------------------------------===//
#include "lldb/lldb-python.h"
+#include "lldb/Host/Config.h"
// C Includes
#include <errno.h>
-#include <spawn.h>
#include <stdlib.h>
+#ifndef LLDB_DISABLE_POSIX
+#include <spawn.h>
#include <netinet/in.h>
#include <sys/mman.h> // for mmap
+#endif
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
@@ -46,6 +49,9 @@
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#ifndef LLDB_DISABLE_PYTHON
+#include "lldb/Interpreter/PythonDataObjects.h"
+#endif
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Target.h"
@@ -93,12 +99,14 @@ namespace {
g_properties[] =
{
{ "packet-timeout" , OptionValue::eTypeUInt64 , true , 1, NULL, NULL, "Specify the default packet timeout in seconds." },
+ { "target-definition-file" , OptionValue::eTypeFileSpec , true, 0 , NULL, NULL, "The file that provides the description for remote target registers." },
{ NULL , OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL }
};
enum
{
- ePropertyPacketTimeout
+ ePropertyPacketTimeout,
+ ePropertyTargetDefinitionFile
};
class PluginProperties : public Properties
@@ -129,6 +137,20 @@ namespace {
const uint32_t idx = ePropertyPacketTimeout;
return m_collection_sp->GetPropertyAtIndexAsUInt64(NULL, idx, g_properties[idx].default_uint_value);
}
+
+ bool
+ SetPacketTimeout(uint64_t timeout)
+ {
+ const uint32_t idx = ePropertyPacketTimeout;
+ return m_collection_sp->SetPropertyAtIndexAsUInt64(NULL, idx, timeout);
+ }
+
+ FileSpec
+ GetTargetDefinitionFile () const
+ {
+ const uint32_t idx = ePropertyTargetDefinitionFile;
+ return m_collection_sp->GetPropertyAtIndexAsFileSpec (NULL, idx);
+ }
};
typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP;
@@ -253,13 +275,13 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
m_continue_C_tids (),
m_continue_s_tids (),
m_continue_S_tids (),
- m_dispatch_queue_offsets_addr (LLDB_INVALID_ADDRESS),
m_max_memory_size (512),
m_addr_to_mmap_size (),
m_thread_create_bp_sp (),
m_waiting_for_attach (false),
m_destroy_tried_resuming (false),
- m_command_sp ()
+ m_command_sp (),
+ m_breakpoint_pc_offset (0)
{
m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit, "async thread should exit");
m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue, "async thread continue");
@@ -304,6 +326,48 @@ ProcessGDBRemote::GetPluginVersion()
return 1;
}
+bool
+ProcessGDBRemote::ParsePythonTargetDefinition(const FileSpec &target_definition_fspec)
+{
+#ifndef LLDB_DISABLE_PYTHON
+ ScriptInterpreter *interpreter = GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
+ Error error;
+ lldb::ScriptInterpreterObjectSP module_object_sp (interpreter->LoadPluginModule(target_definition_fspec, error));
+ if (module_object_sp)
+ {
+ lldb::ScriptInterpreterObjectSP target_definition_sp (interpreter->GetDynamicSettings(module_object_sp,
+ &GetTarget(),
+ "gdb-server-target-definition",
+ error));
+
+ PythonDictionary target_dict(target_definition_sp);
+
+ if (target_dict)
+ {
+ PythonDictionary host_info_dict (target_dict.GetItemForKey("host-info"));
+ if (host_info_dict)
+ {
+ ArchSpec host_arch (host_info_dict.GetItemForKeyAsString(PythonString("triple")));
+
+ if (!host_arch.IsCompatibleMatch(GetTarget().GetArchitecture()))
+ {
+ GetTarget().SetArchitecture(host_arch);
+ }
+
+ }
+ m_breakpoint_pc_offset = target_dict.GetItemForKeyAsInteger("breakpoint-pc-offset", 0);
+
+ if (m_register_info.SetRegisterInfo (target_dict, GetTarget().GetArchitecture().GetByteOrder()) > 0)
+ {
+ return true;
+ }
+ }
+ }
+#endif
+ return false;
+}
+
+
void
ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
{
@@ -479,6 +543,28 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
}
}
+ // Check if qHostInfo specified a specific packet timeout for this connection.
+ // If so then lets update our setting so the user knows what the timeout is
+ // and can see it.
+ const uint32_t host_packet_timeout = m_gdb_comm.GetHostDefaultPacketTimeout();
+ if (host_packet_timeout)
+ {
+ GetGlobalPluginProperties()->SetPacketTimeout(host_packet_timeout);
+ }
+
+
+ if (reg_num == 0)
+ {
+ FileSpec target_definition_fspec = GetGlobalPluginProperties()->GetTargetDefinitionFile ();
+
+ if (target_definition_fspec)
+ {
+ // See if we can get register definitions from a python file
+ if (ParsePythonTargetDefinition (target_definition_fspec))
+ return;
+ }
+ }
+
// We didn't get anything if the accumulated reg_num is zero. See if we are
// debugging ARM and fill with a hard coded register set until we can get an
// updated debugserver down on the devices.
@@ -560,6 +646,11 @@ ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url)
GetThreadList();
if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, m_last_stop_packet, false))
{
+ if (!m_target.GetArchitecture().IsValid()) { // Make sure we have an architecture
+ m_target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());
+ }
+
+
const StateType state = SetThreadStopInfo (m_last_stop_packet);
if (state == eStateStopped)
{
@@ -758,6 +849,10 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, const ProcessLaunchInfo &launch_
if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, m_last_stop_packet, false))
{
+ if (!m_target.GetArchitecture().IsValid()) { // Make sure we have an architecture
+ m_target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());
+ }
+
SetPrivateState (SetThreadStopInfo (m_last_stop_packet));
if (!disable_stdio)
@@ -862,8 +957,6 @@ ProcessGDBRemote::DidLaunchOrAttach ()
log->Printf ("ProcessGDBRemote::DidLaunch()");
if (GetID() != LLDB_INVALID_PROCESS_ID)
{
- m_dispatch_queue_offsets_addr = LLDB_INVALID_ADDRESS;
-
BuildDynamicRegisterInfo (false);
// See if the GDB server supports the qHostInfo information
@@ -1653,7 +1746,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
// Currently we are going to assume SIGTRAP means we are either
// hitting a breakpoint or hardware single stepping.
handled = true;
- addr_t pc = thread_sp->GetRegisterContext()->GetPC();
+ addr_t pc = thread_sp->GetRegisterContext()->GetPC() + m_breakpoint_pc_offset;
lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
if (bp_site_sp)
@@ -1663,6 +1756,8 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
// will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
if (bp_site_sp->ValidForThisThread (thread_sp.get()))
{
+ if(m_breakpoint_pc_offset != 0)
+ thread_sp->GetRegisterContext()->SetPC(pc);
thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
}
else
@@ -2221,7 +2316,7 @@ ProcessGDBRemote::EnableBreakpointSite (BreakpointSite *bp_site)
{
const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site);
- if (bp_site->HardwarePreferred())
+ if (bp_site->HardwareRequired())
{
// Try and set hardware breakpoint, and if that fails, fall through
// and set a software breakpoint?
@@ -2231,12 +2326,19 @@ ProcessGDBRemote::EnableBreakpointSite (BreakpointSite *bp_site)
{
bp_site->SetEnabled(true);
bp_site->SetType (BreakpointSite::eHardware);
- return error;
}
+ else
+ {
+ error.SetErrorString("failed to set hardware breakpoint (hardware breakpoint resources might be exhausted or unavailable)");
+ }
+ }
+ else
+ {
+ error.SetErrorString("hardware breakpoints are not supported");
}
+ return error;
}
-
- if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointSoftware))
+ else if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointSoftware))
{
if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, true, addr, bp_op_size) == 0)
{
@@ -2688,7 +2790,7 @@ ProcessGDBRemote::KillDebugserverProcess ()
{
if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
{
- ::kill (m_debugserver_pid, SIGINT);
+ Host::Kill (m_debugserver_pid, SIGINT);
m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
}
}
@@ -2795,7 +2897,7 @@ ProcessGDBRemote::StopAsyncThread ()
}
-void *
+thread_result_t
ProcessGDBRemote::AsyncThread (void *arg)
{
ProcessGDBRemote *process = (ProcessGDBRemote*) arg;
@@ -2917,97 +3019,6 @@ ProcessGDBRemote::AsyncThread (void *arg)
return NULL;
}
-const char *
-ProcessGDBRemote::GetDispatchQueueNameForThread
-(
- addr_t thread_dispatch_qaddr,
- std::string &dispatch_queue_name
-)
-{
- dispatch_queue_name.clear();
- if (thread_dispatch_qaddr != 0 && thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
- {
- // Cache the dispatch_queue_offsets_addr value so we don't always have
- // to look it up
- if (m_dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS)
- {
- static ConstString g_dispatch_queue_offsets_symbol_name ("dispatch_queue_offsets");
- const Symbol *dispatch_queue_offsets_symbol = NULL;
- ModuleSpec libSystem_module_spec (FileSpec("libSystem.B.dylib", false));
- ModuleSP module_sp(GetTarget().GetImages().FindFirstModule (libSystem_module_spec));
- if (module_sp)
- dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
-
- if (dispatch_queue_offsets_symbol == NULL)
- {
- ModuleSpec libdispatch_module_spec (FileSpec("libdispatch.dylib", false));
- module_sp = GetTarget().GetImages().FindFirstModule (libdispatch_module_spec);
- if (module_sp)
- dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
- }
- if (dispatch_queue_offsets_symbol)
- m_dispatch_queue_offsets_addr = dispatch_queue_offsets_symbol->GetAddress().GetLoadAddress(&m_target);
-
- if (m_dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS)
- return NULL;
- }
-
- uint8_t memory_buffer[8];
- DataExtractor data (memory_buffer,
- sizeof(memory_buffer),
- m_target.GetArchitecture().GetByteOrder(),
- m_target.GetArchitecture().GetAddressByteSize());
-
- // Excerpt from src/queue_private.h
- struct dispatch_queue_offsets_s
- {
- uint16_t dqo_version;
- uint16_t dqo_label; // in version 1-3, offset to string; in version 4+, offset to a pointer to a string
- uint16_t dqo_label_size; // in version 1-3, length of string; in version 4+, size of a (void*) in this process
- } dispatch_queue_offsets;
-
-
- Error error;
- if (ReadMemory (m_dispatch_queue_offsets_addr, memory_buffer, sizeof(dispatch_queue_offsets), error) == sizeof(dispatch_queue_offsets))
- {
- lldb::offset_t data_offset = 0;
- if (data.GetU16(&data_offset, &dispatch_queue_offsets.dqo_version, sizeof(dispatch_queue_offsets)/sizeof(uint16_t)))
- {
- if (ReadMemory (thread_dispatch_qaddr, &memory_buffer, data.GetAddressByteSize(), error) == data.GetAddressByteSize())
- {
- data_offset = 0;
- lldb::addr_t queue_addr = data.GetAddress(&data_offset);
- if (dispatch_queue_offsets.dqo_version >= 4)
- {
- // libdispatch versions 4+, pointer to dispatch name is in the
- // queue structure.
- lldb::addr_t pointer_to_label_address = queue_addr + dispatch_queue_offsets.dqo_label;
- if (ReadMemory (pointer_to_label_address, &memory_buffer, data.GetAddressByteSize(), error) == data.GetAddressByteSize())
- {
- data_offset = 0;
- lldb::addr_t label_addr = data.GetAddress(&data_offset);
- ReadCStringFromMemory (label_addr, dispatch_queue_name, error);
- }
- }
- else
- {
- // libdispatch versions 1-3, dispatch name is a fixed width char array
- // in the queue structure.
- lldb::addr_t label_addr = queue_addr + dispatch_queue_offsets.dqo_label;
- dispatch_queue_name.resize(dispatch_queue_offsets.dqo_label_size, '\0');
- size_t bytes_read = ReadMemory (label_addr, &dispatch_queue_name[0], dispatch_queue_offsets.dqo_label_size, error);
- if (bytes_read < dispatch_queue_offsets.dqo_label_size)
- dispatch_queue_name.erase (bytes_read);
- }
- }
- }
- }
- }
- if (dispatch_queue_name.empty())
- return NULL;
- return dispatch_queue_name.c_str();
-}
-
//uint32_t
//ProcessGDBRemote::ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids)
//{
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index e104b71..b18ac5b 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -291,6 +291,12 @@ protected:
void
SetLastStopPacket (const StringExtractorGDBRemote &response);
+ bool
+ ParsePythonTargetDefinition(const lldb_private::FileSpec &target_definition_fspec);
+
+ bool
+ ParseRegisters(lldb_private::ScriptInterpreterObject *registers_array);
+
//------------------------------------------------------------------
/// Broadcaster event bits definitions.
//------------------------------------------------------------------
@@ -326,13 +332,13 @@ protected:
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;
size_t m_max_memory_size; // The maximum number of bytes to read/write when reading and writing memory
MMapMap m_addr_to_mmap_size;
lldb::BreakpointSP m_thread_create_bp_sp;
bool m_waiting_for_attach;
bool m_destroy_tried_resuming;
lldb::CommandObjectSP m_command_sp;
+ int64_t m_breakpoint_pc_offset;
bool
StartAsyncThread ();
@@ -340,7 +346,7 @@ protected:
void
StopAsyncThread ();
- static void *
+ static lldb::thread_result_t
AsyncThread (void *arg);
static bool
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index 38fb84d..4e475c8 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -10,16 +10,17 @@
#include "ThreadGDBRemote.h"
+#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/DataExtractor.h"
-#include "lldb/Core/StreamString.h"
#include "lldb/Core/State.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Unwind.h"
-#include "lldb/Breakpoint/Watchpoint.h"
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
@@ -73,13 +74,38 @@ ThreadGDBRemote::GetQueueName ()
ProcessSP process_sp (GetProcess());
if (process_sp)
{
- ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get());
- return gdb_process->GetDispatchQueueNameForThread (m_thread_dispatch_qaddr, m_dispatch_queue_name);
+ PlatformSP platform_sp (process_sp->GetTarget().GetPlatform());
+ if (platform_sp)
+ {
+ m_dispatch_queue_name = platform_sp->GetQueueNameForThreadQAddress (process_sp.get(), m_thread_dispatch_qaddr);
+ }
+ if (m_dispatch_queue_name.length() > 0)
+ {
+ return m_dispatch_queue_name.c_str();
+ }
}
}
return NULL;
}
+queue_id_t
+ThreadGDBRemote::GetQueueID ()
+{
+ if (m_thread_dispatch_qaddr != 0 || m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
+ {
+ ProcessSP process_sp (GetProcess());
+ if (process_sp)
+ {
+ PlatformSP platform_sp (process_sp->GetTarget().GetPlatform());
+ if (platform_sp)
+ {
+ return platform_sp->GetQueueIDForThreadQAddress (process_sp.get(), m_thread_dispatch_qaddr);
+ }
+ }
+ }
+ return LLDB_INVALID_QUEUE_ID;
+}
+
void
ThreadGDBRemote::WillResume (StateType resume_state)
{
@@ -164,7 +190,6 @@ lldb::RegisterContextSP
ThreadGDBRemote::CreateRegisterContextForFrame (StackFrame *frame)
{
lldb::RegisterContextSP reg_ctx_sp;
- const bool read_all_registers_at_once = false;
uint32_t concrete_frame_idx = 0;
if (frame)
@@ -177,6 +202,8 @@ ThreadGDBRemote::CreateRegisterContextForFrame (StackFrame *frame)
if (process_sp)
{
ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get());
+ // read_all_registers_at_once will be true if 'p' packet is not supported.
+ bool read_all_registers_at_once = !gdb_process->GetGDBRemote().GetpPacketSupported (GetID());
reg_ctx_sp.reset (new GDBRemoteRegisterContext (*this, concrete_frame_idx, gdb_process->m_register_info, read_all_registers_at_once));
}
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
index 50a3f19..dd4cc03 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
@@ -38,6 +38,9 @@ public:
virtual const char *
GetQueueName ();
+ virtual lldb::queue_id_t
+ GetQueueID ();
+
virtual lldb::RegisterContextSP
GetRegisterContext ();
OpenPOWER on IntegriCloud