import gdb-1999-12-21 snapshot
[deliverable/binutils-gdb.git] / gdb / arm-linux-nat.c
CommitLineData
ed9a39eb
JM
1/* GNU/Linux on ARM native support.
2 Copyright 1999 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 "inferior.h"
23#include "gdbcore.h"
24#include "gdb_string.h"
25
26#include <sys/user.h>
27#include <sys/ptrace.h>
28#include <sys/utsname.h>
29
30extern int arm_apcs_32;
31
32#define typeNone 0x00
33#define typeSingle 0x01
34#define typeDouble 0x02
35#define typeExtended 0x03
36#define FPWORDS 28
37#define CPSR_REGNUM 16
38
39typedef union tagFPREG
40 {
41 unsigned int fSingle;
42 unsigned int fDouble[2];
43 unsigned int fExtended[3];
44 }
45FPREG;
46
47typedef struct tagFPA11
48 {
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. */
55 }
56FPA11;
57
58/* The following variables are used to determine the version of the
59 underlying Linux operating system. Examples:
60
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
66
67 Note: os_version = (os_major << 16) | (os_minor << 8) | os_release
68
69 These are initialized using get_linux_version() from
70 _initialize_arm_linux_nat(). */
71
72static unsigned int os_version, os_major, os_minor, os_release;
73
74static void
75fetch_nw_fpe_single (unsigned int fn, FPA11 * fpa11, unsigned int *pmem)
76{
77 unsigned int mem[3];
78
79 mem[0] = fpa11->fpreg[fn].fSingle;
80 mem[1] = 0;
81 mem[2] = 0;
82 supply_register (F0_REGNUM + fn, (char *) &mem[0]);
83}
84
85static void
86fetch_nw_fpe_double (unsigned int fn, FPA11 * fpa11, unsigned int *pmem)
87{
88 unsigned int mem[3];
89
90 mem[0] = fpa11->fpreg[fn].fDouble[1];
91 mem[1] = fpa11->fpreg[fn].fDouble[0];
92 mem[2] = 0;
93 supply_register (F0_REGNUM + fn, (char *) &mem[0]);
94}
95
96static void
97fetch_nw_fpe_none (unsigned int fn, FPA11 * fpa11, unsigned int *pmem)
98{
99 unsigned int mem[3] =
100 {0, 0, 0};
101
102 supply_register (F0_REGNUM + fn, (char *) &mem[0]);
103}
104
105static void
106fetch_nw_fpe_extended (unsigned int fn, FPA11 * fpa11, unsigned int *pmem)
107{
108 unsigned int mem[3];
109
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]);
114}
115
116static void
117store_nw_fpe_single (unsigned int fn, FPA11 * fpa11)
118{
119 unsigned int mem[3];
120
121 read_register_gen (F0_REGNUM + fn, (char *) &mem[0]);
122 fpa11->fpreg[fn].fSingle = mem[0];
123 fpa11->fType[fn] = typeSingle;
124}
125
126static void
127store_nw_fpe_double (unsigned int fn, FPA11 * fpa11)
128{
129 unsigned int mem[3];
130
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;
135}
136
137void
138store_nw_fpe_extended (unsigned int fn, FPA11 * fpa11)
139{
140 unsigned int mem[3];
141
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;
147}
148
149/* Get the whole floating point state of the process and store the
150 floating point stack into registers[]. */
151
152static void
153fetch_fpregs (void)
154{
155 int ret, regno;
156 FPA11 fp;
157
158 /* Read the floating point state. */
159 ret = ptrace (PT_GETFPREGS, inferior_pid, 0, &fp);
160 if (ret < 0)
161 {
162 warning ("Unable to fetch the floating point state.");
163 return;
164 }
165
166 /* Fetch fpsr. */
167 supply_register (FPS_REGNUM, (char *) &fp.fpsr);
168
169 /* Fetch the floating point registers. */
170 for (regno = F0_REGNUM; regno <= F7_REGNUM; regno++)
171 {
172 int fn = regno - F0_REGNUM;
173 unsigned int *p = (unsigned int *) &registers[REGISTER_BYTE (regno)];
174
175 switch (fp.fType[fn])
176 {
177 case typeSingle:
178 fetch_nw_fpe_single (fn, &fp, p);
179 break;
180
181 case typeDouble:
182 fetch_nw_fpe_double (fn, &fp, p);
183 break;
184
185 case typeExtended:
186 fetch_nw_fpe_extended (fn, &fp, p);
187 break;
188
189 default:
190 fetch_nw_fpe_none (fn, &fp, p);
191 }
192 }
193}
194
195/* Save the whole floating point state of the process using
196 the contents from registers[]. */
197
198static void
199store_fpregs (void)
200{
201 int ret, regno;
202 unsigned int mem[3];
203 FPA11 fp;
204
205 /* Store fpsr. */
206 if (register_valid[FPS_REGNUM])
207 read_register_gen (FPS_REGNUM, (char *) &fp.fpsr);
208
209 /* Store the floating point registers. */
210 for (regno = F0_REGNUM; regno <= F7_REGNUM; regno++)
211 {
212 if (register_valid[regno])
213 {
214 unsigned int fn = regno - F0_REGNUM;
215 switch (fp.fType[fn])
216 {
217 case typeSingle:
218 store_nw_fpe_single (fn, &fp);
219 break;
220
221 case typeDouble:
222 store_nw_fpe_double (fn, &fp);
223 break;
224
225 case typeExtended:
226 store_nw_fpe_extended (fn, &fp);
227 break;
228 }
229 }
230 }
231
232 ret = ptrace (PTRACE_SETFPREGS, inferior_pid, 0, &fp);
233 if (ret < 0)
234 {
235 warning ("Unable to store floating point state.");
236 return;
237 }
238}
239
240/* Fetch all general registers of the process and store into
241 registers[]. */
242
243static void
244fetch_regs (void)
245{
246 int ret, regno;
247 struct pt_regs regs;
248
249 ret = ptrace (PTRACE_GETREGS, inferior_pid, 0, &regs);
250 if (ret < 0)
251 {
252 warning ("Unable to fetch general registers.");
253 return;
254 }
255
256 for (regno = A1_REGNUM; regno < PC_REGNUM; regno++)
257 supply_register (regno, (char *) &regs.uregs[regno]);
258
259 if (arm_apcs_32)
260 supply_register (PS_REGNUM, (char *) &regs.uregs[CPSR_REGNUM]);
261 else
262 supply_register (PS_REGNUM, (char *) &regs.uregs[PC_REGNUM]);
263
264 regs.uregs[PC_REGNUM] = ADDR_BITS_REMOVE (regs.uregs[PC_REGNUM]);
265 supply_register (PC_REGNUM, (char *) &regs.uregs[PC_REGNUM]);
266}
267
268/* Store all general registers of the process from the values in
269 registers[]. */
270
271static void
272store_regs (void)
273{
274 int ret, regno;
275 struct pt_regs regs;
276
277 ret = ptrace (PTRACE_GETREGS, inferior_pid, 0, &regs);
278 if (ret < 0)
279 {
280 warning ("Unable to fetch general registers.");
281 return;
282 }
283
284 for (regno = A1_REGNUM; regno <= PC_REGNUM; regno++)
285 {
286 if (register_valid[regno])
287 read_register_gen (regno, (char *) &regs.uregs[regno]);
288 }
289
290 ret = ptrace (PTRACE_SETREGS, inferior_pid, 0, &regs);
291
292 if (ret < 0)
293 {
294 warning ("Unable to store general registers.");
295 return;
296 }
297}
298
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. */
302
303void
304fetch_inferior_registers (int regno)
305{
306 if ((regno < F0_REGNUM) || (regno > FPS_REGNUM))
307 fetch_regs ();
308
309 if (((regno >= F0_REGNUM) && (regno <= FPS_REGNUM)) || (regno == -1))
310 fetch_fpregs ();
311}
312
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. */
316
317void
318store_inferior_registers (int regno)
319{
320 if ((regno < F0_REGNUM) || (regno > FPS_REGNUM))
321 store_regs ();
322
323 if (((regno >= F0_REGNUM) && (regno <= FPS_REGNUM)) || (regno == -1))
324 store_fpregs ();
325}
326
327#ifdef GET_LONGJMP_TARGET
328
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
334 success. */
335
336#define LONGJMP_TARGET_SIZE sizeof(int)
337#define JB_ELEMENT_SIZE sizeof(int)
338#define JB_SL 18
339#define JB_FP 19
340#define JB_SP 20
341#define JB_PC 21
342
343int
344arm_get_longjmp_target (CORE_ADDR * pc)
345{
346 CORE_ADDR jb_addr;
347 char buf[LONGJMP_TARGET_SIZE];
348
349 jb_addr = read_register (A1_REGNUM);
350
351 if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
352 LONGJMP_TARGET_SIZE))
353 return 0;
354
355 *pc = extract_address (buf, LONGJMP_TARGET_SIZE);
356 return 1;
357}
358
359#endif /* GET_LONGJMP_TARGET */
360
361/*
362 Dynamic Linking on ARM Linux
363 ----------------------------
364
365 Note: PLT = procedure linkage table
366 GOT = global offset table
367
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
371 constraints.
372
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
376 libraries).
377
378 2) The technique must be such that all executable areas must not be
379 modified; and any modified areas must not be executed.
380
381 To do this, there are three steps involved in a typical jump:
382
383 1) in the code
384 2) through the PLT
385 3) using a pointer from the GOT
386
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.
395
396 1) In the code:
397
398 b function_call
399 bl function_call
400
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.
408
409 2) In the PLT:
410
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:
414
415 PLT[0]:
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
420
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:
424
425 lr = (&GOT[3] - . - 20) + (. + 8)
426 lr = (&GOT[3] - 12)
427 lr = &GOT[0]
428
429 On the fourth line, the pc and lr are both updated, so that:
430
431 pc = GOT[2]
432 lr = &GOT[0] + 8
433 = &GOT[2]
434
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.
437
438 PLT[n+1]:
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] - .
443
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.
448
449 3) In the GOT:
450
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.
456
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].
461
462 The special entries in the GOT are:
463
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
467
468 The first invocation of function call comes through and uses the
469 fixup/resolver code. On the entry to the fixup/resolver code:
470
471 ip = &GOT[n+3]
472 lr = &GOT[2]
473 stack[0] = return address (lr) of the function call
474 [r0, r1, r2, r3] are still the arguments to the function call
475
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]. */
479
480CORE_ADDR
481arm_skip_solib_resolver (CORE_ADDR pc)
482{
483 /* FIXME */
484 return 0;
485}
486
487int
488arm_linux_register_u_addr (int blockend, int regnum)
489{
490 return blockend + REGISTER_BYTE (regnum);
491}
492
493int
494arm_linux_kernel_u_size (void)
495{
496 return (sizeof (struct user));
497}
498
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,
501 into VALBUF. */
502
503void
504arm_linux_extract_return_value (struct type *type,
505 char regbuf[REGISTER_BYTES],
506 char *valbuf)
507{
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()). */
513
514 int regnum = (TYPE_CODE_FLT == TYPE_CODE (type)) ? F0_REGNUM : A1_REGNUM;
515 memcpy (valbuf, &regbuf[REGISTER_BYTE (regnum)], TYPE_LENGTH (type));
516}
517
518static unsigned int
519get_linux_version (unsigned int *vmajor,
520 unsigned int *vminor,
521 unsigned int *vrelease)
522{
523 struct utsname info;
524 char *pmajor, *pminor, *prelease, *tail;
525
526 if (-1 == uname (&info))
527 {
528 warning ("Unable to determine Linux version.");
529 return -1;
530 }
531
532 pmajor = strtok (info.release, ".");
533 pminor = strtok (NULL, ".");
534 prelease = strtok (NULL, ".");
535
536 *vmajor = (unsigned int) strtoul (pmajor, &tail, 0);
537 *vminor = (unsigned int) strtoul (pminor, &tail, 0);
538 *vrelease = (unsigned int) strtoul (prelease, &tail, 0);
539
540 return ((*vmajor << 16) | (*vminor << 8) | *vrelease);
541}
542
543void
544_initialize_arm_linux_nat (void)
545{
546 os_version = get_linux_version (&os_major, &os_minor, &os_release);
547}
This page took 0.041956 seconds and 4 git commands to generate.