gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / displaced-stepping.h
index 0cb2d8c97071e97b0afb692de5afa89cf2a3ed61..515d4b19034aaeb24ff3985798cad9bde923a04c 100644 (file)
@@ -1,10 +1,12 @@
 #ifndef DISPLACED_STEPPING_H
 #define DISPLACED_STEPPING_H
 
+#include "gdbsupport/array-view.h"
 #include "gdbsupport/byte-vector.h"
 
 struct gdbarch;
 struct thread_info;
+struct target_ops;
 
 enum displaced_step_prepare_status
 {
@@ -67,6 +69,8 @@ struct displaced_step_inferior_state
   /* True if preparing a displaced step ever failed.  If so, we won't
      try displaced stepping for this inferior again.  */
   bool failed_before;
+
+  bool unavailable = false;
 };
 
 /* Per-thread displaced stepping state.  */
@@ -96,31 +100,65 @@ 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);
 
   displaced_step_finish_status finish (gdbarch *arch, thread_info *thread,
                                       gdb_signal sig);
 
-private:
+  CORE_ADDR first_buf_addr () const
+    {
+      return m_buffers[0].m_buffer_addr;
+    }
 
-  CORE_ADDR m_original_pc;
-  CORE_ADDR m_buffer_addr;
+private:
+  std::vector<displaced_step_buffer_state> m_buffers;
+};
 
-  /* If set, the thread currently using the buffer.  */
-  thread_info *m_current_thread = nullptr;
+bool default_supports_displaced_step (target_ops *target, thread_info *thread);
 
-  gdb::byte_vector m_saved_copy;
-  displaced_step_copy_insn_closure_up m_copy_insn_closure;
-};
+displaced_step_prepare_status
+  default_displaced_step_prepare (target_ops *target, thread_info *thread);
 
+displaced_step_finish_status
+  default_displaced_step_finish (target_ops *target, thread_info *thread,
+                                gdb_signal sig);
 
 #endif /* DISPLACED_STEPPING_H */
This page took 0.037231 seconds and 4 git commands to generate.