OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

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

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

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

powered by: WebSVN 2.1.0

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