* arm-linux-tdep.c (arm_linux_software_single_step): New.
authorDaniel Jacobowitz <drow@false.org>
Thu, 27 Sep 2007 18:48:33 +0000 (18:48 +0000)
committerDaniel Jacobowitz <drow@false.org>
Thu, 27 Sep 2007 18:48:33 +0000 (18:48 +0000)
(arm_linux_init_abi): Use it.
* arm-tdep.c (arm_get_next_pc): Make global.  Handle all-ones
condition correctly.
* arm-tdep.h (arm_get_next_pc): Declare.
* Makefile.in (arm-linux-tdep.o): Update.

gdb/ChangeLog
gdb/Makefile.in
gdb/arm-linux-tdep.c
gdb/arm-tdep.c
gdb/arm-tdep.h

index f6cc0e6f23cd61624a840a45bbdc1f40e9ca546c..e0ae42681e9023e0fae0c9f5b83380b93bcf49c6 100644 (file)
@@ -1,3 +1,12 @@
+2007-09-27  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * arm-linux-tdep.c (arm_linux_software_single_step): New.
+       (arm_linux_init_abi): Use it.
+       * arm-tdep.c (arm_get_next_pc): Make global.  Handle all-ones
+       condition correctly.
+       * arm-tdep.h (arm_get_next_pc): Declare.
+       * Makefile.in (arm-linux-tdep.o): Update.
+
 2007-09-26  Vladimir Prus  <vladimir@codesourcery.com>
 
        * varobj.c (install_new_value): Don't
index cebfbc9bb1261110c9c16ea32d98a9c0472afc76..64692442300fb30ac4be55b69d1fb9fc78caec3a 100644 (file)
@@ -1805,7 +1805,7 @@ arm-linux-nat.o: arm-linux-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) \
 arm-linux-tdep.o: arm-linux-tdep.c $(defs_h) $(target_h) $(value_h) \
        $(gdbtypes_h) $(floatformat_h) $(gdbcore_h) $(frame_h) $(regcache_h) \
        $(doublest_h) $(solib_svr4_h) $(osabi_h) $(arm_tdep_h) \
-       $(regset_h) $(arm_linux_tdep_h) \
+       $(regset_h) $(arm_linux_tdep_h) $(breakpoint_h) \
        $(glibc_tdep_h) $(trad_frame_h) $(tramp_frame_h) $(gdb_string_h)
 armnbsd-nat.o: armnbsd-nat.c $(defs_h) $(gdbcore_h) $(inferior_h) \
        $(regcache_h) $(target_h) $(gdb_string_h) $(arm_tdep_h) $(inf_ptrace_h)
index e33a93e6256b7b6e07f2267fb5f84d21693cab4b..fd6b2e5a6a042fd3e800c53b61f2d38e775eda1a 100644 (file)
@@ -32,6 +32,7 @@
 #include "regset.h"
 #include "trad-frame.h"
 #include "tramp-frame.h"
+#include "breakpoint.h"
 
 #include "arm-tdep.h"
 #include "arm-linux-tdep.h"
@@ -568,6 +569,26 @@ arm_linux_regset_from_core_section (struct gdbarch *gdbarch,
   return NULL;
 }
 
+/* Insert a single step breakpoint at the next executed instruction.  */
+
+int
+arm_linux_software_single_step (struct frame_info *frame)
+{
+  CORE_ADDR next_pc = arm_get_next_pc (frame, get_frame_pc (frame));
+
+  /* The Linux kernel offers some user-mode helpers in a high page.  We can
+     not read this page (as of 2.6.23), and even if we could then we couldn't
+     set breakpoints in it, and even if we could then the atomic operations
+     would fail when interrupted.  They are all called as functions and return
+     to the address in LR, so step to there instead.  */
+  if (next_pc > 0xffff0000)
+    next_pc = get_frame_register_unsigned (frame, ARM_LR_REGNUM);
+
+  insert_single_step_breakpoint (next_pc);
+
+  return 1;
+}
+
 static void
 arm_linux_init_abi (struct gdbarch_info info,
                    struct gdbarch *gdbarch)
@@ -604,7 +625,7 @@ arm_linux_init_abi (struct gdbarch_info info,
     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
 
   /* Single stepping.  */
-  set_gdbarch_software_single_step (gdbarch, arm_software_single_step);
+  set_gdbarch_software_single_step (gdbarch, arm_linux_software_single_step);
 
   /* Shared library handling.  */
   set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
index b4d221184acca8ef61e967d3991a09d0da5ba760..325bd80df7ffd5a8f094dcf1e9b39137f3e0dff0 100644 (file)
@@ -1664,7 +1664,7 @@ thumb_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
   return nextpc;
 }
 
-static CORE_ADDR
+CORE_ADDR
 arm_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
 {
   unsigned long pc_val;
@@ -1680,7 +1680,30 @@ arm_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
   status = get_frame_register_unsigned (frame, ARM_PS_REGNUM);
   nextpc = (CORE_ADDR) (pc_val + 4);   /* Default case */
 
-  if (condition_true (bits (this_instr, 28, 31), status))
+  if (bits (this_instr, 28, 31) == INST_NV)
+    switch (bits (this_instr, 24, 27))
+      {
+      case 0xa:
+      case 0xb:
+       {
+         /* Branch with Link and change to Thumb.  */
+         nextpc = BranchDest (pc, this_instr);
+         nextpc |= bit (this_instr, 24) << 1;
+
+         nextpc = gdbarch_addr_bits_remove (current_gdbarch, nextpc);
+         if (nextpc == pc)
+           error (_("Infinite loop detected"));
+         break;
+       }
+      case 0xc:
+      case 0xd:
+      case 0xe:
+       /* Coprocessor register transfer.  */
+        if (bits (this_instr, 12, 15) == 15)
+         error (_("Invalid update to pc in instruction"));
+       break;
+      }
+  else if (condition_true (bits (this_instr, 28, 31), status))
     {
       switch (bits (this_instr, 24, 27))
        {
@@ -1886,10 +1909,6 @@ arm_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
          {
            nextpc = BranchDest (pc, this_instr);
 
-           /* BLX */
-           if (bits (this_instr, 28, 31) == INST_NV)
-             nextpc |= bit (this_instr, 24) << 1;
-
            nextpc = gdbarch_addr_bits_remove (current_gdbarch, nextpc);
            if (nextpc == pc)
              error (_("Infinite loop detected"));
index 5fa8b62d3828055d7e0c765c9f95164435387a1b..5ab110e8241a6c3cfb9b069a31e62df18c47fafc 100644 (file)
@@ -181,6 +181,7 @@ struct gdbarch_tdep
 #endif
 
 CORE_ADDR arm_skip_stub (struct frame_info *, CORE_ADDR);
+CORE_ADDR arm_get_next_pc (struct frame_info *, CORE_ADDR);
 int arm_software_single_step (struct frame_info *);
 
 /* Functions exported from armbsd-tdep.h.  */