GDB (API)
|
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) ®s, 0) == -1) 00128 perror_with_name (_("Couldn't get registers")); 00129 00130 supply_gregset (regcache, ®s); 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) ®s, 0) == -1) 00156 perror_with_name (_("Couldn't get registers")); 00157 00158 fill_gregset (regcache, ®s, regno); 00159 00160 if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), 00161 (PTRACE_TYPE_ARG3) ®s, 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 }