summaryrefslogtreecommitdiff
path: root/source/Plugins/Process/gdb-remote
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/Process/gdb-remote')
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp59
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h5
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp203
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h9
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp322
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h21
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp2
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h4
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp85
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp116
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp55
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp140
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp784
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.h17
-rw-r--r--source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp46
15 files changed, 1051 insertions, 817 deletions
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
index 4d4a4f8c5c7a8..4e20b56fb111b 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
@@ -109,16 +109,14 @@ StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse(
const bool should_stop = ShouldStop(signals, response);
response.SetFilePos(0);
- // The packet we should resume with. In the future
- // we should check our thread list and "do the right thing"
- // for new threads that show up while we stop and run async
- // packets. Setting the packet to 'c' to continue all threads
- // is the right thing to do 99.99% of the time because if a
- // thread was single stepping, and we sent an interrupt, we
- // will notice above that we didn't stop due to an interrupt
- // but stopped due to stepping and we would _not_ continue.
- // This packet may get modified by the async actions (e.g. to send a
- // signal).
+ // The packet we should resume with. In the future we should check our
+ // thread list and "do the right thing" for new threads that show up
+ // while we stop and run async packets. Setting the packet to 'c' to
+ // continue all threads is the right thing to do 99.99% of the time
+ // because if a thread was single stepping, and we sent an interrupt, we
+ // will notice above that we didn't stop due to an interrupt but stopped
+ // due to stepping and we would _not_ continue. This packet may get
+ // modified by the async actions (e.g. to send a signal).
m_continue_packet = 'c';
cont_lock.unlock();
@@ -177,6 +175,30 @@ GDBRemoteClientBase::SendPacketAndWaitForResponse(
}
GDBRemoteCommunication::PacketResult
+GDBRemoteClientBase::SendPacketAndReceiveResponseWithOutputSupport(
+ llvm::StringRef payload, StringExtractorGDBRemote &response,
+ bool send_async,
+ llvm::function_ref<void(llvm::StringRef)> output_callback) {
+ Lock lock(*this, send_async);
+ if (!lock) {
+ if (Log *log =
+ ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS))
+ log->Printf("GDBRemoteClientBase::%s failed to get mutex, not sending "
+ "packet '%.*s' (send_async=%d)",
+ __FUNCTION__, int(payload.size()), payload.data(),
+ send_async);
+ return PacketResult::ErrorSendFailed;
+ }
+
+ PacketResult packet_result = SendPacketNoLock(payload);
+ if (packet_result != PacketResult::Success)
+ return packet_result;
+
+ return ReadPacketWithOutputSupport(response, GetPacketTimeout(), true,
+ output_callback);
+}
+
+GDBRemoteCommunication::PacketResult
GDBRemoteClientBase::SendPacketAndWaitForResponseNoLock(
llvm::StringRef payload, StringExtractorGDBRemote &response) {
PacketResult packet_result = SendPacketNoLock(payload);
@@ -239,19 +261,16 @@ bool GDBRemoteClientBase::ShouldStop(const UnixSignals &signals,
if (m_async_count == 0)
return true; // We were not interrupted. The process stopped on its own.
- // Older debugserver stubs (before April 2016) can return two
- // stop-reply packets in response to a ^C packet.
- // Additionally, all debugservers still return two stop replies if
- // the inferior stops due to some other reason before the remote
- // stub manages to interrupt it. We need to wait for this
- // additional packet to make sure the packet sequence does not get
- // skewed.
+ // Older debugserver stubs (before April 2016) can return two stop-reply
+ // packets in response to a ^C packet. Additionally, all debugservers still
+ // return two stop replies if the inferior stops due to some other reason
+ // before the remote stub manages to interrupt it. We need to wait for this
+ // additional packet to make sure the packet sequence does not get skewed.
StringExtractorGDBRemote extra_stop_reply_packet;
ReadPacket(extra_stop_reply_packet, milliseconds(100), false);
- // Interrupting is typically done using SIGSTOP or SIGINT, so if
- // the process stops with some other signal, we definitely want to
- // stop.
+ // Interrupting is typically done using SIGSTOP or SIGINT, so if the process
+ // stops with some other signal, we definitely want to stop.
const uint8_t signo = response.GetHexU8(UINT8_MAX);
if (signo != signals.GetSignalNumberFromName("SIGSTOP") &&
signo != signals.GetSignalNumberFromName("SIGINT"))
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
index 2646405c9b916..3d84ce0ebe188 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
@@ -48,6 +48,11 @@ public:
StringExtractorGDBRemote &response,
bool send_async);
+ PacketResult SendPacketAndReceiveResponseWithOutputSupport(
+ llvm::StringRef payload, StringExtractorGDBRemote &response,
+ bool send_async,
+ llvm::function_ref<void(llvm::StringRef)> output_callback);
+
bool SendvContPacket(llvm::StringRef payload,
StringExtractorGDBRemote &response);
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 949cf19db658a..c335b60028619 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -150,9 +150,8 @@ GDBRemoteCommunication::~GDBRemoteCommunication() {
Disconnect();
}
- // Stop the communications read thread which is used to parse all
- // incoming packets. This function will block until the read
- // thread returns.
+ // Stop the communications read thread which is used to parse all incoming
+ // packets. This function will block until the read thread returns.
if (m_read_thread_enabled)
StopReadThread();
}
@@ -217,12 +216,10 @@ GDBRemoteCommunication::SendPacketNoLock(llvm::StringRef payload) {
}
}
- // If logging was just enabled and we have history, then dump out what
- // we have to the log so we get the historical context. The Dump() call
- // that
+ // If logging was just enabled and we have history, then dump out what we
+ // have to the log so we get the historical context. The Dump() call that
// logs all of the packet will set a boolean so that we don't dump this
- // more
- // than once
+ // more than once
if (!m_history.DidDumpToLog())
m_history.Dump(log);
@@ -275,6 +272,23 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunication::GetAck() {
}
GDBRemoteCommunication::PacketResult
+GDBRemoteCommunication::ReadPacketWithOutputSupport(
+ StringExtractorGDBRemote &response, Timeout<std::micro> timeout,
+ bool sync_on_timeout,
+ llvm::function_ref<void(llvm::StringRef)> output_callback) {
+ auto result = ReadPacket(response, timeout, sync_on_timeout);
+ while (result == PacketResult::Success && response.IsNormalResponse() &&
+ response.PeekChar() == 'O') {
+ response.GetChar();
+ std::string output;
+ if (response.GetHexByteString(output))
+ output_callback(output);
+ result = ReadPacket(response, timeout, sync_on_timeout);
+ }
+ return result;
+}
+
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunication::ReadPacket(StringExtractorGDBRemote &response,
Timeout<std::micro> timeout,
bool sync_on_timeout) {
@@ -286,8 +300,8 @@ GDBRemoteCommunication::ReadPacket(StringExtractorGDBRemote &response,
// This function is called when a packet is requested.
// A whole packet is popped from the packet queue and returned to the caller.
-// Packets are placed into this queue from the communication read thread.
-// See GDBRemoteCommunication::AppendBytesToCache.
+// Packets are placed into this queue from the communication read thread. See
+// GDBRemoteCommunication::AppendBytesToCache.
GDBRemoteCommunication::PacketResult
GDBRemoteCommunication::PopPacketFromQueue(StringExtractorGDBRemote &response,
Timeout<std::micro> timeout) {
@@ -407,11 +421,9 @@ GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet,
break;
} else if (successful_responses == 1) {
// We got something else back as the first successful
- // response, it probably is
- // the response to the packet we actually wanted, so copy it
- // over if this
- // is the first success and continue to try to get the qEcho
- // response
+ // response, it probably is the response to the packet we
+ // actually wanted, so copy it over if this is the first
+ // success and continue to try to get the qEcho response
packet = echo_response;
got_actual_response = true;
}
@@ -424,14 +436,13 @@ GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet,
}
// We weren't able to sync back up with the server, we must abort
- // otherwise
- // all responses might not be from the right packets...
+ // otherwise all responses might not be from the right packets...
if (sync_success) {
// We timed out, but were able to recover
if (got_actual_response) {
// We initially timed out, but we did get a response that came in
- // before the successful
- // reply to our qEcho packet, so lets say everything is fine...
+ // before the successful reply to our qEcho packet, so lets say
+ // everything is fine...
return PacketResult::Success;
}
} else {
@@ -473,10 +484,9 @@ bool GDBRemoteCommunication::DecompressPacket() {
size_t pkt_size = m_bytes.size();
- // Smallest possible compressed packet is $N#00 - an uncompressed empty reply,
- // most commonly indicating
- // an unsupported packet. Anything less than 5 characters, it's definitely
- // not a compressed packet.
+ // Smallest possible compressed packet is $N#00 - an uncompressed empty
+ // reply, most commonly indicating an unsupported packet. Anything less than
+ // 5 characters, it's definitely not a compressed packet.
if (pkt_size < 5)
return true;
@@ -505,17 +515,15 @@ bool GDBRemoteCommunication::DecompressPacket() {
1; // The first character of the two hex checksum characters
// Normally size_of_first_packet == m_bytes.size() but m_bytes may contain
- // multiple packets.
- // size_of_first_packet is the size of the initial packet which we'll replace
- // with the decompressed
- // version of, leaving the rest of m_bytes unmodified.
+ // multiple packets. size_of_first_packet is the size of the initial packet
+ // which we'll replace with the decompressed version of, leaving the rest of
+ // m_bytes unmodified.
size_t size_of_first_packet = hash_mark_idx + 3;
// Compressed packets ("$C") start with a base10 number which is the size of
- // the uncompressed payload,
- // then a : and then the compressed data. e.g. $C1024:<binary>#00
- // Update content_start and content_length to only include the <binary> part
- // of the packet.
+ // the uncompressed payload, then a : and then the compressed data. e.g.
+ // $C1024:<binary>#00 Update content_start and content_length to only include
+ // the <binary> part of the packet.
uint64_t decompressed_bufsize = ULONG_MAX;
if (m_bytes[1] == 'C') {
@@ -564,15 +572,14 @@ bool GDBRemoteCommunication::DecompressPacket() {
}
if (m_bytes[1] == 'N') {
- // This packet was not compressed -- delete the 'N' character at the
- // start and the packet may be processed as-is.
+ // This packet was not compressed -- delete the 'N' character at the start
+ // and the packet may be processed as-is.
m_bytes.erase(1, 1);
return true;
}
- // Reverse the gdb-remote binary escaping that was done to the compressed text
- // to
- // guard characters like '$', '#', '}', etc.
+ // Reverse the gdb-remote binary escaping that was done to the compressed
+ // text to guard characters like '$', '#', '}', etc.
std::vector<uint8_t> unescaped_content;
unescaped_content.reserve(content_length);
size_t i = content_start;
@@ -613,12 +620,10 @@ bool GDBRemoteCommunication::DecompressPacket() {
else if (m_compression_type == CompressionType::LZMA)
compression_type = COMPRESSION_LZMA;
- // If we have the expected size of the decompressed payload, we can allocate
- // the right-sized buffer and do it. If we don't have that information,
- // we'll
- // need to try decoding into a big buffer and if the buffer wasn't big
- // enough,
- // increase it and try again.
+ // If we have the expected size of the decompressed payload, we can
+ // allocate the right-sized buffer and do it. If we don't have that
+ // information, we'll need to try decoding into a big buffer and if the
+ // buffer wasn't big enough, increase it and try again.
if (decompressed_bufsize != ULONG_MAX && decompressed_buffer != nullptr) {
decompressed_bytes = compression_decode_buffer(
@@ -706,9 +711,8 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
// 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.
+ // 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;
@@ -743,7 +747,8 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
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
+ // Don't include the # in the content or the $ in the content
+ // length
content_length = hash_pos - 1;
total_length =
@@ -757,11 +762,10 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
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...
+ // 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;
@@ -802,16 +806,14 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
if (log) {
// If logging was just enabled and we have history, then dump out what
// we have to the log so we get the historical context. The Dump() call
- // that
- // logs all of the packet will set a boolean so that we don't dump this
- // more
- // than once
+ // that logs all of the packet will set a boolean so that we don't dump
+ // this more than once
if (!m_history.DidDumpToLog())
m_history.Dump(log);
bool binary = false;
- // Only detect binary for packets that start with a '$' and have a '#CC'
- // checksum
+ // Only detect binary for packets that start with a '$' and have a
+ // '#CC' checksum
if (m_bytes[0] == '$' && total_length > 4) {
for (size_t i = 0; !binary && i < total_length; ++i) {
unsigned char c = m_bytes[i];
@@ -834,8 +836,8 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
// Remove binary escaped bytes when displaying the packet...
const char ch = m_bytes[i];
if (ch == 0x7d) {
- // 0x7d is the escape character. The next character is to
- // be XOR'd with 0x20.
+ // 0x7d is the escape character. The next character is to be
+ // XOR'd with 0x20.
const char escapee = m_bytes[++i] ^ 0x20;
strm.Printf("%2.2x", escapee);
} else {
@@ -863,26 +865,25 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
// Clear packet_str in case there is some existing data in it.
packet_str.clear();
- // Copy the packet from m_bytes to packet_str expanding the
- // run-length encoding in the process.
- // Reserve enough byte for the most common case (no RLE used)
+ // Copy the packet from m_bytes to packet_str expanding the run-length
+ // encoding in the process. Reserve enough byte for the most common case
+ // (no RLE used)
packet_str.reserve(m_bytes.length());
for (std::string::const_iterator c = m_bytes.begin() + content_start;
c != m_bytes.begin() + content_end; ++c) {
if (*c == '*') {
- // '*' indicates RLE. Next character will give us the
- // repeat count and previous character is what is to be
- // repeated.
+ // '*' indicates RLE. Next character will give us the repeat count
+ // and previous character is what is to be repeated.
char char_to_repeat = packet_str.back();
// Number of time the previous character is repeated
int repeat_count = *++c + 3 - ' ';
- // We have the char_to_repeat and repeat_count. Now push
- // it in the packet.
+ // We have the char_to_repeat and repeat_count. Now push it in the
+ // packet.
for (int i = 0; i < repeat_count; ++i)
packet_str.push_back(char_to_repeat);
} else if (*c == 0x7d) {
- // 0x7d is the escape character. The next character is to
- // be XOR'd with 0x20.
+ // 0x7d is the escape character. The next character is to be XOR'd
+ // with 0x20.
char escapee = *++c ^ 0x20;
packet_str.push_back(escapee);
} else {
@@ -897,7 +898,8 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
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);
+ char actual_checksum = CalculcateChecksum(
+ llvm::StringRef(m_bytes).slice(content_start, content_end));
success = packet_checksum == actual_checksum;
if (!success) {
if (log)
@@ -991,11 +993,12 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
char debugserver_path[PATH_MAX];
FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
- // Always check to see if we have an environment override for the path
- // to the debugserver to use and use it if we do.
+ // Always check to see if we have an environment override for the path to the
+ // debugserver to use and use it if we do.
const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
if (env_debugserver_path) {
- debugserver_file_spec.SetFile(env_debugserver_path, false);
+ debugserver_file_spec.SetFile(env_debugserver_path, false,
+ FileSpec::Style::native);
if (log)
log->Printf("GDBRemoteCommunication::%s() gdb-remote stub exe path set "
"from environment variable: %s",
@@ -1004,10 +1007,9 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
debugserver_file_spec = g_debugserver_file_spec;
bool debugserver_exists = debugserver_file_spec.Exists();
if (!debugserver_exists) {
- // The debugserver binary is in the LLDB.framework/Resources
- // directory.
- if (HostInfo::GetLLDBPath(ePathTypeSupportExecutableDir,
- debugserver_file_spec)) {
+ // The debugserver binary is in the LLDB.framework/Resources directory.
+ debugserver_file_spec = HostInfo::GetSupportExeDir();
+ if (debugserver_file_spec) {
debugserver_file_spec.AppendPathComponent(DEBUGSERVER_BASENAME);
debugserver_exists = debugserver_file_spec.Exists();
if (debugserver_exists) {
@@ -1031,8 +1033,7 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
__FUNCTION__, debugserver_file_spec.GetPath().c_str());
}
// Don't cache the platform specific GDB server binary as it could
- // change
- // from platform to platform
+ // change from platform to platform
g_debugserver_file_spec.Clear();
}
}
@@ -1080,14 +1081,14 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
// once data is written to the pipe, debug server is up and running.
Pipe socket_pipe;
- // port is null when debug server should listen on domain socket -
- // we're not interested in port value but rather waiting for debug server
- // to become available.
+ // port is null when debug server should listen on domain socket - we're
+ // not interested in port value but rather waiting for debug server to
+ // become available.
if (pass_comm_fd == -1) {
if (url) {
-// Create a temporary file to get the stdout/stderr and redirect the
-// output of the command into this file. We will later read this file
-// if all goes well and fill the data into "command_output_ptr"
+// Create a temporary file to get the stdout/stderr and redirect the output of
+// the command into this file. We will later read this file if all goes well
+// and fill the data into "command_output_ptr"
#if defined(__APPLE__)
// Binding to port zero, we need to figure out what port it ends up
// using using a named pipe...
@@ -1120,8 +1121,7 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
#endif
} else {
// No host and port given, so lets listen on our end and make the
- // debugserver
- // connect to us..
+ // debugserver connect to us..
error = StartListenThread("127.0.0.1", 0);
if (error.Fail()) {
if (log)
@@ -1134,7 +1134,7 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
ConnectionFileDescriptor *connection =
(ConnectionFileDescriptor *)GetConnection();
// Wait for 10 seconds to resolve the bound port
- uint16_t port_ = connection->GetListeningPort(10);
+ uint16_t port_ = connection->GetListeningPort(std::chrono::seconds(10));
if (port_ > 0) {
char port_cstr[32];
snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", port_);
@@ -1206,11 +1206,7 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
}
// Copy the current environment to the gdbserver/debugserver instance
- StringList env;
- if (Host::GetEnvironment(env)) {
- for (size_t i = 0; i < env.GetSize(); ++i)
- launch_info.GetEnvironmentEntries().AppendArgument(env[i]);
- }
+ launch_info.GetEnvironment() = Host::GetEnvironment();
// Close STDIN, STDOUT and STDERR.
launch_info.AppendCloseFileAction(STDIN_FILENO);
@@ -1327,14 +1323,11 @@ GDBRemoteCommunication::ScopedTimeout::~ScopedTimeout() {
}
// This function is called via the Communications class read thread when bytes
-// become available
-// for this connection. This function will consume all incoming bytes and try to
-// parse whole
-// packets as they become available. Full packets are placed in a queue, so that
-// all packet
-// requests can simply pop from this queue. Async notification packets will be
-// dispatched
-// immediately to the ProcessGDBRemote Async thread via an event.
+// become available for this connection. This function will consume all
+// incoming bytes and try to parse whole packets as they become available. Full
+// packets are placed in a queue, so that all packet requests can simply pop
+// from this queue. Async notification packets will be dispatched immediately
+// to the ProcessGDBRemote Async thread via an event.
void GDBRemoteCommunication::AppendBytesToCache(const uint8_t *bytes,
size_t len, bool broadcast,
lldb::ConnectionStatus status) {
@@ -1343,8 +1336,8 @@ void GDBRemoteCommunication::AppendBytesToCache(const uint8_t *bytes,
while (true) {
PacketType type = CheckForPacket(bytes, len, packet);
- // scrub the data so we do not pass it back to CheckForPacket
- // on future passes of the loop
+ // scrub the data so we do not pass it back to CheckForPacket on future
+ // passes of the loop
bytes = nullptr;
len = 0;
@@ -1368,8 +1361,8 @@ void GDBRemoteCommunication::AppendBytesToCache(const uint8_t *bytes,
// put this packet into an event
const char *pdata = packet.GetStringRef().c_str();
- // as the communication class, we are a broadcaster and the
- // async thread is tuned to listen to us
+ // as the communication class, we are a broadcaster and the async thread
+ // is tuned to listen to us
BroadcastEvent(eBroadcastBitGdbReadThreadGotNotify,
new EventDataBytes(pdata));
}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index ecc9386e49c7d..67796e4c61ef2 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -24,10 +24,10 @@
#include "lldb/Core/Listener.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Host/Predicate.h"
-#include "lldb/Interpreter/Args.h"
+#include "lldb/Utility/Args.h"
#include "lldb/lldb-public.h"
-#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
namespace lldb_private {
namespace process_gdb_remote {
@@ -232,6 +232,11 @@ protected:
PacketResult ReadPacket(StringExtractorGDBRemote &response,
Timeout<std::micro> timeout, bool sync_on_timeout);
+ PacketResult ReadPacketWithOutputSupport(
+ StringExtractorGDBRemote &response, Timeout<std::micro> timeout,
+ bool sync_on_timeout,
+ llvm::function_ref<void(llvm::StringRef)> output_callback);
+
// Pop a packet from the queue in a thread safe manner
PacketResult PopPacketFromQueue(StringExtractorGDBRemote &response,
Timeout<std::micro> timeout);
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 867f57c475cec..c8b59d5d236b9 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -21,11 +21,12 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/State.h"
#include "lldb/Host/HostInfo.h"
-#include "lldb/Interpreter/Args.h"
+#include "lldb/Host/XML.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/UnixSignals.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/JSON.h"
#include "lldb/Utility/LLDBAssert.h"
@@ -35,8 +36,8 @@
// Project includes
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
-#include "Utility/StringExtractorGDBRemote.h"
#include "lldb/Host/Config.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
#include "llvm/ADT/StringSwitch.h"
@@ -81,6 +82,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient()
m_supports_qXfer_libraries_read(eLazyBoolCalculate),
m_supports_qXfer_libraries_svr4_read(eLazyBoolCalculate),
m_supports_qXfer_features_read(eLazyBoolCalculate),
+ m_supports_qXfer_memory_map_read(eLazyBoolCalculate),
m_supports_augmented_libraries_svr4_read(eLazyBoolCalculate),
m_supports_jThreadExtendedInfo(eLazyBoolCalculate),
m_supports_jLoadedDynamicLibrariesInfos(eLazyBoolCalculate),
@@ -98,12 +100,12 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient()
m_curr_pid(LLDB_INVALID_PROCESS_ID), m_curr_tid(LLDB_INVALID_THREAD_ID),
m_curr_tid_run(LLDB_INVALID_THREAD_ID),
m_num_supported_hardware_watchpoints(0), m_host_arch(), m_process_arch(),
- m_os_version_major(UINT32_MAX), m_os_version_minor(UINT32_MAX),
- m_os_version_update(UINT32_MAX), m_os_build(), m_os_kernel(),
- m_hostname(), m_gdb_server_name(), m_gdb_server_version(UINT32_MAX),
- m_default_packet_timeout(0), m_max_packet_size(0),
- m_qSupported_response(), m_supported_async_json_packets_is_valid(false),
- m_supported_async_json_packets_sp() {}
+ m_os_build(), m_os_kernel(), m_hostname(), m_gdb_server_name(),
+ m_gdb_server_version(UINT32_MAX), m_default_packet_timeout(0),
+ m_max_packet_size(0), m_qSupported_response(),
+ m_supported_async_json_packets_is_valid(false),
+ m_supported_async_json_packets_sp(), m_qXfer_memory_map(),
+ m_qXfer_memory_map_loaded(false) {}
//----------------------------------------------------------------------
// Destructor
@@ -116,8 +118,8 @@ GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient() {
bool GDBRemoteCommunicationClient::HandshakeWithServer(Status *error_ptr) {
ResetDiscoverableSettings(false);
- // 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...
+ // 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()) {
// Wait for any responses that might have been queued up in the remote
// GDB server and flush them all
@@ -127,9 +129,9 @@ bool GDBRemoteCommunicationClient::HandshakeWithServer(Status *error_ptr) {
packet_result = ReadPacket(response, milliseconds(10), false);
// The return value from QueryNoAckModeSupported() is true if the packet
- // was sent and _any_ response (including UNIMPLEMENTED) was received),
- // or false if no response was received. This quickly tells us if we have
- // a live connection to a remote GDB server...
+ // was sent and _any_ response (including UNIMPLEMENTED) was received), or
+ // false if no response was received. This quickly tells us if we have a
+ // live connection to a remote GDB server...
if (QueryNoAckModeSupported()) {
return true;
} else {
@@ -192,6 +194,13 @@ bool GDBRemoteCommunicationClient::GetQXferFeaturesReadSupported() {
return m_supports_qXfer_features_read == eLazyBoolYes;
}
+bool GDBRemoteCommunicationClient::GetQXferMemoryMapReadSupported() {
+ if (m_supports_qXfer_memory_map_read == eLazyBoolCalculate) {
+ GetRemoteQSupported();
+ }
+ return m_supports_qXfer_memory_map_read == eLazyBoolYes;
+}
+
uint64_t GDBRemoteCommunicationClient::GetRemoteMaxPacketSize() {
if (m_max_packet_size == 0) {
GetRemoteQSupported();
@@ -205,9 +214,8 @@ bool GDBRemoteCommunicationClient::QueryNoAckModeSupported() {
m_supports_not_sending_acks = eLazyBoolNo;
// This is the first real packet that we'll send in a debug session and it
- // may take a little
- // longer than normal to receive a reply. Wait at least 6 seconds for a
- // reply to this packet.
+ // may take a little longer than normal to receive a reply. Wait at least
+ // 6 seconds for a reply to this packet.
ScopedTimeout timeout(*this, std::max(GetPacketTimeout(), seconds(6)));
@@ -296,6 +304,7 @@ void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) {
m_supports_qXfer_libraries_read = eLazyBoolCalculate;
m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate;
m_supports_qXfer_features_read = eLazyBoolCalculate;
+ m_supports_qXfer_memory_map_read = eLazyBoolCalculate;
m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate;
m_supports_qProcessInfoPID = true;
m_supports_qfProcessInfo = true;
@@ -313,9 +322,7 @@ void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) {
m_qSymbol_requests_done = false;
m_supports_qModuleInfo = true;
m_host_arch.Clear();
- m_os_version_major = UINT32_MAX;
- m_os_version_minor = UINT32_MAX;
- m_os_version_update = UINT32_MAX;
+ m_os_version = llvm::VersionTuple();
m_os_build.clear();
m_os_kernel.clear();
m_hostname.clear();
@@ -329,8 +336,8 @@ void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) {
m_supports_jModulesInfo = true;
}
- // These flags should be reset when we first connect to a GDB server
- // and when our inferior process execs
+ // These flags should be reset when we first connect to a GDB server and when
+ // our inferior process execs
m_qProcessInfo_is_valid = eLazyBoolCalculate;
m_process_arch.Clear();
}
@@ -342,6 +349,7 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() {
m_supports_qXfer_libraries_svr4_read = eLazyBoolNo;
m_supports_augmented_libraries_svr4_read = eLazyBoolNo;
m_supports_qXfer_features_read = eLazyBoolNo;
+ m_supports_qXfer_memory_map_read = eLazyBoolNo;
m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if
// not, we assume no limit
@@ -361,8 +369,7 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() {
const char *response_cstr = response.GetStringRef().c_str();
// Hang on to the qSupported packet, so that platforms can do custom
- // configuration of the transport before attaching/launching the
- // process.
+ // configuration of the transport before attaching/launching the process.
m_qSupported_response = response_cstr;
if (::strstr(response_cstr, "qXfer:auxv:read+"))
@@ -377,9 +384,12 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() {
m_supports_qXfer_libraries_read = eLazyBoolYes;
if (::strstr(response_cstr, "qXfer:features:read+"))
m_supports_qXfer_features_read = eLazyBoolYes;
+ if (::strstr(response_cstr, "qXfer:memory-map:read+"))
+ m_supports_qXfer_memory_map_read = eLazyBoolYes;
// Look for a list of compressions in the features list e.g.
- // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib-deflate,lzma
+ // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib-
+ // deflate,lzma
const char *features_list = ::strstr(response_cstr, "qXfer:features:");
if (features_list) {
const char *compressions =
@@ -543,9 +553,8 @@ GDBRemoteCommunicationClient::SendThreadSpecificPacketAndWaitForResponse(
return SendPacketAndWaitForResponseNoLock(payload.GetString(), response);
}
-// Check if the target supports 'p' packet. It sends out a 'p'
-// packet and checks the response. A normal packet will tell us
-// that support is available.
+// Check if the target supports 'p' packet. It sends out a 'p' packet and
+// checks the response. A normal packet will tell us that support is available.
//
// Takes a valid thread ID because p needs to apply to a thread.
bool GDBRemoteCommunicationClient::GetpPacketSupported(lldb::tid_t tid) {
@@ -600,8 +609,8 @@ bool GDBRemoteCommunicationClient::GetThreadExtendedInfoSupported() {
void GDBRemoteCommunicationClient::EnableErrorStringInPacket() {
if (m_supports_error_string_reply == eLazyBoolCalculate) {
StringExtractorGDBRemote response;
- // We try to enable error strings in remote packets
- // but if we fail, we just work in the older way.
+ // We try to enable error strings in remote packets but if we fail, we just
+ // work in the older way.
m_supports_error_string_reply = eLazyBoolNo;
if (SendPacketAndWaitForResponse("QEnableErrorStrings", response, false) ==
PacketResult::Success) {
@@ -715,12 +724,10 @@ lldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) {
return m_curr_pid;
} else {
// If we don't get a response for qProcessInfo, check if $qC gives us a
- // result.
- // $qC only returns a real process id on older debugserver and lldb-platform
- // stubs.
- // The gdb remote protocol documents $qC as returning the thread id, which
- // newer
- // debugserver and lldb-gdbserver stubs return correctly.
+ // result. $qC only returns a real process id on older debugserver and
+ // lldb-platform stubs. The gdb remote protocol documents $qC as returning
+ // the thread id, which newer debugserver and lldb-gdbserver stubs return
+ // correctly.
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse("qC", response, false) ==
PacketResult::Success) {
@@ -775,8 +782,8 @@ bool GDBRemoteCommunicationClient::GetLaunchSuccess(std::string &error_str) {
int GDBRemoteCommunicationClient::SendArgumentsPacket(
const ProcessLaunchInfo &launch_info) {
// Since we don't get the send argv0 separate from the executable path, we
- // need to
- // make sure to use the actual executable path found in the launch_info...
+ // need to make sure to use the actual executable path found in the
+ // launch_info...
std::vector<const char *> argv;
FileSpec exe_file = launch_info.GetExecutableFile();
std::string exe_path;
@@ -822,6 +829,15 @@ int GDBRemoteCommunicationClient::SendArgumentsPacket(
return -1;
}
+int GDBRemoteCommunicationClient::SendEnvironment(const Environment &env) {
+ for (const auto &KV : env) {
+ int r = SendEnvironmentPacket(Environment::compose(KV).c_str());
+ if (r != 0)
+ return r;
+ }
+ return 0;
+}
+
int GDBRemoteCommunicationClient::SendEnvironmentPacket(
char const *name_equal_value) {
if (name_equal_value && name_equal_value[0]) {
@@ -925,18 +941,9 @@ int GDBRemoteCommunicationClient::SendLaunchEventDataPacket(
return -1;
}
-bool GDBRemoteCommunicationClient::GetOSVersion(uint32_t &major,
- uint32_t &minor,
- uint32_t &update) {
- if (GetHostInfo()) {
- if (m_os_version_major != UINT32_MAX) {
- major = m_os_version_major;
- minor = m_os_version_minor;
- update = m_os_version_update;
- return true;
- }
- }
- return false;
+llvm::VersionTuple GDBRemoteCommunicationClient::GetOSVersion() {
+ GetHostInfo();
+ return m_os_version;
}
bool GDBRemoteCommunicationClient::GetOSBuildString(std::string &s) {
@@ -1199,9 +1206,7 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) {
// "version" key instead of
// "os_version"...
{
- Args::StringToVersion(value, m_os_version_major, m_os_version_minor,
- m_os_version_update);
- if (m_os_version_major != UINT32_MAX)
+ if (!m_os_version.tryParse(value))
++num_keys_decoded;
} else if (name.equals("watchpoint_exceptions_received")) {
m_watchpoints_trigger_after_instruction =
@@ -1451,7 +1456,8 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo(
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse(packet, response, false) ==
- PacketResult::Success) {
+ PacketResult::Success &&
+ response.GetResponseType() == StringExtractorGDBRemote::eResponse) {
llvm::StringRef name;
llvm::StringRef value;
addr_t addr_value = LLDB_INVALID_ADDRESS;
@@ -1527,8 +1533,134 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo(
if (m_supports_memory_region_info == eLazyBoolNo) {
error.SetErrorString("qMemoryRegionInfo is not supported");
}
- if (error.Fail())
- region_info.Clear();
+
+ // Try qXfer:memory-map:read to get region information not included in
+ // qMemoryRegionInfo
+ MemoryRegionInfo qXfer_region_info;
+ Status qXfer_error = GetQXferMemoryMapRegionInfo(addr, qXfer_region_info);
+
+ if (error.Fail()) {
+ // If qMemoryRegionInfo failed, but qXfer:memory-map:read succeeded, use
+ // the qXfer result as a fallback
+ if (qXfer_error.Success()) {
+ region_info = qXfer_region_info;
+ error.Clear();
+ } else {
+ region_info.Clear();
+ }
+ } else if (qXfer_error.Success()) {
+ // If both qMemoryRegionInfo and qXfer:memory-map:read succeeded, and if
+ // both regions are the same range, update the result to include the flash-
+ // memory information that is specific to the qXfer result.
+ if (region_info.GetRange() == qXfer_region_info.GetRange()) {
+ region_info.SetFlash(qXfer_region_info.GetFlash());
+ region_info.SetBlocksize(qXfer_region_info.GetBlocksize());
+ }
+ }
+ return error;
+}
+
+Status GDBRemoteCommunicationClient::GetQXferMemoryMapRegionInfo(
+ lldb::addr_t addr, MemoryRegionInfo &region) {
+ Status error = LoadQXferMemoryMap();
+ if (!error.Success())
+ return error;
+ for (const auto &map_region : m_qXfer_memory_map) {
+ if (map_region.GetRange().Contains(addr)) {
+ region = map_region;
+ return error;
+ }
+ }
+ error.SetErrorString("Region not found");
+ return error;
+}
+
+Status GDBRemoteCommunicationClient::LoadQXferMemoryMap() {
+
+ Status error;
+
+ if (m_qXfer_memory_map_loaded)
+ // Already loaded, return success
+ return error;
+
+ if (!XMLDocument::XMLEnabled()) {
+ error.SetErrorString("XML is not supported");
+ return error;
+ }
+
+ if (!GetQXferMemoryMapReadSupported()) {
+ error.SetErrorString("Memory map is not supported");
+ return error;
+ }
+
+ std::string xml;
+ lldb_private::Status lldberr;
+ if (!ReadExtFeature(ConstString("memory-map"), ConstString(""), xml,
+ lldberr)) {
+ error.SetErrorString("Failed to read memory map");
+ return error;
+ }
+
+ XMLDocument xml_document;
+
+ if (!xml_document.ParseMemory(xml.c_str(), xml.size())) {
+ error.SetErrorString("Failed to parse memory map xml");
+ return error;
+ }
+
+ XMLNode map_node = xml_document.GetRootElement("memory-map");
+ if (!map_node) {
+ error.SetErrorString("Invalid root node in memory map xml");
+ return error;
+ }
+
+ m_qXfer_memory_map.clear();
+
+ map_node.ForEachChildElement([this](const XMLNode &memory_node) -> bool {
+ if (!memory_node.IsElement())
+ return true;
+ if (memory_node.GetName() != "memory")
+ return true;
+ auto type = memory_node.GetAttributeValue("type", "");
+ uint64_t start;
+ uint64_t length;
+ if (!memory_node.GetAttributeValueAsUnsigned("start", start))
+ return true;
+ if (!memory_node.GetAttributeValueAsUnsigned("length", length))
+ return true;
+ MemoryRegionInfo region;
+ region.GetRange().SetRangeBase(start);
+ region.GetRange().SetByteSize(length);
+ if (type == "rom") {
+ region.SetReadable(MemoryRegionInfo::eYes);
+ this->m_qXfer_memory_map.push_back(region);
+ } else if (type == "ram") {
+ region.SetReadable(MemoryRegionInfo::eYes);
+ region.SetWritable(MemoryRegionInfo::eYes);
+ this->m_qXfer_memory_map.push_back(region);
+ } else if (type == "flash") {
+ region.SetFlash(MemoryRegionInfo::eYes);
+ memory_node.ForEachChildElement(
+ [&region](const XMLNode &prop_node) -> bool {
+ if (!prop_node.IsElement())
+ return true;
+ if (prop_node.GetName() != "property")
+ return true;
+ auto propname = prop_node.GetAttributeValue("name", "");
+ if (propname == "blocksize") {
+ uint64_t blocksize;
+ if (prop_node.GetElementTextAsUnsigned(blocksize))
+ region.SetBlocksize(blocksize);
+ }
+ return true;
+ });
+ this->m_qXfer_memory_map.push_back(region);
+ }
+ return true;
+ });
+
+ m_qXfer_memory_map_loaded = true;
+
return error;
}
@@ -1585,13 +1717,13 @@ GDBRemoteCommunicationClient::GetWatchpointsTriggerAfterInstruction(
Status error;
llvm::Triple::ArchType atype = arch.GetMachine();
- // we assume watchpoints will happen after running the relevant opcode
- // and we only want to override this behavior if we have explicitly
- // received a qHostInfo telling us otherwise
+ // we assume watchpoints will happen after running the relevant opcode and we
+ // only want to override this behavior if we have explicitly received a
+ // qHostInfo telling us otherwise
if (m_qHostInfo_is_valid != eLazyBoolYes) {
// On targets like MIPS and ppc64le, watchpoint exceptions are always
- // generated before the instruction is executed. The connected target
- // may not support qHostInfo or qWatchpointSupportInfo packets.
+ // generated before the instruction is executed. The connected target may
+ // not support qHostInfo or qWatchpointSupportInfo packets.
if (atype == llvm::Triple::mips || atype == llvm::Triple::mipsel ||
atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el ||
atype == llvm::Triple::ppc64le)
@@ -1789,11 +1921,12 @@ bool GDBRemoteCommunicationClient::DecodeProcessInfoResponse(
process_info.GetArchitecture().SetTriple(triple.c_str());
} else if (name.equals("name")) {
StringExtractor extractor(value);
- // The process name from ASCII hex bytes since we can't
- // control the characters in a process name
+ // The process name from ASCII hex bytes since we can't control the
+ // characters in a process name
std::string name;
extractor.GetHexByteString(name);
- process_info.GetExecutableFile().SetFile(name, false);
+ process_info.GetExecutableFile().SetFile(name, false,
+ FileSpec::Style::native);
} else if (name.equals("cputype")) {
value.getAsInteger(0, cpu);
} else if (name.equals("cpusubtype")) {
@@ -2046,8 +2179,8 @@ uint32_t GDBRemoteCommunicationClient::FindProcesses(
}
}
StringExtractorGDBRemote response;
- // Increase timeout as the first qfProcessInfo packet takes a long time
- // on Android. The value of 1min was arrived at empirically.
+ // Increase timeout as the first qfProcessInfo packet takes a long time on
+ // Android. The value of 1min was arrived at empirically.
ScopedTimeout timeout(*this, minutes(1));
if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
PacketResult::Success) {
@@ -2081,8 +2214,8 @@ bool GDBRemoteCommunicationClient::GetUserName(uint32_t uid,
PacketResult::Success) {
if (response.IsNormalResponse()) {
// Make sure we parsed the right number of characters. The response is
- // the hex encoded user name and should make up the entire packet.
- // If there are any non-hex ASCII bytes, the length won't match below..
+ // the hex encoded user name and should make up the entire packet. If
+ // there are any non-hex ASCII bytes, the length won't match below..
if (response.GetHexByteString(name) * 2 ==
response.GetStringRef().size())
return true;
@@ -2108,8 +2241,8 @@ bool GDBRemoteCommunicationClient::GetGroupName(uint32_t gid,
PacketResult::Success) {
if (response.IsNormalResponse()) {
// Make sure we parsed the right number of characters. The response is
- // the hex encoded group name and should make up the entire packet.
- // If there are any non-hex ASCII bytes, the length won't match below..
+ // the hex encoded group name and should make up the entire packet. If
+ // there are any non-hex ASCII bytes, the length won't match below..
if (response.GetHexByteString(name) * 2 ==
response.GetStringRef().size())
return true;
@@ -2335,8 +2468,8 @@ bool GDBRemoteCommunicationClient::LaunchGDBServer(
// 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
+ // Make the GDB server we launch accept connections from any host since
+ // we can't figure out the hostname
stream.Printf("host:*;");
}
}
@@ -2650,13 +2783,16 @@ lldb_private::Status GDBRemoteCommunicationClient::RunShellCommand(
// 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
-{
+ const Timeout<std::micro> &timeout) {
lldb_private::StreamString stream;
stream.PutCString("qPlatform_shell:");
stream.PutBytesAsRawHex8(command, strlen(command));
stream.PutChar(',');
+ uint32_t timeout_sec = UINT32_MAX;
+ if (timeout) {
+ // TODO: Use chrono version of std::ceil once c++17 is available.
+ timeout_sec = std::ceil(std::chrono::duration<double>(*timeout).count());
+ }
stream.PutHex32(timeout_sec);
if (working_dir) {
std::string path{working_dir.GetPath(false)};
@@ -3125,9 +3261,8 @@ bool GDBRemoteCommunicationClient::SaveRegisterState(lldb::tid_t tid,
bool GDBRemoteCommunicationClient::RestoreRegisterState(lldb::tid_t tid,
uint32_t save_id) {
// We use the "m_supports_QSaveRegisterState" variable here because the
- // QSaveRegisterState and QRestoreRegisterState packets must both be supported
- // in
- // order to be useful
+ // QSaveRegisterState and QRestoreRegisterState packets must both be
+ // supported in order to be useful
if (m_supports_QSaveRegisterState == eLazyBoolNo)
return false;
@@ -3406,7 +3541,7 @@ bool GDBRemoteCommunicationClient::GetModuleInfo(
StringExtractor extractor(value);
std::string uuid;
extractor.GetHexByteString(uuid);
- module_spec.GetUUID().SetFromCString(uuid.c_str(), uuid.size() / 2);
+ module_spec.GetUUID().SetFromStringRef(uuid, uuid.size() / 2);
} else if (name == "triple") {
StringExtractor extractor(value);
std::string triple;
@@ -3523,8 +3658,8 @@ GDBRemoteCommunicationClient::GetModulesInfo(
// query the target remote for extended information using the qXfer packet
//
-// example: object='features', annex='target.xml', out=<xml output>
-// return: 'true' on success
+// example: object='features', annex='target.xml', out=<xml output> return:
+// 'true' on success
// 'false' on failure (err set)
bool GDBRemoteCommunicationClient::ReadExtFeature(
const lldb_private::ConstString object,
@@ -3631,10 +3766,9 @@ bool GDBRemoteCommunicationClient::ReadExtFeature(
void GDBRemoteCommunicationClient::ServeSymbolLookups(
lldb_private::Process *process) {
- // Set to true once we've resolved a symbol to an address for the remote stub.
- // If we get an 'OK' response after this, the remote stub doesn't need any
- // more
- // symbols and we can stop asking.
+ // Set to true once we've resolved a symbol to an address for the remote
+ // stub. If we get an 'OK' response after this, the remote stub doesn't need
+ // any more symbols and we can stop asking.
bool symbol_response_provided = false;
// Is this the initial qSymbol:: packet?
@@ -3659,8 +3793,8 @@ void GDBRemoteCommunicationClient::ServeSymbolLookups(
first_qsymbol_query = false;
if (response.IsUnsupportedResponse()) {
- // qSymbol is not supported by the current GDB server we are connected
- // to
+ // qSymbol is not supported by the current GDB server we are
+ // connected to
m_supports_qSymbol = false;
return;
} else {
@@ -3725,10 +3859,8 @@ void GDBRemoteCommunicationClient::ServeSymbolLookups(
}
}
// This is the normal path where our symbol lookup was successful
- // and we want
- // to send a packet with the new symbol value and see if another
- // lookup needs to be
- // done.
+ // and we want to send a packet with the new symbol value and see
+ // if another lookup needs to be done.
// Change "packet" to contain the requested symbol value and name
packet.Clear();
@@ -3763,8 +3895,7 @@ void GDBRemoteCommunicationClient::ServeSymbolLookups(
StructuredData::Array *
GDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() {
if (!m_supported_async_json_packets_is_valid) {
- // Query the server for the array of supported asynchronous JSON
- // packets.
+ // Query the server for the array of supported asynchronous JSON packets.
m_supported_async_json_packets_is_valid = true;
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
@@ -3778,8 +3909,8 @@ GDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() {
StructuredData::ParseJSON(response.GetStringRef());
if (m_supported_async_json_packets_sp &&
!m_supported_async_json_packets_sp->GetAsArray()) {
- // We were returned something other than a JSON array. This
- // is invalid. Clear it out.
+ // We were returned something other than a JSON array. This is
+ // invalid. Clear it out.
if (log)
log->Printf("GDBRemoteCommunicationClient::%s(): "
"QSupportedAsyncJSONPackets returned invalid "
@@ -3837,8 +3968,7 @@ Status GDBRemoteCommunicationClient::ConfigureRemoteStructuredData(
return error;
}
- // Build command: Configure{type_name}: serialized config
- // data.
+ // Build command: Configure{type_name}: serialized config data.
StreamGDBRemote stream;
stream.PutCString("QConfigure");
stream.PutCString(type_name.AsCString());
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index ba67b82463987..cf1d249768d7a 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -121,6 +121,7 @@ public:
/// response was received.
//------------------------------------------------------------------
int SendEnvironmentPacket(char const *name_equal_value);
+ int SendEnvironment(const Environment &env);
int SendLaunchArchPacket(const char *arch);
@@ -265,7 +266,7 @@ public:
bool GetDefaultThreadId(lldb::tid_t &tid);
- bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update);
+ llvm::VersionTuple GetOSVersion();
bool GetOSBuildString(std::string &s);
@@ -354,6 +355,8 @@ public:
bool GetQXferFeaturesReadSupported();
+ bool GetQXferMemoryMapReadSupported();
+
LazyBool SupportsAllocDeallocMemory() // const
{
// Uncomment this to have lldb pretend the debug server doesn't respond to
@@ -401,8 +404,7 @@ public:
// the process to exit
std::string
*command_output, // Pass nullptr if you don't want the command output
- uint32_t timeout_sec); // Timeout in seconds to wait for shell program to
- // finish
+ const Timeout<std::micro> &timeout);
bool CalculateMD5(const FileSpec &file_spec, uint64_t &high, uint64_t &low);
@@ -544,6 +546,7 @@ protected:
LazyBool m_supports_qXfer_libraries_read;
LazyBool m_supports_qXfer_libraries_svr4_read;
LazyBool m_supports_qXfer_features_read;
+ LazyBool m_supports_qXfer_memory_map_read;
LazyBool m_supports_augmented_libraries_svr4_read;
LazyBool m_supports_jThreadExtendedInfo;
LazyBool m_supports_jLoadedDynamicLibrariesInfos;
@@ -570,9 +573,7 @@ protected:
ArchSpec m_host_arch;
ArchSpec m_process_arch;
- uint32_t m_os_version_major;
- uint32_t m_os_version_minor;
- uint32_t m_os_version_update;
+ llvm::VersionTuple m_os_version;
std::string m_os_build;
std::string m_os_kernel;
std::string m_hostname;
@@ -587,6 +588,9 @@ protected:
bool m_supported_async_json_packets_is_valid;
lldb_private::StructuredData::ObjectSP m_supported_async_json_packets_sp;
+ std::vector<MemoryRegionInfo> m_qXfer_memory_map;
+ bool m_qXfer_memory_map_loaded;
+
bool GetCurrentProcessInfo(bool allow_lazy_pid = true);
bool GetGDBServerVersion();
@@ -609,6 +613,11 @@ protected:
llvm::MutableArrayRef<uint8_t> &buffer,
size_t offset);
+ Status LoadQXferMemoryMap();
+
+ Status GetQXferMemoryMapRegionInfo(lldb::addr_t addr,
+ MemoryRegionInfo &region);
+
private:
DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationClient);
};
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index 4be92b79fd1a9..4fc1fc7a1964e 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -19,8 +19,8 @@
// Project includes
#include "ProcessGDBRemoteLog.h"
-#include "Utility/StringExtractorGDBRemote.h"
#include "lldb/Utility/StreamString.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
index a35352480040b..880caacd64149 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -57,8 +57,8 @@ protected:
bool m_exit_now; // use in asynchronous handling to indicate process should
// exit.
- bool m_send_error_strings; // If the client enables this then
- // we will send error strings as well.
+ bool m_send_error_strings = false; // If the client enables this then
+ // we will send error strings as well.
PacketResult Handle_QErrorStringEnable(StringExtractorGDBRemote &packet);
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
index 3cf6b8ac07b24..c5b478378faa4 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -28,7 +28,7 @@
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
-#include "lldb/Interpreter/Args.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/FileAction.h"
#include "lldb/Target/Platform.h"
@@ -36,13 +36,14 @@
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/JSON.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/SafeMachO.h"
#include "lldb/Utility/StreamGDBRemote.h"
#include "lldb/Utility/StreamString.h"
#include "llvm/ADT/Triple.h"
// Project includes
#include "ProcessGDBRemoteLog.h"
-#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
#ifdef __ANDROID__
#include "lldb/Host/android/HostInfoAndroid.h"
@@ -218,12 +219,15 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo(
if (sub != LLDB_INVALID_CPUTYPE)
response.Printf("cpusubtype:%u;", sub);
- if (cpu == ArchSpec::kCore_arm_any) {
+ if (cpu == llvm::MachO::CPU_TYPE_ARM
+ || cpu == llvm::MachO::CPU_TYPE_ARM64) {
// Indicate the OS type.
#if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
response.PutCString("ostype:tvos;");
#elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
response.PutCString("ostype:watchos;");
+#elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1
+ response.PutCString("ostype:bridgeos;");
#else
response.PutCString("ostype:ios;");
#endif
@@ -265,19 +269,10 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo(
break;
}
- uint32_t major = UINT32_MAX;
- uint32_t minor = UINT32_MAX;
- uint32_t update = UINT32_MAX;
- if (HostInfo::GetOSVersion(major, minor, update)) {
- if (major != UINT32_MAX) {
- response.Printf("os_version:%u", major);
- if (minor != UINT32_MAX) {
- response.Printf(".%u", minor);
- if (update != UINT32_MAX)
- response.Printf(".%u", update);
- }
- response.PutChar(';');
- }
+ llvm::VersionTuple version = HostInfo::GetOSVersion();
+ if (!version.empty()) {
+ response.Format("os_version:{0}", version.getAsString());
+ response.PutChar(';');
}
std::string s;
@@ -295,9 +290,9 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo(
#if defined(__APPLE__)
#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
- // For iOS devices, we are connected through a USB Mux so we never pretend
- // to actually have a hostname as far as the remote lldb that is connecting
- // to this lldb-platform is concerned
+ // For iOS devices, we are connected through a USB Mux so we never pretend to
+ // actually have a hostname as far as the remote lldb that is connecting to
+ // this lldb-platform is concerned
response.PutCString("hostname:");
response.PutCStringAsRawHex8("127.0.0.1");
response.PutChar(';');
@@ -357,7 +352,8 @@ GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo(
StringExtractor extractor(value);
std::string file;
extractor.GetHexByteString(file);
- match_info.GetProcessInfo().GetExecutableFile().SetFile(file, false);
+ match_info.GetProcessInfo().GetExecutableFile().SetFile(
+ file, false, FileSpec::Style::native);
} else if (key.equals("name_match")) {
NameMatch name_match = llvm::StringSwitch<NameMatch>(value)
.Case("equals", NameMatch::Equals)
@@ -401,7 +397,7 @@ GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo(
match_info.GetProcessInfo().SetEffectiveGroupID(gid);
} else if (key.equals("all_users")) {
match_info.SetMatchAllUsers(
- Args::StringToBoolean(value, false, &success));
+ OptionArgParser::ToBoolean(value, false, &success));
} else if (key.equals("triple")) {
match_info.GetProcessInfo().GetArchitecture() =
HostInfo::GetAugmentedArchSpec(value);
@@ -415,8 +411,8 @@ GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo(
}
if (Host::FindProcesses(match_info, m_proc_infos)) {
- // We found something, return the first item by calling the get
- // subsequent process info packet handler...
+ // We found something, return the first item by calling the get subsequent
+ // process info packet handler...
return Handle_qsProcessInfo(packet);
}
return SendErrorResponse(3);
@@ -731,14 +727,13 @@ GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell(
if (packet.GetChar() == ',') {
// FIXME: add timeout to qPlatform_shell packet
// uint32_t timeout = packet.GetHexMaxU32(false, 32);
- uint32_t timeout = 10;
if (packet.GetChar() == ',')
packet.GetHexByteString(working_dir);
int status, signo;
std::string output;
- Status err =
- Host::RunShellCommand(path.c_str(), FileSpec{working_dir, true},
- &status, &signo, &output, timeout);
+ Status err = Host::RunShellCommand(
+ path.c_str(), FileSpec{working_dir, true}, &status, &signo, &output,
+ std::chrono::seconds(10));
StreamGDBRemote response;
if (err.Fail()) {
response.PutCString("F,");
@@ -945,8 +940,7 @@ GDBRemoteCommunicationServerCommon::Handle_QEnvironment(
packet.SetFilePos(::strlen("QEnvironment:"));
const uint32_t bytes_left = packet.GetBytesLeft();
if (bytes_left > 0) {
- m_process_launch_info.GetEnvironmentEntries().AppendArgument(
- llvm::StringRef::withNullAsEmpty(packet.Peek()));
+ m_process_launch_info.GetEnvironment().insert(packet.Peek());
return SendOKResponse();
}
return SendErrorResponse(12);
@@ -960,7 +954,7 @@ GDBRemoteCommunicationServerCommon::Handle_QEnvironmentHexEncoded(
if (bytes_left > 0) {
std::string str;
packet.GetHexByteString(str);
- m_process_launch_info.GetEnvironmentEntries().AppendArgument(str);
+ m_process_launch_info.GetEnvironment().insert(str);
return SendOKResponse();
}
return SendErrorResponse(12);
@@ -981,11 +975,11 @@ GDBRemoteCommunicationServerCommon::Handle_QLaunchArch(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) {
- // The 'A' packet is the most over designed packet ever here with
- // redundant argument indexes, redundant argument lengths and needed hex
- // encoded argument string values. Really all that is needed is a comma
- // separated hex encoded argument value list, but we will stay true to the
- // documented version of the 'A' packet here...
+ // The 'A' packet is the most over designed packet ever here with redundant
+ // argument indexes, redundant argument lengths and needed hex encoded
+ // argument string values. Really all that is needed is a comma separated hex
+ // encoded argument value list, but we will stay true to the documented
+ // version of the 'A' packet here...
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
int actual_arg_index = 0;
@@ -993,8 +987,8 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) {
packet.SetFilePos(1); // Skip the 'A'
bool success = true;
while (success && packet.GetBytesLeft() > 0) {
- // Decode the decimal argument string length. This length is the
- // number of hex nibbles in the argument string value.
+ // Decode the decimal argument string length. This length is the number of
+ // hex nibbles in the argument string value.
const uint32_t arg_len = packet.GetU32(UINT32_MAX);
if (arg_len == UINT32_MAX)
success = false;
@@ -1003,8 +997,8 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) {
if (packet.GetChar() != ',')
success = false;
else {
- // Decode the argument index. We ignore this really because
- // who would really send down the arguments in a random order???
+ // Decode the argument index. We ignore this really because who would
+ // really send down the arguments in a random order???
const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
if (arg_idx == UINT32_MAX)
success = false;
@@ -1013,9 +1007,9 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) {
if (packet.GetChar() != ',')
success = false;
else {
- // Decode the argument string value from hex bytes
- // back into a UTF8 string and make sure the length
- // matches the one supplied in the packet
+ // Decode the argument string value from hex bytes back into a UTF8
+ // string and make sure the length matches the one supplied in the
+ // packet
std::string arg;
if (packet.GetHexByteStringFixedLength(arg, arg_len) !=
(arg_len / 2))
@@ -1029,7 +1023,8 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) {
if (success) {
if (arg_idx == 0)
- m_process_launch_info.GetExecutableFile().SetFile(arg, false);
+ m_process_launch_info.GetExecutableFile().SetFile(
+ arg, false, FileSpec::Style::native);
m_process_launch_info.GetArguments().AppendArgument(arg);
if (log)
log->Printf("LLGSPacketHandler::%s added arg %d: \"%s\"",
@@ -1254,8 +1249,8 @@ void GDBRemoteCommunicationServerCommon::
// Nothing.
break;
}
- // In case of MIPS64, pointer size is depend on ELF ABI
- // For N32 the pointer size is 4 and for N64 it is 8
+ // In case of MIPS64, pointer size is depend on ELF ABI For N32 the pointer
+ // size is 4 and for N64 it is 8
std::string abi = proc_arch.GetTargetABI();
if (!abi.empty())
response.Printf("elf_abi:%s;", abi.c_str());
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index 32741c2404e22..50392fa389562 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -33,9 +33,9 @@
#include "lldb/Host/common/NativeProcessProtocol.h"
#include "lldb/Host/common/NativeRegisterContext.h"
#include "lldb/Host/common/NativeThreadProtocol.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Target/FileAction.h"
#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/JSON.h"
@@ -49,7 +49,7 @@
// Project includes
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
-#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
using namespace lldb;
using namespace lldb_private;
@@ -236,16 +236,15 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() {
m_debugged_process_up = std::move(*process_or);
}
- // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol
- // as needed.
- // llgs local-process debugging may specify PTY paths, which will make these
- // file actions non-null
- // process launch -i/e/o will also make these file actions non-null
- // nullptr means that the traffic is expected to flow over gdb-remote protocol
+ // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol as
+ // needed. llgs local-process debugging may specify PTY paths, which will
+ // make these file actions non-null process launch -i/e/o will also make
+ // these file actions non-null nullptr means that the traffic is expected to
+ // flow over gdb-remote protocol
if (should_forward_stdio) {
// nullptr means it's not redirected to file or pty (in case of LLGS local)
- // at least one of stdio will be transferred pty<->gdb-remote
- // we need to give the pty master handle to this object to read and/or write
+ // at least one of stdio will be transferred pty<->gdb-remote we need to
+ // give the pty master handle to this object to read and/or write
LLDB_LOG(log,
"pid = {0}: setting up stdout/stderr redirection via $O "
"gdb-remote commands",
@@ -291,7 +290,7 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) {
// else.
if (m_debugged_process_up &&
m_debugged_process_up->GetID() != LLDB_INVALID_PROCESS_ID)
- return Status("cannot attach to a process %" PRIu64
+ return Status("cannot attach to process %" PRIu64
" when another process with pid %" PRIu64
" is being debugged.",
pid, m_debugged_process_up->GetID());
@@ -410,8 +409,8 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) {
JSONObject::SP register_object_sp = std::make_shared<JSONObject>();
#ifdef LLDB_JTHREADSINFO_FULL_REGISTER_SET
- // Expedite all registers in the first register set (i.e. should be GPRs) that
- // are not contained in other registers.
+ // Expedite all registers in the first register set (i.e. should be GPRs)
+ // that are not contained in other registers.
const RegisterSet *reg_set_p = reg_ctx_sp->GetRegisterSet(0);
if (!reg_set_p)
return nullptr;
@@ -420,8 +419,7 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) {
uint32_t reg_num = *reg_num_p;
#else
// Expedite only a couple of registers until we figure out why sending
- // registers is
- // expensive.
+ // registers is expensive.
static const uint32_t k_expedited_registers[] = {
LLDB_REGNUM_GENERIC_PC, LLDB_REGNUM_GENERIC_SP, LLDB_REGNUM_GENERIC_FP,
LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM};
@@ -595,8 +593,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
return SendErrorResponse(52);
// FIXME implement register handling for exec'd inferiors.
- // if (tid_stop_info.reason == eStopReasonExec)
- // {
+ // if (tid_stop_info.reason == eStopReasonExec) {
// const bool force = true;
// InitializeRegisters(force);
// }
@@ -633,14 +630,14 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
response.PutChar(';');
}
- // If a 'QListThreadsInStopReply' was sent to enable this feature, we
- // will send all thread IDs back in the "threads" key whose value is
- // a list of hex thread IDs separated by commas:
+ // If a 'QListThreadsInStopReply' was sent to enable this feature, we will
+ // send all thread IDs back in the "threads" key whose value is a list of hex
+ // thread IDs separated by commas:
// "threads:10a,10b,10c;"
- // This will save the debugger from having to send a pair of qfThreadInfo
- // and qsThreadInfo packets, but it also might take a lot of room in the
- // stop reply packet, so it must be enabled only on systems where there
- // are no limits on packet lengths.
+ // This will save the debugger from having to send a pair of qfThreadInfo and
+ // qsThreadInfo packets, but it also might take a lot of room in the stop
+ // reply packet, so it must be enabled only on systems where there are no
+ // limits on packet lengths.
if (m_list_threads_in_stop_reply) {
response.PutCString("threads:");
@@ -655,12 +652,11 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
}
response.PutChar(';');
- // Include JSON info that describes the stop reason for any threads
- // that actually have stop reasons. We use the new "jstopinfo" key
- // whose values is hex ascii JSON that contains the thread IDs
- // thread stop info only for threads that have stop reasons. Only send
- // this if we have more than one thread otherwise this packet has all
- // the info it needs.
+ // Include JSON info that describes the stop reason for any threads that
+ // actually have stop reasons. We use the new "jstopinfo" key whose values
+ // is hex ascii JSON that contains the thread IDs thread stop info only for
+ // threads that have stop reasons. Only send this if we have more than one
+ // thread otherwise this packet has all the info it needs.
if (thread_index > 0) {
const bool threads_with_valid_stop_info_only = true;
JSONArray::SP threads_info_sp = GetJSONThreadsInfo(
@@ -806,8 +802,8 @@ void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited(
__FUNCTION__, process->GetID());
}
- // Close the pipe to the inferior terminal i/o if we launched it
- // and set one up.
+ // Close the pipe to the inferior terminal i/o if we launched it and set one
+ // up.
MaybeCloseInferiorTerminalConnection();
// We are ready to exit the debug monitor.
@@ -823,8 +819,7 @@ void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped(
if (log)
log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
- // Send the stop reason unless this is the stop after the
- // launch or attach.
+ // Send the stop reason unless this is the stop after the launch or attach.
switch (m_inferior_prev_state) {
case eStateLaunching:
case eStateAttaching:
@@ -859,13 +854,11 @@ void GDBRemoteCommunicationServerLLGS::ProcessStateChanged(
break;
case StateType::eStateStopped:
- // Make sure we get all of the pending stdout/stderr from the inferior
- // and send it to the lldb host before we send the state change
- // notification
+ // Make sure we get all of the pending stdout/stderr from the inferior and
+ // send it to the lldb host before we send the state change notification
SendProcessOutput();
// Then stop the forwarding, so that any late output (see llvm.org/pr25652)
- // does not
- // interfere with our protocol.
+ // does not interfere with our protocol.
StopSTDIOForwarding();
HandleInferiorState_Stopped(process);
break;
@@ -1287,8 +1280,8 @@ GDBRemoteCommunicationServerLLGS::Handle_qC(StringExtractorGDBRemote &packet) {
(m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
return SendErrorResponse(68);
- // Make sure we set the current thread so g and p packets return
- // the data the gdb will expect.
+ // Make sure we set the current thread so g and p packets return the data the
+ // gdb will expect.
lldb::tid_t tid = m_debugged_process_up->GetCurrentThreadID();
SetCurrentThreadID(tid);
@@ -1397,10 +1390,9 @@ GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) {
Status error;
// We have two branches: what to do if a continue thread is specified (in
- // which case we target
- // sending the signal to that thread), or when we don't have a continue thread
- // set (in which
- // case we send a signal to the process).
+ // which case we target sending the signal to that thread), or when we don't
+ // have a continue thread set (in which case we send a signal to the
+ // process).
// TODO discuss with Greg Clayton, make sure this makes sense.
@@ -1639,8 +1631,8 @@ GDBRemoteCommunicationServerLLGS::SendStopReasonForState(
case eStateStopped:
case eStateCrashed: {
lldb::tid_t tid = m_debugged_process_up->GetCurrentThreadID();
- // Make sure we set the current thread so g and p packets return
- // the data the gdb will expect.
+ // Make sure we set the current thread so g and p packets return the data
+ // the gdb will expect.
SetCurrentThreadID(tid);
return SendStopReplyPacketForThread(tid);
}
@@ -2043,9 +2035,8 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) {
return SendErrorResponse(0x47);
}
- // The dwarf expression are evaluate on host site
- // which may cause register size to change
- // Hence the reg_size may not be same as reg_info->bytes_size
+ // The dwarf expression are evaluate on host site which may cause register
+ // size to change Hence the reg_size may not be same as reg_info->bytes_size
if ((reg_size != reg_info->byte_size) &&
!(reg_info->dynamic_size_dwarf_expr_bytes)) {
return SendIllFormedResponse(packet, "P packet register size is incorrect");
@@ -2376,10 +2367,9 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported(
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
// Currently only the NativeProcessProtocol knows if it can handle a
- // qMemoryRegionInfoSupported
- // request, but we're not guaranteed to be attached to a process. For now
- // we'll assume the
- // client only asks this when a process is being debugged.
+ // qMemoryRegionInfoSupported request, but we're not guaranteed to be
+ // attached to a process. For now we'll assume the client only asks this
+ // when a process is being debugged.
// Ensure we have a process running; otherwise, we can't figure this out
// since we won't have a NativeProcessProtocol.
@@ -2670,8 +2660,7 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) {
}
// We first try to use a continue thread id. If any one or any all set, use
- // the current thread.
- // Bail out if we don't have a thread id.
+ // the current thread. Bail out if we don't have a thread id.
lldb::tid_t tid = GetContinueThreadID();
if (tid == 0 || tid == LLDB_INVALID_THREAD_ID)
tid = GetCurrentThreadID();
@@ -2935,7 +2924,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttach(
log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to attach to "
"pid %" PRIu64 ": %s\n",
__FUNCTION__, pid, error.AsCString());
- return SendErrorResponse(0x01);
+ return SendErrorResponse(error);
}
// Notify we attached by sending a stop packet.
@@ -3093,8 +3082,8 @@ GDBRemoteCommunicationServerLLGS::Handle_QPassSignals(
std::vector<int> signals;
packet.SetFilePos(strlen("QPassSignals:"));
- // Read sequence of hex signal numbers divided by a semicolon and
- // optionally spaces.
+ // Read sequence of hex signal numbers divided by a semicolon and optionally
+ // spaces.
while (packet.GetBytesLeft() > 0) {
int signal = packet.GetS32(-1, 16);
if (signal < 0)
@@ -3154,8 +3143,7 @@ NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix(
return nullptr;
// If the client hasn't asked for thread suffix support, there will not be a
- // thread suffix.
- // Use the current thread in that case.
+ // thread suffix. Use the current thread in that case.
if (!m_thread_suffix_supported) {
const lldb::tid_t current_tid = GetCurrentThreadID();
if (current_tid == LLDB_INVALID_THREAD_ID)
@@ -3201,9 +3189,9 @@ NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix(
lldb::tid_t GDBRemoteCommunicationServerLLGS::GetCurrentThreadID() const {
if (m_current_tid == 0 || m_current_tid == LLDB_INVALID_THREAD_ID) {
- // Use whatever the debug process says is the current thread id
- // since the protocol either didn't specify or specified we want
- // any/all threads marked as the current thread.
+ // Use whatever the debug process says is the current thread id since the
+ // protocol either didn't specify or specified we want any/all threads
+ // marked as the current thread.
if (!m_debugged_process_up)
return LLDB_INVALID_THREAD_ID;
return m_debugged_process_up->GetCurrentThreadID();
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
index 04ed9d704e137..26e28a900320a 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
@@ -14,6 +14,7 @@
// C Includes
// C++ Includes
#include <chrono>
+#include <csignal>
#include <cstring>
#include <mutex>
#include <sstream>
@@ -38,7 +39,7 @@
#include "lldb/Utility/UriParser.h"
// Project includes
-#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
using namespace lldb;
using namespace lldb_private;
@@ -101,11 +102,11 @@ Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
if (port == UINT16_MAX)
port = GetNextAvailablePort();
- // Spawn a new thread to accept the port that gets bound after
- // binding to port 0 (zero).
+ // Spawn a new thread to accept the port that gets bound after binding to
+ // port 0 (zero).
- // ignore the hostname send from the remote end, just use the ip address
- // that we're currently communicating with as the hostname
+ // ignore the hostname send from the remote end, just use the ip address that
+ // we're currently communicating with as the hostname
// Spawn a debugserver and try to get the port it listens to.
ProcessLaunchInfo debugserver_launch_info;
@@ -116,8 +117,8 @@ Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
if (log)
log->Printf("Launching debugserver with: %s:%u...", hostname.c_str(), port);
- // Do not run in a new session so that it can not linger after the
- // platform closes.
+ // Do not run in a new session so that it can not linger after the platform
+ // closes.
debugserver_launch_info.SetLaunchInSeparateProcessGroup(false);
debugserver_launch_info.SetMonitorProcessCallback(
std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped,
@@ -170,8 +171,8 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer(
#ifdef _WIN32
return SendErrorResponse(9);
#else
- // Spawn a local debugserver as a platform so we can then attach or launch
- // a process...
+ // Spawn a local debugserver as a platform so we can then attach or launch a
+ // process...
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (log)
@@ -259,8 +260,7 @@ GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess(
lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
- // verify that we know anything about this pid.
- // Scope for locker
+ // verify that we know anything about this pid. Scope for locker
{
std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
@@ -306,8 +306,8 @@ bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) {
return true;
}
- // the launched process still lives. Now try killing it again,
- // this time with an unblockable signal.
+ // the launched process still lives. Now try killing it again, this time
+ // with an unblockable signal.
Host::Kill(pid, SIGKILL);
for (size_t i = 0; i < 10; ++i) {
@@ -321,8 +321,7 @@ bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) {
usleep(10000);
}
- // check one more time after the final usleep
- // Scope for locker
+ // check one more time after the final usleep Scope for locker
{
std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
if (m_spawned_pids.find(pid) == m_spawned_pids.end())
@@ -389,14 +388,13 @@ GDBRemoteCommunicationServerPlatform::Handle_qC(
StreamString response;
response.Printf("QC%" PRIx64, pid);
- // If we launch a process and this GDB server is acting as a platform,
- // then we need to clear the process launch state so we can start
- // launching another process. In order to launch a process a bunch or
- // packets need to be sent: environment packets, working directory,
- // disable ASLR, and many more settings. When we launch a process we
- // then need to know when to clear this information. Currently we are
- // selecting the 'qC' packet as that packet which seems to make the most
- // sense.
+ // If we launch a process and this GDB server is acting as a platform, then
+ // we need to clear the process launch state so we can start launching
+ // another process. In order to launch a process a bunch or packets need to
+ // be sent: environment packets, working directory, disable ASLR, and many
+ // more settings. When we launch a process we then need to know when to clear
+ // this information. Currently we are selecting the 'qC' packet as that
+ // packet which seems to make the most sense.
if (pid != LLDB_INVALID_PROCESS_ID) {
m_process_launch_info.Clear();
}
@@ -445,9 +443,8 @@ Status GDBRemoteCommunicationServerPlatform::LaunchProcess() {
return Status("%s: no process command line specified to launch",
__FUNCTION__);
- // specify the process monitor if not already set. This should
- // generally be what happens since we need to reap started
- // processes.
+ // specify the process monitor if not already set. This should generally be
+ // what happens since we need to reap started processes.
if (!m_process_launch_info.GetMonitorProcessCallback())
m_process_launch_info.SetMonitorProcessCallback(
std::bind(
@@ -466,8 +463,8 @@ Status GDBRemoteCommunicationServerPlatform::LaunchProcess() {
m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
m_process_launch_info.GetProcessID());
- // add to list of spawned processes. On an lldb-gdbserver, we
- // would expect there to be only one.
+ // add to list of spawned processes. On an lldb-gdbserver, we would expect
+ // there to be only one.
const auto pid = m_process_launch_info.GetProcessID();
if (pid != LLDB_INVALID_PROCESS_ID) {
// add to spawned pids
@@ -537,7 +534,7 @@ const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() {
if (domainsocket_dir_env != nullptr)
g_domainsocket_dir = FileSpec(domainsocket_dir_env, false);
else
- HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, g_domainsocket_dir);
+ g_domainsocket_dir = HostInfo::GetProcessTempDir();
});
return g_domainsocket_dir;
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index e418deee01f3d..07dab751f4b90 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -25,7 +25,7 @@
#include "ThreadGDBRemote.h"
#include "Utility/ARM_DWARF_Registers.h"
#include "Utility/ARM_ehframe_Registers.h"
-#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
using namespace lldb;
using namespace lldb_private;
@@ -39,9 +39,9 @@ GDBRemoteRegisterContext::GDBRemoteRegisterContext(
GDBRemoteDynamicRegisterInfo &reg_info, bool read_all_at_once)
: RegisterContext(thread, concrete_frame_idx), m_reg_info(reg_info),
m_reg_valid(), m_reg_data(), m_read_all_at_once(read_all_at_once) {
- // Resize our vector of bools to contain one bool for every register.
- // We will use these boolean values to know when a register value
- // is valid in m_reg_data.
+ // Resize our vector of bools to contain one bool for every register. We will
+ // use these boolean values to know when a register value is valid in
+ // m_reg_data.
m_reg_valid.resize(reg_info.GetNumRegisters());
// Make a heap based buffer that is big enough to store all registers
@@ -119,8 +119,8 @@ bool GDBRemoteRegisterContext::PrivateSetRegisterValue(
if (success) {
SetRegisterIsValid(reg, true);
} else if (data.size() > 0) {
- // Only set register is valid to false if we copied some bytes, else
- // leave it as it was.
+ // Only set register is valid to false if we copied some bytes, else leave
+ // it as it was.
SetRegisterIsValid(reg, false);
}
return success;
@@ -133,11 +133,9 @@ bool GDBRemoteRegisterContext::PrivateSetRegisterValue(uint32_t reg,
return false;
// Early in process startup, we can get a thread that has an invalid byte
- // order
- // because the process hasn't been completely set up yet (see the ctor where
- // the
- // byte order is setfrom the process). If that's the case, we can't set the
- // value here.
+ // order because the process hasn't been completely set up yet (see the ctor
+ // where the byte order is setfrom the process). If that's the case, we
+ // can't set the value here.
if (m_reg_data.GetByteOrder() == eByteOrderInvalid) {
return false;
}
@@ -149,8 +147,7 @@ bool GDBRemoteRegisterContext::PrivateSetRegisterValue(uint32_t reg,
DataExtractor data(buffer_sp, endian::InlHostByteOrder(), sizeof(void *));
// If our register context and our register info disagree, which should never
- // happen, don't
- // overwrite past the end of the buffer.
+ // happen, don't overwrite past the end of the buffer.
if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
return false;
@@ -219,8 +216,7 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info,
}
if (reg_info->value_regs) {
// Process this composite register request by delegating to the
- // constituent
- // primordial registers.
+ // constituent primordial registers.
// Index of the primordial register.
bool success = true;
@@ -228,8 +224,8 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info,
const uint32_t prim_reg = reg_info->value_regs[idx];
if (prim_reg == LLDB_INVALID_REGNUM)
break;
- // We have a valid primordial register as our constituent.
- // Grab the corresponding register info.
+ // We have a valid primordial register as our constituent. Grab the
+ // corresponding register info.
const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg);
if (prim_reg_info == NULL)
success = false;
@@ -242,8 +238,7 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info,
if (success) {
// If we reach this point, all primordial register requests have
- // succeeded.
- // Validate this composite register.
+ // succeeded. Validate this composite register.
SetRegisterIsValid(reg_info, true);
}
} else {
@@ -262,16 +257,14 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info,
reg_info->byte_offset + reg_info->byte_size);
#endif
// If our register context and our register info disagree, which should
- // never happen, don't
- // read past the end of the buffer.
+ // never happen, don't read past the end of the buffer.
if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
return false;
- // If we aren't extracting into our own buffer (which
- // only happens when this function is called from
- // ReadRegisterValue(uint32_t, Scalar&)) then
- // we transfer bytes from our buffer into the data
- // buffer that was passed in
+ // If we aren't extracting into our own buffer (which only happens when
+ // this function is called from ReadRegisterValue(uint32_t, Scalar&)) then
+ // we transfer bytes from our buffer into the data buffer that was passed
+ // in
data.SetByteOrder(m_reg_data.GetByteOrder());
data.SetData(m_reg_data, reg_info->byte_offset, reg_info->byte_size);
@@ -321,8 +314,7 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
#endif
// If our register context and our register info disagree, which should never
- // happen, don't
- // overwrite past the end of the buffer.
+ // happen, don't overwrite past the end of the buffer.
if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
return false;
@@ -358,12 +350,10 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
bool success = true;
if (reg_info->value_regs) {
- // This register is part of another register. In this case we read the
- // actual
- // register data for any "value_regs", and once all that data is read,
- // we will
- // have enough data in our register context bytes for the value of
- // this register
+ // This register is part of another register. In this case we read
+ // the actual register data for any "value_regs", and once all that
+ // data is read, we will have enough data in our register context
+ // bytes for the value of this register
// Invalidate this composite register first.
@@ -371,8 +361,8 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
const uint32_t reg = reg_info->value_regs[idx];
if (reg == LLDB_INVALID_REGNUM)
break;
- // We have a valid primordial register as our constituent.
- // Grab the corresponding register info.
+ // We have a valid primordial register as our constituent. Grab the
+ // corresponding register info.
const RegisterInfo *value_reg_info = GetRegisterInfoAtIndex(reg);
if (value_reg_info == NULL)
success = false;
@@ -385,8 +375,7 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
}
// Check if writing this register will invalidate any other register
- // values?
- // If so, invalidate them
+ // values? If so, invalidate them
if (reg_info->invalidate_regs) {
for (uint32_t idx = 0, reg = reg_info->invalidate_regs[0];
reg != LLDB_INVALID_REGNUM;
@@ -548,26 +537,22 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues(
return true;
uint32_t num_restored = 0;
- // We need to manually go through all of the registers and
- // restore them manually
+ // We need to manually go through all of the registers and restore them
+ // manually
DataExtractor restore_data(data_sp, m_reg_data.GetByteOrder(),
m_reg_data.GetAddressByteSize());
const RegisterInfo *reg_info;
- // The g packet contents may either include the slice registers (registers
- // defined in
- // terms of other registers, e.g. eax is a subset of rax) or not. The
- // slice registers
- // should NOT be in the g packet, but some implementations may incorrectly
- // include them.
+ // The g packet contents may either include the slice registers
+ // (registers defined in terms of other registers, e.g. eax is a subset
+ // of rax) or not. The slice registers should NOT be in the g packet,
+ // but some implementations may incorrectly include them.
//
// If the slice registers are included in the packet, we must step over
- // the slice registers
- // when parsing the packet -- relying on the RegisterInfo byte_offset
- // field would be incorrect.
- // If the slice registers are not included, then using the byte_offset
- // values into the
+ // the slice registers when parsing the packet -- relying on the
+ // RegisterInfo byte_offset field would be incorrect. If the slice
+ // registers are not included, then using the byte_offset values into the
// data buffer is the best way to find individual register values.
uint64_t size_including_slice_registers = 0;
@@ -591,21 +576,17 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues(
} else if (size_not_including_slice_registers ==
restore_data.GetByteSize()) {
// The size of the packet is the same as concatenating all of the
- // registers sequentially,
- // skipping the slice registers
+ // registers sequentially, skipping the slice registers
use_byte_offset_into_buffer = true;
} else if (size_including_slice_registers == restore_data.GetByteSize()) {
// The slice registers are present in the packet (when they shouldn't
- // be).
- // Don't try to use the RegisterInfo byte_offset into the restore_data,
- // it will
- // point to the wrong place.
+ // be). Don't try to use the RegisterInfo byte_offset into the
+ // restore_data, it will point to the wrong place.
use_byte_offset_into_buffer = false;
} else {
// None of our expected sizes match the actual g packet data we're
- // looking at.
- // The most conservative approach here is to use the running total byte
- // offset.
+ // looking at. The most conservative approach here is to use the
+ // running total byte offset.
use_byte_offset_into_buffer = false;
}
@@ -664,11 +645,9 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues(
if (reg_info->value_regs) // skip registers that are slices of real
// registers
continue;
- // Skip the fpsr and fpcr floating point status/control register writing
- // to
- // work around a bug in an older version of debugserver that would lead
- // to
- // register context corruption when writing fpsr/fpcr.
+ // Skip the fpsr and fpcr floating point status/control register
+ // writing to work around a bug in an older version of debugserver that
+ // would lead to register context corruption when writing fpsr/fpcr.
if (arm64_debugserver && (strcmp(reg_info->name, "fpsr") == 0 ||
strcmp(reg_info->name, "fpcr") == 0)) {
continue;
@@ -752,8 +731,8 @@ void GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch) {
static uint32_t g_q14_regs[] = {71, 72, LLDB_INVALID_REGNUM}; // (d28, d29)
static uint32_t g_q15_regs[] = {73, 74, LLDB_INVALID_REGNUM}; // (d30, d31)
- // This is our array of composite registers, with each element coming from the
- // above register mappings.
+ // This is our array of composite registers, with each element coming from
+ // the above register mappings.
static uint32_t *g_composites[] = {
g_d0_regs, g_d1_regs, g_d2_regs, g_d3_regs, g_d4_regs, g_d5_regs,
g_d6_regs, g_d7_regs, g_d8_regs, g_d9_regs, g_d10_regs, g_d11_regs,
@@ -884,21 +863,17 @@ void GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch) {
if (from_scratch) {
// Calculate the offsets of the registers
// Note that the layout of the "composite" registers (d0-d15 and q0-q15)
- // which comes after the
- // "primordial" registers is important. This enables us to calculate the
- // offset of the composite
- // register by using the offset of its first primordial register. For
- // example, to calculate the
- // offset of q0, use s0's offset.
+ // which comes after the "primordial" registers is important. This enables
+ // us to calculate the offset of the composite register by using the offset
+ // of its first primordial register. For example, to calculate the offset
+ // of q0, use s0's offset.
if (g_register_infos[2].byte_offset == 0) {
uint32_t byte_offset = 0;
for (i = 0; i < num_registers; ++i) {
// For primordial registers, increment the byte_offset by the byte_size
- // to arrive at the
- // byte_offset for the next register. Otherwise, we have a composite
- // register whose
- // offset can be calculated by consulting the offset of its first
- // primordial register.
+ // to arrive at the byte_offset for the next register. Otherwise, we
+ // have a composite register whose offset can be calculated by
+ // consulting the offset of its first primordial register.
if (!g_register_infos[i].value_regs) {
g_register_infos[i].byte_offset = byte_offset;
byte_offset += g_register_infos[i].byte_size;
@@ -933,8 +908,8 @@ void GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch) {
RegisterInfo *g_comp_register_infos = g_register_infos + num_common_regs;
// First we need to validate that all registers that we already have match
- // the non composite regs.
- // If so, then we can add the registers, else we need to bail
+ // the non composite regs. If so, then we can add the registers, else we
+ // need to bail
bool match = true;
if (num_dynamic_regs == num_common_regs) {
for (i = 0; match && i < num_dynamic_regs; ++i) {
@@ -970,9 +945,8 @@ void GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch) {
// Find a matching primordial register info entry.
if (reg_info && reg_info->name &&
::strcasecmp(reg_info->name, reg_name) == 0) {
- // The name matches the existing primordial entry.
- // Find and assign the offset, and then add this composite
- // register entry.
+ // The name matches the existing primordial entry. Find and
+ // assign the offset, and then add this composite register entry.
g_comp_register_infos[i].byte_offset = reg_info->byte_offset;
name.SetCString(g_comp_register_infos[i].name);
AddRegister(g_comp_register_infos[i], name, alt_name,
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 35d02c15ab85b..b3d33b19bd666 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -24,6 +24,7 @@
// C++ Includes
#include <algorithm>
+#include <csignal>
#include <map>
#include <mutex>
#include <sstream>
@@ -46,11 +47,11 @@
#include "lldb/Host/Symbols.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/XML.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionGroupBoolean.h"
#include "lldb/Interpreter/OptionGroupUInt64.h"
#include "lldb/Interpreter/OptionValueProperties.h"
@@ -59,10 +60,12 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/TargetList.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/CleanUp.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/StreamString.h"
@@ -77,8 +80,8 @@
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
#include "ThreadGDBRemote.h"
-#include "Utility/StringExtractorGDBRemote.h"
#include "lldb/Host/Host.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Threading.h"
@@ -91,11 +94,11 @@ using namespace lldb_private::process_gdb_remote;
namespace lldb {
// Provide a function that can easily dump the packet history if we know a
-// ProcessGDBRemote * value (which we can get from logs or from debugging).
-// We need the function in the lldb namespace so it makes it into the final
+// ProcessGDBRemote * value (which we can get from logs or from debugging). We
+// need the function in the lldb namespace so it makes it into the final
// executable since the LLDB shared library only exports stuff in the lldb
-// namespace. This allows you to attach with a debugger and call this
-// function and get the packet history dumped to a file.
+// namespace. This allows you to attach with a debugger and call this function
+// and get the packet history dumped to a file.
void DumpProcessGDBRemotePacketHistory(void *p, const char *path) {
StreamFile strm;
Status error(strm.GetFile().Open(path, File::eOpenOptionWrite |
@@ -158,8 +161,8 @@ static const ProcessKDPPropertiesSP &GetGlobalPluginProperties() {
} // anonymous namespace end
// TODO Randomly assigning a port is unsafe. We should get an unused
-// ephemeral port from the kernel and make sure we reserve it before passing
-// it to debugserver.
+// ephemeral port from the kernel and make sure we reserve it before passing it
+// to debugserver.
#if defined(__APPLE__)
#define LOW_PORT (IPPORT_RESERVED)
@@ -233,8 +236,8 @@ bool ProcessGDBRemote::CanDebug(lldb::TargetSP target_sp,
}
return exe_module->GetFileSpec().Exists();
}
- // However, if there is no executable module, we return true since we might be
- // preparing to attach.
+ // However, if there is no executable module, we return true since we might
+ // be preparing to attach.
return true;
}
@@ -256,7 +259,8 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp,
m_addr_to_mmap_size(), m_thread_create_bp_sp(),
m_waiting_for_attach(false), m_destroy_tried_resuming(false),
m_command_sp(), m_breakpoint_pc_offset(0),
- m_initial_tid(LLDB_INVALID_THREAD_ID) {
+ m_initial_tid(LLDB_INVALID_THREAD_ID), m_allow_flash_writes(false),
+ m_erased_flash_ranges() {
m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit,
"async thread should exit");
m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue,
@@ -299,17 +303,16 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp,
ProcessGDBRemote::~ProcessGDBRemote() {
// m_mach_process.UnregisterNotificationCallbacks (this);
Clear();
- // We need to call finalize on the process before destroying ourselves
- // to make sure all of the broadcaster cleanup goes as planned. If we
- // destruct this class, then Process::~Process() might have problems
- // trying to fully destroy the broadcaster.
+ // We need to call finalize on the process before destroying ourselves to
+ // make sure all of the broadcaster cleanup goes as planned. If we destruct
+ // this class, then Process::~Process() might have problems trying to fully
+ // destroy the broadcaster.
Finalize();
- // The general Finalize is going to try to destroy the process and that SHOULD
- // shut down the async thread. However, if we don't kill it it will get
- // stranded and
- // its connection will go away so when it wakes up it will crash. So kill it
- // for sure here.
+ // The general Finalize is going to try to destroy the process and that
+ // SHOULD shut down the async thread. However, if we don't kill it it will
+ // get stranded and its connection will go away so when it wakes up it will
+ // crash. So kill it for sure here.
StopAsyncThread();
KillDebugserverProcess();
}
@@ -368,8 +371,7 @@ bool ProcessGDBRemote::ParsePythonTargetDefinition(
}
// If the remote stub didn't give us eh_frame or DWARF register numbers for a
-// register,
-// see if the ABI can provide them.
+// register, see if the ABI can provide them.
// DWARF and eh_frame register numbers are defined as a part of the ABI.
static void AugmentRegisterInfoViaABI(RegisterInfo &reg_info,
ConstString reg_name, ABISP abi_sp) {
@@ -422,9 +424,9 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
m_register_info.Clear();
- // Check if qHostInfo specified a specific packet timeout for this connection.
- // If so then lets update our setting so the user knows what the timeout is
- // and can see it.
+ // Check if qHostInfo specified a specific packet timeout for this
+ // connection. If so then lets update our setting so the user knows what the
+ // timeout is and can see it.
const auto host_packet_timeout = m_gdb_comm.GetHostDefaultPacketTimeout();
if (host_packet_timeout > std::chrono::seconds(0)) {
GetGlobalPluginProperties()->SetPacketTimeout(host_packet_timeout.count());
@@ -531,7 +533,7 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
reg_info.encoding = encoding;
} else if (name.equals("format")) {
Format format = eFormatInvalid;
- if (Args::StringToFormat(value.str().c_str(), format, NULL)
+ if (OptionArgParser::ToFormat(value.str().c_str(), format, NULL)
.Success())
reg_info.format = format;
else {
@@ -596,10 +598,8 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
}
// We have to make a temporary ABI here, and not use the GetABI because
- // this code
- // gets called in DidAttach, when the target architecture (and
- // consequently the ABI we'll get from
- // the process) may be wrong.
+ // this code gets called in DidAttach, when the target architecture
+ // (and consequently the ABI we'll get from the process) may be wrong.
ABISP abi_to_use = ABI::FindPlugin(shared_from_this(), arch_to_use);
AugmentRegisterInfoViaABI(reg_info, reg_name, abi_to_use);
@@ -620,9 +620,9 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
// We didn't get anything if the accumulated reg_num is zero. See if we are
// debugging ARM and fill with a hard coded register set until we can get an
- // updated debugserver down on the devices.
- // On the other hand, if the accumulated reg_num is positive, see if we can
- // add composite registers to the existing primordial ones.
+ // updated debugserver down on the devices. On the other hand, if the
+ // accumulated reg_num is positive, see if we can add composite registers to
+ // the existing primordial ones.
bool from_scratch = (m_register_info.GetNumRegisters() == 0);
if (!target_arch.IsValid()) {
@@ -669,9 +669,8 @@ Status ProcessGDBRemote::DoConnectRemote(Stream *strm,
lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID();
if (pid == LLDB_INVALID_PROCESS_ID) {
- // We don't have a valid process ID, so note that we are connected
- // and could now request to launch or attach, or get remote process
- // listings...
+ // We don't have a valid process ID, so note that we are connected and
+ // could now request to launch or attach, or get remote process listings...
SetPrivateState(eStateConnected);
} else {
// We have a valid process
@@ -721,7 +720,8 @@ Status ProcessGDBRemote::DoConnectRemote(Stream *strm,
if (error.Success() && !GetTarget().GetArchitecture().IsValid() &&
m_gdb_comm.GetHostArchitecture().IsValid()) {
- // Prefer the *process'* architecture over that of the *host*, if available.
+ // Prefer the *process'* architecture over that of the *host*, if
+ // available.
if (m_gdb_comm.GetProcessArchitecture().IsValid())
GetTarget().SetArchitecture(m_gdb_comm.GetProcessArchitecture());
else
@@ -800,8 +800,8 @@ Status ProcessGDBRemote::DoLaunch(Module *exe_module,
const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;
if (stdin_file_spec || disable_stdio) {
- // the inferior will be reading stdin from the specified file
- // or stdio is completely disabled
+ // the inferior will be reading stdin from the specified file or stdio is
+ // completely disabled
m_stdin_forward = false;
} else {
m_stdin_forward = true;
@@ -824,11 +824,14 @@ Status ProcessGDBRemote::DoLaunch(Module *exe_module,
if (disable_stdio) {
// set to /dev/null unless redirected to a file above
if (!stdin_file_spec)
- stdin_file_spec.SetFile(FileSystem::DEV_NULL, false);
+ stdin_file_spec.SetFile(FileSystem::DEV_NULL, false,
+ FileSpec::Style::native);
if (!stdout_file_spec)
- stdout_file_spec.SetFile(FileSystem::DEV_NULL, false);
+ stdout_file_spec.SetFile(FileSystem::DEV_NULL, false,
+ FileSpec::Style::native);
if (!stderr_file_spec)
- stderr_file_spec.SetFile(FileSystem::DEV_NULL, false);
+ stderr_file_spec.SetFile(FileSystem::DEV_NULL, false,
+ FileSpec::Style::native);
} else if (platform_sp && platform_sp->IsHost()) {
// If the debugserver is local and we aren't disabling STDIO, lets use
// a pseudo terminal to instead of relying on the 'O' packets for stdio
@@ -888,16 +891,7 @@ Status ProcessGDBRemote::DoLaunch(Module *exe_module,
}
// Send the environment and the program + arguments after we connect
- const Args &environment = launch_info.GetEnvironmentEntries();
- if (environment.GetArgumentCount()) {
- size_t num_environment_entries = environment.GetArgumentCount();
- for (size_t i = 0; i < num_environment_entries; ++i) {
- const char *env_entry = environment.GetArgumentAtIndex(i);
- if (env_entry == NULL ||
- m_gdb_comm.SendEnvironmentPacket(env_entry) != 0)
- break;
- }
- }
+ m_gdb_comm.SendEnvironment(launch_info.GetEnvironment());
{
// Scope for the scoped timeout object
@@ -1004,16 +998,15 @@ Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) {
return error;
}
- // Start the communications read thread so all incoming data can be
- // parsed into packets and queued as they arrive.
+ // Start the communications read thread so all incoming data can be parsed
+ // into packets and queued as they arrive.
if (GetTarget().GetNonStopModeEnabled())
m_gdb_comm.StartReadThread();
- // We always seem to be able to open a connection to a local port
- // so we need to make sure we can then send data to it. If we can't
- // then we aren't actually connected to anything, so try and do the
- // handshake with the remote GDB server and make sure that goes
- // alright.
+ // We always seem to be able to open a connection to a local port so we need
+ // to make sure we can then send data to it. If we can't then we aren't
+ // actually connected to anything, so try and do the handshake with the
+ // remote GDB server and make sure that goes alright.
if (!m_gdb_comm.HandshakeWithServer(&error)) {
m_gdb_comm.Disconnect();
if (error.Success())
@@ -1055,9 +1048,9 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {
// See if the GDB server supports the qHostInfo information
- // See if the GDB server supports the qProcessInfo packet, if so
- // prefer that over the Host information as it will be more specific
- // to our process.
+ // See if the GDB server supports the qProcessInfo packet, if so prefer
+ // that over the Host information as it will be more specific to our
+ // process.
const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture();
if (remote_process_arch.IsValid()) {
@@ -1102,9 +1095,8 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {
// architectures.
// You can have an armv6 executable, and if the host is armv7, then the
// system will load the best possible architecture for all shared
- // libraries
- // it has, so we really need to take the remote host architecture as our
- // defacto architecture in this case.
+ // libraries it has, so we really need to take the remote host
+ // architecture as our defacto architecture in this case.
if ((process_arch.GetMachine() == llvm::Triple::arm ||
process_arch.GetMachine() == llvm::Triple::thumb) &&
@@ -1150,14 +1142,14 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {
? target_arch.GetTriple().getTriple().c_str()
: "<null>");
} else {
- // The target doesn't have a valid architecture yet, set it from
- // the architecture we got from the remote GDB server
+ // The target doesn't have a valid architecture yet, set it from the
+ // architecture we got from the remote GDB server
GetTarget().SetArchitecture(process_arch);
}
}
- // Find out which StructuredDataPlugins are supported by the
- // debug monitor. These plugins transmit data over async $J packets.
+ // Find out which StructuredDataPlugins are supported by the debug monitor.
+ // These plugins transmit data over async $J packets.
auto supported_packets_array =
m_gdb_comm.GetSupportedStructuredDataPlugins();
if (supported_packets_array)
@@ -1365,9 +1357,9 @@ Status ProcessGDBRemote::DoResume() {
continue_packet_error = true;
if (continue_packet_error) {
- // Either no vCont support, or we tried to use part of the vCont
- // packet that wasn't supported by the remote GDB server.
- // We need to try and make a simple packet that can do our continue
+ // Either no vCont support, or we tried to use part of the vCont packet
+ // that wasn't supported by the remote GDB server. We need to try and
+ // make a simple packet that can do our continue
const size_t num_continue_c_tids = m_continue_c_tids.size();
const size_t num_continue_C_tids = m_continue_C_tids.size();
const size_t num_continue_s_tids = m_continue_s_tids.size();
@@ -1394,11 +1386,10 @@ Status ProcessGDBRemote::DoResume() {
const int continue_signo = m_continue_C_tids.front().second;
// Only one thread is continuing
if (num_continue_C_tids > 1) {
- // More that one thread with a signal, yet we don't have
- // vCont support and we are being asked to resume each
- // thread with a signal, we need to make sure they are
- // all the same signal, or we can't issue the continue
- // accurately with the current support...
+ // More that one thread with a signal, yet we don't have vCont
+ // support and we are being asked to resume each thread with a
+ // signal, we need to make sure they are all the same signal, or we
+ // can't issue the continue accurately with the current support...
if (num_continue_C_tids > 1) {
continue_packet_error = false;
for (size_t i = 1; i < m_continue_C_tids.size(); ++i) {
@@ -1532,7 +1523,6 @@ void ProcessGDBRemote::ClearThreadIDList() {
size_t
ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue(std::string &value) {
m_thread_ids.clear();
- m_thread_pcs.clear();
size_t comma_pos;
lldb::tid_t tid;
while ((comma_pos = value.find(',')) != std::string::npos) {
@@ -1675,9 +1665,8 @@ bool ProcessGDBRemote::UpdateThreadList(ThreadList &old_thread_list,
}
}
- // Whatever that is left in old_thread_list_copy are not
- // present in new_thread_list. Remove non-existent threads from internal id
- // table.
+ // Whatever that is left in old_thread_list_copy are not present in
+ // new_thread_list. Remove non-existent threads from internal id table.
size_t old_num_thread_ids = old_thread_list_copy.GetSize(false);
for (size_t i = 0; i < old_num_thread_ids; i++) {
ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex(i, false));
@@ -1738,12 +1727,11 @@ bool ProcessGDBRemote::CalculateThreadStopInfo(ThreadGDBRemote *thread) {
return true;
// See if we got thread stop info for any threads valid stop info reasons
- // threads
- // via the "jstopinfo" packet stop reply packet key/value pair?
+ // threads via the "jstopinfo" packet stop reply packet key/value pair?
if (m_jstopinfo_sp) {
// If we have "jstopinfo" then we have stop descriptions for all threads
- // that have stop reasons, and if there is no entry for a thread, then
- // it has no stop reason.
+ // that have stop reasons, and if there is no entry for a thread, then it
+ // has no stop reason.
thread->GetRegisterContext()->InvalidateIfNeeded(true);
if (!GetThreadStopInfoFromJSON(thread, m_jstopinfo_sp)) {
thread->SetStopInfo(StopInfoSP());
@@ -1771,9 +1759,8 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
if (tid != LLDB_INVALID_THREAD_ID) {
// Scope for "locker" below
{
- // m_thread_list_real does have its own mutex, but we need to
- // hold onto the mutex between the call to
- // m_thread_list_real.FindThreadByID(...)
+ // m_thread_list_real does have its own mutex, but we need to hold onto
+ // the mutex between the call to m_thread_list_real.FindThreadByID(...)
// and the m_thread_list_real.AddThread(...) so it doesn't change on us
std::lock_guard<std::recursive_mutex> guard(
m_thread_list_real.GetMutex());
@@ -1827,10 +1814,9 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
if (!thread_sp->StopInfoIsUpToDate()) {
thread_sp->SetStopInfo(StopInfoSP());
// If there's a memory thread backed by this thread, we need to use it
- // to calcualte StopInfo.
- ThreadSP memory_thread_sp =
- m_thread_list.FindThreadByProtocolID(thread_sp->GetProtocolID());
- if (memory_thread_sp)
+ // to calculate StopInfo.
+ if (ThreadSP memory_thread_sp =
+ m_thread_list.GetBackingThread(thread_sp))
thread_sp = memory_thread_sp;
if (exc_type != 0) {
@@ -1852,9 +1838,9 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
->GetBreakpointSiteList()
.FindByAddress(pc);
- // If the current pc is a breakpoint site then the StopInfo should
- // be set to Breakpoint
- // Otherwise, it will be set to Trace.
+ // If the current pc is a breakpoint site then the StopInfo
+ // should be set to Breakpoint Otherwise, it will be set to
+ // Trace.
if (bp_site_sp &&
bp_site_sp->ValidForThisThread(thread_sp.get())) {
thread_sp->SetStopInfo(
@@ -1871,11 +1857,10 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
.FindByAddress(pc);
if (bp_site_sp) {
// If the breakpoint is for this thread, then we'll report the
- // hit, but if it is for another thread,
- // we can just report no reason. We don't need to worry about
- // stepping over the breakpoint here, that
- // will be taken care of when the thread resumes and notices
- // that there's a breakpoint under the pc.
+ // hit, but if it is for another thread, we can just report no
+ // reason. We don't need to worry about stepping over the
+ // breakpoint here, that will be taken care of when the thread
+ // resumes and notices that there's a breakpoint under the pc.
handled = true;
if (bp_site_sp->ValidForThisThread(thread_sp.get())) {
thread_sp->SetStopInfo(
@@ -1937,13 +1922,10 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
pc);
// If the current pc is a breakpoint site then the StopInfo should
- // be set to Breakpoint
- // even though the remote stub did not set it as such. This can
- // happen when
- // the thread is involuntarily interrupted (e.g. due to stops on
- // other
- // threads) just as it is about to execute the breakpoint
- // instruction.
+ // be set to Breakpoint even though the remote stub did not set it
+ // as such. This can happen when the thread is involuntarily
+ // interrupted (e.g. due to stops on other threads) just as it is
+ // about to execute the breakpoint instruction.
if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get())) {
thread_sp->SetStopInfo(
StopInfo::CreateStopReasonWithBreakpointSiteID(
@@ -1965,11 +1947,10 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
if (bp_site_sp) {
// If the breakpoint is for this thread, then we'll report the
- // hit, but if it is for another thread,
- // we can just report no reason. We don't need to worry about
- // stepping over the breakpoint here, that
- // will be taken care of when the thread resumes and notices
- // that there's a breakpoint under the pc.
+ // hit, but if it is for another thread, we can just report no
+ // reason. We don't need to worry about stepping over the
+ // breakpoint here, that will be taken care of when the thread
+ // resumes and notices that there's a breakpoint under the pc.
if (bp_site_sp->ValidForThisThread(thread_sp.get())) {
if (m_breakpoint_pc_offset != 0)
thread_sp->GetRegisterContext()->SetPC(pc);
@@ -1982,8 +1963,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
}
} else {
// If we were stepping then assume the stop was the result of
- // the trace. If we were
- // not stepping then report the SIGTRAP.
+ // the trace. If we were not stepping then report the SIGTRAP.
// FIXME: We are still missing the case where we single step
// over a trap instruction.
if (thread_sp->GetTemporaryResumeState() == eStateStepping)
@@ -2178,15 +2158,15 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
switch (stop_type) {
case 'T':
case 'S': {
- // This is a bit of a hack, but is is required. If we did exec, we
- // need to clear our thread lists and also know to rebuild our dynamic
- // register info before we lookup and threads and populate the expedited
- // register values so we need to know this right away so we can cleanup
- // and update our registers.
+ // This is a bit of a hack, but is is required. If we did exec, we need to
+ // clear our thread lists and also know to rebuild our dynamic register
+ // info before we lookup and threads and populate the expedited register
+ // values so we need to know this right away so we can cleanup and update
+ // our registers.
const uint32_t stop_id = GetStopID();
if (stop_id == 0) {
- // Our first stop, make sure we have a process ID, and also make
- // sure we know about our registers
+ // Our first stop, make sure we have a process ID, and also make sure we
+ // know about our registers
if (GetID() == LLDB_INVALID_PROCESS_ID) {
lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID();
if (pid != LLDB_INVALID_PROCESS_ID)
@@ -2232,8 +2212,7 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
m_thread_ids.clear();
// A comma separated list of all threads in the current
- // process that includes the thread for this stop reply
- // packet
+ // process that includes the thread for this stop reply packet
lldb::tid_t tid;
while (!value.empty()) {
llvm::StringRef tid_str;
@@ -2245,8 +2224,7 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
} else if (key.compare("thread-pcs") == 0) {
m_thread_pcs.clear();
// A comma separated list of all threads in the current
- // process that includes the thread for this stop reply
- // packet
+ // process that includes the thread for this stop reply packet
lldb::addr_t pc;
while (!value.empty()) {
llvm::StringRef pc_str;
@@ -2298,13 +2276,10 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
desc_extractor.GetHexByteString(description);
} else if (key.compare("memory") == 0) {
// Expedited memory. GDB servers can choose to send back expedited
- // memory
- // that can populate the L1 memory cache in the process so that things
- // like
- // the frame pointer backchain can be expedited. This will help stack
- // backtracing be more efficient by not having to send as many memory
- // read
- // requests down the remote GDB server.
+ // memory that can populate the L1 memory cache in the process so that
+ // things like the frame pointer backchain can be expedited. This will
+ // help stack backtracing be more efficient by not having to send as
+ // many memory read requests down the remote GDB server.
// Key/value pair format: memory:<addr>=<bytes>;
// <addr> is a number whose base will be interpreted by the prefix:
@@ -2356,7 +2331,8 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
if (tid == LLDB_INVALID_THREAD_ID) {
// A thread id may be invalid if the response is old style 'S' packet
// which does not provide the
- // thread information. So update the thread list and choose the first one.
+ // thread information. So update the thread list and choose the first
+ // one.
UpdateThreadIDList();
if (!m_thread_ids.empty()) {
@@ -2389,9 +2365,9 @@ void ProcessGDBRemote::RefreshStateAfterStop() {
m_thread_ids.clear();
m_thread_pcs.clear();
- // Set the thread stop info. It might have a "threads" key whose value is
- // a list of all thread IDs in the current process, so m_thread_ids might
- // get set.
+ // Set the thread stop info. It might have a "threads" key whose value is a
+ // list of all thread IDs in the current process, so m_thread_ids might get
+ // set.
// Scope for the lock
{
@@ -2422,8 +2398,8 @@ void ProcessGDBRemote::RefreshStateAfterStop() {
m_initial_tid = LLDB_INVALID_THREAD_ID;
}
- // Let all threads recover from stopping and do any clean up based
- // on the previous thread state (if any).
+ // Let all threads recover from stopping and do any clean up based on the
+ // previous thread state (if any).
m_thread_list_real.RefreshStateAfterStop();
}
@@ -2431,8 +2407,8 @@ Status ProcessGDBRemote::DoHalt(bool &caused_stop) {
Status error;
if (m_public_state.GetValue() == eStateAttaching) {
- // We are being asked to halt during an attach. We need to just close
- // our file handle and debugserver will go away, and we can be done...
+ // We are being asked to halt during an attach. We need to just close our
+ // file handle and debugserver will go away, and we can be done...
m_gdb_comm.Disconnect();
} else
caused_stop = m_gdb_comm.Interrupt();
@@ -2475,31 +2451,24 @@ Status ProcessGDBRemote::DoDestroy() {
log->Printf("ProcessGDBRemote::DoDestroy()");
// There is a bug in older iOS debugservers where they don't shut down the
- // process
- // they are debugging properly. If the process is sitting at a breakpoint or
- // an exception,
- // this can cause problems with restarting. So we check to see if any of our
- // threads are stopped
- // at a breakpoint, and if so we remove all the breakpoints, resume the
- // process, and THEN
- // destroy it again.
+ // process they are debugging properly. If the process is sitting at a
+ // breakpoint or an exception, this can cause problems with restarting. So
+ // we check to see if any of our threads are stopped at a breakpoint, and if
+ // so we remove all the breakpoints, resume the process, and THEN destroy it
+ // again.
//
// Note, we don't have a good way to test the version of debugserver, but I
- // happen to know that
- // the set of all the iOS debugservers which don't support
- // GetThreadSuffixSupported() and that of
- // the debugservers with this bug are equal. There really should be a better
- // way to test this!
+ // happen to know that the set of all the iOS debugservers which don't
+ // support GetThreadSuffixSupported() and that of the debugservers with this
+ // bug are equal. There really should be a better way to test this!
//
// We also use m_destroy_tried_resuming to make sure we only do this once, if
- // we resume and then halt and
- // get called here to destroy again and we're still at a breakpoint or
- // exception, then we should
- // just do the straight-forward kill.
+ // we resume and then halt and get called here to destroy again and we're
+ // still at a breakpoint or exception, then we should just do the straight-
+ // forward kill.
//
// And of course, if we weren't able to stop the process by the time we get
- // here, it isn't
- // necessary (or helpful) to do any of this.
+ // here, it isn't necessary (or helpful) to do any of this.
if (!m_gdb_comm.GetThreadSuffixSupported() &&
m_public_state.GetValue() != eStateRunning) {
@@ -2514,9 +2483,8 @@ Status ProcessGDBRemote::DoDestroy() {
"destroy once already, not doing it again.");
} else {
// At present, the plans are discarded and the breakpoints disabled
- // Process::Destroy,
- // but we really need it to happen here and it doesn't matter if we do
- // it twice.
+ // Process::Destroy, but we really need it to happen here and it
+ // doesn't matter if we do it twice.
m_thread_list.DiscardThreadPlans();
DisableAllBreakpointSites();
@@ -2553,12 +2521,11 @@ Status ProcessGDBRemote::DoDestroy() {
m_destroy_tried_resuming = true;
// If we are going to run again before killing, it would be good to
- // suspend all the threads
- // before resuming so they won't get into more trouble. Sadly, for
- // the threads stopped with
- // the breakpoint or exception, the exception doesn't get cleared if
- // it is suspended, so we do
- // have to run the risk of letting those threads proceed a bit.
+ // suspend all the threads before resuming so they won't get into
+ // more trouble. Sadly, for the threads stopped with the breakpoint
+ // or exception, the exception doesn't get cleared if it is
+ // suspended, so we do have to run the risk of letting those threads
+ // proceed a bit.
{
std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
@@ -2605,17 +2572,14 @@ Status ProcessGDBRemote::DoDestroy() {
if (packet_cmd == 'W' || packet_cmd == 'X') {
#if defined(__APPLE__)
// For Native processes on Mac OS X, we launch through the Host
- // Platform, then hand the process off
- // to debugserver, which becomes the parent process through
- // "PT_ATTACH". Then when we go to kill
- // the process on Mac OS X we call ptrace(PT_KILL) to kill it, then we
- // call waitpid which returns
- // with no error and the correct status. But amusingly enough that
- // doesn't seem to actually reap
+ // Platform, then hand the process off to debugserver, which becomes
+ // the parent process through "PT_ATTACH". Then when we go to kill
+ // the process on Mac OS X we call ptrace(PT_KILL) to kill it, then
+ // we call waitpid which returns with no error and the correct
+ // status. But amusingly enough that doesn't seem to actually reap
// the process, but instead it is left around as a Zombie. Probably
- // the kernel is in the process of
- // switching ownership back to lldb which was the original parent, and
- // gets confused in the handoff.
+ // the kernel is in the process of switching ownership back to lldb
+ // which was the original parent, and gets confused in the handoff.
// Anyway, so call waitpid here to finally reap it.
PlatformSP platform_sp(GetTarget().GetPlatform());
if (platform_sp && platform_sp->IsHost()) {
@@ -2687,9 +2651,8 @@ void ProcessGDBRemote::SetLastStopPacket(
if (GetTarget().GetNonStopModeEnabled() == false)
m_stop_packet_stack.clear();
- // Add this stop packet to the stop packet stack
- // This stack will get popped and examined when we switch to the
- // Stopped state
+ // Add this stop packet to the stop packet stack This stack will get popped
+ // and examined when we switch to the Stopped state
m_stop_packet_stack.push_back(response);
}
}
@@ -2721,12 +2684,11 @@ addr_t ProcessGDBRemote::GetImageInfoAddress() {
}
void ProcessGDBRemote::WillPublicStop() {
- // See if the GDB remote client supports the JSON threads info.
- // If so, we gather stop info for all threads, expedited registers,
- // expedited memory, runtime queue information (iOS and MacOSX only),
- // and more. Expediting memory will help stack backtracing be much
- // faster. Expediting registers will make sure we don't have to read
- // the thread registers for GPRs.
+ // See if the GDB remote client supports the JSON threads info. If so, we
+ // gather stop info for all threads, expedited registers, expedited memory,
+ // runtime queue information (iOS and MacOSX only), and more. Expediting
+ // memory will help stack backtracing be much faster. Expediting registers
+ // will make sure we don't have to read the thread registers for GPRs.
m_jthreadsinfo_sp = m_gdb_comm.GetThreadsInfo();
if (m_jthreadsinfo_sp) {
@@ -2776,14 +2738,13 @@ size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size,
error.Clear();
if (binary_memory_read) {
// The lower level GDBRemoteCommunication packet receive layer has
- // already de-quoted any
- // 0x7d character escaping that was present in the packet
+ // already de-quoted any 0x7d character escaping that was present in
+ // the packet
size_t data_received_size = response.GetBytesLeft();
if (data_received_size > size) {
// Don't write past the end of BUF if the remote debug server gave us
- // too
- // much data for some reason.
+ // too much data for some reason.
data_received_size = size;
}
memcpy(buf, response.GetStringRef().data(), data_received_size);
@@ -2807,6 +2768,145 @@ size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size,
return 0;
}
+Status ProcessGDBRemote::WriteObjectFile(
+ std::vector<ObjectFile::LoadableData> entries) {
+ Status error;
+ // Sort the entries by address because some writes, like those to flash
+ // memory, must happen in order of increasing address.
+ std::stable_sort(
+ std::begin(entries), std::end(entries),
+ [](const ObjectFile::LoadableData a, const ObjectFile::LoadableData b) {
+ return a.Dest < b.Dest;
+ });
+ m_allow_flash_writes = true;
+ error = Process::WriteObjectFile(entries);
+ if (error.Success())
+ error = FlashDone();
+ else
+ // Even though some of the writing failed, try to send a flash done if some
+ // of the writing succeeded so the flash state is reset to normal, but
+ // don't stomp on the error status that was set in the write failure since
+ // that's the one we want to report back.
+ FlashDone();
+ m_allow_flash_writes = false;
+ return error;
+}
+
+bool ProcessGDBRemote::HasErased(FlashRange range) {
+ auto size = m_erased_flash_ranges.GetSize();
+ for (size_t i = 0; i < size; ++i)
+ if (m_erased_flash_ranges.GetEntryAtIndex(i)->Contains(range))
+ return true;
+ return false;
+}
+
+Status ProcessGDBRemote::FlashErase(lldb::addr_t addr, size_t size) {
+ Status status;
+
+ MemoryRegionInfo region;
+ status = GetMemoryRegionInfo(addr, region);
+ if (!status.Success())
+ return status;
+
+ // The gdb spec doesn't say if erasures are allowed across multiple regions,
+ // but we'll disallow it to be safe and to keep the logic simple by worring
+ // about only one region's block size. DoMemoryWrite is this function's
+ // primary user, and it can easily keep writes within a single memory region
+ if (addr + size > region.GetRange().GetRangeEnd()) {
+ status.SetErrorString("Unable to erase flash in multiple regions");
+ return status;
+ }
+
+ uint64_t blocksize = region.GetBlocksize();
+ if (blocksize == 0) {
+ status.SetErrorString("Unable to erase flash because blocksize is 0");
+ return status;
+ }
+
+ // Erasures can only be done on block boundary adresses, so round down addr
+ // and round up size
+ lldb::addr_t block_start_addr = addr - (addr % blocksize);
+ size += (addr - block_start_addr);
+ if ((size % blocksize) != 0)
+ size += (blocksize - size % blocksize);
+
+ FlashRange range(block_start_addr, size);
+
+ if (HasErased(range))
+ return status;
+
+ // We haven't erased the entire range, but we may have erased part of it.
+ // (e.g., block A is already erased and range starts in A and ends in B). So,
+ // adjust range if necessary to exclude already erased blocks.
+ if (!m_erased_flash_ranges.IsEmpty()) {
+ // Assuming that writes and erasures are done in increasing addr order,
+ // because that is a requirement of the vFlashWrite command. Therefore, we
+ // only need to look at the last range in the list for overlap.
+ const auto &last_range = *m_erased_flash_ranges.Back();
+ if (range.GetRangeBase() < last_range.GetRangeEnd()) {
+ auto overlap = last_range.GetRangeEnd() - range.GetRangeBase();
+ // overlap will be less than range.GetByteSize() or else HasErased()
+ // would have been true
+ range.SetByteSize(range.GetByteSize() - overlap);
+ range.SetRangeBase(range.GetRangeBase() + overlap);
+ }
+ }
+
+ StreamString packet;
+ packet.Printf("vFlashErase:%" PRIx64 ",%" PRIx64, range.GetRangeBase(),
+ (uint64_t)range.GetByteSize());
+
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
+ true) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ if (response.IsOKResponse()) {
+ m_erased_flash_ranges.Insert(range, true);
+ } else {
+ if (response.IsErrorResponse())
+ status.SetErrorStringWithFormat("flash erase failed for 0x%" PRIx64,
+ addr);
+ else if (response.IsUnsupportedResponse())
+ status.SetErrorStringWithFormat("GDB server does not support flashing");
+ else
+ status.SetErrorStringWithFormat(
+ "unexpected response to GDB server flash erase packet '%s': '%s'",
+ packet.GetData(), response.GetStringRef().c_str());
+ }
+ } else {
+ status.SetErrorStringWithFormat("failed to send packet: '%s'",
+ packet.GetData());
+ }
+ return status;
+}
+
+Status ProcessGDBRemote::FlashDone() {
+ Status status;
+ // If we haven't erased any blocks, then we must not have written anything
+ // either, so there is no need to actually send a vFlashDone command
+ if (m_erased_flash_ranges.IsEmpty())
+ return status;
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.SendPacketAndWaitForResponse("vFlashDone", response, true) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ if (response.IsOKResponse()) {
+ m_erased_flash_ranges.Clear();
+ } else {
+ if (response.IsErrorResponse())
+ status.SetErrorStringWithFormat("flash done failed");
+ else if (response.IsUnsupportedResponse())
+ status.SetErrorStringWithFormat("GDB server does not support flashing");
+ else
+ status.SetErrorStringWithFormat(
+ "unexpected response to GDB server flash done packet: '%s'",
+ response.GetStringRef().c_str());
+ }
+ } else {
+ status.SetErrorStringWithFormat("failed to send flash done packet");
+ }
+ return status;
+}
+
size_t ProcessGDBRemote::DoWriteMemory(addr_t addr, const void *buf,
size_t size, Status &error) {
GetMaxMemorySize();
@@ -2819,10 +2919,33 @@ size_t ProcessGDBRemote::DoWriteMemory(addr_t addr, const void *buf,
size = max_memory_size;
}
- StreamString packet;
- packet.Printf("M%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size);
- packet.PutBytesAsRawHex8(buf, size, endian::InlHostByteOrder(),
- endian::InlHostByteOrder());
+ StreamGDBRemote packet;
+
+ MemoryRegionInfo region;
+ Status region_status = GetMemoryRegionInfo(addr, region);
+
+ bool is_flash =
+ region_status.Success() && region.GetFlash() == MemoryRegionInfo::eYes;
+
+ if (is_flash) {
+ if (!m_allow_flash_writes) {
+ error.SetErrorString("Writing to flash memory is not allowed");
+ return 0;
+ }
+ // Keep the write within a flash memory region
+ if (addr + size > region.GetRange().GetRangeEnd())
+ size = region.GetRange().GetRangeEnd() - addr;
+ // Flash memory must be erased before it can be written
+ error = FlashErase(addr, size);
+ if (!error.Success())
+ return 0;
+ packet.Printf("vFlashWrite:%" PRIx64 ":", addr);
+ packet.PutEscapedBytes(buf, size);
+ } else {
+ packet.Printf("M%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size);
+ packet.PutBytesAsRawHex8(buf, size, endian::InlHostByteOrder(),
+ endian::InlHostByteOrder());
+ }
StringExtractorGDBRemote response;
if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
true) ==
@@ -2918,8 +3041,8 @@ Status ProcessGDBRemote::DoDeallocateMemory(lldb::addr_t addr) {
switch (supported) {
case eLazyBoolCalculate:
- // We should never be deallocating memory without allocating memory
- // first so we should never get eLazyBoolCalculate
+ // We should never be deallocating memory without allocating memory first
+ // so we should never get eLazyBoolCalculate
error.SetErrorString(
"tried to deallocate memory without ever allocating memory");
break;
@@ -2991,18 +3114,14 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) {
const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site);
// SupportsGDBStoppointPacket() simply checks a boolean, indicating if this
- // breakpoint type
- // is supported by the remote stub. These are set to true by default, and
- // later set to false
- // only after we receive an unimplemented response when sending a breakpoint
- // packet. This means
- // initially that unless we were specifically instructed to use a hardware
- // breakpoint, LLDB will
- // attempt to set a software breakpoint. HardwareRequired() also queries a
- // boolean variable which
- // indicates if the user specifically asked for hardware breakpoints. If true
- // then we will
- // skip over software breakpoints.
+ // breakpoint type is supported by the remote stub. These are set to true by
+ // default, and later set to false only after we receive an unimplemented
+ // response when sending a breakpoint packet. This means initially that
+ // unless we were specifically instructed to use a hardware breakpoint, LLDB
+ // will attempt to set a software breakpoint. HardwareRequired() also queries
+ // a boolean variable which indicates if the user specifically asked for
+ // hardware breakpoints. If true then we will skip over software
+ // breakpoints.
if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware) &&
(!bp_site->HardwareRequired())) {
// Try to send off a software breakpoint packet ($Z0)
@@ -3015,19 +3134,14 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) {
return error;
}
- // SendGDBStoppointTypePacket() will return an error if it was unable to set
- // this
- // breakpoint. We need to differentiate between a error specific to placing
- // this breakpoint
- // or if we have learned that this breakpoint type is unsupported. To do
- // this, we
- // must test the support boolean for this breakpoint type to see if it now
- // indicates that
- // this breakpoint type is unsupported. If they are still supported then we
- // should return
+ // SendGDBStoppointTypePacket() will return an error if it was unable to
+ // set this breakpoint. We need to differentiate between a error specific
+ // to placing this breakpoint or if we have learned that this breakpoint
+ // type is unsupported. To do this, we must test the support boolean for
+ // this breakpoint type to see if it now indicates that this breakpoint
+ // type is unsupported. If they are still supported then we should return
// with the error code. If they are now unsupported, then we would like to
- // fall through
- // and try another form of breakpoint.
+ // fall through and try another form of breakpoint.
if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware)) {
if (error_no != UINT8_MAX)
error.SetErrorStringWithFormat(
@@ -3038,21 +3152,18 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) {
}
// We reach here when software breakpoints have been found to be
- // unsupported. For future
- // calls to set a breakpoint, we will not attempt to set a breakpoint with a
- // type that is
- // known not to be supported.
+ // unsupported. For future calls to set a breakpoint, we will not attempt
+ // to set a breakpoint with a type that is known not to be supported.
if (log)
log->Printf("Software breakpoints are unsupported");
// So we will fall through and try a hardware breakpoint
}
- // The process of setting a hardware breakpoint is much the same as above. We
- // check the
- // supported boolean for this breakpoint type, and if it is thought to be
- // supported then we
- // will try to set this breakpoint with a hardware breakpoint.
+ // The process of setting a hardware breakpoint is much the same as above.
+ // We check the supported boolean for this breakpoint type, and if it is
+ // thought to be supported then we will try to set this breakpoint with a
+ // hardware breakpoint.
if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) {
// Try to send off a hardware breakpoint packet ($Z1)
uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(
@@ -3094,8 +3205,8 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) {
return error;
}
- // As a last resort we want to place a manual breakpoint. An instruction
- // is placed into the process memory using memory write packets.
+ // As a last resort we want to place a manual breakpoint. An instruction is
+ // placed into the process memory using memory write packets.
return EnableSoftwareBreakpoint(bp_site);
}
@@ -3225,10 +3336,9 @@ Status ProcessGDBRemote::DisableWatchpoint(Watchpoint *wp, bool notify) {
log->Printf("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64
") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)",
watchID, (uint64_t)addr);
- // See also 'class WatchpointSentry' within StopInfo.cpp.
- // This disabling attempt might come from the user-supplied actions, we'll
- // route it in order for
- // the watchpoint object to intelligently process this action.
+ // See also 'class WatchpointSentry' within StopInfo.cpp. This disabling
+ // attempt might come from the user-supplied actions, we'll route it in
+ // order for the watchpoint object to intelligently process this action.
wp->SetEnabled(false, notify);
return error;
}
@@ -3313,8 +3423,8 @@ Status ProcessGDBRemote::LaunchAndConnectToDebugserver(
static FileSpec g_debugserver_file_spec;
ProcessLaunchInfo debugserver_launch_info;
- // Make debugserver run in its own session so signals generated by
- // special terminal key sequences (^C) don't affect debugserver.
+ // Make debugserver run in its own session so signals generated by special
+ // terminal key sequences (^C) don't affect debugserver.
debugserver_launch_info.SetLaunchInSeparateProcessGroup(true);
const std::weak_ptr<ProcessGDBRemote> this_wp =
@@ -3325,27 +3435,22 @@ Status ProcessGDBRemote::LaunchAndConnectToDebugserver(
int communication_fd = -1;
#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
- // Auto close the sockets we might open up unless everything goes OK. This
- // helps us not leak file descriptors when things go wrong.
- lldb_utility::CleanUp<int, int> our_socket(-1, -1, close);
- lldb_utility::CleanUp<int, int> gdb_socket(-1, -1, close);
-
// Use a socketpair on non-Windows systems for security and performance
// reasons.
- {
- int sockets[2]; /* the pair of socket descriptors */
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) {
- error.SetErrorToErrno();
- return error;
- }
-
- our_socket.set(sockets[0]);
- gdb_socket.set(sockets[1]);
+ int sockets[2]; /* the pair of socket descriptors */
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) {
+ error.SetErrorToErrno();
+ return error;
}
+ int our_socket = sockets[0];
+ int gdb_socket = sockets[1];
+ CleanUp cleanup_our(close, our_socket);
+ CleanUp cleanup_gdb(close, gdb_socket);
+
// Don't let any child processes inherit our communication socket
- SetCloexecFlag(our_socket.get());
- communication_fd = gdb_socket.get();
+ SetCloexecFlag(our_socket);
+ communication_fd = gdb_socket;
#endif
error = m_gdb_comm.StartDebugserverProcess(
@@ -3359,10 +3464,10 @@ Status ProcessGDBRemote::LaunchAndConnectToDebugserver(
if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID) {
#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
- // Our process spawned correctly, we can now set our connection to use our
- // end of the socket pair
- m_gdb_comm.SetConnection(
- new ConnectionFileDescriptor(our_socket.release(), true));
+ // Our process spawned correctly, we can now set our connection to use
+ // our end of the socket pair
+ cleanup_our.disable();
+ m_gdb_comm.SetConnection(new ConnectionFileDescriptor(our_socket, true));
#endif
StartAsyncThread();
}
@@ -3377,9 +3482,9 @@ Status ProcessGDBRemote::LaunchAndConnectToDebugserver(
}
if (m_gdb_comm.IsConnected()) {
- // Finish the connection process by doing the handshake without connecting
- // (send NULL URL)
- ConnectToDebugserver("");
+ // Finish the connection process by doing the handshake without
+ // connecting (send NULL URL)
+ error = ConnectToDebugserver("");
} else {
error.SetErrorString("connection failed");
}
@@ -3393,8 +3498,8 @@ bool ProcessGDBRemote::MonitorDebugserverProcess(
int signo, // Zero for no signal
int exit_status // Exit value of process if signal is zero
) {
- // "debugserver_pid" argument passed in is the process ID for
- // debugserver that we are tracking...
+ // "debugserver_pid" argument passed in is the process ID for debugserver
+ // that we are tracking...
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
const bool handled = true;
@@ -3410,12 +3515,12 @@ bool ProcessGDBRemote::MonitorDebugserverProcess(
if (!process_sp || process_sp->m_debugserver_pid != debugserver_pid)
return handled;
- // Sleep for a half a second to make sure our inferior process has
- // time to set its exit status before we set it incorrectly when
- // both the debugserver and the inferior process shut down.
+ // Sleep for a half a second to make sure our inferior process has time to
+ // set its exit status before we set it incorrectly when both the debugserver
+ // and the inferior process shut down.
usleep(500000);
- // If our process hasn't yet exited, debugserver might have died.
- // If the process did exit, then we are reaping it.
+ // If our process hasn't yet exited, debugserver might have died. If the
+ // process did exit, then we are reaping it.
const StateType state = process_sp->GetState();
if (state != eStateInvalid && state != eStateUnloaded &&
@@ -3438,8 +3543,8 @@ bool ProcessGDBRemote::MonitorDebugserverProcess(
process_sp->SetExitStatus(-1, error_str);
}
- // Debugserver has exited we need to let our ProcessGDBRemote
- // know that it no longer has a debugserver instance
+ // Debugserver has exited we need to let our ProcessGDBRemote know that it no
+ // longer has a debugserver instance
process_sp->m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
return handled;
}
@@ -3529,10 +3634,9 @@ bool ProcessGDBRemote::HandleNotifyPacket(StringExtractorGDBRemote &packet) {
// check for more stop reasons
HandleStopReplySequence();
- // if the process is stopped then we need to fake a resume
- // so that we can stop properly with the new break. This
- // is possible due to SetPrivateState() broadcasting the
- // state change as a side effect.
+ // if the process is stopped then we need to fake a resume so that we can
+ // stop properly with the new break. This is possible due to
+ // SetPrivateState() broadcasting the state change as a side effect.
if (GetPrivateState() == lldb::StateType::eStateStopped) {
SetPrivateState(lldb::StateType::eStateRunning);
}
@@ -3605,12 +3709,11 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) {
response);
// We need to immediately clear the thread ID list so we are sure
- // to get a valid list of threads.
- // The thread ID list might be contained within the "response", or
- // the stop reply packet that
+ // to get a valid list of threads. The thread ID list might be
+ // contained within the "response", or the stop reply packet that
// caused the stop. So clear it now before we give the stop reply
- // packet to the process
- // using the process->SetLastStopPacket()...
+ // packet to the process using the
+ // process->SetLastStopPacket()...
process->ClearThreadIDList();
switch (stop_state) {
@@ -3647,17 +3750,14 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) {
// Check to see if we were trying to attach and if we got back
// the "E87" error code from debugserver -- this indicates that
// the process is not debuggable. Return a slightly more
- // helpful
- // error message about why the attach failed.
+ // helpful error message about why the attach failed.
if (::strstr(continue_cstr, "vAttach") != NULL &&
response.GetError() == 0x87) {
process->SetExitStatus(-1, "cannot attach to process due to "
"System Integrity Protection");
- }
- // E01 code from vAttach means that the attach failed
- if (::strstr(continue_cstr, "vAttach") != NULL &&
- response.GetError() == 0x1) {
- process->SetExitStatus(-1, "unable to attach");
+ } else if (::strstr(continue_cstr, "vAttach") != NULL &&
+ response.GetStatus().Fail()) {
+ process->SetExitStatus(-1, response.GetStatus().AsCString());
} else {
process->SetExitStatus(-1, "lost connection");
}
@@ -3769,8 +3869,8 @@ Status ProcessGDBRemote::UpdateAutomaticSignalFiltering() {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
LLDB_LOG(log, "Check if need to update ignored signals");
- // QPassSignals package is not supported by the server,
- // there is no way we can ignore any signals on server side.
+ // QPassSignals package is not supported by the server, there is no way we
+ // can ignore any signals on server side.
if (!m_gdb_comm.GetQPassSignalsSupported())
return Status();
@@ -3894,9 +3994,9 @@ ProcessGDBRemote::GetExtendedInfoForThread(lldb::tid_t tid) {
// FIXME the final character of a JSON dictionary, '}', is the escape
// character in gdb-remote binary mode. lldb currently doesn't escape
- // these characters in its packet output -- so we add the quoted version
- // of the } character here manually in case we talk to a debugserver which
- // un-escapes the characters at packet read time.
+ // these characters in its packet output -- so we add the quoted version of
+ // the } character here manually in case we talk to a debugserver which un-
+ // escapes the characters at packet read time.
packet << (char)(0x7d ^ 0x20);
StringExtractorGDBRemote response;
@@ -3966,9 +4066,9 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos_sender(
// FIXME the final character of a JSON dictionary, '}', is the escape
// character in gdb-remote binary mode. lldb currently doesn't escape
- // these characters in its packet output -- so we add the quoted version
- // of the } character here manually in case we talk to a debugserver which
- // un-escapes the characters at packet read time.
+ // these characters in its packet output -- so we add the quoted version of
+ // the } character here manually in case we talk to a debugserver which un-
+ // escapes the characters at packet read time.
packet << (char)(0x7d ^ 0x20);
StringExtractorGDBRemote response;
@@ -3999,9 +4099,9 @@ StructuredData::ObjectSP ProcessGDBRemote::GetSharedCacheInfo() {
// FIXME the final character of a JSON dictionary, '}', is the escape
// character in gdb-remote binary mode. lldb currently doesn't escape
- // these characters in its packet output -- so we add the quoted version
- // of the } character here manually in case we talk to a debugserver which
- // un-escapes the characters at packet read time.
+ // these characters in its packet output -- so we add the quoted version of
+ // the } character here manually in case we talk to a debugserver which un-
+ // escapes the characters at packet read time.
packet << (char)(0x7d ^ 0x20);
StringExtractorGDBRemote response;
@@ -4026,14 +4126,14 @@ Status ProcessGDBRemote::ConfigureStructuredData(
return m_gdb_comm.ConfigureRemoteStructuredData(type_name, config_sp);
}
-// Establish the largest memory read/write payloads we should use.
-// If the remote stub has a max packet size, stay under that size.
+// Establish the largest memory read/write payloads we should use. If the
+// remote stub has a max packet size, stay under that size.
//
-// If the remote stub's max packet size is crazy large, use a
-// reasonable largeish default.
+// If the remote stub's max packet size is crazy large, use a reasonable
+// largeish default.
//
-// If the remote stub doesn't advertise a max packet size, use a
-// conservative default.
+// If the remote stub doesn't advertise a max packet size, use a conservative
+// default.
void ProcessGDBRemote::GetMaxMemorySize() {
const uint64_t reasonable_largeish_default = 128 * 1024;
@@ -4045,15 +4145,15 @@ void ProcessGDBRemote::GetMaxMemorySize() {
// Save the stub's claimed maximum packet size
m_remote_stub_max_memory_size = stub_max_size;
- // Even if the stub says it can support ginormous packets,
- // don't exceed our reasonable largeish default packet size.
+ // Even if the stub says it can support ginormous packets, don't exceed
+ // our reasonable largeish default packet size.
if (stub_max_size > reasonable_largeish_default) {
stub_max_size = reasonable_largeish_default;
}
- // Memory packet have other overheads too like Maddr,size:#NN
- // Instead of calculating the bytes taken by size and addr every
- // time, we take a maximum guess here.
+ // Memory packet have other overheads too like Maddr,size:#NN Instead of
+ // calculating the bytes taken by size and addr every time, we take a
+ // maximum guess here.
if (stub_max_size > 70)
stub_max_size -= 32 + 32 + 6;
else {
@@ -4140,13 +4240,8 @@ void ProcessGDBRemote::PrefetchModuleSpecs(
}
}
-bool ProcessGDBRemote::GetHostOSVersion(uint32_t &major, uint32_t &minor,
- uint32_t &update) {
- if (m_gdb_comm.GetOSVersion(major, minor, update))
- return true;
- // We failed to get the host OS version, defer to the base
- // implementation to correctly invalidate the arguments.
- return Process::GetHostOSVersion(major, minor, update);
+llvm::VersionTuple ProcessGDBRemote::GetHostOSVersion() {
+ return m_gdb_comm.GetOSVersion();
}
namespace {
@@ -4237,7 +4332,7 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info,
} else if (name == "format") {
format_set = true;
Format format = eFormatInvalid;
- if (Args::StringToFormat(value.data(), format, NULL).Success())
+ if (OptionArgParser::ToFormat(value.data(), format, NULL).Success())
reg_info.format = format;
else if (value == "vector-sint8")
reg_info.format = eFormatVectorOfSInt8;
@@ -4311,8 +4406,8 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info,
}
// Only update the register set name if we didn't get a "reg_set"
+ // attribute. "set_name" will be empty if we didn't have a "reg_set"
// attribute.
- // "set_name" will be empty if we didn't have a "reg_set" attribute.
if (!set_name && !gdb_group.empty())
set_name.SetCString(gdb_group.c_str());
@@ -4339,8 +4434,8 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info,
} // namespace {}
-// query the target of gdb-remote for extended target information
-// return: 'true' on success
+// query the target of gdb-remote for extended target information return:
+// 'true' on success
// 'false' on failure
bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) {
// Make sure LLDB has an XML parser it can use first
@@ -4409,15 +4504,27 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) {
return true; // Keep iterating through all children of the target_node
});
+ // If the target.xml includes an architecture entry like
+ // <architecture>i386:x86-64</architecture> (seen from VMWare ESXi)
+ // <architecture>arm</architecture> (seen from Segger JLink on unspecified arm board)
+ // use that if we don't have anything better.
+ if (!arch_to_use.IsValid() && !target_info.arch.empty()) {
+ if (target_info.arch == "i386:x86-64")
+ {
+ // We don't have any information about vendor or OS.
+ arch_to_use.SetTriple("x86_64--");
+ GetTarget().MergeArchitecture(arch_to_use);
+ }
+ }
+
// Initialize these outside of ParseRegisters, since they should not be
// reset inside each include feature
uint32_t cur_reg_num = 0;
uint32_t reg_offset = 0;
- // Don't use Process::GetABI, this code gets called from DidAttach, and in
- // that context we haven't
- // set the Target's architecture yet, so the ABI is also potentially
- // incorrect.
+ // Don't use Process::GetABI, this code gets called from DidAttach, and
+ // in that context we haven't set the Target's architecture yet, so the
+ // ABI is also potentially incorrect.
ABISP abi_to_use_sp = ABI::FindPlugin(shared_from_this(), arch_to_use);
for (auto &feature_node : feature_nodes) {
ParseRegisters(feature_node, target_info, this->m_register_info,
@@ -4758,8 +4865,8 @@ void ProcessGDBRemote::ModulesDidLoad(ModuleList &module_list) {
// do anything
Process::ModulesDidLoad(module_list);
- // After loading shared libraries, we can ask our remote GDB server if
- // it needs any symbols.
+ // After loading shared libraries, we can ask our remote GDB server if it
+ // needs any symbols.
m_gdb_comm.ServeSymbolLookups(this);
}
@@ -4817,8 +4924,8 @@ std::string ProcessGDBRemote::HarmonizeThreadIdsForProfileData(
has_used_usec = true;
usec_value.getAsInteger(0, curr_used_usec);
} else {
- // We didn't find what we want, it is probably
- // an older version. Bail out.
+ // We didn't find what we want, it is probably an older version. Bail
+ // out.
profileDataExtractor.SetFilePos(input_file_pos);
}
}
@@ -4840,8 +4947,8 @@ std::string ProcessGDBRemote::HarmonizeThreadIdsForProfileData(
((real_used_usec > 0) || (HasAssignedIndexIDToThread(thread_id)));
if (good_first_time || good_subsequent_time) {
- // We try to avoid doing too many index id reservation,
- // resulting in fast increase of index ids.
+ // We try to avoid doing too many index id reservation, resulting in
+ // fast increase of index ids.
output_stream << name << ":";
int32_t index_id = AssignIndexIDToThread(thread_id);
@@ -4892,7 +4999,7 @@ ParseStructuredDataPacket(llvm::StringRef packet) {
if (!packet.consume_front(s_async_json_packet_prefix)) {
if (log) {
log->Printf(
- "GDBRemoteCommmunicationClientBase::%s() received $J packet "
+ "GDBRemoteCommunicationClientBase::%s() received $J packet "
"but was not a StructuredData packet: packet starts with "
"%s",
__FUNCTION__,
@@ -4901,8 +5008,7 @@ ParseStructuredDataPacket(llvm::StringRef packet) {
return StructuredData::ObjectSP();
}
- // This is an asynchronous JSON packet, destined for a
- // StructuredDataPlugin.
+ // This is an asynchronous JSON packet, destined for a StructuredDataPlugin.
StructuredData::ObjectSP json_sp = StructuredData::ParseJSON(packet);
if (log) {
if (json_sp) {
@@ -5137,8 +5243,9 @@ public:
~CommandObjectProcessGDBRemotePacketMonitor() {}
- bool DoExecute(const char *command, CommandReturnObject &result) override {
- if (command == NULL || command[0] == '\0') {
+ bool DoExecute(llvm::StringRef command,
+ CommandReturnObject &result) override {
+ if (command.empty()) {
result.AppendErrorWithFormat("'%s' takes a command string argument",
m_cmd_name.c_str());
result.SetStatus(eReturnStatusFailed);
@@ -5150,14 +5257,15 @@ public:
if (process) {
StreamString packet;
packet.PutCString("qRcmd,");
- packet.PutBytesAsRawHex8(command, strlen(command));
+ packet.PutBytesAsRawHex8(command.data(), command.size());
bool send_async = true;
StringExtractorGDBRemote response;
- process->GetGDBRemote().SendPacketAndWaitForResponse(
- packet.GetString(), response, send_async);
- result.SetStatus(eReturnStatusSuccessFinishResult);
Stream &output_strm = result.GetOutputStream();
+ process->GetGDBRemote().SendPacketAndReceiveResponseWithOutputSupport(
+ packet.GetString(), response, send_async,
+ [&output_strm](llvm::StringRef output) { output_strm << output; });
+ result.SetStatus(eReturnStatusSuccessFinishResult);
output_strm.Printf(" packet: %s\n", packet.GetData());
const std::string &response_str = response.GetStringRef();
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 42d1c4ecd6663..45bb2d4c28e71 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -144,6 +144,9 @@ public:
size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
Status &error) override;
+ Status
+ WriteObjectFile(std::vector<ObjectFile::LoadableData> entries) override;
+
size_t DoWriteMemory(lldb::addr_t addr, const void *buf, size_t size,
Status &error) override;
@@ -214,8 +217,7 @@ public:
void PrefetchModuleSpecs(llvm::ArrayRef<FileSpec> module_file_specs,
const llvm::Triple &triple) override;
- bool GetHostOSVersion(uint32_t &major, uint32_t &minor,
- uint32_t &update) override;
+ llvm::VersionTuple GetHostOSVersion() override;
size_t LoadModules(LoadedModuleInfoList &module_list) override;
@@ -302,6 +304,11 @@ protected:
int64_t m_breakpoint_pc_offset;
lldb::tid_t m_initial_tid; // The initial thread ID, given by stub on attach
+ bool m_allow_flash_writes;
+ using FlashRangeVector = lldb_private::RangeVector<lldb::addr_t, size_t>;
+ using FlashRange = FlashRangeVector::Entry;
+ FlashRangeVector m_erased_flash_ranges;
+
//----------------------------------------------------------------------
// Accessors
//----------------------------------------------------------------------
@@ -408,6 +415,12 @@ protected:
Status UpdateAutomaticSignalFiltering() override;
+ Status FlashErase(lldb::addr_t addr, size_t size);
+
+ Status FlashDone();
+
+ bool HasErased(FlashRange range);
+
private:
//------------------------------------------------------------------
// For ProcessGDBRemote only
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index 27dd03bfc7bc5..a525c16b9f135 100644
--- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -24,7 +24,7 @@
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
-#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
using namespace lldb;
using namespace lldb_private;
@@ -55,7 +55,7 @@ ThreadGDBRemote::~ThreadGDBRemote() {
const char *ThreadGDBRemote::GetName() {
if (m_thread_name.empty())
- return NULL;
+ return nullptr;
return m_thread_name.c_str();
}
@@ -80,10 +80,9 @@ void ThreadGDBRemote::SetQueueInfo(std::string &&queue_name,
const char *ThreadGDBRemote::GetQueueName() {
// If our cached queue info is valid, then someone called
- // ThreadGDBRemote::SetQueueInfo(...)
- // with valid information that was gleaned from the stop reply packet. In this
- // case we trust
- // that the info is valid in m_dispatch_queue_name without refetching it
+ // ThreadGDBRemote::SetQueueInfo(...) with valid information that was gleaned
+ // from the stop reply packet. In this case we trust that the info is valid
+ // in m_dispatch_queue_name without refetching it
if (CachedQueueInfoIsValid()) {
if (m_dispatch_queue_name.empty())
return nullptr;
@@ -110,15 +109,14 @@ const char *ThreadGDBRemote::GetQueueName() {
return m_dispatch_queue_name.c_str();
}
}
- return NULL;
+ return nullptr;
}
QueueKind ThreadGDBRemote::GetQueueKind() {
// If our cached queue info is valid, then someone called
- // ThreadGDBRemote::SetQueueInfo(...)
- // with valid information that was gleaned from the stop reply packet. In this
- // case we trust
- // that the info is valid in m_dispatch_queue_name without refetching it
+ // ThreadGDBRemote::SetQueueInfo(...) with valid information that was gleaned
+ // from the stop reply packet. In this case we trust that the info is valid
+ // in m_dispatch_queue_name without refetching it
if (CachedQueueInfoIsValid()) {
return m_queue_kind;
}
@@ -141,10 +139,9 @@ QueueKind ThreadGDBRemote::GetQueueKind() {
queue_id_t ThreadGDBRemote::GetQueueID() {
// If our cached queue info is valid, then someone called
- // ThreadGDBRemote::SetQueueInfo(...)
- // with valid information that was gleaned from the stop reply packet. In this
- // case we trust
- // that the info is valid in m_dispatch_queue_name without refetching it
+ // ThreadGDBRemote::SetQueueInfo(...) with valid information that was gleaned
+ // from the stop reply packet. In this case we trust that the info is valid
+ // in m_dispatch_queue_name without refetching it
if (CachedQueueInfoIsValid())
return m_queue_serial_number;
@@ -275,11 +272,11 @@ void ThreadGDBRemote::RefreshStateAfterStop() {
// Invalidate all registers in our register context. We don't set "force" to
// true because the stop reply packet might have had some register values
// that were expedited and these will already be copied into the register
- // context by the time this function gets called. The GDBRemoteRegisterContext
- // class has been made smart enough to detect when it needs to invalidate
- // which registers are valid by putting hooks in the register read and
- // register supply functions where they check the process stop ID and do
- // the right thing.
+ // context by the time this function gets called. The
+ // GDBRemoteRegisterContext class has been made smart enough to detect when
+ // it needs to invalidate which registers are valid by putting hooks in the
+ // register read and register supply functions where they check the process
+ // stop ID and do the right thing.
const bool force = false;
GetRegisterContext()->InvalidateIfNeeded(force);
}
@@ -292,8 +289,8 @@ void ThreadGDBRemote::Dump(Log *log, uint32_t index) {}
bool ThreadGDBRemote::ShouldStop(bool &step_more) { return true; }
lldb::RegisterContextSP ThreadGDBRemote::GetRegisterContext() {
- if (m_reg_context_sp.get() == NULL)
- m_reg_context_sp = CreateRegisterContextForFrame(NULL);
+ if (!m_reg_context_sp)
+ m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
return m_reg_context_sp;
}
@@ -310,7 +307,8 @@ ThreadGDBRemote::CreateRegisterContextForFrame(StackFrame *frame) {
if (process_sp) {
ProcessGDBRemote *gdb_process =
static_cast<ProcessGDBRemote *>(process_sp.get());
- // read_all_registers_at_once will be true if 'p' packet is not supported.
+ // read_all_registers_at_once will be true if 'p' packet is not
+ // supported.
bool read_all_registers_at_once =
!gdb_process->GetGDBRemote().GetpPacketSupported(GetID());
reg_ctx_sp.reset(new GDBRemoteRegisterContext(
@@ -319,7 +317,7 @@ ThreadGDBRemote::CreateRegisterContextForFrame(StackFrame *frame) {
}
} else {
Unwind *unwinder = GetUnwinder();
- if (unwinder)
+ if (unwinder != nullptr)
reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame);
}
return reg_ctx_sp;