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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [gdb/] [alphanbsd-tdep.c] - Blame information for rev 309

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

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

powered by: WebSVN 2.1.0

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