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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [gdb/] [mipsnbsd-tdep.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1181 sfurman
/* Target-dependent code for MIPS systems running NetBSD.
2
   Copyright 2002 Free Software Foundation, Inc.
3
   Contributed by Wasabi Systems, Inc.
4
 
5
   This file is part of GDB.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 2 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program; if not, write to the Free Software
19
   Foundation, Inc., 59 Temple Place - Suite 330,
20
   Boston, MA 02111-1307, USA.  */
21
 
22
#include "defs.h"
23
#include "gdbcore.h"
24
#include "regcache.h"
25
#include "target.h"
26
#include "value.h"
27
#include "osabi.h"
28
 
29
#include "nbsd-tdep.h"
30
#include "mipsnbsd-tdep.h"
31
 
32
#include "solib-svr4.h"
33
 
34
/* Conveniently, GDB uses the same register numbering as the
35
   ptrace register structure used by NetBSD/mips.  */
36
 
37
void
38
mipsnbsd_supply_reg (char *regs, int regno)
39
{
40
  int i;
41
 
42
  for (i = 0; i <= PC_REGNUM; i++)
43
    {
44
      if (regno == i || regno == -1)
45
        {
46
          if (CANNOT_FETCH_REGISTER (i))
47
            supply_register (i, NULL);
48
          else
49
            supply_register (i, regs + (i * MIPS_REGSIZE));
50
        }
51
    }
52
}
53
 
54
void
55
mipsnbsd_fill_reg (char *regs, int regno)
56
{
57
  int i;
58
 
59
  for (i = 0; i <= PC_REGNUM; i++)
60
    if ((regno == i || regno == -1) && ! CANNOT_STORE_REGISTER (i))
61
      regcache_collect (i, regs + (i * MIPS_REGSIZE));
62
}
63
 
64
void
65
mipsnbsd_supply_fpreg (char *fpregs, int regno)
66
{
67
  int i;
68
 
69
  for (i = FP0_REGNUM; i <= FCRIR_REGNUM; i++)
70
    {
71
      if (regno == i || regno == -1)
72
        {
73
          if (CANNOT_FETCH_REGISTER (i))
74
            supply_register (i, NULL);
75
          else
76
            supply_register (i, fpregs + ((i - FP0_REGNUM) * MIPS_REGSIZE));
77
        }
78
    }
79
}
80
 
81
void
82
mipsnbsd_fill_fpreg (char *fpregs, int regno)
83
{
84
  int i;
85
 
86
  for (i = FP0_REGNUM; i <= FCRCS_REGNUM; i++)
87
    if ((regno == i || regno == -1) && ! CANNOT_STORE_REGISTER (i))
88
      regcache_collect (i, fpregs + ((i - FP0_REGNUM) * MIPS_REGSIZE));
89
}
90
 
91
static void
92
fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
93
                      CORE_ADDR ignore)
94
{
95
  char *regs, *fpregs;
96
 
97
  /* We get everything from one section.  */
98
  if (which != 0)
99
    return;
100
 
101
  regs = core_reg_sect;
102
  fpregs = core_reg_sect + SIZEOF_STRUCT_REG;
103
 
104
  /* Integer registers.  */
105
  mipsnbsd_supply_reg (regs, -1);
106
 
107
  /* Floating point registers.  */
108
  mipsnbsd_supply_fpreg (regs, -1);
109
}
110
 
111
static void
112
fetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size, int which,
113
                         CORE_ADDR ignore)
114
{
115
  switch (which)
116
    {
117
    case 0:  /* Integer registers.  */
118
      if (core_reg_size != SIZEOF_STRUCT_REG)
119
        warning ("Wrong size register set in core file.");
120
      else
121
        mipsnbsd_supply_reg (core_reg_sect, -1);
122
      break;
123
 
124
    case 2:  /* Floating point registers.  */
125
      if (core_reg_size != SIZEOF_STRUCT_FPREG)
126
        warning ("Wrong size register set in core file.");
127
      else
128
        mipsnbsd_supply_fpreg (core_reg_sect, -1);
129
      break;
130
 
131
    default:
132
      /* Don't know what kind of register request this is; just ignore it.  */
133
      break;
134
    }
135
}
136
 
137
static struct core_fns mipsnbsd_core_fns =
138
{
139
  bfd_target_unknown_flavour,           /* core_flavour */
140
  default_check_format,                 /* check_format */
141
  default_core_sniffer,                 /* core_sniffer */
142
  fetch_core_registers,                 /* core_read_registers */
143
  NULL                                  /* next */
144
};
145
 
146
static struct core_fns mipsnbsd_elfcore_fns =
147
{
148
  bfd_target_elf_flavour,               /* core_flavour */
149
  default_check_format,                 /* check_format */
150
  default_core_sniffer,                 /* core_sniffer */
151
  fetch_elfcore_registers,              /* core_read_registers */
152
  NULL                                  /* next */
153
};
154
 
155
/* Under NetBSD/mips, signal handler invocations can be identified by the
156
   designated code sequence that is used to return from a signal handler.
157
   In particular, the return address of a signal handler points to the
158
   following code sequence:
159
 
160
        addu    a0, sp, 16
161
        li      v0, 295                 # __sigreturn14
162
        syscall
163
 
164
   Each instruction has a unique encoding, so we simply attempt to match
165
   the instruction the PC is pointing to with any of the above instructions.
166
   If there is a hit, we know the offset to the start of the designated
167
   sequence and can then check whether we really are executing in the
168
   signal trampoline.  If not, -1 is returned, otherwise the offset from the
169
   start of the return sequence is returned.  */
170
 
171
#define RETCODE_NWORDS  3
172
#define RETCODE_SIZE    (RETCODE_NWORDS * 4)
173
 
174
static const unsigned char sigtramp_retcode_mipsel[RETCODE_SIZE] =
175
{
176
  0x10, 0x00, 0xa4, 0x27,       /* addu a0, sp, 16 */
177
  0x27, 0x01, 0x02, 0x24,       /* li v0, 295 */
178
  0x0c, 0x00, 0x00, 0x00,       /* syscall */
179
};
180
 
181
static const unsigned char sigtramp_retcode_mipseb[RETCODE_SIZE] =
182
{
183
  0x27, 0xa4, 0x00, 0x10,       /* addu a0, sp, 16 */
184
  0x24, 0x02, 0x01, 0x27,       /* li v0, 295 */
185
  0x00, 0x00, 0x00, 0x0c,       /* syscall */
186
};
187
 
188
static LONGEST
189
mipsnbsd_sigtramp_offset (CORE_ADDR pc)
190
{
191
  const char *retcode = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
192
        ? sigtramp_retcode_mipseb : sigtramp_retcode_mipsel;
193
  unsigned char ret[RETCODE_SIZE], w[4];
194
  LONGEST off;
195
  int i;
196
 
197
  if (read_memory_nobpt (pc, (char *) w, sizeof (w)) != 0)
198
    return -1;
199
 
200
  for (i = 0; i < RETCODE_NWORDS; i++)
201
    {
202
      if (memcmp (w, retcode + (i * 4), 4) == 0)
203
        break;
204
    }
205
  if (i == RETCODE_NWORDS)
206
    return -1;
207
 
208
  off = i * 4;
209
  pc -= off;
210
 
211
  if (read_memory_nobpt (pc, (char *) ret, sizeof (ret)) != 0)
212
    return -1;
213
 
214
  if (memcmp (ret, retcode, RETCODE_SIZE) == 0)
215
    return off;
216
 
217
  return -1;
218
}
219
 
220
static int
221
mipsnbsd_pc_in_sigtramp (CORE_ADDR pc, char *func_name)
222
{
223
  return (nbsd_pc_in_sigtramp (pc, func_name)
224
          || mipsnbsd_sigtramp_offset (pc) >= 0);
225
}
226
 
227
/* Figure out where the longjmp will land.  We expect that we have
228
   just entered longjmp and haven't yet setup the stack frame, so
229
   the args are still in the argument regs.  A0_REGNUM points at the
230
   jmp_buf structure from which we extract the PC that we will land
231
   at.  The PC is copied into *pc.  This routine returns true on
232
   success.  */
233
 
234
#define NBSD_MIPS_JB_PC                 (2 * 4)
235
#define NBSD_MIPS_JB_ELEMENT_SIZE       MIPS_REGSIZE
236
#define NBSD_MIPS_JB_OFFSET             (NBSD_MIPS_JB_PC * \
237
                                         NBSD_MIPS_JB_ELEMENT_SIZE)
238
 
239
static int
240
mipsnbsd_get_longjmp_target (CORE_ADDR *pc)
241
{
242
  CORE_ADDR jb_addr;
243
  char *buf;
244
 
245
  buf = alloca (NBSD_MIPS_JB_ELEMENT_SIZE);
246
 
247
  jb_addr = read_register (A0_REGNUM);
248
 
249
  if (target_read_memory (jb_addr + NBSD_MIPS_JB_OFFSET, buf,
250
                          NBSD_MIPS_JB_ELEMENT_SIZE))
251
    return 0;
252
 
253
  *pc = extract_address (buf, NBSD_MIPS_JB_ELEMENT_SIZE);
254
 
255
  return 1;
256
}
257
 
258
static int
259
mipsnbsd_cannot_fetch_register (int regno)
260
{
261
  return (regno >= FP_REGNUM
262
          || regno == ZERO_REGNUM
263
          || regno == FCRIR_REGNUM);
264
}
265
 
266
static int
267
mipsnbsd_cannot_store_register (int regno)
268
{
269
  return (regno >= FP_REGNUM
270
          || regno == ZERO_REGNUM
271
          || regno == FCRIR_REGNUM);
272
}
273
 
274
/* NetBSD/mips uses a slightly different link_map structure from the
275
   other NetBSD platforms.  */
276
static struct link_map_offsets *
277
mipsnbsd_ilp32_solib_svr4_fetch_link_map_offsets (void)
278
{
279
  static struct link_map_offsets lmo;
280
  static struct link_map_offsets *lmp = NULL;
281
 
282
  if (lmp == NULL)
283
    {
284
      lmp = &lmo;
285
 
286
      lmo.r_debug_size = 16;
287
 
288
      lmo.r_map_offset = 4;
289
      lmo.r_map_size   = 4;
290
 
291
      lmo.link_map_size = 24;
292
 
293
      lmo.l_addr_offset = 0;
294
      lmo.l_addr_size   = 4;
295
 
296
      lmo.l_name_offset = 8;
297
      lmo.l_name_size   = 4;
298
 
299
      lmo.l_next_offset = 16;
300
      lmo.l_next_size   = 4;
301
 
302
      lmo.l_prev_offset = 20;
303
      lmo.l_prev_size   = 4;
304
    }
305
 
306
  return lmp;
307
}
308
 
309
static struct link_map_offsets *
310
mipsnbsd_lp64_solib_svr4_fetch_link_map_offsets (void)
311
{
312
  static struct link_map_offsets lmo;
313
  static struct link_map_offsets *lmp = NULL;
314
 
315
  if (lmp == NULL)
316
    {
317
      lmp = &lmo;
318
 
319
      lmo.r_debug_size = 32;
320
 
321
      lmo.r_map_offset = 8;
322
      lmo.r_map_size   = 8;
323
 
324
      lmo.link_map_size = 48;
325
 
326
      lmo.l_addr_offset = 0;
327
      lmo.l_addr_size   = 8;
328
 
329
      lmo.l_name_offset = 16;
330
      lmo.l_name_size   = 8;
331
 
332
      lmo.l_next_offset = 32;
333
      lmo.l_next_size   = 8;
334
 
335
      lmo.l_prev_offset = 40;
336
      lmo.l_prev_size   = 8;
337
    }
338
 
339
  return lmp;
340
}
341
 
342
static void
343
mipsnbsd_init_abi (struct gdbarch_info info,
344
                   struct gdbarch *gdbarch)
345
{
346
  set_gdbarch_pc_in_sigtramp (gdbarch, mipsnbsd_pc_in_sigtramp);
347
 
348
  set_gdbarch_get_longjmp_target (gdbarch, mipsnbsd_get_longjmp_target);
349
 
350
  set_gdbarch_cannot_fetch_register (gdbarch, mipsnbsd_cannot_fetch_register);
351
  set_gdbarch_cannot_store_register (gdbarch, mipsnbsd_cannot_store_register);
352
 
353
  set_gdbarch_software_single_step (gdbarch, mips_software_single_step);
354
 
355
  set_solib_svr4_fetch_link_map_offsets (gdbarch,
356
                                         gdbarch_ptr_bit (gdbarch) == 32 ?
357
                            mipsnbsd_ilp32_solib_svr4_fetch_link_map_offsets :
358
                            mipsnbsd_lp64_solib_svr4_fetch_link_map_offsets);
359
}
360
 
361
void
362
_initialize_mipsnbsd_tdep (void)
363
{
364
  gdbarch_register_osabi (bfd_arch_mips, GDB_OSABI_NETBSD_ELF,
365
                          mipsnbsd_init_abi);
366
 
367
  add_core_fns (&mipsnbsd_core_fns);
368
  add_core_fns (&mipsnbsd_elfcore_fns);
369
}

powered by: WebSVN 2.1.0

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