This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] gdbarch_syscall_pc_increment


Hello all,


This patch fixes stepping over system call instruction on architectures that use software single stepping and also may increment PC upon return from the system call to communicate error. (e.g. this is what we do on Neutrino).


Note: I could only test this on Neutrino.


Thanks,


Aleksandar


ChangeLog:


      * gdbarch.sh (syscall_pc_increment): New function.
      * gdbarch.h, gdbarch.c: Regenerated.
      * arm-tdep.c (arm_software_single_step): Use
      gdbarch_syscall_pc_increment and if provided, insert second
      single step breakpoint at the incremented address.


Index: gdb/gdbarch.sh
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.sh,v
retrieving revision 1.550
diff -u -p -r1.550 gdbarch.sh
--- gdb/gdbarch.sh	21 Nov 2012 00:29:54 -0000	1.550
+++ gdb/gdbarch.sh	11 Dec 2012 20:13:20 -0000
@@ -798,6 +798,10 @@ M:void:record_special_symbol:struct objf
 # Get architecture-specific system calls information from registers.
 M:LONGEST:get_syscall_number:ptid_t ptid:ptid
 
+# Return number of bytes the architecture may increment PC after
+# syscall.
+M:int:syscall_pc_increment:const struct frame_info *frame:frame
+
 # SystemTap related fields and functions.
 
 # Prefix used to mark an integer constant on the architecture's assembly
Index: gdb/gdbarch.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.h,v
retrieving revision 1.449
diff -u -p -r1.449 gdbarch.h
--- gdb/gdbarch.h	21 Nov 2012 00:29:54 -0000	1.449
+++ gdb/gdbarch.h	11 Dec 2012 20:13:20 -0000
@@ -611,7 +611,7 @@ extern void set_gdbarch_addr_bits_remove
    FIXME/cagney/2001-01-18: The logic is backwards.  It should be asking if the
    target can single step.  If not, then implement single step using breakpoints.
   
-   A return value of 1 means that the software_single_step breakpoints
+   A return value of 1 means that the software_single_step breakpoints 
    were inserted; 0 means they were not. */
 
 extern int gdbarch_software_single_step_p (struct gdbarch *gdbarch);
@@ -998,6 +998,15 @@ typedef LONGEST (gdbarch_get_syscall_num
 extern LONGEST gdbarch_get_syscall_number (struct gdbarch *gdbarch, ptid_t ptid);
 extern void set_gdbarch_get_syscall_number (struct gdbarch *gdbarch, gdbarch_get_syscall_number_ftype *get_syscall_number);
 
+/* Return number of bytes the architecture may increment PC after
+   syscall. */
+
+extern int gdbarch_syscall_pc_increment_p (struct gdbarch *gdbarch);
+
+typedef int (gdbarch_syscall_pc_increment_ftype) (struct gdbarch *gdbarch, const struct frame_info *frame);
+extern int gdbarch_syscall_pc_increment (struct gdbarch *gdbarch, const struct frame_info *frame);
+extern void set_gdbarch_syscall_pc_increment (struct gdbarch *gdbarch, gdbarch_syscall_pc_increment_ftype *syscall_pc_increment);
+
 /* SystemTap related fields and functions.
    Prefix used to mark an integer constant on the architecture's assembly
    For example, on x86 integer constants are written as:
Index: gdb/gdbarch.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.c,v
retrieving revision 1.501
diff -u -p -r1.501 gdbarch.c
--- gdb/gdbarch.c	21 Nov 2012 00:29:54 -0000	1.501
+++ gdb/gdbarch.c	11 Dec 2012 20:13:20 -0000
@@ -263,6 +263,7 @@ struct gdbarch
   gdbarch_get_siginfo_type_ftype *get_siginfo_type;
   gdbarch_record_special_symbol_ftype *record_special_symbol;
   gdbarch_get_syscall_number_ftype *get_syscall_number;
+  gdbarch_syscall_pc_increment_ftype *syscall_pc_increment;
   const char * stap_integer_prefix;
   const char * stap_integer_suffix;
   const char * stap_register_prefix;
@@ -431,6 +432,7 @@ struct gdbarch startup_gdbarch =
   0,  /* get_siginfo_type */
   0,  /* record_special_symbol */
   0,  /* get_syscall_number */
+  0,  /* syscall_pc_increment */
   0,  /* stap_integer_prefix */
   0,  /* stap_integer_suffix */
   0,  /* stap_register_prefix */
@@ -731,6 +733,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of get_siginfo_type, has predicate.  */
   /* Skip verify of record_special_symbol, has predicate.  */
   /* Skip verify of get_syscall_number, has predicate.  */
+  /* Skip verify of syscall_pc_increment, has predicate.  */
   /* Skip verify of stap_integer_prefix, invalid_p == 0 */
   /* Skip verify of stap_integer_suffix, invalid_p == 0 */
   /* Skip verify of stap_register_prefix, invalid_p == 0 */
@@ -1345,6 +1348,12 @@ gdbarch_dump (struct gdbarch *gdbarch, s
                       "gdbarch_dump: static_transform_name = <%s>\n",
                       host_address_to_string (gdbarch->static_transform_name));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_syscall_pc_increment_p() = %d\n",
+                      gdbarch_syscall_pc_increment_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: syscall_pc_increment = <%s>\n",
+                      host_address_to_string (gdbarch->syscall_pc_increment));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: target_desc = %s\n",
                       host_address_to_string (gdbarch->target_desc));
   fprintf_unfiltered (file,
@@ -3890,6 +3899,30 @@ set_gdbarch_get_syscall_number (struct g
   gdbarch->get_syscall_number = get_syscall_number;
 }
 
+int
+gdbarch_syscall_pc_increment_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->syscall_pc_increment != NULL;
+}
+
+int
+gdbarch_syscall_pc_increment (struct gdbarch *gdbarch, const struct frame_info *frame)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->syscall_pc_increment != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_syscall_pc_increment called\n");
+  return gdbarch->syscall_pc_increment (gdbarch, frame);
+}
+
+void
+set_gdbarch_syscall_pc_increment (struct gdbarch *gdbarch,
+                                  gdbarch_syscall_pc_increment_ftype syscall_pc_increment)
+{
+  gdbarch->syscall_pc_increment = syscall_pc_increment;
+}
+
 const char *
 gdbarch_stap_integer_prefix (struct gdbarch *gdbarch)
 {
Index: gdb/arm-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/arm-tdep.c,v
retrieving revision 1.373
diff -u -p -r1.373 arm-tdep.c
--- gdb/arm-tdep.c	21 Nov 2012 00:29:54 -0000	1.373
+++ gdb/arm-tdep.c	11 Dec 2012 20:13:21 -0000
@@ -5242,6 +5242,31 @@ arm_software_single_step (struct frame_i
   next_pc = arm_get_next_pc (frame, get_frame_pc (frame));
   arm_insert_single_step_breakpoint (gdbarch, aspace, next_pc);
 
+  if (gdbarch_syscall_pc_increment_p (gdbarch))
+    {
+      /* Some OS-es will increment pc to differentiate success vs
+       * error returning from a sys call. */
+      const int inc = gdbarch_syscall_pc_increment (gdbarch, frame);
+      const enum bfd_endian byte_order_for_code
+	= gdbarch_byte_order_for_code (gdbarch);
+      const LONGEST this_pc = get_frame_pc (frame);
+      LONGEST insn, mask, match;
+
+      if (arm_frame_is_thumb (frame))
+	{
+	  mask = 0xff000000;
+	  match = 0xdf000000;
+	}
+      else
+	{
+	  mask = 0x0f000000;
+	  match = 0x0f000000;
+	}
+      if (safe_read_memory_integer (this_pc, 4, byte_order_for_code, &insn)
+	  && (insn & mask) == match)
+	  arm_insert_single_step_breakpoint (gdbarch, aspace, next_pc + inc);
+    }
+
   return 1;
 }
 



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]