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

Subversion Repositories openrisc_me

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

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

Line No. Rev Author Line
1 24 jeremybenn
/* Target-dependent code for NetBSD/mips.
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 "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
static LONGEST
248
mipsnbsd_sigtramp_offset (struct frame_info *next_frame)
249
{
250
  CORE_ADDR pc = frame_pc_unwind (next_frame);
251
  const char *retcode = gdbarch_byte_order (get_frame_arch (next_frame))
252
                        == BFD_ENDIAN_BIG ? sigtramp_retcode_mipseb :
253
                        sigtramp_retcode_mipsel;
254
  unsigned char ret[RETCODE_SIZE], w[4];
255
  LONGEST off;
256
  int i;
257
 
258
  if (!safe_frame_unwind_memory (next_frame, pc, w, sizeof (w)))
259
    return -1;
260
 
261
  for (i = 0; i < RETCODE_NWORDS; i++)
262
    {
263
      if (memcmp (w, retcode + (i * 4), 4) == 0)
264
        break;
265
    }
266
  if (i == RETCODE_NWORDS)
267
    return -1;
268
 
269
  off = i * 4;
270
  pc -= off;
271
 
272
  if (!safe_frame_unwind_memory (next_frame, pc, ret, sizeof (ret)))
273
    return -1;
274
 
275
  if (memcmp (ret, retcode, RETCODE_SIZE) == 0)
276
    return off;
277
 
278
  return -1;
279
}
280
 
281
/* Figure out where the longjmp will land.  We expect that we have
282
   just entered longjmp and haven't yet setup the stack frame, so the
283
   args are still in the argument regs.  MIPS_A0_REGNUM points at the
284
   jmp_buf structure from which we extract the PC that we will land
285
   at.  The PC is copied into *pc.  This routine returns true on
286
   success.  */
287
 
288
#define NBSD_MIPS_JB_PC                 (2 * 4)
289
#define NBSD_MIPS_JB_ELEMENT_SIZE       mips_isa_regsize (current_gdbarch)
290
#define NBSD_MIPS_JB_OFFSET             (NBSD_MIPS_JB_PC * \
291
                                         NBSD_MIPS_JB_ELEMENT_SIZE)
292
 
293
static int
294
mipsnbsd_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
295
{
296
  CORE_ADDR jb_addr;
297
  char *buf;
298
 
299
  buf = alloca (NBSD_MIPS_JB_ELEMENT_SIZE);
300
 
301
  jb_addr = get_frame_register_unsigned (frame, MIPS_A0_REGNUM);
302
 
303
  if (target_read_memory (jb_addr + NBSD_MIPS_JB_OFFSET, buf,
304
                          NBSD_MIPS_JB_ELEMENT_SIZE))
305
    return 0;
306
 
307
  *pc = extract_unsigned_integer (buf, NBSD_MIPS_JB_ELEMENT_SIZE);
308
 
309
  return 1;
310
}
311
 
312
static int
313
mipsnbsd_cannot_fetch_register (struct gdbarch *gdbarch, int regno)
314
{
315
  return (regno == MIPS_ZERO_REGNUM
316
          || regno == mips_regnum (gdbarch)->fp_implementation_revision);
317
}
318
 
319
static int
320
mipsnbsd_cannot_store_register (struct gdbarch *gdbarch, int regno)
321
{
322
  return (regno == MIPS_ZERO_REGNUM
323
          || regno == mips_regnum (gdbarch)->fp_implementation_revision);
324
}
325
 
326
/* Shared library support.  */
327
 
328
/* NetBSD/mips uses a slightly different `struct link_map' than the
329
   other NetBSD platforms.  */
330
 
331
static struct link_map_offsets *
332
mipsnbsd_ilp32_fetch_link_map_offsets (void)
333
{
334
  static struct link_map_offsets lmo;
335
  static struct link_map_offsets *lmp = NULL;
336
 
337
  if (lmp == NULL)
338
    {
339
      lmp = &lmo;
340
 
341
      lmo.r_version_offset = 0;
342
      lmo.r_version_size = 4;
343
      lmo.r_map_offset = 4;
344
      lmo.r_brk_offset = 8;
345
      lmo.r_ldsomap_offset = -1;
346
 
347
      /* Everything we need is in the first 24 bytes.  */
348
      lmo.link_map_size = 24;
349
      lmo.l_addr_offset = 4;
350
      lmo.l_name_offset = 8;
351
      lmo.l_ld_offset = 12;
352
      lmo.l_next_offset = 16;
353
      lmo.l_prev_offset = 20;
354
    }
355
 
356
  return lmp;
357
}
358
 
359
static struct link_map_offsets *
360
mipsnbsd_lp64_fetch_link_map_offsets (void)
361
{
362
  static struct link_map_offsets lmo;
363
  static struct link_map_offsets *lmp = NULL;
364
 
365
  if (lmp == NULL)
366
    {
367
      lmp = &lmo;
368
 
369
      lmo.r_version_offset = 0;
370
      lmo.r_version_size = 4;
371
      lmo.r_map_offset = 8;
372
      lmo.r_brk_offset = 16;
373
      lmo.r_ldsomap_offset = -1;
374
 
375
      /* Everything we need is in the first 40 bytes.  */
376
      lmo.link_map_size = 48;
377
      lmo.l_addr_offset = 0;
378
      lmo.l_name_offset = 16;
379
      lmo.l_ld_offset = 24;
380
      lmo.l_next_offset = 32;
381
      lmo.l_prev_offset = 40;
382
    }
383
 
384
  return lmp;
385
}
386
 
387
 
388
static void
389
mipsnbsd_init_abi (struct gdbarch_info info,
390
                   struct gdbarch *gdbarch)
391
{
392
  set_gdbarch_regset_from_core_section
393
    (gdbarch, mipsnbsd_regset_from_core_section);
394
 
395
  set_gdbarch_get_longjmp_target (gdbarch, mipsnbsd_get_longjmp_target);
396
 
397
  set_gdbarch_cannot_fetch_register (gdbarch, mipsnbsd_cannot_fetch_register);
398
  set_gdbarch_cannot_store_register (gdbarch, mipsnbsd_cannot_store_register);
399
 
400
  set_gdbarch_software_single_step (gdbarch, mips_software_single_step);
401
 
402
  /* NetBSD/mips has SVR4-style shared libraries.  */
403
  set_solib_svr4_fetch_link_map_offsets
404
    (gdbarch, (gdbarch_ptr_bit (gdbarch) == 32 ?
405
               mipsnbsd_ilp32_fetch_link_map_offsets :
406
               mipsnbsd_lp64_fetch_link_map_offsets));
407
}
408
 
409
 
410
static enum gdb_osabi
411
mipsnbsd_core_osabi_sniffer (bfd *abfd)
412
{
413
  if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0)
414
    return GDB_OSABI_NETBSD_ELF;
415
 
416
  return GDB_OSABI_UNKNOWN;
417
}
418
 
419
void
420
_initialize_mipsnbsd_tdep (void)
421
{
422
  gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_NETBSD_ELF,
423
                          mipsnbsd_init_abi);
424
}

powered by: WebSVN 2.1.0

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