Commit | Line | Data |
---|---|---|
4f9d9906 JB |
1 | /* Native-dependent code for FreeBSD/arm. |
2 | ||
3 | Copyright (C) 2017 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 | ||
32 | /* Determine if PT_GETREGS fetches REGNUM. */ | |
33 | ||
34 | static bool | |
35 | getregs_supplies (struct gdbarch *gdbarch, int regnum) | |
36 | { | |
37 | return ((regnum >= ARM_A1_REGNUM && regnum <= ARM_PC_REGNUM) | |
38 | || regnum == ARM_PS_REGNUM); | |
39 | } | |
40 | ||
41 | #ifdef PT_GETVFPREGS | |
42 | /* Determine if PT_GETVFPREGS fetches REGNUM. */ | |
43 | ||
44 | static bool | |
45 | getvfpregs_supplies (struct gdbarch *gdbarch, int regnum) | |
46 | { | |
47 | return ((regnum >= ARM_D0_REGNUM && regnum <= ARM_D31_REGNUM) | |
48 | || regnum == ARM_FPSCR_REGNUM); | |
49 | } | |
50 | #endif | |
51 | ||
52 | /* Fetch register REGNUM from the inferior. If REGNUM is -1, do this | |
53 | for all registers. */ | |
54 | ||
55 | static void | |
56 | arm_fbsd_fetch_inferior_registers (struct target_ops *ops, | |
57 | struct regcache *regcache, int regnum) | |
58 | { | |
59 | pid_t pid = get_ptrace_pid (regcache_get_ptid (regcache)); | |
60 | ||
61 | struct gdbarch *gdbarch = get_regcache_arch (regcache); | |
62 | if (regnum == -1 || getregs_supplies (gdbarch, regnum)) | |
63 | { | |
64 | struct reg regs; | |
65 | ||
66 | if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) | |
67 | perror_with_name (_("Couldn't get registers")); | |
68 | ||
69 | regcache->supply_regset (&arm_fbsd_gregset, regnum, ®s, | |
70 | sizeof (regs)); | |
71 | } | |
72 | ||
73 | #ifdef PT_GETVFPREGS | |
74 | if (regnum == -1 || getvfpregs_supplies (gdbarch, regnum)) | |
75 | { | |
76 | struct vfpreg vfpregs; | |
77 | ||
78 | if (ptrace (PT_GETVFPREGS, pid, (PTRACE_TYPE_ARG3) &vfpregs, 0) == -1) | |
79 | perror_with_name (_("Couldn't get floating point status")); | |
80 | ||
81 | regcache->supply_regset (&arm_fbsd_vfpregset, regnum, &vfpregs, | |
82 | sizeof (vfpregs)); | |
83 | } | |
84 | #endif | |
85 | } | |
86 | ||
87 | /* Store register REGNUM back into the inferior. If REGNUM is -1, do | |
88 | this for all registers. */ | |
89 | ||
90 | static void | |
91 | arm_fbsd_store_inferior_registers (struct target_ops *ops, | |
92 | struct regcache *regcache, int regnum) | |
93 | { | |
94 | pid_t pid = get_ptrace_pid (regcache_get_ptid (regcache)); | |
95 | ||
96 | struct gdbarch *gdbarch = get_regcache_arch (regcache); | |
97 | if (regnum == -1 || getregs_supplies (gdbarch, regnum)) | |
98 | { | |
99 | struct reg regs; | |
100 | ||
101 | if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) | |
102 | perror_with_name (_("Couldn't get registers")); | |
103 | ||
104 | regcache->collect_regset (&arm_fbsd_gregset, regnum, ®s, | |
105 | sizeof (regs)); | |
106 | ||
107 | if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) | |
108 | perror_with_name (_("Couldn't write registers")); | |
109 | } | |
110 | ||
111 | #ifdef PT_GETVFPREGS | |
112 | if (regnum == -1 || getvfpregs_supplies (gdbarch, regnum)) | |
113 | { | |
114 | struct vfpreg vfpregs; | |
115 | ||
116 | if (ptrace (PT_GETVFPREGS, pid, (PTRACE_TYPE_ARG3) &vfpregs, 0) == -1) | |
117 | perror_with_name (_("Couldn't get floating point status")); | |
118 | ||
119 | regcache->collect_regset (&arm_fbsd_vfpregset, regnum, &vfpregs, | |
120 | sizeof (vfpregs)); | |
121 | ||
122 | if (ptrace (PT_SETVFPREGS, pid, (PTRACE_TYPE_ARG3) &vfpregs, 0) == -1) | |
123 | perror_with_name (_("Couldn't write floating point status")); | |
124 | } | |
125 | #endif | |
126 | } | |
127 | ||
128 | /* Implement the to_read_description method. */ | |
129 | ||
130 | static const struct target_desc * | |
131 | arm_fbsd_read_description (struct target_ops *ops) | |
132 | { | |
133 | const struct target_desc *desc; | |
134 | ||
135 | desc = arm_fbsd_read_description_auxv (ops); | |
136 | if (desc == NULL) | |
137 | desc = ops->beneath->to_read_description (ops->beneath); | |
138 | return desc; | |
139 | } | |
140 | ||
141 | void | |
142 | _initialize_arm_fbsd_nat (void) | |
143 | { | |
144 | struct target_ops *t; | |
145 | ||
146 | t = inf_ptrace_target (); | |
147 | t->to_fetch_registers = arm_fbsd_fetch_inferior_registers; | |
148 | t->to_store_registers = arm_fbsd_store_inferior_registers; | |
149 | t->to_read_description = arm_fbsd_read_description; | |
150 | fbsd_nat_add_target (t); | |
151 | } |