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 &reg_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
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to