* 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>
 
 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. 
 
        * 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,
   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
 };
 
 /* 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".  */
   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);
 
       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",
       "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)
     };
 
   if (regnum < 0 || regnum >= TILEGX_NUM_REGS)
@@ -772,6 +772,36 @@ tilegx_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
   return 0;
 }
 
   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 *
 /* 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;
 {
   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;
     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);
 
   /* 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);
 
   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_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 };
   };
 
 enum { tilegx_reg_size = 8 };