1 #ifndef DISPLACED_STEPPING_H
2 #define DISPLACED_STEPPING_H
4 #include "gdbsupport/array-view.h"
5 #include "gdbsupport/byte-vector.h"
10 enum displaced_step_prepare_status
12 /* A displaced stepping buffer was successfully allocated and prepared. */
13 DISPLACED_STEP_PREPARE_STATUS_OK
,
15 /* Something bad happened. */
16 DISPLACED_STEP_PREPARE_STATUS_ERROR
,
18 /* Not enough resources are available at this time, try again later. */
19 DISPLACED_STEP_PREPARE_STATUS_UNAVAILABLE
,
22 enum displaced_step_finish_status
24 /* The instruction was stepped and fixed up. */
25 DISPLACED_STEP_FINISH_STATUS_OK
,
27 /* The instruction was not stepped. */
28 DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED
,
31 /* Data returned by a gdbarch displaced_step_copy_insn method, to be passed to
32 the matching displaced_step_fixup method. */
34 struct displaced_step_copy_insn_closure
36 virtual ~displaced_step_copy_insn_closure () = 0;
39 typedef std::unique_ptr
<displaced_step_copy_insn_closure
>
40 displaced_step_copy_insn_closure_up
;
42 /* A simple displaced step closure that contains only a byte buffer. */
44 struct buf_displaced_step_copy_insn_closure
: displaced_step_copy_insn_closure
46 buf_displaced_step_copy_insn_closure (int buf_size
)
53 /* Per-inferior displaced stepping state. */
55 struct displaced_step_inferior_state
57 displaced_step_inferior_state ()
62 /* Put this object back in its original state. */
65 failed_before
= false;
68 /* True if preparing a displaced step ever failed. If so, we won't
69 try displaced stepping for this inferior again. */
72 bool unavailable
= false;
75 /* Per-thread displaced stepping state. */
77 struct displaced_step_thread_state
79 /* Return true if this thread is currently executing a displaced step. */
80 bool in_progress () const
81 { return m_original_gdbarch
!= nullptr; }
83 /* Return the gdbarch of the thread prior to the step. */
84 gdbarch
*get_original_gdbarch () const
85 { return m_original_gdbarch
; }
87 /* Mark this thread as currently executing a displaced step.
89 ORIGINAL_GDBARCH is the current gdbarch of the thread (before the step
91 void set (gdbarch
*original_gdbarch
)
92 { m_original_gdbarch
= original_gdbarch
; }
94 /* mark this thread as no longer executing a displaced step. */
96 { m_original_gdbarch
= nullptr; }
99 gdbarch
*m_original_gdbarch
= nullptr;
102 struct displaced_step_buffer_state
104 displaced_step_buffer_state (CORE_ADDR buffer_addr
)
105 : m_buffer_addr (buffer_addr
)
108 const CORE_ADDR m_buffer_addr
;
110 /* When a displaced step operation is using this buffer, this is the original
111 PC of the instruction currently begin stepped. */
112 CORE_ADDR m_original_pc
= 0;
114 /* If set, the thread currently using the buffer. If unset, the buffer is not
116 thread_info
*m_current_thread
= nullptr;
118 /* Saved copy of the bytes in the displaced buffer, to be restored once the
119 buffer is no longer used. */
120 gdb::byte_vector m_saved_copy
;
122 /* Closure obtained from gdbarch_displaced_step_copy_insn, to be passed to
123 gdbarch_displaced_step_fixup_insn. */
124 displaced_step_copy_insn_closure_up m_copy_insn_closure
;
127 /* Manage access to a single displaced stepping buffer, without any
130 struct multiple_displaced_buffer_manager
132 multiple_displaced_buffer_manager (gdb::array_view
<CORE_ADDR
> buffer_addrs
)
134 gdb_assert (buffer_addrs
.size () > 0);
136 for (CORE_ADDR buffer_addr
: buffer_addrs
)
137 m_buffers
.emplace_back (buffer_addr
);
140 displaced_step_prepare_status
prepare (thread_info
*thread
);
142 displaced_step_finish_status
finish (gdbarch
*arch
, thread_info
*thread
,
146 std::vector
<displaced_step_buffer_state
> m_buffers
;
150 #endif /* DISPLACED_STEPPING_H */