eb3f41b0b93b5b418e9f77fe73830f1123b02bfa
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_nwfpe_single (unsigned int fn
, FPA11
* fpa11
)
79 mem
[0] = fpa11
->fpreg
[fn
].fSingle
;
82 supply_register (F0_REGNUM
+ fn
, (char *) &mem
[0]);
86 fetch_nwfpe_double (unsigned int fn
, FPA11
* fpa11
)
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_nwfpe_none (unsigned int fn
)
102 supply_register (F0_REGNUM
+ fn
, (char *) &mem
[0]);
106 fetch_nwfpe_extended (unsigned int fn
, FPA11
* fpa11
)
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_nwfpe_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_nwfpe_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_nwfpe_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_nwfpe_single (fn
, &fp
);
182 fetch_nwfpe_double (fn
, &fp
);
186 fetch_nwfpe_extended (fn
, &fp
);
190 fetch_nwfpe_none (fn
);
195 /* Save the whole floating point state of the process using
196 the contents from registers[]. */
205 if (register_valid
[FPS_REGNUM
])
206 read_register_gen (FPS_REGNUM
, (char *) &fp
.fpsr
);
208 /* Store the floating point registers. */
209 for (regno
= F0_REGNUM
; regno
<= F7_REGNUM
; regno
++)
211 if (register_valid
[regno
])
213 unsigned int fn
= regno
- F0_REGNUM
;
214 switch (fp
.fType
[fn
])
217 store_nwfpe_single (fn
, &fp
);
221 store_nwfpe_double (fn
, &fp
);
225 store_nwfpe_extended (fn
, &fp
);
231 ret
= ptrace (PTRACE_SETFPREGS
, inferior_pid
, 0, &fp
);
234 warning ("Unable to store floating point state.");
239 /* Fetch all general registers of the process and store into
248 ret
= ptrace (PTRACE_GETREGS
, inferior_pid
, 0, ®s
);
251 warning ("Unable to fetch general registers.");
255 for (regno
= A1_REGNUM
; regno
< PC_REGNUM
; regno
++)
256 supply_register (regno
, (char *) ®s
.uregs
[regno
]);
259 supply_register (PS_REGNUM
, (char *) ®s
.uregs
[CPSR_REGNUM
]);
261 supply_register (PS_REGNUM
, (char *) ®s
.uregs
[PC_REGNUM
]);
263 regs
.uregs
[PC_REGNUM
] = ADDR_BITS_REMOVE (regs
.uregs
[PC_REGNUM
]);
264 supply_register (PC_REGNUM
, (char *) ®s
.uregs
[PC_REGNUM
]);
267 /* Store all general registers of the process from the values in
276 ret
= ptrace (PTRACE_GETREGS
, inferior_pid
, 0, ®s
);
279 warning ("Unable to fetch general registers.");
283 for (regno
= A1_REGNUM
; regno
<= PC_REGNUM
; regno
++)
285 if (register_valid
[regno
])
286 read_register_gen (regno
, (char *) ®s
.uregs
[regno
]);
289 ret
= ptrace (PTRACE_SETREGS
, inferior_pid
, 0, ®s
);
293 warning ("Unable to store general registers.");
298 /* Fetch registers from the child process. Fetch all registers if
299 regno == -1, otherwise fetch all general registers or all floating
300 point registers depending upon the value of regno. */
303 fetch_inferior_registers (int regno
)
305 if ((regno
< F0_REGNUM
) || (regno
> FPS_REGNUM
))
308 if (((regno
>= F0_REGNUM
) && (regno
<= FPS_REGNUM
)) || (regno
== -1))
312 /* Store registers back into the inferior. Store all registers if
313 regno == -1, otherwise store all general registers or all floating
314 point registers depending upon the value of regno. */
317 store_inferior_registers (int regno
)
319 if ((regno
< F0_REGNUM
) || (regno
> FPS_REGNUM
))
322 if (((regno
>= F0_REGNUM
) && (regno
<= FPS_REGNUM
)) || (regno
== -1))
326 #ifdef GET_LONGJMP_TARGET
328 /* Figure out where the longjmp will land. We expect that we have
329 just entered longjmp and haven't yet altered r0, r1, so the
330 arguments are still in the registers. (A1_REGNUM) points at the
331 jmp_buf structure from which we extract the pc (JB_PC) that we will
332 land at. The pc is copied into ADDR. This routine returns true on
335 #define LONGJMP_TARGET_SIZE sizeof(int)
336 #define JB_ELEMENT_SIZE sizeof(int)
343 arm_get_longjmp_target (CORE_ADDR
* pc
)
346 char buf
[LONGJMP_TARGET_SIZE
];
348 jb_addr
= read_register (A1_REGNUM
);
350 if (target_read_memory (jb_addr
+ JB_PC
* JB_ELEMENT_SIZE
, buf
,
351 LONGJMP_TARGET_SIZE
))
354 *pc
= extract_address (buf
, LONGJMP_TARGET_SIZE
);
358 #endif /* GET_LONGJMP_TARGET */
361 Dynamic Linking on ARM Linux
362 ----------------------------
364 Note: PLT = procedure linkage table
365 GOT = global offset table
367 As much as possible, ELF dynamic linking defers the resolution of
368 jump/call addresses until the last minute. The technique used is
369 inspired by the i386 ELF design, and is based on the following
372 1) The calling technique should not force a change in the assembly
373 code produced for apps; it MAY cause changes in the way assembly
374 code is produced for position independent code (i.e. shared
377 2) The technique must be such that all executable areas must not be
378 modified; and any modified areas must not be executed.
380 To do this, there are three steps involved in a typical jump:
384 3) using a pointer from the GOT
386 When the executable or library is first loaded, each GOT entry is
387 initialized to point to the code which implements dynamic name
388 resolution and code finding. This is normally a function in the
389 program interpreter (on ARM Linux this is usually ld-linux.so.2,
390 but it does not have to be). On the first invocation, the function
391 is located and the GOT entry is replaced with the real function
392 address. Subsequent calls go through steps 1, 2 and 3 and end up
393 calling the real code.
400 This is typical ARM code using the 26 bit relative branch or branch
401 and link instructions. The target of the instruction
402 (function_call is usually the address of the function to be called.
403 In position independent code, the target of the instruction is
404 actually an entry in the PLT when calling functions in a shared
405 library. Note that this call is identical to a normal function
406 call, only the target differs.
410 The PLT is a synthetic area, created by the linker. It exists in
411 both executables and libraries. It is an array of stubs, one per
412 imported function call. It looks like this:
415 str lr, [sp, #-4]! @push the return address (lr)
416 ldr lr, [pc, #16] @load from 6 words ahead
417 add lr, pc, lr @form an address for GOT[0]
418 ldr pc, [lr, #8]! @jump to the contents of that addr
420 The return address (lr) is pushed on the stack and used for
421 calculations. The load on the second line loads the lr with
422 &GOT[3] - . - 20. The addition on the third leaves:
424 lr = (&GOT[3] - . - 20) + (. + 8)
428 On the fourth line, the pc and lr are both updated, so that:
434 NOTE: PLT[0] borrows an offset .word from PLT[1]. This is a little
435 "tight", but allows us to keep all the PLT entries the same size.
438 ldr ip, [pc, #4] @load offset from gotoff
439 add ip, pc, ip @add the offset to the pc
440 ldr pc, [ip] @jump to that address
441 gotoff: .word GOT[n+3] - .
443 The load on the first line, gets an offset from the fourth word of
444 the PLT entry. The add on the second line makes ip = &GOT[n+3],
445 which contains either a pointer to PLT[0] (the fixup trampoline) or
446 a pointer to the actual code.
450 The GOT contains helper pointers for both code (PLT) fixups and
451 data fixups. The first 3 entries of the GOT are special. The next
452 M entries (where M is the number of entries in the PLT) belong to
453 the PLT fixups. The next D (all remaining) entries belong to
454 various data fixups. The actual size of the GOT is 3 + M + D.
456 The GOT is also a synthetic area, created by the linker. It exists
457 in both executables and libraries. When the GOT is first
458 initialized , all the GOT entries relating to PLT fixups are
459 pointing to code back at PLT[0].
461 The special entries in the GOT are:
463 GOT[0] = linked list pointer used by the dynamic loader
464 GOT[1] = pointer to the reloc table for this module
465 GOT[2] = pointer to the fixup/resolver code
467 The first invocation of function call comes through and uses the
468 fixup/resolver code. On the entry to the fixup/resolver code:
472 stack[0] = return address (lr) of the function call
473 [r0, r1, r2, r3] are still the arguments to the function call
475 This is enough information for the fixup/resolver code to work
476 with. Before the fixup/resolver code returns, it actually calls
477 the requested function and repairs &GOT[n+3]. */
480 arm_skip_solib_resolver (CORE_ADDR pc
)
487 arm_linux_register_u_addr (int blockend
, int regnum
)
489 return blockend
+ REGISTER_BYTE (regnum
);
493 arm_linux_kernel_u_size (void)
495 return (sizeof (struct user
));
498 /* Extract from an array REGBUF containing the (raw) register state
499 a function return value of type TYPE, and copy that, in virtual format,
503 arm_linux_extract_return_value (struct type
*type
,
504 char regbuf
[REGISTER_BYTES
],
507 /* ScottB: This needs to be looked at to handle the different
508 floating point emulators on ARM Linux. Right now the code
509 assumes that fetch inferior registers does the right thing for
510 GDB. I suspect this won't handle NWFPE registers correctly, nor
511 will the default ARM version (arm_extract_return_value()). */
513 int regnum
= (TYPE_CODE_FLT
== TYPE_CODE (type
)) ? F0_REGNUM
: A1_REGNUM
;
514 memcpy (valbuf
, ®buf
[REGISTER_BYTE (regnum
)], TYPE_LENGTH (type
));
518 get_linux_version (unsigned int *vmajor
,
519 unsigned int *vminor
,
520 unsigned int *vrelease
)
523 char *pmajor
, *pminor
, *prelease
, *tail
;
525 if (-1 == uname (&info
))
527 warning ("Unable to determine Linux version.");
531 pmajor
= strtok (info
.release
, ".");
532 pminor
= strtok (NULL
, ".");
533 prelease
= strtok (NULL
, ".");
535 *vmajor
= (unsigned int) strtoul (pmajor
, &tail
, 0);
536 *vminor
= (unsigned int) strtoul (pminor
, &tail
, 0);
537 *vrelease
= (unsigned int) strtoul (prelease
, &tail
, 0);
539 return ((*vmajor
<< 16) | (*vminor
<< 8) | *vrelease
);
543 _initialize_arm_linux_nat (void)
545 os_version
= get_linux_version (&os_major
, &os_minor
, &os_release
);
This page took 0.040627 seconds and 4 git commands to generate.