Determine the kind of single step breakpoint
authorYao Qi <yao.qi@linaro.org>
Thu, 3 Nov 2016 14:35:14 +0000 (14:35 +0000)
committerYao Qi <yao.qi@linaro.org>
Thu, 3 Nov 2016 14:35:14 +0000 (14:35 +0000)
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.

gdb/ChangeLog
gdb/arch-utils.c
gdb/arch-utils.h
gdb/arm-tdep.c
gdb/breakpoint.c
gdb/gdbarch.c
gdb/gdbarch.h
gdb/gdbarch.sh

index 313e24c1f2f68796c8f69cd75fc50efac911e4ae..3482f71e0636977f440136bb821ade60f2398199 100644 (file)
@@ -1,3 +1,19 @@
+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.
+
 2016-11-03  Yao Qi  <yao.qi@linaro.org>
 
        * arch-utils.c (default_breakpoint_from_pc): New function.
index 39e8eb53e4d05b5fc6458e5b3fcfd2a6ce3b97eb..d64a73db2eb9ca7be6c2c98120d82db3781af88a 100644 (file)
@@ -848,6 +848,14 @@ default_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
 
   return gdbarch_sw_breakpoint_from_kind (gdbarch, kind, lenptr);
 }
+int
+default_breakpoint_kind_from_current_state (struct gdbarch *gdbarch,
+                                           struct regcache *regcache,
+                                           CORE_ADDR *pcptr)
+{
+  return gdbarch_breakpoint_kind_from_pc (gdbarch, pcptr);
+}
+
 
 void
 default_gen_return_address (struct gdbarch *gdbarch,
index 791725db977e1cf538943f0a783ff6c5f43cdd65..9592580d79b7ea141ab87402b82ace8d910a64bc 100644 (file)
@@ -218,6 +218,10 @@ extern const gdb_byte *default_breakpoint_from_pc (struct gdbarch *gdbarch,
                                                   CORE_ADDR *pcptr,
                                                   int *lenptr);
 
+extern int default_breakpoint_kind_from_current_state (struct gdbarch *gdbarch,
+                                                      struct regcache *regcache,
+                                                      CORE_ADDR *pcptr);
+
 extern void default_gen_return_address (struct gdbarch *gdbarch,
                                        struct agent_expr *ax,
                                        struct axs_value *value,
index ac989447041734ed8d0072848e4b4d813f7862ed..28fc20c44142e3389340d5845ad127cfc024f7ee 100644 (file)
@@ -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);
index 9afbdbdd58e6ad45f4d239128555b9b810624fbf..3908dabffecdbc375dfdfbeeb298a89e943a838b 100644 (file)
@@ -2603,12 +2603,26 @@ build_target_command_list (struct bp_location *bl)
     bl->target_info.persist = 1;
 }
 
-/* Return the kind of breakpoint on address *ADDR.  */
+/* Return the kind of breakpoint on address *ADDR.  Get the kind
+   of breakpoint according to ADDR except single-step breakpoint.
+   Get the kind of single-step breakpoint according to the current
+   registers state.  */
 
 static int
 breakpoint_kind (struct bp_location *bl, CORE_ADDR *addr)
 {
-  return gdbarch_breakpoint_kind_from_pc (bl->gdbarch, addr);
+  if (bl->owner->type == bp_single_step)
+    {
+      struct thread_info *thr = find_thread_global_id (bl->owner->thread);
+      struct regcache *regcache;
+
+      regcache = get_thread_regcache (thr->ptid);
+
+      return gdbarch_breakpoint_kind_from_current_state (bl->gdbarch,
+                                                        regcache, addr);
+    }
+  else
+    return gdbarch_breakpoint_kind_from_pc (bl->gdbarch, addr);
 }
 
 /* Insert a low-level "breakpoint" of some type.  BL is the breakpoint
index 1a3acabd49a9501a44d4a183de30af1225e27cca..463f6e0b89c84527a7117c40a975fbd1c73dc969 100644 (file)
@@ -232,6 +232,7 @@ struct gdbarch
   gdbarch_breakpoint_from_pc_ftype *breakpoint_from_pc;
   gdbarch_breakpoint_kind_from_pc_ftype *breakpoint_kind_from_pc;
   gdbarch_sw_breakpoint_from_kind_ftype *sw_breakpoint_from_kind;
+  gdbarch_breakpoint_kind_from_current_state_ftype *breakpoint_kind_from_current_state;
   gdbarch_adjust_breakpoint_address_ftype *adjust_breakpoint_address;
   gdbarch_memory_insert_breakpoint_ftype *memory_insert_breakpoint;
   gdbarch_memory_remove_breakpoint_ftype *memory_remove_breakpoint;
@@ -406,6 +407,7 @@ gdbarch_alloc (const struct gdbarch_info *info,
   gdbarch->return_in_first_hidden_param_p = default_return_in_first_hidden_param_p;
   gdbarch->breakpoint_from_pc = default_breakpoint_from_pc;
   gdbarch->sw_breakpoint_from_kind = NULL;
+  gdbarch->breakpoint_kind_from_current_state = default_breakpoint_kind_from_current_state;
   gdbarch->memory_insert_breakpoint = default_memory_insert_breakpoint;
   gdbarch->memory_remove_breakpoint = default_memory_remove_breakpoint;
   gdbarch->remote_register_number = default_remote_register_number;
@@ -587,6 +589,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   if (gdbarch->breakpoint_kind_from_pc == 0)
     fprintf_unfiltered (log, "\n\tbreakpoint_kind_from_pc");
   /* Skip verify of sw_breakpoint_from_kind, invalid_p == 0 */
+  /* Skip verify of breakpoint_kind_from_current_state, invalid_p == 0 */
   /* Skip verify of adjust_breakpoint_address, has predicate.  */
   /* Skip verify of memory_insert_breakpoint, invalid_p == 0 */
   /* Skip verify of memory_remove_breakpoint, invalid_p == 0 */
@@ -795,6 +798,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
   fprintf_unfiltered (file,
                       "gdbarch_dump: breakpoint_from_pc = <%s>\n",
                       host_address_to_string (gdbarch->breakpoint_from_pc));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: breakpoint_kind_from_current_state = <%s>\n",
+                      host_address_to_string (gdbarch->breakpoint_kind_from_current_state));
   fprintf_unfiltered (file,
                       "gdbarch_dump: breakpoint_kind_from_pc = <%s>\n",
                       host_address_to_string (gdbarch->breakpoint_kind_from_pc));
@@ -2822,6 +2828,23 @@ set_gdbarch_sw_breakpoint_from_kind (struct gdbarch *gdbarch,
   gdbarch->sw_breakpoint_from_kind = sw_breakpoint_from_kind;
 }
 
+int
+gdbarch_breakpoint_kind_from_current_state (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR *pcptr)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->breakpoint_kind_from_current_state != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_breakpoint_kind_from_current_state called\n");
+  return gdbarch->breakpoint_kind_from_current_state (gdbarch, regcache, pcptr);
+}
+
+void
+set_gdbarch_breakpoint_kind_from_current_state (struct gdbarch *gdbarch,
+                                                gdbarch_breakpoint_kind_from_current_state_ftype breakpoint_kind_from_current_state)
+{
+  gdbarch->breakpoint_kind_from_current_state = breakpoint_kind_from_current_state;
+}
+
 int
 gdbarch_adjust_breakpoint_address_p (struct gdbarch *gdbarch)
 {
index 09cb8cc7fe16990ff8f4b2bf755b9138cdd38c9b..add7e13383b36554ea0285efff55877a4f1ea9b8 100644 (file)
@@ -564,6 +564,14 @@ typedef const gdb_byte * (gdbarch_sw_breakpoint_from_kind_ftype) (struct gdbarch
 extern const gdb_byte * gdbarch_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size);
 extern void set_gdbarch_sw_breakpoint_from_kind (struct gdbarch *gdbarch, gdbarch_sw_breakpoint_from_kind_ftype *sw_breakpoint_from_kind);
 
+/* Return the breakpoint kind for this target based on the current
+   processor state (e.g. the current instruction mode on ARM) and the
+   *PCPTR.  In default, it is gdbarch->breakpoint_kind_from_pc. */
+
+typedef int (gdbarch_breakpoint_kind_from_current_state_ftype) (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR *pcptr);
+extern int gdbarch_breakpoint_kind_from_current_state (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR *pcptr);
+extern void set_gdbarch_breakpoint_kind_from_current_state (struct gdbarch *gdbarch, gdbarch_breakpoint_kind_from_current_state_ftype *breakpoint_kind_from_current_state);
+
 extern int gdbarch_adjust_breakpoint_address_p (struct gdbarch *gdbarch);
 
 typedef CORE_ADDR (gdbarch_adjust_breakpoint_address_ftype) (struct gdbarch *gdbarch, CORE_ADDR bpaddr);
index e3ead6b440cd12d31d46ad303fc473607b024767..ae7dd97c53164fb5bdf2ab50f1b6dc0f99afad3a 100755 (executable)
@@ -569,6 +569,11 @@ m:int:breakpoint_kind_from_pc:CORE_ADDR *pcptr:pcptr::0:
 # SIZE is set to the software breakpoint's length in memory.
 m:const gdb_byte *:sw_breakpoint_from_kind:int kind, int *size:kind, size::NULL::0
 
+# Return the breakpoint kind for this target based on the current
+# processor state (e.g. the current instruction mode on ARM) and the
+# *PCPTR.  In default, it is gdbarch->breakpoint_kind_from_pc.
+m:int:breakpoint_kind_from_current_state:struct regcache *regcache, CORE_ADDR *pcptr:regcache, pcptr:0:default_breakpoint_kind_from_current_state::0
+
 M:CORE_ADDR:adjust_breakpoint_address:CORE_ADDR bpaddr:bpaddr
 m:int:memory_insert_breakpoint:struct bp_target_info *bp_tgt:bp_tgt:0:default_memory_insert_breakpoint::0
 m:int:memory_remove_breakpoint:struct bp_target_info *bp_tgt:bp_tgt:0:default_memory_remove_breakpoint::0