1 /* Native-dependent code for OpenBSD/powerpc.
2
3 Copyright (C) 2004, 2005, 2006 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 2 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, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
21
22 #include "defs.h"
23 #include "gdbcore.h"
24 #include "inferior.h"
25 #include "regcache.h"
26
27 #include "gdb_assert.h"
28 #include <stddef.h>
29 #include <sys/types.h>
30 #include <sys/ptrace.h>
31 #include <sys/signal.h>
32 #include <machine/frame.h>
33 #include <machine/pcb.h>
34 #include <machine/reg.h>
35
36 #include "obsd-nat.h"
37 #include "ppc-tdep.h"
38 #include "ppc64obsd-tdep.h"
39 #include "inf-ptrace.h"
40 #include "bsd-kvm.h"
41
42 /* OpenBSD/powerpc didn't have PT_GETFPREGS/PT_SETFPREGS until release
43 4.0. On older releases the floating-point registers are handled by
44 PT_GETREGS/PT_SETREGS, but fpscr wasn't available.. */
45
46 #ifdef PT_GETFPREGS
47
48 /* Returns true if PT_GETFPREGS fetches this register. */
49
50 static int
getfpregs_supplies(int regnum)51 getfpregs_supplies (int regnum)
52 {
53 struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
54
55 /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating
56 point registers. Traditionally, GDB's register set has still
57 listed the floating point registers for such machines, so this
58 code is harmless. However, the new E500 port actually omits the
59 floating point registers entirely from the register set --- they
60 don't even have register numbers assigned to them.
61
62 It's not clear to me how best to update this code, so this assert
63 will alert the first person to encounter the NetBSD/E500
64 combination to the problem. */
65 gdb_assert (ppc_floating_point_unit_p (current_gdbarch));
66
67 return ((regnum >= tdep->ppc_fp0_regnum
68 && regnum < tdep->ppc_fp0_regnum + ppc_num_fprs)
69 || regnum == tdep->ppc_fpscr_regnum);
70 }
71
72 #endif /* PT_GETFPREGS */
73
74 /* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
75 for all registers. */
76
77 static void
ppc64obsd_fetch_registers(int regnum)78 ppc64obsd_fetch_registers (int regnum)
79 {
80 struct reg regs;
81 int pid;
82
83 /* Cater for systems like OpenBSD, that implement threads as
84 separate processes. */
85 pid = ptid_get_lwp (inferior_ptid);
86 if (pid == 0)
87 pid = ptid_get_pid (inferior_ptid);
88
89 if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1)
90 perror_with_name (_("Couldn't get registers"));
91
92 ppc_supply_gregset (&ppc64obsd_gregset, current_regcache, -1,
93 ®s, sizeof regs);
94 #ifndef PT_GETFPREGS
95 ppc_supply_fpregset (&ppc64obsd_gregset, current_regcache, -1,
96 ®s, sizeof regs);
97 #endif
98
99 #ifdef PT_GETFPREGS
100 if (regnum == -1 || getfpregs_supplies (regnum))
101 {
102 struct fpreg fpregs;
103
104 if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
105 perror_with_name (_("Couldn't get floating point status"));
106
107 ppc_supply_fpregset (&ppc64obsd_fpregset, current_regcache, -1,
108 &fpregs, sizeof fpregs);
109 }
110 #endif
111 }
112
113 /* Store register REGNUM back into the inferior. If REGNUM is -1, do
114 this for all registers. */
115
116 static void
ppc64obsd_store_registers(int regnum)117 ppc64obsd_store_registers (int regnum)
118 {
119 struct reg regs;
120 int pid;
121
122 /* Cater for systems like OpenBSD, that implement threads as
123 separate processes. */
124 pid = ptid_get_lwp (inferior_ptid);
125 if (pid == 0)
126 pid = ptid_get_pid (inferior_ptid);
127
128 if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1)
129 perror_with_name (_("Couldn't get registers"));
130
131 ppc_collect_gregset (&ppc64obsd_gregset, current_regcache,
132 regnum, ®s, sizeof regs);
133 #ifndef PT_GETFPREGS
134 ppc_collect_fpregset (&ppc64obsd_gregset, current_regcache,
135 regnum, ®s, sizeof regs);
136 #endif
137
138 if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1)
139 perror_with_name (_("Couldn't write registers"));
140
141 #ifdef PT_GETFPREGS
142 if (regnum == -1 || getfpregs_supplies (regnum))
143 {
144 struct fpreg fpregs;
145
146 if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
147 perror_with_name (_("Couldn't get floating point status"));
148
149 ppc_collect_fpregset (&ppc64obsd_fpregset, current_regcache,
150 regnum, &fpregs, sizeof fpregs);
151
152 if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
153 perror_with_name (_("Couldn't write floating point status"));
154 }
155 #endif
156 }
157
158
159 static int
ppc64obsd_supply_pcb(struct regcache * regcache,struct pcb * pcb)160 ppc64obsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
161 {
162 #if 0
163 struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
164 struct switchframe sf;
165 struct callframe cf;
166 int i, regnum;
167
168 /* The following is true for OpenBSD 3.7:
169
170 The pcb contains %r1 (the stack pointer) at the point of the
171 context switch in cpu_switch(). At that point we have a stack
172 frame as described by `struct switchframe', and below that a call
173 frame as described by `struct callframe'. From this information
174 we reconstruct the register state as it would look when we are in
175 cpu_switch(). */
176
177 /* The stack pointer shouldn't be zero. */
178 if (pcb->pcb_sp == 0)
179 return 0;
180
181 read_memory (pcb->pcb_sp, (char *)&sf, sizeof sf);
182 regcache_raw_supply (regcache, tdep->ppc_cr_regnum, &sf.cr);
183 regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 2, &sf.fixreg2);
184 for (i = 0, regnum = tdep->ppc_gp0_regnum + 13; i < 19; i++, regnum++)
185 regcache_raw_supply (regcache, regnum, &sf.fixreg[i]);
186
187 read_memory (sf.sp, (char *)&cf, sizeof cf);
188 regcache_raw_supply (regcache, SP_REGNUM, &cf.sp);
189 regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 30, &cf.r30);
190 regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 31, &cf.r31);
191
192 read_memory (cf.sp, (char *)&cf, sizeof cf);
193 regcache_raw_supply (regcache, PC_REGNUM, &cf.lr);
194 #endif
195
196 return 1;
197 }
198
199
200 /* Provide a prototype to silence -Wmissing-prototypes. */
201 void _initialize_ppc64obsd_nat (void);
202
203 void
_initialize_ppc64obsd_nat(void)204 _initialize_ppc64obsd_nat (void)
205 {
206 struct target_ops *t;
207
208 /* Add in local overrides. */
209 t = inf_ptrace_target ();
210 t->to_fetch_registers = ppc64obsd_fetch_registers;
211 t->to_store_registers = ppc64obsd_store_registers;
212 t->to_pid_to_str = obsd_pid_to_str;
213 t->to_find_new_threads = obsd_find_new_threads;
214 t->to_wait = obsd_wait;
215 add_target (t);
216
217 /* General-purpose registers. */
218 ppc64obsd_reg_offsets.r0_offset = offsetof (struct reg, r_reg);
219 ppc64obsd_reg_offsets.pc_offset = offsetof (struct reg, r_pc);
220 ppc64obsd_reg_offsets.ps_offset = offsetof (struct reg, r_msr);
221 ppc64obsd_reg_offsets.cr_offset = offsetof (struct reg, r_cr);
222 ppc64obsd_reg_offsets.lr_offset = offsetof (struct reg, r_lr);
223 ppc64obsd_reg_offsets.ctr_offset = offsetof (struct reg, r_ctr);
224 ppc64obsd_reg_offsets.xer_offset = offsetof (struct reg, r_xer);
225 ppc64obsd_reg_offsets.mq_offset = -1;
226
227 /* Floating-point registers. */
228 ppc64obsd_reg_offsets.f0_offset = -1;
229 ppc64obsd_reg_offsets.fpscr_offset = -1;
230 #ifdef PT_GETFPREGS
231 ppc64obsd_fpreg_offsets.f0_offset = -1;
232 ppc64obsd_fpreg_offsets.fpscr_offset = -1;
233 #endif
234
235 /* AltiVec registers. */
236 ppc64obsd_reg_offsets.vr0_offset = -1;
237 ppc64obsd_reg_offsets.vscr_offset = -1;
238 ppc64obsd_reg_offsets.vrsave_offset = -1;
239
240 /* Support debugging kernel virtual memory images. */
241 bsd_kvm_add_target (ppc64obsd_supply_pcb);
242 }
243