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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.1/] [gdb/] [mipsnbsd-tdep.c] - Blame information for rev 227

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 227 jeremybenn
/* Target-dependent code for NetBSD/mips.
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 "gdbcore.h"
25
#include "regcache.h"
26
#include "regset.h"
27
#include "target.h"
28
#include "value.h"
29
#include "osabi.h"
30
 
31
#include "gdb_assert.h"
32
#include "gdb_string.h"
33
 
34
#include "nbsd-tdep.h"
35
#include "mipsnbsd-tdep.h"
36
#include "mips-tdep.h"
37
 
38
#include "solib-svr4.h"
39
 
40
/* Shorthand for some register numbers used below.  */
41
#define MIPS_PC_REGNUM  MIPS_EMBED_PC_REGNUM
42
#define MIPS_FP0_REGNUM MIPS_EMBED_FP0_REGNUM
43
#define MIPS_FSR_REGNUM MIPS_EMBED_FP0_REGNUM + 32
44
 
45
/* Core file support.  */
46
 
47
/* Number of registers in `struct reg' from <machine/reg.h>.  */
48
#define MIPSNBSD_NUM_GREGS      38
49
 
50
/* Number of registers in `struct fpreg' from <machine/reg.h>.  */
51
#define MIPSNBSD_NUM_FPREGS     33
52
 
53
/* Supply register REGNUM from the buffer specified by FPREGS and LEN
54
   in the floating-point register set REGSET to register cache
55
   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
56
 
57
static void
58
mipsnbsd_supply_fpregset (const struct regset *regset,
59
                          struct regcache *regcache,
60
                          int regnum, const void *fpregs, size_t len)
61
{
62
  size_t regsize = mips_isa_regsize (get_regcache_arch (regcache));
63
  const char *regs = fpregs;
64
  int i;
65
 
66
  gdb_assert (len >= MIPSNBSD_NUM_FPREGS * regsize);
67
 
68
  for (i = MIPS_FP0_REGNUM; i <= MIPS_FSR_REGNUM; i++)
69
    {
70
      if (regnum == i || regnum == -1)
71
        regcache_raw_supply (regcache, i,
72
                             regs + (i - MIPS_FP0_REGNUM) * regsize);
73
    }
74
}
75
 
76
/* Supply register REGNUM from the buffer specified by GREGS and LEN
77
   in the general-purpose register set REGSET to register cache
78
   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
79
 
80
static void
81
mipsnbsd_supply_gregset (const struct regset *regset,
82
                         struct regcache *regcache, int regnum,
83
                         const void *gregs, size_t len)
84
{
85
  size_t regsize = mips_isa_regsize (get_regcache_arch (regcache));
86
  const char *regs = gregs;
87
  int i;
88
 
89
  gdb_assert (len >= MIPSNBSD_NUM_GREGS * regsize);
90
 
91
  for (i = 0; i <= MIPS_PC_REGNUM; i++)
92
    {
93
      if (regnum == i || regnum == -1)
94
        regcache_raw_supply (regcache, i, regs + i * regsize);
95
    }
96
 
97
  if (len >= (MIPSNBSD_NUM_GREGS + MIPSNBSD_NUM_FPREGS) * regsize)
98
    {
99
      regs += MIPSNBSD_NUM_GREGS * regsize;
100
      len -= MIPSNBSD_NUM_GREGS * regsize;
101
      mipsnbsd_supply_fpregset (regset, regcache, regnum, regs, len);
102
    }
103
}
104
 
105
/* NetBSD/mips register sets.  */
106
 
107
static struct regset mipsnbsd_gregset =
108
{
109
  NULL,
110
  mipsnbsd_supply_gregset
111
};
112
 
113
static struct regset mipsnbsd_fpregset =
114
{
115
  NULL,
116
  mipsnbsd_supply_fpregset
117
};
118
 
119
/* Return the appropriate register set for the core section identified
120
   by SECT_NAME and SECT_SIZE.  */
121
 
122
static const struct regset *
123
mipsnbsd_regset_from_core_section (struct gdbarch *gdbarch,
124
                                   const char *sect_name, size_t sect_size)
125
{
126
  size_t regsize = mips_isa_regsize (gdbarch);
127
 
128
  if (strcmp (sect_name, ".reg") == 0
129
      && sect_size >= MIPSNBSD_NUM_GREGS * regsize)
130
    return &mipsnbsd_gregset;
131
 
132
  if (strcmp (sect_name, ".reg2") == 0
133
      && sect_size >= MIPSNBSD_NUM_FPREGS * regsize)
134
    return &mipsnbsd_fpregset;
135
 
136
  return NULL;
137
}
138
 
139
 
140
/* Conveniently, GDB uses the same register numbering as the
141
   ptrace register structure used by NetBSD/mips.  */
142
 
143
void
144
mipsnbsd_supply_reg (struct regcache *regcache, const char *regs, int regno)
145
{
146
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
147
  int i;
148
 
149
  for (i = 0; i <= gdbarch_pc_regnum (gdbarch); i++)
150
    {
151
      if (regno == i || regno == -1)
152
        {
153
          if (gdbarch_cannot_fetch_register (gdbarch, i))
154
            regcache_raw_supply (regcache, i, NULL);
155
          else
156
            regcache_raw_supply (regcache, i,
157
                                 regs + (i * mips_isa_regsize (gdbarch)));
158
        }
159
    }
160
}
161
 
162
void
163
mipsnbsd_fill_reg (const struct regcache *regcache, char *regs, int regno)
164
{
165
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
166
  int i;
167
 
168
  for (i = 0; i <= gdbarch_pc_regnum (gdbarch); i++)
169
    if ((regno == i || regno == -1)
170
        && ! gdbarch_cannot_store_register (gdbarch, i))
171
      regcache_raw_collect (regcache, i,
172
                            regs + (i * mips_isa_regsize (gdbarch)));
173
}
174
 
175
void
176
mipsnbsd_supply_fpreg (struct regcache *regcache, const char *fpregs, int regno)
177
{
178
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
179
  int i;
180
 
181
  for (i = gdbarch_fp0_regnum (gdbarch);
182
       i <= mips_regnum (gdbarch)->fp_implementation_revision;
183
       i++)
184
    {
185
      if (regno == i || regno == -1)
186
        {
187
          if (gdbarch_cannot_fetch_register (gdbarch, i))
188
            regcache_raw_supply (regcache, i, NULL);
189
          else
190
            regcache_raw_supply (regcache, i,
191
                                 fpregs
192
                                 + ((i - gdbarch_fp0_regnum (gdbarch))
193
                                    * mips_isa_regsize (gdbarch)));
194
        }
195
    }
196
}
197
 
198
void
199
mipsnbsd_fill_fpreg (const struct regcache *regcache, char *fpregs, int regno)
200
{
201
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
202
  int i;
203
 
204
  for (i = gdbarch_fp0_regnum (gdbarch);
205
       i <= mips_regnum (gdbarch)->fp_control_status;
206
       i++)
207
    if ((regno == i || regno == -1)
208
        && ! gdbarch_cannot_store_register (gdbarch, i))
209
      regcache_raw_collect (regcache, i,
210
                            fpregs + ((i - gdbarch_fp0_regnum (gdbarch))
211
                              * mips_isa_regsize (gdbarch)));
212
}
213
 
214
/* Under NetBSD/mips, signal handler invocations can be identified by the
215
   designated code sequence that is used to return from a signal handler.
216
   In particular, the return address of a signal handler points to the
217
   following code sequence:
218
 
219
        addu    a0, sp, 16
220
        li      v0, 295                 # __sigreturn14
221
        syscall
222
 
223
   Each instruction has a unique encoding, so we simply attempt to match
224
   the instruction the PC is pointing to with any of the above instructions.
225
   If there is a hit, we know the offset to the start of the designated
226
   sequence and can then check whether we really are executing in the
227
   signal trampoline.  If not, -1 is returned, otherwise the offset from the
228
   start of the return sequence is returned.  */
229
 
230
#define RETCODE_NWORDS  3
231
#define RETCODE_SIZE    (RETCODE_NWORDS * 4)
232
 
233
static const unsigned char sigtramp_retcode_mipsel[RETCODE_SIZE] =
234
{
235
  0x10, 0x00, 0xa4, 0x27,       /* addu a0, sp, 16 */
236
  0x27, 0x01, 0x02, 0x24,       /* li v0, 295 */
237
  0x0c, 0x00, 0x00, 0x00,       /* syscall */
238
};
239
 
240
static const unsigned char sigtramp_retcode_mipseb[RETCODE_SIZE] =
241
{
242
  0x27, 0xa4, 0x00, 0x10,       /* addu a0, sp, 16 */
243
  0x24, 0x02, 0x01, 0x27,       /* li v0, 295 */
244
  0x00, 0x00, 0x00, 0x0c,       /* syscall */
245
};
246
 
247
/* Figure out where the longjmp will land.  We expect that we have
248
   just entered longjmp and haven't yet setup the stack frame, so the
249
   args are still in the argument regs.  MIPS_A0_REGNUM points at the
250
   jmp_buf structure from which we extract the PC that we will land
251
   at.  The PC is copied into *pc.  This routine returns true on
252
   success.  */
253
 
254
#define NBSD_MIPS_JB_PC                 (2 * 4)
255
#define NBSD_MIPS_JB_ELEMENT_SIZE(gdbarch)      mips_isa_regsize (gdbarch)
256
#define NBSD_MIPS_JB_OFFSET(gdbarch)            (NBSD_MIPS_JB_PC * \
257
                                         NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch))
258
 
259
static int
260
mipsnbsd_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
261
{
262
  struct gdbarch *gdbarch = get_frame_arch (frame);
263
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
264
  CORE_ADDR jb_addr;
265
  char *buf;
266
 
267
  buf = alloca (NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch));
268
 
269
  jb_addr = get_frame_register_unsigned (frame, MIPS_A0_REGNUM);
270
 
271
  if (target_read_memory (jb_addr + NBSD_MIPS_JB_OFFSET (gdbarch), buf,
272
                          NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch)))
273
    return 0;
274
 
275
  *pc = extract_unsigned_integer (buf, NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch),
276
                                  byte_order);
277
  return 1;
278
}
279
 
280
static int
281
mipsnbsd_cannot_fetch_register (struct gdbarch *gdbarch, int regno)
282
{
283
  return (regno == MIPS_ZERO_REGNUM
284
          || regno == mips_regnum (gdbarch)->fp_implementation_revision);
285
}
286
 
287
static int
288
mipsnbsd_cannot_store_register (struct gdbarch *gdbarch, int regno)
289
{
290
  return (regno == MIPS_ZERO_REGNUM
291
          || regno == mips_regnum (gdbarch)->fp_implementation_revision);
292
}
293
 
294
/* Shared library support.  */
295
 
296
/* NetBSD/mips uses a slightly different `struct link_map' than the
297
   other NetBSD platforms.  */
298
 
299
static struct link_map_offsets *
300
mipsnbsd_ilp32_fetch_link_map_offsets (void)
301
{
302
  static struct link_map_offsets lmo;
303
  static struct link_map_offsets *lmp = NULL;
304
 
305
  if (lmp == NULL)
306
    {
307
      lmp = &lmo;
308
 
309
      lmo.r_version_offset = 0;
310
      lmo.r_version_size = 4;
311
      lmo.r_map_offset = 4;
312
      lmo.r_brk_offset = 8;
313
      lmo.r_ldsomap_offset = -1;
314
 
315
      /* Everything we need is in the first 24 bytes.  */
316
      lmo.link_map_size = 24;
317
      lmo.l_addr_offset = 4;
318
      lmo.l_name_offset = 8;
319
      lmo.l_ld_offset = 12;
320
      lmo.l_next_offset = 16;
321
      lmo.l_prev_offset = 20;
322
    }
323
 
324
  return lmp;
325
}
326
 
327
static struct link_map_offsets *
328
mipsnbsd_lp64_fetch_link_map_offsets (void)
329
{
330
  static struct link_map_offsets lmo;
331
  static struct link_map_offsets *lmp = NULL;
332
 
333
  if (lmp == NULL)
334
    {
335
      lmp = &lmo;
336
 
337
      lmo.r_version_offset = 0;
338
      lmo.r_version_size = 4;
339
      lmo.r_map_offset = 8;
340
      lmo.r_brk_offset = 16;
341
      lmo.r_ldsomap_offset = -1;
342
 
343
      /* Everything we need is in the first 40 bytes.  */
344
      lmo.link_map_size = 48;
345
      lmo.l_addr_offset = 0;
346
      lmo.l_name_offset = 16;
347
      lmo.l_ld_offset = 24;
348
      lmo.l_next_offset = 32;
349
      lmo.l_prev_offset = 40;
350
    }
351
 
352
  return lmp;
353
}
354
 
355
 
356
static void
357
mipsnbsd_init_abi (struct gdbarch_info info,
358
                   struct gdbarch *gdbarch)
359
{
360
  set_gdbarch_regset_from_core_section
361
    (gdbarch, mipsnbsd_regset_from_core_section);
362
 
363
  set_gdbarch_get_longjmp_target (gdbarch, mipsnbsd_get_longjmp_target);
364
 
365
  set_gdbarch_cannot_fetch_register (gdbarch, mipsnbsd_cannot_fetch_register);
366
  set_gdbarch_cannot_store_register (gdbarch, mipsnbsd_cannot_store_register);
367
 
368
  set_gdbarch_software_single_step (gdbarch, mips_software_single_step);
369
 
370
  /* NetBSD/mips has SVR4-style shared libraries.  */
371
  set_solib_svr4_fetch_link_map_offsets
372
    (gdbarch, (gdbarch_ptr_bit (gdbarch) == 32 ?
373
               mipsnbsd_ilp32_fetch_link_map_offsets :
374
               mipsnbsd_lp64_fetch_link_map_offsets));
375
}
376
 
377
 
378
/* Provide a prototype to silence -Wmissing-prototypes.  */
379
extern initialize_file_ftype _initialize_mipsnbsd_tdep;
380
 
381
void
382
_initialize_mipsnbsd_tdep (void)
383
{
384
  gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_NETBSD_ELF,
385
                          mipsnbsd_init_abi);
386
}

powered by: WebSVN 2.1.0

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