3 #include "displaced-stepping.h"
11 displaced_step_copy_insn_closure::~displaced_step_copy_insn_closure() = default;
13 displaced_step_prepare_status
14 multiple_displaced_buffer_manager::prepare (thread_info
*thread
)
16 gdb_assert (thread
!= nullptr);
18 gdbarch
*arch
= thread
->arch ();
20 /* This class requires that the arch implements both copy_insn and fixup. */
21 gdb_assert (gdbarch_displaced_step_copy_insn_p (arch
));
22 gdb_assert (gdbarch_displaced_step_fixup_p (arch
));
24 /* It's invalid to `prepare` a thread that already has a displaced step in
26 gdb_assert (!thread
->displaced_step_state
.in_progress ());
28 /* Sanity check: no buffer is currently assigned to this thread. */
29 for (displaced_step_buffer_state
&buf
: m_buffers
)
30 gdb_assert (buf
.m_current_thread
!= thread
);
32 /* Search for an unused buffer. */
33 displaced_step_buffer_state
*buffer
= nullptr;
35 for (displaced_step_buffer_state
&candidate
: m_buffers
)
37 if (candidate
.m_current_thread
== nullptr)
44 if (buffer
== nullptr)
45 return DISPLACED_STEP_PREPARE_STATUS_UNAVAILABLE
;
49 fprintf_unfiltered (gdb_stdlog
, "displaced: selected buffer at %s\n",
50 paddress (arch
, buffer
->m_buffer_addr
));
52 struct regcache
*regcache
= thread
->regcache ();
53 ULONGEST len
= gdbarch_max_insn_length (arch
);
54 buffer
->m_original_pc
= regcache_read_pc (regcache
);
56 /* Save the original contents of the displaced stepping buffer. */
57 buffer
->m_saved_copy
.resize (len
);
59 int status
= target_read_memory (buffer
->m_buffer_addr
, buffer
->m_saved_copy
.data (), len
);
61 throw_error (MEMORY_ERROR
,
62 _("Error accessing memory address %s (%s) for "
63 "displaced-stepping scratch space."),
64 paddress (arch
, buffer
->m_buffer_addr
), safe_strerror (status
));
68 fprintf_unfiltered (gdb_stdlog
, "displaced: saved %s: ",
69 paddress (arch
, buffer
->m_buffer_addr
));
70 displaced_step_dump_bytes (gdb_stdlog
, buffer
->m_saved_copy
.data (), len
);
73 buffer
->m_copy_insn_closure
74 = gdbarch_displaced_step_copy_insn (arch
, buffer
->m_original_pc
,
75 buffer
->m_buffer_addr
, regcache
);
76 if (buffer
->m_copy_insn_closure
== nullptr)
78 /* The architecture doesn't know how or want to displaced step
79 this instruction or instruction sequence. Fallback to
80 stepping over the breakpoint in-line. */
81 return DISPLACED_STEP_PREPARE_STATUS_ERROR
;
86 /* Resume execution at the copy. */
87 regcache_write_pc (regcache
, buffer
->m_buffer_addr
);
91 /* Failed to write the PC. Release the architecture's displaced
92 stepping resources and the thread's displaced stepping state. */
93 buffer
->m_copy_insn_closure
.reset ();
95 return DISPLACED_STEP_PREPARE_STATUS_ERROR
;
98 /* This marks the buffer as being in use. */
99 buffer
->m_current_thread
= thread
;
101 return DISPLACED_STEP_PREPARE_STATUS_OK
;
105 write_memory_ptid (ptid_t ptid
, CORE_ADDR memaddr
,
106 const gdb_byte
*myaddr
, int len
)
108 scoped_restore save_inferior_ptid
= make_scoped_restore (&inferior_ptid
);
110 inferior_ptid
= ptid
;
111 write_memory (memaddr
, myaddr
, len
);
115 displaced_step_instruction_executed_successfully (gdbarch
*arch
, gdb_signal signal
)
117 if (signal
!= GDB_SIGNAL_TRAP
)
120 if (target_stopped_by_watchpoint ())
122 // FIXME: Not sure about this condition.
123 if (gdbarch_have_nonsteppable_watchpoint (arch
)
124 || target_have_steppable_watchpoint
)
131 displaced_step_finish_status
132 multiple_displaced_buffer_manager::finish (gdbarch
*arch
, thread_info
*thread
,
135 displaced_step_finish_status status
;
136 displaced_step_buffer_state
*buffer
= nullptr;
138 gdb_assert (thread
->displaced_step_state
.in_progress ());
140 /* Find the buffer this thread was using. */
141 for (displaced_step_buffer_state
&candidate
: m_buffers
)
143 if (thread
== candidate
.m_current_thread
)
150 gdb_assert (buffer
!= nullptr);
152 ULONGEST len
= gdbarch_max_insn_length (arch
);
154 /* Restore memory of the buffer. */
155 write_memory_ptid (thread
->ptid
, buffer
->m_buffer_addr
,
156 buffer
->m_saved_copy
.data (), len
);
158 fprintf_unfiltered (gdb_stdlog
, "displaced: restored %s %s\n",
159 target_pid_to_str (thread
->ptid
).c_str (),
160 paddress (arch
, buffer
->m_buffer_addr
));
162 regcache
*rc
= get_thread_regcache (thread
);
164 bool instruction_executed_successfully
165 = displaced_step_instruction_executed_successfully (arch
, sig
);
167 if (instruction_executed_successfully
)
169 gdbarch_displaced_step_fixup (arch
, buffer
->m_copy_insn_closure
.get (),
170 buffer
->m_original_pc
,
171 buffer
->m_buffer_addr
, rc
);
172 status
= DISPLACED_STEP_FINISH_STATUS_OK
;
176 /* Since the instruction didn't complete, all we can do is relocate the
178 CORE_ADDR pc
= regcache_read_pc (rc
);
179 pc
= buffer
->m_original_pc
+ (pc
- buffer
->m_buffer_addr
);
180 regcache_write_pc (rc
, pc
);
181 status
= DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED
;
184 buffer
->m_copy_insn_closure
.reset ();
185 buffer
->m_current_thread
= nullptr;
190 displaced_step_prepare_status
191 default_displaced_step_prepare (target_ops
*target
, thread_info
*thread
)
193 gdbarch
*arch
= thread
->arch ();
194 return gdbarch_displaced_step_prepare (arch
, thread
);
197 displaced_step_finish_status
198 default_displaced_step_finish (target_ops
*target
,
202 gdbarch
*arch
= thread
->arch ();
203 return gdbarch_displaced_step_finish (arch
, thread
, sig
);