gdb: stop trying to prepare displaced steps for an inferior when it returns _UNAVAILABLE
[deliverable/binutils-gdb.git] / gdb / displaced-stepping.h
1 #ifndef DISPLACED_STEPPING_H
2 #define DISPLACED_STEPPING_H
3
4 #include "gdbsupport/byte-vector.h"
5
6 struct gdbarch;
7 struct thread_info;
8
9 enum displaced_step_prepare_status
10 {
11 /* A displaced stepping buffer was successfully allocated and prepared. */
12 DISPLACED_STEP_PREPARE_STATUS_OK,
13
14 /* Something bad happened. */
15 DISPLACED_STEP_PREPARE_STATUS_ERROR,
16
17 /* Not enough resources are available at this time, try again later. */
18 DISPLACED_STEP_PREPARE_STATUS_UNAVAILABLE,
19 };
20
21 enum displaced_step_finish_status
22 {
23 /* The instruction was stepped and fixed up. */
24 DISPLACED_STEP_FINISH_STATUS_OK,
25
26 /* The instruction was not stepped. */
27 DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED,
28 };
29
30 /* Data returned by a gdbarch displaced_step_copy_insn method, to be passed to
31 the matching displaced_step_fixup method. */
32
33 struct displaced_step_copy_insn_closure
34 {
35 virtual ~displaced_step_copy_insn_closure () = 0;
36 };
37
38 typedef std::unique_ptr<displaced_step_copy_insn_closure>
39 displaced_step_copy_insn_closure_up;
40
41 /* A simple displaced step closure that contains only a byte buffer. */
42
43 struct buf_displaced_step_copy_insn_closure : displaced_step_copy_insn_closure
44 {
45 buf_displaced_step_copy_insn_closure (int buf_size)
46 : buf (buf_size)
47 {}
48
49 gdb::byte_vector buf;
50 };
51
52 /* Per-inferior displaced stepping state. */
53
54 struct displaced_step_inferior_state
55 {
56 displaced_step_inferior_state ()
57 {
58 reset ();
59 }
60
61 /* Put this object back in its original state. */
62 void reset ()
63 {
64 failed_before = false;
65 }
66
67 /* True if preparing a displaced step ever failed. If so, we won't
68 try displaced stepping for this inferior again. */
69 bool failed_before;
70
71 bool unavailable = false;
72 };
73
74 /* Per-thread displaced stepping state. */
75
76 struct displaced_step_thread_state
77 {
78 /* Return true if this thread is currently executing a displaced step. */
79 bool in_progress () const
80 { return m_original_gdbarch != nullptr; }
81
82 /* Return the gdbarch of the thread prior to the step. */
83 gdbarch *get_original_gdbarch () const
84 { return m_original_gdbarch; }
85
86 /* Mark this thread as currently executing a displaced step.
87
88 ORIGINAL_GDBARCH is the current gdbarch of the thread (before the step
89 is executed). */
90 void set (gdbarch *original_gdbarch)
91 { m_original_gdbarch = original_gdbarch; }
92
93 /* mark this thread as no longer executing a displaced step. */
94 void reset ()
95 { m_original_gdbarch = nullptr; }
96
97 private:
98 gdbarch *m_original_gdbarch = nullptr;
99 };
100
101 /* Manage access to a single displaced stepping buffer, without any
102 sharing. */
103
104 struct single_displaced_buffer_manager
105 {
106 single_displaced_buffer_manager (CORE_ADDR buffer_addr)
107 : m_buffer_addr (buffer_addr)
108 {}
109
110 displaced_step_prepare_status prepare (thread_info *thread);
111
112 displaced_step_finish_status finish (gdbarch *arch, thread_info *thread,
113 gdb_signal sig);
114
115 private:
116
117 CORE_ADDR m_original_pc;
118 CORE_ADDR m_buffer_addr;
119
120 /* If set, the thread currently using the buffer. */
121 thread_info *m_current_thread = nullptr;
122
123 gdb::byte_vector m_saved_copy;
124 displaced_step_copy_insn_closure_up m_copy_insn_closure;
125 };
126
127
128 #endif /* DISPLACED_STEPPING_H */
This page took 0.032193 seconds and 4 git commands to generate.