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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [gdb/] [mips-linux-nat.c] - Blame information for rev 294

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

Line No. Rev Author Line
1 24 jeremybenn
/* Native-dependent code for GNU/Linux on MIPS processors.
2
 
3
   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
4
   Free Software Foundation, Inc.
5
 
6
   This file is part of GDB.
7
 
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
 
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
 
21
#include "defs.h"
22
#include "inferior.h"
23
#include "mips-tdep.h"
24
#include "target.h"
25
#include "regcache.h"
26
#include "linux-nat.h"
27
#include "mips-linux-tdep.h"
28
#include "target-descriptions.h"
29
 
30
#include "gdb_proc_service.h"
31
#include "gregset.h"
32
 
33
#include <sgidefs.h>
34
#include <sys/ptrace.h>
35
 
36
#include "features/mips-linux.c"
37
#include "features/mips64-linux.c"
38
 
39
#ifndef PTRACE_GET_THREAD_AREA
40
#define PTRACE_GET_THREAD_AREA 25
41
#endif
42
 
43
/* Assume that we have PTRACE_GETREGS et al. support.  If we do not,
44
   we'll clear this and use PTRACE_PEEKUSER instead.  */
45
static int have_ptrace_regsets = 1;
46
 
47
/* Saved function pointers to fetch and store a single register using
48
   PTRACE_PEEKUSER and PTRACE_POKEUSER.  */
49
 
50
void (*super_fetch_registers) (struct regcache *, int);
51
void (*super_store_registers) (struct regcache *, int);
52
 
53
/* Map gdb internal register number to ptrace ``address''.
54
   These ``addresses'' are normally defined in <asm/ptrace.h>.
55
 
56
   ptrace does not provide a way to read (or set) MIPS_PS_REGNUM,
57
   and there's no point in reading or setting MIPS_ZERO_REGNUM.
58
   We also can not set BADVADDR, CAUSE, or FCRIR via ptrace().  */
59
 
60
static CORE_ADDR
61
mips_linux_register_addr (struct gdbarch *gdbarch, int regno, int store)
62
{
63
  CORE_ADDR regaddr;
64
 
65
  if (regno < 0 || regno >= gdbarch_num_regs (gdbarch))
66
    error (_("Bogon register number %d."), regno);
67
 
68
  if (regno > MIPS_ZERO_REGNUM && regno < MIPS_ZERO_REGNUM + 32)
69
    regaddr = regno;
70
  else if ((regno >= mips_regnum (gdbarch)->fp0)
71
           && (regno < mips_regnum (gdbarch)->fp0 + 32))
72
    regaddr = FPR_BASE + (regno - mips_regnum (gdbarch)->fp0);
73
  else if (regno == mips_regnum (gdbarch)->pc)
74
    regaddr = PC;
75
  else if (regno == mips_regnum (gdbarch)->cause)
76
    regaddr = store? (CORE_ADDR) -1 : CAUSE;
77
  else if (regno == mips_regnum (gdbarch)->badvaddr)
78
    regaddr = store? (CORE_ADDR) -1 : BADVADDR;
79
  else if (regno == mips_regnum (gdbarch)->lo)
80
    regaddr = MMLO;
81
  else if (regno == mips_regnum (gdbarch)->hi)
82
    regaddr = MMHI;
83
  else if (regno == mips_regnum (gdbarch)->fp_control_status)
84
    regaddr = FPC_CSR;
85
  else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
86
    regaddr = store? (CORE_ADDR) -1 : FPC_EIR;
87
  else if (mips_linux_restart_reg_p (gdbarch) && regno == MIPS_RESTART_REGNUM)
88
    regaddr = 0;
89
  else
90
    regaddr = (CORE_ADDR) -1;
91
 
92
  return regaddr;
93
}
94
 
95
static CORE_ADDR
96
mips64_linux_register_addr (struct gdbarch *gdbarch, int regno, int store)
97
{
98
  CORE_ADDR regaddr;
99
 
100
  if (regno < 0 || regno >= gdbarch_num_regs (gdbarch))
101
    error (_("Bogon register number %d."), regno);
102
 
103
  if (regno > MIPS_ZERO_REGNUM && regno < MIPS_ZERO_REGNUM + 32)
104
    regaddr = regno;
105
  else if ((regno >= mips_regnum (gdbarch)->fp0)
106
           && (regno < mips_regnum (gdbarch)->fp0 + 32))
107
    regaddr = MIPS64_FPR_BASE + (regno - gdbarch_fp0_regnum (gdbarch));
108
  else if (regno == mips_regnum (gdbarch)->pc)
109
    regaddr = MIPS64_PC;
110
  else if (regno == mips_regnum (gdbarch)->cause)
111
    regaddr = store? (CORE_ADDR) -1 : MIPS64_CAUSE;
112
  else if (regno == mips_regnum (gdbarch)->badvaddr)
113
    regaddr = store? (CORE_ADDR) -1 : MIPS64_BADVADDR;
114
  else if (regno == mips_regnum (gdbarch)->lo)
115
    regaddr = MIPS64_MMLO;
116
  else if (regno == mips_regnum (gdbarch)->hi)
117
    regaddr = MIPS64_MMHI;
118
  else if (regno == mips_regnum (gdbarch)->fp_control_status)
119
    regaddr = MIPS64_FPC_CSR;
120
  else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
121
    regaddr = store? (CORE_ADDR) -1 : MIPS64_FPC_EIR;
122
  else if (mips_linux_restart_reg_p (gdbarch) && regno == MIPS_RESTART_REGNUM)
123
    regaddr = 0;
124
  else
125
    regaddr = (CORE_ADDR) -1;
126
 
127
  return regaddr;
128
}
129
 
130
/* Fetch the thread-local storage pointer for libthread_db.  */
131
 
132
ps_err_e
133
ps_get_thread_area (const struct ps_prochandle *ph,
134
                    lwpid_t lwpid, int idx, void **base)
135
{
136
  if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
137
    return PS_ERR;
138
 
139
  /* IDX is the bias from the thread pointer to the beginning of the
140
     thread descriptor.  It has to be subtracted due to implementation
141
     quirks in libthread_db.  */
142
  *base = (void *) ((char *)*base - idx);
143
 
144
  return PS_OK;
145
}
146
 
147
/* Wrapper functions.  These are only used by libthread_db.  */
148
 
149
void
150
supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
151
{
152
  if (mips_isa_regsize (get_regcache_arch (regcache)) == 4)
153
    mips_supply_gregset (regcache, (const mips_elf_gregset_t *) gregsetp);
154
  else
155
    mips64_supply_gregset (regcache, (const mips64_elf_gregset_t *) gregsetp);
156
}
157
 
158
void
159
fill_gregset (const struct regcache *regcache,
160
              gdb_gregset_t *gregsetp, int regno)
161
{
162
  if (mips_isa_regsize (get_regcache_arch (regcache)) == 4)
163
    mips_fill_gregset (regcache, (mips_elf_gregset_t *) gregsetp, regno);
164
  else
165
    mips64_fill_gregset (regcache, (mips64_elf_gregset_t *) gregsetp, regno);
166
}
167
 
168
void
169
supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
170
{
171
  if (mips_isa_regsize (get_regcache_arch (regcache)) == 4)
172
    mips_supply_fpregset (regcache, (const mips_elf_fpregset_t *) fpregsetp);
173
  else
174
    mips64_supply_fpregset (regcache, (const mips64_elf_fpregset_t *) fpregsetp);
175
}
176
 
177
void
178
fill_fpregset (const struct regcache *regcache,
179
               gdb_fpregset_t *fpregsetp, int regno)
180
{
181
  if (mips_isa_regsize (get_regcache_arch (regcache)) == 4)
182
    mips_fill_fpregset (regcache, (mips_elf_fpregset_t *) fpregsetp, regno);
183
  else
184
    mips64_fill_fpregset (regcache, (mips64_elf_fpregset_t *) fpregsetp, regno);
185
}
186
 
187
 
188
/* Fetch REGNO (or all registers if REGNO == -1) from the target
189
   using PTRACE_GETREGS et al.  */
190
 
191
static void
192
mips64_linux_regsets_fetch_registers (struct regcache *regcache, int regno)
193
{
194
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
195
  int is_fp;
196
  int tid;
197
 
198
  if (regno >= mips_regnum (gdbarch)->fp0
199
      && regno <= mips_regnum (gdbarch)->fp0 + 32)
200
    is_fp = 1;
201
  else if (regno == mips_regnum (gdbarch)->fp_control_status)
202
    is_fp = 1;
203
  else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
204
    is_fp = 1;
205
  else
206
    is_fp = 0;
207
 
208
  tid = ptid_get_lwp (inferior_ptid);
209
  if (tid == 0)
210
    tid = ptid_get_pid (inferior_ptid);
211
 
212
  if (regno == -1 || !is_fp)
213
    {
214
      mips64_elf_gregset_t regs;
215
 
216
      if (ptrace (PTRACE_GETREGS, tid, 0L, (PTRACE_TYPE_ARG3) &regs) == -1)
217
        {
218
          if (errno == EIO)
219
            {
220
              have_ptrace_regsets = 0;
221
              return;
222
            }
223
          perror_with_name (_("Couldn't get registers"));
224
        }
225
 
226
      mips64_supply_gregset (regcache,
227
                             (const mips64_elf_gregset_t *) &regs);
228
    }
229
 
230
  if (regno == -1 || is_fp)
231
    {
232
      mips64_elf_fpregset_t fp_regs;
233
 
234
      if (ptrace (PTRACE_GETFPREGS, tid, 0L,
235
                  (PTRACE_TYPE_ARG3) &fp_regs) == -1)
236
        {
237
          if (errno == EIO)
238
            {
239
              have_ptrace_regsets = 0;
240
              return;
241
            }
242
          perror_with_name (_("Couldn't get FP registers"));
243
        }
244
 
245
      mips64_supply_fpregset (regcache,
246
                              (const mips64_elf_fpregset_t *) &fp_regs);
247
    }
248
}
249
 
250
/* Store REGNO (or all registers if REGNO == -1) to the target
251
   using PTRACE_SETREGS et al.  */
252
 
253
static void
254
mips64_linux_regsets_store_registers (const struct regcache *regcache, int regno)
255
{
256
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
257
  int is_fp;
258
  int tid;
259
 
260
  if (regno >= mips_regnum (gdbarch)->fp0
261
      && regno <= mips_regnum (gdbarch)->fp0 + 32)
262
    is_fp = 1;
263
  else if (regno == mips_regnum (gdbarch)->fp_control_status)
264
    is_fp = 1;
265
  else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
266
    is_fp = 1;
267
  else
268
    is_fp = 0;
269
 
270
  tid = ptid_get_lwp (inferior_ptid);
271
  if (tid == 0)
272
    tid = ptid_get_pid (inferior_ptid);
273
 
274
  if (regno == -1 || !is_fp)
275
    {
276
      mips64_elf_gregset_t regs;
277
 
278
      if (ptrace (PTRACE_GETREGS, tid, 0L, (PTRACE_TYPE_ARG3) &regs) == -1)
279
        perror_with_name (_("Couldn't get registers"));
280
 
281
      mips64_fill_gregset (regcache, &regs, regno);
282
 
283
      if (ptrace (PTRACE_SETREGS, tid, 0L, (PTRACE_TYPE_ARG3) &regs) == -1)
284
        perror_with_name (_("Couldn't set registers"));
285
    }
286
 
287
  if (regno == -1 || is_fp)
288
    {
289
      mips64_elf_fpregset_t fp_regs;
290
 
291
      if (ptrace (PTRACE_GETFPREGS, tid, 0L,
292
                  (PTRACE_TYPE_ARG3) &fp_regs) == -1)
293
        perror_with_name (_("Couldn't get FP registers"));
294
 
295
      mips64_fill_fpregset (regcache, &fp_regs, regno);
296
 
297
      if (ptrace (PTRACE_SETFPREGS, tid, 0L,
298
                  (PTRACE_TYPE_ARG3) &fp_regs) == -1)
299
        perror_with_name (_("Couldn't set FP registers"));
300
    }
301
}
302
 
303
/* Fetch REGNO (or all registers if REGNO == -1) from the target
304
   using any working method.  */
305
 
306
static void
307
mips64_linux_fetch_registers (struct regcache *regcache, int regnum)
308
{
309
  /* Unless we already know that PTRACE_GETREGS does not work, try it.  */
310
  if (have_ptrace_regsets)
311
    mips64_linux_regsets_fetch_registers (regcache, regnum);
312
 
313
  /* If we know, or just found out, that PTRACE_GETREGS does not work, fall
314
     back to PTRACE_PEEKUSER.  */
315
  if (!have_ptrace_regsets)
316
    super_fetch_registers (regcache, regnum);
317
}
318
 
319
/* Store REGNO (or all registers if REGNO == -1) to the target
320
   using any working method.  */
321
 
322
static void
323
mips64_linux_store_registers (struct regcache *regcache, int regnum)
324
{
325
  /* Unless we already know that PTRACE_GETREGS does not work, try it.  */
326
  if (have_ptrace_regsets)
327
    mips64_linux_regsets_store_registers (regcache, regnum);
328
 
329
  /* If we know, or just found out, that PTRACE_GETREGS does not work, fall
330
     back to PTRACE_PEEKUSER.  */
331
  if (!have_ptrace_regsets)
332
    super_store_registers (regcache, regnum);
333
}
334
 
335
/* Return the address in the core dump or inferior of register
336
   REGNO.  */
337
 
338
static CORE_ADDR
339
mips_linux_register_u_offset (struct gdbarch *gdbarch, int regno, int store_p)
340
{
341
  if (mips_abi_regsize (gdbarch) == 8)
342
    return mips64_linux_register_addr (gdbarch, regno, store_p);
343
  else
344
    return mips_linux_register_addr (gdbarch, regno, store_p);
345
}
346
 
347
static const struct target_desc *
348
mips_linux_read_description (struct target_ops *ops)
349
{
350
  /* Report that target registers are a size we know for sure
351
     that we can get from ptrace.  */
352
  if (_MIPS_SIM == _ABIO32)
353
    return tdesc_mips_linux;
354
  else
355
    return tdesc_mips64_linux;
356
}
357
 
358
void _initialize_mips_linux_nat (void);
359
 
360
void
361
_initialize_mips_linux_nat (void)
362
{
363
  struct target_ops *t = linux_trad_target (mips_linux_register_u_offset);
364
 
365
  super_fetch_registers = t->to_fetch_registers;
366
  super_store_registers = t->to_store_registers;
367
 
368
  t->to_fetch_registers = mips64_linux_fetch_registers;
369
  t->to_store_registers = mips64_linux_store_registers;
370
 
371
  t->to_read_description = mips_linux_read_description;
372
 
373
  linux_nat_add_target (t);
374
 
375
  /* Initialize the standard target descriptions.  */
376
  initialize_tdesc_mips_linux ();
377
  initialize_tdesc_mips64_linux ();
378
}

powered by: WebSVN 2.1.0

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