X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fppcnbsd-nat.c;h=a200505cef86975fac73a02532d58890db54f491;hb=def18405fbc42d460b2282b273b8d597eff96ebf;hp=3fba3971fd5a129559fd704a1a9a376e65377931;hpb=fba45db2faf619e71856ee38ec63949c0ef6903e;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/ppcnbsd-nat.c b/gdb/ppcnbsd-nat.c index 3fba3971fd..a200505cef 100644 --- a/gdb/ppcnbsd-nat.c +++ b/gdb/ppcnbsd-nat.c @@ -1,5 +1,8 @@ -/* 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, 2005, 2006 Free Software Foundation, Inc. + + Contributed by Wasabi Systems, Inc. This file is part of GDB. @@ -15,116 +18,176 @@ 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. */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ #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 (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 (int regnum) { - struct reg inferior_registers; - struct fpreg inferior_fp_registers; - int i; + struct gdbarch_tdep *tdep = gdbarch_tdep (current_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 == PC_REGNUM); +} + +/* 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 (int regnum) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (current_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 (current_gdbarch)); + + return ((regnum >= tdep->ppc_fp0_regnum + && regnum < tdep->ppc_fp0_regnum + ppc_num_fprs) + || regnum == tdep->ppc_fpscr_regnum); } -void -store_inferior_registers (int regno) +static void +ppcnbsd_fetch_inferior_registers (int regnum) { - struct reg inferior_registers; - struct fpreg inferior_fp_registers; - int i; + if (regnum == -1 || getregs_supplies (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, current_regcache, + regnum, ®s, sizeof regs); + } + + if (regnum == -1 || getfpregs_supplies (regnum)) + { + struct fpreg fpregs; - 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 (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, current_regcache, + regnum, &fpregs, sizeof fpregs); + } } -struct md_core +static void +ppcnbsd_store_inferior_registers (int regnum) { - struct reg intreg; - struct fpreg freg; -}; + if (regnum == -1 || getregs_supplies (regnum)) + { + struct reg regs; -void -fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which, - CORE_ADDR ignore) + 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, current_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 (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, current_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_tdep *tdep = gdbarch_tdep (current_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, PC_REGNUM, &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 (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); }