Please use GitHub pull requests for new patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
Show First 20 Lines • Show All 233 Lines • ▼ Show 20 Lines | while (result == PacketResult::Success && response.IsNormalResponse() && | ||||
std::string output; | std::string output; | ||||
if (response.GetHexByteString(output)) | if (response.GetHexByteString(output)) | ||||
output_callback(output); | output_callback(output); | ||||
result = ReadPacket(response, timeout, sync_on_timeout); | result = ReadPacket(response, timeout, sync_on_timeout); | ||||
} | } | ||||
return result; | return result; | ||||
} | } | ||||
GDBRemoteCommunication::PacketResult | GDBRemoteCommunication::PacketResult GDBRemoteCommunication::ReadPacket( | ||||
GDBRemoteCommunication::ReadPacket(StringExtractorGDBRemote &response, | StringExtractorGDBRemote &response, Timeout<std::micro> timeout, | ||||
Timeout<std::micro> timeout, | bool sync_on_timeout, bool allow_notification) { | ||||
bool sync_on_timeout) { | |||||
using ResponseType = StringExtractorGDBRemote::ResponseType; | using ResponseType = StringExtractorGDBRemote::ResponseType; | ||||
Log *log = GetLog(GDBRLog::Packets); | Log *log = GetLog(GDBRLog::Packets); | ||||
for (;;) { | for (;;) { | ||||
PacketResult result = | PacketResult result = WaitForPacketNoLock( | ||||
WaitForPacketNoLock(response, timeout, sync_on_timeout); | response, timeout, sync_on_timeout, allow_notification); | ||||
if (result != PacketResult::Success || | if (result != PacketResult::Success || | ||||
(response.GetResponseType() != ResponseType::eAck && | (response.GetResponseType() != ResponseType::eAck && | ||||
response.GetResponseType() != ResponseType::eNack)) | response.GetResponseType() != ResponseType::eNack)) | ||||
return result; | return result; | ||||
LLDB_LOG(log, "discarding spurious `{0}` packet", response.GetStringRef()); | LLDB_LOG(log, "discarding spurious `{0}` packet", response.GetStringRef()); | ||||
} | } | ||||
} | } | ||||
GDBRemoteCommunication::PacketResult | GDBRemoteCommunication::PacketResult | ||||
GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet, | GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet, | ||||
Timeout<std::micro> timeout, | Timeout<std::micro> timeout, | ||||
bool sync_on_timeout) { | bool sync_on_timeout, | ||||
bool allow_notification) { | |||||
uint8_t buffer[8192]; | uint8_t buffer[8192]; | ||||
Status error; | Status error; | ||||
Log *log = GetLog(GDBRLog::Packets); | Log *log = GetLog(GDBRLog::Packets); | ||||
// Check for a packet from our cache first without trying any reading... | // If the caller expects notifications, check the notification queue first. | ||||
if (CheckForPacket(nullptr, 0, packet) != PacketType::Invalid) | if (allow_notification && !m_notification_packet_queue.empty()) { | ||||
packet.Reset(m_notification_packet_queue.front()); | |||||
m_notification_packet_queue.pop_front(); | |||||
return PacketResult::Success; | return PacketResult::Success; | ||||
} | |||||
// Check for a packet from our cache first without trying any reading... | |||||
PacketType packet_type = CheckForPacket(nullptr, 0, packet); | |||||
if (packet_type == PacketType::Notify && !allow_notification) { | |||||
// If the caller does not support notifications, queue it for later. | |||||
m_notification_packet_queue.push_back(packet.GetStringRef().str()); | |||||
packet_type = CheckForPacket(nullptr, 0, packet); | |||||
} | |||||
if (packet_type != PacketType::Invalid) | |||||
return packet_type == PacketType::Standard ? PacketResult::Success | |||||
: PacketResult::Notify; | |||||
bool timed_out = false; | bool timed_out = false; | ||||
bool disconnected = false; | bool disconnected = false; | ||||
while (IsConnected() && !timed_out) { | while (IsConnected() && !timed_out) { | ||||
lldb::ConnectionStatus status = eConnectionStatusNoConnection; | lldb::ConnectionStatus status = eConnectionStatusNoConnection; | ||||
size_t bytes_read = Read(buffer, sizeof(buffer), timeout, status, &error); | size_t bytes_read = Read(buffer, sizeof(buffer), timeout, status, &error); | ||||
LLDB_LOGV(log, | LLDB_LOGV(log, | ||||
"Read(buffer, sizeof(buffer), timeout = {0}, " | "Read(buffer, sizeof(buffer), timeout = {0}, " | ||||
"status = {1}, error = {2}) => bytes_read = {3}", | "status = {1}, error = {2}) => bytes_read = {3}", | ||||
timeout, Communication::ConnectionStatusAsString(status), error, | timeout, Communication::ConnectionStatusAsString(status), error, | ||||
bytes_read); | bytes_read); | ||||
if (bytes_read > 0) { | if (bytes_read > 0) { | ||||
if (CheckForPacket(buffer, bytes_read, packet) != PacketType::Invalid) | packet_type = CheckForPacket(buffer, bytes_read, packet); | ||||
return PacketResult::Success; | if (packet_type == PacketType::Notify && !allow_notification) | ||||
m_notification_packet_queue.push_back(packet.GetStringRef().str()); | |||||
else if (packet_type != PacketType::Invalid) | |||||
return packet_type == PacketType::Standard ? PacketResult::Success | |||||
: PacketResult::Notify; | |||||
} else { | } else { | ||||
switch (status) { | switch (status) { | ||||
case eConnectionStatusTimedOut: | case eConnectionStatusTimedOut: | ||||
case eConnectionStatusInterrupted: | case eConnectionStatusInterrupted: | ||||
if (sync_on_timeout) { | if (sync_on_timeout) { | ||||
/// Sync the remote GDB server and make sure we get a response that | /// Sync the remote GDB server and make sure we get a response that | ||||
/// corresponds to what we send. | /// corresponds to what we send. | ||||
/// | /// | ||||
▲ Show 20 Lines • Show All 1,014 Lines • ▼ Show 20 Lines | case PacketResult::ErrorReplyAck: | ||||
Stream << "ErrorReplyAck"; | Stream << "ErrorReplyAck"; | ||||
break; | break; | ||||
case PacketResult::ErrorDisconnected: | case PacketResult::ErrorDisconnected: | ||||
Stream << "ErrorDisconnected"; | Stream << "ErrorDisconnected"; | ||||
break; | break; | ||||
case PacketResult::ErrorNoSequenceLock: | case PacketResult::ErrorNoSequenceLock: | ||||
Stream << "ErrorNoSequenceLock"; | Stream << "ErrorNoSequenceLock"; | ||||
break; | break; | ||||
case PacketResult::Notify: | |||||
Stream << "Notify"; | |||||
break; | |||||
} | } | ||||
} | } | ||||
std::string GDBRemoteCommunication::ExpandRLE(std::string packet) { | std::string GDBRemoteCommunication::ExpandRLE(std::string packet) { | ||||
// Reserve enough byte for the most common case (no RLE used). | // Reserve enough byte for the most common case (no RLE used). | ||||
std::string decoded; | std::string decoded; | ||||
decoded.reserve(packet.size()); | decoded.reserve(packet.size()); | ||||
for (std::string::const_iterator c = packet.begin(); c != packet.end(); ++c) { | for (std::string::const_iterator c = packet.begin(); c != packet.end(); ++c) { | ||||
Show All 21 Lines |