xref: /dflybsd-src/contrib/gdb-7/gdb/amd64dfly-nat.c (revision 8a286ab35ddbd8fd8ac6b75a2820e262cf43e21c)
169e0f06dSSimon Schubert /* Native-dependent code for DragonFly/amd64.
269e0f06dSSimon Schubert 
3*8a286ab3SJohn Marino    Copyright (C) 2003-2013 Free Software Foundation, Inc.
469e0f06dSSimon Schubert 
569e0f06dSSimon Schubert    This file is part of GDB.
669e0f06dSSimon Schubert 
769e0f06dSSimon Schubert    This program is free software; you can redistribute it and/or modify
869e0f06dSSimon Schubert    it under the terms of the GNU General Public License as published by
969e0f06dSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
1069e0f06dSSimon Schubert    (at your option) any later version.
1169e0f06dSSimon Schubert 
1269e0f06dSSimon Schubert    This program is distributed in the hope that it will be useful,
1369e0f06dSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
1469e0f06dSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1569e0f06dSSimon Schubert    GNU General Public License for more details.
1669e0f06dSSimon Schubert 
1769e0f06dSSimon Schubert    You should have received a copy of the GNU General Public License
1869e0f06dSSimon Schubert    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
1969e0f06dSSimon Schubert 
2069e0f06dSSimon Schubert #include "defs.h"
2169e0f06dSSimon Schubert #include "inferior.h"
2269e0f06dSSimon Schubert #include "regcache.h"
2369e0f06dSSimon Schubert #include "target.h"
24*8a286ab3SJohn Marino #include "gregset.h"
2569e0f06dSSimon Schubert 
2669e0f06dSSimon Schubert #include "gdb_assert.h"
2769e0f06dSSimon Schubert #include <signal.h>
2869e0f06dSSimon Schubert #include <stddef.h>
2969e0f06dSSimon Schubert #include <sys/types.h>
30*8a286ab3SJohn Marino #include <sys/procfs.h>
3169e0f06dSSimon Schubert #include <sys/ptrace.h>
3269e0f06dSSimon Schubert #include <sys/sysctl.h>
3369e0f06dSSimon Schubert #include <machine/reg.h>
3469e0f06dSSimon Schubert 
3569e0f06dSSimon Schubert #include "fbsd-nat.h"
3669e0f06dSSimon Schubert #include "amd64-tdep.h"
3769e0f06dSSimon Schubert #include "amd64-nat.h"
38*8a286ab3SJohn Marino #include "amd64bsd-nat.h"
39*8a286ab3SJohn Marino #include "i386-nat.h"
4069e0f06dSSimon Schubert 
4169e0f06dSSimon Schubert 
4269e0f06dSSimon Schubert /* Offset in `struct reg' where MEMBER is stored.  */
4369e0f06dSSimon Schubert #define REG_OFFSET(member) offsetof (struct reg, member)
4469e0f06dSSimon Schubert 
4569e0f06dSSimon Schubert /* At amd64dfly64_r_reg_offset[REGNUM] you'll find the offset in
4669e0f06dSSimon Schubert    `struct reg' location where the GDB register REGNUM is stored.
4769e0f06dSSimon Schubert    Unsupported registers are marked with `-1'.  */
4869e0f06dSSimon Schubert static int amd64dfly64_r_reg_offset[] =
4969e0f06dSSimon Schubert {
5069e0f06dSSimon Schubert   REG_OFFSET (r_rax),
5169e0f06dSSimon Schubert   REG_OFFSET (r_rbx),
5269e0f06dSSimon Schubert   REG_OFFSET (r_rcx),
5369e0f06dSSimon Schubert   REG_OFFSET (r_rdx),
5469e0f06dSSimon Schubert   REG_OFFSET (r_rsi),
5569e0f06dSSimon Schubert   REG_OFFSET (r_rdi),
5669e0f06dSSimon Schubert   REG_OFFSET (r_rbp),
5769e0f06dSSimon Schubert   REG_OFFSET (r_rsp),
5869e0f06dSSimon Schubert   REG_OFFSET (r_r8),
5969e0f06dSSimon Schubert   REG_OFFSET (r_r9),
6069e0f06dSSimon Schubert   REG_OFFSET (r_r10),
6169e0f06dSSimon Schubert   REG_OFFSET (r_r11),
6269e0f06dSSimon Schubert   REG_OFFSET (r_r12),
6369e0f06dSSimon Schubert   REG_OFFSET (r_r13),
6469e0f06dSSimon Schubert   REG_OFFSET (r_r14),
6569e0f06dSSimon Schubert   REG_OFFSET (r_r15),
6669e0f06dSSimon Schubert   REG_OFFSET (r_rip),
6769e0f06dSSimon Schubert   REG_OFFSET (r_rflags),
6869e0f06dSSimon Schubert   REG_OFFSET (r_cs),
6969e0f06dSSimon Schubert   REG_OFFSET (r_ss),
7069e0f06dSSimon Schubert   -1,
7169e0f06dSSimon Schubert   -1,
7269e0f06dSSimon Schubert   -1,
7369e0f06dSSimon Schubert   -1
7469e0f06dSSimon Schubert };
7569e0f06dSSimon Schubert 
7669e0f06dSSimon Schubert 
7769e0f06dSSimon Schubert /* Mapping between the general-purpose registers in DragonFly/amd64
7869e0f06dSSimon Schubert    `struct reg' format and GDB's register cache layout for
7969e0f06dSSimon Schubert    DragonFly/i386.
8069e0f06dSSimon Schubert 
8169e0f06dSSimon Schubert    Note that most DragonFly/amd64 registers are 64-bit, while the
8269e0f06dSSimon Schubert    DragonFly/i386 registers are all 32-bit, but since we're
8369e0f06dSSimon Schubert    little-endian we get away with that.  */
8469e0f06dSSimon Schubert 
8569e0f06dSSimon Schubert /* From <machine/reg.h>.  */
8669e0f06dSSimon Schubert static int amd64dfly32_r_reg_offset[I386_NUM_GREGS] =
8769e0f06dSSimon Schubert {
8869e0f06dSSimon Schubert   14 * 8, 13 * 8,		/* %eax, %ecx */
8969e0f06dSSimon Schubert   12 * 8, 11 * 8,		/* %edx, %ebx */
9069e0f06dSSimon Schubert   20 * 8, 10 * 8,		/* %esp, %ebp */
9169e0f06dSSimon Schubert   9 * 8, 8 * 8,			/* %esi, %edi */
9269e0f06dSSimon Schubert   17 * 8, 19 * 8,		/* %eip, %eflags */
9369e0f06dSSimon Schubert   18 * 8, 21 * 8,		/* %cs, %ss */
9469e0f06dSSimon Schubert   -1, -1, -1, -1		/* %ds, %es, %fs, %gs */
9569e0f06dSSimon Schubert };
9669e0f06dSSimon Schubert 
9769e0f06dSSimon Schubert 
98*8a286ab3SJohn Marino #ifdef DFLY_PCB_SUPPLY
99*8a286ab3SJohn Marino /* Transfering the registers between GDB, inferiors and core files.  */
100*8a286ab3SJohn Marino 
101*8a286ab3SJohn Marino /* Fill GDB's register array with the general-purpose register values
102*8a286ab3SJohn Marino    in *GREGSETP.  */
103*8a286ab3SJohn Marino 
104*8a286ab3SJohn Marino void
105*8a286ab3SJohn Marino supply_gregset (struct regcache *regcache, const gregset_t *gregsetp)
106*8a286ab3SJohn Marino {
107*8a286ab3SJohn Marino   amd64_supply_native_gregset (regcache, gregsetp, -1);
108*8a286ab3SJohn Marino }
109*8a286ab3SJohn Marino 
110*8a286ab3SJohn Marino /* Fill register REGNUM (if it is a general-purpose register) in
111*8a286ab3SJohn Marino    *GREGSETPS with the value in GDB's register array.  If REGNUM is -1,
112*8a286ab3SJohn Marino    do this for all registers.  */
113*8a286ab3SJohn Marino 
114*8a286ab3SJohn Marino void
115*8a286ab3SJohn Marino fill_gregset (const struct regcache *regcache, gdb_gregset_t *gregsetp, int regnum)
116*8a286ab3SJohn Marino {
117*8a286ab3SJohn Marino   amd64_collect_native_gregset (regcache, gregsetp, regnum);
118*8a286ab3SJohn Marino }
119*8a286ab3SJohn Marino 
120*8a286ab3SJohn Marino /* Fill GDB's register array with the floating-point register values
121*8a286ab3SJohn Marino    in *FPREGSETP.  */
122*8a286ab3SJohn Marino 
123*8a286ab3SJohn Marino void
124*8a286ab3SJohn Marino supply_fpregset (struct regcache *regcache, const fpregset_t *fpregsetp)
125*8a286ab3SJohn Marino {
126*8a286ab3SJohn Marino   amd64_supply_fxsave (regcache, -1, fpregsetp);
127*8a286ab3SJohn Marino }
128*8a286ab3SJohn Marino 
129*8a286ab3SJohn Marino /* Fill register REGNUM (if it is a floating-point register) in
130*8a286ab3SJohn Marino    *FPREGSETP with the value in GDB's register array.  If REGNUM is -1,
131*8a286ab3SJohn Marino    do this for all registers.  */
132*8a286ab3SJohn Marino 
133*8a286ab3SJohn Marino void
134*8a286ab3SJohn Marino fill_fpregset (const struct regcache *regcache, gdb_fpregset_t *fpregsetp, int regnum)
135*8a286ab3SJohn Marino {
136*8a286ab3SJohn Marino   amd64_collect_fxsave (regcache, regnum, fpregsetp);
137*8a286ab3SJohn Marino }
138*8a286ab3SJohn Marino 
139*8a286ab3SJohn Marino /* Support for debugging kernel virtual memory images.  */
140*8a286ab3SJohn Marino 
141*8a286ab3SJohn Marino #include <sys/types.h>
142*8a286ab3SJohn Marino #include <machine/pcb.h>
143*8a286ab3SJohn Marino #include <osreldate.h>
144*8a286ab3SJohn Marino 
145*8a286ab3SJohn Marino #include "bsd-kvm.h"
146*8a286ab3SJohn Marino 
147*8a286ab3SJohn Marino static int
148*8a286ab3SJohn Marino amd64dfly_supply_pcb (struct regcache *regcache, struct pcb *pcb)
149*8a286ab3SJohn Marino {
150*8a286ab3SJohn Marino   /* The following is true for FreeBSD 5.2:
151*8a286ab3SJohn Marino 
152*8a286ab3SJohn Marino      The pcb contains %rip, %rbx, %rsp, %rbp, %r12, %r13, %r14, %r15,
153*8a286ab3SJohn Marino      %ds, %es, %fs and %gs.  This accounts for all callee-saved
154*8a286ab3SJohn Marino      registers specified by the psABI and then some.  Here %esp
155*8a286ab3SJohn Marino      contains the stack pointer at the point just after the call to
156*8a286ab3SJohn Marino      cpu_switch().  From this information we reconstruct the register
157*8a286ab3SJohn Marino      state as it would like when we just returned from cpu_switch().  */
158*8a286ab3SJohn Marino 
159*8a286ab3SJohn Marino   /* The stack pointer shouldn't be zero.  */
160*8a286ab3SJohn Marino   if (pcb->pcb_rsp == 0)
161*8a286ab3SJohn Marino     return 0;
162*8a286ab3SJohn Marino 
163*8a286ab3SJohn Marino   pcb->pcb_rsp += 8;
164*8a286ab3SJohn Marino   regcache_raw_supply (regcache, AMD64_RIP_REGNUM, &pcb->pcb_rip);
165*8a286ab3SJohn Marino   regcache_raw_supply (regcache, AMD64_RBX_REGNUM, &pcb->pcb_rbx);
166*8a286ab3SJohn Marino   regcache_raw_supply (regcache, AMD64_RSP_REGNUM, &pcb->pcb_rsp);
167*8a286ab3SJohn Marino   regcache_raw_supply (regcache, AMD64_RBP_REGNUM, &pcb->pcb_rbp);
168*8a286ab3SJohn Marino   regcache_raw_supply (regcache, 12, &pcb->pcb_r12);
169*8a286ab3SJohn Marino   regcache_raw_supply (regcache, 13, &pcb->pcb_r13);
170*8a286ab3SJohn Marino   regcache_raw_supply (regcache, 14, &pcb->pcb_r14);
171*8a286ab3SJohn Marino   regcache_raw_supply (regcache, 15, &pcb->pcb_r15);
172*8a286ab3SJohn Marino #if (__FreeBSD_version < 800075) && (__FreeBSD_kernel_version < 800075)
173*8a286ab3SJohn Marino   /* struct pcb provides the pcb_ds/pcb_es/pcb_fs/pcb_gs fields only
174*8a286ab3SJohn Marino      up until __FreeBSD_version 800074: The removal of these fields
175*8a286ab3SJohn Marino      occurred on 2009-04-01 while the __FreeBSD_version number was
176*8a286ab3SJohn Marino      bumped to 800075 on 2009-04-06.  So 800075 is the closest version
177*8a286ab3SJohn Marino      number where we should not try to access these fields.  */
178*8a286ab3SJohn Marino   regcache_raw_supply (regcache, AMD64_DS_REGNUM, &pcb->pcb_ds);
179*8a286ab3SJohn Marino   regcache_raw_supply (regcache, AMD64_ES_REGNUM, &pcb->pcb_es);
180*8a286ab3SJohn Marino   regcache_raw_supply (regcache, AMD64_FS_REGNUM, &pcb->pcb_fs);
181*8a286ab3SJohn Marino   regcache_raw_supply (regcache, AMD64_GS_REGNUM, &pcb->pcb_gs);
182*8a286ab3SJohn Marino #endif
183*8a286ab3SJohn Marino 
184*8a286ab3SJohn Marino   return 1;
185*8a286ab3SJohn Marino }
186*8a286ab3SJohn Marino #endif /* DFLY_PCB_SUPPLY */
187*8a286ab3SJohn Marino 
188*8a286ab3SJohn Marino 
189*8a286ab3SJohn Marino static void (*super_mourn_inferior) (struct target_ops *ops);
190*8a286ab3SJohn Marino 
191*8a286ab3SJohn Marino static void
192*8a286ab3SJohn Marino amd64dfly_mourn_inferior (struct target_ops *ops)
193*8a286ab3SJohn Marino {
194*8a286ab3SJohn Marino #ifdef HAVE_PT_GETDBREGS
195*8a286ab3SJohn Marino   i386_cleanup_dregs ();
196*8a286ab3SJohn Marino #endif
197*8a286ab3SJohn Marino   super_mourn_inferior (ops);
198*8a286ab3SJohn Marino }
199*8a286ab3SJohn Marino 
20069e0f06dSSimon Schubert /* Provide a prototype to silence -Wmissing-prototypes.  */
20169e0f06dSSimon Schubert void _initialize_amd64dfly_nat (void);
20269e0f06dSSimon Schubert 
20369e0f06dSSimon Schubert void
20469e0f06dSSimon Schubert _initialize_amd64dfly_nat (void)
20569e0f06dSSimon Schubert {
20669e0f06dSSimon Schubert   struct target_ops *t;
20769e0f06dSSimon Schubert   int offset;
20869e0f06dSSimon Schubert 
20969e0f06dSSimon Schubert   amd64_native_gregset32_reg_offset = amd64dfly32_r_reg_offset;
21069e0f06dSSimon Schubert   amd64_native_gregset64_reg_offset = amd64dfly64_r_reg_offset;
21169e0f06dSSimon Schubert 
21269e0f06dSSimon Schubert   /* Add some extra features to the common *BSD/i386 target.  */
21369e0f06dSSimon Schubert   t = amd64bsd_target ();
214*8a286ab3SJohn Marino 
215*8a286ab3SJohn Marino #ifdef HAVE_PT_GETDBREGS
216*8a286ab3SJohn Marino 
217*8a286ab3SJohn Marino   i386_use_watchpoints (t);
218*8a286ab3SJohn Marino 
219*8a286ab3SJohn Marino   i386_dr_low.set_control = amd64bsd_dr_set_control;
220*8a286ab3SJohn Marino   i386_dr_low.set_addr = amd64bsd_dr_set_addr;
221*8a286ab3SJohn Marino   i386_dr_low.get_addr = amd64bsd_dr_get_addr;
222*8a286ab3SJohn Marino   i386_dr_low.get_status = amd64bsd_dr_get_status;
223*8a286ab3SJohn Marino   i386_dr_low.get_control = amd64bsd_dr_get_control;
224*8a286ab3SJohn Marino   i386_set_debug_register_length (8);
225*8a286ab3SJohn Marino 
226*8a286ab3SJohn Marino #endif /* HAVE_PT_GETDBREGS */
227*8a286ab3SJohn Marino 
228*8a286ab3SJohn Marino   super_mourn_inferior = t->to_mourn_inferior;
229*8a286ab3SJohn Marino   t->to_mourn_inferior = amd64dfly_mourn_inferior;
230*8a286ab3SJohn Marino 
23169e0f06dSSimon Schubert   t->to_pid_to_exec_file = fbsd_pid_to_exec_file;
23269e0f06dSSimon Schubert   t->to_find_memory_regions = fbsd_find_memory_regions;
23369e0f06dSSimon Schubert   t->to_make_corefile_notes = fbsd_make_corefile_notes;
23469e0f06dSSimon Schubert   add_target (t);
23569e0f06dSSimon Schubert 
236*8a286ab3SJohn Marino #ifdef DFLY_PCB_SUPPLY
237*8a286ab3SJohn Marino   /* Support debugging kernel virtual memory images.  */
238*8a286ab3SJohn Marino   bsd_kvm_add_target (amd64dfly_supply_pcb);
239*8a286ab3SJohn Marino #endif
240*8a286ab3SJohn Marino 
24169e0f06dSSimon Schubert   /* To support the recognition of signal handlers, i386bsd-tdep.c
24269e0f06dSSimon Schubert      hardcodes some constants.  Inclusion of this file means that we
24369e0f06dSSimon Schubert      are compiling a native debugger, which means that we can use the
24469e0f06dSSimon Schubert      system header files and sysctl(3) to get at the relevant
24569e0f06dSSimon Schubert      information.  */
24669e0f06dSSimon Schubert 
24769e0f06dSSimon Schubert #define SC_REG_OFFSET amd64dfly_sc_reg_offset
24869e0f06dSSimon Schubert 
24969e0f06dSSimon Schubert   /* We only check the program counter, stack pointer and frame
25069e0f06dSSimon Schubert      pointer since these members of `struct sigcontext' are essential
25169e0f06dSSimon Schubert      for providing backtraces.  */
25269e0f06dSSimon Schubert 
25369e0f06dSSimon Schubert #define SC_RIP_OFFSET SC_REG_OFFSET[AMD64_RIP_REGNUM]
25469e0f06dSSimon Schubert #define SC_RSP_OFFSET SC_REG_OFFSET[AMD64_RSP_REGNUM]
25569e0f06dSSimon Schubert #define SC_RBP_OFFSET SC_REG_OFFSET[AMD64_RBP_REGNUM]
25669e0f06dSSimon Schubert 
25769e0f06dSSimon Schubert   /* Override the default value for the offset of the program counter
25869e0f06dSSimon Schubert      in the sigcontext structure.  */
25969e0f06dSSimon Schubert   offset = offsetof (struct sigcontext, sc_rip);
26069e0f06dSSimon Schubert 
26169e0f06dSSimon Schubert   if (SC_RIP_OFFSET != offset)
26269e0f06dSSimon Schubert     {
26369e0f06dSSimon Schubert       warning (_("\
26469e0f06dSSimon Schubert offsetof (struct sigcontext, sc_rip) yields %d instead of %d.\n\
26569e0f06dSSimon Schubert Please report this to <bug-gdb@gnu.org>."),
26669e0f06dSSimon Schubert 	       offset, SC_RIP_OFFSET);
26769e0f06dSSimon Schubert     }
26869e0f06dSSimon Schubert 
26969e0f06dSSimon Schubert   SC_RIP_OFFSET = offset;
27069e0f06dSSimon Schubert 
27169e0f06dSSimon Schubert   /* Likewise for the stack pointer.  */
27269e0f06dSSimon Schubert   offset = offsetof (struct sigcontext, sc_rsp);
27369e0f06dSSimon Schubert 
27469e0f06dSSimon Schubert   if (SC_RSP_OFFSET != offset)
27569e0f06dSSimon Schubert     {
27669e0f06dSSimon Schubert       warning (_("\
27769e0f06dSSimon Schubert offsetof (struct sigcontext, sc_rsp) yields %d instead of %d.\n\
27869e0f06dSSimon Schubert Please report this to <bug-gdb@gnu.org>."),
27969e0f06dSSimon Schubert 	       offset, SC_RSP_OFFSET);
28069e0f06dSSimon Schubert     }
28169e0f06dSSimon Schubert 
28269e0f06dSSimon Schubert   SC_RSP_OFFSET = offset;
28369e0f06dSSimon Schubert 
28469e0f06dSSimon Schubert   /* And the frame pointer.  */
28569e0f06dSSimon Schubert   offset = offsetof (struct sigcontext, sc_rbp);
28669e0f06dSSimon Schubert 
28769e0f06dSSimon Schubert   if (SC_RBP_OFFSET != offset)
28869e0f06dSSimon Schubert     {
28969e0f06dSSimon Schubert       warning (_("\
29069e0f06dSSimon Schubert offsetof (struct sigcontext, sc_rbp) yields %d instead of %d.\n\
29169e0f06dSSimon Schubert Please report this to <bug-gdb@gnu.org>."),
29269e0f06dSSimon Schubert 	       offset, SC_RBP_OFFSET);
29369e0f06dSSimon Schubert     }
29469e0f06dSSimon Schubert 
29569e0f06dSSimon Schubert   SC_RBP_OFFSET = offset;
29669e0f06dSSimon Schubert 
29769e0f06dSSimon Schubert   /* DragonFly provides a kern.ps_strings sysctl that we can use to
29869e0f06dSSimon Schubert      locate the sigtramp.  That way we can still recognize a sigtramp
29969e0f06dSSimon Schubert      if its location is changed in a new kernel.  Of course this is
30069e0f06dSSimon Schubert      still based on the assumption that the sigtramp is placed
30169e0f06dSSimon Schubert      directly under the location where the program arguments and
30269e0f06dSSimon Schubert      environment can be found.  */
30369e0f06dSSimon Schubert   {
30469e0f06dSSimon Schubert     int mib[2];
30569e0f06dSSimon Schubert     long ps_strings;
30669e0f06dSSimon Schubert     size_t len;
30769e0f06dSSimon Schubert 
30869e0f06dSSimon Schubert     mib[0] = CTL_KERN;
30969e0f06dSSimon Schubert     mib[1] = KERN_PS_STRINGS;
31069e0f06dSSimon Schubert     len = sizeof (ps_strings);
31169e0f06dSSimon Schubert     if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0)
31269e0f06dSSimon Schubert       {
31369e0f06dSSimon Schubert 	amd64dfly_sigtramp_start_addr = ps_strings - 32;
31469e0f06dSSimon Schubert 	amd64dfly_sigtramp_end_addr = ps_strings;
31569e0f06dSSimon Schubert       }
31669e0f06dSSimon Schubert   }
31769e0f06dSSimon Schubert }
318