From: Ulrich Weigand Date: Wed, 28 Mar 2007 18:56:07 +0000 (+0000) Subject: * arch-utils.c (legacy_pc_in_sigtramp): Remove. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=74174d2e39eb80df2d5c665c5453394ab927db8c;p=binutils-gdb.git * arch-utils.c (legacy_pc_in_sigtramp): Remove. * arch-utils.h (legacy_pc_in_sigtramp): Remove. * config/ia64/linux.mt (DEPRECATED_TM_FILE): Remove. * config/ia64/tm-linux.h: Remove file. * ia64-tdep.h (struct gdbarch_tdep): Add pc_in_sigtramp callback. * ia64-tdep.c (ia64_sigtramp_frame_sniffer): Use it instead of legacy_pc_in_sigtramp. (ia64_gdbarch_init): Initialize tdep->pc_in_sigtramp. * ia64-linux-tdep.c (ia64_linux_pc_in_sigtramp): Make static. Remove func_name argument. (ia64_linux_init_abi): Install it as tdep->pc_in_sigtramp. * infrun.c (HAVE_STEPPABLE_WATCHPOINT): Do not redefine. * target.c (update_current_target): Add to_have_steppable_watchpoint. * target.h (struct target_ops): Add to_have_steppable_watchpoint. (HAVE_STEPPABLE_WATCHPOINT): Define. * config/ia64/linux.mh (NATDEPFILES): Remove core-aout.o. * config/ia64/nm-linux.h (KERNEL_U_ADDR, U_REGS_OFFSET, CANNOT_FETCH_REGISTER, CANNOT_STORE_REGISTER, TARGET_CAN_USE_HARDWARE_WATCHPOINT, HAVE_STEPPABLE_WATCHPOINT, STOPPED_BY_WATCHPOINT, target_stopped_data_address, target_insert_watchpoint, target_remove_watchpoint): Remove. (FETCH_INFERIOR_REGISTERS): Define. * ia64-linux-nat.c (ia64_register_addr): Make static. (ia64_cannot_fetch_register, ia64_cannot_store_register): Likewise. (ia64_linux_insert_watchpoint): Make static. Remove ptid_p argument. (ia64_linux_remove_watchpoint): Likewise. Add type argument. (ia64_linux_stopped_data_address): Make static. Add target_ops. (ia64_linux_stopped_by_watchpoint): Make static. (ia64_linux_can_use_hw_breakpoint): New function. (ia64_linux_fetch_register, ia64_linux_fetch_registers): Likewise. (ia64_linux_store_register, ia64_linux_store_registers): Likewise. (_initialize_ia64_linux_nat): Install register and watchpoint ops. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index e8768abb5c0..7e0a0f176d8 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,41 @@ +2007-03-28 Ulrich Weigand + + * arch-utils.c (legacy_pc_in_sigtramp): Remove. + * arch-utils.h (legacy_pc_in_sigtramp): Remove. + + * config/ia64/linux.mt (DEPRECATED_TM_FILE): Remove. + * config/ia64/tm-linux.h: Remove file. + * ia64-tdep.h (struct gdbarch_tdep): Add pc_in_sigtramp callback. + * ia64-tdep.c (ia64_sigtramp_frame_sniffer): Use it instead of + legacy_pc_in_sigtramp. + (ia64_gdbarch_init): Initialize tdep->pc_in_sigtramp. + * ia64-linux-tdep.c (ia64_linux_pc_in_sigtramp): Make static. + Remove func_name argument. + (ia64_linux_init_abi): Install it as tdep->pc_in_sigtramp. + + * infrun.c (HAVE_STEPPABLE_WATCHPOINT): Do not redefine. + * target.c (update_current_target): Add to_have_steppable_watchpoint. + * target.h (struct target_ops): Add to_have_steppable_watchpoint. + (HAVE_STEPPABLE_WATCHPOINT): Define. + + * config/ia64/linux.mh (NATDEPFILES): Remove core-aout.o. + * config/ia64/nm-linux.h (KERNEL_U_ADDR, U_REGS_OFFSET, + CANNOT_FETCH_REGISTER, CANNOT_STORE_REGISTER, + TARGET_CAN_USE_HARDWARE_WATCHPOINT, HAVE_STEPPABLE_WATCHPOINT, + STOPPED_BY_WATCHPOINT, target_stopped_data_address, + target_insert_watchpoint, target_remove_watchpoint): Remove. + (FETCH_INFERIOR_REGISTERS): Define. + * ia64-linux-nat.c (ia64_register_addr): Make static. + (ia64_cannot_fetch_register, ia64_cannot_store_register): Likewise. + (ia64_linux_insert_watchpoint): Make static. Remove ptid_p argument. + (ia64_linux_remove_watchpoint): Likewise. Add type argument. + (ia64_linux_stopped_data_address): Make static. Add target_ops. + (ia64_linux_stopped_by_watchpoint): Make static. + (ia64_linux_can_use_hw_breakpoint): New function. + (ia64_linux_fetch_register, ia64_linux_fetch_registers): Likewise. + (ia64_linux_store_register, ia64_linux_store_registers): Likewise. + (_initialize_ia64_linux_nat): Install register and watchpoint ops. + 2007-03-28 Pedro Alves * linespec.c: Include language.h. diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c index 1ec3c37ff45..bf93c7bb6fb 100644 --- a/gdb/arch-utils.c +++ b/gdb/arch-utils.c @@ -234,16 +234,6 @@ generic_register_byte (int regnum) } -int -legacy_pc_in_sigtramp (CORE_ADDR pc, char *name) -{ -#if defined (DEPRECATED_IN_SIGTRAMP) - return DEPRECATED_IN_SIGTRAMP (pc, name); -#else - return name && strcmp ("_sigtramp", name) == 0; -#endif -} - int generic_convert_register_p (int regnum, struct type *type) { diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h index d528d67daf0..7906f76ff59 100644 --- a/gdb/arch-utils.h +++ b/gdb/arch-utils.h @@ -97,9 +97,6 @@ extern int generic_register_size (int regnum); /* Assume that the world is sane, the registers are all adjacent. */ extern int generic_register_byte (int regnum); -/* Prop up old targets that use various sigtramp macros. */ -extern int legacy_pc_in_sigtramp (CORE_ADDR pc, char *name); - /* By default, registers are not convertible. */ extern int generic_convert_register_p (int regnum, struct type *type); diff --git a/gdb/config/ia64/linux.mh b/gdb/config/ia64/linux.mh index 3ae22b26298..44bf8d3859a 100644 --- a/gdb/config/ia64/linux.mh +++ b/gdb/config/ia64/linux.mh @@ -2,7 +2,7 @@ NAT_FILE= nm-linux.h NATDEPFILES= inf-ptrace.o fork-child.o corelow.o gcore.o \ - core-aout.o core-regset.o ia64-linux-nat.o \ + core-regset.o ia64-linux-nat.o \ proc-service.o linux-thread-db.o linux-nat.o linux-fork.o LOADLIBES = -ldl -rdynamic diff --git a/gdb/config/ia64/linux.mt b/gdb/config/ia64/linux.mt index d326ccf9f00..22aa1711f45 100644 --- a/gdb/config/ia64/linux.mt +++ b/gdb/config/ia64/linux.mt @@ -1,4 +1,3 @@ # Target: Intel IA-64 running GNU/Linux TDEPFILES= ia64-tdep.o ia64-linux-tdep.o \ solib.o solib-svr4.o solib-legacy.o symfile-mem.o -DEPRECATED_TM_FILE= tm-linux.h diff --git a/gdb/config/ia64/nm-linux.h b/gdb/config/ia64/nm-linux.h index ce3addc7564..7f60064feb2 100644 --- a/gdb/config/ia64/nm-linux.h +++ b/gdb/config/ia64/nm-linux.h @@ -22,56 +22,8 @@ #ifndef NM_LINUX_H #define NM_LINUX_H -struct target_ops; - #include "config/nm-linux.h" -/* This is the amount to subtract from u.u_ar0 - to get the offset in the core file of the register values. */ -#define KERNEL_U_ADDR 0x0 - -/* Note: It seems likely that we'll have to eventually define - FETCH_INFERIOR_REGISTERS. But until that time, we'll make do - with the following. */ - -#define CANNOT_FETCH_REGISTER(regno) ia64_cannot_fetch_register(regno) -extern int ia64_cannot_fetch_register (int regno); - -#define CANNOT_STORE_REGISTER(regno) ia64_cannot_store_register(regno) -extern int ia64_cannot_store_register (int regno); - -#define U_REGS_OFFSET 0 - -/* Hardware watchpoints */ - -#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) 1 - -/* The IA-64 architecture can step over a watch point (without triggering - it again) if the "dd" (data debug fault disable) bit in the processor - status word is set. - - This PSR bit is set in ia64_linux_stopped_by_watchpoint when the - code there has determined that a hardware watchpoint has indeed - been hit. The CPU will then be able to execute one instruction - without triggering a watchpoint. */ -#define HAVE_STEPPABLE_WATCHPOINT 1 - -#define STOPPED_BY_WATCHPOINT(W) \ - ia64_linux_stopped_by_watchpoint () -extern int ia64_linux_stopped_by_watchpoint (); - -#define target_stopped_data_address(target, x) \ - ia64_linux_stopped_data_address(x) -extern int ia64_linux_stopped_data_address (CORE_ADDR *addr_p); - -#define target_insert_watchpoint(addr, len, type) \ - ia64_linux_insert_watchpoint (inferior_ptid, addr, len, type) -extern int ia64_linux_insert_watchpoint (ptid_t ptid, CORE_ADDR addr, - int len, int rw); - -#define target_remove_watchpoint(addr, len, type) \ - ia64_linux_remove_watchpoint (inferior_ptid, addr, len) -extern int ia64_linux_remove_watchpoint (ptid_t ptid, CORE_ADDR addr, - int len); +#define FETCH_INFERIOR_REGISTERS #endif /* #ifndef NM_LINUX_H */ diff --git a/gdb/config/ia64/tm-linux.h b/gdb/config/ia64/tm-linux.h deleted file mode 100644 index 5c8db313005..00000000000 --- a/gdb/config/ia64/tm-linux.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Definitions to target GDB to GNU/Linux on ia64. - - Copyright 1992, 1993, 2000, 2004, 2005, 2007 Free Software Foundation, Inc. - - This file is part of GDB. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef TM_LINUX_H -#define TM_LINUX_H - -extern int ia64_linux_in_sigtramp (CORE_ADDR pc, char *func_name); -#define DEPRECATED_IN_SIGTRAMP(pc,func_name) ia64_linux_in_sigtramp (pc, func_name) - -#endif /* #ifndef TM_LINUX_H */ diff --git a/gdb/ia64-linux-nat.c b/gdb/ia64-linux-nat.c index bce6e55fa47..989550a8120 100644 --- a/gdb/ia64-linux-nat.c +++ b/gdb/ia64-linux-nat.c @@ -303,8 +303,8 @@ static int u_offsets[] = -1, -1, -1, -1, -1, -1, -1, -1, }; -CORE_ADDR -register_addr (int regno, CORE_ADDR blockend) +static CORE_ADDR +ia64_register_addr (int regno) { CORE_ADDR addr; @@ -319,14 +319,14 @@ register_addr (int regno, CORE_ADDR blockend) return addr; } -int ia64_cannot_fetch_register (regno) - int regno; +static int +ia64_cannot_fetch_register (int regno) { return regno < 0 || regno >= NUM_REGS || u_offsets[regno] == -1; } -int ia64_cannot_store_register (regno) - int regno; +static int +ia64_cannot_store_register (int regno) { /* Rationale behind not permitting stores to bspstore... @@ -561,9 +561,10 @@ is_power_of_2 (int val) return onecount <= 1; } -int -ia64_linux_insert_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int rw) +static int +ia64_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw) { + ptid_t ptid = inferior_ptid; int idx; long dbr_addr, dbr_mask; int max_watchpoints = 4; @@ -608,9 +609,10 @@ ia64_linux_insert_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int rw) return 0; } -int -ia64_linux_remove_watchpoint (ptid_t ptid, CORE_ADDR addr, int len) +static int +ia64_linux_remove_watchpoint (CORE_ADDR addr, int len, int type) { + ptid_t ptid = inferior_ptid; int idx; long dbr_addr, dbr_mask; int max_watchpoints = 4; @@ -632,8 +634,8 @@ ia64_linux_remove_watchpoint (ptid_t ptid, CORE_ADDR addr, int len) return -1; } -int -ia64_linux_stopped_data_address (CORE_ADDR *addr_p) +static int +ia64_linux_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p) { CORE_ADDR psr; int tid; @@ -660,13 +662,130 @@ ia64_linux_stopped_data_address (CORE_ADDR *addr_p) return 1; } -int +static int ia64_linux_stopped_by_watchpoint (void) { CORE_ADDR addr; - return ia64_linux_stopped_data_address (&addr); + return ia64_linux_stopped_data_address (¤t_target, &addr); +} + +static int +ia64_linux_can_use_hw_breakpoint (int type, int cnt, int othertype) +{ + return 1; +} + + +/* Fetch register REGNUM from the inferior. */ + +static void +ia64_linux_fetch_register (int regnum) +{ + CORE_ADDR addr; + size_t size; + PTRACE_TYPE_RET *buf; + int pid, i; + + if (ia64_cannot_fetch_register (regnum)) + { + regcache_raw_supply (current_regcache, regnum, NULL); + return; + } + + /* Cater for systems like GNU/Linux, that implement threads as + separate processes. */ + pid = ptid_get_lwp (inferior_ptid); + if (pid == 0) + pid = ptid_get_pid (inferior_ptid); + + /* This isn't really an address, but ptrace thinks of it as one. */ + addr = ia64_register_addr (regnum); + size = register_size (current_gdbarch, regnum); + + gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0); + buf = alloca (size); + + /* Read the register contents from the inferior a chunk at a time. */ + for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++) + { + errno = 0; + buf[i] = ptrace (PT_READ_U, pid, (PTRACE_TYPE_ARG3)addr, 0); + if (errno != 0) + error (_("Couldn't read register %s (#%d): %s."), + REGISTER_NAME (regnum), regnum, safe_strerror (errno)); + + addr += sizeof (PTRACE_TYPE_RET); + } + regcache_raw_supply (current_regcache, regnum, buf); +} + +/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this + for all registers. */ + +static void +ia64_linux_fetch_registers (int regnum) +{ + if (regnum == -1) + for (regnum = 0; regnum < NUM_REGS; regnum++) + ia64_linux_fetch_register (regnum); + else + ia64_linux_fetch_register (regnum); +} + +/* Store register REGNUM into the inferior. */ + +static void +ia64_linux_store_register (int regnum) +{ + CORE_ADDR addr; + size_t size; + PTRACE_TYPE_RET *buf; + int pid, i; + + if (ia64_cannot_store_register (regnum)) + return; + + /* Cater for systems like GNU/Linux, that implement threads as + separate processes. */ + pid = ptid_get_lwp (inferior_ptid); + if (pid == 0) + pid = ptid_get_pid (inferior_ptid); + + /* This isn't really an address, but ptrace thinks of it as one. */ + addr = ia64_register_addr (regnum); + size = register_size (current_gdbarch, regnum); + + gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0); + buf = alloca (size); + + /* Write the register contents into the inferior a chunk at a time. */ + regcache_raw_collect (current_regcache, regnum, buf); + for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++) + { + errno = 0; + ptrace (PT_WRITE_U, pid, (PTRACE_TYPE_ARG3)addr, buf[i]); + if (errno != 0) + error (_("Couldn't write register %s (#%d): %s."), + REGISTER_NAME (regnum), regnum, safe_strerror (errno)); + + addr += sizeof (PTRACE_TYPE_RET); + } } +/* Store register REGNUM back into the inferior. If REGNUM is -1, do + this for all registers. */ + +static void +ia64_linux_store_registers (int regnum) +{ + if (regnum == -1) + for (regnum = 0; regnum < NUM_REGS; regnum++) + ia64_linux_store_register (regnum); + else + ia64_linux_store_register (regnum); +} + + static LONGEST (*super_xfer_partial) (struct target_ops *, enum target_object, const char *, gdb_byte *, const gdb_byte *, ULONGEST, LONGEST); @@ -695,10 +814,32 @@ _initialize_ia64_linux_nat (void) /* Fill in the generic GNU/Linux methods. */ t = linux_target (); + /* Override the default fetch/store register routines. */ + t->to_fetch_registers = ia64_linux_fetch_registers; + t->to_store_registers = ia64_linux_store_registers; + /* Override the default to_xfer_partial. */ super_xfer_partial = t->to_xfer_partial; t->to_xfer_partial = ia64_linux_xfer_partial; + /* Override watchpoint routines. */ + + /* The IA-64 architecture can step over a watch point (without triggering + it again) if the "dd" (data debug fault disable) bit in the processor + status word is set. + + This PSR bit is set in ia64_linux_stopped_by_watchpoint when the + code there has determined that a hardware watchpoint has indeed + been hit. The CPU will then be able to execute one instruction + without triggering a watchpoint. */ + + t->to_have_steppable_watchpoint = 1; + t->to_can_use_hw_breakpoint = ia64_linux_can_use_hw_breakpoint; + t->to_stopped_by_watchpoint = ia64_linux_stopped_by_watchpoint; + t->to_stopped_data_address = ia64_linux_stopped_data_address; + t->to_insert_watchpoint = ia64_linux_insert_watchpoint; + t->to_remove_watchpoint = ia64_linux_remove_watchpoint; + /* Register the target. */ linux_nat_add_target (t); } diff --git a/gdb/ia64-linux-tdep.c b/gdb/ia64-linux-tdep.c index 286a00dd2b8..bb7d4b478e6 100644 --- a/gdb/ia64-linux-tdep.c +++ b/gdb/ia64-linux-tdep.c @@ -39,8 +39,8 @@ /* Offset to sigcontext structure from frame of handler */ #define IA64_LINUX_SIGCONTEXT_OFFSET 192 -int -ia64_linux_in_sigtramp (CORE_ADDR pc, char *func_name) +static int +ia64_linux_pc_in_sigtramp (CORE_ADDR pc) { return (pc >= (CORE_ADDR) GATE_AREA_START && pc < (CORE_ADDR) GATE_AREA_END); } @@ -125,6 +125,9 @@ ia64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) registers are saved. */ tdep->sigcontext_register_address = ia64_linux_sigcontext_register_address; + /* Set the pc_in_sigtramp method. */ + tdep->pc_in_sigtramp = ia64_linux_pc_in_sigtramp; + set_gdbarch_write_pc (gdbarch, ia64_linux_write_pc); set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c index 98ca406eb5f..09c37068bed 100644 --- a/gdb/ia64-tdep.c +++ b/gdb/ia64-tdep.c @@ -2078,12 +2078,14 @@ static const struct frame_unwind ia64_sigtramp_frame_unwind = static const struct frame_unwind * ia64_sigtramp_frame_sniffer (struct frame_info *next_frame) { - char *name; - CORE_ADDR pc = frame_pc_unwind (next_frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (next_frame)); + if (tdep->pc_in_sigtramp) + { + CORE_ADDR pc = frame_pc_unwind (next_frame); - find_pc_partial_function (pc, &name, NULL, NULL); - if (legacy_pc_in_sigtramp (pc, name)) - return &ia64_sigtramp_frame_unwind; + if (tdep->pc_in_sigtramp (pc)) + return &ia64_sigtramp_frame_unwind; + } return NULL; } @@ -3576,6 +3578,7 @@ ia64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) gdbarch = gdbarch_alloc (&info, tdep); tdep->sigcontext_register_address = 0; + tdep->pc_in_sigtramp = 0; /* Define the ia64 floating-point format to gdb. */ builtin_type_ia64_ext = diff --git a/gdb/ia64-tdep.h b/gdb/ia64-tdep.h index a6531476888..469d981aa77 100644 --- a/gdb/ia64-tdep.h +++ b/gdb/ia64-tdep.h @@ -199,6 +199,7 @@ struct gdbarch_tdep { CORE_ADDR (*sigcontext_register_address) (CORE_ADDR, int); + int (*pc_in_sigtramp) (CORE_ADDR); }; extern void ia64_write_pc (CORE_ADDR, ptid_t); diff --git a/gdb/infrun.c b/gdb/infrun.c index 0bea6a9a1f8..394fa869e7e 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -197,13 +197,6 @@ a command like `return' or `jump' to continue execution.")); /* Convert the #defines into values. This is temporary until wfi control flow is completely sorted out. */ -#ifndef HAVE_STEPPABLE_WATCHPOINT -#define HAVE_STEPPABLE_WATCHPOINT 0 -#else -#undef HAVE_STEPPABLE_WATCHPOINT -#define HAVE_STEPPABLE_WATCHPOINT 1 -#endif - #ifndef CANNOT_STEP_HW_WATCHPOINTS #define CANNOT_STEP_HW_WATCHPOINTS 0 #else diff --git a/gdb/target.c b/gdb/target.c index f9d6064e0c4..7d9d315795a 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -413,6 +413,7 @@ update_current_target (void) INHERIT (to_remove_watchpoint, t); INHERIT (to_stopped_data_address, t); INHERIT (to_stopped_by_watchpoint, t); + INHERIT (to_have_steppable_watchpoint, t); INHERIT (to_have_continuable_watchpoint, t); INHERIT (to_region_ok_for_hw_watchpoint, t); INHERIT (to_terminal_init, t); diff --git a/gdb/target.h b/gdb/target.h index 7a5f084888b..d9f1ca17cea 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -362,6 +362,7 @@ struct target_ops int (*to_remove_watchpoint) (CORE_ADDR, int, int); int (*to_insert_watchpoint) (CORE_ADDR, int, int); int (*to_stopped_by_watchpoint) (void); + int to_have_steppable_watchpoint; int to_have_continuable_watchpoint; int (*to_stopped_data_address) (struct target_ops *, CORE_ADDR *); int (*to_region_ok_for_hw_watchpoint) (CORE_ADDR, int); @@ -1128,6 +1129,13 @@ extern void (*deprecated_target_new_objfile_hook) (struct objfile *); (*current_target.to_stopped_by_watchpoint) () #endif +/* Non-zero if we have steppable watchpoints */ + +#ifndef HAVE_STEPPABLE_WATCHPOINT +#define HAVE_STEPPABLE_WATCHPOINT \ + (current_target.to_have_steppable_watchpoint) +#endif + /* Non-zero if we have continuable watchpoints */ #ifndef HAVE_CONTINUABLE_WATCHPOINT