f73805030434a5cccd6717d9eedb3ec95007854a
1 /* GNU/Linux on ARM native support.
2 Copyright 1999 Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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. */
24 #include "gdb_string.h"
27 #include <sys/ptrace.h>
28 #include <sys/utsname.h>
30 extern int arm_apcs_32
;
33 #define typeSingle 0x01
34 #define typeDouble 0x02
35 #define typeExtended 0x03
37 #define CPSR_REGNUM 16
39 typedef union tagFPREG
42 unsigned int fDouble
[2];
43 unsigned int fExtended
[3];
47 typedef struct tagFPA11
49 FPREG fpreg
[8]; /* 8 floating point registers */
50 unsigned int fpsr
; /* floating point status register */
51 unsigned int fpcr
; /* floating point control register */
52 unsigned char fType
[8]; /* type of floating point value held in
53 floating point registers. */
54 int initflag
; /* NWFPE initialization flag. */
58 /* The following variables are used to determine the version of the
59 underlying Linux operating system. Examples:
61 Linux 2.0.35 Linux 2.2.12
62 os_version = 0x00020023 os_version = 0x0002020c
63 os_major = 2 os_major = 2
64 os_minor = 0 os_minor = 2
65 os_release = 35 os_release = 12
67 Note: os_version = (os_major << 16) | (os_minor << 8) | os_release
69 These are initialized using get_linux_version() from
70 _initialize_arm_linux_nat(). */
72 static unsigned int os_version
, os_major
, os_minor
, os_release
;
75 fetch_nw_fpe_single (unsigned int fn
, FPA11
* fpa11
, unsigned int *pmem
)
79 mem
[0] = fpa11
->fpreg
[fn
].fSingle
;
82 supply_register (F0_REGNUM
+ fn
, (char *) &mem
[0]);
86 fetch_nw_fpe_double (unsigned int fn
, FPA11
* fpa11
, unsigned int *pmem
)
90 mem
[0] = fpa11
->fpreg
[fn
].fDouble
[1];
91 mem
[1] = fpa11
->fpreg
[fn
].fDouble
[0];
93 supply_register (F0_REGNUM
+ fn
, (char *) &mem
[0]);
97 fetch_nw_fpe_none (unsigned int fn
, FPA11
* fpa11
, unsigned int *pmem
)
102 supply_register (F0_REGNUM
+ fn
, (char *) &mem
[0]);
106 fetch_nw_fpe_extended (unsigned int fn
, FPA11
* fpa11
, unsigned int *pmem
)
110 mem
[0] = fpa11
->fpreg
[fn
].fExtended
[0]; /* sign & exponent */
111 mem
[1] = fpa11
->fpreg
[fn
].fExtended
[2]; /* ls bits */
112 mem
[2] = fpa11
->fpreg
[fn
].fExtended
[1]; /* ms bits */
113 supply_register (F0_REGNUM
+ fn
, (char *) &mem
[0]);
117 store_nw_fpe_single (unsigned int fn
, FPA11
* fpa11
)
121 read_register_gen (F0_REGNUM
+ fn
, (char *) &mem
[0]);
122 fpa11
->fpreg
[fn
].fSingle
= mem
[0];
123 fpa11
->fType
[fn
] = typeSingle
;
127 store_nw_fpe_double (unsigned int fn
, FPA11
* fpa11
)
131 read_register_gen (F0_REGNUM
+ fn
, (char *) &mem
[0]);
132 fpa11
->fpreg
[fn
].fDouble
[1] = mem
[0];
133 fpa11
->fpreg
[fn
].fDouble
[0] = mem
[1];
134 fpa11
->fType
[fn
] = typeDouble
;
138 store_nw_fpe_extended (unsigned int fn
, FPA11
* fpa11
)
142 read_register_gen (F0_REGNUM
+ fn
, (char *) &mem
[0]);
143 fpa11
->fpreg
[fn
].fExtended
[0] = mem
[0]; /* sign & exponent */
144 fpa11
->fpreg
[fn
].fExtended
[2] = mem
[1]; /* ls bits */
145 fpa11
->fpreg
[fn
].fExtended
[1] = mem
[2]; /* ms bits */
146 fpa11
->fType
[fn
] = typeDouble
;
149 /* Get the whole floating point state of the process and store the
150 floating point stack into registers[]. */
158 /* Read the floating point state. */
159 ret
= ptrace (PT_GETFPREGS
, inferior_pid
, 0, &fp
);
162 warning ("Unable to fetch the floating point state.");
167 supply_register (FPS_REGNUM
, (char *) &fp
.fpsr
);
169 /* Fetch the floating point registers. */
170 for (regno
= F0_REGNUM
; regno
<= F7_REGNUM
; regno
++)
172 int fn
= regno
- F0_REGNUM
;
173 unsigned int *p
= (unsigned int *) ®isters
[REGISTER_BYTE (regno
)];
175 switch (fp
.fType
[fn
])
178 fetch_nw_fpe_single (fn
, &fp
, p
);
182 fetch_nw_fpe_double (fn
, &fp
, p
);
186 fetch_nw_fpe_extended (fn
, &fp
, p
);
190 fetch_nw_fpe_none (fn
, &fp
, p
);
195 /* Save the whole floating point state of the process using
196 the contents from registers[]. */
206 if (register_valid
[FPS_REGNUM
])
207 read_register_gen (FPS_REGNUM
, (char *) &fp
.fpsr
);
209 /* Store the floating point registers. */
210 for (regno
= F0_REGNUM
; regno
<= F7_REGNUM
; regno
++)
212 if (register_valid
[regno
])
214 unsigned int fn
= regno
- F0_REGNUM
;
215 switch (fp
.fType
[fn
])
218 store_nw_fpe_single (fn
, &fp
);
222 store_nw_fpe_double (fn
, &fp
);
226 store_nw_fpe_extended (fn
, &fp
);
232 ret
= ptrace (PTRACE_SETFPREGS
, inferior_pid
, 0, &fp
);
235 warning ("Unable to store floating point state.");
240 /* Fetch all general registers of the process and store into
249 ret
= ptrace (PTRACE_GETREGS
, inferior_pid
, 0, ®s
);
252 warning ("Unable to fetch general registers.");
256 for (regno
= A1_REGNUM
; regno
< PC_REGNUM
; regno
++)
257 supply_register (regno
, (char *) ®s
.uregs
[regno
]);
260 supply_register (PS_REGNUM
, (char *) ®s
.uregs
[CPSR_REGNUM
]);
262 supply_register (PS_REGNUM
, (char *) ®s
.uregs
[PC_REGNUM
]);
264 regs
.uregs
[PC_REGNUM
] = ADDR_BITS_REMOVE (regs
.uregs
[PC_REGNUM
]);
265 supply_register (PC_REGNUM
, (char *) ®s
.uregs
[PC_REGNUM
]);
268 /* Store all general registers of the process from the values in
277 ret
= ptrace (PTRACE_GETREGS
, inferior_pid
, 0, ®s
);
280 warning ("Unable to fetch general registers.");
284 for (regno
= A1_REGNUM
; regno
<= PC_REGNUM
; regno
++)
286 if (register_valid
[regno
])
287 read_register_gen (regno
, (char *) ®s
.uregs
[regno
]);
290 ret
= ptrace (PTRACE_SETREGS
, inferior_pid
, 0, ®s
);
294 warning ("Unable to store general registers.");
299 /* Fetch registers from the child process. Fetch all registers if
300 regno == -1, otherwise fetch all general registers or all floating
301 point registers depending upon the value of regno. */
304 fetch_inferior_registers (int regno
)
306 if ((regno
< F0_REGNUM
) || (regno
> FPS_REGNUM
))
309 if (((regno
>= F0_REGNUM
) && (regno
<= FPS_REGNUM
)) || (regno
== -1))
313 /* Store registers back into the inferior. Store all registers if
314 regno == -1, otherwise store all general registers or all floating
315 point registers depending upon the value of regno. */
318 store_inferior_registers (int regno
)
320 if ((regno
< F0_REGNUM
) || (regno
> FPS_REGNUM
))
323 if (((regno
>= F0_REGNUM
) && (regno
<= FPS_REGNUM
)) || (regno
== -1))
327 #ifdef GET_LONGJMP_TARGET
329 /* Figure out where the longjmp will land. We expect that we have
330 just entered longjmp and haven't yet altered r0, r1, so the
331 arguments are still in the registers. (A1_REGNUM) points at the
332 jmp_buf structure from which we extract the pc (JB_PC) that we will
333 land at. The pc is copied into ADDR. This routine returns true on
336 #define LONGJMP_TARGET_SIZE sizeof(int)
337 #define JB_ELEMENT_SIZE sizeof(int)
344 arm_get_longjmp_target (CORE_ADDR
* pc
)
347 char buf
[LONGJMP_TARGET_SIZE
];
349 jb_addr
= read_register (A1_REGNUM
);
351 if (target_read_memory (jb_addr
+ JB_PC
* JB_ELEMENT_SIZE
, buf
,
352 LONGJMP_TARGET_SIZE
))
355 *pc
= extract_address (buf
, LONGJMP_TARGET_SIZE
);
359 #endif /* GET_LONGJMP_TARGET */
362 Dynamic Linking on ARM Linux
363 ----------------------------
365 Note: PLT = procedure linkage table
366 GOT = global offset table
368 As much as possible, ELF dynamic linking defers the resolution of
369 jump/call addresses until the last minute. The technique used is
370 inspired by the i386 ELF design, and is based on the following
373 1) The calling technique should not force a change in the assembly
374 code produced for apps; it MAY cause changes in the way assembly
375 code is produced for position independent code (i.e. shared
378 2) The technique must be such that all executable areas must not be
379 modified; and any modified areas must not be executed.
381 To do this, there are three steps involved in a typical jump:
385 3) using a pointer from the GOT
387 When the executable or library is first loaded, each GOT entry is
388 initialized to point to the code which implements dynamic name
389 resolution and code finding. This is normally a function in the
390 program interpreter (on ARM Linux this is usually ld-linux.so.2,
391 but it does not have to be). On the first invocation, the function
392 is located and the GOT entry is replaced with the real function
393 address. Subsequent calls go through steps 1, 2 and 3 and end up
394 calling the real code.
401 This is typical ARM code using the 26 bit relative branch or branch
402 and link instructions. The target of the instruction
403 (function_call is usually the address of the function to be called.
404 In position independent code, the target of the instruction is
405 actually an entry in the PLT when calling functions in a shared
406 library. Note that this call is identical to a normal function
407 call, only the target differs.
411 The PLT is a synthetic area, created by the linker. It exists in
412 both executables and libraries. It is an array of stubs, one per
413 imported function call. It looks like this:
416 str lr, [sp, #-4]! @push the return address (lr)
417 ldr lr, [pc, #16] @load from 6 words ahead
418 add lr, pc, lr @form an address for GOT[0]
419 ldr pc, [lr, #8]! @jump to the contents of that addr
421 The return address (lr) is pushed on the stack and used for
422 calculations. The load on the second line loads the lr with
423 &GOT[3] - . - 20. The addition on the third leaves:
425 lr = (&GOT[3] - . - 20) + (. + 8)
429 On the fourth line, the pc and lr are both updated, so that:
435 NOTE: PLT[0] borrows an offset .word from PLT[1]. This is a little
436 "tight", but allows us to keep all the PLT entries the same size.
439 ldr ip, [pc, #4] @load offset from gotoff
440 add ip, pc, ip @add the offset to the pc
441 ldr pc, [ip] @jump to that address
442 gotoff: .word GOT[n+3] - .
444 The load on the first line, gets an offset from the fourth word of
445 the PLT entry. The add on the second line makes ip = &GOT[n+3],
446 which contains either a pointer to PLT[0] (the fixup trampoline) or
447 a pointer to the actual code.
451 The GOT contains helper pointers for both code (PLT) fixups and
452 data fixups. The first 3 entries of the GOT are special. The next
453 M entries (where M is the number of entries in the PLT) belong to
454 the PLT fixups. The next D (all remaining) entries belong to
455 various data fixups. The actual size of the GOT is 3 + M + D.
457 The GOT is also a synthetic area, created by the linker. It exists
458 in both executables and libraries. When the GOT is first
459 initialized , all the GOT entries relating to PLT fixups are
460 pointing to code back at PLT[0].
462 The special entries in the GOT are:
464 GOT[0] = linked list pointer used by the dynamic loader
465 GOT[1] = pointer to the reloc table for this module
466 GOT[2] = pointer to the fixup/resolver code
468 The first invocation of function call comes through and uses the
469 fixup/resolver code. On the entry to the fixup/resolver code:
473 stack[0] = return address (lr) of the function call
474 [r0, r1, r2, r3] are still the arguments to the function call
476 This is enough information for the fixup/resolver code to work
477 with. Before the fixup/resolver code returns, it actually calls
478 the requested function and repairs &GOT[n+3]. */
481 arm_skip_solib_resolver (CORE_ADDR pc
)
488 arm_linux_register_u_addr (int blockend
, int regnum
)
490 return blockend
+ REGISTER_BYTE (regnum
);
494 arm_linux_kernel_u_size (void)
496 return (sizeof (struct user
));
499 /* Extract from an array REGBUF containing the (raw) register state
500 a function return value of type TYPE, and copy that, in virtual format,
504 arm_linux_extract_return_value (struct type
*type
,
505 char regbuf
[REGISTER_BYTES
],
508 /* ScottB: This needs to be looked at to handle the different
509 floating point emulators on ARM Linux. Right now the code
510 assumes that fetch inferior registers does the right thing for
511 GDB. I suspect this won't handle NWFPE registers correctly, nor
512 will the default ARM version (arm_extract_return_value()). */
514 int regnum
= (TYPE_CODE_FLT
== TYPE_CODE (type
)) ? F0_REGNUM
: A1_REGNUM
;
515 memcpy (valbuf
, ®buf
[REGISTER_BYTE (regnum
)], TYPE_LENGTH (type
));
519 get_linux_version (unsigned int *vmajor
,
520 unsigned int *vminor
,
521 unsigned int *vrelease
)
524 char *pmajor
, *pminor
, *prelease
, *tail
;
526 if (-1 == uname (&info
))
528 warning ("Unable to determine Linux version.");
532 pmajor
= strtok (info
.release
, ".");
533 pminor
= strtok (NULL
, ".");
534 prelease
= strtok (NULL
, ".");
536 *vmajor
= (unsigned int) strtoul (pmajor
, &tail
, 0);
537 *vminor
= (unsigned int) strtoul (pminor
, &tail
, 0);
538 *vrelease
= (unsigned int) strtoul (prelease
, &tail
, 0);
540 return ((*vmajor
<< 16) | (*vminor
<< 8) | *vrelease
);
544 _initialize_arm_linux_nat (void)
546 os_version
= get_linux_version (&os_major
, &os_minor
, &os_release
);
This page took 0.066692 seconds and 4 git commands to generate.