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

Subversion Repositories openrisc_me

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 227 jeremybenn
/* GNU/Linux on ARM target support.
2
 
3
   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
4
   2009, 2010 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 "target.h"
23
#include "value.h"
24
#include "gdbtypes.h"
25
#include "floatformat.h"
26
#include "gdbcore.h"
27
#include "frame.h"
28
#include "regcache.h"
29
#include "doublest.h"
30
#include "solib-svr4.h"
31
#include "osabi.h"
32
#include "regset.h"
33
#include "trad-frame.h"
34
#include "tramp-frame.h"
35
#include "breakpoint.h"
36
 
37
#include "arm-tdep.h"
38
#include "arm-linux-tdep.h"
39
#include "linux-tdep.h"
40
#include "glibc-tdep.h"
41
#include "arch-utils.h"
42
#include "inferior.h"
43
#include "gdbthread.h"
44
#include "symfile.h"
45
 
46
#include "gdb_string.h"
47
 
48
extern int arm_apcs_32;
49
 
50
/* Under ARM GNU/Linux the traditional way of performing a breakpoint
51
   is to execute a particular software interrupt, rather than use a
52
   particular undefined instruction to provoke a trap.  Upon exection
53
   of the software interrupt the kernel stops the inferior with a
54
   SIGTRAP, and wakes the debugger.  */
55
 
56
static const char arm_linux_arm_le_breakpoint[] = { 0x01, 0x00, 0x9f, 0xef };
57
 
58
static const char arm_linux_arm_be_breakpoint[] = { 0xef, 0x9f, 0x00, 0x01 };
59
 
60
/* However, the EABI syscall interface (new in Nov. 2005) does not look at
61
   the operand of the swi if old-ABI compatibility is disabled.  Therefore,
62
   use an undefined instruction instead.  This is supported as of kernel
63
   version 2.5.70 (May 2003), so should be a safe assumption for EABI
64
   binaries.  */
65
 
66
static const char eabi_linux_arm_le_breakpoint[] = { 0xf0, 0x01, 0xf0, 0xe7 };
67
 
68
static const char eabi_linux_arm_be_breakpoint[] = { 0xe7, 0xf0, 0x01, 0xf0 };
69
 
70
/* All the kernels which support Thumb support using a specific undefined
71
   instruction for the Thumb breakpoint.  */
72
 
73
static const char arm_linux_thumb_be_breakpoint[] = {0xde, 0x01};
74
 
75
static const char arm_linux_thumb_le_breakpoint[] = {0x01, 0xde};
76
 
77
/* Because the 16-bit Thumb breakpoint is affected by Thumb-2 IT blocks,
78
   we must use a length-appropriate breakpoint for 32-bit Thumb
79
   instructions.  See also thumb_get_next_pc.  */
80
 
81
static const char arm_linux_thumb2_be_breakpoint[] = { 0xf7, 0xf0, 0xa0, 0x00 };
82
 
83
static const char arm_linux_thumb2_le_breakpoint[] = { 0xf0, 0xf7, 0x00, 0xa0 };
84
 
85
/* Description of the longjmp buffer.  */
86
#define ARM_LINUX_JB_ELEMENT_SIZE       INT_REGISTER_SIZE
87
#define ARM_LINUX_JB_PC                 21
88
 
89
/*
90
   Dynamic Linking on ARM GNU/Linux
91
   --------------------------------
92
 
93
   Note: PLT = procedure linkage table
94
   GOT = global offset table
95
 
96
   As much as possible, ELF dynamic linking defers the resolution of
97
   jump/call addresses until the last minute. The technique used is
98
   inspired by the i386 ELF design, and is based on the following
99
   constraints.
100
 
101
   1) The calling technique should not force a change in the assembly
102
   code produced for apps; it MAY cause changes in the way assembly
103
   code is produced for position independent code (i.e. shared
104
   libraries).
105
 
106
   2) The technique must be such that all executable areas must not be
107
   modified; and any modified areas must not be executed.
108
 
109
   To do this, there are three steps involved in a typical jump:
110
 
111
   1) in the code
112
   2) through the PLT
113
   3) using a pointer from the GOT
114
 
115
   When the executable or library is first loaded, each GOT entry is
116
   initialized to point to the code which implements dynamic name
117
   resolution and code finding.  This is normally a function in the
118
   program interpreter (on ARM GNU/Linux this is usually
119
   ld-linux.so.2, but it does not have to be).  On the first
120
   invocation, the function is located and the GOT entry is replaced
121
   with the real function address.  Subsequent calls go through steps
122
   1, 2 and 3 and end up calling the real code.
123
 
124
   1) In the code:
125
 
126
   b    function_call
127
   bl   function_call
128
 
129
   This is typical ARM code using the 26 bit relative branch or branch
130
   and link instructions.  The target of the instruction
131
   (function_call is usually the address of the function to be called.
132
   In position independent code, the target of the instruction is
133
   actually an entry in the PLT when calling functions in a shared
134
   library.  Note that this call is identical to a normal function
135
   call, only the target differs.
136
 
137
   2) In the PLT:
138
 
139
   The PLT is a synthetic area, created by the linker. It exists in
140
   both executables and libraries. It is an array of stubs, one per
141
   imported function call. It looks like this:
142
 
143
   PLT[0]:
144
   str     lr, [sp, #-4]!       @push the return address (lr)
145
   ldr     lr, [pc, #16]   @load from 6 words ahead
146
   add     lr, pc, lr      @form an address for GOT[0]
147
   ldr     pc, [lr, #8]!   @jump to the contents of that addr
148
 
149
   The return address (lr) is pushed on the stack and used for
150
   calculations.  The load on the second line loads the lr with
151
   &GOT[3] - . - 20.  The addition on the third leaves:
152
 
153
   lr = (&GOT[3] - . - 20) + (. + 8)
154
   lr = (&GOT[3] - 12)
155
   lr = &GOT[0]
156
 
157
   On the fourth line, the pc and lr are both updated, so that:
158
 
159
   pc = GOT[2]
160
   lr = &GOT[0] + 8
161
   = &GOT[2]
162
 
163
   NOTE: PLT[0] borrows an offset .word from PLT[1]. This is a little
164
   "tight", but allows us to keep all the PLT entries the same size.
165
 
166
   PLT[n+1]:
167
   ldr     ip, [pc, #4]    @load offset from gotoff
168
   add     ip, pc, ip      @add the offset to the pc
169
   ldr     pc, [ip]        @jump to that address
170
   gotoff: .word   GOT[n+3] - .
171
 
172
   The load on the first line, gets an offset from the fourth word of
173
   the PLT entry.  The add on the second line makes ip = &GOT[n+3],
174
   which contains either a pointer to PLT[0] (the fixup trampoline) or
175
   a pointer to the actual code.
176
 
177
   3) In the GOT:
178
 
179
   The GOT contains helper pointers for both code (PLT) fixups and
180
   data fixups.  The first 3 entries of the GOT are special. The next
181
   M entries (where M is the number of entries in the PLT) belong to
182
   the PLT fixups. The next D (all remaining) entries belong to
183
   various data fixups. The actual size of the GOT is 3 + M + D.
184
 
185
   The GOT is also a synthetic area, created by the linker. It exists
186
   in both executables and libraries.  When the GOT is first
187
   initialized , all the GOT entries relating to PLT fixups are
188
   pointing to code back at PLT[0].
189
 
190
   The special entries in the GOT are:
191
 
192
   GOT[0] = linked list pointer used by the dynamic loader
193
   GOT[1] = pointer to the reloc table for this module
194
   GOT[2] = pointer to the fixup/resolver code
195
 
196
   The first invocation of function call comes through and uses the
197
   fixup/resolver code.  On the entry to the fixup/resolver code:
198
 
199
   ip = &GOT[n+3]
200
   lr = &GOT[2]
201
   stack[0] = return address (lr) of the function call
202
   [r0, r1, r2, r3] are still the arguments to the function call
203
 
204
   This is enough information for the fixup/resolver code to work
205
   with.  Before the fixup/resolver code returns, it actually calls
206
   the requested function and repairs &GOT[n+3].  */
207
 
208
/* The constants below were determined by examining the following files
209
   in the linux kernel sources:
210
 
211
      arch/arm/kernel/signal.c
212
          - see SWI_SYS_SIGRETURN and SWI_SYS_RT_SIGRETURN
213
      include/asm-arm/unistd.h
214
          - see __NR_sigreturn, __NR_rt_sigreturn, and __NR_SYSCALL_BASE */
215
 
216
#define ARM_LINUX_SIGRETURN_INSTR       0xef900077
217
#define ARM_LINUX_RT_SIGRETURN_INSTR    0xef9000ad
218
 
219
/* For ARM EABI, the syscall number is not in the SWI instruction
220
   (instead it is loaded into r7).  We recognize the pattern that
221
   glibc uses...  alternatively, we could arrange to do this by
222
   function name, but they are not always exported.  */
223
#define ARM_SET_R7_SIGRETURN            0xe3a07077
224
#define ARM_SET_R7_RT_SIGRETURN         0xe3a070ad
225
#define ARM_EABI_SYSCALL                0xef000000
226
 
227
/* OABI syscall restart trampoline, used for EABI executables too
228
   whenever OABI support has been enabled in the kernel.  */
229
#define ARM_OABI_SYSCALL_RESTART_SYSCALL 0xef900000
230
#define ARM_LDR_PC_SP_12                0xe49df00c
231
 
232
static void
233
arm_linux_sigtramp_cache (struct frame_info *this_frame,
234
                          struct trad_frame_cache *this_cache,
235
                          CORE_ADDR func, int regs_offset)
236
{
237
  CORE_ADDR sp = get_frame_register_unsigned (this_frame, ARM_SP_REGNUM);
238
  CORE_ADDR base = sp + regs_offset;
239
  int i;
240
 
241
  for (i = 0; i < 16; i++)
242
    trad_frame_set_reg_addr (this_cache, i, base + i * 4);
243
 
244
  trad_frame_set_reg_addr (this_cache, ARM_PS_REGNUM, base + 16 * 4);
245
 
246
  /* The VFP or iWMMXt registers may be saved on the stack, but there's
247
     no reliable way to restore them (yet).  */
248
 
249
  /* Save a frame ID.  */
250
  trad_frame_set_id (this_cache, frame_id_build (sp, func));
251
}
252
 
253
/* There are a couple of different possible stack layouts that
254
   we need to support.
255
 
256
   Before version 2.6.18, the kernel used completely independent
257
   layouts for non-RT and RT signals.  For non-RT signals the stack
258
   began directly with a struct sigcontext.  For RT signals the stack
259
   began with two redundant pointers (to the siginfo and ucontext),
260
   and then the siginfo and ucontext.
261
 
262
   As of version 2.6.18, the non-RT signal frame layout starts with
263
   a ucontext and the RT signal frame starts with a siginfo and then
264
   a ucontext.  Also, the ucontext now has a designated save area
265
   for coprocessor registers.
266
 
267
   For RT signals, it's easy to tell the difference: we look for
268
   pinfo, the pointer to the siginfo.  If it has the expected
269
   value, we have an old layout.  If it doesn't, we have the new
270
   layout.
271
 
272
   For non-RT signals, it's a bit harder.  We need something in one
273
   layout or the other with a recognizable offset and value.  We can't
274
   use the return trampoline, because ARM usually uses SA_RESTORER,
275
   in which case the stack return trampoline is not filled in.
276
   We can't use the saved stack pointer, because sigaltstack might
277
   be in use.  So for now we guess the new layout...  */
278
 
279
/* There are three words (trap_no, error_code, oldmask) in
280
   struct sigcontext before r0.  */
281
#define ARM_SIGCONTEXT_R0 0xc
282
 
283
/* There are five words (uc_flags, uc_link, and three for uc_stack)
284
   in the ucontext_t before the sigcontext.  */
285
#define ARM_UCONTEXT_SIGCONTEXT 0x14
286
 
287
/* There are three elements in an rt_sigframe before the ucontext:
288
   pinfo, puc, and info.  The first two are pointers and the third
289
   is a struct siginfo, with size 128 bytes.  We could follow puc
290
   to the ucontext, but it's simpler to skip the whole thing.  */
291
#define ARM_OLD_RT_SIGFRAME_SIGINFO 0x8
292
#define ARM_OLD_RT_SIGFRAME_UCONTEXT 0x88
293
 
294
#define ARM_NEW_RT_SIGFRAME_UCONTEXT 0x80
295
 
296
#define ARM_NEW_SIGFRAME_MAGIC 0x5ac3c35a
297
 
298
static void
299
arm_linux_sigreturn_init (const struct tramp_frame *self,
300
                          struct frame_info *this_frame,
301
                          struct trad_frame_cache *this_cache,
302
                          CORE_ADDR func)
303
{
304
  struct gdbarch *gdbarch = get_frame_arch (this_frame);
305
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
306
  CORE_ADDR sp = get_frame_register_unsigned (this_frame, ARM_SP_REGNUM);
307
  ULONGEST uc_flags = read_memory_unsigned_integer (sp, 4, byte_order);
308
 
309
  if (uc_flags == ARM_NEW_SIGFRAME_MAGIC)
310
    arm_linux_sigtramp_cache (this_frame, this_cache, func,
311
                              ARM_UCONTEXT_SIGCONTEXT
312
                              + ARM_SIGCONTEXT_R0);
313
  else
314
    arm_linux_sigtramp_cache (this_frame, this_cache, func,
315
                              ARM_SIGCONTEXT_R0);
316
}
317
 
318
static void
319
arm_linux_rt_sigreturn_init (const struct tramp_frame *self,
320
                          struct frame_info *this_frame,
321
                          struct trad_frame_cache *this_cache,
322
                          CORE_ADDR func)
323
{
324
  struct gdbarch *gdbarch = get_frame_arch (this_frame);
325
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
326
  CORE_ADDR sp = get_frame_register_unsigned (this_frame, ARM_SP_REGNUM);
327
  ULONGEST pinfo = read_memory_unsigned_integer (sp, 4, byte_order);
328
 
329
  if (pinfo == sp + ARM_OLD_RT_SIGFRAME_SIGINFO)
330
    arm_linux_sigtramp_cache (this_frame, this_cache, func,
331
                              ARM_OLD_RT_SIGFRAME_UCONTEXT
332
                              + ARM_UCONTEXT_SIGCONTEXT
333
                              + ARM_SIGCONTEXT_R0);
334
  else
335
    arm_linux_sigtramp_cache (this_frame, this_cache, func,
336
                              ARM_NEW_RT_SIGFRAME_UCONTEXT
337
                              + ARM_UCONTEXT_SIGCONTEXT
338
                              + ARM_SIGCONTEXT_R0);
339
}
340
 
341
static void
342
arm_linux_restart_syscall_init (const struct tramp_frame *self,
343
                                struct frame_info *this_frame,
344
                                struct trad_frame_cache *this_cache,
345
                                CORE_ADDR func)
346
{
347
  CORE_ADDR sp = get_frame_register_unsigned (this_frame, ARM_SP_REGNUM);
348
 
349
  trad_frame_set_reg_addr (this_cache, ARM_PC_REGNUM, sp);
350
  trad_frame_set_reg_value (this_cache, ARM_SP_REGNUM, sp + 12);
351
 
352
  /* Save a frame ID.  */
353
  trad_frame_set_id (this_cache, frame_id_build (sp, func));
354
}
355
 
356
static struct tramp_frame arm_linux_sigreturn_tramp_frame = {
357
  SIGTRAMP_FRAME,
358
  4,
359
  {
360
    { ARM_LINUX_SIGRETURN_INSTR, -1 },
361
    { TRAMP_SENTINEL_INSN }
362
  },
363
  arm_linux_sigreturn_init
364
};
365
 
366
static struct tramp_frame arm_linux_rt_sigreturn_tramp_frame = {
367
  SIGTRAMP_FRAME,
368
  4,
369
  {
370
    { ARM_LINUX_RT_SIGRETURN_INSTR, -1 },
371
    { TRAMP_SENTINEL_INSN }
372
  },
373
  arm_linux_rt_sigreturn_init
374
};
375
 
376
static struct tramp_frame arm_eabi_linux_sigreturn_tramp_frame = {
377
  SIGTRAMP_FRAME,
378
  4,
379
  {
380
    { ARM_SET_R7_SIGRETURN, -1 },
381
    { ARM_EABI_SYSCALL, -1 },
382
    { TRAMP_SENTINEL_INSN }
383
  },
384
  arm_linux_sigreturn_init
385
};
386
 
387
static struct tramp_frame arm_eabi_linux_rt_sigreturn_tramp_frame = {
388
  SIGTRAMP_FRAME,
389
  4,
390
  {
391
    { ARM_SET_R7_RT_SIGRETURN, -1 },
392
    { ARM_EABI_SYSCALL, -1 },
393
    { TRAMP_SENTINEL_INSN }
394
  },
395
  arm_linux_rt_sigreturn_init
396
};
397
 
398
static struct tramp_frame arm_linux_restart_syscall_tramp_frame = {
399
  NORMAL_FRAME,
400
  4,
401
  {
402
    { ARM_OABI_SYSCALL_RESTART_SYSCALL, -1 },
403
    { ARM_LDR_PC_SP_12, -1 },
404
    { TRAMP_SENTINEL_INSN }
405
  },
406
  arm_linux_restart_syscall_init
407
};
408
 
409
/* Core file and register set support.  */
410
 
411
#define ARM_LINUX_SIZEOF_GREGSET (18 * INT_REGISTER_SIZE)
412
 
413
void
414
arm_linux_supply_gregset (const struct regset *regset,
415
                          struct regcache *regcache,
416
                          int regnum, const void *gregs_buf, size_t len)
417
{
418
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
419
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
420
  const gdb_byte *gregs = gregs_buf;
421
  int regno;
422
  CORE_ADDR reg_pc;
423
  gdb_byte pc_buf[INT_REGISTER_SIZE];
424
 
425
  for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
426
    if (regnum == -1 || regnum == regno)
427
      regcache_raw_supply (regcache, regno,
428
                           gregs + INT_REGISTER_SIZE * regno);
429
 
430
  if (regnum == ARM_PS_REGNUM || regnum == -1)
431
    {
432
      if (arm_apcs_32)
433
        regcache_raw_supply (regcache, ARM_PS_REGNUM,
434
                             gregs + INT_REGISTER_SIZE * ARM_CPSR_GREGNUM);
435
      else
436
        regcache_raw_supply (regcache, ARM_PS_REGNUM,
437
                             gregs + INT_REGISTER_SIZE * ARM_PC_REGNUM);
438
    }
439
 
440
  if (regnum == ARM_PC_REGNUM || regnum == -1)
441
    {
442
      reg_pc = extract_unsigned_integer (gregs
443
                                         + INT_REGISTER_SIZE * ARM_PC_REGNUM,
444
                                         INT_REGISTER_SIZE, byte_order);
445
      reg_pc = gdbarch_addr_bits_remove (gdbarch, reg_pc);
446
      store_unsigned_integer (pc_buf, INT_REGISTER_SIZE, byte_order, reg_pc);
447
      regcache_raw_supply (regcache, ARM_PC_REGNUM, pc_buf);
448
    }
449
}
450
 
451
void
452
arm_linux_collect_gregset (const struct regset *regset,
453
                           const struct regcache *regcache,
454
                           int regnum, void *gregs_buf, size_t len)
455
{
456
  gdb_byte *gregs = gregs_buf;
457
  int regno;
458
 
459
  for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
460
    if (regnum == -1 || regnum == regno)
461
      regcache_raw_collect (regcache, regno,
462
                            gregs + INT_REGISTER_SIZE * regno);
463
 
464
  if (regnum == ARM_PS_REGNUM || regnum == -1)
465
    {
466
      if (arm_apcs_32)
467
        regcache_raw_collect (regcache, ARM_PS_REGNUM,
468
                              gregs + INT_REGISTER_SIZE * ARM_CPSR_GREGNUM);
469
      else
470
        regcache_raw_collect (regcache, ARM_PS_REGNUM,
471
                              gregs + INT_REGISTER_SIZE * ARM_PC_REGNUM);
472
    }
473
 
474
  if (regnum == ARM_PC_REGNUM || regnum == -1)
475
    regcache_raw_collect (regcache, ARM_PC_REGNUM,
476
                          gregs + INT_REGISTER_SIZE * ARM_PC_REGNUM);
477
}
478
 
479
/* Support for register format used by the NWFPE FPA emulator.  */
480
 
481
#define typeNone                0x00
482
#define typeSingle              0x01
483
#define typeDouble              0x02
484
#define typeExtended            0x03
485
 
486
void
487
supply_nwfpe_register (struct regcache *regcache, int regno,
488
                       const gdb_byte *regs)
489
{
490
  const gdb_byte *reg_data;
491
  gdb_byte reg_tag;
492
  gdb_byte buf[FP_REGISTER_SIZE];
493
 
494
  reg_data = regs + (regno - ARM_F0_REGNUM) * FP_REGISTER_SIZE;
495
  reg_tag = regs[(regno - ARM_F0_REGNUM) + NWFPE_TAGS_OFFSET];
496
  memset (buf, 0, FP_REGISTER_SIZE);
497
 
498
  switch (reg_tag)
499
    {
500
    case typeSingle:
501
      memcpy (buf, reg_data, 4);
502
      break;
503
    case typeDouble:
504
      memcpy (buf, reg_data + 4, 4);
505
      memcpy (buf + 4, reg_data, 4);
506
      break;
507
    case typeExtended:
508
      /* We want sign and exponent, then least significant bits,
509
         then most significant.  NWFPE does sign, most, least.  */
510
      memcpy (buf, reg_data, 4);
511
      memcpy (buf + 4, reg_data + 8, 4);
512
      memcpy (buf + 8, reg_data + 4, 4);
513
      break;
514
    default:
515
      break;
516
    }
517
 
518
  regcache_raw_supply (regcache, regno, buf);
519
}
520
 
521
void
522
collect_nwfpe_register (const struct regcache *regcache, int regno,
523
                        gdb_byte *regs)
524
{
525
  gdb_byte *reg_data;
526
  gdb_byte reg_tag;
527
  gdb_byte buf[FP_REGISTER_SIZE];
528
 
529
  regcache_raw_collect (regcache, regno, buf);
530
 
531
  /* NOTE drow/2006-06-07: This code uses the tag already in the
532
     register buffer.  I've preserved that when moving the code
533
     from the native file to the target file.  But this doesn't
534
     always make sense.  */
535
 
536
  reg_data = regs + (regno - ARM_F0_REGNUM) * FP_REGISTER_SIZE;
537
  reg_tag = regs[(regno - ARM_F0_REGNUM) + NWFPE_TAGS_OFFSET];
538
 
539
  switch (reg_tag)
540
    {
541
    case typeSingle:
542
      memcpy (reg_data, buf, 4);
543
      break;
544
    case typeDouble:
545
      memcpy (reg_data, buf + 4, 4);
546
      memcpy (reg_data + 4, buf, 4);
547
      break;
548
    case typeExtended:
549
      memcpy (reg_data, buf, 4);
550
      memcpy (reg_data + 4, buf + 8, 4);
551
      memcpy (reg_data + 8, buf + 4, 4);
552
      break;
553
    default:
554
      break;
555
    }
556
}
557
 
558
void
559
arm_linux_supply_nwfpe (const struct regset *regset,
560
                        struct regcache *regcache,
561
                        int regnum, const void *regs_buf, size_t len)
562
{
563
  const gdb_byte *regs = regs_buf;
564
  int regno;
565
 
566
  if (regnum == ARM_FPS_REGNUM || regnum == -1)
567
    regcache_raw_supply (regcache, ARM_FPS_REGNUM,
568
                         regs + NWFPE_FPSR_OFFSET);
569
 
570
  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
571
    if (regnum == -1 || regnum == regno)
572
      supply_nwfpe_register (regcache, regno, regs);
573
}
574
 
575
void
576
arm_linux_collect_nwfpe (const struct regset *regset,
577
                         const struct regcache *regcache,
578
                         int regnum, void *regs_buf, size_t len)
579
{
580
  gdb_byte *regs = regs_buf;
581
  int regno;
582
 
583
  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
584
    if (regnum == -1 || regnum == regno)
585
      collect_nwfpe_register (regcache, regno, regs);
586
 
587
  if (regnum == ARM_FPS_REGNUM || regnum == -1)
588
    regcache_raw_collect (regcache, ARM_FPS_REGNUM,
589
                          regs + INT_REGISTER_SIZE * ARM_FPS_REGNUM);
590
}
591
 
592
/* Return the appropriate register set for the core section identified
593
   by SECT_NAME and SECT_SIZE.  */
594
 
595
static const struct regset *
596
arm_linux_regset_from_core_section (struct gdbarch *gdbarch,
597
                                    const char *sect_name, size_t sect_size)
598
{
599
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
600
 
601
  if (strcmp (sect_name, ".reg") == 0
602
      && sect_size == ARM_LINUX_SIZEOF_GREGSET)
603
    {
604
      if (tdep->gregset == NULL)
605
        tdep->gregset = regset_alloc (gdbarch, arm_linux_supply_gregset,
606
                                      arm_linux_collect_gregset);
607
      return tdep->gregset;
608
    }
609
 
610
  if (strcmp (sect_name, ".reg2") == 0
611
      && sect_size == ARM_LINUX_SIZEOF_NWFPE)
612
    {
613
      if (tdep->fpregset == NULL)
614
        tdep->fpregset = regset_alloc (gdbarch, arm_linux_supply_nwfpe,
615
                                       arm_linux_collect_nwfpe);
616
      return tdep->fpregset;
617
    }
618
 
619
  return NULL;
620
}
621
 
622
/* Insert a single step breakpoint at the next executed instruction.  */
623
 
624
static int
625
arm_linux_software_single_step (struct frame_info *frame)
626
{
627
  struct gdbarch *gdbarch = get_frame_arch (frame);
628
  struct address_space *aspace = get_frame_address_space (frame);
629
  CORE_ADDR next_pc = arm_get_next_pc (frame, get_frame_pc (frame));
630
 
631
  /* The Linux kernel offers some user-mode helpers in a high page.  We can
632
     not read this page (as of 2.6.23), and even if we could then we couldn't
633
     set breakpoints in it, and even if we could then the atomic operations
634
     would fail when interrupted.  They are all called as functions and return
635
     to the address in LR, so step to there instead.  */
636
  if (next_pc > 0xffff0000)
637
    next_pc = get_frame_register_unsigned (frame, ARM_LR_REGNUM);
638
 
639
  insert_single_step_breakpoint (gdbarch, aspace, next_pc);
640
 
641
  return 1;
642
}
643
 
644
/* Support for displaced stepping of Linux SVC instructions.  */
645
 
646
static void
647
arm_linux_cleanup_svc (struct gdbarch *gdbarch ATTRIBUTE_UNUSED,
648
                       struct regcache *regs,
649
                       struct displaced_step_closure *dsc)
650
{
651
  CORE_ADDR from = dsc->insn_addr;
652
  ULONGEST apparent_pc;
653
  int within_scratch;
654
 
655
  regcache_cooked_read_unsigned (regs, ARM_PC_REGNUM, &apparent_pc);
656
 
657
  within_scratch = (apparent_pc >= dsc->scratch_base
658
                    && apparent_pc < (dsc->scratch_base
659
                                      + DISPLACED_MODIFIED_INSNS * 4 + 4));
660
 
661
  if (debug_displaced)
662
    {
663
      fprintf_unfiltered (gdb_stdlog, "displaced: PC is apparently %.8lx after "
664
                          "SVC step ", (unsigned long) apparent_pc);
665
      if (within_scratch)
666
        fprintf_unfiltered (gdb_stdlog, "(within scratch space)\n");
667
      else
668
        fprintf_unfiltered (gdb_stdlog, "(outside scratch space)\n");
669
    }
670
 
671
  if (within_scratch)
672
    displaced_write_reg (regs, dsc, ARM_PC_REGNUM, from + 4, BRANCH_WRITE_PC);
673
}
674
 
675
static int
676
arm_linux_copy_svc (struct gdbarch *gdbarch, uint32_t insn, CORE_ADDR to,
677
                    struct regcache *regs, struct displaced_step_closure *dsc)
678
{
679
  CORE_ADDR from = dsc->insn_addr;
680
  struct frame_info *frame;
681
  unsigned int svc_number = displaced_read_reg (regs, from, 7);
682
 
683
  if (debug_displaced)
684
    fprintf_unfiltered (gdb_stdlog, "displaced: copying Linux svc insn %.8lx\n",
685
                        (unsigned long) insn);
686
 
687
  frame = get_current_frame ();
688
 
689
  /* Is this a sigreturn or rt_sigreturn syscall?  Note: these are only useful
690
     for EABI.  */
691
  if (svc_number == 119 || svc_number == 173)
692
    {
693
      if (get_frame_type (frame) == SIGTRAMP_FRAME)
694
        {
695
          CORE_ADDR return_to;
696
          struct symtab_and_line sal;
697
 
698
          if (debug_displaced)
699
            fprintf_unfiltered (gdb_stdlog, "displaced: found "
700
              "sigreturn/rt_sigreturn SVC call. PC in frame = %lx\n",
701
              (unsigned long) get_frame_pc (frame));
702
 
703
          return_to = frame_unwind_caller_pc (frame);
704
          if (debug_displaced)
705
            fprintf_unfiltered (gdb_stdlog, "displaced: unwind pc = %lx. "
706
              "Setting momentary breakpoint.\n", (unsigned long) return_to);
707
 
708
          gdb_assert (inferior_thread ()->step_resume_breakpoint == NULL);
709
 
710
          sal = find_pc_line (return_to, 0);
711
          sal.pc = return_to;
712
          sal.section = find_pc_overlay (return_to);
713
          sal.explicit_pc = 1;
714
 
715
          frame = get_prev_frame (frame);
716
 
717
          if (frame)
718
            {
719
              inferior_thread ()->step_resume_breakpoint
720
                = set_momentary_breakpoint (gdbarch, sal, get_frame_id (frame),
721
                                            bp_step_resume);
722
 
723
              /* We need to make sure we actually insert the momentary
724
                 breakpoint set above.  */
725
              insert_breakpoints ();
726
            }
727
          else if (debug_displaced)
728
            fprintf_unfiltered (gdb_stderr, "displaced: couldn't find previous "
729
                                "frame to set momentary breakpoint for "
730
                                "sigreturn/rt_sigreturn\n");
731
        }
732
      else if (debug_displaced)
733
        fprintf_unfiltered (gdb_stdlog, "displaced: sigreturn/rt_sigreturn "
734
                            "SVC call not in signal trampoline frame\n");
735
    }
736
 
737
  /* Preparation: If we detect sigreturn, set momentary breakpoint at resume
738
                  location, else nothing.
739
     Insn: unmodified svc.
740
     Cleanup: if pc lands in scratch space, pc <- insn_addr + 4
741
              else leave pc alone.  */
742
 
743
  dsc->modinsn[0] = insn;
744
 
745
  dsc->cleanup = &arm_linux_cleanup_svc;
746
  /* Pretend we wrote to the PC, so cleanup doesn't set PC to the next
747
     instruction.  */
748
  dsc->wrote_to_pc = 1;
749
 
750
  return 0;
751
}
752
 
753
 
754
/* The following two functions implement single-stepping over calls to Linux
755
   kernel helper routines, which perform e.g. atomic operations on architecture
756
   variants which don't support them natively.
757
 
758
   When this function is called, the PC will be pointing at the kernel helper
759
   (at an address inaccessible to GDB), and r14 will point to the return
760
   address.  Displaced stepping always executes code in the copy area:
761
   so, make the copy-area instruction branch back to the kernel helper (the
762
   "from" address), and make r14 point to the breakpoint in the copy area.  In
763
   that way, we regain control once the kernel helper returns, and can clean
764
   up appropriately (as if we had just returned from the kernel helper as it
765
   would have been called from the non-displaced location).  */
766
 
767
static void
768
cleanup_kernel_helper_return (struct gdbarch *gdbarch ATTRIBUTE_UNUSED,
769
                              struct regcache *regs,
770
                              struct displaced_step_closure *dsc)
771
{
772
  displaced_write_reg (regs, dsc, ARM_LR_REGNUM, dsc->tmp[0], CANNOT_WRITE_PC);
773
  displaced_write_reg (regs, dsc, ARM_PC_REGNUM, dsc->tmp[0], BRANCH_WRITE_PC);
774
}
775
 
776
static void
777
arm_catch_kernel_helper_return (struct gdbarch *gdbarch, CORE_ADDR from,
778
                                CORE_ADDR to, struct regcache *regs,
779
                                struct displaced_step_closure *dsc)
780
{
781
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
782
 
783
  dsc->numinsns = 1;
784
  dsc->insn_addr = from;
785
  dsc->cleanup = &cleanup_kernel_helper_return;
786
  /* Say we wrote to the PC, else cleanup will set PC to the next
787
     instruction in the helper, which isn't helpful.  */
788
  dsc->wrote_to_pc = 1;
789
 
790
  /* Preparation: tmp[0] <- r14
791
                  r14 <- <scratch space>+4
792
                  *(<scratch space>+8) <- from
793
     Insn: ldr pc, [r14, #4]
794
     Cleanup: r14 <- tmp[0], pc <- tmp[0].  */
795
 
796
  dsc->tmp[0] = displaced_read_reg (regs, from, ARM_LR_REGNUM);
797
  displaced_write_reg (regs, dsc, ARM_LR_REGNUM, (ULONGEST) to + 4,
798
                       CANNOT_WRITE_PC);
799
  write_memory_unsigned_integer (to + 8, 4, byte_order, from);
800
 
801
  dsc->modinsn[0] = 0xe59ef004;  /* ldr pc, [lr, #4].  */
802
}
803
 
804
/* Linux-specific displaced step instruction copying function.  Detects when
805
   the program has stepped into a Linux kernel helper routine (which must be
806
   handled as a special case), falling back to arm_displaced_step_copy_insn()
807
   if it hasn't.  */
808
 
809
static struct displaced_step_closure *
810
arm_linux_displaced_step_copy_insn (struct gdbarch *gdbarch,
811
                                    CORE_ADDR from, CORE_ADDR to,
812
                                    struct regcache *regs)
813
{
814
  struct displaced_step_closure *dsc
815
    = xmalloc (sizeof (struct displaced_step_closure));
816
 
817
  /* Detect when we enter an (inaccessible by GDB) Linux kernel helper, and
818
     stop at the return location.  */
819
  if (from > 0xffff0000)
820
    {
821
      if (debug_displaced)
822
        fprintf_unfiltered (gdb_stdlog, "displaced: detected kernel helper "
823
                            "at %.8lx\n", (unsigned long) from);
824
 
825
      arm_catch_kernel_helper_return (gdbarch, from, to, regs, dsc);
826
    }
827
  else
828
    {
829
      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
830
      uint32_t insn = read_memory_unsigned_integer (from, 4, byte_order);
831
 
832
      if (debug_displaced)
833
        fprintf_unfiltered (gdb_stdlog, "displaced: stepping insn %.8lx "
834
                            "at %.8lx\n", (unsigned long) insn,
835
                            (unsigned long) from);
836
 
837
      /* Override the default handling of SVC instructions.  */
838
      dsc->u.svc.copy_svc_os = arm_linux_copy_svc;
839
 
840
      arm_process_displaced_insn (gdbarch, insn, from, to, regs, dsc);
841
    }
842
 
843
  arm_displaced_init_closure (gdbarch, from, to, dsc);
844
 
845
  return dsc;
846
}
847
 
848
static void
849
arm_linux_init_abi (struct gdbarch_info info,
850
                    struct gdbarch *gdbarch)
851
{
852
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
853
 
854
  tdep->lowest_pc = 0x8000;
855
  if (info.byte_order == BFD_ENDIAN_BIG)
856
    {
857
      if (tdep->arm_abi == ARM_ABI_AAPCS)
858
        tdep->arm_breakpoint = eabi_linux_arm_be_breakpoint;
859
      else
860
        tdep->arm_breakpoint = arm_linux_arm_be_breakpoint;
861
      tdep->thumb_breakpoint = arm_linux_thumb_be_breakpoint;
862
      tdep->thumb2_breakpoint = arm_linux_thumb2_be_breakpoint;
863
    }
864
  else
865
    {
866
      if (tdep->arm_abi == ARM_ABI_AAPCS)
867
        tdep->arm_breakpoint = eabi_linux_arm_le_breakpoint;
868
      else
869
        tdep->arm_breakpoint = arm_linux_arm_le_breakpoint;
870
      tdep->thumb_breakpoint = arm_linux_thumb_le_breakpoint;
871
      tdep->thumb2_breakpoint = arm_linux_thumb2_le_breakpoint;
872
    }
873
  tdep->arm_breakpoint_size = sizeof (arm_linux_arm_le_breakpoint);
874
  tdep->thumb_breakpoint_size = sizeof (arm_linux_thumb_le_breakpoint);
875
  tdep->thumb2_breakpoint_size = sizeof (arm_linux_thumb2_le_breakpoint);
876
 
877
  if (tdep->fp_model == ARM_FLOAT_AUTO)
878
    tdep->fp_model = ARM_FLOAT_FPA;
879
 
880
  tdep->jb_pc = ARM_LINUX_JB_PC;
881
  tdep->jb_elt_size = ARM_LINUX_JB_ELEMENT_SIZE;
882
 
883
  set_solib_svr4_fetch_link_map_offsets
884
    (gdbarch, svr4_ilp32_fetch_link_map_offsets);
885
 
886
  /* Single stepping.  */
887
  set_gdbarch_software_single_step (gdbarch, arm_linux_software_single_step);
888
 
889
  /* Shared library handling.  */
890
  set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
891
  set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
892
 
893
  /* Enable TLS support.  */
894
  set_gdbarch_fetch_tls_load_module_address (gdbarch,
895
                                             svr4_fetch_objfile_link_map);
896
 
897
  tramp_frame_prepend_unwinder (gdbarch,
898
                                &arm_linux_sigreturn_tramp_frame);
899
  tramp_frame_prepend_unwinder (gdbarch,
900
                                &arm_linux_rt_sigreturn_tramp_frame);
901
  tramp_frame_prepend_unwinder (gdbarch,
902
                                &arm_eabi_linux_sigreturn_tramp_frame);
903
  tramp_frame_prepend_unwinder (gdbarch,
904
                                &arm_eabi_linux_rt_sigreturn_tramp_frame);
905
  tramp_frame_prepend_unwinder (gdbarch,
906
                                &arm_linux_restart_syscall_tramp_frame);
907
 
908
  /* Core file support.  */
909
  set_gdbarch_regset_from_core_section (gdbarch,
910
                                        arm_linux_regset_from_core_section);
911
 
912
  set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
913
 
914
  /* Displaced stepping.  */
915
  set_gdbarch_displaced_step_copy_insn (gdbarch,
916
                                        arm_linux_displaced_step_copy_insn);
917
  set_gdbarch_displaced_step_fixup (gdbarch, arm_displaced_step_fixup);
918
  set_gdbarch_displaced_step_free_closure (gdbarch,
919
                                           simple_displaced_step_free_closure);
920
  set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);
921
}
922
 
923
/* Provide a prototype to silence -Wmissing-prototypes.  */
924
extern initialize_file_ftype _initialize_arm_linux_tdep;
925
 
926
void
927
_initialize_arm_linux_tdep (void)
928
{
929
  gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_LINUX,
930
                          arm_linux_init_abi);
931
}

powered by: WebSVN 2.1.0

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