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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gdb-7.2/] [gdb/] [alphanbsd-tdep.c] - Blame information for rev 851

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

Line No. Rev Author Line
1 330 jeremybenn
/* Target-dependent code for NetBSD/alpha.
2
 
3
   Copyright (C) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010
4
   Free Software Foundation, Inc.
5
 
6
   Contributed by Wasabi Systems, Inc.
7
 
8
   This file is part of GDB.
9
 
10
   This program is free software; you can redistribute it and/or modify
11
   it under the terms of the GNU General Public License as published by
12
   the Free Software Foundation; either version 3 of the License, or
13
   (at your option) any later version.
14
 
15
   This program is distributed in the hope that it will be useful,
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
   GNU General Public License for more details.
19
 
20
   You should have received a copy of the GNU General Public License
21
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
 
23
#include "defs.h"
24
#include "frame.h"
25
#include "gdbcore.h"
26
#include "osabi.h"
27
#include "regcache.h"
28
#include "regset.h"
29
#include "value.h"
30
 
31
#include "gdb_assert.h"
32
#include "gdb_string.h"
33
 
34
#include "alpha-tdep.h"
35
#include "alphabsd-tdep.h"
36
#include "nbsd-tdep.h"
37
#include "solib-svr4.h"
38
#include "target.h"
39
 
40
/* Core file support.  */
41
 
42
/* Even though NetBSD/alpha used ELF since day one, it used the
43
   traditional a.out-style core dump format before NetBSD 1.6.  */
44
 
45
/* Sizeof `struct reg' in <machine/reg.h>.  */
46
#define ALPHANBSD_SIZEOF_GREGS  (32 * 8)
47
 
48
/* Sizeof `struct fpreg' in <machine/reg.h.  */
49
#define ALPHANBSD_SIZEOF_FPREGS ((32 * 8) + 8)
50
 
51
/* Supply register REGNUM from the buffer specified by FPREGS and LEN
52
   in the floating-point register set REGSET to register cache
53
   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
54
 
55
static void
56
alphanbsd_supply_fpregset (const struct regset *regset,
57
                           struct regcache *regcache,
58
                           int regnum, const void *fpregs, size_t len)
59
{
60
  const gdb_byte *regs = fpregs;
61
  int i;
62
 
63
  gdb_assert (len >= ALPHANBSD_SIZEOF_FPREGS);
64
 
65
  for (i = ALPHA_FP0_REGNUM; i < ALPHA_FP0_REGNUM + 31; i++)
66
    {
67
      if (regnum == i || regnum == -1)
68
        regcache_raw_supply (regcache, i, regs + (i - ALPHA_FP0_REGNUM) * 8);
69
    }
70
 
71
  if (regnum == ALPHA_FPCR_REGNUM || regnum == -1)
72
    regcache_raw_supply (regcache, ALPHA_FPCR_REGNUM, regs + 32 * 8);
73
}
74
 
75
/* Supply register REGNUM from the buffer specified by GREGS and LEN
76
   in the general-purpose register set REGSET to register cache
77
   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
78
 
79
static void
80
alphanbsd_supply_gregset (const struct regset *regset,
81
                          struct regcache *regcache,
82
                          int regnum, const void *gregs, size_t len)
83
{
84
  const gdb_byte *regs = gregs;
85
  int i;
86
 
87
  gdb_assert (len >= ALPHANBSD_SIZEOF_GREGS);
88
 
89
  for (i = 0; i < ALPHA_ZERO_REGNUM; i++)
90
    {
91
      if (regnum == i || regnum == -1)
92
        regcache_raw_supply (regcache, i, regs + i * 8);
93
    }
94
 
95
  if (regnum == ALPHA_PC_REGNUM || regnum == -1)
96
    regcache_raw_supply (regcache, ALPHA_PC_REGNUM, regs + 31 * 8);
97
}
98
 
99
/* Supply register REGNUM from the buffer specified by GREGS and LEN
100
   in the general-purpose register set REGSET to register cache
101
   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
102
 
103
static void
104
alphanbsd_aout_supply_gregset (const struct regset *regset,
105
                               struct regcache *regcache,
106
                               int regnum, const void *gregs, size_t len)
107
{
108
  const gdb_byte *regs = gregs;
109
  int i;
110
 
111
  /* Table to map a GDB register number to a trapframe register index.  */
112
  static const int regmap[] =
113
  {
114
     0,   1,   2,   3,
115
     4,   5,   6,   7,
116
     8,   9,  10,  11,
117
    12,  13,  14,  15,
118
    30,  31,  32,  16,
119
    17,  18,  19,  20,
120
    21,  22,  23,  24,
121
    25,  29,  26
122
  };
123
 
124
  gdb_assert (len >= ALPHANBSD_SIZEOF_GREGS);
125
 
126
  for (i = 0; i < ARRAY_SIZE(regmap); i++)
127
    {
128
      if (regnum == i || regnum == -1)
129
        regcache_raw_supply (regcache, i, regs + regmap[i] * 8);
130
    }
131
 
132
  if (regnum == ALPHA_PC_REGNUM || regnum == -1)
133
    regcache_raw_supply (regcache, ALPHA_PC_REGNUM, regs + 31 * 8);
134
 
135
  if (len >= ALPHANBSD_SIZEOF_GREGS + ALPHANBSD_SIZEOF_FPREGS)
136
    {
137
      regs += ALPHANBSD_SIZEOF_GREGS;
138
      len -= ALPHANBSD_SIZEOF_GREGS;
139
      alphanbsd_supply_fpregset (regset, regcache, regnum, regs, len);
140
    }
141
}
142
 
143
/* NetBSD/alpha register sets.  */
144
 
145
static struct regset alphanbsd_gregset =
146
{
147
  NULL,
148
  alphanbsd_supply_gregset
149
};
150
 
151
static struct regset alphanbsd_fpregset =
152
{
153
  NULL,
154
  alphanbsd_supply_fpregset
155
};
156
 
157
static struct regset alphanbsd_aout_gregset =
158
{
159
  NULL,
160
  alphanbsd_aout_supply_gregset
161
};
162
 
163
/* Return the appropriate register set for the core section identified
164
   by SECT_NAME and SECT_SIZE.  */
165
 
166
const struct regset *
167
alphanbsd_regset_from_core_section (struct gdbarch *gdbarch,
168
                                    const char *sect_name, size_t sect_size)
169
{
170
  if (strcmp (sect_name, ".reg") == 0 && sect_size >= ALPHANBSD_SIZEOF_GREGS)
171
    {
172
      if (sect_size >= ALPHANBSD_SIZEOF_GREGS + ALPHANBSD_SIZEOF_FPREGS)
173
        return &alphanbsd_aout_gregset;
174
      else
175
        return &alphanbsd_gregset;
176
    }
177
 
178
  if (strcmp (sect_name, ".reg2") == 0 && sect_size >= ALPHANBSD_SIZEOF_FPREGS)
179
    return &alphanbsd_fpregset;
180
 
181
  return NULL;
182
}
183
 
184
 
185
/* Signal trampolines.  */
186
 
187
/* Under NetBSD/alpha, signal handler invocations can be identified by the
188
   designated code sequence that is used to return from a signal handler.
189
   In particular, the return address of a signal handler points to the
190
   following code sequence:
191
 
192
        ldq     a0, 0(sp)
193
        lda     sp, 16(sp)
194
        lda     v0, 295(zero)   # __sigreturn14
195
        call_pal callsys
196
 
197
   Each instruction has a unique encoding, so we simply attempt to match
198
   the instruction the PC is pointing to with any of the above instructions.
199
   If there is a hit, we know the offset to the start of the designated
200
   sequence and can then check whether we really are executing in the
201
   signal trampoline.  If not, -1 is returned, otherwise the offset from the
202
   start of the return sequence is returned.  */
203
static const unsigned char sigtramp_retcode[] =
204
{
205
  0x00, 0x00, 0x1e, 0xa6,       /* ldq a0, 0(sp) */
206
  0x10, 0x00, 0xde, 0x23,       /* lda sp, 16(sp) */
207
  0x27, 0x01, 0x1f, 0x20,       /* lda v0, 295(zero) */
208
  0x83, 0x00, 0x00, 0x00,       /* call_pal callsys */
209
};
210
#define RETCODE_NWORDS          4
211
#define RETCODE_SIZE            (RETCODE_NWORDS * 4)
212
 
213
static LONGEST
214
alphanbsd_sigtramp_offset (struct gdbarch *gdbarch, CORE_ADDR pc)
215
{
216
  unsigned char ret[RETCODE_SIZE], w[4];
217
  LONGEST off;
218
  int i;
219
 
220
  if (target_read_memory (pc, (char *) w, 4) != 0)
221
    return -1;
222
 
223
  for (i = 0; i < RETCODE_NWORDS; i++)
224
    {
225
      if (memcmp (w, sigtramp_retcode + (i * 4), 4) == 0)
226
        break;
227
    }
228
  if (i == RETCODE_NWORDS)
229
    return (-1);
230
 
231
  off = i * 4;
232
  pc -= off;
233
 
234
  if (target_read_memory (pc, (char *) ret, sizeof (ret)) != 0)
235
    return -1;
236
 
237
  if (memcmp (ret, sigtramp_retcode, RETCODE_SIZE) == 0)
238
    return off;
239
 
240
  return -1;
241
}
242
 
243
static int
244
alphanbsd_pc_in_sigtramp (struct gdbarch *gdbarch,
245
                          CORE_ADDR pc, char *func_name)
246
{
247
  return (nbsd_pc_in_sigtramp (pc, func_name)
248
          || alphanbsd_sigtramp_offset (gdbarch, pc) >= 0);
249
}
250
 
251
static CORE_ADDR
252
alphanbsd_sigcontext_addr (struct frame_info *frame)
253
{
254
  /* FIXME: This is not correct for all versions of NetBSD/alpha.
255
     We will probably need to disassemble the trampoline to figure
256
     out which trampoline frame type we have.  */
257
  if (!get_next_frame (frame))
258
    return 0;
259
  return get_frame_base (get_next_frame (frame));
260
}
261
 
262
 
263
static void
264
alphanbsd_init_abi (struct gdbarch_info info,
265
                    struct gdbarch *gdbarch)
266
{
267
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
268
 
269
  /* Hook into the DWARF CFI frame unwinder.  */
270
  alpha_dwarf2_init_abi (info, gdbarch);
271
 
272
  /* Hook into the MDEBUG frame unwinder.  */
273
  alpha_mdebug_init_abi (info, gdbarch);
274
 
275
  /* NetBSD/alpha does not provide single step support via ptrace(2); we
276
     must use software single-stepping.  */
277
  set_gdbarch_software_single_step (gdbarch, alpha_software_single_step);
278
 
279
  /* NetBSD/alpha has SVR4-style shared libraries.  */
280
  set_solib_svr4_fetch_link_map_offsets
281
    (gdbarch, svr4_lp64_fetch_link_map_offsets);
282
 
283
  tdep->dynamic_sigtramp_offset = alphanbsd_sigtramp_offset;
284
  tdep->pc_in_sigtramp = alphanbsd_pc_in_sigtramp;
285
  tdep->sigcontext_addr = alphanbsd_sigcontext_addr;
286
 
287
  tdep->jb_pc = 2;
288
  tdep->jb_elt_size = 8;
289
 
290
  set_gdbarch_regset_from_core_section
291
    (gdbarch, alphanbsd_regset_from_core_section);
292
}
293
 
294
 
295
static enum gdb_osabi
296
alphanbsd_core_osabi_sniffer (bfd *abfd)
297
{
298
  if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0)
299
    return GDB_OSABI_NETBSD_ELF;
300
 
301
  return GDB_OSABI_UNKNOWN;
302
}
303
 
304
 
305
/* Provide a prototype to silence -Wmissing-prototypes.  */
306
void _initialize_alphanbsd_tdep (void);
307
 
308
void
309
_initialize_alphanbsd_tdep (void)
310
{
311
  /* BFD doesn't set a flavour for NetBSD style a.out core files.  */
312
  gdbarch_register_osabi_sniffer (bfd_arch_alpha, bfd_target_unknown_flavour,
313
                                  alphanbsd_core_osabi_sniffer);
314
 
315
  gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_NETBSD_ELF,
316
                          alphanbsd_init_abi);
317
}

powered by: WebSVN 2.1.0

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