aboutsummaryrefslogtreecommitdiff
path: root/gdb/arm-tdep.c
diff options
context:
space:
mode:
authorYao Qi <yao.qi@linaro.org>2016-11-03 14:35:14 +0000
committerYao Qi <yao.qi@linaro.org>2016-11-03 14:35:14 +0000
commit833b7ab5008b769dca6db6d5ee1d21d33e730132 (patch)
treefc32095c2c5c42d58de5ef58eeec05fb0af80da2 /gdb/arm-tdep.c
parent22f13eb869197fc45a0da2a8a96b03d39809862e (diff)
downloadgdb-833b7ab5008b769dca6db6d5ee1d21d33e730132.zip
gdb-833b7ab5008b769dca6db6d5ee1d21d33e730132.tar.gz
gdb-833b7ab5008b769dca6db6d5ee1d21d33e730132.tar.bz2
Determine the kind of single step breakpoint
This patch adds a new gdbarch method breakpoint_kind_from_current_state for single step breakpoint, and uses it in breakpoint_kind. gdb: 2016-11-03 Yao Qi <yao.qi@linaro.org> * arch-utils.c (default_breakpoint_kind_from_current_state): New function. * arch-utils.h (default_breakpoint_kind_from_current_state): Declare. * arm-tdep.c (arm_breakpoint_kind_from_current_state): New function. (arm_gdbarch_init): Call set_gdbarch_breakpoint_kind_from_current_state. * breakpoint.c (breakpoint_kind): Call gdbarch_breakpoint_kind_from_current_state for single step breakpoint. Update comments. * gdbarch.sh (breakpoint_kind_from_current_state): New. * gdbarch.c, gdbarch.h: Regenerate.
Diffstat (limited to 'gdb/arm-tdep.c')
-rw-r--r--gdb/arm-tdep.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index ac98944..28fc20c 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -7901,6 +7901,59 @@ arm_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
}
}
+/* Implement the breakpoint_kind_from_current_state gdbarch method. */
+
+static int
+arm_breakpoint_kind_from_current_state (struct gdbarch *gdbarch,
+ struct regcache *regcache,
+ CORE_ADDR *pcptr)
+{
+ gdb_byte buf[4];
+
+ /* Check the memory pointed by PC is readable. */
+ if (target_read_memory (regcache_read_pc (regcache), buf, 4) == 0)
+ {
+ struct arm_get_next_pcs next_pcs_ctx;
+ CORE_ADDR pc;
+ int i;
+ VEC (CORE_ADDR) *next_pcs = NULL;
+ struct cleanup *old_chain
+ = make_cleanup (VEC_cleanup (CORE_ADDR), &next_pcs);
+
+ arm_get_next_pcs_ctor (&next_pcs_ctx,
+ &arm_get_next_pcs_ops,
+ gdbarch_byte_order (gdbarch),
+ gdbarch_byte_order_for_code (gdbarch),
+ 0,
+ regcache);
+
+ next_pcs = arm_get_next_pcs (&next_pcs_ctx);
+
+ /* If MEMADDR is the next instruction of current pc, do the
+ software single step computation, and get the thumb mode by
+ the destination address. */
+ for (i = 0; VEC_iterate (CORE_ADDR, next_pcs, i, pc); i++)
+ {
+ if (UNMAKE_THUMB_ADDR (pc) == *pcptr)
+ {
+ do_cleanups (old_chain);
+
+ if (IS_THUMB_ADDR (pc))
+ {
+ *pcptr = MAKE_THUMB_ADDR (*pcptr);
+ return arm_breakpoint_kind_from_pc (gdbarch, pcptr);
+ }
+ else
+ return ARM_BP_KIND_ARM;
+ }
+ }
+
+ do_cleanups (old_chain);
+ }
+
+ return arm_breakpoint_kind_from_pc (gdbarch, pcptr);
+}
+
/* Extract from an array REGBUF containing the (raw) register state a
function return value of type TYPE, and copy that, in virtual
format, into VALBUF. */
@@ -9409,6 +9462,8 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
/* Breakpoint manipulation. */
SET_GDBARCH_BREAKPOINT_MANIPULATION (arm);
+ set_gdbarch_breakpoint_kind_from_current_state (gdbarch,
+ arm_breakpoint_kind_from_current_state);
/* Information about registers, etc. */
set_gdbarch_sp_regnum (gdbarch, ARM_SP_REGNUM);