1 #ifndef DISPLACED_STEPPING_H
2 #define DISPLACED_STEPPING_H
4 #include "gdbsupport/array-view.h"
5 #include "gdbsupport/byte-vector.h"
11 enum displaced_step_prepare_status
13 /* A displaced stepping buffer was successfully allocated and prepared. */
14 DISPLACED_STEP_PREPARE_STATUS_OK
,
16 /* Something bad happened. */
17 DISPLACED_STEP_PREPARE_STATUS_ERROR
,
19 /* Not enough resources are available at this time, try again later. */
20 DISPLACED_STEP_PREPARE_STATUS_UNAVAILABLE
,
23 enum displaced_step_finish_status
25 /* The instruction was stepped and fixed up. */
26 DISPLACED_STEP_FINISH_STATUS_OK
,
28 /* The instruction was not stepped. */
29 DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED
,
32 /* Data returned by a gdbarch displaced_step_copy_insn method, to be passed to
33 the matching displaced_step_fixup method. */
35 struct displaced_step_copy_insn_closure
37 virtual ~displaced_step_copy_insn_closure () = 0;
40 typedef std::unique_ptr
<displaced_step_copy_insn_closure
>
41 displaced_step_copy_insn_closure_up
;
43 /* A simple displaced step closure that contains only a byte buffer. */
45 struct buf_displaced_step_copy_insn_closure
: displaced_step_copy_insn_closure
47 buf_displaced_step_copy_insn_closure (int buf_size
)
54 /* Per-inferior displaced stepping state. */
56 struct displaced_step_inferior_state
58 displaced_step_inferior_state ()
63 /* Put this object back in its original state. */
66 failed_before
= false;
69 /* True if preparing a displaced step ever failed. If so, we won't
70 try displaced stepping for this inferior again. */
73 bool unavailable
= false;
76 /* Per-thread displaced stepping state. */
78 struct displaced_step_thread_state
80 /* Return true if this thread is currently executing a displaced step. */
81 bool in_progress () const
82 { return m_original_gdbarch
!= nullptr; }
84 /* Return the gdbarch of the thread prior to the step. */
85 gdbarch
*get_original_gdbarch () const
86 { return m_original_gdbarch
; }
88 /* Mark this thread as currently executing a displaced step.
90 ORIGINAL_GDBARCH is the current gdbarch of the thread (before the step
92 void set (gdbarch
*original_gdbarch
)
93 { m_original_gdbarch
= original_gdbarch
; }
95 /* mark this thread as no longer executing a displaced step. */
97 { m_original_gdbarch
= nullptr; }
100 gdbarch
*m_original_gdbarch
= nullptr;
103 struct displaced_step_buffer_state
105 displaced_step_buffer_state (CORE_ADDR buffer_addr
)
106 : m_buffer_addr (buffer_addr
)
109 const CORE_ADDR m_buffer_addr
;
111 /* When a displaced step operation is using this buffer, this is the original
112 PC of the instruction currently begin stepped. */
113 CORE_ADDR m_original_pc
= 0;
115 /* If set, the thread currently using the buffer. If unset, the buffer is not
117 thread_info
*m_current_thread
= nullptr;
119 /* Saved copy of the bytes in the displaced buffer, to be restored once the
120 buffer is no longer used. */
121 gdb::byte_vector m_saved_copy
;
123 /* Closure obtained from gdbarch_displaced_step_copy_insn, to be passed to
124 gdbarch_displaced_step_fixup_insn. */
125 displaced_step_copy_insn_closure_up m_copy_insn_closure
;
128 /* Manage access to a single displaced stepping buffer, without any
131 struct multiple_displaced_buffer_manager
133 multiple_displaced_buffer_manager (gdb::array_view
<CORE_ADDR
> buffer_addrs
)
135 gdb_assert (buffer_addrs
.size () > 0);
137 for (CORE_ADDR buffer_addr
: buffer_addrs
)
138 m_buffers
.emplace_back (buffer_addr
);
141 displaced_step_prepare_status
prepare (thread_info
*thread
);
143 displaced_step_finish_status
finish (gdbarch
*arch
, thread_info
*thread
,
146 CORE_ADDR
first_buf_addr () const
148 return m_buffers
[0].m_buffer_addr
;
152 std::vector
<displaced_step_buffer_state
> m_buffers
;
155 displaced_step_prepare_status
156 default_displaced_step_prepare (target_ops
*target
, thread_info
*thread
);
158 displaced_step_finish_status
159 default_displaced_step_finish (target_ops
*target
, thread_info
*thread
,
162 #endif /* DISPLACED_STEPPING_H */