]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/gdb/gdb/amd64fbsd-nat.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / gdb / gdb / amd64fbsd-nat.c
1 /* Native-dependent code for FreeBSD/amd64.
2
3    Copyright 2003, 2004 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., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.  */
21
22 #include "defs.h"
23 #include "inferior.h"
24 #include "regcache.h"
25
26 #include "gdb_assert.h"
27 #include <signal.h>
28 #include <stddef.h>
29 #include <sys/types.h>
30 #include <sys/ptrace.h>
31 #include <sys/sysctl.h>
32 #include <sys/user.h>
33 #include <machine/reg.h>
34
35 #ifdef HAVE_SYS_PROCFS_H
36 #include <sys/procfs.h>
37 #endif
38
39 #ifndef HAVE_GREGSET_T
40 typedef struct reg gregset_t;
41 #endif
42
43 #ifndef HAVE_FPREGSET_T
44 typedef struct fpreg fpregset_t;
45 #endif
46
47 #include "gregset.h"
48 #include "amd64-tdep.h"
49 #include "amd64-nat.h"
50 \f
51
52 /* Offset to the gregset_t location where REG is stored.  */
53 #define REG_OFFSET(reg) offsetof (gregset_t, reg)
54
55 /* At reg_offset[REGNUM] you'll find the offset to the gregset_t
56    location where the GDB register REGNUM is stored.  Unsupported
57    registers are marked with `-1'.  */
58 static int reg_offset[] =
59 {
60   REG_OFFSET (r_rax),
61   REG_OFFSET (r_rbx),
62   REG_OFFSET (r_rcx),
63   REG_OFFSET (r_rdx),
64   REG_OFFSET (r_rsi),
65   REG_OFFSET (r_rdi),
66   REG_OFFSET (r_rbp),
67   REG_OFFSET (r_rsp),
68   REG_OFFSET (r_r8),
69   REG_OFFSET (r_r9),
70   REG_OFFSET (r_r10),
71   REG_OFFSET (r_r11),
72   REG_OFFSET (r_r12),
73   REG_OFFSET (r_r13),
74   REG_OFFSET (r_r14),
75   REG_OFFSET (r_r15),
76   REG_OFFSET (r_rip),
77   REG_OFFSET (r_rflags),
78   REG_OFFSET (r_cs),
79   REG_OFFSET (r_ss),
80   -1,
81   -1,
82   -1,
83   -1
84 };
85 \f
86
87 /* Mapping between the general-purpose registers in FreeBSD/amd64
88    `struct reg' format and GDB's register cache layout for
89    FreeBSD/i386.
90
91    Note that most FreeBSD/amd64 registers are 64-bit, while the
92    FreeBSD/i386 registers are all 32-bit, but since we're
93    little-endian we get away with that.  */
94
95 /* From <machine/reg.h>.  */
96 static int amd64fbsd32_r_reg_offset[I386_NUM_GREGS] =
97 {
98   14 * 8, 13 * 8,               /* %eax, %ecx */
99   12 * 8, 11 * 8,               /* %edx, %ebx */
100   20 * 8, 10 * 8,               /* %esp, %ebp */
101   9 * 8, 8 * 8,                 /* %esi, %edi */
102   17 * 8, 19 * 8,               /* %eip, %eflags */
103   18 * 8, 21 * 8,               /* %cs, %ss */
104   -1, -1, -1, -1                /* %ds, %es, %fs, %gs */
105 };
106 \f
107
108 /* Transfering the registers between GDB, inferiors and core files.  */
109
110 /* Fill GDB's register array with the general-purpose register values
111    in *GREGSETP.  */
112
113 void
114 supply_gregset (gregset_t *gregsetp)
115 {
116   amd64_supply_native_gregset (current_regcache, gregsetp, -1);
117 }
118
119 /* Fill register REGNUM (if it is a general-purpose register) in
120    *GREGSETPS with the value in GDB's register array.  If REGNUM is -1,
121    do this for all registers.  */
122
123 void
124 fill_gregset (gregset_t *gregsetp, int regnum)
125 {
126   amd64_collect_native_gregset (current_regcache, gregsetp, regnum);
127 }
128
129 /* Fill GDB's register array with the floating-point register values
130    in *FPREGSETP.  */
131
132 void
133 supply_fpregset (fpregset_t *fpregsetp)
134 {
135   amd64_supply_fxsave (current_regcache, -1, fpregsetp);
136 }
137
138 /* Fill register REGNUM (if it is a floating-point register) in
139    *FPREGSETP with the value in GDB's register array.  If REGNUM is -1,
140    do this for all registers.  */
141
142 void
143 fill_fpregset (fpregset_t *fpregsetp, int regnum)
144 {
145   amd64_fill_fxsave ((char *) fpregsetp, regnum);
146 }
147 \f
148
149 /* Provide a prototype to silence -Wmissing-prototypes.  */
150 void _initialize_amd64fbsd_nat (void);
151
152 void
153 _initialize_amd64fbsd_nat (void)
154 {
155   int offset;
156
157   amd64_native_gregset32_reg_offset = amd64fbsd32_r_reg_offset;
158   amd64_native_gregset64_reg_offset = reg_offset;
159
160   /* To support the recognition of signal handlers, i386bsd-tdep.c
161      hardcodes some constants.  Inclusion of this file means that we
162      are compiling a native debugger, which means that we can use the
163      system header files and sysctl(3) to get at the relevant
164      information.  */
165
166 #define SC_REG_OFFSET amd64fbsd_sc_reg_offset
167
168   /* We only check the program counter, stack pointer and frame
169      pointer since these members of `struct sigcontext' are essential
170      for providing backtraces.  */
171
172 #define SC_RIP_OFFSET SC_REG_OFFSET[AMD64_RIP_REGNUM]
173 #define SC_RSP_OFFSET SC_REG_OFFSET[AMD64_RSP_REGNUM]
174 #define SC_RBP_OFFSET SC_REG_OFFSET[AMD64_RBP_REGNUM]
175
176   /* Override the default value for the offset of the program counter
177      in the sigcontext structure.  */
178   offset = offsetof (struct sigcontext, sc_rip);
179
180   if (SC_RIP_OFFSET != offset)
181     {
182       warning ("\
183 offsetof (struct sigcontext, sc_rip) yields %d instead of %d.\n\
184 Please report this to <bug-gdb@gnu.org>.", 
185                offset, SC_RIP_OFFSET);
186     }
187
188   SC_RIP_OFFSET = offset;
189
190   /* Likewise for the stack pointer.  */
191   offset = offsetof (struct sigcontext, sc_rsp);
192
193   if (SC_RSP_OFFSET != offset)
194     {
195       warning ("\
196 offsetof (struct sigcontext, sc_rsp) yields %d instead of %d.\n\
197 Please report this to <bug-gdb@gnu.org>.",
198                offset, SC_RSP_OFFSET);
199     }
200
201   SC_RSP_OFFSET = offset;
202
203   /* And the frame pointer.  */
204   offset = offsetof (struct sigcontext, sc_rbp);
205
206   if (SC_RBP_OFFSET != offset)
207     {
208       warning ("\
209 offsetof (struct sigcontext, sc_rbp) yields %d instead of %d.\n\
210 Please report this to <bug-gdb@gnu.org>.",
211                offset, SC_RBP_OFFSET);
212     }
213
214   SC_RBP_OFFSET = offset;
215
216   /* FreeBSD provides a kern.proc.sigtramp sysctl that we can use to
217      locate the sigtramp.  That way we can still recognize a sigtramp
218      if its location is changed in a new kernel. */
219   {
220     int mib[4];
221     struct kinfo_sigtramp kst;
222     size_t len;
223
224     mib[0] = CTL_KERN;
225     mib[1] = KERN_PROC;
226     mib[2] = KERN_PROC_SIGTRAMP;
227     mib[3] = getpid();
228     len = sizeof (kst);
229     if (sysctl (mib, sizeof(mib) / sizeof(mib[0]), &kst, &len, NULL, 0) == 0)
230       {
231         amd64fbsd_sigtramp_start_addr = kst.ksigtramp_start;
232         amd64fbsd_sigtramp_end_addr = kst.ksigtramp_end;
233       }
234   }
235 }