mirror of
https://github.com/intel/llvm.git
synced 2026-01-15 12:25:46 +08:00
Added the ability to connect using "tcp://<host>:<port>" which is the
same as the old "connect://<host>:<port>". Also added the ability to connect using "udp://<host>:<port>" which will open a connected datagram socket. I need to find a way to specify a non connected datagram socket as well. We might need to start setting some settings in the URL itself, maybe something like: udp://<host>:<port>?connected=yes udp://<host>:<port>?connected=no I am open to suggestions for URL settings. Also did more work on the KDP darwin kernel plug-in. llvm-svn: 135277
This commit is contained in:
@@ -61,8 +61,11 @@ protected:
|
||||
SocketListen (uint16_t listen_port_num, Error *error_ptr);
|
||||
|
||||
lldb::ConnectionStatus
|
||||
SocketConnect (const char *host_and_port, Error *error_ptr);
|
||||
|
||||
ConnectTCP (const char *host_and_port, Error *error_ptr);
|
||||
|
||||
lldb::ConnectionStatus
|
||||
ConnectUDP (const char *host_and_port, Error *error_ptr);
|
||||
|
||||
lldb::ConnectionStatus
|
||||
NamedSocketAccept (const char *socket_name, Error *error_ptr);
|
||||
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
26368A3C126B697600E8659F /* darwin-debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26368A3B126B697600E8659F /* darwin-debug.cpp */; };
|
||||
26368AF7126B960500E8659F /* darwin-debug in Resources */ = {isa = PBXBuildFile; fileRef = 26579F68126A25920007C5CB /* darwin-debug */; };
|
||||
263E949F13661AEA00E7D1CE /* UnwindAssembly-x86.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263E949D13661AE400E7D1CE /* UnwindAssembly-x86.cpp */; };
|
||||
2642FBAE13D003B400ED6808 /* CommunicationKDP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2642FBA813D003B400ED6808 /* CommunicationKDP.cpp */; };
|
||||
2642FBAF13D003B400ED6808 /* CommunicationKDP.h in Headers */ = {isa = PBXBuildFile; fileRef = 2642FBA913D003B400ED6808 /* CommunicationKDP.h */; };
|
||||
2642FBB013D003B400ED6808 /* ProcessKDP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2642FBAA13D003B400ED6808 /* ProcessKDP.cpp */; };
|
||||
2642FBB113D003B400ED6808 /* ProcessKDP.h in Headers */ = {isa = PBXBuildFile; fileRef = 2642FBAB13D003B400ED6808 /* ProcessKDP.h */; };
|
||||
2642FBB213D003B400ED6808 /* ProcessKDPLog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2642FBAC13D003B400ED6808 /* ProcessKDPLog.cpp */; };
|
||||
2642FBB313D003B400ED6808 /* ProcessKDPLog.h in Headers */ = {isa = PBXBuildFile; fileRef = 2642FBAD13D003B400ED6808 /* ProcessKDPLog.h */; };
|
||||
264A97BF133918BC0017F0BE /* PlatformRemoteGDBServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264A97BD133918BC0017F0BE /* PlatformRemoteGDBServer.cpp */; };
|
||||
264D8D5013661BD7003A368F /* UnwindAssembly.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264D8D4F13661BD7003A368F /* UnwindAssembly.cpp */; };
|
||||
265ABF6310F42EE900531910 /* DebugSymbols.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 265ABF6210F42EE900531910 /* DebugSymbols.framework */; };
|
||||
@@ -640,6 +646,12 @@
|
||||
263FEDA5112CC1DA00E4C208 /* ThreadSafeSTLMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadSafeSTLMap.h; path = include/lldb/Core/ThreadSafeSTLMap.h; sourceTree = "<group>"; };
|
||||
26424E3C125986CB0016D82C /* ValueObjectConstResult.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectConstResult.cpp; path = source/Core/ValueObjectConstResult.cpp; sourceTree = "<group>"; };
|
||||
26424E3E125986D30016D82C /* ValueObjectConstResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectConstResult.h; path = include/lldb/Core/ValueObjectConstResult.h; sourceTree = "<group>"; };
|
||||
2642FBA813D003B400ED6808 /* CommunicationKDP.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CommunicationKDP.cpp; sourceTree = "<group>"; };
|
||||
2642FBA913D003B400ED6808 /* CommunicationKDP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommunicationKDP.h; sourceTree = "<group>"; };
|
||||
2642FBAA13D003B400ED6808 /* ProcessKDP.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessKDP.cpp; sourceTree = "<group>"; };
|
||||
2642FBAB13D003B400ED6808 /* ProcessKDP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessKDP.h; sourceTree = "<group>"; };
|
||||
2642FBAC13D003B400ED6808 /* ProcessKDPLog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessKDPLog.cpp; sourceTree = "<group>"; };
|
||||
2642FBAD13D003B400ED6808 /* ProcessKDPLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessKDPLog.h; sourceTree = "<group>"; };
|
||||
264334381110F63100CDB6C6 /* ValueObjectRegister.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectRegister.cpp; path = source/Core/ValueObjectRegister.cpp; sourceTree = "<group>"; };
|
||||
2643343A1110F63C00CDB6C6 /* ValueObjectRegister.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectRegister.h; path = include/lldb/Core/ValueObjectRegister.h; sourceTree = "<group>"; };
|
||||
264723A511FA076E00DE380C /* CleanUp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CleanUp.h; path = include/lldb/Utility/CleanUp.h; sourceTree = "<group>"; };
|
||||
@@ -1483,6 +1495,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4CEE62F71145F1C70064CF93 /* GDB Remote */,
|
||||
2642FBA713D003B400ED6808 /* MacOSX-Kernel */,
|
||||
260C898B10F57C5600BB2B04 /* MacOSX-User */,
|
||||
26B4666E11A2080F00CF6220 /* Utility */,
|
||||
);
|
||||
@@ -1723,6 +1736,19 @@
|
||||
name = API;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2642FBA713D003B400ED6808 /* MacOSX-Kernel */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2642FBA813D003B400ED6808 /* CommunicationKDP.cpp */,
|
||||
2642FBA913D003B400ED6808 /* CommunicationKDP.h */,
|
||||
2642FBAA13D003B400ED6808 /* ProcessKDP.cpp */,
|
||||
2642FBAB13D003B400ED6808 /* ProcessKDP.h */,
|
||||
2642FBAC13D003B400ED6808 /* ProcessKDPLog.cpp */,
|
||||
2642FBAD13D003B400ED6808 /* ProcessKDPLog.h */,
|
||||
);
|
||||
path = "MacOSX-Kernel";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
264A97BC133918A30017F0BE /* GDB Server */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -2686,6 +2712,9 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9A9E1F0113980943005AC039 /* InputReaderStack.h in Headers */,
|
||||
2642FBAF13D003B400ED6808 /* CommunicationKDP.h in Headers */,
|
||||
2642FBB113D003B400ED6808 /* ProcessKDP.h in Headers */,
|
||||
2642FBB313D003B400ED6808 /* ProcessKDPLog.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -3279,6 +3308,9 @@
|
||||
26F4214413C6515B00E04E5E /* DynamicLoaderMacOSXKernel.cpp in Sources */,
|
||||
94611EB213CCA4A4003A22AF /* RefCounter.cpp in Sources */,
|
||||
94031A9E13CF486700DCFF3C /* InputReaderEZ.cpp in Sources */,
|
||||
2642FBAE13D003B400ED6808 /* CommunicationKDP.cpp in Sources */,
|
||||
2642FBB013D003B400ED6808 /* ProcessKDP.cpp in Sources */,
|
||||
2642FBB213D003B400ED6808 /* ProcessKDPLog.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
@@ -97,7 +97,15 @@ ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr)
|
||||
}
|
||||
else if (strstr(s, "connect://"))
|
||||
{
|
||||
return SocketConnect (s + strlen("connect://"), error_ptr);
|
||||
return ConnectTCP (s + strlen("connect://"), error_ptr);
|
||||
}
|
||||
else if (strstr(s, "tcp://"))
|
||||
{
|
||||
return ConnectTCP (s + strlen("tcp://"), error_ptr);
|
||||
}
|
||||
else if (strstr(s, "udp://"))
|
||||
{
|
||||
return ConnectUDP (s + strlen("udp://"), error_ptr);
|
||||
}
|
||||
else if (strstr(s, "fd://"))
|
||||
{
|
||||
@@ -626,10 +634,10 @@ ConnectionFileDescriptor::SocketListen (uint16_t listen_port_num, Error *error_p
|
||||
}
|
||||
|
||||
ConnectionStatus
|
||||
ConnectionFileDescriptor::SocketConnect (const char *host_and_port, Error *error_ptr)
|
||||
ConnectionFileDescriptor::ConnectTCP (const char *host_and_port, Error *error_ptr)
|
||||
{
|
||||
lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION,
|
||||
"%p ConnectionFileDescriptor::SocketConnect (host/port = %s)",
|
||||
"%p ConnectionFileDescriptor::ConnectTCP (host/port = %s)",
|
||||
this, host_and_port);
|
||||
Close (m_fd, NULL);
|
||||
m_is_socket = true;
|
||||
@@ -715,6 +723,96 @@ ConnectionFileDescriptor::SocketConnect (const char *host_and_port, Error *error
|
||||
return eConnectionStatusSuccess;
|
||||
}
|
||||
|
||||
ConnectionStatus
|
||||
ConnectionFileDescriptor::ConnectUDP (const char *host_and_port, Error *error_ptr)
|
||||
{
|
||||
lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION,
|
||||
"%p ConnectionFileDescriptor::ConnectUDP (host/port = %s)",
|
||||
this, host_and_port);
|
||||
Close (m_fd, NULL);
|
||||
m_is_socket = true;
|
||||
|
||||
RegularExpression regex ("([^:]+):([0-9]+)");
|
||||
if (regex.Execute (host_and_port, 2) == false)
|
||||
{
|
||||
if (error_ptr)
|
||||
error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port);
|
||||
return eConnectionStatusError;
|
||||
}
|
||||
std::string host_str;
|
||||
std::string port_str;
|
||||
if (regex.GetMatchAtIndex (host_and_port, 1, host_str) == false ||
|
||||
regex.GetMatchAtIndex (host_and_port, 2, port_str) == false)
|
||||
{
|
||||
if (error_ptr)
|
||||
error_ptr->SetErrorStringWithFormat("invalid host:port specification '%s'", host_and_port);
|
||||
return eConnectionStatusError;
|
||||
}
|
||||
|
||||
int32_t port = Args::StringToSInt32 (port_str.c_str(), INT32_MIN);
|
||||
if (port == INT32_MIN)
|
||||
{
|
||||
if (error_ptr)
|
||||
error_ptr->SetErrorStringWithFormat("invalid port '%s'", port_str.c_str());
|
||||
return eConnectionStatusError;
|
||||
}
|
||||
// Create the socket
|
||||
m_fd = ::socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (m_fd == -1)
|
||||
{
|
||||
if (error_ptr)
|
||||
error_ptr->SetErrorToErrno();
|
||||
return eConnectionStatusError;
|
||||
}
|
||||
|
||||
m_should_close_fd = true;
|
||||
|
||||
// Enable local address reuse
|
||||
SetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, 1);
|
||||
|
||||
struct sockaddr_in sa;
|
||||
::memset (&sa, 0, sizeof (sa));
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons (port);
|
||||
|
||||
int inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr);
|
||||
|
||||
if (inet_pton_result <= 0)
|
||||
{
|
||||
struct hostent *host_entry = gethostbyname (host_str.c_str());
|
||||
if (host_entry)
|
||||
host_str = ::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list);
|
||||
inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr);
|
||||
if (inet_pton_result <= 0)
|
||||
{
|
||||
|
||||
if (error_ptr)
|
||||
{
|
||||
if (inet_pton_result == -1)
|
||||
error_ptr->SetErrorToErrno();
|
||||
else
|
||||
error_ptr->SetErrorStringWithFormat("invalid host string: '%s'", host_str.c_str());
|
||||
}
|
||||
Close (m_fd, NULL);
|
||||
return eConnectionStatusError;
|
||||
}
|
||||
}
|
||||
|
||||
if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa)))
|
||||
{
|
||||
if (error_ptr)
|
||||
error_ptr->SetErrorToErrno();
|
||||
Close (m_fd, NULL);
|
||||
return eConnectionStatusError;
|
||||
}
|
||||
|
||||
// Keep our TCP packets coming without any delays.
|
||||
SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1);
|
||||
if (error_ptr)
|
||||
error_ptr->Clear();
|
||||
return eConnectionStatusSuccess;
|
||||
}
|
||||
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
typedef const char * set_socket_option_arg_type;
|
||||
typedef char * get_socket_option_arg_type;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
// C++ Includes
|
||||
// Other libraries and framework includes
|
||||
#include "lldb/Core/DataExtractor.h"
|
||||
#include "lldb/Core/Log.h"
|
||||
#include "lldb/Core/StreamString.h"
|
||||
#include "lldb/Host/FileSpec.h"
|
||||
@@ -41,7 +42,9 @@ CommunicationKDP::CommunicationKDP (const char *comm_name) :
|
||||
m_sequence_mutex (Mutex::eMutexTypeRecursive),
|
||||
m_public_is_running (false),
|
||||
m_private_is_running (false),
|
||||
m_send_acks (true)
|
||||
m_session_key (0),
|
||||
m_request_sequence_id (0),
|
||||
m_exception_sequence_id (0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -56,110 +59,68 @@ CommunicationKDP::~CommunicationKDP()
|
||||
}
|
||||
}
|
||||
|
||||
char
|
||||
CommunicationKDP::CalculcateChecksum (const char *payload, size_t payload_length)
|
||||
{
|
||||
int checksum = 0;
|
||||
|
||||
// We only need to compute the checksum if we are sending acks
|
||||
if (GetSendAcks ())
|
||||
{
|
||||
for (size_t i = 0; i < payload_length; ++i)
|
||||
checksum += payload[i];
|
||||
}
|
||||
return checksum & 255;
|
||||
}
|
||||
|
||||
size_t
|
||||
CommunicationKDP::SendAck ()
|
||||
{
|
||||
LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
|
||||
if (log)
|
||||
log->Printf ("send packet: +");
|
||||
ConnectionStatus status = eConnectionStatusSuccess;
|
||||
char ack_char = '+';
|
||||
return Write (&ack_char, 1, status, NULL);
|
||||
}
|
||||
|
||||
size_t
|
||||
CommunicationKDP::SendNack ()
|
||||
{
|
||||
LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
|
||||
if (log)
|
||||
log->Printf ("send packet: -");
|
||||
ConnectionStatus status = eConnectionStatusSuccess;
|
||||
char nack_char = '-';
|
||||
return Write (&nack_char, 1, status, NULL);
|
||||
}
|
||||
|
||||
size_t
|
||||
CommunicationKDP::SendPacket (lldb_private::StreamString &payload)
|
||||
bool
|
||||
CommunicationKDP::SendRequestPacket (const StreamString &request_packet)
|
||||
{
|
||||
Mutex::Locker locker(m_sequence_mutex);
|
||||
const std::string &p (payload.GetString());
|
||||
return SendPacketNoLock (p.c_str(), p.size());
|
||||
return SendRequestPacketNoLock (request_packet);
|
||||
}
|
||||
|
||||
size_t
|
||||
CommunicationKDP::SendPacket (const char *payload)
|
||||
void
|
||||
CommunicationKDP::MakeRequestPacketHeader (RequestType request_type,
|
||||
StreamString &request_packet)
|
||||
{
|
||||
Mutex::Locker locker(m_sequence_mutex);
|
||||
return SendPacketNoLock (payload, ::strlen (payload));
|
||||
request_packet.Clear();
|
||||
request_packet.PutHex32 (request_type); // Set the request type
|
||||
request_packet.PutHex8 (ePacketTypeRequest); // Set the packet type
|
||||
request_packet.PutHex8 (++m_request_sequence_id); // Sequence number
|
||||
request_packet.PutHex16 (0); // Pad1 and Pad2 bytes
|
||||
request_packet.PutHex32 (m_session_key); // Session key
|
||||
}
|
||||
|
||||
size_t
|
||||
CommunicationKDP::SendPacket (const char *payload, size_t payload_length)
|
||||
{
|
||||
Mutex::Locker locker(m_sequence_mutex);
|
||||
return SendPacketNoLock (payload, payload_length);
|
||||
}
|
||||
|
||||
size_t
|
||||
CommunicationKDP::SendPacketNoLock (const char *payload, size_t payload_length)
|
||||
bool
|
||||
CommunicationKDP::SendRequestPacketNoLock (const StreamString &request_packet)
|
||||
{
|
||||
if (IsConnected())
|
||||
{
|
||||
StreamString packet(0, 4, eByteOrderBig);
|
||||
|
||||
packet.PutChar('$');
|
||||
packet.Write (payload, payload_length);
|
||||
packet.PutChar('#');
|
||||
packet.PutHex8(CalculcateChecksum (payload, payload_length));
|
||||
const char *packet_data = request_packet.GetData();
|
||||
const size_t packet_size = request_packet.GetSize();
|
||||
|
||||
LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
|
||||
if (log)
|
||||
log->Printf ("send packet: %.*s", (int)packet.GetSize(), packet.GetData());
|
||||
{
|
||||
StreamString log_strm;
|
||||
DataExtractor data (packet_data,
|
||||
packet_size,
|
||||
request_packet.GetByteOrder(),
|
||||
request_packet.GetAddressByteSize());
|
||||
data.Dump (&log_strm,
|
||||
0,
|
||||
eFormatBytes,
|
||||
1,
|
||||
packet_size,
|
||||
32, // Num bytes per line
|
||||
0, // Base address
|
||||
0,
|
||||
0);
|
||||
|
||||
log->Printf("request packet: <%u>\n%s", packet_size, log_strm.GetString().c_str());
|
||||
}
|
||||
ConnectionStatus status = eConnectionStatusSuccess;
|
||||
size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL);
|
||||
if (bytes_written == packet.GetSize())
|
||||
{
|
||||
if (GetSendAcks ())
|
||||
{
|
||||
if (GetAck () != '+')
|
||||
{
|
||||
printf("get ack failed...");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
|
||||
if (log)
|
||||
log->Printf ("error: failed to send packet: %.*s", (int)packet.GetSize(), packet.GetData());
|
||||
}
|
||||
return bytes_written;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char
|
||||
CommunicationKDP::GetAck ()
|
||||
{
|
||||
StringExtractor packet;
|
||||
if (WaitForPacketWithTimeoutMicroSeconds (packet, GetPacketTimeoutInMicroSeconds ()) == 1)
|
||||
return packet.GetChar();
|
||||
return 0;
|
||||
size_t bytes_written = Write (packet_data,
|
||||
packet_size,
|
||||
status,
|
||||
NULL);
|
||||
|
||||
if (bytes_written == packet_size)
|
||||
return true;
|
||||
|
||||
if (log)
|
||||
log->Printf ("error: failed to send packet entire packet %zu of %zu bytes sent", bytes_written, packet_size);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -262,142 +223,30 @@ CommunicationKDP::CheckForPacket (const uint8_t *src, size_t src_len, StringExtr
|
||||
// Parse up the packets into gdb remote packets
|
||||
if (!m_bytes.empty())
|
||||
{
|
||||
// end_idx must be one past the last valid packet byte. Start
|
||||
// it off with an invalid value that is the same as the current
|
||||
// index.
|
||||
size_t content_start = 0;
|
||||
size_t content_length = 0;
|
||||
size_t total_length = 0;
|
||||
size_t checksum_idx = std::string::npos;
|
||||
|
||||
switch (m_bytes[0])
|
||||
{
|
||||
case '+': // Look for ack
|
||||
case '-': // Look for cancel
|
||||
case '\x03': // ^C to halt target
|
||||
content_length = total_length = 1; // The command is one byte long...
|
||||
break;
|
||||
|
||||
case '$':
|
||||
// Look for a standard gdb packet?
|
||||
{
|
||||
size_t hash_pos = m_bytes.find('#');
|
||||
if (hash_pos != std::string::npos)
|
||||
{
|
||||
if (hash_pos + 2 < m_bytes.size())
|
||||
{
|
||||
checksum_idx = hash_pos + 1;
|
||||
// Skip the dollar sign
|
||||
content_start = 1;
|
||||
// Don't include the # in the content or the $ in the content length
|
||||
content_length = hash_pos - 1;
|
||||
|
||||
total_length = hash_pos + 3; // Skip the # and the two hex checksum bytes
|
||||
}
|
||||
else
|
||||
{
|
||||
// Checksum bytes aren't all here yet
|
||||
content_length = std::string::npos;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
// We have an unexpected byte and we need to flush all bad
|
||||
// data that is in m_bytes, so we need to find the first
|
||||
// byte that is a '+' (ACK), '-' (NACK), \x03 (CTRL+C interrupt),
|
||||
// or '$' character (start of packet header) or of course,
|
||||
// the end of the data in m_bytes...
|
||||
const size_t bytes_len = m_bytes.size();
|
||||
bool done = false;
|
||||
uint32_t idx;
|
||||
for (idx = 1; !done && idx < bytes_len; ++idx)
|
||||
{
|
||||
switch (m_bytes[idx])
|
||||
{
|
||||
case '+':
|
||||
case '-':
|
||||
case '\x03':
|
||||
case '$':
|
||||
done = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (log)
|
||||
log->Printf ("CommunicationKDP::%s tossing %u junk bytes: '%.*s'",
|
||||
__FUNCTION__, idx, idx, m_bytes.c_str());
|
||||
m_bytes.erase(0, idx);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (content_length == std::string::npos)
|
||||
{
|
||||
packet.Clear();
|
||||
return false;
|
||||
}
|
||||
else if (total_length > 0)
|
||||
{
|
||||
|
||||
// We have a valid packet...
|
||||
assert (content_length <= m_bytes.size());
|
||||
assert (total_length <= m_bytes.size());
|
||||
assert (content_length <= total_length);
|
||||
|
||||
bool success = true;
|
||||
std::string &packet_str = packet.GetStringRef();
|
||||
packet_str.assign (m_bytes, content_start, content_length);
|
||||
if (m_bytes[0] == '$')
|
||||
{
|
||||
assert (checksum_idx < m_bytes.size());
|
||||
if (::isxdigit (m_bytes[checksum_idx+0]) ||
|
||||
::isxdigit (m_bytes[checksum_idx+1]))
|
||||
{
|
||||
if (GetSendAcks ())
|
||||
{
|
||||
const char *packet_checksum_cstr = &m_bytes[checksum_idx];
|
||||
char packet_checksum = strtol (packet_checksum_cstr, NULL, 16);
|
||||
char actual_checksum = CalculcateChecksum (packet_str.c_str(), packet_str.size());
|
||||
success = packet_checksum == actual_checksum;
|
||||
if (!success)
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("error: checksum mismatch: %.*s expected 0x%2.2x, got 0x%2.2x",
|
||||
(int)(total_length),
|
||||
m_bytes.c_str(),
|
||||
(uint8_t)packet_checksum,
|
||||
(uint8_t)actual_checksum);
|
||||
}
|
||||
// Send the ack or nack if needed
|
||||
if (!success)
|
||||
SendNack();
|
||||
else
|
||||
SendAck();
|
||||
}
|
||||
if (success)
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("read packet: %.*s", (int)(total_length), m_bytes.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
success = false;
|
||||
if (log)
|
||||
log->Printf ("error: invalid checksum in packet: '%s'\n", (int)(total_length), m_bytes.c_str());
|
||||
}
|
||||
}
|
||||
m_bytes.erase(0, total_length);
|
||||
packet.SetFilePos(0);
|
||||
return success;
|
||||
}
|
||||
// TODO: Figure out if we have a full packet reply
|
||||
}
|
||||
packet.Clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
CommunicationKDP::ErrorType
|
||||
CommunicationKDP::Connect (uint16_t reply_port,
|
||||
uint16_t exc_port,
|
||||
const char *greeting)
|
||||
{
|
||||
StreamString request_packet (Stream::eBinary, 4, eByteOrderLittle);
|
||||
MakeRequestPacketHeader (eRequestTypeConnect, request_packet);
|
||||
request_packet.PutHex16(reply_port);
|
||||
request_packet.PutHex16(exc_port);
|
||||
request_packet.PutCString(greeting);
|
||||
|
||||
return eErrorUnimplemented;
|
||||
}
|
||||
|
||||
CommunicationKDP::ErrorType
|
||||
CommunicationKDP::Disconnect ()
|
||||
{
|
||||
return eErrorUnimplemented;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,53 @@ public:
|
||||
{
|
||||
eBroadcastBitRunPacketSent = kLoUserBroadcastBit
|
||||
};
|
||||
|
||||
const static uint32_t kMaxPacketSize = 1200;
|
||||
const static uint32_t kMaxDataSize = 1024;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
eRequestTypeConnect = 0u,
|
||||
eRequestTypeDisconnect,
|
||||
eRequestTypeHostInfo,
|
||||
eRequestTypeVersion,
|
||||
eRequestTypeMaxBytes,
|
||||
eRequestTypeReadMemory,
|
||||
eRequestTypeWriteMemory,
|
||||
eRequestTypeReadRegisters,
|
||||
eRequestTypeWriteRegisters,
|
||||
eRequestTypeLoad,
|
||||
eRequestTypeImagePath,
|
||||
eRequestTypeSuspend,
|
||||
eRequestTypeResume,
|
||||
eRequestTypeException,
|
||||
eRequestTypeTermination,
|
||||
eRequestTypeBreakpointSet,
|
||||
eRequestTypeBreakpointRemove,
|
||||
eRequestTypeRegions,
|
||||
eRequestTypeReattach,
|
||||
eRequestTypeHostReboot,
|
||||
eRequestTypeReadMemory64,
|
||||
eRequestTypeWriteMemory64,
|
||||
eRequestTypeBreakpointSet64,
|
||||
eRequestTypeBreakpointRemove64,
|
||||
eRequestTypeKernelVersion
|
||||
} RequestType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
eErrorSuccess = 0,
|
||||
eErrorAlreadyConnected,
|
||||
eErrorPacketToBig,
|
||||
eErrorInvalidRegisterFlavor,
|
||||
eErrorUnimplemented
|
||||
} ErrorType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ePacketTypeRequest = 0u,
|
||||
ePacketTypeReply = 1u
|
||||
} PacketType;
|
||||
//------------------------------------------------------------------
|
||||
// Constructors and Destructors
|
||||
//------------------------------------------------------------------
|
||||
@@ -41,34 +88,14 @@ public:
|
||||
virtual
|
||||
~CommunicationKDP();
|
||||
|
||||
size_t
|
||||
SendPacket (const char *payload);
|
||||
|
||||
size_t
|
||||
SendPacket (const char *payload,
|
||||
size_t payload_length);
|
||||
|
||||
size_t
|
||||
SendPacket (lldb_private::StreamString &response);
|
||||
bool
|
||||
SendRequestPacket (const lldb_private::StreamString &request_packet);
|
||||
|
||||
// Wait for a packet within 'nsec' seconds
|
||||
size_t
|
||||
WaitForPacketWithTimeoutMicroSeconds (StringExtractor &response,
|
||||
uint32_t usec);
|
||||
|
||||
char
|
||||
GetAck ();
|
||||
|
||||
size_t
|
||||
SendAck ();
|
||||
|
||||
size_t
|
||||
SendNack ();
|
||||
|
||||
char
|
||||
CalculcateChecksum (const char *payload,
|
||||
size_t payload_length);
|
||||
|
||||
bool
|
||||
GetSequenceMutex(lldb_private::Mutex::Locker& locker);
|
||||
|
||||
@@ -82,12 +109,6 @@ public:
|
||||
return m_public_is_running.GetValue();
|
||||
}
|
||||
|
||||
bool
|
||||
GetSendAcks ()
|
||||
{
|
||||
return m_send_acks;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Set the global packet timeout.
|
||||
//
|
||||
@@ -119,12 +140,19 @@ public:
|
||||
lldb_private::ProcessLaunchInfo &launch_info);
|
||||
|
||||
|
||||
ErrorType
|
||||
Connect (uint16_t reply_port,
|
||||
uint16_t exc_port,
|
||||
const char *greeting);
|
||||
|
||||
ErrorType
|
||||
Disconnect ();
|
||||
|
||||
protected:
|
||||
typedef std::list<std::string> packet_collection;
|
||||
|
||||
size_t
|
||||
SendPacketNoLock (const char *payload,
|
||||
size_t payload_length);
|
||||
bool
|
||||
SendRequestPacketNoLock (const lldb_private::StreamString &request_packet);
|
||||
|
||||
size_t
|
||||
WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractor &response,
|
||||
@@ -133,6 +161,10 @@ protected:
|
||||
bool
|
||||
WaitForNotRunningPrivate (const lldb_private::TimeValue *timeout_ptr);
|
||||
|
||||
void
|
||||
MakeRequestPacketHeader (RequestType request_type,
|
||||
lldb_private::StreamString &request_packet);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Classes that inherit from CommunicationKDP can see and modify these
|
||||
//------------------------------------------------------------------
|
||||
@@ -140,8 +172,9 @@ protected:
|
||||
lldb_private::Mutex m_sequence_mutex; // Restrict access to sending/receiving packets to a single thread at a time
|
||||
lldb_private::Predicate<bool> m_public_is_running;
|
||||
lldb_private::Predicate<bool> m_private_is_running;
|
||||
bool m_send_acks;
|
||||
|
||||
uint32_t m_session_key;
|
||||
uint8_t m_request_sequence_id;
|
||||
uint8_t m_exception_sequence_id;
|
||||
private:
|
||||
//------------------------------------------------------------------
|
||||
// For CommunicationKDP only
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "lldb/Core/PluginManager.h"
|
||||
#include "lldb/Core/State.h"
|
||||
#include "lldb/Host/Host.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
|
||||
// Project includes
|
||||
#include "ProcessKDP.h"
|
||||
@@ -414,7 +415,7 @@ ProcessKDP::DoDetach()
|
||||
|
||||
m_thread_list.DiscardThreadPlans();
|
||||
|
||||
size_t response_size = m_comm.SendPacket ("D", 1);
|
||||
size_t response_size = m_comm.Disconnect ();
|
||||
if (log)
|
||||
{
|
||||
if (response_size)
|
||||
|
||||
Reference in New Issue
Block a user