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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [gdb/] [gdbserver/] [linux-arm-low.c] - Blame information for rev 833

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

Line No. Rev Author Line
1 227 jeremybenn
/* GNU/Linux/ARM specific low level interface, for the remote server for GDB.
2
   Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3
   2006, 2007, 2008, 2009, 2010 Free Software Foundation, 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 3 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, see <http://www.gnu.org/licenses/>.  */
19
 
20
#include "server.h"
21
#include "linux-low.h"
22
 
23
/* Don't include elf.h if linux/elf.h got included by gdb_proc_service.h.
24
   On Bionic elf.h and linux/elf.h have conflicting definitions.  */
25
#ifndef ELFMAG0
26
#include <elf.h>
27
#endif
28
#include <sys/ptrace.h>
29
 
30
/* Defined in auto-generated files.  */
31
void init_registers_arm (void);
32
void init_registers_arm_with_iwmmxt (void);
33
void init_registers_arm_with_vfpv2 (void);
34
void init_registers_arm_with_vfpv3 (void);
35
void init_registers_arm_with_neon (void);
36
 
37
#ifndef PTRACE_GET_THREAD_AREA
38
#define PTRACE_GET_THREAD_AREA 22
39
#endif
40
 
41
#ifndef PTRACE_GETWMMXREGS
42
# define PTRACE_GETWMMXREGS 18
43
# define PTRACE_SETWMMXREGS 19
44
#endif
45
 
46
#ifndef PTRACE_GETVFPREGS
47
# define PTRACE_GETVFPREGS 27
48
# define PTRACE_SETVFPREGS 28
49
#endif
50
 
51
static unsigned long arm_hwcap;
52
 
53
/* These are in <asm/elf.h> in current kernels.  */
54
#define HWCAP_VFP       64
55
#define HWCAP_IWMMXT    512
56
#define HWCAP_NEON      4096
57
#define HWCAP_VFPv3     8192
58
#define HWCAP_VFPv3D16  16384
59
 
60
#ifdef HAVE_SYS_REG_H
61
#include <sys/reg.h>
62
#endif
63
 
64
#define arm_num_regs 26
65
 
66
static int arm_regmap[] = {
67
  0, 4, 8, 12, 16, 20, 24, 28,
68
  32, 36, 40, 44, 48, 52, 56, 60,
69
  -1, -1, -1, -1, -1, -1, -1, -1, -1,
70
  64
71
};
72
 
73
static int
74
arm_cannot_store_register (int regno)
75
{
76
  return (regno >= arm_num_regs);
77
}
78
 
79
static int
80
arm_cannot_fetch_register (int regno)
81
{
82
  return (regno >= arm_num_regs);
83
}
84
 
85
static void
86
arm_fill_gregset (struct regcache *regcache, void *buf)
87
{
88
  int i;
89
 
90
  for (i = 0; i < arm_num_regs; i++)
91
    if (arm_regmap[i] != -1)
92
      collect_register (regcache, i, ((char *) buf) + arm_regmap[i]);
93
}
94
 
95
static void
96
arm_store_gregset (struct regcache *regcache, const void *buf)
97
{
98
  int i;
99
  char zerobuf[8];
100
 
101
  memset (zerobuf, 0, 8);
102
  for (i = 0; i < arm_num_regs; i++)
103
    if (arm_regmap[i] != -1)
104
      supply_register (regcache, i, ((char *) buf) + arm_regmap[i]);
105
    else
106
      supply_register (regcache, i, zerobuf);
107
}
108
 
109
static void
110
arm_fill_wmmxregset (struct regcache *regcache, void *buf)
111
{
112
  int i;
113
 
114
  if (!(arm_hwcap & HWCAP_IWMMXT))
115
    return;
116
 
117
  for (i = 0; i < 16; i++)
118
    collect_register (regcache, arm_num_regs + i, (char *) buf + i * 8);
119
 
120
  /* We only have access to wcssf, wcasf, and wcgr0-wcgr3.  */
121
  for (i = 0; i < 6; i++)
122
    collect_register (regcache, arm_num_regs + i + 16,
123
                      (char *) buf + 16 * 8 + i * 4);
124
}
125
 
126
static void
127
arm_store_wmmxregset (struct regcache *regcache, const void *buf)
128
{
129
  int i;
130
 
131
  if (!(arm_hwcap & HWCAP_IWMMXT))
132
    return;
133
 
134
  for (i = 0; i < 16; i++)
135
    supply_register (regcache, arm_num_regs + i, (char *) buf + i * 8);
136
 
137
  /* We only have access to wcssf, wcasf, and wcgr0-wcgr3.  */
138
  for (i = 0; i < 6; i++)
139
    supply_register (regcache, arm_num_regs + i + 16,
140
                     (char *) buf + 16 * 8 + i * 4);
141
}
142
 
143
static void
144
arm_fill_vfpregset (struct regcache *regcache, void *buf)
145
{
146
  int i, num, base;
147
 
148
  if (!(arm_hwcap & HWCAP_VFP))
149
    return;
150
 
151
  if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
152
    num = 32;
153
  else
154
    num = 16;
155
 
156
  base = find_regno ("d0");
157
  for (i = 0; i < num; i++)
158
    collect_register (regcache, base + i, (char *) buf + i * 8);
159
 
160
  collect_register_by_name (regcache, "fpscr", (char *) buf + 32 * 8);
161
}
162
 
163
static void
164
arm_store_vfpregset (struct regcache *regcache, const void *buf)
165
{
166
  int i, num, base;
167
 
168
  if (!(arm_hwcap & HWCAP_VFP))
169
    return;
170
 
171
  if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
172
    num = 32;
173
  else
174
    num = 16;
175
 
176
  base = find_regno ("d0");
177
  for (i = 0; i < num; i++)
178
    supply_register (regcache, base + i, (char *) buf + i * 8);
179
 
180
  supply_register_by_name (regcache, "fpscr", (char *) buf + 32 * 8);
181
}
182
 
183
extern int debug_threads;
184
 
185
static CORE_ADDR
186
arm_get_pc (struct regcache *regcache)
187
{
188
  unsigned long pc;
189
  collect_register_by_name (regcache, "pc", &pc);
190
  if (debug_threads)
191
    fprintf (stderr, "stop pc is %08lx\n", pc);
192
  return pc;
193
}
194
 
195
static void
196
arm_set_pc (struct regcache *regcache, CORE_ADDR pc)
197
{
198
  unsigned long newpc = pc;
199
  supply_register_by_name (regcache, "pc", &newpc);
200
}
201
 
202
/* Correct in either endianness.  */
203
static const unsigned long arm_breakpoint = 0xef9f0001;
204
#define arm_breakpoint_len 4
205
static const unsigned short thumb_breakpoint = 0xde01;
206
static const unsigned short thumb2_breakpoint[] = { 0xf7f0, 0xa000 };
207
 
208
/* For new EABI binaries.  We recognize it regardless of which ABI
209
   is used for gdbserver, so single threaded debugging should work
210
   OK, but for multi-threaded debugging we only insert the current
211
   ABI's breakpoint instruction.  For now at least.  */
212
static const unsigned long arm_eabi_breakpoint = 0xe7f001f0;
213
 
214
static int
215
arm_breakpoint_at (CORE_ADDR where)
216
{
217
  struct regcache *regcache = get_thread_regcache (current_inferior, 1);
218
  unsigned long cpsr;
219
 
220
  collect_register_by_name (regcache, "cpsr", &cpsr);
221
 
222
  if (cpsr & 0x20)
223
    {
224
      /* Thumb mode.  */
225
      unsigned short insn;
226
 
227
      (*the_target->read_memory) (where, (unsigned char *) &insn, 2);
228
      if (insn == thumb_breakpoint)
229
        return 1;
230
 
231
      if (insn == thumb2_breakpoint[0])
232
        {
233
          (*the_target->read_memory) (where + 2, (unsigned char *) &insn, 2);
234
          if (insn == thumb2_breakpoint[1])
235
            return 1;
236
        }
237
    }
238
  else
239
    {
240
      /* ARM mode.  */
241
      unsigned long insn;
242
 
243
      (*the_target->read_memory) (where, (unsigned char *) &insn, 4);
244
      if (insn == arm_breakpoint)
245
        return 1;
246
 
247
      if (insn == arm_eabi_breakpoint)
248
        return 1;
249
    }
250
 
251
  return 0;
252
}
253
 
254
/* We only place breakpoints in empty marker functions, and thread locking
255
   is outside of the function.  So rather than importing software single-step,
256
   we can just run until exit.  */
257
static CORE_ADDR
258
arm_reinsert_addr (void)
259
{
260
  struct regcache *regcache = get_thread_regcache (current_inferior, 1);
261
  unsigned long pc;
262
  collect_register_by_name (regcache, "lr", &pc);
263
  return pc;
264
}
265
 
266
/* Fetch the thread-local storage pointer for libthread_db.  */
267
 
268
ps_err_e
269
ps_get_thread_area (const struct ps_prochandle *ph,
270
                    lwpid_t lwpid, int idx, void **base)
271
{
272
  if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
273
    return PS_ERR;
274
 
275
  /* IDX is the bias from the thread pointer to the beginning of the
276
     thread descriptor.  It has to be subtracted due to implementation
277
     quirks in libthread_db.  */
278
  *base = (void *) ((char *)*base - idx);
279
 
280
  return PS_OK;
281
}
282
 
283
static int
284
arm_get_hwcap (unsigned long *valp)
285
{
286
  unsigned char *data = alloca (8);
287
  int offset = 0;
288
 
289
  while ((*the_target->read_auxv) (offset, data, 8) == 8)
290
    {
291
      unsigned int *data_p = (unsigned int *)data;
292
      if (data_p[0] == AT_HWCAP)
293
        {
294
          *valp = data_p[1];
295
          return 1;
296
        }
297
 
298
      offset += 8;
299
    }
300
 
301
  *valp = 0;
302
  return 0;
303
}
304
 
305
static void
306
arm_arch_setup (void)
307
{
308
  arm_hwcap = 0;
309
  if (arm_get_hwcap (&arm_hwcap) == 0)
310
    {
311
      init_registers_arm ();
312
      return;
313
    }
314
 
315
  if (arm_hwcap & HWCAP_IWMMXT)
316
    {
317
      init_registers_arm_with_iwmmxt ();
318
      return;
319
    }
320
 
321
  if (arm_hwcap & HWCAP_VFP)
322
    {
323
      int pid;
324
      char *buf;
325
 
326
      /* NEON implies either no VFP, or VFPv3-D32.  We only support
327
         it with VFP.  */
328
      if (arm_hwcap & HWCAP_NEON)
329
        init_registers_arm_with_neon ();
330
      else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
331
        init_registers_arm_with_vfpv3 ();
332
      else
333
        init_registers_arm_with_vfpv2 ();
334
 
335
      /* Now make sure that the kernel supports reading these
336
         registers.  Support was added in 2.6.30.  */
337
      pid = lwpid_of (get_thread_lwp (current_inferior));
338
      errno = 0;
339
      buf = malloc (32 * 8 + 4);
340
      if (ptrace (PTRACE_GETVFPREGS, pid, 0, buf) < 0
341
          && errno == EIO)
342
        {
343
          arm_hwcap = 0;
344
          init_registers_arm ();
345
        }
346
      free (buf);
347
 
348
      return;
349
    }
350
 
351
  /* The default configuration uses legacy FPA registers, probably
352
     simulated.  */
353
  init_registers_arm ();
354
}
355
 
356
struct regset_info target_regsets[] = {
357
  { PTRACE_GETREGS, PTRACE_SETREGS, 18 * 4,
358
    GENERAL_REGS,
359
    arm_fill_gregset, arm_store_gregset },
360
  { PTRACE_GETWMMXREGS, PTRACE_SETWMMXREGS, 16 * 8 + 6 * 4,
361
    EXTENDED_REGS,
362
    arm_fill_wmmxregset, arm_store_wmmxregset },
363
  { PTRACE_GETVFPREGS, PTRACE_SETVFPREGS, 32 * 8 + 4,
364
    EXTENDED_REGS,
365
    arm_fill_vfpregset, arm_store_vfpregset },
366
  { 0, 0, -1, -1, NULL, NULL }
367
};
368
 
369
struct linux_target_ops the_low_target = {
370
  arm_arch_setup,
371
  arm_num_regs,
372
  arm_regmap,
373
  arm_cannot_fetch_register,
374
  arm_cannot_store_register,
375
  arm_get_pc,
376
  arm_set_pc,
377
 
378
  /* Define an ARM-mode breakpoint; we only set breakpoints in the C
379
     library, which is most likely to be ARM.  If the kernel supports
380
     clone events, we will never insert a breakpoint, so even a Thumb
381
     C library will work; so will mixing EABI/non-EABI gdbserver and
382
     application.  */
383
#ifndef __ARM_EABI__
384
  (const unsigned char *) &arm_breakpoint,
385
#else
386
  (const unsigned char *) &arm_eabi_breakpoint,
387
#endif
388
  arm_breakpoint_len,
389
  arm_reinsert_addr,
390
  0,
391
  arm_breakpoint_at,
392
};

powered by: WebSVN 2.1.0

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