1/* Native-dependent code for FreeBSD/arm. 2 3 Copyright (C) 2017-2020 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20#include "defs.h" 21#include "target.h" 22 23#include <sys/types.h> 24#include <sys/ptrace.h> 25#include <machine/reg.h> 26 27#include "fbsd-nat.h" 28#include "arm-tdep.h" 29#include "arm-fbsd-tdep.h" 30#include "inf-ptrace.h" 31 32struct arm_fbsd_nat_target : public fbsd_nat_target 33{ 34 void fetch_registers (struct regcache *, int) override; 35 void store_registers (struct regcache *, int) override; 36 const struct target_desc *read_description () override; 37}; 38 39static arm_fbsd_nat_target the_arm_fbsd_nat_target; 40 41/* Determine if PT_GETREGS fetches REGNUM. */ 42 43static bool 44getregs_supplies (int regnum) 45{ 46 return ((regnum >= ARM_A1_REGNUM && regnum <= ARM_PC_REGNUM) 47 || regnum == ARM_PS_REGNUM); 48} 49 50#ifdef PT_GETVFPREGS 51/* Determine if PT_GETVFPREGS fetches REGNUM. */ 52 53static bool 54getvfpregs_supplies (int regnum) 55{ 56 return ((regnum >= ARM_D0_REGNUM && regnum <= ARM_D31_REGNUM) 57 || regnum == ARM_FPSCR_REGNUM); 58} 59#endif 60 61/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this 62 for all registers. */ 63 64void 65arm_fbsd_nat_target::fetch_registers (struct regcache *regcache, int regnum) 66{ 67 pid_t pid = get_ptrace_pid (regcache->ptid ()); 68 69 if (regnum == -1 || getregs_supplies (regnum)) 70 { 71 struct reg regs; 72 73 if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) 74 perror_with_name (_("Couldn't get registers")); 75 76 regcache->supply_regset (&arm_fbsd_gregset, regnum, ®s, 77 sizeof (regs)); 78 } 79 80#ifdef PT_GETVFPREGS 81 if (regnum == -1 || getvfpregs_supplies (regnum)) 82 { 83 struct vfpreg vfpregs; 84 85 if (ptrace (PT_GETVFPREGS, pid, (PTRACE_TYPE_ARG3) &vfpregs, 0) == -1) 86 perror_with_name (_("Couldn't get floating point status")); 87 88 regcache->supply_regset (&arm_fbsd_vfpregset, regnum, &vfpregs, 89 sizeof (vfpregs)); 90 } 91#endif 92} 93 94/* Store register REGNUM back into the inferior. If REGNUM is -1, do 95 this for all registers. */ 96 97void 98arm_fbsd_nat_target::store_registers (struct regcache *regcache, int regnum) 99{ 100 pid_t pid = get_ptrace_pid (regcache->ptid ()); 101 102 if (regnum == -1 || getregs_supplies (regnum)) 103 { 104 struct reg regs; 105 106 if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) 107 perror_with_name (_("Couldn't get registers")); 108 109 regcache->collect_regset (&arm_fbsd_gregset, regnum, ®s, 110 sizeof (regs)); 111 112 if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) 113 perror_with_name (_("Couldn't write registers")); 114 } 115 116#ifdef PT_GETVFPREGS 117 if (regnum == -1 || getvfpregs_supplies (regnum)) 118 { 119 struct vfpreg vfpregs; 120 121 if (ptrace (PT_GETVFPREGS, pid, (PTRACE_TYPE_ARG3) &vfpregs, 0) == -1) 122 perror_with_name (_("Couldn't get floating point status")); 123 124 regcache->collect_regset (&arm_fbsd_vfpregset, regnum, &vfpregs, 125 sizeof (vfpregs)); 126 127 if (ptrace (PT_SETVFPREGS, pid, (PTRACE_TYPE_ARG3) &vfpregs, 0) == -1) 128 perror_with_name (_("Couldn't write floating point status")); 129 } 130#endif 131} 132 133/* Implement the to_read_description method. */ 134 135const struct target_desc * 136arm_fbsd_nat_target::read_description () 137{ 138 const struct target_desc *desc; 139 140 desc = arm_fbsd_read_description_auxv (this); 141 if (desc == NULL) 142 desc = this->beneath ()->read_description (); 143 return desc; 144} 145 146void _initialize_arm_fbsd_nat (); 147void 148_initialize_arm_fbsd_nat () 149{ 150 add_inf_child_target (&the_arm_fbsd_nat_target); 151} 152