gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / displaced-stepping.h
CommitLineData
e088209c
SM
1#ifndef DISPLACED_STEPPING_H
2#define DISPLACED_STEPPING_H
3
9635ae5d 4#include "gdbsupport/array-view.h"
e088209c
SM
5#include "gdbsupport/byte-vector.h"
6
7struct gdbarch;
8struct thread_info;
348a832d 9struct target_ops;
e088209c
SM
10
11enum 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
23enum 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
35struct displaced_step_copy_insn_closure
36{
37 virtual ~displaced_step_copy_insn_closure () = 0;
38};
39
40typedef 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
45struct 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
56struct 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;
d6864985
SM
72
73 bool unavailable = false;
e088209c
SM
74};
75
76/* Per-thread displaced stepping state. */
77
78struct 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
99private:
100 gdbarch *m_original_gdbarch = nullptr;
101};
102
9635ae5d
SM
103struct 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
e088209c
SM
128/* Manage access to a single displaced stepping buffer, without any
129 sharing. */
130
9635ae5d 131struct multiple_displaced_buffer_manager
e088209c 132{
9635ae5d
SM
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 }
e088209c
SM
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
c0fdb45e
SM
146 CORE_ADDR first_buf_addr () const
147 {
148 return m_buffers[0].m_buffer_addr;
149 }
150
e088209c 151private:
9635ae5d 152 std::vector<displaced_step_buffer_state> m_buffers;
e088209c
SM
153};
154
65a7e4d6
SM
155bool default_supports_displaced_step (target_ops *target, thread_info *thread);
156
348a832d
SM
157displaced_step_prepare_status
158 default_displaced_step_prepare (target_ops *target, thread_info *thread);
159
160displaced_step_finish_status
161 default_displaced_step_finish (target_ops *target, thread_info *thread,
162 gdb_signal sig);
e088209c
SM
163
164#endif /* DISPLACED_STEPPING_H */
This page took 0.036275 seconds and 4 git commands to generate.