forked from OSchip/llvm-project
Improved the packet throughput when debugging with GDB remote by over 3x on
darwin (not sure about other platforms). Modified the communication and connection classes to not require the BytesAvailable function. Now the "Read(...)" function has a timeout in microseconds. Fixed a lot of assertions that were firing off in certain cases and replaced them with error output and code that can deal with the assertion case. llvm-svn: 133224
This commit is contained in:
parent
2cd8327605
commit
73bf5dbd16
|
@ -40,15 +40,6 @@ public:
|
|||
lldb::ConnectionStatus
|
||||
AdoptFileDesriptor (int fd, bool owns_fd);
|
||||
|
||||
lldb::ConnectionStatus
|
||||
CheckIfBytesAvailable ();
|
||||
|
||||
lldb::ConnectionStatus
|
||||
WaitForBytesAvailableInfinite ();
|
||||
|
||||
lldb::ConnectionStatus
|
||||
WaitForBytesAvailableWithTimeout (uint32_t timeout_usec);
|
||||
|
||||
lldb::ConnectionStatus
|
||||
Connect (const char *url);
|
||||
|
||||
|
|
|
@ -120,20 +120,6 @@ public:
|
|||
void
|
||||
Clear ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Poll for bytes available if the communications supports it.
|
||||
///
|
||||
/// @param[in] timeout_usec
|
||||
/// A timeout value in micro-seconds, UINT32_MAX for infinite
|
||||
/// wait.
|
||||
///
|
||||
/// @return
|
||||
/// \b True if the bytes are, or became available within the
|
||||
/// timeout period, \b false otherwise.
|
||||
//------------------------------------------------------------------
|
||||
virtual lldb::ConnectionStatus
|
||||
BytesAvailable (uint32_t timeout_usec, Error *error_ptr);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Connect using the current connection by passing \a url to its
|
||||
/// connect function.
|
||||
|
@ -185,10 +171,7 @@ public:
|
|||
/// Read bytes from the current connection.
|
||||
///
|
||||
/// If no read thread is running, this function call the
|
||||
/// connection's Connection::BytesAvailable(uint32_t) method to
|
||||
/// wait for available data, and then call the
|
||||
/// Connection::Read(void *, size_t) function to get any available
|
||||
/// bytes if Connection::BytesAvailable(uint32_t) returned true.
|
||||
/// connection's Connection::Read(...) function to get any available.
|
||||
///
|
||||
/// If a read thread has been started, this function will check for
|
||||
/// any cached bytes that have already been read and return any
|
||||
|
@ -212,7 +195,6 @@ public:
|
|||
/// @return
|
||||
/// The number of bytes actually read.
|
||||
///
|
||||
/// @see bool Connection::BytesAvailable (uint32_t);
|
||||
/// @see size_t Connection::Read (void *, size_t);
|
||||
//------------------------------------------------------------------
|
||||
size_t
|
||||
|
@ -365,6 +347,7 @@ protected:
|
|||
size_t
|
||||
ReadFromConnection (void *dst,
|
||||
size_t dst_len,
|
||||
uint32_t timeout_usec,
|
||||
lldb::ConnectionStatus &status,
|
||||
Error *error_ptr);
|
||||
//------------------------------------------------------------------
|
||||
|
|
|
@ -46,24 +46,6 @@ public:
|
|||
virtual
|
||||
~Connection ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Poll for bytes available if the communications supports it.
|
||||
///
|
||||
/// @param[in] timeout_usec
|
||||
/// A timeout value in micro-seconds.
|
||||
///
|
||||
/// @param[out] error
|
||||
/// A reference to an error object that should be given an
|
||||
/// approriate error value if this method returns false. This
|
||||
/// value can be NULL if the error value should be ignored.
|
||||
///
|
||||
/// @return
|
||||
/// \b True if the bytes are, or became available within the
|
||||
/// timeout period, \b false otherwise.
|
||||
//------------------------------------------------------------------
|
||||
virtual lldb::ConnectionStatus
|
||||
BytesAvailable (uint32_t timeout_usec, Error *error_ptr) = 0;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Connect using the connect string \a url.
|
||||
///
|
||||
|
@ -137,7 +119,11 @@ public:
|
|||
/// @see size_t Communication::Read (void *, size_t, uint32_t);
|
||||
//------------------------------------------------------------------
|
||||
virtual size_t
|
||||
Read (void *dst, size_t dst_len, lldb::ConnectionStatus &status, Error *error_ptr) = 0;
|
||||
Read (void *dst,
|
||||
size_t dst_len,
|
||||
uint32_t timeout_usec,
|
||||
lldb::ConnectionStatus &status,
|
||||
Error *error_ptr) = 0;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// The actual write function that attempts to write to the
|
||||
|
|
|
@ -33,9 +33,6 @@ public:
|
|||
virtual bool
|
||||
IsConnected () const;
|
||||
|
||||
virtual lldb::ConnectionStatus
|
||||
BytesAvailable (uint32_t timeout_usec, Error *error_ptr);
|
||||
|
||||
virtual lldb::ConnectionStatus
|
||||
Connect (const char *s, Error *error_ptr);
|
||||
|
||||
|
@ -43,12 +40,23 @@ public:
|
|||
Disconnect (Error *error_ptr);
|
||||
|
||||
virtual size_t
|
||||
Read (void *dst, size_t dst_len, lldb::ConnectionStatus &status, Error *error_ptr);
|
||||
Read (void *dst,
|
||||
size_t dst_len,
|
||||
uint32_t timeout_usec,
|
||||
lldb::ConnectionStatus &status,
|
||||
Error *error_ptr);
|
||||
|
||||
virtual size_t
|
||||
Write (const void *src, size_t src_len, lldb::ConnectionStatus &status, Error *error_ptr);
|
||||
Write (const void *src,
|
||||
size_t src_len,
|
||||
lldb::ConnectionStatus &status,
|
||||
Error *error_ptr);
|
||||
|
||||
protected:
|
||||
|
||||
lldb::ConnectionStatus
|
||||
BytesAvailable (uint32_t timeout_usec, Error *error_ptr);
|
||||
|
||||
lldb::ConnectionStatus
|
||||
SocketListen (uint16_t listen_port_num, Error *error_ptr);
|
||||
|
||||
|
@ -67,10 +75,14 @@ protected:
|
|||
int m_fd; // Socket we use to communicate once conn established
|
||||
bool m_is_socket;
|
||||
bool m_should_close_fd; // True if this class should close the file descriptor when it goes away.
|
||||
|
||||
uint32_t m_socket_timeout_usec;
|
||||
|
||||
static int
|
||||
SetSocketOption(int fd, int level, int option_name, int option_value);
|
||||
|
||||
bool
|
||||
SetSocketRecieveTimeout (uint32_t timeout_usec);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN (ConnectionFileDescriptor);
|
||||
};
|
||||
|
|
|
@ -45,6 +45,7 @@ public:
|
|||
virtual size_t
|
||||
Read (void *dst,
|
||||
size_t dst_len,
|
||||
uint32_t timeout_usec,
|
||||
lldb::ConnectionStatus &status,
|
||||
lldb_private::Error *error_ptr);
|
||||
|
||||
|
|
|
@ -44,7 +44,11 @@ public:
|
|||
Disconnect (Error *error_ptr);
|
||||
|
||||
virtual size_t
|
||||
Read (void *dst, size_t dst_len, lldb::ConnectionStatus &status, Error *error_ptr);
|
||||
Read (void *dst,
|
||||
size_t dst_len,
|
||||
uint32_t timeout_usec,
|
||||
lldb::ConnectionStatus &status,
|
||||
Error *error_ptr);
|
||||
|
||||
virtual size_t
|
||||
Write (const void *src, size_t src_len, lldb::ConnectionStatus &status, Error *error_ptr);
|
||||
|
|
|
@ -58,30 +58,6 @@ SBCommunication::SetCloseOnEOF (bool b)
|
|||
m_opaque->SetCloseOnEOF (b);
|
||||
}
|
||||
|
||||
ConnectionStatus
|
||||
SBCommunication::CheckIfBytesAvailable ()
|
||||
{
|
||||
if (m_opaque)
|
||||
return m_opaque->BytesAvailable (0, NULL);
|
||||
return eConnectionStatusNoConnection;
|
||||
}
|
||||
|
||||
ConnectionStatus
|
||||
SBCommunication::WaitForBytesAvailableInfinite ()
|
||||
{
|
||||
if (m_opaque)
|
||||
return m_opaque->BytesAvailable (UINT32_MAX, NULL);
|
||||
return eConnectionStatusNoConnection;
|
||||
}
|
||||
|
||||
ConnectionStatus
|
||||
SBCommunication::WaitForBytesAvailableWithTimeout (uint32_t timeout_usec)
|
||||
{
|
||||
if (m_opaque)
|
||||
return m_opaque->BytesAvailable (timeout_usec, NULL);
|
||||
return eConnectionStatusNoConnection;
|
||||
}
|
||||
|
||||
ConnectionStatus
|
||||
SBCommunication::Connect (const char *url)
|
||||
{
|
||||
|
|
|
@ -68,19 +68,6 @@ Communication::Clear()
|
|||
Disconnect (NULL);
|
||||
}
|
||||
|
||||
ConnectionStatus
|
||||
Communication::BytesAvailable (uint32_t timeout_usec, Error *error_ptr)
|
||||
{
|
||||
lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::BytesAvailable (timeout_usec = %u)", this, timeout_usec);
|
||||
|
||||
lldb::ConnectionSP connection_sp (m_connection_sp);
|
||||
if (connection_sp.get())
|
||||
return connection_sp->BytesAvailable (timeout_usec, error_ptr);
|
||||
if (error_ptr)
|
||||
error_ptr->SetErrorString("Invalid connection.");
|
||||
return eConnectionStatusNoConnection;
|
||||
}
|
||||
|
||||
ConnectionStatus
|
||||
Communication::Connect (const char *url, Error *error_ptr)
|
||||
{
|
||||
|
@ -139,7 +126,7 @@ size_t
|
|||
Communication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status, Error *error_ptr)
|
||||
{
|
||||
lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
|
||||
"%p Communication::Read (dst = %p, dst_len = %zu, timeout_usec = %u) connection = %p",
|
||||
"%p Communication::Read (dst = %p, dst_len = %zu, timeout = %u usec) connection = %p",
|
||||
this,
|
||||
dst,
|
||||
dst_len,
|
||||
|
@ -196,9 +183,7 @@ Communication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, Connectio
|
|||
lldb::ConnectionSP connection_sp (m_connection_sp);
|
||||
if (connection_sp.get())
|
||||
{
|
||||
status = connection_sp->BytesAvailable (timeout_usec, error_ptr);
|
||||
if (status == eConnectionStatusSuccess)
|
||||
return connection_sp->Read (dst, dst_len, status, error_ptr);
|
||||
return connection_sp->Read (dst, dst_len, timeout_usec, status, error_ptr);
|
||||
}
|
||||
|
||||
if (error_ptr)
|
||||
|
@ -320,11 +305,15 @@ Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broad
|
|||
}
|
||||
|
||||
size_t
|
||||
Communication::ReadFromConnection (void *dst, size_t dst_len, ConnectionStatus &status, Error *error_ptr)
|
||||
Communication::ReadFromConnection (void *dst,
|
||||
size_t dst_len,
|
||||
uint32_t timeout_usec,
|
||||
ConnectionStatus &status,
|
||||
Error *error_ptr)
|
||||
{
|
||||
lldb::ConnectionSP connection_sp (m_connection_sp);
|
||||
if (connection_sp.get())
|
||||
return connection_sp->Read (dst, dst_len, status, error_ptr);
|
||||
return connection_sp->Read (dst, dst_len, timeout_usec, status, error_ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -351,20 +340,15 @@ Communication::ReadThread (void *p)
|
|||
bool done = false;
|
||||
while (!done && comm->m_read_thread_enabled)
|
||||
{
|
||||
status = comm->BytesAvailable (UINT32_MAX, &error);
|
||||
|
||||
if (status == eConnectionStatusSuccess)
|
||||
size_t bytes_read = comm->ReadFromConnection (buf, sizeof(buf), 5 * USEC_PER_SEC, status, &error);
|
||||
if (bytes_read > 0)
|
||||
comm->AppendBytesToCache (buf, bytes_read, true, status);
|
||||
else if ((bytes_read == 0)
|
||||
&& status == eConnectionStatusEndOfFile)
|
||||
{
|
||||
size_t bytes_read = comm->ReadFromConnection (buf, sizeof(buf), status, &error);
|
||||
if (bytes_read > 0)
|
||||
comm->AppendBytesToCache (buf, bytes_read, true, status);
|
||||
else if ((bytes_read == 0)
|
||||
&& status == eConnectionStatusEndOfFile)
|
||||
{
|
||||
if (comm->GetCloseOnEOF ())
|
||||
comm->Disconnect ();
|
||||
comm->AppendBytesToCache (buf, bytes_read, true, status);
|
||||
}
|
||||
if (comm->GetCloseOnEOF ())
|
||||
comm->Disconnect ();
|
||||
comm->AppendBytesToCache (buf, bytes_read, true, status);
|
||||
}
|
||||
|
||||
switch (status)
|
||||
|
@ -384,7 +368,7 @@ Communication::ReadThread (void *p)
|
|||
case eConnectionStatusError: // Check GetError() for details
|
||||
case eConnectionStatusTimedOut: // Request timed out
|
||||
if (log)
|
||||
error.LogIfError(log.get(), "%p Communication::BytesAvailable () => status = %i", p, status);
|
||||
error.LogIfError(log.get(), "%p Communication::ReadFromConnection () => status = %i", p, status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,8 @@ ConnectionFileDescriptor::ConnectionFileDescriptor () :
|
|||
Connection(),
|
||||
m_fd (-1),
|
||||
m_is_socket (false),
|
||||
m_should_close_fd (false)
|
||||
m_should_close_fd (false),
|
||||
m_socket_timeout_usec(0)
|
||||
{
|
||||
lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT,
|
||||
"%p ConnectionFileDescriptor::ConnectionFileDescriptor ()",
|
||||
|
@ -50,7 +51,8 @@ ConnectionFileDescriptor::ConnectionFileDescriptor (int fd, bool owns_fd) :
|
|||
Connection(),
|
||||
m_fd (fd),
|
||||
m_is_socket (false),
|
||||
m_should_close_fd (owns_fd)
|
||||
m_should_close_fd (owns_fd),
|
||||
m_socket_timeout_usec(0)
|
||||
{
|
||||
lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT,
|
||||
"%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = %i, owns_fd = %i)",
|
||||
|
@ -185,13 +187,33 @@ ConnectionFileDescriptor::Disconnect (Error *error_ptr)
|
|||
}
|
||||
|
||||
size_t
|
||||
ConnectionFileDescriptor::Read (void *dst, size_t dst_len, ConnectionStatus &status, Error *error_ptr)
|
||||
ConnectionFileDescriptor::Read (void *dst,
|
||||
size_t dst_len,
|
||||
uint32_t timeout_usec,
|
||||
ConnectionStatus &status,
|
||||
Error *error_ptr)
|
||||
{
|
||||
LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
|
||||
if (log)
|
||||
log->Printf ("%p ConnectionFileDescriptor::Read () ::read (fd = %i, dst = %p, dst_len = %zu)...",
|
||||
this, m_fd, dst, dst_len);
|
||||
|
||||
if (timeout_usec == UINT32_MAX)
|
||||
{
|
||||
if (m_is_socket)
|
||||
SetSocketRecieveTimeout (0);
|
||||
status = eConnectionStatusSuccess;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_is_socket && SetSocketRecieveTimeout (timeout_usec))
|
||||
status = eConnectionStatusSuccess;
|
||||
else
|
||||
status = BytesAvailable (timeout_usec, error_ptr);
|
||||
}
|
||||
if (status != eConnectionStatusSuccess)
|
||||
return 0;
|
||||
|
||||
Error error;
|
||||
ssize_t bytes_read = ::read (m_fd, dst, dst_len);
|
||||
if (bytes_read == 0)
|
||||
|
@ -370,7 +392,7 @@ ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_pt
|
|||
|
||||
log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION);
|
||||
if (log)
|
||||
log->Printf("%p ConnectionFileDescriptor::Write() ::select (nfds = %i, fd = %i, NULL, NULL, timeout = %p)...",
|
||||
log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds = %i, fd = %i, NULL, NULL, timeout = %p)...",
|
||||
this, nfds, m_fd, tv_ptr);
|
||||
|
||||
const int num_set_fds = ::select (nfds, &read_fds, NULL, NULL, tv_ptr);
|
||||
|
@ -381,7 +403,7 @@ ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_pt
|
|||
|
||||
log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION);
|
||||
if (log)
|
||||
log->Printf("%p ConnectionFileDescriptor::Write() ::select (nfds = %i, fd = %i, NULL, NULL, timeout = %p) => %d, error = %s",
|
||||
log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds = %i, fd = %i, NULL, NULL, timeout = %p) => %d, error = %s",
|
||||
this, nfds, m_fd, tv_ptr, num_set_fds, error.AsCString());
|
||||
|
||||
if (error_ptr)
|
||||
|
@ -703,4 +725,25 @@ ConnectionFileDescriptor::SetSocketOption(int fd, int level, int option_name, in
|
|||
return ::setsockopt(fd, level, option_name, option_value_p, sizeof(option_value));
|
||||
}
|
||||
|
||||
bool
|
||||
ConnectionFileDescriptor::SetSocketRecieveTimeout (uint32_t timeout_usec)
|
||||
{
|
||||
if (m_is_socket)
|
||||
{
|
||||
// Check in case timeout for m_fd has already been set to this value
|
||||
if (timeout_usec == m_socket_timeout_usec)
|
||||
return true;
|
||||
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = timeout_usec / USEC_PER_SEC;
|
||||
timeout.tv_usec = timeout_usec % USEC_PER_SEC;
|
||||
if (::setsockopt (m_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == 0)
|
||||
{
|
||||
m_socket_timeout_usec = timeout_usec;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -213,7 +213,11 @@ ConnectionMachPort::Disconnect (Error *error_ptr)
|
|||
}
|
||||
|
||||
size_t
|
||||
ConnectionMachPort::Read (void *dst, size_t dst_len, ConnectionStatus &status, Error *error_ptr)
|
||||
ConnectionMachPort::Read (void *dst,
|
||||
size_t dst_len,
|
||||
uint32_t timeout_usec,
|
||||
ConnectionStatus &status,
|
||||
Error *error_ptr)
|
||||
{
|
||||
PayloadType payload;
|
||||
|
||||
|
|
|
@ -80,7 +80,11 @@ ConnectionSharedMemory::Disconnect (Error *error_ptr)
|
|||
}
|
||||
|
||||
size_t
|
||||
ConnectionSharedMemory::Read (void *dst, size_t dst_len, ConnectionStatus &status, Error *error_ptr)
|
||||
ConnectionSharedMemory::Read (void *dst,
|
||||
size_t dst_len,
|
||||
uint32_t timeout_usec,
|
||||
ConnectionStatus &status,
|
||||
Error *error_ptr)
|
||||
{
|
||||
status = eConnectionStatusSuccess;
|
||||
return 0;
|
||||
|
|
|
@ -195,7 +195,7 @@ AcceptPIDFromInferior (void *arg)
|
|||
char pid_str[256];
|
||||
::memset (pid_str, 0, sizeof(pid_str));
|
||||
ConnectionStatus status;
|
||||
const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), status, NULL);
|
||||
const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), NULL, status, NULL);
|
||||
if (pid_str_len > 0)
|
||||
{
|
||||
int pid = atoi (pid_str);
|
||||
|
|
|
@ -258,26 +258,40 @@ RegisterContextLLDB::InitializeNonZerothFrame()
|
|||
m_current_offset_backed_up_one = -1;
|
||||
addr_t cfa_regval;
|
||||
int row_register_kind = m_full_unwind_plan_sp->GetRegisterKind ();
|
||||
uint32_t cfa_regnum = m_full_unwind_plan_sp->GetRowForFunctionOffset(0)->GetCFARegister();
|
||||
int cfa_offset = m_full_unwind_plan_sp->GetRowForFunctionOffset(0)->GetCFAOffset();
|
||||
if (!ReadGPRValue (row_register_kind, cfa_regnum, cfa_regval))
|
||||
const UnwindPlan::Row *row = m_full_unwind_plan_sp->GetRowForFunctionOffset(0);
|
||||
if (row)
|
||||
{
|
||||
if (log)
|
||||
uint32_t cfa_regnum = row->GetCFARegister();
|
||||
int cfa_offset = row->GetCFAOffset();
|
||||
if (!ReadGPRValue (row_register_kind, cfa_regnum, cfa_regval))
|
||||
{
|
||||
log->Printf("%*sFrame %u failed to get cfa value",
|
||||
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
|
||||
if (log)
|
||||
{
|
||||
log->Printf("%*sFrame %u failed to get cfa value",
|
||||
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
|
||||
}
|
||||
m_frame_type = eNormalFrame;
|
||||
return;
|
||||
}
|
||||
m_frame_type = eNormalFrame;
|
||||
return;
|
||||
}
|
||||
m_cfa = cfa_regval + cfa_offset;
|
||||
m_cfa = cfa_regval + cfa_offset;
|
||||
|
||||
// A couple of sanity checks..
|
||||
if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1)
|
||||
// A couple of sanity checks..
|
||||
if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1)
|
||||
{
|
||||
if (log)
|
||||
{
|
||||
log->Printf("%*sFrame %u could not find a valid cfa address",
|
||||
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
|
||||
}
|
||||
m_frame_type = eNotAValidFrame;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (log)
|
||||
{
|
||||
log->Printf("%*sFrame %u could not find a valid cfa address",
|
||||
log->Printf("%*sFrame %u could not find a row for function offset zero",
|
||||
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
|
||||
}
|
||||
m_frame_type = eNotAValidFrame;
|
||||
|
|
|
@ -39,16 +39,12 @@ GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name,
|
|||
bool is_platform) :
|
||||
Communication(comm_name),
|
||||
m_packet_timeout (60),
|
||||
m_rx_packet_listener (listener_name),
|
||||
m_sequence_mutex (Mutex::eMutexTypeRecursive),
|
||||
m_public_is_running (false),
|
||||
m_private_is_running (false),
|
||||
m_send_acks (true),
|
||||
m_is_platform (is_platform)
|
||||
{
|
||||
m_rx_packet_listener.StartListeningForEvents(this,
|
||||
Communication::eBroadcastBitPacketAvailable |
|
||||
Communication::eBroadcastBitReadThreadDidExit);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -56,12 +52,8 @@ GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name,
|
|||
//----------------------------------------------------------------------
|
||||
GDBRemoteCommunication::~GDBRemoteCommunication()
|
||||
{
|
||||
m_rx_packet_listener.StopListeningForEvents(this,
|
||||
Communication::eBroadcastBitPacketAvailable |
|
||||
Communication::eBroadcastBitReadThreadDidExit);
|
||||
if (IsConnected())
|
||||
{
|
||||
StopReadThread();
|
||||
Disconnect();
|
||||
}
|
||||
}
|
||||
|
@ -167,7 +159,7 @@ char
|
|||
GDBRemoteCommunication::GetAck ()
|
||||
{
|
||||
StringExtractorGDBRemote packet;
|
||||
if (WaitForPacket (packet, m_packet_timeout) == 1)
|
||||
if (WaitForPacketWithTimeoutMicroSeconds (packet, GetPacketTimeoutInMicroSeconds ()) == 1)
|
||||
return packet.GetChar();
|
||||
return 0;
|
||||
}
|
||||
|
@ -186,99 +178,63 @@ GDBRemoteCommunication::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
|
|||
}
|
||||
|
||||
size_t
|
||||
GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &packet, uint32_t timeout_seconds)
|
||||
GDBRemoteCommunication::WaitForPacketWithTimeoutMicroSeconds (StringExtractorGDBRemote &packet, uint32_t timeout_usec)
|
||||
{
|
||||
Mutex::Locker locker(m_sequence_mutex);
|
||||
TimeValue timeout_time;
|
||||
timeout_time = TimeValue::Now();
|
||||
timeout_time.OffsetWithSeconds (timeout_seconds);
|
||||
return WaitForPacketNoLock (packet, &timeout_time);
|
||||
return WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec);
|
||||
}
|
||||
|
||||
size_t
|
||||
GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &packet, const TimeValue* timeout_time_ptr)
|
||||
GDBRemoteCommunication::WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractorGDBRemote &packet, uint32_t timeout_usec)
|
||||
{
|
||||
Mutex::Locker locker(m_sequence_mutex);
|
||||
return WaitForPacketNoLock (packet, timeout_time_ptr);
|
||||
}
|
||||
uint8_t buffer[8192];
|
||||
Error error;
|
||||
|
||||
size_t
|
||||
GDBRemoteCommunication::WaitForPacketNoLock (StringExtractorGDBRemote &packet, const TimeValue* timeout_time_ptr)
|
||||
{
|
||||
bool checksum_error = false;
|
||||
packet.Clear ();
|
||||
// Check for a packet from our cache first without trying any reading...
|
||||
if (CheckForPacket (NULL, 0, packet))
|
||||
return packet.GetStringRef().size();
|
||||
|
||||
EventSP event_sp;
|
||||
|
||||
if (m_rx_packet_listener.WaitForEvent (timeout_time_ptr, event_sp))
|
||||
bool timed_out = false;
|
||||
while (IsConnected() && !timed_out)
|
||||
{
|
||||
const uint32_t event_type = event_sp->GetType();
|
||||
if (event_type | Communication::eBroadcastBitPacketAvailable)
|
||||
lldb::ConnectionStatus status;
|
||||
size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error);
|
||||
if (bytes_read > 0)
|
||||
{
|
||||
const EventDataBytes *event_bytes = EventDataBytes::GetEventDataFromEvent(event_sp.get());
|
||||
if (event_bytes)
|
||||
if (CheckForPacket (buffer, bytes_read, packet))
|
||||
return packet.GetStringRef().size();
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
const char *packet_data = (const char *)event_bytes->GetBytes();
|
||||
const uint32_t packet_size = event_bytes->GetByteSize();
|
||||
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
|
||||
if (log)
|
||||
log->Printf ("read packet: %.*s", packet_size, packet_data);
|
||||
if (packet_data && packet_size > 0)
|
||||
{
|
||||
std::string &packet_str = packet.GetStringRef();
|
||||
if (packet_data[0] == '$')
|
||||
{
|
||||
bool success = false;
|
||||
if (packet_size < 4)
|
||||
::fprintf (stderr, "Packet that starts with $ is too short: '%s'\n", packet_data);
|
||||
else if (packet_data[packet_size-3] != '#' ||
|
||||
!::isxdigit (packet_data[packet_size-2]) ||
|
||||
!::isxdigit (packet_data[packet_size-1]))
|
||||
::fprintf (stderr, "Invalid checksum footer for packet: '%s'\n", packet_data);
|
||||
else
|
||||
success = true;
|
||||
|
||||
if (success)
|
||||
packet_str.assign (packet_data + 1, packet_size - 4);
|
||||
if (GetSendAcks ())
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
char packet_checksum = strtol (&packet_data[packet_size-2], NULL, 16);
|
||||
char actual_checksum = CalculcateChecksum (&packet_str[0], packet_str.size());
|
||||
checksum_error = packet_checksum != actual_checksum;
|
||||
}
|
||||
// Send the ack or nack if needed
|
||||
if (checksum_error || !success)
|
||||
SendNack();
|
||||
else
|
||||
SendAck();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
packet_str.assign (packet_data, packet_size);
|
||||
}
|
||||
return packet_str.size();
|
||||
}
|
||||
case eConnectionStatusSuccess:
|
||||
break;
|
||||
|
||||
case eConnectionStatusEndOfFile:
|
||||
case eConnectionStatusNoConnection:
|
||||
case eConnectionStatusLostConnection:
|
||||
case eConnectionStatusError:
|
||||
Disconnect();
|
||||
break;
|
||||
|
||||
case eConnectionStatusTimedOut:
|
||||
timed_out = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (event_type | Communication::eBroadcastBitReadThreadDidExit)
|
||||
{
|
||||
// Our read thread exited on us so just fall through and return zero...
|
||||
Disconnect();
|
||||
}
|
||||
}
|
||||
packet.Clear ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
GDBRemoteCommunication::AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast,
|
||||
ConnectionStatus status)
|
||||
bool
|
||||
GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, StringExtractorGDBRemote &packet)
|
||||
{
|
||||
// Put the packet data into the buffer in a thread safe fashion
|
||||
Mutex::Locker locker(m_bytes_mutex);
|
||||
m_bytes.append ((const char *)src, src_len);
|
||||
if (src && src_len > 0)
|
||||
m_bytes.append ((const char *)src, src_len);
|
||||
|
||||
// Parse up the packets into gdb remote packets
|
||||
while (!m_bytes.empty())
|
||||
|
@ -286,29 +242,40 @@ GDBRemoteCommunication::AppendBytesToCache (const uint8_t *src, size_t src_len,
|
|||
// 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 end_idx = 0;
|
||||
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
|
||||
end_idx = 1; // The command is one byte long...
|
||||
content_length = total_length = 1; // The command is one byte long...
|
||||
break;
|
||||
|
||||
case '$':
|
||||
// Look for a standard gdb packet?
|
||||
end_idx = m_bytes.find('#');
|
||||
if (end_idx != std::string::npos)
|
||||
{
|
||||
if (end_idx + 2 < m_bytes.size())
|
||||
size_t hash_pos = m_bytes.find('#');
|
||||
if (hash_pos != std::string::npos)
|
||||
{
|
||||
end_idx += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Checksum bytes aren't all here yet
|
||||
end_idx = 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;
|
||||
|
@ -317,27 +284,76 @@ GDBRemoteCommunication::AppendBytesToCache (const uint8_t *src, size_t src_len,
|
|||
break;
|
||||
}
|
||||
|
||||
if (end_idx == std::string::npos)
|
||||
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
|
||||
if (content_length == std::string::npos)
|
||||
{
|
||||
//ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE, "GDBRemoteCommunication::%s packet not yet complete: '%s'",__FUNCTION__, m_bytes.c_str());
|
||||
return;
|
||||
packet.Clear();
|
||||
return false;
|
||||
}
|
||||
else if (end_idx > 0)
|
||||
else if (content_length > 0)
|
||||
{
|
||||
|
||||
// We have a valid packet...
|
||||
assert (end_idx <= m_bytes.size());
|
||||
std::auto_ptr<EventDataBytes> event_bytes_ap (new EventDataBytes (&m_bytes[0], end_idx));
|
||||
ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "got full packet: %s", event_bytes_ap->GetBytes());
|
||||
BroadcastEvent (eBroadcastBitPacketAvailable, event_bytes_ap.release());
|
||||
m_bytes.erase(0, end_idx);
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert (1 <= m_bytes.size());
|
||||
ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "GDBRemoteCommunication::%s tossing junk byte at %c",__FUNCTION__, m_bytes[0]);
|
||||
if (log)
|
||||
log->Printf ("GDBRemoteCommunication::%s tossing junk byte at %c",__FUNCTION__, m_bytes[0]);
|
||||
m_bytes.erase(0, 1);
|
||||
}
|
||||
}
|
||||
packet.Clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
Error
|
||||
|
|
|
@ -56,14 +56,8 @@ public:
|
|||
|
||||
// Wait for a packet within 'nsec' seconds
|
||||
size_t
|
||||
WaitForPacket (StringExtractorGDBRemote &response,
|
||||
uint32_t sec);
|
||||
|
||||
// Wait for a packet with an absolute timeout time. If 'timeout' is NULL
|
||||
// wait indefinitely.
|
||||
size_t
|
||||
WaitForPacket (StringExtractorGDBRemote &response,
|
||||
const lldb_private::TimeValue* timeout);
|
||||
WaitForPacketWithTimeoutMicroSeconds (StringExtractorGDBRemote &response,
|
||||
uint32_t usec);
|
||||
|
||||
char
|
||||
GetAck ();
|
||||
|
@ -81,12 +75,10 @@ public:
|
|||
bool
|
||||
GetSequenceMutex(lldb_private::Mutex::Locker& locker);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Communication overrides
|
||||
//------------------------------------------------------------------
|
||||
virtual void
|
||||
AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast, lldb::ConnectionStatus status);
|
||||
|
||||
bool
|
||||
CheckForPacket (const uint8_t *src,
|
||||
size_t src_len,
|
||||
StringExtractorGDBRemote &packet);
|
||||
bool
|
||||
IsRunning() const
|
||||
{
|
||||
|
@ -121,6 +113,11 @@ public:
|
|||
return old_packet_timeout;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
GetPacketTimeoutInMicroSeconds () const
|
||||
{
|
||||
return m_packet_timeout * USEC_PER_SEC;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
// Start a debugserver instance on the current host using the
|
||||
// supplied connection URL.
|
||||
|
@ -130,6 +127,7 @@ public:
|
|||
const char *unix_socket_name,
|
||||
lldb_private::ProcessLaunchInfo &launch_info);
|
||||
|
||||
|
||||
protected:
|
||||
typedef std::list<std::string> packet_collection;
|
||||
|
||||
|
@ -138,8 +136,8 @@ protected:
|
|||
size_t payload_length);
|
||||
|
||||
size_t
|
||||
WaitForPacketNoLock (StringExtractorGDBRemote &response,
|
||||
const lldb_private::TimeValue* timeout_ptr);
|
||||
WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractorGDBRemote &response,
|
||||
uint32_t timeout_usec);
|
||||
|
||||
bool
|
||||
WaitForNotRunningPrivate (const lldb_private::TimeValue *timeout_ptr);
|
||||
|
@ -148,7 +146,6 @@ protected:
|
|||
// Classes that inherit from GDBRemoteCommunication can see and modify these
|
||||
//------------------------------------------------------------------
|
||||
uint32_t m_packet_timeout;
|
||||
lldb_private::Listener m_rx_packet_listener;
|
||||
lldb_private::Mutex m_sequence_mutex; // Restrict access to sending/receiving packets to a single thread at a time
|
||||
lldb_private::Predicate<bool> m_public_is_running;
|
||||
lldb_private::Predicate<bool> m_private_is_running;
|
||||
|
|
|
@ -68,9 +68,6 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
|
|||
m_os_version_minor (UINT32_MAX),
|
||||
m_os_version_update (UINT32_MAX)
|
||||
{
|
||||
m_rx_packet_listener.StartListeningForEvents(this,
|
||||
Communication::eBroadcastBitPacketAvailable |
|
||||
Communication::eBroadcastBitReadThreadDidExit);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -78,14 +75,8 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
|
|||
//----------------------------------------------------------------------
|
||||
GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient()
|
||||
{
|
||||
m_rx_packet_listener.StopListeningForEvents(this,
|
||||
Communication::eBroadcastBitPacketAvailable |
|
||||
Communication::eBroadcastBitReadThreadDidExit);
|
||||
if (IsConnected())
|
||||
{
|
||||
StopReadThread();
|
||||
Disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -94,7 +85,7 @@ GDBRemoteCommunicationClient::HandshakeWithServer (Error *error_ptr)
|
|||
// Start the read thread after we send the handshake ack since if we
|
||||
// fail to send the handshake ack, there is no reason to continue...
|
||||
if (SendAck())
|
||||
return StartReadThread (error_ptr);
|
||||
return true;
|
||||
|
||||
if (error_ptr)
|
||||
error_ptr->SetErrorString("failed to send the handshake ack");
|
||||
|
@ -245,15 +236,12 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
|
|||
)
|
||||
{
|
||||
Mutex::Locker locker;
|
||||
TimeValue timeout_time;
|
||||
timeout_time = TimeValue::Now();
|
||||
timeout_time.OffsetWithSeconds (m_packet_timeout);
|
||||
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
|
||||
|
||||
if (GetSequenceMutex (locker))
|
||||
{
|
||||
if (SendPacketNoLock (payload, payload_length))
|
||||
return WaitForPacketNoLock (response, &timeout_time);
|
||||
return WaitForPacketWithTimeoutMicroSecondsNoLock (response, GetPacketTimeoutInMicroSeconds ());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -272,6 +260,10 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
|
|||
{
|
||||
if (sent_interrupt)
|
||||
{
|
||||
TimeValue timeout_time;
|
||||
timeout_time = TimeValue::Now();
|
||||
timeout_time.OffsetWithSeconds (m_packet_timeout);
|
||||
|
||||
if (log)
|
||||
log->Printf ("async: sent interrupt");
|
||||
if (m_async_packet_predicate.WaitForValueEqualTo (false, &timeout_time, &timed_out))
|
||||
|
@ -380,7 +372,7 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
|
|||
if (log)
|
||||
log->Printf ("GDBRemoteCommunicationClient::%s () WaitForPacket(%.*s)", __FUNCTION__);
|
||||
|
||||
if (WaitForPacket (response, (TimeValue*)NULL))
|
||||
if (WaitForPacketWithTimeoutMicroSeconds (response, UINT32_MAX))
|
||||
{
|
||||
if (response.Empty())
|
||||
state = eStateInvalid;
|
||||
|
@ -1662,13 +1654,9 @@ GDBRemoteCommunicationClient::GetCurrentThreadIDs (std::vector<lldb::tid_t> &thr
|
|||
sequence_mutex_unavailable = false;
|
||||
StringExtractorGDBRemote response;
|
||||
|
||||
TimeValue timeout_time;
|
||||
timeout_time = TimeValue::Now();
|
||||
timeout_time.OffsetWithSeconds (m_packet_timeout*2); // We will always send at least two packets here...
|
||||
|
||||
for (SendPacketNoLock ("qfThreadInfo", strlen("qfThreadInfo")) && WaitForPacketNoLock (response, &timeout_time);
|
||||
for (SendPacketNoLock ("qfThreadInfo", strlen("qfThreadInfo")) && WaitForPacketWithTimeoutMicroSecondsNoLock (response, GetPacketTimeoutInMicroSeconds ());
|
||||
response.IsNormalResponse();
|
||||
SendPacketNoLock ("qsThreadInfo", strlen("qsThreadInfo")) && WaitForPacketNoLock (response, &timeout_time))
|
||||
SendPacketNoLock ("qsThreadInfo", strlen("qsThreadInfo")) && WaitForPacketWithTimeoutMicroSecondsNoLock (response, GetPacketTimeoutInMicroSeconds ()))
|
||||
{
|
||||
char ch = response.GetChar();
|
||||
if (ch == 'l')
|
||||
|
|
|
@ -78,13 +78,13 @@ GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer()
|
|||
//}
|
||||
//
|
||||
bool
|
||||
GDBRemoteCommunicationServer::GetPacketAndSendResponse (const TimeValue* timeout_ptr,
|
||||
GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
|
||||
Error &error,
|
||||
bool &interrupt,
|
||||
bool &quit)
|
||||
{
|
||||
StringExtractorGDBRemote packet;
|
||||
if (WaitForPacketNoLock (packet, timeout_ptr))
|
||||
if (WaitForPacketWithTimeoutMicroSeconds(packet, timeout_usec))
|
||||
{
|
||||
const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType ();
|
||||
switch (packet_type)
|
||||
|
@ -199,9 +199,7 @@ GDBRemoteCommunicationServer::SendOKResponse ()
|
|||
bool
|
||||
GDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr)
|
||||
{
|
||||
if (StartReadThread(error_ptr))
|
||||
return GetAck();
|
||||
return false;
|
||||
return GetAck();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -517,7 +515,7 @@ AcceptPortFromInferior (void *arg)
|
|||
char pid_str[256];
|
||||
::memset (pid_str, 0, sizeof(pid_str));
|
||||
ConnectionStatus status;
|
||||
const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), status, NULL);
|
||||
const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), NULL, status, NULL);
|
||||
if (pid_str_len > 0)
|
||||
{
|
||||
int pid = atoi (pid_str);
|
||||
|
|
|
@ -37,7 +37,7 @@ public:
|
|||
~GDBRemoteCommunicationServer();
|
||||
|
||||
bool
|
||||
GetPacketAndSendResponse (const lldb_private::TimeValue* timeout_ptr,
|
||||
GetPacketAndSendResponse (uint32_t timeout_usec,
|
||||
lldb_private::Error &error,
|
||||
bool &interrupt,
|
||||
bool &quit);
|
||||
|
|
|
@ -2273,10 +2273,16 @@ SymbolFileDWARF::FindTypes(const SymbolContext& sc, const ConstString &name, boo
|
|||
{
|
||||
// We found a type pointer, now find the shared pointer form our type list
|
||||
TypeSP type_sp (GetTypeList()->FindType(matching_type->GetID()));
|
||||
assert (type_sp.get() != NULL);
|
||||
types.InsertUnique (type_sp);
|
||||
if (types.GetSize() >= max_matches)
|
||||
break;
|
||||
if (type_sp)
|
||||
{
|
||||
types.InsertUnique (type_sp);
|
||||
if (types.GetSize() >= max_matches)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "error: can't find shared pointer for type 0x%8.8x.\n", matching_type->GetID());
|
||||
}
|
||||
}
|
||||
}
|
||||
return types.GetSize() - initial_types_size;
|
||||
|
@ -4170,7 +4176,6 @@ SymbolFileDWARF::ParseVariables
|
|||
if (orig_die == NULL)
|
||||
return 0;
|
||||
|
||||
size_t vars_added = 0;
|
||||
const DWARFDebugInfoEntry *die = orig_die;
|
||||
const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(orig_die);
|
||||
dw_tag_t parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0;
|
||||
|
@ -4189,8 +4194,12 @@ SymbolFileDWARF::ParseVariables
|
|||
}
|
||||
else
|
||||
{
|
||||
assert(!"Parent DIE was a compile unit, yet we don't have a valid compile unit in the symbol context...");
|
||||
vars_added = 0;
|
||||
fprintf (stderr,
|
||||
"error: parent 0x%8.8x %s with no valid compile unit in symbol context for 0x%8.8x %s.\n",
|
||||
sc_parent_die->GetOffset(),
|
||||
DW_TAG_value_to_name (parent_tag),
|
||||
orig_die->GetOffset(),
|
||||
DW_TAG_value_to_name (orig_die->Tag()));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -4202,71 +4211,91 @@ SymbolFileDWARF::ParseVariables
|
|||
// Check to see if we already have parsed the variables for the given scope
|
||||
|
||||
Block *block = sc.function->GetBlock(true).FindBlockByID(sc_parent_die->GetOffset());
|
||||
assert (block != NULL);
|
||||
variables = block->GetVariableList(false, false);
|
||||
if (variables.get() == NULL)
|
||||
if (block != NULL)
|
||||
{
|
||||
variables.reset(new VariableList());
|
||||
block->SetVariableList(variables);
|
||||
variables = block->GetVariableList(false, false);
|
||||
if (variables.get() == NULL)
|
||||
{
|
||||
variables.reset(new VariableList());
|
||||
block->SetVariableList(variables);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr,
|
||||
"error: NULL block for 0x%8.8x %s for variable at 0x%8.8x %s\n",
|
||||
sc_parent_die->GetOffset(),
|
||||
DW_TAG_value_to_name (parent_tag),
|
||||
orig_die->GetOffset(),
|
||||
DW_TAG_value_to_name (orig_die->Tag()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(!"Parent DIE was a function or block, yet we don't have a function in the symbol context...");
|
||||
vars_added = 0;
|
||||
fprintf (stderr,
|
||||
"error: parent 0x%8.8x %s with no valid function in symbol context for 0x%8.8x %s.\n",
|
||||
sc_parent_die->GetOffset(),
|
||||
DW_TAG_value_to_name (parent_tag),
|
||||
orig_die->GetOffset(),
|
||||
DW_TAG_value_to_name (orig_die->Tag()));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(!"Didn't find appropriate parent DIE for variable list...");
|
||||
fprintf (stderr,
|
||||
"error: didn't find appropriate parent DIE for variable list for 0x%8.8x %s.\n",
|
||||
orig_die->GetOffset(),
|
||||
DW_TAG_value_to_name (orig_die->Tag()));
|
||||
break;
|
||||
}
|
||||
|
||||
// We need to have a variable list at this point that we can add variables to
|
||||
assert(variables.get());
|
||||
|
||||
while (die != NULL)
|
||||
if (variables.get())
|
||||
{
|
||||
dw_tag_t tag = die->Tag();
|
||||
size_t vars_added = 0;
|
||||
while (die != NULL)
|
||||
{
|
||||
dw_tag_t tag = die->Tag();
|
||||
|
||||
// Check to see if we have already parsed this variable or constant?
|
||||
if (m_die_to_variable_sp[die])
|
||||
{
|
||||
if (cc_variable_list)
|
||||
cc_variable_list->AddVariableIfUnique (m_die_to_variable_sp[die]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We haven't already parsed it, lets do that now.
|
||||
if ((tag == DW_TAG_variable) ||
|
||||
(tag == DW_TAG_constant) ||
|
||||
(tag == DW_TAG_formal_parameter && sc.function))
|
||||
// Check to see if we have already parsed this variable or constant?
|
||||
if (m_die_to_variable_sp[die])
|
||||
{
|
||||
VariableSP var_sp (ParseVariableDIE(sc, dwarf_cu, die, func_low_pc));
|
||||
if (var_sp)
|
||||
if (cc_variable_list)
|
||||
cc_variable_list->AddVariableIfUnique (m_die_to_variable_sp[die]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We haven't already parsed it, lets do that now.
|
||||
if ((tag == DW_TAG_variable) ||
|
||||
(tag == DW_TAG_constant) ||
|
||||
(tag == DW_TAG_formal_parameter && sc.function))
|
||||
{
|
||||
variables->AddVariableIfUnique (var_sp);
|
||||
if (cc_variable_list)
|
||||
cc_variable_list->AddVariableIfUnique (var_sp);
|
||||
++vars_added;
|
||||
VariableSP var_sp (ParseVariableDIE(sc, dwarf_cu, die, func_low_pc));
|
||||
if (var_sp)
|
||||
{
|
||||
variables->AddVariableIfUnique (var_sp);
|
||||
if (cc_variable_list)
|
||||
cc_variable_list->AddVariableIfUnique (var_sp);
|
||||
++vars_added;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool skip_children = (sc.function == NULL && tag == DW_TAG_subprogram);
|
||||
|
||||
if (!skip_children && parse_children && die->HasChildren())
|
||||
{
|
||||
vars_added += ParseVariables(sc, dwarf_cu, func_low_pc, die->GetFirstChild(), true, true, cc_variable_list);
|
||||
}
|
||||
|
||||
if (parse_siblings)
|
||||
die = die->GetSibling();
|
||||
else
|
||||
die = NULL;
|
||||
}
|
||||
|
||||
bool skip_children = (sc.function == NULL && tag == DW_TAG_subprogram);
|
||||
|
||||
if (!skip_children && parse_children && die->HasChildren())
|
||||
{
|
||||
vars_added += ParseVariables(sc, dwarf_cu, func_low_pc, die->GetFirstChild(), true, true, cc_variable_list);
|
||||
}
|
||||
|
||||
if (parse_siblings)
|
||||
die = die->GetSibling();
|
||||
else
|
||||
die = NULL;
|
||||
return vars_added;
|
||||
}
|
||||
|
||||
return vars_added;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
|
|
@ -300,7 +300,7 @@ DWARFCallFrameInfo::GetFDEIndex ()
|
|||
}
|
||||
while (m_cfi_data.ValidOffsetForDataOfSize (offset, 8))
|
||||
{
|
||||
dw_offset_t current_entry = offset;
|
||||
const dw_offset_t current_entry = offset;
|
||||
uint32_t len = m_cfi_data.GetU32 (&offset);
|
||||
dw_offset_t next_entry = current_entry + len + 4;
|
||||
dw_offset_t cie_id = m_cfi_data.GetU32 (&offset);
|
||||
|
@ -312,20 +312,29 @@ DWARFCallFrameInfo::GetFDEIndex ()
|
|||
continue;
|
||||
}
|
||||
|
||||
const CIE *cie = GetCIE (current_entry + 4 - cie_id);
|
||||
assert (cie != NULL);
|
||||
|
||||
const lldb::addr_t pc_rel_addr = m_section->GetFileAddress();
|
||||
const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS;
|
||||
const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS;
|
||||
|
||||
lldb::addr_t addr = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding, pc_rel_addr, text_addr, data_addr);
|
||||
lldb::addr_t length = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding & DW_EH_PE_MASK_ENCODING, pc_rel_addr, text_addr, data_addr);
|
||||
FDEEntry fde;
|
||||
fde.bounds = AddressRange (addr, length, m_objfile.GetSectionList());
|
||||
fde.offset = current_entry;
|
||||
m_fde_index.push_back(fde);
|
||||
const dw_offset_t cie_offset = current_entry + 4 - cie_id;
|
||||
const CIE *cie = GetCIE (cie_offset);
|
||||
if (cie)
|
||||
{
|
||||
const lldb::addr_t pc_rel_addr = m_section->GetFileAddress();
|
||||
const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS;
|
||||
const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS;
|
||||
|
||||
lldb::addr_t addr = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding, pc_rel_addr, text_addr, data_addr);
|
||||
lldb::addr_t length = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding & DW_EH_PE_MASK_ENCODING, pc_rel_addr, text_addr, data_addr);
|
||||
FDEEntry fde;
|
||||
fde.bounds = AddressRange (addr, length, m_objfile.GetSectionList());
|
||||
fde.offset = current_entry;
|
||||
m_fde_index.push_back(fde);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr,
|
||||
"error: unable to find CIE at 0x%8.8x for cie_id = 0x%8.8x for entry at 0x%8.8x.\n",
|
||||
cie_offset,
|
||||
cie_id,
|
||||
current_entry);
|
||||
}
|
||||
offset = next_entry;
|
||||
}
|
||||
std::sort (m_fde_index.begin(), m_fde_index.end());
|
||||
|
|
|
@ -72,7 +72,7 @@ main (int argc, char *argv[])
|
|||
StreamSP log_stream_sp;
|
||||
Args log_args;
|
||||
Error error;
|
||||
std::string listen_host_post;
|
||||
std::string listen_host_port;
|
||||
char ch;
|
||||
Debugger::Initialize();
|
||||
|
||||
|
@ -163,7 +163,7 @@ main (int argc, char *argv[])
|
|||
break;
|
||||
|
||||
case 'L':
|
||||
listen_host_post.append (optarg);
|
||||
listen_host_port.append (optarg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -181,15 +181,15 @@ main (int argc, char *argv[])
|
|||
|
||||
|
||||
GDBRemoteCommunicationServer gdb_server (true);
|
||||
if (!listen_host_post.empty())
|
||||
if (!listen_host_port.empty())
|
||||
{
|
||||
std::auto_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
|
||||
if (conn_ap.get())
|
||||
{
|
||||
std::string connect_url ("listen://");
|
||||
connect_url.append(listen_host_post.c_str());
|
||||
connect_url.append(listen_host_port.c_str());
|
||||
|
||||
printf ("Listening for a connection on %s...\n", listen_host_post.c_str());
|
||||
printf ("Listening for a connection on %s...\n", listen_host_port.c_str());
|
||||
if (conn_ap->Connect(connect_url.c_str(), &error) == eConnectionStatusSuccess)
|
||||
{
|
||||
printf ("Connection established.\n");
|
||||
|
@ -208,7 +208,7 @@ main (int argc, char *argv[])
|
|||
bool done = false;
|
||||
while (!interrupt && !done)
|
||||
{
|
||||
if (!gdb_server.GetPacketAndSendResponse(NULL, error, interrupt, done))
|
||||
if (!gdb_server.GetPacketAndSendResponse (UINT32_MAX, error, interrupt, done))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue