15796c8dcSSimon Schubert /* Native-dependent code for AMD64 BSD's.
25796c8dcSSimon Schubert
3*ef5ccd6cSJohn Marino Copyright (C) 2003-2013 Free Software Foundation, Inc.
45796c8dcSSimon Schubert
55796c8dcSSimon Schubert This file is part of GDB.
65796c8dcSSimon Schubert
75796c8dcSSimon Schubert This program is free software; you can redistribute it and/or modify
85796c8dcSSimon Schubert it under the terms of the GNU General Public License as published by
95796c8dcSSimon Schubert the Free Software Foundation; either version 3 of the License, or
105796c8dcSSimon Schubert (at your option) any later version.
115796c8dcSSimon Schubert
125796c8dcSSimon Schubert This program is distributed in the hope that it will be useful,
135796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of
145796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
155796c8dcSSimon Schubert GNU General Public License for more details.
165796c8dcSSimon Schubert
175796c8dcSSimon Schubert You should have received a copy of the GNU General Public License
185796c8dcSSimon Schubert along with this program. If not, see <http://www.gnu.org/licenses/>. */
195796c8dcSSimon Schubert
205796c8dcSSimon Schubert #include "defs.h"
215796c8dcSSimon Schubert #include "inferior.h"
225796c8dcSSimon Schubert #include "regcache.h"
235796c8dcSSimon Schubert #include "target.h"
245796c8dcSSimon Schubert
255796c8dcSSimon Schubert /* We include <signal.h> to make sure `struct fxsave64' is defined on
265796c8dcSSimon Schubert NetBSD, since NetBSD's <machine/reg.h> needs it. */
275796c8dcSSimon Schubert #include "gdb_assert.h"
285796c8dcSSimon Schubert #include <signal.h>
295796c8dcSSimon Schubert #include <sys/types.h>
305796c8dcSSimon Schubert #include <sys/ptrace.h>
315796c8dcSSimon Schubert #include <machine/reg.h>
325796c8dcSSimon Schubert
335796c8dcSSimon Schubert #include "amd64-tdep.h"
345796c8dcSSimon Schubert #include "amd64-nat.h"
35*ef5ccd6cSJohn Marino #include "amd64bsd-nat.h"
365796c8dcSSimon Schubert #include "inf-ptrace.h"
375796c8dcSSimon Schubert
385796c8dcSSimon Schubert
395796c8dcSSimon Schubert /* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
405796c8dcSSimon Schubert for all registers (including the floating-point registers). */
415796c8dcSSimon Schubert
425796c8dcSSimon Schubert static void
amd64bsd_fetch_inferior_registers(struct target_ops * ops,struct regcache * regcache,int regnum)435796c8dcSSimon Schubert amd64bsd_fetch_inferior_registers (struct target_ops *ops,
445796c8dcSSimon Schubert struct regcache *regcache, int regnum)
455796c8dcSSimon Schubert {
465796c8dcSSimon Schubert struct gdbarch *gdbarch = get_regcache_arch (regcache);
475796c8dcSSimon Schubert
485796c8dcSSimon Schubert if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum))
495796c8dcSSimon Schubert {
505796c8dcSSimon Schubert struct reg regs;
515796c8dcSSimon Schubert
525796c8dcSSimon Schubert if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
535796c8dcSSimon Schubert (PTRACE_TYPE_ARG3) ®s, 0) == -1)
545796c8dcSSimon Schubert perror_with_name (_("Couldn't get registers"));
555796c8dcSSimon Schubert
565796c8dcSSimon Schubert amd64_supply_native_gregset (regcache, ®s, -1);
575796c8dcSSimon Schubert if (regnum != -1)
585796c8dcSSimon Schubert return;
595796c8dcSSimon Schubert }
605796c8dcSSimon Schubert
615796c8dcSSimon Schubert if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum))
625796c8dcSSimon Schubert {
635796c8dcSSimon Schubert struct fpreg fpregs;
645796c8dcSSimon Schubert
655796c8dcSSimon Schubert if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
665796c8dcSSimon Schubert (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
675796c8dcSSimon Schubert perror_with_name (_("Couldn't get floating point status"));
685796c8dcSSimon Schubert
695796c8dcSSimon Schubert amd64_supply_fxsave (regcache, -1, &fpregs);
705796c8dcSSimon Schubert }
715796c8dcSSimon Schubert }
725796c8dcSSimon Schubert
735796c8dcSSimon Schubert /* Store register REGNUM back into the inferior. If REGNUM is -1, do
745796c8dcSSimon Schubert this for all registers (including the floating-point registers). */
755796c8dcSSimon Schubert
765796c8dcSSimon Schubert static void
amd64bsd_store_inferior_registers(struct target_ops * ops,struct regcache * regcache,int regnum)775796c8dcSSimon Schubert amd64bsd_store_inferior_registers (struct target_ops *ops,
785796c8dcSSimon Schubert struct regcache *regcache, int regnum)
795796c8dcSSimon Schubert {
805796c8dcSSimon Schubert struct gdbarch *gdbarch = get_regcache_arch (regcache);
815796c8dcSSimon Schubert
825796c8dcSSimon Schubert if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum))
835796c8dcSSimon Schubert {
845796c8dcSSimon Schubert struct reg regs;
855796c8dcSSimon Schubert
865796c8dcSSimon Schubert if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
875796c8dcSSimon Schubert (PTRACE_TYPE_ARG3) ®s, 0) == -1)
885796c8dcSSimon Schubert perror_with_name (_("Couldn't get registers"));
895796c8dcSSimon Schubert
905796c8dcSSimon Schubert amd64_collect_native_gregset (regcache, ®s, regnum);
915796c8dcSSimon Schubert
925796c8dcSSimon Schubert if (ptrace (PT_SETREGS, PIDGET (inferior_ptid),
935796c8dcSSimon Schubert (PTRACE_TYPE_ARG3) ®s, 0) == -1)
945796c8dcSSimon Schubert perror_with_name (_("Couldn't write registers"));
955796c8dcSSimon Schubert
965796c8dcSSimon Schubert if (regnum != -1)
975796c8dcSSimon Schubert return;
985796c8dcSSimon Schubert }
995796c8dcSSimon Schubert
1005796c8dcSSimon Schubert if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum))
1015796c8dcSSimon Schubert {
1025796c8dcSSimon Schubert struct fpreg fpregs;
1035796c8dcSSimon Schubert
1045796c8dcSSimon Schubert if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
1055796c8dcSSimon Schubert (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
1065796c8dcSSimon Schubert perror_with_name (_("Couldn't get floating point status"));
1075796c8dcSSimon Schubert
1085796c8dcSSimon Schubert amd64_collect_fxsave (regcache, regnum, &fpregs);
1095796c8dcSSimon Schubert
1105796c8dcSSimon Schubert if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
1115796c8dcSSimon Schubert (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
1125796c8dcSSimon Schubert perror_with_name (_("Couldn't write floating point status"));
1135796c8dcSSimon Schubert }
1145796c8dcSSimon Schubert }
1155796c8dcSSimon Schubert
1165796c8dcSSimon Schubert /* Create a prototype *BSD/amd64 target. The client can override it
1175796c8dcSSimon Schubert with local methods. */
1185796c8dcSSimon Schubert
1195796c8dcSSimon Schubert struct target_ops *
amd64bsd_target(void)1205796c8dcSSimon Schubert amd64bsd_target (void)
1215796c8dcSSimon Schubert {
1225796c8dcSSimon Schubert struct target_ops *t;
1235796c8dcSSimon Schubert
1245796c8dcSSimon Schubert t = inf_ptrace_target ();
1255796c8dcSSimon Schubert t->to_fetch_registers = amd64bsd_fetch_inferior_registers;
1265796c8dcSSimon Schubert t->to_store_registers = amd64bsd_store_inferior_registers;
1275796c8dcSSimon Schubert return t;
1285796c8dcSSimon Schubert }
129*ef5ccd6cSJohn Marino
130*ef5ccd6cSJohn Marino
131*ef5ccd6cSJohn Marino /* Support for debug registers. */
132*ef5ccd6cSJohn Marino
133*ef5ccd6cSJohn Marino #ifdef HAVE_PT_GETDBREGS
134*ef5ccd6cSJohn Marino
135*ef5ccd6cSJohn Marino static unsigned long
amd64bsd_dr_get(ptid_t ptid,int regnum)136*ef5ccd6cSJohn Marino amd64bsd_dr_get (ptid_t ptid, int regnum)
137*ef5ccd6cSJohn Marino {
138*ef5ccd6cSJohn Marino struct dbreg dbregs;
139*ef5ccd6cSJohn Marino
140*ef5ccd6cSJohn Marino if (ptrace (PT_GETDBREGS, PIDGET (inferior_ptid),
141*ef5ccd6cSJohn Marino (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
142*ef5ccd6cSJohn Marino perror_with_name (_("Couldn't read debug registers"));
143*ef5ccd6cSJohn Marino
144*ef5ccd6cSJohn Marino return DBREG_DRX ((&dbregs), regnum);
145*ef5ccd6cSJohn Marino }
146*ef5ccd6cSJohn Marino
147*ef5ccd6cSJohn Marino static void
amd64bsd_dr_set(int regnum,unsigned long value)148*ef5ccd6cSJohn Marino amd64bsd_dr_set (int regnum, unsigned long value)
149*ef5ccd6cSJohn Marino {
150*ef5ccd6cSJohn Marino struct dbreg dbregs;
151*ef5ccd6cSJohn Marino
152*ef5ccd6cSJohn Marino if (ptrace (PT_GETDBREGS, PIDGET (inferior_ptid),
153*ef5ccd6cSJohn Marino (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
154*ef5ccd6cSJohn Marino perror_with_name (_("Couldn't get debug registers"));
155*ef5ccd6cSJohn Marino
156*ef5ccd6cSJohn Marino /* For some mysterious reason, some of the reserved bits in the
157*ef5ccd6cSJohn Marino debug control register get set. Mask these off, otherwise the
158*ef5ccd6cSJohn Marino ptrace call below will fail. */
159*ef5ccd6cSJohn Marino DBREG_DRX ((&dbregs), 7) &= ~(0xffffffff0000fc00);
160*ef5ccd6cSJohn Marino
161*ef5ccd6cSJohn Marino DBREG_DRX ((&dbregs), regnum) = value;
162*ef5ccd6cSJohn Marino
163*ef5ccd6cSJohn Marino if (ptrace (PT_SETDBREGS, PIDGET (inferior_ptid),
164*ef5ccd6cSJohn Marino (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
165*ef5ccd6cSJohn Marino perror_with_name (_("Couldn't write debug registers"));
166*ef5ccd6cSJohn Marino }
167*ef5ccd6cSJohn Marino
168*ef5ccd6cSJohn Marino void
amd64bsd_dr_set_control(unsigned long control)169*ef5ccd6cSJohn Marino amd64bsd_dr_set_control (unsigned long control)
170*ef5ccd6cSJohn Marino {
171*ef5ccd6cSJohn Marino amd64bsd_dr_set (7, control);
172*ef5ccd6cSJohn Marino }
173*ef5ccd6cSJohn Marino
174*ef5ccd6cSJohn Marino void
amd64bsd_dr_set_addr(int regnum,CORE_ADDR addr)175*ef5ccd6cSJohn Marino amd64bsd_dr_set_addr (int regnum, CORE_ADDR addr)
176*ef5ccd6cSJohn Marino {
177*ef5ccd6cSJohn Marino gdb_assert (regnum >= 0 && regnum <= 4);
178*ef5ccd6cSJohn Marino
179*ef5ccd6cSJohn Marino amd64bsd_dr_set (regnum, addr);
180*ef5ccd6cSJohn Marino }
181*ef5ccd6cSJohn Marino
182*ef5ccd6cSJohn Marino CORE_ADDR
amd64bsd_dr_get_addr(int regnum)183*ef5ccd6cSJohn Marino amd64bsd_dr_get_addr (int regnum)
184*ef5ccd6cSJohn Marino {
185*ef5ccd6cSJohn Marino return amd64bsd_dr_get (inferior_ptid, regnum);
186*ef5ccd6cSJohn Marino }
187*ef5ccd6cSJohn Marino
188*ef5ccd6cSJohn Marino unsigned long
amd64bsd_dr_get_status(void)189*ef5ccd6cSJohn Marino amd64bsd_dr_get_status (void)
190*ef5ccd6cSJohn Marino {
191*ef5ccd6cSJohn Marino return amd64bsd_dr_get (inferior_ptid, 6);
192*ef5ccd6cSJohn Marino }
193*ef5ccd6cSJohn Marino
194*ef5ccd6cSJohn Marino unsigned long
amd64bsd_dr_get_control(void)195*ef5ccd6cSJohn Marino amd64bsd_dr_get_control (void)
196*ef5ccd6cSJohn Marino {
197*ef5ccd6cSJohn Marino return amd64bsd_dr_get (inferior_ptid, 7);
198*ef5ccd6cSJohn Marino }
199*ef5ccd6cSJohn Marino
200*ef5ccd6cSJohn Marino #endif /* PT_GETDBREGS */
201