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]

[RFC/TileGX 3/6]fix syscall restart for hand call


like x86, 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.


gdb/ChangeLog:

        * tilegx-tdep.c (tilegx_write_pc): New function.
        prevent kernel from restarting syscall for gdb hand call.
        (tilegx_cannot_reference_register): Likewise.
        (tilegx_gdbarch_init): Likewise.
        (tilegx_register_name): Likewise.
        * tilegx-tdep.h (enum tilegx_regnum): Update.
        * tilegx-linux-tdep.c (tilegx_linux_supply_regseit): Likewise.
        * tilegx-linux-nat.c (regmap): Update.

please review.

---
Regards,
Jiong
Tilera Corporation.

---
 gdb/tilegx-linux-nat.c  |    2 +-
 gdb/tilegx-linux-tdep.c |    6 ++++--
 gdb/tilegx-tdep.c       |   32 ++++++++++++++++++++++++++++++--
 gdb/tilegx-tdep.h       |    4 ++--
 4 files changed, 37 insertions(+), 7 deletions(-)

diff --git a/gdb/tilegx-linux-nat.c b/gdb/tilegx-linux-nat.c
index 442970b..39c62ac 100644
--- a/gdb/tilegx-linux-nat.c
+++ b/gdb/tilegx-linux-nat.c
@@ -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
diff --git a/gdb/tilegx-linux-tdep.c b/gdb/tilegx-linux-tdep.c
index 64ddf00..7a44917 100644
--- a/gdb/tilegx-linux-tdep.c
+++ b/gdb/tilegx-linux-tdep.c
@@ -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);
diff --git a/gdb/tilegx-tdep.c b/gdb/tilegx-tdep.c
index 6432edb..638be6c 100644
--- a/gdb/tilegx-tdep.c
+++ b/gdb/tilegx-tdep.c
@@ -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)
@@ -776,6 +776,32 @@ tilegx_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
   return 0;
 }
 
+#define INT_SWINT_1_SIGRETURN (~0)
+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 *
@@ -907,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;
@@ -990,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);
 
diff --git a/gdb/tilegx-tdep.h b/gdb/tilegx-tdep.h
index c4a9e37..b598f31 100644
--- a/gdb/tilegx-tdep.h
+++ b/gdb/tilegx-tdep.h
@@ -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 };
-- 
1.7.10.3



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