c46f99f549c0ceb8ad44b8bedff5b87543871598
[deliverable/binutils-gdb.git] / gdb / displaced-stepping.h
1 #ifndef DISPLACED_STEPPING_H
2 #define DISPLACED_STEPPING_H
3
4 #include "gdbsupport/array-view.h"
5 #include "gdbsupport/byte-vector.h"
6
7 struct gdbarch;
8 struct thread_info;
9 struct target_ops;
10
11 enum displaced_step_prepare_status
12 {
13 /* A displaced stepping buffer was successfully allocated and prepared. */
14 DISPLACED_STEP_PREPARE_STATUS_OK,
15
16 /* Something bad happened. */
17 DISPLACED_STEP_PREPARE_STATUS_ERROR,
18
19 /* Not enough resources are available at this time, try again later. */
20 DISPLACED_STEP_PREPARE_STATUS_UNAVAILABLE,
21 };
22
23 enum displaced_step_finish_status
24 {
25 /* The instruction was stepped and fixed up. */
26 DISPLACED_STEP_FINISH_STATUS_OK,
27
28 /* The instruction was not stepped. */
29 DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED,
30 };
31
32 /* Data returned by a gdbarch displaced_step_copy_insn method, to be passed to
33 the matching displaced_step_fixup method. */
34
35 struct displaced_step_copy_insn_closure
36 {
37 virtual ~displaced_step_copy_insn_closure () = 0;
38 };
39
40 typedef std::unique_ptr<displaced_step_copy_insn_closure>
41 displaced_step_copy_insn_closure_up;
42
43 /* A simple displaced step closure that contains only a byte buffer. */
44
45 struct buf_displaced_step_copy_insn_closure : displaced_step_copy_insn_closure
46 {
47 buf_displaced_step_copy_insn_closure (int buf_size)
48 : buf (buf_size)
49 {}
50
51 gdb::byte_vector buf;
52 };
53
54 /* Per-inferior displaced stepping state. */
55
56 struct displaced_step_inferior_state
57 {
58 displaced_step_inferior_state ()
59 {
60 reset ();
61 }
62
63 /* Put this object back in its original state. */
64 void reset ()
65 {
66 failed_before = false;
67 }
68
69 /* True if preparing a displaced step ever failed. If so, we won't
70 try displaced stepping for this inferior again. */
71 bool failed_before;
72
73 bool unavailable = false;
74 };
75
76 /* Per-thread displaced stepping state. */
77
78 struct displaced_step_thread_state
79 {
80 /* Return true if this thread is currently executing a displaced step. */
81 bool in_progress () const
82 { return m_original_gdbarch != nullptr; }
83
84 /* Return the gdbarch of the thread prior to the step. */
85 gdbarch *get_original_gdbarch () const
86 { return m_original_gdbarch; }
87
88 /* Mark this thread as currently executing a displaced step.
89
90 ORIGINAL_GDBARCH is the current gdbarch of the thread (before the step
91 is executed). */
92 void set (gdbarch *original_gdbarch)
93 { m_original_gdbarch = original_gdbarch; }
94
95 /* mark this thread as no longer executing a displaced step. */
96 void reset ()
97 { m_original_gdbarch = nullptr; }
98
99 private:
100 gdbarch *m_original_gdbarch = nullptr;
101 };
102
103 struct displaced_step_buffer_state
104 {
105 displaced_step_buffer_state (CORE_ADDR buffer_addr)
106 : m_buffer_addr (buffer_addr)
107 {}
108
109 const CORE_ADDR m_buffer_addr;
110
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;
114
115 /* If set, the thread currently using the buffer. If unset, the buffer is not
116 used. */
117 thread_info *m_current_thread = nullptr;
118
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;
122
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;
126 };
127
128 /* Manage access to a single displaced stepping buffer, without any
129 sharing. */
130
131 struct multiple_displaced_buffer_manager
132 {
133 multiple_displaced_buffer_manager (gdb::array_view<CORE_ADDR> buffer_addrs)
134 {
135 gdb_assert (buffer_addrs.size () > 0);
136
137 for (CORE_ADDR buffer_addr : buffer_addrs)
138 m_buffers.emplace_back (buffer_addr);
139 }
140
141 displaced_step_prepare_status prepare (thread_info *thread);
142
143 displaced_step_finish_status finish (gdbarch *arch, thread_info *thread,
144 gdb_signal sig);
145
146 CORE_ADDR first_buf_addr () const
147 {
148 return m_buffers[0].m_buffer_addr;
149 }
150
151 private:
152 std::vector<displaced_step_buffer_state> m_buffers;
153 };
154
155 displaced_step_prepare_status
156 default_displaced_step_prepare (target_ops *target, thread_info *thread);
157
158 displaced_step_finish_status
159 default_displaced_step_finish (target_ops *target, thread_info *thread,
160 gdb_signal sig);
161
162 #endif /* DISPLACED_STEPPING_H */
This page took 0.031789 seconds and 3 git commands to generate.