xref: /dragonfly/contrib/gdb-7/gdb/amd64bsd-nat.c (revision ef5ccd6c)
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) &regs, 0) == -1)
545796c8dcSSimon Schubert 	perror_with_name (_("Couldn't get registers"));
555796c8dcSSimon Schubert 
565796c8dcSSimon Schubert       amd64_supply_native_gregset (regcache, &regs, -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) &regs, 0) == -1)
885796c8dcSSimon Schubert         perror_with_name (_("Couldn't get registers"));
895796c8dcSSimon Schubert 
905796c8dcSSimon Schubert       amd64_collect_native_gregset (regcache, &regs, regnum);
915796c8dcSSimon Schubert 
925796c8dcSSimon Schubert       if (ptrace (PT_SETREGS, PIDGET (inferior_ptid),
935796c8dcSSimon Schubert 	          (PTRACE_TYPE_ARG3) &regs, 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