OSDN Git Service

* i386bsd-nat.c: s/regno/regnum/g.
[pf3gnuchains/pf3gnuchains3x.git] / gdb / i386bsd-nat.c
1 /* Native-dependent code for modern i386 BSD's.
2
3    Copyright 2000, 2001, 2002, 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 <machine/reg.h>
32 #include <machine/frame.h>
33
34 #ifdef HAVE_SYS_PROCFS_H
35 #include <sys/procfs.h>
36 #endif
37
38 #ifndef HAVE_GREGSET_T
39 typedef struct reg gregset_t;
40 #endif
41
42 #ifndef HAVE_FPREGSET_T
43 typedef struct fpreg fpregset_t;
44 #endif
45
46 #include "gregset.h"
47 #include "i386-tdep.h"
48 \f
49
50 /* In older BSD versions we cannot get at some of the segment
51    registers.  FreeBSD for example didn't support the %fs and %gs
52    registers until the 3.0 release.  We have autoconf checks for their
53    presence, and deal gracefully with their absence.  */
54
55 /* Registers we shouldn't try to fetch.  */
56 #undef CANNOT_FETCH_REGISTER
57 #define CANNOT_FETCH_REGISTER(regnum) cannot_fetch_register (regnum)
58
59 /* Registers we shouldn't try to store.  */
60 #undef CANNOT_STORE_REGISTER
61 #define CANNOT_STORE_REGISTER(regnum) cannot_fetch_register (regnum)
62
63 /* Offset to the gregset_t location where REG is stored.  */
64 #define REG_OFFSET(reg) offsetof (gregset_t, reg)
65
66 /* At reg_offset[REGNUM] you'll find the offset to the gregset_t
67    location where the GDB register REGNUM is stored.  Unsupported
68    registers are marked with `-1'.  */
69 static int reg_offset[] =
70 {
71   REG_OFFSET (r_eax),
72   REG_OFFSET (r_ecx),
73   REG_OFFSET (r_edx),
74   REG_OFFSET (r_ebx),
75   REG_OFFSET (r_esp),
76   REG_OFFSET (r_ebp),
77   REG_OFFSET (r_esi),
78   REG_OFFSET (r_edi),
79   REG_OFFSET (r_eip),
80   REG_OFFSET (r_eflags),
81   REG_OFFSET (r_cs),
82   REG_OFFSET (r_ss),
83   REG_OFFSET (r_ds),
84   REG_OFFSET (r_es),
85 #ifdef HAVE_STRUCT_REG_R_FS
86   REG_OFFSET (r_fs),
87 #else
88   -1,
89 #endif
90 #ifdef HAVE_STRUCT_REG_R_GS
91   REG_OFFSET (r_gs)
92 #else
93   -1
94 #endif
95 };
96
97 #define REG_ADDR(regset, regnum) ((char *) (regset) + reg_offset[regnum])
98
99 /* Macro to determine if a register is fetched with PT_GETREGS.  */
100 #define GETREGS_SUPPLIES(regnum) \
101   ((0 <= (regnum) && (regnum) <= 15))
102
103 #ifdef HAVE_PT_GETXMMREGS
104 /* Set to 1 if the kernel supports PT_GETXMMREGS.  Initialized to -1
105    so that we try PT_GETXMMREGS the first time around.  */
106 static int have_ptrace_xmmregs = -1;
107 #endif
108
109 /* Return nonzero if we shouldn't try to fetch register REGNUM.  */
110
111 static int
112 cannot_fetch_register (int regnum)
113 {
114   return (reg_offset[regnum] == -1);
115 }
116 \f
117
118 /* Transfering the registers between GDB, inferiors and core files.  */
119
120 /* Fill GDB's register array with the general-purpose register values
121    in *GREGSETP.  */
122
123 void
124 supply_gregset (gregset_t *gregsetp)
125 {
126   int i;
127
128   for (i = 0; i < I386_NUM_GREGS; i++)
129     {
130       if (CANNOT_FETCH_REGISTER (i))
131         supply_register (i, NULL);
132       else
133         supply_register (i, REG_ADDR (gregsetp, i));
134     }
135 }
136
137 /* Fill register REGNUM (if it is a general-purpose register) in
138    *GREGSETPS with the value in GDB's register array.  If REGNUM is -1,
139    do this for all registers.  */
140
141 void
142 fill_gregset (gregset_t *gregsetp, int regnum)
143 {
144   int i;
145
146   for (i = 0; i < I386_NUM_GREGS; i++)
147     if ((regnum == -1 || regnum == i) && ! CANNOT_STORE_REGISTER (i))
148       regcache_collect (i, REG_ADDR (gregsetp, i));
149 }
150
151 #include "i387-tdep.h"
152
153 /* Fill GDB's register array with the floating-point register values
154    in *FPREGSETP.  */
155
156 void
157 supply_fpregset (fpregset_t *fpregsetp)
158 {
159   i387_supply_fsave (current_regcache, -1, fpregsetp);
160 }
161
162 /* Fill register REGNUM (if it is a floating-point register) in
163    *FPREGSETP with the value in GDB's register array.  If REGNUM is
164    -1, do this for all registers.  */
165
166 void
167 fill_fpregset (fpregset_t *fpregsetp, int regnum)
168 {
169   i387_collect_fsave (current_regcache, regnum, fpregsetp);
170 }
171
172 /* Fetch register REGNUM from the inferior.  If REGNUM is -1, do this
173    for all registers (including the floating point registers).  */
174
175 void
176 fetch_inferior_registers (int regnum)
177 {
178   if (regnum == -1 || GETREGS_SUPPLIES (regnum))
179     {
180       gregset_t gregs;
181
182       if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
183                   (PTRACE_ARG3_TYPE) &gregs, 0) == -1)
184         perror_with_name ("Couldn't get registers");
185
186       supply_gregset (&gregs);
187       if (regnum != -1)
188         return;
189     }
190
191   if (regnum == -1 || regnum >= I386_ST0_REGNUM)
192     {
193       fpregset_t fpregs;
194 #ifdef HAVE_PT_GETXMMREGS
195       char xmmregs[512];
196
197       if (have_ptrace_xmmregs != 0
198           && ptrace(PT_GETXMMREGS, PIDGET (inferior_ptid),
199                     (PTRACE_ARG3_TYPE) xmmregs, 0) == 0)
200         {
201           have_ptrace_xmmregs = 1;
202           i387_supply_fxsave (current_regcache, -1, xmmregs);
203         }
204       else
205         {
206           if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
207                       (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
208             perror_with_name ("Couldn't get floating point status");
209
210           i387_supply_fsave (current_regcache, -1, &fpregs);
211         }
212 #else
213       if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
214                   (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
215         perror_with_name ("Couldn't get floating point status");
216
217       i387_supply_fsave (current_regcache, -1, &fpregs);
218 #endif
219     }
220 }
221
222 /* Store register REGNUM back into the inferior.  If REGNUM is -1, do
223    this for all registers (including the floating point registers).  */
224
225 void
226 store_inferior_registers (int regnum)
227 {
228   if (regnum == -1 || GETREGS_SUPPLIES (regnum))
229     {
230       gregset_t gregs;
231
232       if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
233                   (PTRACE_ARG3_TYPE) &gregs, 0) == -1)
234         perror_with_name ("Couldn't get registers");
235
236       fill_gregset (&gregs, regnum);
237
238       if (ptrace (PT_SETREGS, PIDGET (inferior_ptid),
239                   (PTRACE_ARG3_TYPE) &gregs, 0) == -1)
240         perror_with_name ("Couldn't write registers");
241
242       if (regnum != -1)
243         return;
244     }
245
246   if (regnum == -1 || regnum >= I386_ST0_REGNUM)
247     {
248       fpregset_t fpregs;
249 #ifdef HAVE_PT_GETXMMREGS
250       char xmmregs[512];
251
252       if (have_ptrace_xmmregs != 0
253           && ptrace(PT_GETXMMREGS, PIDGET (inferior_ptid),
254                     (PTRACE_ARG3_TYPE) xmmregs, 0) == 0)
255         {
256           have_ptrace_xmmregs = 1;
257
258           i387_collect_fxsave (current_regcache, regnum, xmmregs);
259
260           if (ptrace (PT_SETXMMREGS, PIDGET (inferior_ptid),
261                       (PTRACE_ARG3_TYPE) xmmregs, 0) == -1)
262             perror_with_name ("Couldn't write XMM registers");
263         }
264       else
265         {
266           have_ptrace_xmmregs = 0;
267 #endif
268           if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
269                       (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
270             perror_with_name ("Couldn't get floating point status");
271
272           i387_collect_fsave (current_regcache, regnum, &fpregs);
273
274           if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
275                       (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
276             perror_with_name ("Couldn't write floating point status");
277 #ifdef HAVE_PT_GETXMMREGS
278         }
279 #endif
280     }
281 }
282 \f
283
284 /* Support for debug registers.  */
285
286 #ifdef HAVE_PT_GETDBREGS
287
288 /* Not all versions of FreeBSD/i386 that support the debug registers
289    have this macro.  */
290 #ifndef DBREG_DRX
291 #define DBREG_DRX(d, x) ((&d->dr0)[x])
292 #endif
293
294 static void
295 i386bsd_dr_set (int regnum, unsigned int value)
296 {
297   struct dbreg dbregs;
298
299   if (ptrace (PT_GETDBREGS, PIDGET (inferior_ptid),
300               (PTRACE_ARG3_TYPE) &dbregs, 0) == -1)
301     perror_with_name ("Couldn't get debug registers");
302
303   /* For some mysterious reason, some of the reserved bits in the
304      debug control register get set.  Mask these off, otherwise the
305      ptrace call below will fail.  */
306   DBREG_DRX ((&dbregs), 7) &= ~(0x0000fc00);
307
308   DBREG_DRX ((&dbregs), regnum) = value;
309
310   if (ptrace (PT_SETDBREGS, PIDGET (inferior_ptid),
311               (PTRACE_ARG3_TYPE) &dbregs, 0) == -1)
312     perror_with_name ("Couldn't write debug registers");
313 }
314
315 void
316 i386bsd_dr_set_control (unsigned long control)
317 {
318   i386bsd_dr_set (7, control);
319 }
320
321 void
322 i386bsd_dr_set_addr (int regnum, CORE_ADDR addr)
323 {
324   gdb_assert (regnum >= 0 && regnum <= 4);
325
326   i386bsd_dr_set (regnum, addr);
327 }
328
329 void
330 i386bsd_dr_reset_addr (int regnum)
331 {
332   gdb_assert (regnum >= 0 && regnum <= 4);
333
334   i386bsd_dr_set (regnum, 0);
335 }
336
337 unsigned long
338 i386bsd_dr_get_status (void)
339 {
340   struct dbreg dbregs;
341
342   /* FIXME: kettenis/2001-03-31: Calling perror_with_name if the
343      ptrace call fails breaks debugging remote targets.  The correct
344      way to fix this is to add the hardware breakpoint and watchpoint
345      stuff to the target vector.  For now, just return zero if the
346      ptrace call fails.  */
347   if (ptrace (PT_GETDBREGS, PIDGET (inferior_ptid),
348               (PTRACE_ARG3_TYPE) & dbregs, 0) == -1)
349 #if 0
350     perror_with_name ("Couldn't read debug registers");
351 #else
352     return 0;
353 #endif
354
355   return DBREG_DRX ((&dbregs), 6);
356 }
357
358 #endif /* PT_GETDBREGS */
359 \f
360
361 /* Support for the user struct.  */
362
363 /* Return the address register REGNUM.  BLOCKEND is the value of
364    u.u_ar0, which should point to the registers.  */
365
366 CORE_ADDR
367 register_u_addr (CORE_ADDR blockend, int regnum)
368 {
369   return (CORE_ADDR) REG_ADDR (blockend, regnum);
370 }
371
372 #include <sys/param.h>
373 #include <sys/user.h>
374
375 /* Return the size of the user struct.  */
376
377 int
378 kernel_u_size (void)
379 {
380   return (sizeof (struct user));
381 }
382 \f
383 void
384 _initialize_i386bsd_nat (void)
385 {
386   int offset;
387
388   /* To support the recognition of signal handlers, i386bsd-tdep.c
389      hardcodes some constants.  Inclusion of this file means that we
390      are compiling a native debugger, which means that we can use the
391      system header files and sysctl(3) to get at the relevant
392      information.  */
393
394 #if defined (__FreeBSD_version) && __FreeBSD_version >= 400011
395 #define SC_REG_OFFSET i386fbsd4_sc_reg_offset
396 #elif defined (__FreeBSD_version) && __FreeBSD_version >= 300005
397 #define SC_REG_OFFSET i386fbsd_sc_reg_offset
398 #elif defined (NetBSD) || defined (__NetBSD_Version__)
399 #define SC_REG_OFFSET i386nbsd_sc_reg_offset
400 #elif defined (OpenBSD)
401 #define SC_REG_OFFSET i386obsd_sc_reg_offset
402 #else
403 #define SC_REG_OFFSET i386bsd_sc_reg_offset
404 #endif
405
406   /* We only check the program counter, stack pointer and frame
407      pointer since these members of `struct sigcontext' are essential
408      for providing backtraces.  More checks could be added, but would
409      involve adding configure checks for the appropriate structure
410      members, since older BSD's don't provide all of them.  */
411
412 #define SC_PC_OFFSET SC_REG_OFFSET[I386_EIP_REGNUM]
413 #define SC_SP_OFFSET SC_REG_OFFSET[I386_ESP_REGNUM]
414 #define SC_FP_OFFSET SC_REG_OFFSET[I386_EBP_REGNUM]
415
416   /* Override the default value for the offset of the program counter
417      in the sigcontext structure.  */
418   offset = offsetof (struct sigcontext, sc_pc);
419
420   if (SC_PC_OFFSET != offset)
421     {
422       warning ("\
423 offsetof (struct sigcontext, sc_pc) yields %d instead of %d.\n\
424 Please report this to <bug-gdb@gnu.org>.", 
425                offset, SC_PC_OFFSET);
426     }
427
428   SC_PC_OFFSET = offset;
429
430   /* Likewise for the stack pointer.  */
431   offset = offsetof (struct sigcontext, sc_sp);
432
433   if (SC_SP_OFFSET != offset)
434     {
435       warning ("\
436 offsetof (struct sigcontext, sc_sp) yields %d instead of %d.\n\
437 Please report this to <bug-gdb@gnu.org>.",
438                offset, SC_SP_OFFSET);
439     }
440
441   SC_SP_OFFSET = offset;
442
443   /* And the frame pointer.  */
444   offset = offsetof (struct sigcontext, sc_fp);
445
446   if (SC_FP_OFFSET != offset)
447     {
448       warning ("\
449 offsetof (struct sigcontext, sc_fp) yields %d instead of %d.\n\
450 Please report this to <bug-gdb@gnu.org>.",
451                offset, SC_FP_OFFSET);
452     }
453
454   SC_FP_OFFSET = offset;
455 }