Commit | Line | Data |
---|---|---|
e088209c SM |
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; | |
d6864985 SM |
70 | |
71 | bool unavailable = false; | |
e088209c SM |
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 */ |