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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [gdb/] [i386bsd-nat.c] - Blame information for rev 816

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 24 jeremybenn
/* Native-dependent code for modern i386 BSD's.
2
 
3
   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
4
   Free Software Foundation, Inc.
5
 
6
   This file is part of GDB.
7
 
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
 
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
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
#include "i386-tdep.h"
34
#include "i387-tdep.h"
35
#include "i386bsd-nat.h"
36
#include "inf-ptrace.h"
37
 
38
 
39
/* In older BSD versions we cannot get at some of the segment
40
   registers.  FreeBSD for example didn't support the %fs and %gs
41
   registers until the 3.0 release.  We have autoconf checks for their
42
   presence, and deal gracefully with their absence.  */
43
 
44
/* Offset in `struct reg' where MEMBER is stored.  */
45
#define REG_OFFSET(member) offsetof (struct reg, member)
46
 
47
/* At i386bsd_reg_offset[REGNUM] you'll find the offset in `struct
48
   reg' where the GDB register REGNUM is stored.  Unsupported
49
   registers are marked with `-1'.  */
50
static int i386bsd_r_reg_offset[] =
51
{
52
  REG_OFFSET (r_eax),
53
  REG_OFFSET (r_ecx),
54
  REG_OFFSET (r_edx),
55
  REG_OFFSET (r_ebx),
56
  REG_OFFSET (r_esp),
57
  REG_OFFSET (r_ebp),
58
  REG_OFFSET (r_esi),
59
  REG_OFFSET (r_edi),
60
  REG_OFFSET (r_eip),
61
  REG_OFFSET (r_eflags),
62
  REG_OFFSET (r_cs),
63
  REG_OFFSET (r_ss),
64
  REG_OFFSET (r_ds),
65
  REG_OFFSET (r_es),
66
#ifdef HAVE_STRUCT_REG_R_FS
67
  REG_OFFSET (r_fs),
68
#else
69
  -1,
70
#endif
71
#ifdef HAVE_STRUCT_REG_R_GS
72
  REG_OFFSET (r_gs)
73
#else
74
  -1
75
#endif
76
};
77
 
78
/* Macro to determine if a register is fetched with PT_GETREGS.  */
79
#define GETREGS_SUPPLIES(regnum) \
80
  ((0 <= (regnum) && (regnum) <= 15))
81
 
82
#ifdef HAVE_PT_GETXMMREGS
83
/* Set to 1 if the kernel supports PT_GETXMMREGS.  Initialized to -1
84
   so that we try PT_GETXMMREGS the first time around.  */
85
static int have_ptrace_xmmregs = -1;
86
#endif
87
 
88
 
89
/* Supply the general-purpose registers in GREGS, to REGCACHE.  */
90
 
91
static void
92
i386bsd_supply_gregset (struct regcache *regcache, const void *gregs)
93
{
94
  const char *regs = gregs;
95
  int regnum;
96
 
97
  for (regnum = 0; regnum < ARRAY_SIZE (i386bsd_r_reg_offset); regnum++)
98
    {
99
      int offset = i386bsd_r_reg_offset[regnum];
100
 
101
      if (offset != -1)
102
        regcache_raw_supply (regcache, regnum, regs + offset);
103
    }
104
}
105
 
106
/* Collect register REGNUM from REGCACHE and store its contents in
107
   GREGS.  If REGNUM is -1, collect and store all appropriate
108
   registers.  */
109
 
110
static void
111
i386bsd_collect_gregset (const struct regcache *regcache,
112
                         void *gregs, int regnum)
113
{
114
  char *regs = gregs;
115
  int i;
116
 
117
  for (i = 0; i < ARRAY_SIZE (i386bsd_r_reg_offset); i++)
118
    {
119
      if (regnum == -1 || regnum == i)
120
        {
121
          int offset = i386bsd_r_reg_offset[i];
122
 
123
          if (offset != -1)
124
            regcache_raw_collect (regcache, i, regs + offset);
125
        }
126
    }
127
}
128
 
129
/* Fetch register REGNUM from the inferior.  If REGNUM is -1, do this
130
   for all registers (including the floating point registers).  */
131
 
132
static void
133
i386bsd_fetch_inferior_registers (struct regcache *regcache, int regnum)
134
{
135
  if (regnum == -1 || GETREGS_SUPPLIES (regnum))
136
    {
137
      struct reg regs;
138
 
139
      if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
140
                  (PTRACE_TYPE_ARG3) &regs, 0) == -1)
141
        perror_with_name (_("Couldn't get registers"));
142
 
143
      i386bsd_supply_gregset (regcache, &regs);
144
      if (regnum != -1)
145
        return;
146
    }
147
 
148
  if (regnum == -1 || regnum >= I386_ST0_REGNUM)
149
    {
150
      struct fpreg fpregs;
151
#ifdef HAVE_PT_GETXMMREGS
152
      char xmmregs[512];
153
 
154
      if (have_ptrace_xmmregs != 0
155
          && ptrace(PT_GETXMMREGS, PIDGET (inferior_ptid),
156
                    (PTRACE_TYPE_ARG3) xmmregs, 0) == 0)
157
        {
158
          have_ptrace_xmmregs = 1;
159
          i387_supply_fxsave (regcache, -1, xmmregs);
160
        }
161
      else
162
        {
163
          if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
164
                      (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
165
            perror_with_name (_("Couldn't get floating point status"));
166
 
167
          i387_supply_fsave (regcache, -1, &fpregs);
168
        }
169
#else
170
      if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
171
                  (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
172
        perror_with_name (_("Couldn't get floating point status"));
173
 
174
      i387_supply_fsave (regcache, -1, &fpregs);
175
#endif
176
    }
177
}
178
 
179
/* Store register REGNUM back into the inferior.  If REGNUM is -1, do
180
   this for all registers (including the floating point registers).  */
181
 
182
static void
183
i386bsd_store_inferior_registers (struct regcache *regcache, int regnum)
184
{
185
  if (regnum == -1 || GETREGS_SUPPLIES (regnum))
186
    {
187
      struct reg regs;
188
 
189
      if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
190
                  (PTRACE_TYPE_ARG3) &regs, 0) == -1)
191
        perror_with_name (_("Couldn't get registers"));
192
 
193
      i386bsd_collect_gregset (regcache, &regs, regnum);
194
 
195
      if (ptrace (PT_SETREGS, PIDGET (inferior_ptid),
196
                  (PTRACE_TYPE_ARG3) &regs, 0) == -1)
197
        perror_with_name (_("Couldn't write registers"));
198
 
199
      if (regnum != -1)
200
        return;
201
    }
202
 
203
  if (regnum == -1 || regnum >= I386_ST0_REGNUM)
204
    {
205
      struct fpreg fpregs;
206
#ifdef HAVE_PT_GETXMMREGS
207
      char xmmregs[512];
208
 
209
      if (have_ptrace_xmmregs != 0
210
          && ptrace(PT_GETXMMREGS, PIDGET (inferior_ptid),
211
                    (PTRACE_TYPE_ARG3) xmmregs, 0) == 0)
212
        {
213
          have_ptrace_xmmregs = 1;
214
 
215
          i387_collect_fxsave (regcache, regnum, xmmregs);
216
 
217
          if (ptrace (PT_SETXMMREGS, PIDGET (inferior_ptid),
218
                      (PTRACE_TYPE_ARG3) xmmregs, 0) == -1)
219
            perror_with_name (_("Couldn't write XMM registers"));
220
        }
221
      else
222
        {
223
          have_ptrace_xmmregs = 0;
224
#endif
225
          if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
226
                      (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
227
            perror_with_name (_("Couldn't get floating point status"));
228
 
229
          i387_collect_fsave (regcache, regnum, &fpregs);
230
 
231
          if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
232
                      (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
233
            perror_with_name (_("Couldn't write floating point status"));
234
#ifdef HAVE_PT_GETXMMREGS
235
        }
236
#endif
237
    }
238
}
239
 
240
/* Create a prototype *BSD/i386 target.  The client can override it
241
   with local methods.  */
242
 
243
struct target_ops *
244
i386bsd_target (void)
245
{
246
  struct target_ops *t;
247
 
248
  t = inf_ptrace_target ();
249
  t->to_fetch_registers = i386bsd_fetch_inferior_registers;
250
  t->to_store_registers = i386bsd_store_inferior_registers;
251
  return t;
252
}
253
 
254
 
255
/* Support for debug registers.  */
256
 
257
#ifdef HAVE_PT_GETDBREGS
258
 
259
/* Not all versions of FreeBSD/i386 that support the debug registers
260
   have this macro.  */
261
#ifndef DBREG_DRX
262
#define DBREG_DRX(d, x) ((&d->dr0)[x])
263
#endif
264
 
265
static void
266
i386bsd_dr_set (int regnum, unsigned int value)
267
{
268
  struct dbreg dbregs;
269
 
270
  if (ptrace (PT_GETDBREGS, PIDGET (inferior_ptid),
271
              (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
272
    perror_with_name (_("Couldn't get debug registers"));
273
 
274
  /* For some mysterious reason, some of the reserved bits in the
275
     debug control register get set.  Mask these off, otherwise the
276
     ptrace call below will fail.  */
277
  DBREG_DRX ((&dbregs), 7) &= ~(0x0000fc00);
278
 
279
  DBREG_DRX ((&dbregs), regnum) = value;
280
 
281
  if (ptrace (PT_SETDBREGS, PIDGET (inferior_ptid),
282
              (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
283
    perror_with_name (_("Couldn't write debug registers"));
284
}
285
 
286
void
287
i386bsd_dr_set_control (unsigned long control)
288
{
289
  i386bsd_dr_set (7, control);
290
}
291
 
292
void
293
i386bsd_dr_set_addr (int regnum, CORE_ADDR addr)
294
{
295
  gdb_assert (regnum >= 0 && regnum <= 4);
296
 
297
  i386bsd_dr_set (regnum, addr);
298
}
299
 
300
void
301
i386bsd_dr_reset_addr (int regnum)
302
{
303
  gdb_assert (regnum >= 0 && regnum <= 4);
304
 
305
  i386bsd_dr_set (regnum, 0);
306
}
307
 
308
unsigned long
309
i386bsd_dr_get_status (void)
310
{
311
  struct dbreg dbregs;
312
 
313
  /* FIXME: kettenis/2001-03-31: Calling perror_with_name if the
314
     ptrace call fails breaks debugging remote targets.  The correct
315
     way to fix this is to add the hardware breakpoint and watchpoint
316
     stuff to the target vector.  For now, just return zero if the
317
     ptrace call fails.  */
318
  if (ptrace (PT_GETDBREGS, PIDGET (inferior_ptid),
319
              (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
320
#if 0
321
    perror_with_name (_("Couldn't read debug registers"));
322
#else
323
    return 0;
324
#endif
325
 
326
  return DBREG_DRX ((&dbregs), 6);
327
}
328
 
329
#endif /* PT_GETDBREGS */
330
 
331
 
332
void
333
_initialize_i386bsd_nat (void)
334
{
335
  int offset;
336
 
337
  /* To support the recognition of signal handlers, i386bsd-tdep.c
338
     hardcodes some constants.  Inclusion of this file means that we
339
     are compiling a native debugger, which means that we can use the
340
     system header files and sysctl(3) to get at the relevant
341
     information.  */
342
 
343
#if defined (__FreeBSD_version) && __FreeBSD_version >= 400011
344
#define SC_REG_OFFSET i386fbsd4_sc_reg_offset
345
#elif defined (__FreeBSD_version) && __FreeBSD_version >= 300005
346
#define SC_REG_OFFSET i386fbsd_sc_reg_offset
347
#elif defined (NetBSD) || defined (__NetBSD_Version__)
348
#define SC_REG_OFFSET i386nbsd_sc_reg_offset
349
#elif defined (OpenBSD)
350
#define SC_REG_OFFSET i386obsd_sc_reg_offset
351
#endif
352
 
353
#ifdef SC_REG_OFFSET
354
 
355
  /* We only check the program counter, stack pointer and frame
356
     pointer since these members of `struct sigcontext' are essential
357
     for providing backtraces.  More checks could be added, but would
358
     involve adding configure checks for the appropriate structure
359
     members, since older BSD's don't provide all of them.  */
360
 
361
#define SC_PC_OFFSET SC_REG_OFFSET[I386_EIP_REGNUM]
362
#define SC_SP_OFFSET SC_REG_OFFSET[I386_ESP_REGNUM]
363
#define SC_FP_OFFSET SC_REG_OFFSET[I386_EBP_REGNUM]
364
 
365
  /* Override the default value for the offset of the program counter
366
     in the sigcontext structure.  */
367
  offset = offsetof (struct sigcontext, sc_pc);
368
 
369
  if (SC_PC_OFFSET != offset)
370
    {
371
      warning (_("\
372
offsetof (struct sigcontext, sc_pc) yields %d instead of %d.\n\
373
Please report this to <bug-gdb@gnu.org>."),
374
               offset, SC_PC_OFFSET);
375
    }
376
 
377
  SC_PC_OFFSET = offset;
378
 
379
  /* Likewise for the stack pointer.  */
380
  offset = offsetof (struct sigcontext, sc_sp);
381
 
382
  if (SC_SP_OFFSET != offset)
383
    {
384
      warning (_("\
385
offsetof (struct sigcontext, sc_sp) yields %d instead of %d.\n\
386
Please report this to <bug-gdb@gnu.org>."),
387
               offset, SC_SP_OFFSET);
388
    }
389
 
390
  SC_SP_OFFSET = offset;
391
 
392
  /* And the frame pointer.  */
393
  offset = offsetof (struct sigcontext, sc_fp);
394
 
395
  if (SC_FP_OFFSET != offset)
396
    {
397
      warning (_("\
398
offsetof (struct sigcontext, sc_fp) yields %d instead of %d.\n\
399
Please report this to <bug-gdb@gnu.org>."),
400
               offset, SC_FP_OFFSET);
401
    }
402
 
403
  SC_FP_OFFSET = offset;
404
 
405
#endif /* SC_REG_OFFSET */
406
}

powered by: WebSVN 2.1.0

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