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
->displaced_step_state
.in_progress ());
17 displaced_step_buffer_state
*buffer
= nullptr;
20 for (displaced_step_buffer_state
&buf
: m_buffers
)
21 gdb_assert (buf
.m_current_thread
!= thread
);
23 /* Search for an unused buffer. */
24 for (displaced_step_buffer_state
&candidate
: m_buffers
)
26 if (candidate
.m_current_thread
== nullptr)
33 if (buffer
== nullptr)
34 return DISPLACED_STEP_PREPARE_STATUS_UNAVAILABLE
;
36 gdbarch
*arch
= thread
->arch ();
39 fprintf_unfiltered (gdb_stdlog
, "displaced: selected buffer at %s\n",
40 paddress (arch
, buffer
->m_buffer_addr
));
42 struct regcache
*regcache
= thread
->regcache ();
43 ULONGEST len
= gdbarch_max_insn_length (arch
);
44 buffer
->m_original_pc
= regcache_read_pc (regcache
);
46 /* Save the original contents of the displaced stepping buffer. */
47 buffer
->m_saved_copy
.resize (len
);
49 int status
= target_read_memory (buffer
->m_buffer_addr
, buffer
->m_saved_copy
.data (), len
);
51 throw_error (MEMORY_ERROR
,
52 _("Error accessing memory address %s (%s) for "
53 "displaced-stepping scratch space."),
54 paddress (arch
, buffer
->m_buffer_addr
), safe_strerror (status
));
58 fprintf_unfiltered (gdb_stdlog
, "displaced: saved %s: ",
59 paddress (arch
, buffer
->m_buffer_addr
));
60 displaced_step_dump_bytes (gdb_stdlog
, buffer
->m_saved_copy
.data (), len
);
63 buffer
->m_copy_insn_closure
64 = gdbarch_displaced_step_copy_insn (arch
, buffer
->m_original_pc
,
65 buffer
->m_buffer_addr
, regcache
);
66 if (buffer
->m_copy_insn_closure
== nullptr)
68 /* The architecture doesn't know how or want to displaced step
69 this instruction or instruction sequence. Fallback to
70 stepping over the breakpoint in-line. */
71 return DISPLACED_STEP_PREPARE_STATUS_ERROR
;
76 /* Resume execution at the copy. */
77 regcache_write_pc (regcache
, buffer
->m_buffer_addr
);
81 /* Failed to write the PC. Release the architecture's displaced
82 stepping resources and the thread's displaced stepping state. */
83 buffer
->m_copy_insn_closure
.reset ();
85 return DISPLACED_STEP_PREPARE_STATUS_ERROR
;
88 /* This marks the buffer as being in use. */
89 buffer
->m_current_thread
= thread
;
91 return DISPLACED_STEP_PREPARE_STATUS_OK
;
95 write_memory_ptid (ptid_t ptid
, CORE_ADDR memaddr
,
96 const gdb_byte
*myaddr
, int len
)
98 scoped_restore save_inferior_ptid
= make_scoped_restore (&inferior_ptid
);
100 inferior_ptid
= ptid
;
101 write_memory (memaddr
, myaddr
, len
);
105 displaced_step_instruction_executed_successfully (gdbarch
*arch
, gdb_signal signal
)
107 if (signal
!= GDB_SIGNAL_TRAP
)
110 if (target_stopped_by_watchpoint ())
112 // FIXME: Not sure about this condition.
113 if (gdbarch_have_nonsteppable_watchpoint (arch
)
114 || target_have_steppable_watchpoint
)
121 displaced_step_finish_status
122 multiple_displaced_buffer_manager::finish (gdbarch
*arch
, thread_info
*thread
,
125 displaced_step_finish_status status
;
126 displaced_step_buffer_state
*buffer
= nullptr;
128 gdb_assert (thread
->displaced_step_state
.in_progress ());
130 /* Find the buffer this thread was using. */
131 for (displaced_step_buffer_state
&candidate
: m_buffers
)
133 if (thread
== candidate
.m_current_thread
)
140 gdb_assert (buffer
!= nullptr);
142 ULONGEST len
= gdbarch_max_insn_length (arch
);
144 /* Restore memory of the buffer. */
145 write_memory_ptid (thread
->ptid
, buffer
->m_buffer_addr
,
146 buffer
->m_saved_copy
.data (), len
);
148 fprintf_unfiltered (gdb_stdlog
, "displaced: restored %s %s\n",
149 target_pid_to_str (thread
->ptid
).c_str (),
150 paddress (arch
, buffer
->m_buffer_addr
));
152 regcache
*rc
= get_thread_regcache (thread
);
154 bool instruction_executed_successfully
155 = displaced_step_instruction_executed_successfully (arch
, sig
);
157 if (instruction_executed_successfully
)
159 gdbarch_displaced_step_fixup (arch
, buffer
->m_copy_insn_closure
.get (),
160 buffer
->m_original_pc
,
161 buffer
->m_buffer_addr
, rc
);
162 status
= DISPLACED_STEP_FINISH_STATUS_OK
;
166 /* Since the instruction didn't complete, all we can do is relocate the
168 CORE_ADDR pc
= regcache_read_pc (rc
);
169 pc
= buffer
->m_original_pc
+ (pc
- buffer
->m_buffer_addr
);
170 regcache_write_pc (rc
, pc
);
171 status
= DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED
;
174 buffer
->m_copy_insn_closure
.reset ();
175 buffer
->m_current_thread
= nullptr;