Automatic Copyright Year update after running gdb/copyright.py
[deliverable/binutils-gdb.git] / gdb / displaced-stepping.h
CommitLineData
bab37966
SM
1/* Displaced stepping related things.
2
88b9d363 3 Copyright (C) 2020-2022 Free Software Foundation, Inc.
bab37966
SM
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20#ifndef DISPLACED_STEPPING_H
21#define DISPLACED_STEPPING_H
22
480af54c 23#include "gdbsupport/array-view.h"
c7acb87b
SM
24#include "gdbsupport/byte-vector.h"
25
187b041e 26struct gdbarch;
c7acb87b
SM
27struct thread_info;
28
29/* True if we are debugging displaced stepping. */
30
31extern bool debug_displaced;
32
33/* Print a "displaced" debug statement. */
34
35#define displaced_debug_printf(fmt, ...) \
74b773fc 36 debug_prefixed_printf_cond (debug_displaced, "displaced",fmt, ##__VA_ARGS__)
c7acb87b 37
bab37966
SM
38enum displaced_step_prepare_status
39{
40 /* A displaced stepping buffer was successfully allocated and prepared. */
41 DISPLACED_STEP_PREPARE_STATUS_OK,
42
43 /* This particular instruction can't be displaced stepped, GDB should fall
44 back on in-line stepping. */
45 DISPLACED_STEP_PREPARE_STATUS_CANT,
46
47 /* Not enough resources are available at this time, try again later. */
48 DISPLACED_STEP_PREPARE_STATUS_UNAVAILABLE,
49};
50
51enum displaced_step_finish_status
52{
53 /* Either the instruction was stepped and fixed up, or the specified thread
54 wasn't executing a displaced step (in which case there's nothing to
55 finish). */
56 DISPLACED_STEP_FINISH_STATUS_OK,
57
58 /* The thread started a displaced step, but didn't complete it. */
59 DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED,
60};
61
187b041e
SM
62/* Data returned by a gdbarch displaced_step_copy_insn method, to be passed to
63 the matching displaced_step_fixup method. */
c7acb87b
SM
64
65struct displaced_step_copy_insn_closure
66{
67 virtual ~displaced_step_copy_insn_closure () = 0;
68};
69
70using displaced_step_copy_insn_closure_up
71 = std::unique_ptr<displaced_step_copy_insn_closure>;
72
73/* A simple displaced step closure that contains only a byte buffer. */
74
75struct buf_displaced_step_copy_insn_closure : displaced_step_copy_insn_closure
76{
77 buf_displaced_step_copy_insn_closure (int buf_size)
78 : buf (buf_size)
79 {}
80
187b041e
SM
81 /* The content of this buffer is up to the user of the class, but typically
82 original instruction bytes, used during fixup to determine what needs to
83 be fixed up. */
c7acb87b
SM
84 gdb::byte_vector buf;
85};
86
87/* Per-inferior displaced stepping state. */
88
89struct displaced_step_inferior_state
90{
91 displaced_step_inferior_state ()
92 {
93 reset ();
94 }
95
96 /* Put this object back in its original state. */
97 void reset ()
98 {
187b041e
SM
99 failed_before = false;
100 in_progress_count = 0;
101 unavailable = false;
c7acb87b
SM
102 }
103
104 /* True if preparing a displaced step ever failed. If so, we won't
105 try displaced stepping for this inferior again. */
187b041e 106 bool failed_before;
c7acb87b 107
187b041e
SM
108 /* Number of displaced steps in progress for this inferior. */
109 unsigned int in_progress_count;
c7acb87b 110
187b041e
SM
111 /* If true, this tells GDB that it's not worth asking the gdbarch displaced
112 stepping implementation to prepare a displaced step, because it would
113 return UNAVAILABLE. This is set and reset by the gdbarch in the
114 displaced_step_prepare and displaced_step_finish methods. */
115 bool unavailable;
116};
c7acb87b 117
187b041e 118/* Per-thread displaced stepping state. */
c7acb87b 119
187b041e
SM
120struct displaced_step_thread_state
121{
122 /* Return true if this thread is currently executing a displaced step. */
123 bool in_progress () const
124 {
125 return m_original_gdbarch != nullptr;
126 }
127
128 /* Return the gdbarch of the thread prior to the step. */
129 gdbarch *get_original_gdbarch () const
130 {
131 return m_original_gdbarch;
132 }
133
134 /* Mark this thread as currently executing a displaced step.
135
136 ORIGINAL_GDBARCH is the current gdbarch of the thread (before the step
137 is executed). */
138 void set (gdbarch *original_gdbarch)
139 {
140 m_original_gdbarch = original_gdbarch;
141 }
142
143 /* Mark this thread as no longer executing a displaced step. */
144 void reset ()
145 {
146 m_original_gdbarch = nullptr;
147 }
148
149private:
150 gdbarch *m_original_gdbarch = nullptr;
151};
152
480af54c 153/* Control access to multiple displaced stepping buffers at fixed addresses. */
187b041e 154
480af54c 155struct displaced_step_buffers
187b041e 156{
480af54c
SM
157 explicit displaced_step_buffers (gdb::array_view<CORE_ADDR> buffer_addrs)
158 {
159 gdb_assert (buffer_addrs.size () > 0);
160
161 m_buffers.reserve (buffer_addrs.size ());
162
163 for (CORE_ADDR buffer_addr : buffer_addrs)
164 m_buffers.emplace_back (buffer_addr);
165 }
187b041e
SM
166
167 displaced_step_prepare_status prepare (thread_info *thread,
168 CORE_ADDR &displaced_pc);
169
170 displaced_step_finish_status finish (gdbarch *arch, thread_info *thread,
171 gdb_signal sig);
172
173 const displaced_step_copy_insn_closure *
174 copy_insn_closure_by_addr (CORE_ADDR addr);
175
176 void restore_in_ptid (ptid_t ptid);
177
178private:
187b041e 179
480af54c
SM
180 /* State of a single buffer. */
181
182 struct displaced_step_buffer
183 {
184 explicit displaced_step_buffer (CORE_ADDR addr)
185 : addr (addr)
186 {}
187
188 /* Address of the buffer. */
189 const CORE_ADDR addr;
190
191 /* The original PC of the instruction currently being stepped. */
192 CORE_ADDR original_pc = 0;
193
194 /* If set, the thread currently using the buffer. If unset, the buffer is not
195 used. */
196 thread_info *current_thread = nullptr;
187b041e 197
480af54c
SM
198 /* Saved copy of the bytes in the displaced buffer, to be restored once the
199 buffer is no longer used. */
200 gdb::byte_vector saved_copy;
c7acb87b 201
480af54c
SM
202 /* Closure obtained from gdbarch_displaced_step_copy_insn, to be passed to
203 gdbarch_displaced_step_fixup_insn. */
204 displaced_step_copy_insn_closure_up copy_insn_closure;
205 };
187b041e 206
480af54c 207 std::vector<displaced_step_buffer> m_buffers;
c7acb87b
SM
208};
209
bab37966 210#endif /* DISPLACED_STEPPING_H */
This page took 0.087758 seconds and 4 git commands to generate.