From: Walter Lee Date: Tue, 19 Feb 2013 16:19:33 +0000 (+0000) Subject: * tilegx-tdep.c (INT_SWINT_1_SIGRETURN): New macro. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4aaf25031b9372b24fa813709dd310724696a5bf;p=binutils-gdb.git * 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. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 2deb18213b9..7e1db9054f8 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,16 @@ +2013-02-19 Jiong Wang + + * 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 * tilegx-tdep.c (tilegx_push_dummy_call): args pushed on stack 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 };