GDB (API)
/home/stan/gdb/src/gdb/ppcfbsd-nat.c
Go to the documentation of this file.
00001 /* Native-dependent code for PowerPC's running FreeBSD, for GDB.
00002 
00003    Copyright (C) 2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 #include "defs.h"
00021 #include "gdbcore.h"
00022 #include "inferior.h"
00023 #include "regcache.h"
00024 
00025 #include "gdb_assert.h"
00026 #include <stddef.h>
00027 #include <sys/types.h>
00028 #include <sys/procfs.h>
00029 #include <sys/ptrace.h>
00030 #include <sys/signal.h>
00031 #include <machine/frame.h>
00032 #include <machine/pcb.h>
00033 #include <machine/reg.h>
00034 
00035 #include "fbsd-nat.h"
00036 #include "gregset.h"
00037 #include "ppc-tdep.h"
00038 #include "ppcfbsd-tdep.h"
00039 #include "inf-ptrace.h"
00040 #include "bsd-kvm.h"
00041 
00042 /* Fill GDB's register array with the general-purpose register values
00043    in *GREGSETP.  */
00044 
00045 void
00046 supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
00047 {
00048   const struct regset *regset = ppc_fbsd_gregset (sizeof (long));
00049 
00050   ppc_supply_gregset (regset, regcache, -1, gregsetp, sizeof (*gregsetp));
00051 }
00052 
00053 /* Fill register REGNO (if a gpr) in *GREGSETP with the value in GDB's
00054    register array. If REGNO is -1 do it for all registers.  */
00055 
00056 void
00057 fill_gregset (const struct regcache *regcache,
00058               gdb_gregset_t *gregsetp, int regno)
00059 {
00060   const struct regset *regset = ppc_fbsd_gregset (sizeof (long));
00061 
00062   if (regno == -1)
00063     memset (gregsetp, 0, sizeof (*gregsetp));
00064   ppc_collect_gregset (regset, regcache, regno, gregsetp, sizeof (*gregsetp));
00065 }
00066 
00067 /* Fill GDB's register array with the floating-point register values
00068    in *FPREGSETP.  */
00069 
00070 void
00071 supply_fpregset (struct regcache *regcache, const gdb_fpregset_t * fpregsetp)
00072 {
00073   const struct regset *regset = ppc_fbsd_fpregset ();
00074 
00075   ppc_supply_fpregset (regset, regcache, -1,
00076                        fpregsetp, sizeof (*fpregsetp));
00077 }
00078 
00079 /* Fill register REGNO in *FGREGSETP with the value in GDB's
00080    register array. If REGNO is -1 do it for all registers.  */
00081 
00082 void
00083 fill_fpregset (const struct regcache *regcache,
00084                gdb_fpregset_t *fpregsetp, int regno)
00085 {
00086   const struct regset *regset = ppc_fbsd_fpregset ();
00087 
00088   ppc_collect_fpregset (regset, regcache, regno,
00089                         fpregsetp, sizeof (*fpregsetp));
00090 }
00091 
00092 /* Returns true if PT_GETFPREGS fetches this register.  */
00093 
00094 static int
00095 getfpregs_supplies (struct gdbarch *gdbarch, int regno)
00096 {
00097   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
00098 
00099   /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating
00100          point registers.  Traditionally, GDB's register set has still
00101          listed the floating point registers for such machines, so this
00102          code is harmless.  However, the new E500 port actually omits the
00103          floating point registers entirely from the register set --- they
00104          don't even have register numbers assigned to them.
00105 
00106          It's not clear to me how best to update this code, so this assert
00107          will alert the first person to encounter the NetBSD/E500
00108          combination to the problem.  */
00109 
00110   gdb_assert (ppc_floating_point_unit_p (gdbarch));
00111 
00112   return ((regno >= tdep->ppc_fp0_regnum
00113            && regno < tdep->ppc_fp0_regnum + ppc_num_fprs)
00114           || regno == tdep->ppc_fpscr_regnum);
00115 }
00116 
00117 /* Fetch register REGNO from the child process. If REGNO is -1, do it
00118    for all registers.  */
00119 
00120 static void
00121 ppcfbsd_fetch_inferior_registers (struct target_ops *ops,
00122                                   struct regcache *regcache, int regno)
00123 {
00124   gdb_gregset_t regs;
00125 
00126   if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid),
00127               (PTRACE_TYPE_ARG3) &regs, 0) == -1)
00128     perror_with_name (_("Couldn't get registers"));
00129 
00130   supply_gregset (regcache, &regs);
00131 
00132   if (regno == -1 || getfpregs_supplies (get_regcache_arch (regcache), regno))
00133     {
00134       const struct regset *fpregset = ppc_fbsd_fpregset ();
00135       gdb_fpregset_t fpregs;
00136 
00137       if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid),
00138                   (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
00139         perror_with_name (_("Couldn't get FP registers"));
00140 
00141       ppc_supply_fpregset (fpregset, regcache, regno, &fpregs, sizeof fpregs);
00142     }
00143 }
00144 
00145 /* Store register REGNO back into the child process. If REGNO is -1,
00146    do this for all registers.  */
00147 
00148 static void
00149 ppcfbsd_store_inferior_registers (struct target_ops *ops,
00150                                   struct regcache *regcache, int regno)
00151 {
00152   gdb_gregset_t regs;
00153 
00154   if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid),
00155               (PTRACE_TYPE_ARG3) &regs, 0) == -1)
00156     perror_with_name (_("Couldn't get registers"));
00157 
00158   fill_gregset (regcache, &regs, regno);
00159 
00160   if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid),
00161               (PTRACE_TYPE_ARG3) &regs, 0) == -1)
00162     perror_with_name (_("Couldn't write registers"));
00163 
00164   if (regno == -1 || getfpregs_supplies (get_regcache_arch (regcache), regno))
00165     {
00166       gdb_fpregset_t fpregs;
00167 
00168       if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid),
00169                   (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
00170         perror_with_name (_("Couldn't get FP registers"));
00171 
00172       fill_fpregset (regcache, &fpregs, regno);
00173 
00174       if (ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid),
00175                   (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
00176         perror_with_name (_("Couldn't set FP registers"));
00177     }
00178 }
00179 
00180 /* Architecture specific function that reconstructs the
00181    register state from PCB (Process Control Block) and supplies it
00182    to REGCACHE.  */
00183 
00184 static int
00185 ppcfbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
00186 {
00187   struct gdbarch *gdbarch = get_regcache_arch (regcache);
00188   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
00189   int i, regnum;
00190 
00191   /* The stack pointer shouldn't be zero.  */
00192   if (pcb->pcb_sp == 0)
00193     return 0;
00194 
00195   regcache_raw_supply (regcache, gdbarch_sp_regnum (gdbarch), &pcb->pcb_sp);
00196   regcache_raw_supply (regcache, tdep->ppc_cr_regnum, &pcb->pcb_cr);
00197   regcache_raw_supply (regcache, tdep->ppc_lr_regnum, &pcb->pcb_lr);
00198   for (i = 0, regnum = tdep->ppc_gp0_regnum + 14; i < 20; i++, regnum++)
00199     regcache_raw_supply (regcache, regnum, &pcb->pcb_context[i]);
00200 
00201   return 1;
00202 }
00203 
00204 /* Provide a prototype to silence -Wmissing-prototypes.  */
00205 
00206 void _initialize_ppcfbsd_nat (void);
00207 
00208 void
00209 _initialize_ppcfbsd_nat (void)
00210 {
00211   struct target_ops *t;
00212 
00213   /* Add in local overrides.  */
00214   t = inf_ptrace_target ();
00215   t->to_fetch_registers = ppcfbsd_fetch_inferior_registers;
00216   t->to_store_registers = ppcfbsd_store_inferior_registers;
00217   t->to_pid_to_exec_file = fbsd_pid_to_exec_file;
00218   t->to_find_memory_regions = fbsd_find_memory_regions;
00219   t->to_make_corefile_notes = fbsd_make_corefile_notes;
00220   add_target (t);
00221 
00222   /* Support debugging kernel virtual memory images.  */
00223   bsd_kvm_add_target (ppcfbsd_supply_pcb);
00224 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines