2005-07-14 Jeff Johnsotn * linux-nat.c (linux_nat_xfer_memory): Incorporate Fujitsu work-around to use /proc/mem for storage, but to fall-back to PTRACE for ia64 rse register areas. * ia64-linux-nat.c (ia64_rse_slot_num): New static function. (ia64_rse_skip_regs): Ditto. (ia64_linux_check_stack_region): New function. Index: gdb-6.8.50.20090226/gdb/linux-nat.c =================================================================== --- gdb-6.8.50.20090226.orig/gdb/linux-nat.c 2009-02-27 07:51:44.000000000 +0100 +++ gdb-6.8.50.20090226/gdb/linux-nat.c 2009-02-28 07:19:05.000000000 +0100 @@ -4386,15 +4386,38 @@ linux_xfer_partial (struct target_ops *o return linux_nat_xfer_osdata (ops, object, annex, readbuf, writebuf, offset, len); -#ifndef NATIVE_XFER_UNWIND_TABLE - /* FIXME: For ia64, we cannot currently use linux_proc_xfer_memory - for accessing thread storage. Revert when Bugzilla 147436 - is fixed. */ xfer = linux_proc_xfer_partial (ops, object, annex, readbuf, writebuf, offset, len); if (xfer != 0) - return xfer; + { +#ifdef NATIVE_XFER_UNWIND_TABLE + struct mem_region range; + range.lo = memaddr; + range.hi = memaddr + len; + + /* FIXME: For ia64, we cannot currently use + linux_proc_xfer_partial for accessing rse register storage. + Revert when Bugzilla 147436 is fixed. */ +#ifdef NATIVE_XFER_UNWIND_TABLE + extern int ia64_linux_check_stack_region (struct lwp_info *lwp, + void *range); +#endif + if (iterate_over_lwps (ia64_linux_check_stack_region, &range) != NULL) + { /* This region contains ia64 rse registers, we have to re-read. */ + int xxfer; + + /* Re-read register stack area. */ + xxfer = super_xfer_partial (ops, object, annex, + readbuf + (range.lo - memaddr), + writebuf + (range.lo - memaddr), + offset + (range.lo - memaddr), + range.hi - range.lo); + if (xxfer == 0) + xfer = 0; + } #endif + return xfer; + } return super_xfer_partial (ops, object, annex, readbuf, writebuf, offset, len); Index: gdb-6.8.50.20090226/gdb/ia64-linux-nat.c =================================================================== --- gdb-6.8.50.20090226.orig/gdb/ia64-linux-nat.c 2009-02-23 01:03:49.000000000 +0100 +++ gdb-6.8.50.20090226/gdb/ia64-linux-nat.c 2009-02-28 07:18:10.000000000 +0100 @@ -809,6 +809,64 @@ ia64_linux_xfer_partial (struct target_o void _initialize_ia64_linux_nat (void); +/* + * Note: taken from ia64_tdep.c + * + */ + +static __inline__ unsigned long +ia64_rse_slot_num (unsigned long addr) +{ + return (addr >> 3) & 0x3f; +} + +/* Skip over a designated number of registers in the backing + store, remembering every 64th position is for NAT. */ +static __inline__ unsigned long +ia64_rse_skip_regs (unsigned long addr, long num_regs) +{ + long delta = ia64_rse_slot_num(addr) + num_regs; + + if (num_regs < 0) + delta -= 0x3e; + return addr + ((num_regs + delta/0x3f) << 3); +} + +/* + * Check mem_region is stack or not. If stack, /proc//mem cannot return + * expected value. + */ +int ia64_linux_check_stack_region(struct lwp_info *ti, struct mem_region *range) +{ + CORE_ADDR addr; + int error; + unsigned long bsp, cfm, bspstore; + long sof; + pid_t pid = ptid_get_lwp(ti->ptid); + bsp = ptrace(PTRACE_PEEKUSER, pid, PT_AR_BSP ,NULL); + if (bsp == (unsigned long)-1) { + return 1; + } + /* stack is allocated by one-segment, not separated into several segments. + So, we only have to check whether bsp is in *range* or not. */ + if((range->lo <= bsp) && (bsp <= range->hi)) { + bspstore = ptrace(PTRACE_PEEKUSER, pid, PT_AR_BSPSTORE, NULL); + cfm = ptrace(PTRACE_PEEKUSER, pid, PT_CFM, NULL); + sof = cfm & 0x3f; + bsp = ia64_rse_skip_regs(bsp, -sof); + range->lo = bspstore; + range->hi = bsp; + /* we have to check the size of dirty register stack area */ + /* + fprintf_unfiltered(gdb_stdlog, "<%d> <%p> <%lx> <%p> <%p>\n", + pid, bsp, sof, range->lo, range->hi); + */ + return 1; + } + + return 0; +} + void _initialize_ia64_linux_nat (void) {