gdb: change single_displaced_buffer_manager into multiple_displaced_buffer_manager
authorSimon Marchi <simon.marchi@efficios.com>
Wed, 11 Mar 2020 22:13:44 +0000 (18:13 -0400)
committerSimon Marchi <simon.marchi@efficios.com>
Thu, 4 Jun 2020 19:04:21 +0000 (15:04 -0400)
single_displaced_buffer_manager, introduced in a previous patch, is
responsible for managing the access to a single displaced step buffer.
We'll want to be able to use more than one, so change it to
multiple_displaced_buffer_manager, which receives a collection of
buffer addresses at construction, instead of a single buffer address.

The callers keep passing a single buffer, however, so there is not
expected behavior change.

gdb/amd64-linux-tdep.c
gdb/displaced-stepping.c
gdb/displaced-stepping.h

index 937ec8359684c59b1a86f905f5fce35dbed70525..4cb33d5b5d2a55cfa51ae98951ae97088c74631e 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "defs.h"
 #include "arch-utils.h"
+#include "displaced-stepping.h"
 #include "frame.h"
 #include "gdbarch.h"
 #include "gdbcore.h"
@@ -1798,11 +1799,11 @@ amd64_dtrace_parse_probe_argument (struct gdbarch *gdbarch,
 
 struct amd64_linux_per_inferior
 {
-  amd64_linux_per_inferior (CORE_ADDR disp_step_buffer_addr)
-    : disp_step_buf_mgr (disp_step_buffer_addr)
+  amd64_linux_per_inferior (gdb::array_view<CORE_ADDR> disp_step_buffer_addrs)
+    : disp_step_buf_mgr (disp_step_buffer_addrs)
   {}
 
-  single_displaced_buffer_manager disp_step_buf_mgr;
+  multiple_displaced_buffer_manager disp_step_buf_mgr;
 };
 
 static const inferior_key<amd64_linux_per_inferior>
index cbf2425e370e0ca086e16083cb791d84b2219dd3..f373be79642fcf52234ff7808962932812534bb0 100644 (file)
 displaced_step_copy_insn_closure::~displaced_step_copy_insn_closure() = default;
 
 displaced_step_prepare_status
-single_displaced_buffer_manager::prepare (thread_info *thread)
+multiple_displaced_buffer_manager::prepare (thread_info *thread)
 {
-  /* Is a thread currently using the buffer?  */
-  if (m_current_thread != nullptr)
+  gdb_assert (!thread->displaced_step_state.in_progress ());
+  displaced_step_buffer_state *buffer = nullptr;
+
+  /* Sanity check.  */
+  for (displaced_step_buffer_state &buf : m_buffers)
+    gdb_assert (buf.m_current_thread != thread);
+
+  /* Search for an unused buffer.  */
+  for (displaced_step_buffer_state &candidate : m_buffers)
     {
-      /* If so, it better not be this thread.  */
-      gdb_assert (thread != m_current_thread);
-      return DISPLACED_STEP_PREPARE_STATUS_UNAVAILABLE;
+      if (candidate.m_current_thread == nullptr)
+       {
+         buffer = &candidate;
+         break;
+       }
     }
 
+  if (buffer == nullptr)
+    return DISPLACED_STEP_PREPARE_STATUS_UNAVAILABLE;
+
   gdbarch *arch = thread->arch ();
+
+  if (debug_displaced)
+    fprintf_unfiltered (gdb_stdlog, "displaced: selected buffer at %s\n",
+                       paddress (arch, buffer->m_buffer_addr));
+
   struct regcache *regcache = thread->regcache ();
   ULONGEST len = gdbarch_max_insn_length (arch);
-  m_original_pc = regcache_read_pc (regcache);
+  buffer->m_original_pc = regcache_read_pc (regcache);
 
   /* Save the original contents of the displaced stepping buffer.  */
-  m_saved_copy.resize (len);
+  buffer->m_saved_copy.resize (len);
 
-  int status = target_read_memory (m_buffer_addr, m_saved_copy.data (), len);
+  int status = target_read_memory (buffer->m_buffer_addr, buffer->m_saved_copy.data (), len);
   if (status != 0)
     throw_error (MEMORY_ERROR,
                 _("Error accessing memory address %s (%s) for "
                   "displaced-stepping scratch space."),
-                paddress (arch, m_buffer_addr), safe_strerror (status));
+                paddress (arch, buffer->m_buffer_addr), safe_strerror (status));
 
   if (debug_displaced)
     {
       fprintf_unfiltered (gdb_stdlog, "displaced: saved %s: ",
-                         paddress (arch, m_buffer_addr));
-      displaced_step_dump_bytes (gdb_stdlog, m_saved_copy.data (), len);
+                         paddress (arch, buffer->m_buffer_addr));
+      displaced_step_dump_bytes (gdb_stdlog, buffer->m_saved_copy.data (), len);
     };
 
-  m_copy_insn_closure = gdbarch_displaced_step_copy_insn (arch,
-                                                         m_original_pc,
-                                                         m_buffer_addr,
-                                                         regcache);
-  if (m_copy_insn_closure == nullptr)
+  buffer->m_copy_insn_closure
+    = gdbarch_displaced_step_copy_insn (arch, buffer->m_original_pc,
+                                       buffer->m_buffer_addr, regcache);
+  if (buffer->m_copy_insn_closure == nullptr)
     {
       /* The architecture doesn't know how or want to displaced step
         this instruction or instruction sequence.  Fallback to
@@ -58,19 +74,19 @@ single_displaced_buffer_manager::prepare (thread_info *thread)
   try
     {
       /* Resume execution at the copy.  */
-      regcache_write_pc (regcache, m_buffer_addr);
+      regcache_write_pc (regcache, buffer->m_buffer_addr);
     }
   catch (...)
     {
       /* Failed to write the PC.  Release the architecture's displaced
          stepping resources and the thread's displaced stepping state.  */
-      m_copy_insn_closure.reset ();
+      buffer->m_copy_insn_closure.reset ();
 
       return DISPLACED_STEP_PREPARE_STATUS_ERROR;
     }
 
   /* This marks the buffer as being in use.  */
-  m_current_thread = thread;
+  buffer->m_current_thread = thread;
 
   return DISPLACED_STEP_PREPARE_STATUS_OK;
 }
@@ -103,32 +119,46 @@ displaced_step_instruction_executed_successfully (gdbarch *arch, gdb_signal sign
 }
 
 displaced_step_finish_status
-single_displaced_buffer_manager::finish (gdbarch *arch, thread_info *thread,
-                                        gdb_signal sig)
+multiple_displaced_buffer_manager::finish (gdbarch *arch, thread_info *thread,
+                                          gdb_signal sig)
 {
   displaced_step_finish_status status;
+  displaced_step_buffer_state *buffer = nullptr;
 
-  gdb_assert (thread == m_current_thread);
+  gdb_assert (thread->displaced_step_state.in_progress ());
+
+  /* Find the buffer this thread was using.  */
+  for (displaced_step_buffer_state &candidate : m_buffers)
+    {
+      if (thread == candidate.m_current_thread)
+       {
+         buffer = &candidate;
+         break;
+       }
+    }
+
+  gdb_assert (buffer != nullptr);
 
   ULONGEST len = gdbarch_max_insn_length (arch);
 
-  write_memory_ptid (thread->ptid, m_buffer_addr,
-                    m_saved_copy.data (), len);
+  /* Restore memory of the buffer.  */
+  write_memory_ptid (thread->ptid, buffer->m_buffer_addr,
+                    buffer->m_saved_copy.data (), len);
   if (debug_displaced)
     fprintf_unfiltered (gdb_stdlog, "displaced: restored %s %s\n",
                        target_pid_to_str (thread->ptid).c_str (),
-                       paddress (arch, m_buffer_addr));
+                       paddress (arch, buffer->m_buffer_addr));
 
   regcache *rc = get_thread_regcache (thread);
 
   bool instruction_executed_successfully
     = displaced_step_instruction_executed_successfully (arch, sig);
 
-
   if (instruction_executed_successfully)
     {
-      gdbarch_displaced_step_fixup (arch, m_copy_insn_closure.get (), m_original_pc,
-                                   m_buffer_addr, rc);
+      gdbarch_displaced_step_fixup (arch, buffer->m_copy_insn_closure.get (),
+                                   buffer->m_original_pc,
+                                   buffer->m_buffer_addr, rc);
       status = DISPLACED_STEP_FINISH_STATUS_OK;
     }
   else
@@ -136,13 +166,13 @@ single_displaced_buffer_manager::finish (gdbarch *arch, thread_info *thread,
       /* Since the instruction didn't complete, all we can do is relocate the
         PC.  */
       CORE_ADDR pc = regcache_read_pc (rc);
-      pc = m_original_pc + (pc - m_buffer_addr);
+      pc = buffer->m_original_pc + (pc - buffer->m_buffer_addr);
       regcache_write_pc (rc, pc);
       status = DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED;
     }
 
-  m_copy_insn_closure.reset ();
-  m_current_thread = nullptr;
+  buffer->m_copy_insn_closure.reset ();
+  buffer->m_current_thread = nullptr;
 
   return status;
 }
index 835fd92086bad096ec85b4fc42db8720c81dc6ba..7bb02b3bbfc736e1a0984e80ec97bba859fe9ea2 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef DISPLACED_STEPPING_H
 #define DISPLACED_STEPPING_H
 
+#include "gdbsupport/array-view.h"
 #include "gdbsupport/byte-vector.h"
 
 struct gdbarch;
@@ -98,14 +99,43 @@ private:
   gdbarch *m_original_gdbarch = nullptr;
 };
 
+struct displaced_step_buffer_state
+{
+  displaced_step_buffer_state (CORE_ADDR buffer_addr)
+    : m_buffer_addr (buffer_addr)
+  {}
+
+  const CORE_ADDR m_buffer_addr;
+
+  /* When a displaced step operation is using this buffer, this is the original
+     PC of the instruction currently begin stepped.  */
+  CORE_ADDR m_original_pc = 0;
+
+  /* If set, the thread currently using the buffer.  If unset, the buffer is not
+     used.  */
+  thread_info *m_current_thread = nullptr;
+
+  /* Saved copy of the bytes in the displaced buffer, to be restored once the
+     buffer is no longer used.  */
+  gdb::byte_vector m_saved_copy;
+
+  /* Closure obtained from gdbarch_displaced_step_copy_insn, to be passed to
+     gdbarch_displaced_step_fixup_insn.  */
+  displaced_step_copy_insn_closure_up m_copy_insn_closure;
+};
+
 /* Manage access to a single displaced stepping buffer, without any
    sharing.  */
 
-struct single_displaced_buffer_manager
+struct multiple_displaced_buffer_manager
 {
-  single_displaced_buffer_manager (CORE_ADDR buffer_addr)
-    : m_buffer_addr (buffer_addr)
-  {}
+  multiple_displaced_buffer_manager (gdb::array_view<CORE_ADDR> buffer_addrs)
+  {
+    gdb_assert (buffer_addrs.size () > 0);
+
+    for (CORE_ADDR buffer_addr : buffer_addrs)
+      m_buffers.emplace_back (buffer_addr);
+  }
 
   displaced_step_prepare_status prepare (thread_info *thread);
 
@@ -113,15 +143,7 @@ struct single_displaced_buffer_manager
                                       gdb_signal sig);
 
 private:
-
-  CORE_ADDR m_original_pc;
-  CORE_ADDR m_buffer_addr;
-
-  /* If set, the thread currently using the buffer.  */
-  thread_info *m_current_thread = nullptr;
-
-  gdb::byte_vector m_saved_copy;
-  displaced_step_copy_insn_closure_up m_copy_insn_closure;
+  std::vector<displaced_step_buffer_state> m_buffers;
 };
 
 
This page took 0.02901 seconds and 4 git commands to generate.