OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [gdb/] [i386bsd-nat.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.