X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fppcnbsd-nat.c;h=2b7837dfeb81a817650e07aa19b6f472af4d3981;hb=2dc3df72a7ffca9a893ae41db8c3788c0019d59c;hp=b754fa71a4893d1b5541053c555c83f40353146a;hpb=d0352a18a504a4e7b761f6b3264cf11347d8d056;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/ppcnbsd-nat.c b/gdb/ppcnbsd-nat.c index b754fa71a4..2b7837dfeb 100644 --- a/gdb/ppcnbsd-nat.c +++ b/gdb/ppcnbsd-nat.c @@ -1,11 +1,14 @@ -/* Native-dependent code for PowerPC's running NetBSD, for GDB. - Copyright 1988, 1989, 1991, 1992, 1994, 1996, 2000 Free Software Foundation, Inc. +/* Native-dependent code for NetBSD/powerpc. + + Copyright (C) 2002, 2004-2012 Free Software Foundation, Inc. + + Contributed by Wasabi Systems, 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -14,122 +17,183 @@ 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. */ + along with this program. If not, see . */ + +#include "defs.h" #include #include #include #include +#include -#include "defs.h" -#include "inferior.h" #include "gdbcore.h" +#include "inferior.h" +#include "regcache.h" -#define RF(dst, src) \ - memcpy(®isters[REGISTER_BYTE(dst)], &src, sizeof(src)) - -#define RS(src, dst) \ - memcpy(&dst, ®isters[REGISTER_BYTE(src)], sizeof(dst)) +#include "gdb_assert.h" -void -fetch_inferior_registers (regno) - int regno; +#include "ppc-tdep.h" +#include "ppcnbsd-tdep.h" +#include "bsd-kvm.h" +#include "inf-ptrace.h" + +/* Returns true if PT_GETREGS fetches this register. */ + +static int +getregs_supplies (struct gdbarch *gdbarch, int regnum) { - struct reg inferior_registers; - struct fpreg inferior_fp_registers; - int i; + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + return ((regnum >= tdep->ppc_gp0_regnum + && regnum < tdep->ppc_gp0_regnum + ppc_num_gprs) + || regnum == tdep->ppc_lr_regnum + || regnum == tdep->ppc_cr_regnum + || regnum == tdep->ppc_xer_regnum + || regnum == tdep->ppc_ctr_regnum + || regnum == gdbarch_pc_regnum (gdbarch)); +} + +/* Like above, but for PT_GETFPREGS. */ - ptrace (PT_GETREGS, inferior_pid, - (PTRACE_ARG3_TYPE) & inferior_registers, 0); - for (i = 0; i < 32; i++) - RF (i, inferior_registers.fixreg[i]); - RF (LR_REGNUM, inferior_registers.lr); - RF (CR_REGNUM, inferior_registers.cr); - RF (XER_REGNUM, inferior_registers.xer); - RF (CTR_REGNUM, inferior_registers.ctr); - RF (PC_REGNUM, inferior_registers.pc); - - ptrace (PT_GETFPREGS, inferior_pid, - (PTRACE_ARG3_TYPE) & inferior_fp_registers, 0); - for (i = 0; i < 32; i++) - RF (FP0_REGNUM + i, inferior_fp_registers.r_regs[i]); - - registers_fetched (); +static int +getfpregs_supplies (struct gdbarch *gdbarch, int regnum) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating + point registers. Traditionally, GDB's register set has still + listed the floating point registers for such machines, so this + code is harmless. However, the new E500 port actually omits the + floating point registers entirely from the register set --- they + don't even have register numbers assigned to them. + + It's not clear to me how best to update this code, so this assert + will alert the first person to encounter the NetBSD/E500 + combination to the problem. */ + gdb_assert (ppc_floating_point_unit_p (gdbarch)); + + return ((regnum >= tdep->ppc_fp0_regnum + && regnum < tdep->ppc_fp0_regnum + ppc_num_fprs) + || regnum == tdep->ppc_fpscr_regnum); } -void -store_inferior_registers (regno) - int regno; +static void +ppcnbsd_fetch_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) { - struct reg inferior_registers; - struct fpreg inferior_fp_registers; - int i; + struct gdbarch *gdbarch = get_regcache_arch (regcache); + + if (regnum == -1 || getregs_supplies (gdbarch, regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + ppc_supply_gregset (&ppcnbsd_gregset, regcache, + regnum, ®s, sizeof regs); + } - for (i = 0; i < 32; i++) - RS (i, inferior_registers.fixreg[i]); - RS (LR_REGNUM, inferior_registers.lr); - RS (CR_REGNUM, inferior_registers.cr); - RS (XER_REGNUM, inferior_registers.xer); - RS (CTR_REGNUM, inferior_registers.ctr); - RS (PC_REGNUM, inferior_registers.pc); - - ptrace (PT_SETREGS, inferior_pid, - (PTRACE_ARG3_TYPE) & inferior_registers, 0); - - for (i = 0; i < 32; i++) - RS (FP0_REGNUM + i, inferior_fp_registers.r_regs[i]); - ptrace (PT_SETFPREGS, inferior_pid, - (PTRACE_ARG3_TYPE) & inferior_fp_registers, 0); + if (regnum == -1 || getfpregs_supplies (gdbarch, regnum)) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get FP registers")); + + ppc_supply_fpregset (&ppcnbsd_fpregset, regcache, + regnum, &fpregs, sizeof fpregs); + } } -struct md_core +static void +ppcnbsd_store_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) { - struct reg intreg; - struct fpreg freg; -}; + struct gdbarch *gdbarch = get_regcache_arch (regcache); -void -fetch_core_registers (core_reg_sect, core_reg_size, which, ignore) - char *core_reg_sect; - unsigned core_reg_size; - int which; - CORE_ADDR ignore; + if (regnum == -1 || getregs_supplies (gdbarch, regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + ppc_collect_gregset (&ppcnbsd_gregset, regcache, + regnum, ®s, sizeof regs); + + if (ptrace (PT_SETREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't write registers")); + } + + if (regnum == -1 || getfpregs_supplies (gdbarch, regnum)) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get FP registers")); + + ppc_collect_fpregset (&ppcnbsd_fpregset, regcache, + regnum, &fpregs, sizeof fpregs); + + if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't set FP registers")); + } +} + +static int +ppcnbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) { - struct md_core *core_reg = (struct md_core *) core_reg_sect; + struct switchframe sf; + struct callframe cf; + struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int i; - /* Integer registers */ - for (i = 0; i < 32; i++) - RF (i, core_reg->intreg.fixreg[i]); - RF (LR_REGNUM, core_reg->intreg.lr); - RF (CR_REGNUM, core_reg->intreg.cr); - RF (XER_REGNUM, core_reg->intreg.xer); - RF (CTR_REGNUM, core_reg->intreg.ctr); - RF (PC_REGNUM, core_reg->intreg.pc); + /* The stack pointer shouldn't be zero. */ + if (pcb->pcb_sp == 0) + return 0; - /* Floating point registers */ - for (i = 0; i < 32; i++) - RF (FP0_REGNUM + i, core_reg->freg.r_regs[i]); + read_memory (pcb->pcb_sp, (gdb_byte *)&sf, sizeof sf); + regcache_raw_supply (regcache, tdep->ppc_cr_regnum, &sf.cr); + regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 2, &sf.fixreg2); + for (i = 0 ; i < 19 ; i++) + regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 13 + i, + &sf.fixreg[i]); - registers_fetched (); -} + read_memory(sf.sp, (gdb_byte *)&cf, sizeof(cf)); + regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 30, &cf.r30); + regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 31, &cf.r31); + regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 1, &cf.sp); -/* Register that we are able to handle ppcnbsd core file formats. - FIXME: is this really bfd_target_unknown_flavour? */ + read_memory(cf.sp, (gdb_byte *)&cf, sizeof(cf)); + regcache_raw_supply (regcache, tdep->ppc_lr_regnum, &cf.lr); + regcache_raw_supply (regcache, gdbarch_pc_regnum (gdbarch), &cf.lr); -static struct core_fns ppcnbsd_core_fns = -{ - bfd_target_unknown_flavour, /* core_flavour */ - default_check_format, /* check_format */ - default_core_sniffer, /* core_sniffer */ - fetch_core_registers, /* core_read_registers */ - NULL /* next */ -}; + return 1; +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_ppcnbsd_nat (void); void -_initialize_ppcnbsd_nat () +_initialize_ppcnbsd_nat (void) { - add_core_fns (&ppcnbsd_core_fns); + struct target_ops *t; + + /* Support debugging kernel virtual memory images. */ + bsd_kvm_add_target (ppcnbsd_supply_pcb); + + /* Add in local overrides. */ + t = inf_ptrace_target (); + t->to_fetch_registers = ppcnbsd_fetch_inferior_registers; + t->to_store_registers = ppcnbsd_store_inferior_registers; + add_target (t); }