guiandrade created this revision.
guiandrade added a reviewer: labath.
guiandrade added a project: LLDB.
Herald added a subscriber: lldb-commits.
This change makes it possible to fetch all registers at once from Linux by
defining a macro.
This is useful for the case when all registers are being fetched every step and
the RTT is non-negligible.
Repository:
rLLDB LLDB
https://reviews.llvm.org/D62221
Files:
lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteGPacket.py
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
lldb/source/Utility/StringExtractorGDBRemote.cpp
Index: lldb/source/Utility/StringExtractorGDBRemote.cpp
===================================================================
--- lldb/source/Utility/StringExtractorGDBRemote.cpp
+++ lldb/source/Utility/StringExtractorGDBRemote.cpp
@@ -377,9 +377,7 @@
break;
case 'g':
- if (packet_size == 1)
- return eServerPacketType_g;
- break;
+ return eServerPacketType_g;
case 'G':
return eServerPacketType_G;
Index: lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -303,10 +303,17 @@
if (process_sp) {
ProcessGDBRemote *gdb_process =
static_cast<ProcessGDBRemote *>(process_sp.get());
+
+#ifdef LLDB_REMOTE_SHOULD_READ_ALL_REGISTERS_AT_ONCE
+ // Always fetch the registers at once when the flag has been defined.
+ bool read_all_registers_at_once = true;
+#else
// 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());
+#endif
+
reg_ctx_sp = std::make_shared<GDBRemoteRegisterContext>(
*this, concrete_frame_idx, gdb_process->m_register_info,
read_all_registers_at_once);
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
@@ -178,6 +178,8 @@
PacketResult Handle_QPassSignals(StringExtractorGDBRemote &packet);
+ PacketResult Handle_g(StringExtractorGDBRemote &packet);
+
void SetCurrentThreadID(lldb::tid_t tid);
lldb::tid_t GetCurrentThreadID() const;
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -187,6 +187,9 @@
StringExtractorGDBRemote::eServerPacketType_jTraceConfigRead,
&GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead);
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_g,
+ &GDBRemoteCommunicationServerLLGS::Handle_g);
+
RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k,
[this](StringExtractorGDBRemote packet, Status &error,
bool &interrupt, bool &quit) {
@@ -1891,6 +1894,68 @@
return SendPacketNoLock("l");
}
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_g(StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+
+ // Move past packet name.
+ packet.SetFilePos(strlen("g"));
+
+ // Get the thread to use.
+ NativeThreadProtocol *thread = GetThreadFromSuffix(packet);
+ if (!thread) {
+ LLDB_LOG(log, "failed, no thread available");
+ return SendErrorResponse(0x15);
+ }
+
+ // Get the thread's register context.
+ NativeRegisterContext ®_ctx = thread->GetRegisterContext();
+
+ // As the register offsets are not necessarily sorted,
+ // use a map to store all registers data.
+ std::map<uint32_t, uint8_t> regs_buffer;
+ for (uint32_t reg_num = 0; reg_num < reg_ctx.GetUserRegisterCount();
+ ++reg_num) {
+ const RegisterInfo *reg_info = reg_ctx.GetRegisterInfoAtIndex(reg_num);
+
+ if (reg_info == nullptr) {
+ LLDB_LOG(log, "failed to get register info for register index {0}",
+ reg_num);
+ return SendErrorResponse(0x15);
+ }
+
+ if (reg_info->value_regs != nullptr)
+ continue; // skip registers that are contained in other registers
+
+ RegisterValue reg_value;
+ Status error = reg_ctx.ReadRegister(reg_info, reg_value);
+ if (error.Fail()) {
+ LLDB_LOG(log, "failed to read register at index {0}", reg_num);
+ return SendErrorResponse(0x15);
+ }
+
+ // Write the register data to the buffer.
+ const uint8_t *const data =
+ reinterpret_cast<const uint8_t *>(reg_value.GetBytes());
+ for (uint32_t i = 0; i < reg_info->byte_size; ++i)
+ regs_buffer[reg_info->byte_offset + i] = data[i];
+ }
+
+ // Write the response.
+ StreamGDBRemote response;
+ uint32_t next_pos = 0;
+ for (const auto &it : regs_buffer) {
+ // Populate the gap between the last and the current position
+ // with zeroes.
+ while (next_pos++ < it.first)
+ response.PutHex8(0);
+
+ response.PutHex8(it.second);
+ }
+
+ return SendPacketNoLock(response.GetString());
+}
+
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
Index: lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteGPacket.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteGPacket.py
+++ lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteGPacket.py
@@ -11,31 +11,39 @@
mydir = TestBase.compute_mydir(__file__)
- def run_test_g_packet(self):
+ def run_test_g_packet(self, read, write):
self.build()
self.prep_debug_monitor_and_inferior()
- self.test_sequence.add_log_lines(
- ["read packet: $g#67",
- {"direction": "send", "regex": r"^\$(.+)#[0-9a-fA-F]{2}$",
- "capture": {1: "register_bank"}}],
- True)
self.connect_to_debug_monitor()
- context = self.expect_gdbremote_sequence()
- register_bank = context.get("register_bank")
- self.assertTrue(register_bank[0] != 'E')
-
- self.test_sequence.add_log_lines(
- ["read packet: $G" + register_bank + "#00",
- {"direction": "send", "regex": r"^\$(.+)#[0-9a-fA-F]{2}$",
- "capture": {1: "G_reply"}}],
- True)
- context = self.expect_gdbremote_sequence()
- self.assertTrue(context.get("G_reply")[0] != 'E')
+ if read:
+ self.test_sequence.add_log_lines(
+ ["read packet: $g#67",
+ {"direction": "send", "regex": r"^\$(.+)#[0-9a-fA-F]{2}$",
+ "capture": {1: "register_bank"}}],
+ True)
+ context = self.expect_gdbremote_sequence()
+ register_bank = context.get("register_bank")
+ self.assertTrue(register_bank[0] != 'E')
+
+ if write:
+ self.test_sequence.add_log_lines(
+ ["read packet: $G" + register_bank + "#00",
+ {"direction": "send", "regex": r"^\$(.+)#[0-9a-fA-F]{2}$",
+ "capture": {1: "G_reply"}}],
+ True)
+ context = self.expect_gdbremote_sequence()
+ self.assertTrue(context.get("G_reply")[0] != 'E')
@skipIfOutOfTreeDebugserver
@debugserver_test
@skipIfDarwinEmbedded
def test_g_packet_debugserver(self):
self.init_debugserver_test()
- self.run_test_g_packet()
+ self.run_test_g_packet(read=True, write=True)
+
+ @llgs_test
+ @skipIfDarwinEmbedded
+ def test_g_packet_llgs(self):
+ self.init_llgs_test()
+ self.run_test_g_packet(read=True, write=False)
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits