* tilegx-tdep.c (INT_SWINT_1_SIGRETURN): New macro.
authorWalter Lee <walt@tilera.com>
Tue, 19 Feb 2013 16:19:33 +0000 (16:19 +0000)
committerWalter Lee <walt@tilera.com>
Tue, 19 Feb 2013 16:19:33 +0000 (16:19 +0000)
        (tilegx_write_pc): New function.
        (tilegx_cannot_reference_register): Return zero if REGNO
        is TILEGX_FAULTNUM_REGNUM.
        (tilegx_gdbarch_init): Add call to set_gdbarch_write_pc.
        (tilegx_register_name): Add handling of "faultnum" register.
        * tilegx-tdep.h (enum tilegx_regnum): Add TILEGX_FAULTNUM_REGNUM.
        * tilegx-linux-tdep.c (tilegx_linux_supply_regset): Add
        handling of TILEGX_FAULTNUM_REGNUM.
        * tilegx-linux-nat.c (regmap): Add entry for TILEGX_FAULTNUM_REGNUM.

gdb/ChangeLog
gdb/tilegx-linux-nat.c
gdb/tilegx-linux-tdep.c
gdb/tilegx-tdep.c
gdb/tilegx-tdep.h

index 2deb182..7e1db90 100644 (file)
@@ -1,5 +1,18 @@
 2013-02-19  Jiong Wang  <jiwang@tilera.com>
 
+        * tilegx-tdep.c (INT_SWINT_1_SIGRETURN): New macro.
+       (tilegx_write_pc): New function.
+       (tilegx_cannot_reference_register): Return zero if REGNO
+       is TILEGX_FAULTNUM_REGNUM.
+       (tilegx_gdbarch_init): Add call to set_gdbarch_write_pc.
+       (tilegx_register_name): Add handling of "faultnum" register.
+       * tilegx-tdep.h (enum tilegx_regnum): Add TILEGX_FAULTNUM_REGNUM.
+       * tilegx-linux-tdep.c (tilegx_linux_supply_regset): Add
+       handling of TILEGX_FAULTNUM_REGNUM.
+       * tilegx-linux-nat.c (regmap): Add entry for TILEGX_FAULTNUM_REGNUM.
+
+2013-02-19  Jiong Wang  <jiwang@tilera.com>
+
        * tilegx-tdep.c (tilegx_push_dummy_call): args pushed on stack
        should be aligned to 64bit. 
 
index 442970b..39c62ac 100644 (file)
@@ -65,7 +65,7 @@ static const int regmap[] =
   40, 41, 42, 43, 44, 45, 46, 47,
   48, 49, 50, 51, 52, 53, 54, 55,
   -1, -1, -1, -1, -1, -1, -1, -1,
-  56
+  56, 58
 };
 
 /* Transfering the general-purpose registers between GDB, inferiors
index 1067d37..abcc943 100644 (file)
@@ -85,9 +85,11 @@ tilegx_linux_supply_regset (const struct regset *regset,
   int i;
 
   /* This logic must match that of struct pt_regs in "ptrace.h".  */
-  for (i = 0; i < TILEGX_NUM_EASY_REGS + 1; i++, ptr += tilegx_reg_size)
+  for (i = 0; i < TILEGX_NUM_EASY_REGS + 2; i++, ptr += tilegx_reg_size)
     {
-      int gri = (i < TILEGX_NUM_EASY_REGS) ? i : TILEGX_PC_REGNUM;
+      int gri = (i < TILEGX_NUM_EASY_REGS)
+                 ? i : (i == TILEGX_NUM_EASY_REGS)
+                        ? TILEGX_PC_REGNUM : TILEGX_FAULTNUM_REGNUM;
 
       if (regnum == gri || regnum == -1)
        regcache_raw_supply (regcache, gri, ptr);
index 8be4046..5d2e3ee 100644 (file)
@@ -155,7 +155,7 @@ tilegx_register_name (struct gdbarch *gdbarch, int regnum)
       "r40",  "r41",  "r42",  "r43",  "r44",  "r45",  "r46",  "r47",
       "r48",  "r49",  "r50",  "r51",  "r52",  "tp",   "sp",   "lr",
       "sn",   "idn0", "idn1", "udn0", "udn1", "udn2", "udn3", "zero",
-      "pc"
+      "pc",   "faultnum",
     };
 
   if (regnum < 0 || regnum >= TILEGX_NUM_REGS)
@@ -772,6 +772,36 @@ tilegx_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
   return 0;
 }
 
+/* by assigning the 'faultnum' reg in kernel pt_regs with this value,
+   kernel do_signal will not check r0. see tilegx kernel/signal.c
+   for details.  */
+#define INT_SWINT_1_SIGRETURN (~0)
+
+/* Implement the "write_pc" gdbarch method.  */
+
+static void
+tilegx_write_pc (struct regcache *regcache, CORE_ADDR pc)
+{
+  regcache_cooked_write_unsigned (regcache, TILEGX_PC_REGNUM, pc);
+
+  /* We must be careful with modifying the program counter.  If we
+     just interrupted a system call, the kernel might try to restart
+     it when we resume the inferior.  On restarting the system call,
+     the kernel will try backing up the program counter even though it
+     no longer points at the system call.  This typically results in a
+     SIGSEGV or SIGILL.  We can prevent this by writing INT_SWINT_1_SIGRETURN
+     in the "faultnum" pseudo-register.
+
+     Note that "faultnum" is saved when setting up a dummy call frame.
+     This means that it is properly restored when that frame is
+     popped, and that the interrupted system call will be restarted
+     when we resume the inferior on return from a function call from
+     within GDB.  In all other cases the system call will not be
+     restarted.  */
+  regcache_cooked_write_unsigned (regcache, TILEGX_FAULTNUM_REGNUM,
+                                  INT_SWINT_1_SIGRETURN);
+}
+
 /* This is the implementation of gdbarch method breakpoint_from_pc.  */
 
 static const unsigned char *
@@ -903,7 +933,8 @@ tilegx_cannot_reference_register (struct gdbarch *gdbarch, int regno)
 {
   if (regno >= 0 && regno < TILEGX_NUM_EASY_REGS)
     return 0;
-  else if (regno == TILEGX_PC_REGNUM)
+  else if (regno == TILEGX_PC_REGNUM
+           || regno == TILEGX_FAULTNUM_REGNUM)
     return 0;
   else
     return 1;
@@ -986,6 +1017,7 @@ tilegx_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   /* These values and methods are used when gdb calls a target function.  */
   set_gdbarch_push_dummy_call (gdbarch, tilegx_push_dummy_call);
+  set_gdbarch_write_pc (gdbarch, tilegx_write_pc);
   set_gdbarch_breakpoint_from_pc (gdbarch, tilegx_breakpoint_from_pc);
   set_gdbarch_return_value (gdbarch, tilegx_return_value);
 
index c4a9e37..b598f31 100644 (file)
@@ -100,8 +100,8 @@ enum tilegx_regnum
 
     TILEGX_PC_REGNUM,
     TILEGX_NUM_PHYS_REGS = TILEGX_PC_REGNUM, /* 64 */
-
-    TILEGX_NUM_REGS /* 65 */
+    TILEGX_FAULTNUM_REGNUM,
+    TILEGX_NUM_REGS, /* 66 */
   };
 
 enum { tilegx_reg_size = 8 };