guiandrade updated this revision to Diff 200846.
guiandrade marked an inline comment as done.
guiandrade edited the summary of this revision.
guiandrade added a comment.
Making this revision be responsible only for adding the 'g' packet handler and
tests. Also, I'm starting to implement a stronger test to verify the actual
content of the packets returned by the new handler.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D62221/new/
https://reviews.llvm.org/D62221
Files:
lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
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/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/TestLldbGdbServer.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py
+++ lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py
@@ -545,8 +545,7 @@
self.set_inferior_startup_attach()
self.qThreadInfo_matches_qC()
- def p_returns_correct_data_size_for_each_qRegisterInfo(self):
- procs = self.prep_debug_monitor_and_inferior()
+ def generateValidRegisterInfoEntries(self):
self.add_register_info_collection_packets()
# Run the packet stream.
@@ -563,7 +562,6 @@
byte_order = Target.GetByteOrder()
# Read value for each register.
- reg_index = 0
for reg_info in reg_infos:
# Skip registers that don't have a register set. For x86, these are
# the DRx registers, which have no LLDB-kind register number and thus
@@ -572,6 +570,49 @@
if not "set" in reg_info:
continue
+ if "dynamic_size_dwarf_expr_bytes" in reg_info:
+ self.updateRegInfoBitsize(reg_info, byte_order)
+
+ yield reg_info
+
+ def assertRegisterValue(self, expected, reg_info, reg_bank):
+ reg_offset = int(reg_info["offset"])*2
+ reg_byte_size = int(2 * int(reg_info["bitsize"]) / 8)
+
+ # Extract the register from the bank and verify it is equal to expected.
+ self.assertEqual(expected, reg_bank[reg_offset:reg_offset+reg_byte_size])
+
+ def g_returns_correct_data(self):
+ procs = self.prep_debug_monitor_and_inferior()
+
+ # Get register bank using 'g' packet
+ 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()
+ reg_bank = context.get("register_bank")
+ self.assertTrue(reg_bank[0] != 'E')
+
+ reg_infos = {
+ info['name']: info for info in self.generateValidRegisterInfoEntries()}
+
+ self.assertRegisterValue('0000000000000000', reg_infos['r8'], reg_bank)
+ self.assertRegisterValue('0000000000000000', reg_infos['r9'], reg_bank)
+ self.assertRegisterValue('0000000000000000', reg_infos['r10'], reg_bank)
+
+ @llgs_test
+ def test_g_returns_correct_data(self):
+ self.init_llgs_test()
+ self.build()
+ self.set_inferior_startup_launch()
+ self.g_returns_correct_data()
+
+ def p_returns_correct_data_size_for_each_qRegisterInfo(self):
+ procs = self.prep_debug_monitor_and_inferior()
+
+ for reg_index, reg_info in enumerate(self.generateValidRegisterInfoEntries()):
# Clear existing packet expectations.
self.reset_test_sequence()
@@ -587,13 +628,8 @@
p_response = context.get("p_response")
self.assertIsNotNone(p_response)
- if "dynamic_size_dwarf_expr_bytes" in reg_info:
- self.updateRegInfoBitsize(reg_info, byte_order)
self.assertEqual(len(p_response), 2 * int(reg_info["bitsize"]) / 8)
- # Increment loop
- reg_index += 1
-
@debugserver_test
@skipIfDarwinEmbedded # <rdar://problem/34539270> lldb-server tests not updated to work on ios etc yet
def test_p_returns_correct_data_size_for_each_qRegisterInfo_launch_debugserver(
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits