summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog13
-rw-r--r--gdb/tilegx-linux-nat.c2
-rw-r--r--gdb/tilegx-linux-tdep.c6
-rw-r--r--gdb/tilegx-tdep.c36
-rw-r--r--gdb/tilegx-tdep.h4
5 files changed, 54 insertions, 7 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 2deb18213b9..7e1db9054f8 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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.
diff --git a/gdb/tilegx-linux-nat.c b/gdb/tilegx-linux-nat.c
index 442970b1654..39c62ac1eee 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 1067d3728be..abcc9435f9f 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 8be4046afe6..5d2e3ee4ba0 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)
@@ -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);
diff --git a/gdb/tilegx-tdep.h b/gdb/tilegx-tdep.h
index c4a9e370970..b598f31eee1 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 };