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

Reply via email to