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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [gdb/] [arm-linux-tdep.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* GNU/Linux on ARM target support.
2
   Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
3
 
4
   This file is part of GDB.
5
 
6
   This program is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 2 of the License, or
9
   (at your option) any later version.
10
 
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
 
16
   You should have received a copy of the GNU General Public License
17
   along with this program; if not, write to the Free Software
18
   Foundation, Inc., 59 Temple Place - Suite 330,
19
   Boston, MA 02111-1307, USA.  */
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
 
30
/* For arm_linux_skip_solib_resolver.  */
31
#include "symtab.h"
32
#include "symfile.h"
33
#include "objfiles.h"
34
 
35
#ifdef GET_LONGJMP_TARGET
36
 
37
/* Figure out where the longjmp will land.  We expect that we have
38
   just entered longjmp and haven't yet altered r0, r1, so the
39
   arguments are still in the registers.  (A1_REGNUM) points at the
40
   jmp_buf structure from which we extract the pc (JB_PC) that we will
41
   land at.  The pc is copied into ADDR.  This routine returns true on
42
   success. */
43
 
44
#define LONGJMP_TARGET_SIZE     sizeof(int)
45
#define JB_ELEMENT_SIZE         sizeof(int)
46
#define JB_SL                   18
47
#define JB_FP                   19
48
#define JB_SP                   20
49
#define JB_PC                   21
50
 
51
int
52
arm_get_longjmp_target (CORE_ADDR * pc)
53
{
54
  CORE_ADDR jb_addr;
55
  char buf[LONGJMP_TARGET_SIZE];
56
 
57
  jb_addr = read_register (A1_REGNUM);
58
 
59
  if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
60
                          LONGJMP_TARGET_SIZE))
61
    return 0;
62
 
63
  *pc = extract_address (buf, LONGJMP_TARGET_SIZE);
64
  return 1;
65
}
66
 
67
#endif /* GET_LONGJMP_TARGET */
68
 
69
/* Extract from an array REGBUF containing the (raw) register state
70
   a function return value of type TYPE, and copy that, in virtual format,
71
   into VALBUF.  */
72
 
73
void
74
arm_linux_extract_return_value (struct type *type,
75
                                char regbuf[REGISTER_BYTES],
76
                                char *valbuf)
77
{
78
  /* ScottB: This needs to be looked at to handle the different
79
     floating point emulators on ARM Linux.  Right now the code
80
     assumes that fetch inferior registers does the right thing for
81
     GDB.  I suspect this won't handle NWFPE registers correctly, nor
82
     will the default ARM version (arm_extract_return_value()).  */
83
 
84
  int regnum = (TYPE_CODE_FLT == TYPE_CODE (type)) ? F0_REGNUM : A1_REGNUM;
85
  memcpy (valbuf, &regbuf[REGISTER_BYTE (regnum)], TYPE_LENGTH (type));
86
}
87
 
88
/* Note: ScottB
89
 
90
   This function does not support passing parameters using the FPA
91
   variant of the APCS.  It passes any floating point arguments in the
92
   general registers and/or on the stack.
93
 
94
   FIXME:  This and arm_push_arguments should be merged.  However this
95
           function breaks on a little endian host, big endian target
96
           using the COFF file format.  ELF is ok.
97
 
98
           ScottB.  */
99
 
100
/* Addresses for calling Thumb functions have the bit 0 set.
101
   Here are some macros to test, set, or clear bit 0 of addresses.  */
102
#define IS_THUMB_ADDR(addr)     ((addr) & 1)
103
#define MAKE_THUMB_ADDR(addr)   ((addr) | 1)
104
#define UNMAKE_THUMB_ADDR(addr) ((addr) & ~1)
105
 
106
CORE_ADDR
107
arm_linux_push_arguments (int nargs, value_ptr * args, CORE_ADDR sp,
108
                          int struct_return, CORE_ADDR struct_addr)
109
{
110
  char *fp;
111
  int argnum, argreg, nstack_size;
112
 
113
  /* Walk through the list of args and determine how large a temporary
114
     stack is required.  Need to take care here as structs may be
115
     passed on the stack, and we have to to push them.  */
116
  nstack_size = -4 * REGISTER_SIZE;     /* Some arguments go into A1-A4.  */
117
 
118
  if (struct_return)                    /* The struct address goes in A1.  */
119
    nstack_size += REGISTER_SIZE;
120
 
121
  /* Walk through the arguments and add their size to nstack_size.  */
122
  for (argnum = 0; argnum < nargs; argnum++)
123
    {
124
      int len;
125
      struct type *arg_type;
126
 
127
      arg_type = check_typedef (VALUE_TYPE (args[argnum]));
128
      len = TYPE_LENGTH (arg_type);
129
 
130
      /* ANSI C code passes float arguments as integers, K&R code
131
         passes float arguments as doubles.  Correct for this here.  */
132
      if (TYPE_CODE_FLT == TYPE_CODE (arg_type) && REGISTER_SIZE == len)
133
        nstack_size += FP_REGISTER_VIRTUAL_SIZE;
134
      else
135
        nstack_size += len;
136
    }
137
 
138
  /* Allocate room on the stack, and initialize our stack frame
139
     pointer.  */
140
  fp = NULL;
141
  if (nstack_size > 0)
142
    {
143
      sp -= nstack_size;
144
      fp = (char *) sp;
145
    }
146
 
147
  /* Initialize the integer argument register pointer.  */
148
  argreg = A1_REGNUM;
149
 
150
  /* The struct_return pointer occupies the first parameter passing
151
     register.  */
152
  if (struct_return)
153
    write_register (argreg++, struct_addr);
154
 
155
  /* Process arguments from left to right.  Store as many as allowed
156
     in the parameter passing registers (A1-A4), and save the rest on
157
     the temporary stack.  */
158
  for (argnum = 0; argnum < nargs; argnum++)
159
    {
160
      int len;
161
      char *val;
162
      double dbl_arg;
163
      CORE_ADDR regval;
164
      enum type_code typecode;
165
      struct type *arg_type, *target_type;
166
 
167
      arg_type = check_typedef (VALUE_TYPE (args[argnum]));
168
      target_type = TYPE_TARGET_TYPE (arg_type);
169
      len = TYPE_LENGTH (arg_type);
170
      typecode = TYPE_CODE (arg_type);
171
      val = (char *) VALUE_CONTENTS (args[argnum]);
172
 
173
      /* ANSI C code passes float arguments as integers, K&R code
174
         passes float arguments as doubles.  The .stabs record for
175
         for ANSI prototype floating point arguments records the
176
         type as FP_INTEGER, while a K&R style (no prototype)
177
         .stabs records the type as FP_FLOAT.  In this latter case
178
         the compiler converts the float arguments to double before
179
         calling the function.  */
180
      if (TYPE_CODE_FLT == typecode && REGISTER_SIZE == len)
181
        {
182
          /* Float argument in buffer is in host format.  Read it and
183
             convert to DOUBLEST, and store it in target double.  */
184
          DOUBLEST dblval;
185
 
186
          len = TARGET_DOUBLE_BIT / TARGET_CHAR_BIT;
187
          floatformat_to_doublest (HOST_FLOAT_FORMAT, val, &dblval);
188
          store_floating (&dbl_arg, len, dblval);
189
          val = (char *) &dbl_arg;
190
        }
191
 
192
      /* If the argument is a pointer to a function, and it is a Thumb
193
         function, set the low bit of the pointer.  */
194
      if (TYPE_CODE_PTR == typecode
195
          && NULL != target_type
196
          && TYPE_CODE_FUNC == TYPE_CODE (target_type))
197
        {
198
          CORE_ADDR regval = extract_address (val, len);
199
          if (arm_pc_is_thumb (regval))
200
            store_address (val, len, MAKE_THUMB_ADDR (regval));
201
        }
202
 
203
      /* Copy the argument to general registers or the stack in
204
         register-sized pieces.  Large arguments are split between
205
         registers and stack.  */
206
      while (len > 0)
207
        {
208
          int partial_len = len < REGISTER_SIZE ? len : REGISTER_SIZE;
209
 
210
          if (argreg <= ARM_LAST_ARG_REGNUM)
211
            {
212
              /* It's an argument being passed in a general register.  */
213
              regval = extract_address (val, partial_len);
214
              write_register (argreg++, regval);
215
            }
216
          else
217
            {
218
              /* Push the arguments onto the stack.  */
219
              write_memory ((CORE_ADDR) fp, val, REGISTER_SIZE);
220
              fp += REGISTER_SIZE;
221
            }
222
 
223
          len -= partial_len;
224
          val += partial_len;
225
        }
226
    }
227
 
228
  /* Return adjusted stack pointer.  */
229
  return sp;
230
}
231
 
232
/*
233
   Dynamic Linking on ARM Linux
234
   ----------------------------
235
 
236
   Note: PLT = procedure linkage table
237
   GOT = global offset table
238
 
239
   As much as possible, ELF dynamic linking defers the resolution of
240
   jump/call addresses until the last minute. The technique used is
241
   inspired by the i386 ELF design, and is based on the following
242
   constraints.
243
 
244
   1) The calling technique should not force a change in the assembly
245
   code produced for apps; it MAY cause changes in the way assembly
246
   code is produced for position independent code (i.e. shared
247
   libraries).
248
 
249
   2) The technique must be such that all executable areas must not be
250
   modified; and any modified areas must not be executed.
251
 
252
   To do this, there are three steps involved in a typical jump:
253
 
254
   1) in the code
255
   2) through the PLT
256
   3) using a pointer from the GOT
257
 
258
   When the executable or library is first loaded, each GOT entry is
259
   initialized to point to the code which implements dynamic name
260
   resolution and code finding.  This is normally a function in the
261
   program interpreter (on ARM Linux this is usually ld-linux.so.2,
262
   but it does not have to be).  On the first invocation, the function
263
   is located and the GOT entry is replaced with the real function
264
   address.  Subsequent calls go through steps 1, 2 and 3 and end up
265
   calling the real code.
266
 
267
   1) In the code:
268
 
269
   b    function_call
270
   bl   function_call
271
 
272
   This is typical ARM code using the 26 bit relative branch or branch
273
   and link instructions.  The target of the instruction
274
   (function_call is usually the address of the function to be called.
275
   In position independent code, the target of the instruction is
276
   actually an entry in the PLT when calling functions in a shared
277
   library.  Note that this call is identical to a normal function
278
   call, only the target differs.
279
 
280
   2) In the PLT:
281
 
282
   The PLT is a synthetic area, created by the linker. It exists in
283
   both executables and libraries. It is an array of stubs, one per
284
   imported function call. It looks like this:
285
 
286
   PLT[0]:
287
   str     lr, [sp, #-4]!       @push the return address (lr)
288
   ldr     lr, [pc, #16]   @load from 6 words ahead
289
   add     lr, pc, lr      @form an address for GOT[0]
290
   ldr     pc, [lr, #8]!   @jump to the contents of that addr
291
 
292
   The return address (lr) is pushed on the stack and used for
293
   calculations.  The load on the second line loads the lr with
294
   &GOT[3] - . - 20.  The addition on the third leaves:
295
 
296
   lr = (&GOT[3] - . - 20) + (. + 8)
297
   lr = (&GOT[3] - 12)
298
   lr = &GOT[0]
299
 
300
   On the fourth line, the pc and lr are both updated, so that:
301
 
302
   pc = GOT[2]
303
   lr = &GOT[0] + 8
304
   = &GOT[2]
305
 
306
   NOTE: PLT[0] borrows an offset .word from PLT[1]. This is a little
307
   "tight", but allows us to keep all the PLT entries the same size.
308
 
309
   PLT[n+1]:
310
   ldr     ip, [pc, #4]    @load offset from gotoff
311
   add     ip, pc, ip      @add the offset to the pc
312
   ldr     pc, [ip]        @jump to that address
313
   gotoff: .word   GOT[n+3] - .
314
 
315
   The load on the first line, gets an offset from the fourth word of
316
   the PLT entry.  The add on the second line makes ip = &GOT[n+3],
317
   which contains either a pointer to PLT[0] (the fixup trampoline) or
318
   a pointer to the actual code.
319
 
320
   3) In the GOT:
321
 
322
   The GOT contains helper pointers for both code (PLT) fixups and
323
   data fixups.  The first 3 entries of the GOT are special. The next
324
   M entries (where M is the number of entries in the PLT) belong to
325
   the PLT fixups. The next D (all remaining) entries belong to
326
   various data fixups. The actual size of the GOT is 3 + M + D.
327
 
328
   The GOT is also a synthetic area, created by the linker. It exists
329
   in both executables and libraries.  When the GOT is first
330
   initialized , all the GOT entries relating to PLT fixups are
331
   pointing to code back at PLT[0].
332
 
333
   The special entries in the GOT are:
334
 
335
   GOT[0] = linked list pointer used by the dynamic loader
336
   GOT[1] = pointer to the reloc table for this module
337
   GOT[2] = pointer to the fixup/resolver code
338
 
339
   The first invocation of function call comes through and uses the
340
   fixup/resolver code.  On the entry to the fixup/resolver code:
341
 
342
   ip = &GOT[n+3]
343
   lr = &GOT[2]
344
   stack[0] = return address (lr) of the function call
345
   [r0, r1, r2, r3] are still the arguments to the function call
346
 
347
   This is enough information for the fixup/resolver code to work
348
   with.  Before the fixup/resolver code returns, it actually calls
349
   the requested function and repairs &GOT[n+3].  */
350
 
351
/* Find the minimal symbol named NAME, and return both the minsym
352
   struct and its objfile.  This probably ought to be in minsym.c, but
353
   everything there is trying to deal with things like C++ and
354
   SOFUN_ADDRESS_MAYBE_TURQUOISE, ...  Since this is so simple, it may
355
   be considered too special-purpose for general consumption.  */
356
 
357
static struct minimal_symbol *
358
find_minsym_and_objfile (char *name, struct objfile **objfile_p)
359
{
360
  struct objfile *objfile;
361
 
362
  ALL_OBJFILES (objfile)
363
    {
364
      struct minimal_symbol *msym;
365
 
366
      ALL_OBJFILE_MSYMBOLS (objfile, msym)
367
        {
368
          if (SYMBOL_NAME (msym)
369
              && STREQ (SYMBOL_NAME (msym), name))
370
            {
371
              *objfile_p = objfile;
372
              return msym;
373
            }
374
        }
375
    }
376
 
377
  return 0;
378
}
379
 
380
 
381
static CORE_ADDR
382
skip_hurd_resolver (CORE_ADDR pc)
383
{
384
  /* The HURD dynamic linker is part of the GNU C library, so many
385
     GNU/Linux distributions use it.  (All ELF versions, as far as I
386
     know.)  An unresolved PLT entry points to "_dl_runtime_resolve",
387
     which calls "fixup" to patch the PLT, and then passes control to
388
     the function.
389
 
390
     We look for the symbol `_dl_runtime_resolve', and find `fixup' in
391
     the same objfile.  If we are at the entry point of `fixup', then
392
     we set a breakpoint at the return address (at the top of the
393
     stack), and continue.
394
 
395
     It's kind of gross to do all these checks every time we're
396
     called, since they don't change once the executable has gotten
397
     started.  But this is only a temporary hack --- upcoming versions
398
     of Linux will provide a portable, efficient interface for
399
     debugging programs that use shared libraries.  */
400
 
401
  struct objfile *objfile;
402
  struct minimal_symbol *resolver
403
    = find_minsym_and_objfile ("_dl_runtime_resolve", &objfile);
404
 
405
  if (resolver)
406
    {
407
      struct minimal_symbol *fixup
408
        = lookup_minimal_symbol ("fixup", 0, objfile);
409
 
410
      if (fixup && SYMBOL_VALUE_ADDRESS (fixup) == pc)
411
        return (SAVED_PC_AFTER_CALL (get_current_frame ()));
412
    }
413
 
414
  return 0;
415
}
416
 
417
/* See the comments for SKIP_SOLIB_RESOLVER at the top of infrun.c.
418
   This function:
419
   1) decides whether a PLT has sent us into the linker to resolve
420
      a function reference, and
421
   2) if so, tells us where to set a temporary breakpoint that will
422
      trigger when the dynamic linker is done.  */
423
 
424
CORE_ADDR
425
arm_linux_skip_solib_resolver (CORE_ADDR pc)
426
{
427
  CORE_ADDR result;
428
 
429
  /* Plug in functions for other kinds of resolvers here.  */
430
  result = skip_hurd_resolver (pc);
431
 
432
  if (result)
433
    return result;
434
 
435
  return 0;
436
}
437
 
438
/* The constants below were determined by examining the following files
439
   in the linux kernel sources:
440
 
441
      arch/arm/kernel/signal.c
442
          - see SWI_SYS_SIGRETURN and SWI_SYS_RT_SIGRETURN
443
      include/asm-arm/unistd.h
444
          - see __NR_sigreturn, __NR_rt_sigreturn, and __NR_SYSCALL_BASE */
445
 
446
#define ARM_LINUX_SIGRETURN_INSTR       0xef900077
447
#define ARM_LINUX_RT_SIGRETURN_INSTR    0xef9000ad
448
 
449
/* arm_linux_in_sigtramp determines if PC points at one of the
450
   instructions which cause control to return to the Linux kernel upon
451
   return from a signal handler.  FUNC_NAME is unused.  */
452
 
453
int
454
arm_linux_in_sigtramp (CORE_ADDR pc, char *func_name)
455
{
456
  unsigned long inst;
457
 
458
  inst = read_memory_integer (pc, 4);
459
 
460
  return (inst == ARM_LINUX_SIGRETURN_INSTR
461
          || inst == ARM_LINUX_RT_SIGRETURN_INSTR);
462
 
463
}
464
 
465
/* arm_linux_sigcontext_register_address returns the address in the
466
   sigcontext of register REGNO given a stack pointer value SP and
467
   program counter value PC.  The value 0 is returned if PC is not
468
   pointing at one of the signal return instructions or if REGNO is
469
   not saved in the sigcontext struct.  */
470
 
471
CORE_ADDR
472
arm_linux_sigcontext_register_address (CORE_ADDR sp, CORE_ADDR pc, int regno)
473
{
474
  unsigned long inst;
475
  CORE_ADDR reg_addr = 0;
476
 
477
  inst = read_memory_integer (pc, 4);
478
 
479
  if (inst == ARM_LINUX_SIGRETURN_INSTR || inst == ARM_LINUX_RT_SIGRETURN_INSTR)
480
    {
481
      CORE_ADDR sigcontext_addr;
482
 
483
      /* The sigcontext structure is at different places for the two
484
         signal return instructions.  For ARM_LINUX_SIGRETURN_INSTR,
485
         it starts at the SP value.  For ARM_LINUX_RT_SIGRETURN_INSTR,
486
         it is at SP+8.  For the latter instruction, it may also be
487
         the case that the address of this structure may be determined
488
         by reading the 4 bytes at SP, but I'm not convinced this is
489
         reliable.
490
 
491
         In any event, these magic constants (0 and 8) may be
492
         determined by examining struct sigframe and struct
493
         rt_sigframe in arch/arm/kernel/signal.c in the Linux kernel
494
         sources.  */
495
 
496
      if (inst == ARM_LINUX_RT_SIGRETURN_INSTR)
497
        sigcontext_addr = sp + 8;
498
      else /* inst == ARM_LINUX_SIGRETURN_INSTR */
499
        sigcontext_addr = sp + 0;
500
 
501
      /* The layout of the sigcontext structure for ARM GNU/Linux is
502
         in include/asm-arm/sigcontext.h in the Linux kernel sources.
503
 
504
         There are three 4-byte fields which precede the saved r0
505
         field.  (This accounts for the 12 in the code below.)  The
506
         sixteen registers (4 bytes per field) follow in order.  The
507
         PSR value follows the sixteen registers which accounts for
508
         the constant 19 below. */
509
 
510
      if (0 <= regno && regno <= PC_REGNUM)
511
        reg_addr = sigcontext_addr + 12 + (4 * regno);
512
      else if (regno == PS_REGNUM)
513
        reg_addr = sigcontext_addr + 19 * 4;
514
    }
515
 
516
  return reg_addr;
517
}
518
 
519
void
520
_initialize_arm_linux_tdep (void)
521
{
522
}

powered by: WebSVN 2.1.0

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