diff options
-rw-r--r-- | gdb/aarch64-linux-tdep.c | 4 | ||||
-rw-r--r-- | gdb/arm-tdep.c | 4 | ||||
-rw-r--r-- | gdb/displaced-stepping.c | 6 | ||||
-rw-r--r-- | gdb/gdbarch-gen.h | 12 | ||||
-rw-r--r-- | gdb/gdbarch.c | 26 | ||||
-rw-r--r-- | gdb/gdbarch_components.py | 18 | ||||
-rw-r--r-- | gdb/linux-tdep.c | 2 | ||||
-rw-r--r-- | gdb/rs6000-tdep.c | 6 |
8 files changed, 66 insertions, 12 deletions
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c index 0000b49..b183a3c 100644 --- a/gdb/aarch64-linux-tdep.c +++ b/gdb/aarch64-linux-tdep.c @@ -2240,7 +2240,9 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) set_gdbarch_get_syscall_number (gdbarch, aarch64_linux_get_syscall_number); /* Displaced stepping. */ - set_gdbarch_max_insn_length (gdbarch, 4 * AARCH64_DISPLACED_MODIFIED_INSNS); + set_gdbarch_max_insn_length (gdbarch, 4); + set_gdbarch_displaced_step_buffer_length + (gdbarch, 4 * AARCH64_DISPLACED_MODIFIED_INSNS); set_gdbarch_displaced_step_copy_insn (gdbarch, aarch64_displaced_step_copy_insn); set_gdbarch_displaced_step_fixup (gdbarch, aarch64_displaced_step_fixup); diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 70d7745..883f8be 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -10662,7 +10662,9 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Note: for displaced stepping, this includes the breakpoint, and one word of additional scratch space. This setting isn't used for anything beside displaced stepping at present. */ - set_gdbarch_max_insn_length (gdbarch, 4 * ARM_DISPLACED_MODIFIED_INSNS); + set_gdbarch_displaced_step_buffer_length + (gdbarch, 4 * ARM_DISPLACED_MODIFIED_INSNS); + set_gdbarch_max_insn_length (gdbarch, 4); /* This should be low enough for everything. */ tdep->lowest_pc = 0x20; diff --git a/gdb/displaced-stepping.c b/gdb/displaced-stepping.c index 06b32a8..9f98ea8 100644 --- a/gdb/displaced-stepping.c +++ b/gdb/displaced-stepping.c @@ -55,7 +55,7 @@ displaced_step_buffers::prepare (thread_info *thread, CORE_ADDR &displaced_pc) regcache *regcache = get_thread_regcache (thread); const address_space *aspace = regcache->aspace (); gdbarch *arch = regcache->arch (); - ULONGEST len = gdbarch_max_insn_length (arch); + ULONGEST len = gdbarch_displaced_step_buffer_length (arch); /* Search for an unused buffer. */ displaced_step_buffer *buffer = nullptr; @@ -243,7 +243,7 @@ displaced_step_buffers::finish (gdbarch *arch, thread_info *thread, below. */ thread->inf->displaced_step_state.unavailable = false; - ULONGEST len = gdbarch_max_insn_length (arch); + ULONGEST len = gdbarch_displaced_step_buffer_length (arch); /* Restore memory of the buffer. */ write_memory_ptid (thread->ptid, buffer->addr, @@ -302,7 +302,7 @@ displaced_step_buffers::restore_in_ptid (ptid_t ptid) regcache *regcache = get_thread_regcache (buffer.current_thread); gdbarch *arch = regcache->arch (); - ULONGEST len = gdbarch_max_insn_length (arch); + ULONGEST len = gdbarch_displaced_step_buffer_length (arch); write_memory_ptid (ptid, buffer.addr, buffer.saved_copy.data (), len); diff --git a/gdb/gdbarch-gen.h b/gdb/gdbarch-gen.h index ddb97f6..76d12a1 100644 --- a/gdb/gdbarch-gen.h +++ b/gdb/gdbarch-gen.h @@ -1039,8 +1039,8 @@ extern void set_gdbarch_max_insn_length (struct gdbarch *gdbarch, ULONGEST max_i see the comments in infrun.c. The TO area is only guaranteed to have space for - gdbarch_max_insn_length (arch) bytes, so this function must not - write more bytes than that to that area. + gdbarch_displaced_step_buffer_length (arch) octets, so this + function must not write more octets than that to this area. If you do not provide this function, GDB assumes that the architecture does not support displaced stepping. @@ -1122,6 +1122,14 @@ typedef void (gdbarch_displaced_step_restore_all_in_ptid_ftype) (inferior *paren extern void gdbarch_displaced_step_restore_all_in_ptid (struct gdbarch *gdbarch, inferior *parent_inf, ptid_t child_ptid); extern void set_gdbarch_displaced_step_restore_all_in_ptid (struct gdbarch *gdbarch, gdbarch_displaced_step_restore_all_in_ptid_ftype *displaced_step_restore_all_in_ptid); +/* The maximum length in octets required for a displaced-step instruction + buffer. By default this will be the same as gdbarch::max_insn_length, + but should be overridden for architectures that might expand a + displaced-step instruction to multiple replacement instructions. */ + +extern ULONGEST gdbarch_displaced_step_buffer_length (struct gdbarch *gdbarch); +extern void set_gdbarch_displaced_step_buffer_length (struct gdbarch *gdbarch, ULONGEST displaced_step_buffer_length); + /* Relocate an instruction to execute at a different address. OLDLOC is the address in the inferior memory where the instruction to relocate is currently at. On input, TO points to the destination diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 84f6a48..b4763aa 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -192,6 +192,7 @@ struct gdbarch gdbarch_displaced_step_finish_ftype *displaced_step_finish = NULL; gdbarch_displaced_step_copy_insn_closure_by_addr_ftype *displaced_step_copy_insn_closure_by_addr = nullptr; gdbarch_displaced_step_restore_all_in_ptid_ftype *displaced_step_restore_all_in_ptid = nullptr; + ULONGEST displaced_step_buffer_length = 0; gdbarch_relocate_instruction_ftype *relocate_instruction = NULL; gdbarch_overlay_update_ftype *overlay_update = nullptr; gdbarch_core_read_description_ftype *core_read_description = nullptr; @@ -451,6 +452,10 @@ verify_gdbarch (struct gdbarch *gdbarch) log.puts ("\n\tdisplaced_step_finish"); /* Skip verify of displaced_step_copy_insn_closure_by_addr, has predicate. */ /* Skip verify of displaced_step_restore_all_in_ptid, invalid_p == 0 */ + if (gdbarch->displaced_step_buffer_length == 0) + gdbarch->displaced_step_buffer_length = gdbarch->max_insn_length; + if (gdbarch->displaced_step_buffer_length < gdbarch->max_insn_length) + log.puts ("\n\tdisplaced_step_buffer_length"); /* Skip verify of relocate_instruction, has predicate. */ /* Skip verify of overlay_update, has predicate. */ /* Skip verify of core_read_description, has predicate. */ @@ -1110,6 +1115,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) "gdbarch_dump: displaced_step_restore_all_in_ptid = <%s>\n", host_address_to_string (gdbarch->displaced_step_restore_all_in_ptid)); gdb_printf (file, + "gdbarch_dump: displaced_step_buffer_length = %s\n", + plongest (gdbarch->displaced_step_buffer_length)); + gdb_printf (file, "gdbarch_dump: gdbarch_relocate_instruction_p() = %d\n", gdbarch_relocate_instruction_p (gdbarch)); gdb_printf (file, @@ -4157,6 +4165,24 @@ set_gdbarch_displaced_step_restore_all_in_ptid (struct gdbarch *gdbarch, gdbarch->displaced_step_restore_all_in_ptid = displaced_step_restore_all_in_ptid; } +ULONGEST +gdbarch_displaced_step_buffer_length (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + /* Check variable is valid. */ + gdb_assert (!(gdbarch->displaced_step_buffer_length < gdbarch->max_insn_length)); + if (gdbarch_debug >= 2) + gdb_printf (gdb_stdlog, "gdbarch_displaced_step_buffer_length called\n"); + return gdbarch->displaced_step_buffer_length; +} + +void +set_gdbarch_displaced_step_buffer_length (struct gdbarch *gdbarch, + ULONGEST displaced_step_buffer_length) +{ + gdbarch->displaced_step_buffer_length = displaced_step_buffer_length; +} + bool gdbarch_relocate_instruction_p (struct gdbarch *gdbarch) { diff --git a/gdb/gdbarch_components.py b/gdb/gdbarch_components.py index 6cdf15b..92c501d 100644 --- a/gdb/gdbarch_components.py +++ b/gdb/gdbarch_components.py @@ -1735,8 +1735,8 @@ For a general explanation of displaced stepping and how GDB uses it, see the comments in infrun.c. The TO area is only guaranteed to have space for -gdbarch_max_insn_length (arch) bytes, so this function must not -write more bytes than that to that area. +gdbarch_displaced_step_buffer_length (arch) octets, so this +function must not write more octets than that to this area. If you do not provide this function, GDB assumes that the architecture does not support displaced stepping. @@ -1844,6 +1844,20 @@ contents of all displaced step buffers in the child's address space. invalid=False, ) +Value( + comment=""" +The maximum length in octets required for a displaced-step instruction +buffer. By default this will be the same as gdbarch::max_insn_length, +but should be overridden for architectures that might expand a +displaced-step instruction to multiple replacement instructions. +""", + type="ULONGEST", + name="displaced_step_buffer_length", + predefault="0", + postdefault="gdbarch->max_insn_length", + invalid="gdbarch->displaced_step_buffer_length < gdbarch->max_insn_length", +) + Method( comment=""" Relocate an instruction to execute at a different address. OLDLOC diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c index e6ce13a..3eaa5f3 100644 --- a/gdb/linux-tdep.c +++ b/gdb/linux-tdep.c @@ -2603,7 +2603,7 @@ linux_displaced_step_prepare (gdbarch *arch, thread_info *thread, 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); + int buf_len = gdbarch_displaced_step_buffer_length (arch); linux_gdbarch_data *gdbarch_data = get_linux_gdbarch_data (arch); gdb_assert (gdbarch_data->num_disp_step_buffers > 0); diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index 6ba5652..9859a7d 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -889,7 +889,8 @@ ppc_displaced_step_copy_insn (struct gdbarch *gdbarch, CORE_ADDR from, CORE_ADDR to, struct regcache *regs) { - size_t len = gdbarch_max_insn_length (gdbarch); + size_t len = gdbarch_displaced_step_buffer_length (gdbarch); + gdb_assert (len > PPC_INSN_SIZE); std::unique_ptr<ppc_displaced_step_copy_insn_closure> closure (new ppc_displaced_step_copy_insn_closure (len)); gdb_byte *buf = closure->buf.data (); @@ -8363,8 +8364,9 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_displaced_step_finish (gdbarch, ppc_displaced_step_finish); set_gdbarch_displaced_step_restore_all_in_ptid (gdbarch, ppc_displaced_step_restore_all_in_ptid); + set_gdbarch_displaced_step_buffer_length (gdbarch, 2 * PPC_INSN_SIZE); - set_gdbarch_max_insn_length (gdbarch, 2 * PPC_INSN_SIZE); + set_gdbarch_max_insn_length (gdbarch, PPC_INSN_SIZE); /* Hook in ABI-specific overrides, if they have been registered. */ info.target_desc = tdesc; |