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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [gdb/] [sparc-nat.c] - Blame information for rev 294

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

Line No. Rev Author Line
1 24 jeremybenn
/* Native-dependent code for SPARC.
2
 
3
   Copyright (C) 2003, 2004, 2005, 2007, 2008 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 3 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, see <http://www.gnu.org/licenses/>.  */
19
 
20
#include "defs.h"
21
#include "inferior.h"
22
#include "regcache.h"
23
#include "target.h"
24
 
25
#include "gdb_assert.h"
26
#include <signal.h>
27
#include "gdb_string.h"
28
#include <sys/ptrace.h>
29
#include "gdb_wait.h"
30
#ifdef HAVE_MACHINE_REG_H
31
#include <machine/reg.h>
32
#endif
33
 
34
#include "sparc-tdep.h"
35
#include "sparc-nat.h"
36
#include "inf-ptrace.h"
37
 
38
/* With some trickery we can use the code in this file for most (if
39
   not all) ptrace(2) based SPARC systems, which includes SunOS 4,
40
   GNU/Linux and the various SPARC BSD's.
41
 
42
   First, we need a data structure for use with ptrace(2).  SunOS has
43
   `struct regs' and `struct fp_status' in <machine/reg.h>.  BSD's
44
   have `struct reg' and `struct fpreg' in <machine/reg.h>.  GNU/Linux
45
   has the same structures as SunOS 4, but they're in <asm/reg.h>,
46
   which is a kernel header.  As a general rule we avoid including
47
   GNU/Linux kernel headers.  Fortunately GNU/Linux has a `gregset_t'
48
   and a `fpregset_t' that are equivalent to `struct regs' and `struct
49
   fp_status' in <sys/ucontext.h>, which is automatically included by
50
   <signal.h>.  Settling on using the `gregset_t' and `fpregset_t'
51
   typedefs, providing them for the other systems, therefore solves
52
   the puzzle.  */
53
 
54
#ifdef HAVE_MACHINE_REG_H
55
#ifdef HAVE_STRUCT_REG
56
typedef struct reg gregset_t;
57
typedef struct fpreg fpregset_t;
58
#else 
59
typedef struct regs gregset_t;
60
typedef struct fp_status fpregset_t;
61
#endif
62
#endif
63
 
64
/* Second, we need to remap the BSD ptrace(2) requests to their SunOS
65
   equivalents.  GNU/Linux already follows SunOS here.  */
66
 
67
#ifndef PTRACE_GETREGS
68
#define PTRACE_GETREGS PT_GETREGS
69
#endif
70
 
71
#ifndef PTRACE_SETREGS
72
#define PTRACE_SETREGS PT_SETREGS
73
#endif
74
 
75
#ifndef PTRACE_GETFPREGS
76
#define PTRACE_GETFPREGS PT_GETFPREGS
77
#endif
78
 
79
#ifndef PTRACE_SETFPREGS
80
#define PTRACE_SETFPREGS PT_SETFPREGS
81
#endif
82
 
83
/* Register set description.  */
84
const struct sparc_gregset *sparc_gregset;
85
void (*sparc_supply_gregset) (const struct sparc_gregset *,
86
                              struct regcache *, int , const void *);
87
void (*sparc_collect_gregset) (const struct sparc_gregset *,
88
                               const struct regcache *, int, void *);
89
void (*sparc_supply_fpregset) (struct regcache *, int , const void *);
90
void (*sparc_collect_fpregset) (const struct regcache *, int , void *);
91
int (*sparc_gregset_supplies_p) (int);
92
int (*sparc_fpregset_supplies_p) (int);
93
 
94
/* Determine whether `gregset_t' contains register REGNUM.  */
95
 
96
int
97
sparc32_gregset_supplies_p (int regnum)
98
{
99
  /* Integer registers.  */
100
  if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_G7_REGNUM)
101
      || (regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM)
102
      || (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_L7_REGNUM)
103
      || (regnum >= SPARC_I0_REGNUM && regnum <= SPARC_I7_REGNUM))
104
    return 1;
105
 
106
  /* Control registers.  */
107
  if (regnum == SPARC32_PC_REGNUM
108
      || regnum == SPARC32_NPC_REGNUM
109
      || regnum == SPARC32_PSR_REGNUM
110
      || regnum == SPARC32_Y_REGNUM)
111
    return 1;
112
 
113
  return 0;
114
}
115
 
116
/* Determine whether `fpregset_t' contains register REGNUM.  */
117
 
118
int
119
sparc32_fpregset_supplies_p (int regnum)
120
{
121
  /* Floating-point registers.  */
122
  if (regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F31_REGNUM)
123
    return 1;
124
 
125
  /* Control registers.  */
126
  if (regnum == SPARC32_FSR_REGNUM)
127
    return 1;
128
 
129
  return 0;
130
}
131
 
132
/* Fetch register REGNUM from the inferior.  If REGNUM is -1, do this
133
   for all registers (including the floating-point registers).  */
134
 
135
void
136
sparc_fetch_inferior_registers (struct regcache *regcache, int regnum)
137
{
138
  int pid;
139
 
140
  /* NOTE: cagney/2002-12-03: This code assumes that the currently
141
     selected light weight processes' registers can be written
142
     directly into the selected thread's register cache.  This works
143
     fine when given an 1:1 LWP:thread model (such as found on
144
     GNU/Linux) but will, likely, have problems when used on an N:1
145
     (userland threads) or N:M (userland multiple LWP) model.  In the
146
     case of the latter two, the LWP's registers do not necessarily
147
     belong to the selected thread (the LWP could be in the middle of
148
     executing the thread switch code).
149
 
150
     These functions should instead be paramaterized with an explicit
151
     object (struct regcache, struct thread_info?) into which the LWPs
152
     registers can be written.  */
153
  pid = TIDGET (inferior_ptid);
154
  if (pid == 0)
155
    pid = PIDGET (inferior_ptid);
156
 
157
  if (regnum == SPARC_G0_REGNUM)
158
    {
159
      regcache_raw_supply (regcache, SPARC_G0_REGNUM, NULL);
160
      return;
161
    }
162
 
163
  if (regnum == -1 || sparc_gregset_supplies_p (regnum))
164
    {
165
      gregset_t regs;
166
 
167
      if (ptrace (PTRACE_GETREGS, pid, (PTRACE_TYPE_ARG3) &regs, 0) == -1)
168
        perror_with_name (_("Couldn't get registers"));
169
 
170
      sparc_supply_gregset (sparc_gregset, regcache, -1, &regs);
171
      if (regnum != -1)
172
        return;
173
    }
174
 
175
  if (regnum == -1 || sparc_fpregset_supplies_p (regnum))
176
    {
177
      fpregset_t fpregs;
178
 
179
      if (ptrace (PTRACE_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
180
        perror_with_name (_("Couldn't get floating point status"));
181
 
182
      sparc_supply_fpregset (regcache, -1, &fpregs);
183
    }
184
}
185
 
186
void
187
sparc_store_inferior_registers (struct regcache *regcache, int regnum)
188
{
189
  int pid;
190
 
191
  /* NOTE: cagney/2002-12-02: See comment in fetch_inferior_registers
192
     about threaded assumptions.  */
193
  pid = TIDGET (inferior_ptid);
194
  if (pid == 0)
195
    pid = PIDGET (inferior_ptid);
196
 
197
  if (regnum == -1 || sparc_gregset_supplies_p (regnum))
198
    {
199
      gregset_t regs;
200
 
201
      if (ptrace (PTRACE_GETREGS, pid, (PTRACE_TYPE_ARG3) &regs, 0) == -1)
202
        perror_with_name (_("Couldn't get registers"));
203
 
204
      sparc_collect_gregset (sparc_gregset, regcache, regnum, &regs);
205
 
206
      if (ptrace (PTRACE_SETREGS, pid, (PTRACE_TYPE_ARG3) &regs, 0) == -1)
207
        perror_with_name (_("Couldn't write registers"));
208
 
209
      /* Deal with the stack regs.  */
210
      if (regnum == -1 || regnum == SPARC_SP_REGNUM
211
          || (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM))
212
        {
213
          ULONGEST sp;
214
 
215
          regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp);
216
          sparc_collect_rwindow (regcache, sp, regnum);
217
        }
218
 
219
      if (regnum != -1)
220
        return;
221
    }
222
 
223
  if (regnum == -1 || sparc_fpregset_supplies_p (regnum))
224
    {
225
      fpregset_t fpregs, saved_fpregs;
226
 
227
      if (ptrace (PTRACE_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
228
        perror_with_name (_("Couldn't get floating-point registers"));
229
 
230
      memcpy (&saved_fpregs, &fpregs, sizeof (fpregs));
231
      sparc_collect_fpregset (regcache, regnum, &fpregs);
232
 
233
      /* Writing the floating-point registers will fail on NetBSD with
234
         EINVAL if the inferior process doesn't have an FPU state
235
         (i.e. if it didn't use the FPU yet).  Therefore we don't try
236
         to write the registers if nothing changed.  */
237
      if (memcmp (&saved_fpregs, &fpregs, sizeof (fpregs)) != 0)
238
        {
239
          if (ptrace (PTRACE_SETFPREGS, pid,
240
                      (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
241
            perror_with_name (_("Couldn't write floating-point registers"));
242
        }
243
 
244
      if (regnum != -1)
245
        return;
246
    }
247
}
248
 
249
 
250
/* Fetch StackGhost Per-Process XOR cookie.  */
251
 
252
LONGEST
253
sparc_xfer_wcookie (struct target_ops *ops, enum target_object object,
254
                    const char *annex, gdb_byte *readbuf,
255
                    const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
256
{
257
  unsigned long wcookie = 0;
258
  char *buf = (char *)&wcookie;
259
 
260
  gdb_assert (object == TARGET_OBJECT_WCOOKIE);
261
  gdb_assert (readbuf && writebuf == NULL);
262
 
263
  if (offset == sizeof (unsigned long))
264
    return 0;                    /* Signal EOF.  */
265
  if (offset > sizeof (unsigned long))
266
    return -1;
267
 
268
#ifdef PT_WCOOKIE
269
  /* If PT_WCOOKIE is defined (by <sys/ptrace.h>), assume we're
270
     running on an OpenBSD release that uses StackGhost (3.1 or
271
     later).  Since release 3.6, OpenBSD uses a fully randomized
272
     cookie.  */
273
  {
274
    int pid;
275
 
276
    pid = TIDGET (inferior_ptid);
277
    if (pid == 0)
278
      pid = PIDGET (inferior_ptid);
279
 
280
    /* Sanity check.  The proper type for a cookie is register_t, but
281
       we can't assume that this type exists on all systems supported
282
       by the code in this file.  */
283
    gdb_assert (sizeof (wcookie) == sizeof (register_t));
284
 
285
    /* Fetch the cookie.  */
286
    if (ptrace (PT_WCOOKIE, pid, (PTRACE_TYPE_ARG3) &wcookie, 0) == -1)
287
      {
288
        if (errno != EINVAL)
289
          perror_with_name (_("Couldn't get StackGhost cookie"));
290
 
291
        /* Although PT_WCOOKIE is defined on OpenBSD 3.1 and later,
292
           the request wasn't implemented until after OpenBSD 3.4.  If
293
           the kernel doesn't support the PT_WCOOKIE request, assume
294
           we're running on a kernel that uses non-randomized cookies.  */
295
        wcookie = 0x3;
296
      }
297
  }
298
#endif /* PT_WCOOKIE */
299
 
300
  if (len > sizeof (unsigned long) - offset)
301
    len = sizeof (unsigned long) - offset;
302
 
303
  memcpy (readbuf, buf + offset, len);
304
  return len;
305
}
306
 
307
LONGEST (*inf_ptrace_xfer_partial) (struct target_ops *, enum target_object,
308
                                    const char *, gdb_byte *, const gdb_byte *,
309
                                    ULONGEST, LONGEST);
310
 
311
static LONGEST
312
sparc_xfer_partial (struct target_ops *ops, enum target_object object,
313
                    const char *annex, gdb_byte *readbuf,
314
                    const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
315
{
316
  if (object == TARGET_OBJECT_WCOOKIE)
317
    return sparc_xfer_wcookie (ops, object, annex, readbuf, writebuf,
318
                               offset, len);
319
 
320
  return inf_ptrace_xfer_partial (ops, object, annex, readbuf, writebuf,
321
                                  offset, len);
322
}
323
 
324
/* Create a prototype generic SPARC target.  The client can override
325
   it with local methods.  */
326
 
327
struct target_ops *
328
sparc_target (void)
329
{
330
  struct target_ops *t;
331
 
332
  t = inf_ptrace_target ();
333
  t->to_fetch_registers = sparc_fetch_inferior_registers;
334
  t->to_store_registers = sparc_store_inferior_registers;
335
  inf_ptrace_xfer_partial = t->to_xfer_partial;
336
  t->to_xfer_partial = sparc_xfer_partial;
337
  return t;
338
}
339
 
340
 
341
/* Provide a prototype to silence -Wmissing-prototypes.  */
342
void _initialize_sparc_nat (void);
343
 
344
void
345
_initialize_sparc_nat (void)
346
{
347
  /* Deafult to using SunOS 4 register sets.  */
348
  if (sparc_gregset == NULL)
349
    sparc_gregset = &sparc32_sunos4_gregset;
350
  if (sparc_supply_gregset == NULL)
351
    sparc_supply_gregset = sparc32_supply_gregset;
352
  if (sparc_collect_gregset == NULL)
353
    sparc_collect_gregset = sparc32_collect_gregset;
354
  if (sparc_supply_fpregset == NULL)
355
    sparc_supply_fpregset = sparc32_supply_fpregset;
356
  if (sparc_collect_fpregset == NULL)
357
    sparc_collect_fpregset = sparc32_collect_fpregset;
358
  if (sparc_gregset_supplies_p == NULL)
359
    sparc_gregset_supplies_p = sparc32_gregset_supplies_p;
360
  if (sparc_fpregset_supplies_p == NULL)
361
    sparc_fpregset_supplies_p = sparc32_fpregset_supplies_p;
362
}

powered by: WebSVN 2.1.0

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