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

Subversion Repositories openrisc_me

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

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

Line No. Rev Author Line
1 24 jeremybenn
/* GNU/Linux on ARM target support.
2
 
3
   Copyright (C) 1999, 2000, 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 "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 "glibc-tdep.h"
40
 
41
#include "gdb_string.h"
42
 
43
extern int arm_apcs_32;
44
 
45
/* Under ARM GNU/Linux the traditional way of performing a breakpoint
46
   is to execute a particular software interrupt, rather than use a
47
   particular undefined instruction to provoke a trap.  Upon exection
48
   of the software interrupt the kernel stops the inferior with a
49
   SIGTRAP, and wakes the debugger.  */
50
 
51
static const char arm_linux_arm_le_breakpoint[] = { 0x01, 0x00, 0x9f, 0xef };
52
 
53
static const char arm_linux_arm_be_breakpoint[] = { 0xef, 0x9f, 0x00, 0x01 };
54
 
55
/* However, the EABI syscall interface (new in Nov. 2005) does not look at
56
   the operand of the swi if old-ABI compatibility is disabled.  Therefore,
57
   use an undefined instruction instead.  This is supported as of kernel
58
   version 2.5.70 (May 2003), so should be a safe assumption for EABI
59
   binaries.  */
60
 
61
static const char eabi_linux_arm_le_breakpoint[] = { 0xf0, 0x01, 0xf0, 0xe7 };
62
 
63
static const char eabi_linux_arm_be_breakpoint[] = { 0xe7, 0xf0, 0x01, 0xf0 };
64
 
65
/* All the kernels which support Thumb support using a specific undefined
66
   instruction for the Thumb breakpoint.  */
67
 
68
static const char arm_linux_thumb_be_breakpoint[] = {0xde, 0x01};
69
 
70
static const char arm_linux_thumb_le_breakpoint[] = {0x01, 0xde};
71
 
72
/* Description of the longjmp buffer.  */
73
#define ARM_LINUX_JB_ELEMENT_SIZE       INT_REGISTER_SIZE
74
#define ARM_LINUX_JB_PC                 21
75
 
76
/*
77
   Dynamic Linking on ARM GNU/Linux
78
   --------------------------------
79
 
80
   Note: PLT = procedure linkage table
81
   GOT = global offset table
82
 
83
   As much as possible, ELF dynamic linking defers the resolution of
84
   jump/call addresses until the last minute. The technique used is
85
   inspired by the i386 ELF design, and is based on the following
86
   constraints.
87
 
88
   1) The calling technique should not force a change in the assembly
89
   code produced for apps; it MAY cause changes in the way assembly
90
   code is produced for position independent code (i.e. shared
91
   libraries).
92
 
93
   2) The technique must be such that all executable areas must not be
94
   modified; and any modified areas must not be executed.
95
 
96
   To do this, there are three steps involved in a typical jump:
97
 
98
   1) in the code
99
   2) through the PLT
100
   3) using a pointer from the GOT
101
 
102
   When the executable or library is first loaded, each GOT entry is
103
   initialized to point to the code which implements dynamic name
104
   resolution and code finding.  This is normally a function in the
105
   program interpreter (on ARM GNU/Linux this is usually
106
   ld-linux.so.2, but it does not have to be).  On the first
107
   invocation, the function is located and the GOT entry is replaced
108
   with the real function address.  Subsequent calls go through steps
109
   1, 2 and 3 and end up calling the real code.
110
 
111
   1) In the code:
112
 
113
   b    function_call
114
   bl   function_call
115
 
116
   This is typical ARM code using the 26 bit relative branch or branch
117
   and link instructions.  The target of the instruction
118
   (function_call is usually the address of the function to be called.
119
   In position independent code, the target of the instruction is
120
   actually an entry in the PLT when calling functions in a shared
121
   library.  Note that this call is identical to a normal function
122
   call, only the target differs.
123
 
124
   2) In the PLT:
125
 
126
   The PLT is a synthetic area, created by the linker. It exists in
127
   both executables and libraries. It is an array of stubs, one per
128
   imported function call. It looks like this:
129
 
130
   PLT[0]:
131
   str     lr, [sp, #-4]!       @push the return address (lr)
132
   ldr     lr, [pc, #16]   @load from 6 words ahead
133
   add     lr, pc, lr      @form an address for GOT[0]
134
   ldr     pc, [lr, #8]!   @jump to the contents of that addr
135
 
136
   The return address (lr) is pushed on the stack and used for
137
   calculations.  The load on the second line loads the lr with
138
   &GOT[3] - . - 20.  The addition on the third leaves:
139
 
140
   lr = (&GOT[3] - . - 20) + (. + 8)
141
   lr = (&GOT[3] - 12)
142
   lr = &GOT[0]
143
 
144
   On the fourth line, the pc and lr are both updated, so that:
145
 
146
   pc = GOT[2]
147
   lr = &GOT[0] + 8
148
   = &GOT[2]
149
 
150
   NOTE: PLT[0] borrows an offset .word from PLT[1]. This is a little
151
   "tight", but allows us to keep all the PLT entries the same size.
152
 
153
   PLT[n+1]:
154
   ldr     ip, [pc, #4]    @load offset from gotoff
155
   add     ip, pc, ip      @add the offset to the pc
156
   ldr     pc, [ip]        @jump to that address
157
   gotoff: .word   GOT[n+3] - .
158
 
159
   The load on the first line, gets an offset from the fourth word of
160
   the PLT entry.  The add on the second line makes ip = &GOT[n+3],
161
   which contains either a pointer to PLT[0] (the fixup trampoline) or
162
   a pointer to the actual code.
163
 
164
   3) In the GOT:
165
 
166
   The GOT contains helper pointers for both code (PLT) fixups and
167
   data fixups.  The first 3 entries of the GOT are special. The next
168
   M entries (where M is the number of entries in the PLT) belong to
169
   the PLT fixups. The next D (all remaining) entries belong to
170
   various data fixups. The actual size of the GOT is 3 + M + D.
171
 
172
   The GOT is also a synthetic area, created by the linker. It exists
173
   in both executables and libraries.  When the GOT is first
174
   initialized , all the GOT entries relating to PLT fixups are
175
   pointing to code back at PLT[0].
176
 
177
   The special entries in the GOT are:
178
 
179
   GOT[0] = linked list pointer used by the dynamic loader
180
   GOT[1] = pointer to the reloc table for this module
181
   GOT[2] = pointer to the fixup/resolver code
182
 
183
   The first invocation of function call comes through and uses the
184
   fixup/resolver code.  On the entry to the fixup/resolver code:
185
 
186
   ip = &GOT[n+3]
187
   lr = &GOT[2]
188
   stack[0] = return address (lr) of the function call
189
   [r0, r1, r2, r3] are still the arguments to the function call
190
 
191
   This is enough information for the fixup/resolver code to work
192
   with.  Before the fixup/resolver code returns, it actually calls
193
   the requested function and repairs &GOT[n+3].  */
194
 
195
/* The constants below were determined by examining the following files
196
   in the linux kernel sources:
197
 
198
      arch/arm/kernel/signal.c
199
          - see SWI_SYS_SIGRETURN and SWI_SYS_RT_SIGRETURN
200
      include/asm-arm/unistd.h
201
          - see __NR_sigreturn, __NR_rt_sigreturn, and __NR_SYSCALL_BASE */
202
 
203
#define ARM_LINUX_SIGRETURN_INSTR       0xef900077
204
#define ARM_LINUX_RT_SIGRETURN_INSTR    0xef9000ad
205
 
206
/* For ARM EABI, the syscall number is not in the SWI instruction
207
   (instead it is loaded into r7).  We recognize the pattern that
208
   glibc uses...  alternatively, we could arrange to do this by
209
   function name, but they are not always exported.  */
210
#define ARM_SET_R7_SIGRETURN            0xe3a07077
211
#define ARM_SET_R7_RT_SIGRETURN         0xe3a070ad
212
#define ARM_EABI_SYSCALL                0xef000000
213
 
214
static void
215
arm_linux_sigtramp_cache (struct frame_info *next_frame,
216
                          struct trad_frame_cache *this_cache,
217
                          CORE_ADDR func, int regs_offset)
218
{
219
  CORE_ADDR sp = frame_unwind_register_unsigned (next_frame, ARM_SP_REGNUM);
220
  CORE_ADDR base = sp + regs_offset;
221
  int i;
222
 
223
  for (i = 0; i < 16; i++)
224
    trad_frame_set_reg_addr (this_cache, i, base + i * 4);
225
 
226
  trad_frame_set_reg_addr (this_cache, ARM_PS_REGNUM, base + 16 * 4);
227
 
228
  /* The VFP or iWMMXt registers may be saved on the stack, but there's
229
     no reliable way to restore them (yet).  */
230
 
231
  /* Save a frame ID.  */
232
  trad_frame_set_id (this_cache, frame_id_build (sp, func));
233
}
234
 
235
/* There are a couple of different possible stack layouts that
236
   we need to support.
237
 
238
   Before version 2.6.18, the kernel used completely independent
239
   layouts for non-RT and RT signals.  For non-RT signals the stack
240
   began directly with a struct sigcontext.  For RT signals the stack
241
   began with two redundant pointers (to the siginfo and ucontext),
242
   and then the siginfo and ucontext.
243
 
244
   As of version 2.6.18, the non-RT signal frame layout starts with
245
   a ucontext and the RT signal frame starts with a siginfo and then
246
   a ucontext.  Also, the ucontext now has a designated save area
247
   for coprocessor registers.
248
 
249
   For RT signals, it's easy to tell the difference: we look for
250
   pinfo, the pointer to the siginfo.  If it has the expected
251
   value, we have an old layout.  If it doesn't, we have the new
252
   layout.
253
 
254
   For non-RT signals, it's a bit harder.  We need something in one
255
   layout or the other with a recognizable offset and value.  We can't
256
   use the return trampoline, because ARM usually uses SA_RESTORER,
257
   in which case the stack return trampoline is not filled in.
258
   We can't use the saved stack pointer, because sigaltstack might
259
   be in use.  So for now we guess the new layout...  */
260
 
261
/* There are three words (trap_no, error_code, oldmask) in
262
   struct sigcontext before r0.  */
263
#define ARM_SIGCONTEXT_R0 0xc
264
 
265
/* There are five words (uc_flags, uc_link, and three for uc_stack)
266
   in the ucontext_t before the sigcontext.  */
267
#define ARM_UCONTEXT_SIGCONTEXT 0x14
268
 
269
/* There are three elements in an rt_sigframe before the ucontext:
270
   pinfo, puc, and info.  The first two are pointers and the third
271
   is a struct siginfo, with size 128 bytes.  We could follow puc
272
   to the ucontext, but it's simpler to skip the whole thing.  */
273
#define ARM_OLD_RT_SIGFRAME_SIGINFO 0x8
274
#define ARM_OLD_RT_SIGFRAME_UCONTEXT 0x88
275
 
276
#define ARM_NEW_RT_SIGFRAME_UCONTEXT 0x80
277
 
278
#define ARM_NEW_SIGFRAME_MAGIC 0x5ac3c35a
279
 
280
static void
281
arm_linux_sigreturn_init (const struct tramp_frame *self,
282
                          struct frame_info *next_frame,
283
                          struct trad_frame_cache *this_cache,
284
                          CORE_ADDR func)
285
{
286
  CORE_ADDR sp = frame_unwind_register_unsigned (next_frame, ARM_SP_REGNUM);
287
  ULONGEST uc_flags = read_memory_unsigned_integer (sp, 4);
288
 
289
  if (uc_flags == ARM_NEW_SIGFRAME_MAGIC)
290
    arm_linux_sigtramp_cache (next_frame, this_cache, func,
291
                              ARM_UCONTEXT_SIGCONTEXT
292
                              + ARM_SIGCONTEXT_R0);
293
  else
294
    arm_linux_sigtramp_cache (next_frame, this_cache, func,
295
                              ARM_SIGCONTEXT_R0);
296
}
297
 
298
static void
299
arm_linux_rt_sigreturn_init (const struct tramp_frame *self,
300
                          struct frame_info *next_frame,
301
                          struct trad_frame_cache *this_cache,
302
                          CORE_ADDR func)
303
{
304
  CORE_ADDR sp = frame_unwind_register_unsigned (next_frame, ARM_SP_REGNUM);
305
  ULONGEST pinfo = read_memory_unsigned_integer (sp, 4);
306
 
307
  if (pinfo == sp + ARM_OLD_RT_SIGFRAME_SIGINFO)
308
    arm_linux_sigtramp_cache (next_frame, this_cache, func,
309
                              ARM_OLD_RT_SIGFRAME_UCONTEXT
310
                              + ARM_UCONTEXT_SIGCONTEXT
311
                              + ARM_SIGCONTEXT_R0);
312
  else
313
    arm_linux_sigtramp_cache (next_frame, this_cache, func,
314
                              ARM_NEW_RT_SIGFRAME_UCONTEXT
315
                              + ARM_UCONTEXT_SIGCONTEXT
316
                              + ARM_SIGCONTEXT_R0);
317
}
318
 
319
static struct tramp_frame arm_linux_sigreturn_tramp_frame = {
320
  SIGTRAMP_FRAME,
321
  4,
322
  {
323
    { ARM_LINUX_SIGRETURN_INSTR, -1 },
324
    { TRAMP_SENTINEL_INSN }
325
  },
326
  arm_linux_sigreturn_init
327
};
328
 
329
static struct tramp_frame arm_linux_rt_sigreturn_tramp_frame = {
330
  SIGTRAMP_FRAME,
331
  4,
332
  {
333
    { ARM_LINUX_RT_SIGRETURN_INSTR, -1 },
334
    { TRAMP_SENTINEL_INSN }
335
  },
336
  arm_linux_rt_sigreturn_init
337
};
338
 
339
static struct tramp_frame arm_eabi_linux_sigreturn_tramp_frame = {
340
  SIGTRAMP_FRAME,
341
  4,
342
  {
343
    { ARM_SET_R7_SIGRETURN, -1 },
344
    { ARM_EABI_SYSCALL, -1 },
345
    { TRAMP_SENTINEL_INSN }
346
  },
347
  arm_linux_sigreturn_init
348
};
349
 
350
static struct tramp_frame arm_eabi_linux_rt_sigreturn_tramp_frame = {
351
  SIGTRAMP_FRAME,
352
  4,
353
  {
354
    { ARM_SET_R7_RT_SIGRETURN, -1 },
355
    { ARM_EABI_SYSCALL, -1 },
356
    { TRAMP_SENTINEL_INSN }
357
  },
358
  arm_linux_rt_sigreturn_init
359
};
360
 
361
/* Core file and register set support.  */
362
 
363
#define ARM_LINUX_SIZEOF_GREGSET (18 * INT_REGISTER_SIZE)
364
 
365
void
366
arm_linux_supply_gregset (const struct regset *regset,
367
                          struct regcache *regcache,
368
                          int regnum, const void *gregs_buf, size_t len)
369
{
370
  const gdb_byte *gregs = gregs_buf;
371
  int regno;
372
  CORE_ADDR reg_pc;
373
  gdb_byte pc_buf[INT_REGISTER_SIZE];
374
 
375
  for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
376
    if (regnum == -1 || regnum == regno)
377
      regcache_raw_supply (regcache, regno,
378
                           gregs + INT_REGISTER_SIZE * regno);
379
 
380
  if (regnum == ARM_PS_REGNUM || regnum == -1)
381
    {
382
      if (arm_apcs_32)
383
        regcache_raw_supply (regcache, ARM_PS_REGNUM,
384
                             gregs + INT_REGISTER_SIZE * ARM_CPSR_REGNUM);
385
      else
386
        regcache_raw_supply (regcache, ARM_PS_REGNUM,
387
                             gregs + INT_REGISTER_SIZE * ARM_PC_REGNUM);
388
    }
389
 
390
  if (regnum == ARM_PC_REGNUM || regnum == -1)
391
    {
392
      reg_pc = extract_unsigned_integer (gregs
393
                                         + INT_REGISTER_SIZE * ARM_PC_REGNUM,
394
                                         INT_REGISTER_SIZE);
395
      reg_pc = gdbarch_addr_bits_remove (get_regcache_arch (regcache), reg_pc);
396
      store_unsigned_integer (pc_buf, INT_REGISTER_SIZE, reg_pc);
397
      regcache_raw_supply (regcache, ARM_PC_REGNUM, pc_buf);
398
    }
399
}
400
 
401
void
402
arm_linux_collect_gregset (const struct regset *regset,
403
                           const struct regcache *regcache,
404
                           int regnum, void *gregs_buf, size_t len)
405
{
406
  gdb_byte *gregs = gregs_buf;
407
  int regno;
408
 
409
  for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
410
    if (regnum == -1 || regnum == regno)
411
      regcache_raw_collect (regcache, regno,
412
                            gregs + INT_REGISTER_SIZE * regno);
413
 
414
  if (regnum == ARM_PS_REGNUM || regnum == -1)
415
    {
416
      if (arm_apcs_32)
417
        regcache_raw_collect (regcache, ARM_PS_REGNUM,
418
                              gregs + INT_REGISTER_SIZE * ARM_CPSR_REGNUM);
419
      else
420
        regcache_raw_collect (regcache, ARM_PS_REGNUM,
421
                              gregs + INT_REGISTER_SIZE * ARM_PC_REGNUM);
422
    }
423
 
424
  if (regnum == ARM_PC_REGNUM || regnum == -1)
425
    regcache_raw_collect (regcache, ARM_PC_REGNUM,
426
                          gregs + INT_REGISTER_SIZE * ARM_PC_REGNUM);
427
}
428
 
429
/* Support for register format used by the NWFPE FPA emulator.  */
430
 
431
#define typeNone                0x00
432
#define typeSingle              0x01
433
#define typeDouble              0x02
434
#define typeExtended            0x03
435
 
436
void
437
supply_nwfpe_register (struct regcache *regcache, int regno,
438
                       const gdb_byte *regs)
439
{
440
  const gdb_byte *reg_data;
441
  gdb_byte reg_tag;
442
  gdb_byte buf[FP_REGISTER_SIZE];
443
 
444
  reg_data = regs + (regno - ARM_F0_REGNUM) * FP_REGISTER_SIZE;
445
  reg_tag = regs[(regno - ARM_F0_REGNUM) + NWFPE_TAGS_OFFSET];
446
  memset (buf, 0, FP_REGISTER_SIZE);
447
 
448
  switch (reg_tag)
449
    {
450
    case typeSingle:
451
      memcpy (buf, reg_data, 4);
452
      break;
453
    case typeDouble:
454
      memcpy (buf, reg_data + 4, 4);
455
      memcpy (buf + 4, reg_data, 4);
456
      break;
457
    case typeExtended:
458
      /* We want sign and exponent, then least significant bits,
459
         then most significant.  NWFPE does sign, most, least.  */
460
      memcpy (buf, reg_data, 4);
461
      memcpy (buf + 4, reg_data + 8, 4);
462
      memcpy (buf + 8, reg_data + 4, 4);
463
      break;
464
    default:
465
      break;
466
    }
467
 
468
  regcache_raw_supply (regcache, regno, buf);
469
}
470
 
471
void
472
collect_nwfpe_register (const struct regcache *regcache, int regno,
473
                        gdb_byte *regs)
474
{
475
  gdb_byte *reg_data;
476
  gdb_byte reg_tag;
477
  gdb_byte buf[FP_REGISTER_SIZE];
478
 
479
  regcache_raw_collect (regcache, regno, buf);
480
 
481
  /* NOTE drow/2006-06-07: This code uses the tag already in the
482
     register buffer.  I've preserved that when moving the code
483
     from the native file to the target file.  But this doesn't
484
     always make sense.  */
485
 
486
  reg_data = regs + (regno - ARM_F0_REGNUM) * FP_REGISTER_SIZE;
487
  reg_tag = regs[(regno - ARM_F0_REGNUM) + NWFPE_TAGS_OFFSET];
488
 
489
  switch (reg_tag)
490
    {
491
    case typeSingle:
492
      memcpy (reg_data, buf, 4);
493
      break;
494
    case typeDouble:
495
      memcpy (reg_data, buf + 4, 4);
496
      memcpy (reg_data + 4, buf, 4);
497
      break;
498
    case typeExtended:
499
      memcpy (reg_data, buf, 4);
500
      memcpy (reg_data + 4, buf + 8, 4);
501
      memcpy (reg_data + 8, buf + 4, 4);
502
      break;
503
    default:
504
      break;
505
    }
506
}
507
 
508
void
509
arm_linux_supply_nwfpe (const struct regset *regset,
510
                        struct regcache *regcache,
511
                        int regnum, const void *regs_buf, size_t len)
512
{
513
  const gdb_byte *regs = regs_buf;
514
  int regno;
515
 
516
  if (regnum == ARM_FPS_REGNUM || regnum == -1)
517
    regcache_raw_supply (regcache, ARM_FPS_REGNUM,
518
                         regs + NWFPE_FPSR_OFFSET);
519
 
520
  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
521
    if (regnum == -1 || regnum == regno)
522
      supply_nwfpe_register (regcache, regno, regs);
523
}
524
 
525
void
526
arm_linux_collect_nwfpe (const struct regset *regset,
527
                         const struct regcache *regcache,
528
                         int regnum, void *regs_buf, size_t len)
529
{
530
  gdb_byte *regs = regs_buf;
531
  int regno;
532
 
533
  for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
534
    if (regnum == -1 || regnum == regno)
535
      collect_nwfpe_register (regcache, regno, regs);
536
 
537
  if (regnum == ARM_FPS_REGNUM || regnum == -1)
538
    regcache_raw_collect (regcache, ARM_FPS_REGNUM,
539
                          regs + INT_REGISTER_SIZE * ARM_FPS_REGNUM);
540
}
541
 
542
/* Return the appropriate register set for the core section identified
543
   by SECT_NAME and SECT_SIZE.  */
544
 
545
static const struct regset *
546
arm_linux_regset_from_core_section (struct gdbarch *gdbarch,
547
                                    const char *sect_name, size_t sect_size)
548
{
549
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
550
 
551
  if (strcmp (sect_name, ".reg") == 0
552
      && sect_size == ARM_LINUX_SIZEOF_GREGSET)
553
    {
554
      if (tdep->gregset == NULL)
555
        tdep->gregset = regset_alloc (gdbarch, arm_linux_supply_gregset,
556
                                      arm_linux_collect_gregset);
557
      return tdep->gregset;
558
    }
559
 
560
  if (strcmp (sect_name, ".reg2") == 0
561
      && sect_size == ARM_LINUX_SIZEOF_NWFPE)
562
    {
563
      if (tdep->fpregset == NULL)
564
        tdep->fpregset = regset_alloc (gdbarch, arm_linux_supply_nwfpe,
565
                                       arm_linux_collect_nwfpe);
566
      return tdep->fpregset;
567
    }
568
 
569
  return NULL;
570
}
571
 
572
/* Insert a single step breakpoint at the next executed instruction.  */
573
 
574
int
575
arm_linux_software_single_step (struct frame_info *frame)
576
{
577
  CORE_ADDR next_pc = arm_get_next_pc (frame, get_frame_pc (frame));
578
 
579
  /* The Linux kernel offers some user-mode helpers in a high page.  We can
580
     not read this page (as of 2.6.23), and even if we could then we couldn't
581
     set breakpoints in it, and even if we could then the atomic operations
582
     would fail when interrupted.  They are all called as functions and return
583
     to the address in LR, so step to there instead.  */
584
  if (next_pc > 0xffff0000)
585
    next_pc = get_frame_register_unsigned (frame, ARM_LR_REGNUM);
586
 
587
  insert_single_step_breakpoint (next_pc);
588
 
589
  return 1;
590
}
591
 
592
static void
593
arm_linux_init_abi (struct gdbarch_info info,
594
                    struct gdbarch *gdbarch)
595
{
596
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
597
 
598
  tdep->lowest_pc = 0x8000;
599
  if (info.byte_order == BFD_ENDIAN_BIG)
600
    {
601
      if (tdep->arm_abi == ARM_ABI_AAPCS)
602
        tdep->arm_breakpoint = eabi_linux_arm_be_breakpoint;
603
      else
604
        tdep->arm_breakpoint = arm_linux_arm_be_breakpoint;
605
      tdep->thumb_breakpoint = arm_linux_thumb_be_breakpoint;
606
    }
607
  else
608
    {
609
      if (tdep->arm_abi == ARM_ABI_AAPCS)
610
        tdep->arm_breakpoint = eabi_linux_arm_le_breakpoint;
611
      else
612
        tdep->arm_breakpoint = arm_linux_arm_le_breakpoint;
613
      tdep->thumb_breakpoint = arm_linux_thumb_le_breakpoint;
614
    }
615
  tdep->arm_breakpoint_size = sizeof (arm_linux_arm_le_breakpoint);
616
  tdep->thumb_breakpoint_size = sizeof (arm_linux_thumb_le_breakpoint);
617
 
618
  if (tdep->fp_model == ARM_FLOAT_AUTO)
619
    tdep->fp_model = ARM_FLOAT_FPA;
620
 
621
  tdep->jb_pc = ARM_LINUX_JB_PC;
622
  tdep->jb_elt_size = ARM_LINUX_JB_ELEMENT_SIZE;
623
 
624
  set_solib_svr4_fetch_link_map_offsets
625
    (gdbarch, svr4_ilp32_fetch_link_map_offsets);
626
 
627
  /* Single stepping.  */
628
  set_gdbarch_software_single_step (gdbarch, arm_linux_software_single_step);
629
 
630
  /* Shared library handling.  */
631
  set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
632
  set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
633
 
634
  /* Enable TLS support.  */
635
  set_gdbarch_fetch_tls_load_module_address (gdbarch,
636
                                             svr4_fetch_objfile_link_map);
637
 
638
  tramp_frame_prepend_unwinder (gdbarch,
639
                                &arm_linux_sigreturn_tramp_frame);
640
  tramp_frame_prepend_unwinder (gdbarch,
641
                                &arm_linux_rt_sigreturn_tramp_frame);
642
  tramp_frame_prepend_unwinder (gdbarch,
643
                                &arm_eabi_linux_sigreturn_tramp_frame);
644
  tramp_frame_prepend_unwinder (gdbarch,
645
                                &arm_eabi_linux_rt_sigreturn_tramp_frame);
646
 
647
  /* Core file support.  */
648
  set_gdbarch_regset_from_core_section (gdbarch,
649
                                        arm_linux_regset_from_core_section);
650
}
651
 
652
void
653
_initialize_arm_linux_tdep (void)
654
{
655
  gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_LINUX,
656
                          arm_linux_init_abi);
657
}

powered by: WebSVN 2.1.0

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