3 #include "displaced-stepping.h"
11 displaced_step_copy_insn_closure::~displaced_step_copy_insn_closure() = default;
13 displaced_step_prepare_status
14 single_displaced_buffer_manager::prepare (thread_info
*thread
)
16 /* Is a thread currently using the buffer? */
17 if (m_current_thread
!= nullptr)
19 /* If so, it better not be this thread. */
20 gdb_assert (thread
!= m_current_thread
);
21 return DISPLACED_STEP_PREPARE_STATUS_UNAVAILABLE
;
24 gdbarch
*arch
= thread
->arch ();
25 struct regcache
*regcache
= thread
->regcache ();
26 ULONGEST len
= gdbarch_max_insn_length (arch
);
27 m_original_pc
= regcache_read_pc (regcache
);
29 /* Save the original contents of the displaced stepping buffer. */
30 m_saved_copy
.resize (len
);
32 int status
= target_read_memory (m_buffer_addr
, m_saved_copy
.data (), len
);
34 throw_error (MEMORY_ERROR
,
35 _("Error accessing memory address %s (%s) for "
36 "displaced-stepping scratch space."),
37 paddress (arch
, m_buffer_addr
), safe_strerror (status
));
41 fprintf_unfiltered (gdb_stdlog
, "displaced: saved %s: ",
42 paddress (arch
, m_buffer_addr
));
43 displaced_step_dump_bytes (gdb_stdlog
, m_saved_copy
.data (), len
);
46 m_copy_insn_closure
= gdbarch_displaced_step_copy_insn (arch
,
50 if (m_copy_insn_closure
== nullptr)
52 /* The architecture doesn't know how or want to displaced step
53 this instruction or instruction sequence. Fallback to
54 stepping over the breakpoint in-line. */
55 return DISPLACED_STEP_PREPARE_STATUS_ERROR
;
60 /* Resume execution at the copy. */
61 regcache_write_pc (regcache
, m_buffer_addr
);
65 /* Failed to write the PC. Release the architecture's displaced
66 stepping resources and the thread's displaced stepping state. */
67 m_copy_insn_closure
.reset ();
69 return DISPLACED_STEP_PREPARE_STATUS_ERROR
;
72 /* This marks the buffer as being in use. */
73 m_current_thread
= thread
;
75 return DISPLACED_STEP_PREPARE_STATUS_OK
;
79 write_memory_ptid (ptid_t ptid
, CORE_ADDR memaddr
,
80 const gdb_byte
*myaddr
, int len
)
82 scoped_restore save_inferior_ptid
= make_scoped_restore (&inferior_ptid
);
85 write_memory (memaddr
, myaddr
, len
);
89 displaced_step_instruction_executed_successfully (gdbarch
*arch
, gdb_signal signal
)
91 if (signal
!= GDB_SIGNAL_TRAP
)
94 if (target_stopped_by_watchpoint ())
96 // FIXME: Not sure about this condition.
97 if (gdbarch_have_nonsteppable_watchpoint (arch
)
98 || target_have_steppable_watchpoint
)
105 displaced_step_finish_status
106 single_displaced_buffer_manager::finish (gdbarch
*arch
, thread_info
*thread
,
109 displaced_step_finish_status status
;
111 gdb_assert (thread
== m_current_thread
);
113 ULONGEST len
= gdbarch_max_insn_length (arch
);
115 write_memory_ptid (thread
->ptid
, m_buffer_addr
,
116 m_saved_copy
.data (), len
);
118 fprintf_unfiltered (gdb_stdlog
, "displaced: restored %s %s\n",
119 target_pid_to_str (thread
->ptid
).c_str (),
120 paddress (arch
, m_buffer_addr
));
122 regcache
*rc
= get_thread_regcache (thread
);
124 bool instruction_executed_successfully
125 = displaced_step_instruction_executed_successfully (arch
, sig
);
128 if (instruction_executed_successfully
)
130 gdbarch_displaced_step_fixup (arch
, m_copy_insn_closure
.get (), m_original_pc
,
132 status
= DISPLACED_STEP_FINISH_STATUS_OK
;
136 /* Since the instruction didn't complete, all we can do is relocate the
138 CORE_ADDR pc
= regcache_read_pc (rc
);
139 pc
= m_original_pc
+ (pc
- m_buffer_addr
);
140 regcache_write_pc (rc
, pc
);
141 status
= DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED
;
144 m_copy_insn_closure
.reset ();
145 m_current_thread
= nullptr;