summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp')
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp369
1 files changed, 363 insertions, 6 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 6a6e063e35b..e3183fca1db 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -20,6 +20,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"
@@ -2137,21 +2138,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;
}
@@ -2159,6 +2176,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();
+ pid = LLDB_INVALID_PROCESS_ID;
+ 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)
@@ -2351,3 +2385,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 UINT64_MAX;
+}
+
+// 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;
+}
OpenPOWER on IntegriCloud