Commit 480af54c authored by Simon Marchi's avatar Simon Marchi
Browse files

gdb: make displaced stepping implementation capable of managing multiple buffers

The displaced_step_buffer class, introduced in the previous patch,
manages access to a single displaced step buffer.  Change it into
displaced_step_buffers (note the plural), which manages access to
multiple displaced step buffers.

When preparing a displaced step for a thread, it looks for an unused
buffer.

For now, all users still pass a single displaced step buffer, so no real
behavior change is expected here.  The following patch makes a user pass
more than one buffer, so the functionality introduced by this patch is
going to be useful in the next one.

gdb/ChangeLog:

	* displaced-stepping.h (struct displaced_step_buffer): Rename
	to...
	(struct displaced_step_buffers): ... this.
	<m_addr, m_current_thread, m_copy_insn_closure>: Remove.
	<struct displaced_step_buffer>: New inner class.
	<m_buffers>: New.
	* displaced-stepping.c (displaced_step_buffer::prepare): Rename
	to...
	(displaced_step_buffers::prepare): ... this, adjust for multiple
	buffers.
	(displaced_step_buffer::finish):  Rename to...
	(displaced_step_buffers::finish): ... this, adjust for multiple
	buffers.
	(displaced_step_buffer::copy_insn_closure_by_addr): Rename to...
	(displaced_step_buffers::copy_insn_closure_by_addr): ... this,
	adjust for multiple buffers.
	(displaced_step_buffer::restore_in_ptid): Rename to...
	(displaced_step_buffers::restore_in_ptid): ... this, adjust for
	multiple buffers.
	* linux-tdep.h (linux_init_abi): Change supports_displaced_step
	for num_disp_step_buffers.
	* linux-tdep.c (struct linux_gdbarch_data)
	<num_disp_step_buffers>: New field.
	(struct linux_info) <disp_step_buf>: Rename to...
	<disp_step_bufs>: ... this, change type to
	displaced_step_buffers.
	(linux_displaced_step_prepare): Use
	linux_gdbarch_data::num_disp_step_buffers to create that number
	of buffers.
	(linux_displaced_step_finish): Adjust.
	(linux_displaced_step_copy_insn_closure_by_addr): Adjust.
	(linux_displaced_step_restore_all_in_ptid): Adjust.
	(linux_init_abi): Change supports_displaced_step parameter for
	num_disp_step_buffers, save it in linux_gdbarch_data.
	* aarch64-linux-tdep.c (aarch64_linux_init_abi): Adjust.
	* alpha-linux-tdep.c (alpha_linux_init_abi): Adjust.
	* amd64-linux-tdep.c (amd64_linux_init_abi_common): Change
	supports_displaced_step parameter for num_disp_step_buffers.
	(amd64_linux_init_abi): Adjust.
	(amd64_x32_linux_init_abi): Adjust.
	* arc-linux-tdep.c (arc_linux_init_osabi): Adjust.
	* arm-linux-tdep.c (arm_linux_init_abi): Adjust.
	* bfin-linux-tdep.c (bfin_linux_init_abi): Adjust.
	* cris-linux-tdep.c (cris_linux_init_abi): Adjust.
	* csky-linux-tdep.c (csky_linux_init_abi): Adjust.
	* frv-linux-tdep.c (frv_linux_init_abi): Adjust.
	* hppa-linux-tdep.c (hppa_linux_init_abi): Adjust.
	* i386-linux-tdep.c (i386_linux_init_abi): Adjust.
	* ia64-linux-tdep.c (ia64_linux_init_abi): Adjust.
	* m32r-linux-tdep.c (m32r_linux_init_abi): Adjust.
	* m68k-linux-tdep.c (m68k_linux_init_abi):
	* microblaze-linux-tdep.c (microblaze_linux_init_abi):
	* mips-linux-tdep.c (mips_linux_init_abi): Adjust.
	* mn10300-linux-tdep.c (am33_linux_init_osabi): Adjust.
	* nios2-linux-tdep.c (nios2_linux_init_abi): Adjust.
	* or1k-linux-tdep.c (or1k_linux_init_abi): Adjust.
	* ppc-linux-tdep.c (ppc_linux_init_abi): Adjust.
	* riscv-linux-tdep.c (riscv_linux_init_abi): Adjust.
	* rs6000-tdep.c (struct ppc_inferior_data) <disp_step_buf>:
	Change type to displaced_step_buffers.
	* s390-linux-tdep.c (s390_linux_init_abi_any): Adjust.
	* sh-linux-tdep.c (sh_linux_init_abi): Adjust.
	* sparc-linux-tdep.c (sparc32_linux_init_abi): Adjust.
	* sparc64-linux-tdep.c (sparc64_linux_init_abi): Adjust.
	* tic6x-linux-tdep.c (tic6x_uclinux_init_abi): Adjust.
	* tilegx-linux-tdep.c (tilegx_linux_init_abi): Adjust.
	* xtensa-linux-tdep.c (xtensa_linux_init_abi): Adjust.

Change-Id: Ia9c02f207da2c9e1d9188020139619122392bb70
parent d9655058
2020-12-04 Simon Marchi <simon.marchi@efficios.com>
* displaced-stepping.h (struct displaced_step_buffer): Rename
to...
(struct displaced_step_buffers): ... this.
<m_addr, m_current_thread, m_copy_insn_closure>: Remove.
<struct displaced_step_buffer>: New inner class.
<m_buffers>: New.
* displaced-stepping.c (displaced_step_buffer::prepare): Rename
to...
(displaced_step_buffers::prepare): ... this, adjust for multiple
buffers.
(displaced_step_buffer::finish): Rename to...
(displaced_step_buffers::finish): ... this, adjust for multiple
buffers.
(displaced_step_buffer::copy_insn_closure_by_addr): Rename to...
(displaced_step_buffers::copy_insn_closure_by_addr): ... this,
adjust for multiple buffers.
(displaced_step_buffer::restore_in_ptid): Rename to...
(displaced_step_buffers::restore_in_ptid): ... this, adjust for
multiple buffers.
* linux-tdep.h (linux_init_abi): Change supports_displaced_step
for num_disp_step_buffers.
* linux-tdep.c (struct linux_gdbarch_data)
<num_disp_step_buffers>: New field.
(struct linux_info) <disp_step_buf>: Rename to...
<disp_step_bufs>: ... this, change type to
displaced_step_buffers.
(linux_displaced_step_prepare): Use
linux_gdbarch_data::num_disp_step_buffers to create that number
of buffers.
(linux_displaced_step_finish): Adjust.
(linux_displaced_step_copy_insn_closure_by_addr): Adjust.
(linux_displaced_step_restore_all_in_ptid): Adjust.
(linux_init_abi): Change supports_displaced_step parameter for
num_disp_step_buffers, save it in linux_gdbarch_data.
* aarch64-linux-tdep.c (aarch64_linux_init_abi): Adjust.
* alpha-linux-tdep.c (alpha_linux_init_abi): Adjust.
* amd64-linux-tdep.c (amd64_linux_init_abi_common): Change
supports_displaced_step parameter for num_disp_step_buffers.
(amd64_linux_init_abi): Adjust.
(amd64_x32_linux_init_abi): Adjust.
* arc-linux-tdep.c (arc_linux_init_osabi): Adjust.
* arm-linux-tdep.c (arm_linux_init_abi): Adjust.
* bfin-linux-tdep.c (bfin_linux_init_abi): Adjust.
* cris-linux-tdep.c (cris_linux_init_abi): Adjust.
* csky-linux-tdep.c (csky_linux_init_abi): Adjust.
* frv-linux-tdep.c (frv_linux_init_abi): Adjust.
* hppa-linux-tdep.c (hppa_linux_init_abi): Adjust.
* i386-linux-tdep.c (i386_linux_init_abi): Adjust.
* ia64-linux-tdep.c (ia64_linux_init_abi): Adjust.
* m32r-linux-tdep.c (m32r_linux_init_abi): Adjust.
* m68k-linux-tdep.c (m68k_linux_init_abi):
* microblaze-linux-tdep.c (microblaze_linux_init_abi):
* mips-linux-tdep.c (mips_linux_init_abi): Adjust.
* mn10300-linux-tdep.c (am33_linux_init_osabi): Adjust.
* nios2-linux-tdep.c (nios2_linux_init_abi): Adjust.
* or1k-linux-tdep.c (or1k_linux_init_abi): Adjust.
* ppc-linux-tdep.c (ppc_linux_init_abi): Adjust.
* riscv-linux-tdep.c (riscv_linux_init_abi): Adjust.
* rs6000-tdep.c (struct ppc_inferior_data) <disp_step_buf>:
Change type to displaced_step_buffers.
* s390-linux-tdep.c (s390_linux_init_abi_any): Adjust.
* sh-linux-tdep.c (sh_linux_init_abi): Adjust.
* sparc-linux-tdep.c (sparc32_linux_init_abi): Adjust.
* sparc64-linux-tdep.c (sparc64_linux_init_abi): Adjust.
* tic6x-linux-tdep.c (tic6x_uclinux_init_abi): Adjust.
* tilegx-linux-tdep.c (tilegx_linux_init_abi): Adjust.
* xtensa-linux-tdep.c (xtensa_linux_init_abi): Adjust.
2020-12-04 Simon Marchi <simon.marchi@efficios.com>
 
* linux-tdep.c (init_linux_gdbarch_data): Change parameter to
......
......@@ -1445,7 +1445,7 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
tdep->lowest_pc = 0x8000;
linux_init_abi (info, gdbarch, true);
linux_init_abi (info, gdbarch, 1);
set_solib_svr4_fetch_link_map_offsets (gdbarch,
svr4_lp64_fetch_link_map_offsets);
......
......@@ -356,7 +356,7 @@ alpha_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
struct gdbarch_tdep *tdep;
linux_init_abi (info, gdbarch, false);
linux_init_abi (info, gdbarch, 0);
/* Hook into the DWARF CFI frame unwinder. */
alpha_dwarf2_init_abi (info, gdbarch);
......
......@@ -1796,11 +1796,11 @@ amd64_dtrace_parse_probe_argument (struct gdbarch *gdbarch,
static void
amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch,
bool supports_displaced_step)
int num_disp_step_buffers)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
linux_init_abi (info, gdbarch, supports_displaced_step);
linux_init_abi (info, gdbarch, num_disp_step_buffers);
tdep->sigtramp_p = amd64_linux_sigtramp_p;
tdep->sigcontext_addr = amd64_linux_sigcontext_addr;
......@@ -1880,7 +1880,7 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
if (!valid_p)
return;
amd64_linux_init_abi_common (info, gdbarch, true);
amd64_linux_init_abi_common (info, gdbarch, 1);
/* Initialize the amd64_linux_record_tdep. */
/* These values are the size of the type that will be used in a system
......@@ -2095,7 +2095,7 @@ amd64_x32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
if (!valid_p)
return;
amd64_linux_init_abi_common (info, gdbarch, false);
amd64_linux_init_abi_common (info, gdbarch, 0);
/* Initialize the amd64_x32_linux_record_tdep. */
/* These values are the size of the type that will be used in a system
......
......@@ -439,7 +439,7 @@ arc_linux_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
*/
tdep->jb_pc = 15;
linux_init_abi (info, gdbarch, false);
linux_init_abi (info, gdbarch, 0);
/* Set up target dependent GDB architecture entries. */
set_gdbarch_cannot_fetch_register (gdbarch, arc_linux_cannot_fetch_register);
......
......@@ -1721,7 +1721,7 @@ arm_linux_init_abi (struct gdbarch_info info,
NULL };
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
linux_init_abi (info, gdbarch, true);
linux_init_abi (info, gdbarch, 1);
tdep->lowest_pc = 0x8000;
if (info.byte_order_for_code == BFD_ENDIAN_BIG)
......
......@@ -150,7 +150,7 @@ bfin_linux_get_syscall_number (struct gdbarch *gdbarch,
static void
bfin_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
linux_init_abi (info, gdbarch, false);
linux_init_abi (info, gdbarch, 0);
/* Set the sigtramp frame sniffer. */
tramp_frame_prepend_unwinder (gdbarch, &bfin_linux_sigframe);
......
......@@ -35,7 +35,7 @@ cris_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
linux_init_abi (info, gdbarch, false);
linux_init_abi (info, gdbarch, 0);
if (tdep->cris_version == 32)
/* Threaded debugging is only supported on CRISv32 for now. */
......
......@@ -233,7 +233,7 @@ csky_linux_rt_sigreturn_tramp_frame = {
static void
csky_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
linux_init_abi (info, gdbarch, false);
linux_init_abi (info, gdbarch, 0);
/* Shared library handling. */
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
......
......@@ -44,82 +44,121 @@ show_debug_displaced (struct ui_file *file, int from_tty,
}
displaced_step_prepare_status
displaced_step_buffer::prepare (thread_info *thread, CORE_ADDR &displaced_pc)
displaced_step_buffers::prepare (thread_info *thread, CORE_ADDR &displaced_pc)
{
gdb_assert (!thread->displaced_step_state.in_progress ());
/* Is a thread currently using the buffer? */
if (m_current_thread != nullptr)
{
/* If so, it better not be this thread. */
gdb_assert (thread != m_current_thread);
return DISPLACED_STEP_PREPARE_STATUS_UNAVAILABLE;
}
/* Sanity check: the thread should not be using a buffer at this point. */
for (displaced_step_buffer &buf : m_buffers)
gdb_assert (buf.current_thread != thread);
regcache *regcache = get_thread_regcache (thread);
const address_space *aspace = regcache->aspace ();
gdbarch *arch = regcache->arch ();
ULONGEST len = gdbarch_max_insn_length (arch);
if (breakpoint_in_range_p (aspace, m_addr, len))
{
/* There's a breakpoint set in the scratch pad location range
(which is usually around the entry point). We'd either
install it before resuming, which would overwrite/corrupt the
scratch pad, or if it was already inserted, this displaced
step would overwrite it. The latter is OK in the sense that
we already assume that no thread is going to execute the code
in the scratch pad range (after initial startup) anyway, but
the former is unacceptable. Simply punt and fallback to
stepping over this breakpoint in-line. */
displaced_debug_printf ("breakpoint set in scratch pad. "
"Stepping over breakpoint in-line instead.");
/* Search for an unused buffer. */
displaced_step_buffer *buffer = nullptr;
displaced_step_prepare_status fail_status
= DISPLACED_STEP_PREPARE_STATUS_CANT;
return DISPLACED_STEP_PREPARE_STATUS_CANT;
for (displaced_step_buffer &candidate : m_buffers)
{
bool bp_in_range = breakpoint_in_range_p (aspace, candidate.addr, len);
bool is_free = candidate.current_thread == nullptr;
if (!bp_in_range)
{
if (is_free)
{
buffer = &candidate;
break;
}
else
{
/* This buffer would be suitable, but it's used right now. */
fail_status = DISPLACED_STEP_PREPARE_STATUS_UNAVAILABLE;
}
}
else
{
/* There's a breakpoint set in the scratch pad location range
(which is usually around the entry point). We'd either
install it before resuming, which would overwrite/corrupt the
scratch pad, or if it was already inserted, this displaced
step would overwrite it. The latter is OK in the sense that
we already assume that no thread is going to execute the code
in the scratch pad range (after initial startup) anyway, but
the former is unacceptable. Simply punt and fallback to
stepping over this breakpoint in-line. */
displaced_debug_printf ("breakpoint set in displaced stepping "
"buffer at %s, can't use.",
paddress (arch, candidate.addr));
}
}
m_original_pc = regcache_read_pc (regcache);
displaced_pc = m_addr;
if (buffer == nullptr)
return fail_status;
displaced_debug_printf ("selected buffer at %s",
paddress (arch, buffer->addr));
/* Save the original PC of the thread. */
buffer->original_pc = regcache_read_pc (regcache);
/* Return displaced step buffer address to caller. */
displaced_pc = buffer->addr;
/* Save the original contents of the displaced stepping buffer. */
m_saved_copy.resize (len);
buffer->saved_copy.resize (len);
int status = target_read_memory (m_addr, m_saved_copy.data (), len);
int status = target_read_memory (buffer->addr,
buffer->saved_copy.data (), len);
if (status != 0)
throw_error (MEMORY_ERROR,
_("Error accessing memory address %s (%s) for "
"displaced-stepping scratch space."),
paddress (arch, m_addr), safe_strerror (status));
paddress (arch, buffer->addr), safe_strerror (status));
displaced_debug_printf ("saved %s: %s",
paddress (arch, m_addr),
paddress (arch, buffer->addr),
displaced_step_dump_bytes
(m_saved_copy.data (), len).c_str ());
(buffer->saved_copy.data (), len).c_str ());
/* Save this in a local variable first, so it's released if code below
throws. */
displaced_step_copy_insn_closure_up copy_insn_closure
= gdbarch_displaced_step_copy_insn (arch, m_original_pc, m_addr, regcache);
= gdbarch_displaced_step_copy_insn (arch, buffer->original_pc,
buffer->addr, regcache);
if (copy_insn_closure == nullptr)
{
/* The architecture doesn't know how or want to displaced step
this instruction or instruction sequence. Fallback to
stepping over the breakpoint in-line. */
this instruction or instruction sequence. Fallback to
stepping over the breakpoint in-line. */
return DISPLACED_STEP_PREPARE_STATUS_CANT;
}
/* Resume execution at the copy. */
regcache_write_pc (regcache, m_addr);
regcache_write_pc (regcache, buffer->addr);
/* This marks the buffer as being in use. */
m_current_thread = thread;
buffer->current_thread = thread;
/* Save this, now that we know everything went fine. */
m_copy_insn_closure = std::move (copy_insn_closure);
buffer->copy_insn_closure = std::move (copy_insn_closure);
/* Tell infrun not to try preparing a displaced step again for this inferior. */
/* Tell infrun not to try preparing a displaced step again for this inferior if
all buffers are taken. */
thread->inf->displaced_step_state.unavailable = true;
for (const displaced_step_buffer &buf : m_buffers)
{
if (buf.current_thread == nullptr)
{
thread->inf->displaced_step_state.unavailable = false;
break;
}
}
return DISPLACED_STEP_PREPARE_STATUS_OK;
}
......@@ -152,21 +191,34 @@ displaced_step_instruction_executed_successfully (gdbarch *arch,
}
displaced_step_finish_status
displaced_step_buffer::finish (gdbarch *arch, thread_info *thread,
gdb_signal sig)
displaced_step_buffers::finish (gdbarch *arch, thread_info *thread,
gdb_signal sig)
{
gdb_assert (thread->displaced_step_state.in_progress ());
gdb_assert (thread == m_current_thread);
/* Find the buffer this thread was using. */
displaced_step_buffer *buffer = nullptr;
for (displaced_step_buffer &candidate : m_buffers)
{
if (candidate.current_thread == thread)
{
buffer = &candidate;
break;
}
}
gdb_assert (buffer != nullptr);
/* Move this to a local variable so it's released in case something goes
wrong. */
displaced_step_copy_insn_closure_up copy_insn_closure
= std::move (m_copy_insn_closure);
= std::move (buffer->copy_insn_closure);
gdb_assert (copy_insn_closure != nullptr);
/* Reset M_CURRENT_THREAD immediately to mark the buffer as available, in case
something goes wrong below. */
m_current_thread = nullptr;
/* Reset BUFFER->CURRENT_THREAD immediately to mark the buffer as available,
in case something goes wrong below. */
buffer->current_thread = nullptr;
/* Now that a buffer gets freed, tell infrun it can ask us to prepare a displaced
step again for this inferior. Do that here in case something goes wrong
......@@ -175,12 +227,13 @@ displaced_step_buffer::finish (gdbarch *arch, thread_info *thread,
ULONGEST len = gdbarch_max_insn_length (arch);
write_memory_ptid (thread->ptid, m_addr,
m_saved_copy.data (), len);
/* Restore memory of the buffer. */
write_memory_ptid (thread->ptid, buffer->addr,
buffer->saved_copy.data (), len);
displaced_debug_printf ("restored %s %s",
target_pid_to_str (thread->ptid).c_str (),
paddress (arch, m_addr));
paddress (arch, buffer->addr));
regcache *rc = get_thread_regcache (thread);
......@@ -189,8 +242,9 @@ displaced_step_buffer::finish (gdbarch *arch, thread_info *thread,
if (instruction_executed_successfully)
{
gdbarch_displaced_step_fixup (arch, copy_insn_closure.get (), m_original_pc,
m_addr, rc);
gdbarch_displaced_step_fixup (arch, copy_insn_closure.get (),
buffer->original_pc,
buffer->addr, rc);
return DISPLACED_STEP_FINISH_STATUS_OK;
}
else
......@@ -198,35 +252,41 @@ displaced_step_buffer::finish (gdbarch *arch, thread_info *thread,
/* Since the instruction didn't complete, all we can do is relocate the
PC. */
CORE_ADDR pc = regcache_read_pc (rc);
pc = m_original_pc + (pc - m_addr);
pc = buffer->original_pc + (pc - buffer->addr);
regcache_write_pc (rc, pc);
return DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED;
}
}
const displaced_step_copy_insn_closure *
displaced_step_buffer::copy_insn_closure_by_addr (CORE_ADDR addr)
displaced_step_buffers::copy_insn_closure_by_addr (CORE_ADDR addr)
{
if (addr == m_addr)
return m_copy_insn_closure.get ();
else
return nullptr;
for (const displaced_step_buffer &buffer : m_buffers)
{
if (addr == buffer.addr)
return buffer.copy_insn_closure.get ();
}
return nullptr;
}
void
displaced_step_buffer::restore_in_ptid (ptid_t ptid)
displaced_step_buffers::restore_in_ptid (ptid_t ptid)
{
if (m_current_thread != nullptr)
for (const displaced_step_buffer &buffer : m_buffers)
{
regcache *regcache = get_thread_regcache (m_current_thread);
if (buffer.current_thread == nullptr)
continue;
regcache *regcache = get_thread_regcache (buffer.current_thread);
gdbarch *arch = regcache->arch ();
ULONGEST len = gdbarch_max_insn_length (arch);
write_memory_ptid (ptid, m_addr, m_saved_copy.data (), len);
write_memory_ptid (ptid, buffer.addr, buffer.saved_copy.data (), len);
displaced_debug_printf ("restored in ptid %s %s",
target_pid_to_str (ptid).c_str (),
paddress (arch, m_addr));
paddress (arch, buffer.addr));
}
}
......
......@@ -20,6 +20,7 @@
#ifndef DISPLACED_STEPPING_H
#define DISPLACED_STEPPING_H
#include "gdbsupport/array-view.h"
#include "gdbsupport/byte-vector.h"
struct gdbarch;
......@@ -154,13 +155,19 @@ private:
gdbarch *m_original_gdbarch = nullptr;
};
/* Manage access to a single displaced stepping buffer. */
/* Control access to multiple displaced stepping buffers at fixed addresses. */
struct displaced_step_buffer
struct displaced_step_buffers
{
explicit displaced_step_buffer (CORE_ADDR buffer_addr)
: m_addr (buffer_addr)
{}
explicit displaced_step_buffers (gdb::array_view<CORE_ADDR> buffer_addrs)
{
gdb_assert (buffer_addrs.size () > 0);
m_buffers.reserve (buffer_addrs.size ());
for (CORE_ADDR buffer_addr : buffer_addrs)
m_buffers.emplace_back (buffer_addr);
}
displaced_step_prepare_status prepare (thread_info *thread,
CORE_ADDR &displaced_pc);
......@@ -174,21 +181,35 @@ struct displaced_step_buffer
void restore_in_ptid (ptid_t ptid);
private:
/* Original PC of the instruction being displaced-stepped in this buffer. */
CORE_ADDR m_original_pc = 0;
/* Address of the buffer. */
const CORE_ADDR m_addr;
/* State of a single buffer. */
struct displaced_step_buffer
{
explicit displaced_step_buffer (CORE_ADDR addr)
: addr (addr)
{}
/* Address of the buffer. */
const CORE_ADDR addr;
/* The original PC of the instruction currently being stepped. */
CORE_ADDR original_pc = 0;
/* If set, the thread currently using the buffer. If unset, the buffer is not
used. */
thread_info *current_thread = nullptr;
/* If set, the thread currently using the buffer. */
thread_info *m_current_thread = nullptr;
/* Saved copy of the bytes in the displaced buffer, to be restored once the
buffer is no longer used. */
gdb::byte_vector saved_copy;
/* Saved contents of copy area. */
gdb::byte_vector m_saved_copy;
/* Closure obtained from gdbarch_displaced_step_copy_insn, to be passed to
gdbarch_displaced_step_fixup_insn. */
displaced_step_copy_insn_closure_up copy_insn_closure;
};
/* The closure provided gdbarch_displaced_step_copy_insn, to be used
for post-step cleanup. */
displaced_step_copy_insn_closure_up m_copy_insn_closure;
std::vector<displaced_step_buffer> m_buffers;
};
#endif /* DISPLACED_STEPPING_H */
......@@ -456,7 +456,7 @@ frv_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
static void
frv_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
linux_init_abi (info, gdbarch, false);
linux_init_abi (info, gdbarch, 0);
/* Set the sigtramp frame sniffer. */
frame_unwind_append_unwinder (gdbarch, &frv_linux_sigtramp_frame_unwind);
......
......@@ -489,7 +489,7 @@ hppa_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
linux_init_abi (info, gdbarch, false);
linux_init_abi (info, gdbarch, 0);
/* GNU/Linux is always ELF. */
tdep->is_elf = 1;
......
......@@ -832,7 +832,7 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
gdb_assert (tdesc_data);
linux_init_abi (info, gdbarch, true);
linux_init_abi (info, gdbarch, 1);
/* GNU/Linux uses ELF. */
i386_elf_init_abi (info, gdbarch);
......
......@@ -223,7 +223,7 @@ ia64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
static const char *const stap_register_indirection_suffixes[] = { "]",
NULL };
linux_init_abi (info, gdbarch, false);
linux_init_abi (info, gdbarch, 0);
/* Set the method of obtaining the sigcontext addresses at which
registers are saved. */
......
......@@ -166,9 +166,10 @@ enum
static struct gdbarch_data *linux_gdbarch_data_handle;
struct linux_gdbarch_data
{
struct type *siginfo_type;
};
{
struct type *siginfo_type;
int num_disp_step_buffers;
};
static void *
init_linux_gdbarch_data (struct obstack *obstack)
......@@ -200,8 +201,8 @@ struct linux_info
if we tried looking it up but failed. */
int vsyscall_range_p = 0;
/* Inferior's displaced step buffer. */
gdb::optional<displaced_step_buffer> disp_step_buf;
/* Inferior's displaced step buffers. */
gdb::optional<displaced_step_buffers> disp_step_bufs;
};
/* Per-inferior data key. */
......@@ -2540,15 +2541,25 @@ linux_displaced_step_prepare (gdbarch *arch, thread_info *thread,
{
linux_info *per_inferior = get_linux_inferior_data (thread->inf);
if (!per_inferior->disp_step_buf.has_value ())
if (!per_inferior->disp_step_bufs.has_value ())
{
/* Figure out the location of the buffers. They are contiguous, starting
at DISP_STEP_BUF_ADDR. They are all of size BUF_LEN. */
CORE_ADDR disp_step_buf_addr
= linux_displaced_step_location (thread->inf->gdbarch);
int buf_len = gdbarch_max_insn_length (arch);
per_inferior->disp_step_buf.emplace (disp_step_buf_addr);
linux_gdbarch_data *gdbarch_data = get_linux_gdbarch_data (arch);
gdb_assert (gdbarch_data->num_disp_step_buffers >