2004-01-09 Elena Zannoni <ezannoni@redhat.com>
[deliverable/binutils-gdb.git] / gdb / mips-linux-tdep.c
CommitLineData
75c9abc6 1/* Target-dependent code for GNU/Linux on MIPS processors.
a094c6fb
AC
2
3 Copyright 2001, 2002 Free Software Foundation, Inc.
2aa830e4
DJ
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22#include "defs.h"
23#include "gdbcore.h"
24#include "target.h"
25#include "solib-svr4.h"
19ed69dd 26#include "osabi.h"
96f026fc 27#include "mips-tdep.h"
19ed69dd 28#include "gdb_string.h"
96f026fc 29#include "gdb_assert.h"
2aa830e4
DJ
30
31/* Copied from <asm/elf.h>. */
32#define ELF_NGREG 45
33#define ELF_NFPREG 33
34
35typedef unsigned char elf_greg_t[4];
36typedef elf_greg_t elf_gregset_t[ELF_NGREG];
37
38typedef unsigned char elf_fpreg_t[8];
39typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
40
41/* 0 - 31 are integer registers, 32 - 63 are fp registers. */
42#define FPR_BASE 32
43#define PC 64
44#define CAUSE 65
45#define BADVADDR 66
46#define MMHI 67
47#define MMLO 68
48#define FPC_CSR 69
49#define FPC_EIR 70
50
51#define EF_REG0 6
52#define EF_REG31 37
53#define EF_LO 38
54#define EF_HI 39
55#define EF_CP0_EPC 40
56#define EF_CP0_BADVADDR 41
57#define EF_CP0_STATUS 42
58#define EF_CP0_CAUSE 43
59
60#define EF_SIZE 180
61
62/* Figure out where the longjmp will land.
63 We expect the first arg to be a pointer to the jmp_buf structure from
bf072999
DJ
64 which we extract the pc (MIPS_LINUX_JB_PC) that we will land at. The pc
65 is copied into PC. This routine returns 1 on success. */
2aa830e4 66
19ed69dd
KB
67#define MIPS_LINUX_JB_ELEMENT_SIZE 4
68#define MIPS_LINUX_JB_PC 0
69
70static int
2aa830e4
DJ
71mips_linux_get_longjmp_target (CORE_ADDR *pc)
72{
73 CORE_ADDR jb_addr;
74 char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
75
76 jb_addr = read_register (A0_REGNUM);
77
bf072999
DJ
78 if (target_read_memory (jb_addr
79 + MIPS_LINUX_JB_PC * MIPS_LINUX_JB_ELEMENT_SIZE,
80 buf, TARGET_PTR_BIT / TARGET_CHAR_BIT))
2aa830e4
DJ
81 return 0;
82
7c0b4a20 83 *pc = extract_unsigned_integer (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
2aa830e4
DJ
84
85 return 1;
86}
87
4246e332
AC
88/* Transform the bits comprising a 32-bit register to the right size
89 for supply_register(). This is needed when mips_regsize() is 8. */
96f026fc
KB
90
91static void
92supply_32bit_reg (int regnum, const void *addr)
93{
d9d9c31f 94 char buf[MAX_REGISTER_SIZE];
12c266ea 95 store_signed_integer (buf, DEPRECATED_REGISTER_RAW_SIZE (regnum),
96f026fc
KB
96 extract_signed_integer (addr, 4));
97 supply_register (regnum, buf);
98}
99
2aa830e4
DJ
100/* Unpack an elf_gregset_t into GDB's register cache. */
101
102void
103supply_gregset (elf_gregset_t *gregsetp)
104{
105 int regi;
106 elf_greg_t *regp = *gregsetp;
d9d9c31f 107 char zerobuf[MAX_REGISTER_SIZE];
bf072999 108
d9d9c31f 109 memset (zerobuf, 0, MAX_REGISTER_SIZE);
2aa830e4
DJ
110
111 for (regi = EF_REG0; regi <= EF_REG31; regi++)
96f026fc 112 supply_32bit_reg ((regi - EF_REG0), (char *)(regp + regi));
2aa830e4 113
56cea623
AC
114 supply_32bit_reg (mips_regnum (current_gdbarch)->lo,
115 (char *)(regp + EF_LO));
116 supply_32bit_reg (mips_regnum (current_gdbarch)->hi,
117 (char *)(regp + EF_HI));
118
119 supply_32bit_reg (mips_regnum (current_gdbarch)->pc,
120 (char *)(regp + EF_CP0_EPC));
121 supply_32bit_reg (mips_regnum (current_gdbarch)->badvaddr,
122 (char *)(regp + EF_CP0_BADVADDR));
96f026fc 123 supply_32bit_reg (PS_REGNUM, (char *)(regp + EF_CP0_STATUS));
56cea623
AC
124 supply_32bit_reg (mips_regnum (current_gdbarch)->cause,
125 (char *)(regp + EF_CP0_CAUSE));
2aa830e4
DJ
126
127 /* Fill inaccessible registers with zero. */
2aa830e4
DJ
128 supply_register (UNUSED_REGNUM, zerobuf);
129 for (regi = FIRST_EMBED_REGNUM; regi < LAST_EMBED_REGNUM; regi++)
130 supply_register (regi, zerobuf);
131}
132
133/* Pack our registers (or one register) into an elf_gregset_t. */
134
135void
136fill_gregset (elf_gregset_t *gregsetp, int regno)
137{
138 int regaddr, regi;
139 elf_greg_t *regp = *gregsetp;
96f026fc 140 void *dst;
2aa830e4
DJ
141
142 if (regno == -1)
143 {
144 memset (regp, 0, sizeof (elf_gregset_t));
145 for (regi = 0; regi < 32; regi++)
146 fill_gregset (gregsetp, regi);
56cea623
AC
147 fill_gregset (gregsetp, mips_regnum (current_gdbarch)->lo);
148 fill_gregset (gregsetp, mips_regnum (current_gdbarch)->hi);
149 fill_gregset (gregsetp, mips_regnum (current_gdbarch)->pc);
150 fill_gregset (gregsetp, mips_regnum (current_gdbarch)->badvaddr);
2aa830e4 151 fill_gregset (gregsetp, PS_REGNUM);
56cea623 152 fill_gregset (gregsetp, mips_regnum (current_gdbarch)->cause);
2aa830e4
DJ
153
154 return;
155 }
156
157 if (regno < 32)
158 {
2aa830e4 159 dst = regp + regno + EF_REG0;
96f026fc 160 regcache_collect (regno, dst);
2aa830e4
DJ
161 return;
162 }
163
56cea623
AC
164 if (regno == mips_regnum (current_gdbarch)->lo)
165 regaddr = EF_LO;
166 else if (regno == mips_regnum (current_gdbarch)->hi)
167 regaddr = EF_HI;
168 else if (regno == mips_regnum (current_gdbarch)->pc)
169 regaddr = EF_CP0_EPC;
170 else if (regno == mips_regnum (current_gdbarch)->badvaddr)
171 regaddr = EF_CP0_BADVADDR;
172 else if (regno == PS_REGNUM)
173 regaddr = EF_CP0_STATUS;
174 else if (regno == mips_regnum (current_gdbarch)->cause)
175 regaddr = EF_CP0_CAUSE;
176 else
177 regaddr = -1;
2aa830e4
DJ
178
179 if (regaddr != -1)
180 {
2aa830e4 181 dst = regp + regaddr;
96f026fc 182 regcache_collect (regno, dst);
2aa830e4
DJ
183 }
184}
185
186/* Likewise, unpack an elf_fpregset_t. */
187
188void
189supply_fpregset (elf_fpregset_t *fpregsetp)
190{
52f0bd74 191 int regi;
d9d9c31f 192 char zerobuf[MAX_REGISTER_SIZE];
bf072999 193
d9d9c31f 194 memset (zerobuf, 0, MAX_REGISTER_SIZE);
2aa830e4
DJ
195
196 for (regi = 0; regi < 32; regi++)
197 supply_register (FP0_REGNUM + regi,
198 (char *)(*fpregsetp + regi));
199
56cea623
AC
200 supply_register (mips_regnum (current_gdbarch)->fp_control_status,
201 (char *)(*fpregsetp + 32));
2aa830e4 202
56cea623
AC
203 /* FIXME: how can we supply FCRIR? The ABI doesn't tell us. */
204 supply_register (mips_regnum (current_gdbarch)->fp_implementation_revision,
205 zerobuf);
2aa830e4
DJ
206}
207
208/* Likewise, pack one or all floating point registers into an
209 elf_fpregset_t. */
210
211void
212fill_fpregset (elf_fpregset_t *fpregsetp, int regno)
213{
214 char *from, *to;
215
216 if ((regno >= FP0_REGNUM) && (regno < FP0_REGNUM + 32))
217 {
62700349 218 from = (char *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)];
2aa830e4 219 to = (char *) (*fpregsetp + regno - FP0_REGNUM);
12c266ea 220 memcpy (to, from, DEPRECATED_REGISTER_RAW_SIZE (regno - FP0_REGNUM));
2aa830e4 221 }
56cea623 222 else if (regno == mips_regnum (current_gdbarch)->fp_control_status)
2aa830e4 223 {
62700349 224 from = (char *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)];
2aa830e4 225 to = (char *) (*fpregsetp + 32);
12c266ea 226 memcpy (to, from, DEPRECATED_REGISTER_RAW_SIZE (regno));
2aa830e4
DJ
227 }
228 else if (regno == -1)
229 {
230 int regi;
231
232 for (regi = 0; regi < 32; regi++)
233 fill_fpregset (fpregsetp, FP0_REGNUM + regi);
56cea623 234 fill_fpregset(fpregsetp, mips_regnum (current_gdbarch)->fp_control_status);
2aa830e4
DJ
235 }
236}
237
238/* Map gdb internal register number to ptrace ``address''.
239 These ``addresses'' are normally defined in <asm/ptrace.h>. */
240
96f026fc
KB
241static CORE_ADDR
242mips_linux_register_addr (int regno, CORE_ADDR blockend)
2aa830e4
DJ
243{
244 int regaddr;
245
246 if (regno < 0 || regno >= NUM_REGS)
247 error ("Bogon register number %d.", regno);
248
249 if (regno < 32)
250 regaddr = regno;
56cea623
AC
251 else if ((regno >= mips_regnum (current_gdbarch)->fp0)
252 && (regno < mips_regnum (current_gdbarch)->fp0 + 32))
253 regaddr = FPR_BASE + (regno - mips_regnum (current_gdbarch)->fp0);
254 else if (regno == mips_regnum (current_gdbarch)->pc)
2aa830e4 255 regaddr = PC;
56cea623 256 else if (regno == mips_regnum (current_gdbarch)->cause)
2aa830e4 257 regaddr = CAUSE;
56cea623 258 else if (regno == mips_regnum (current_gdbarch)->badvaddr)
2aa830e4 259 regaddr = BADVADDR;
56cea623 260 else if (regno == mips_regnum (current_gdbarch)->lo)
2aa830e4 261 regaddr = MMLO;
56cea623 262 else if (regno == mips_regnum (current_gdbarch)->hi)
2aa830e4 263 regaddr = MMHI;
56cea623 264 else if (regno == mips_regnum (current_gdbarch)->fp_control_status)
2aa830e4 265 regaddr = FPC_CSR;
56cea623 266 else if (regno == mips_regnum (current_gdbarch)->fp_implementation_revision)
2aa830e4
DJ
267 regaddr = FPC_EIR;
268 else
269 error ("Unknowable register number %d.", regno);
270
271 return regaddr;
272}
273
96f026fc
KB
274
275/* Fetch (and possibly build) an appropriate link_map_offsets
276 structure for native GNU/Linux MIPS targets using the struct offsets
277 defined in link.h (but without actual reference to that file).
278
279 This makes it possible to access GNU/Linux MIPS shared libraries from a
280 GDB that was built on a different host platform (for cross debugging). */
281
282static struct link_map_offsets *
283mips_linux_svr4_fetch_link_map_offsets (void)
284{
285 static struct link_map_offsets lmo;
286 static struct link_map_offsets *lmp = NULL;
287
288 if (lmp == NULL)
289 {
290 lmp = &lmo;
291
292 lmo.r_debug_size = 8; /* The actual size is 20 bytes, but
293 this is all we need. */
294 lmo.r_map_offset = 4;
295 lmo.r_map_size = 4;
296
297 lmo.link_map_size = 20;
298
299 lmo.l_addr_offset = 0;
300 lmo.l_addr_size = 4;
301
302 lmo.l_name_offset = 4;
303 lmo.l_name_size = 4;
304
305 lmo.l_next_offset = 12;
306 lmo.l_next_size = 4;
307
308 lmo.l_prev_offset = 16;
309 lmo.l_prev_size = 4;
310 }
311
312 return lmp;
313}
314
315/* Support for 64-bit ABIs. */
316
317/* Copied from <asm/elf.h>. */
318#define MIPS64_ELF_NGREG 45
319#define MIPS64_ELF_NFPREG 33
320
321typedef unsigned char mips64_elf_greg_t[8];
322typedef mips64_elf_greg_t mips64_elf_gregset_t[MIPS64_ELF_NGREG];
323
324typedef unsigned char mips64_elf_fpreg_t[8];
325typedef mips64_elf_fpreg_t mips64_elf_fpregset_t[MIPS64_ELF_NFPREG];
326
327/* 0 - 31 are integer registers, 32 - 63 are fp registers. */
328#define MIPS64_FPR_BASE 32
329#define MIPS64_PC 64
330#define MIPS64_CAUSE 65
331#define MIPS64_BADVADDR 66
332#define MIPS64_MMHI 67
333#define MIPS64_MMLO 68
334#define MIPS64_FPC_CSR 69
335#define MIPS64_FPC_EIR 70
336
337#define MIPS64_EF_REG0 0
338#define MIPS64_EF_REG31 31
339#define MIPS64_EF_LO 32
340#define MIPS64_EF_HI 33
341#define MIPS64_EF_CP0_EPC 34
342#define MIPS64_EF_CP0_BADVADDR 35
343#define MIPS64_EF_CP0_STATUS 36
344#define MIPS64_EF_CP0_CAUSE 37
345
346#define MIPS64_EF_SIZE 304
347
348/* Figure out where the longjmp will land.
349 We expect the first arg to be a pointer to the jmp_buf structure from
350 which we extract the pc (MIPS_LINUX_JB_PC) that we will land at. The pc
351 is copied into PC. This routine returns 1 on success. */
352
353/* Details about jmp_buf. */
354
355#define MIPS64_LINUX_JB_PC 0
356
357static int
358mips64_linux_get_longjmp_target (CORE_ADDR *pc)
359{
360 CORE_ADDR jb_addr;
361 void *buf = alloca (TARGET_PTR_BIT / TARGET_CHAR_BIT);
362 int element_size = TARGET_PTR_BIT == 32 ? 4 : 8;
363
364 jb_addr = read_register (A0_REGNUM);
365
366 if (target_read_memory (jb_addr + MIPS64_LINUX_JB_PC * element_size,
367 buf, TARGET_PTR_BIT / TARGET_CHAR_BIT))
368 return 0;
369
7c0b4a20 370 *pc = extract_unsigned_integer (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
96f026fc
KB
371
372 return 1;
373}
374
375/* Unpack an elf_gregset_t into GDB's register cache. */
376
377static void
378mips64_supply_gregset (mips64_elf_gregset_t *gregsetp)
379{
380 int regi;
381 mips64_elf_greg_t *regp = *gregsetp;
d9d9c31f 382 char zerobuf[MAX_REGISTER_SIZE];
96f026fc 383
d9d9c31f 384 memset (zerobuf, 0, MAX_REGISTER_SIZE);
96f026fc
KB
385
386 for (regi = MIPS64_EF_REG0; regi <= MIPS64_EF_REG31; regi++)
387 supply_register ((regi - MIPS64_EF_REG0), (char *)(regp + regi));
388
56cea623
AC
389 supply_register (mips_regnum (current_gdbarch)->lo,
390 (char *)(regp + MIPS64_EF_LO));
391 supply_register (mips_regnum (current_gdbarch)->hi,
392 (char *)(regp + MIPS64_EF_HI));
96f026fc 393
56cea623
AC
394 supply_register (mips_regnum (current_gdbarch)->pc,
395 (char *)(regp + MIPS64_EF_CP0_EPC));
396 supply_register (mips_regnum (current_gdbarch)->badvaddr,
397 (char *)(regp + MIPS64_EF_CP0_BADVADDR));
96f026fc 398 supply_register (PS_REGNUM, (char *)(regp + MIPS64_EF_CP0_STATUS));
56cea623
AC
399 supply_register (mips_regnum (current_gdbarch)->cause,
400 (char *)(regp + MIPS64_EF_CP0_CAUSE));
96f026fc
KB
401
402 /* Fill inaccessible registers with zero. */
403 supply_register (UNUSED_REGNUM, zerobuf);
404 for (regi = FIRST_EMBED_REGNUM; regi < LAST_EMBED_REGNUM; regi++)
405 supply_register (regi, zerobuf);
406}
407
408/* Pack our registers (or one register) into an elf_gregset_t. */
409
410static void
411mips64_fill_gregset (mips64_elf_gregset_t *gregsetp, int regno)
412{
413 int regaddr, regi;
414 mips64_elf_greg_t *regp = *gregsetp;
415 void *src, *dst;
416
417 if (regno == -1)
418 {
419 memset (regp, 0, sizeof (mips64_elf_gregset_t));
420 for (regi = 0; regi < 32; regi++)
421 mips64_fill_gregset (gregsetp, regi);
56cea623
AC
422 mips64_fill_gregset (gregsetp, mips_regnum (current_gdbarch)->lo);
423 mips64_fill_gregset (gregsetp, mips_regnum (current_gdbarch)->hi);
424 mips64_fill_gregset (gregsetp, mips_regnum (current_gdbarch)->pc);
425 mips64_fill_gregset (gregsetp, mips_regnum (current_gdbarch)->badvaddr);
96f026fc 426 mips64_fill_gregset (gregsetp, PS_REGNUM);
56cea623 427 mips64_fill_gregset (gregsetp, mips_regnum (current_gdbarch)->cause);
96f026fc
KB
428
429 return;
430 }
431
432 if (regno < 32)
433 {
434 dst = regp + regno + MIPS64_EF_REG0;
435 regcache_collect (regno, dst);
436 return;
437 }
438
56cea623
AC
439 if (regno == mips_regnum (current_gdbarch)->lo)
440 regaddr = MIPS64_EF_LO;
441 else if (regno == mips_regnum (current_gdbarch)->hi)
442 regaddr = MIPS64_EF_HI;
443 else if (regno == mips_regnum (current_gdbarch)->pc)
444 regaddr = MIPS64_EF_CP0_EPC;
445 else if (regno == mips_regnum (current_gdbarch)->badvaddr)
446 regaddr = MIPS64_EF_CP0_BADVADDR;
447 else if (regno == PS_REGNUM)
448 regaddr = MIPS64_EF_CP0_STATUS;
449 else if (regno == mips_regnum (current_gdbarch)->cause)
450 regaddr = MIPS64_EF_CP0_CAUSE;
451 else
452 regaddr = -1;
96f026fc
KB
453
454 if (regaddr != -1)
455 {
456 dst = regp + regaddr;
457 regcache_collect (regno, dst);
458 }
459}
460
461/* Likewise, unpack an elf_fpregset_t. */
462
463static void
464mips64_supply_fpregset (mips64_elf_fpregset_t *fpregsetp)
465{
52f0bd74 466 int regi;
d9d9c31f 467 char zerobuf[MAX_REGISTER_SIZE];
96f026fc 468
d9d9c31f 469 memset (zerobuf, 0, MAX_REGISTER_SIZE);
96f026fc
KB
470
471 for (regi = 0; regi < 32; regi++)
472 supply_register (FP0_REGNUM + regi,
473 (char *)(*fpregsetp + regi));
474
56cea623
AC
475 supply_register (mips_regnum (current_gdbarch)->fp_control_status,
476 (char *)(*fpregsetp + 32));
96f026fc 477
56cea623
AC
478 /* FIXME: how can we supply FCRIR? The ABI doesn't tell us. */
479 supply_register (mips_regnum (current_gdbarch)->fp_implementation_revision,
480 zerobuf);
96f026fc
KB
481}
482
483/* Likewise, pack one or all floating point registers into an
484 elf_fpregset_t. */
485
486static void
487mips64_fill_fpregset (mips64_elf_fpregset_t *fpregsetp, int regno)
488{
489 char *from, *to;
490
491 if ((regno >= FP0_REGNUM) && (regno < FP0_REGNUM + 32))
492 {
62700349 493 from = (char *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)];
96f026fc 494 to = (char *) (*fpregsetp + regno - FP0_REGNUM);
12c266ea 495 memcpy (to, from, DEPRECATED_REGISTER_RAW_SIZE (regno - FP0_REGNUM));
96f026fc 496 }
56cea623 497 else if (regno == mips_regnum (current_gdbarch)->fp_control_status)
96f026fc 498 {
62700349 499 from = (char *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)];
96f026fc 500 to = (char *) (*fpregsetp + 32);
12c266ea 501 memcpy (to, from, DEPRECATED_REGISTER_RAW_SIZE (regno));
96f026fc
KB
502 }
503 else if (regno == -1)
504 {
505 int regi;
506
507 for (regi = 0; regi < 32; regi++)
508 mips64_fill_fpregset (fpregsetp, FP0_REGNUM + regi);
56cea623
AC
509 mips64_fill_fpregset(fpregsetp,
510 mips_regnum (current_gdbarch)->fp_control_status);
96f026fc
KB
511 }
512}
513
514
515/* Map gdb internal register number to ptrace ``address''.
516 These ``addresses'' are normally defined in <asm/ptrace.h>. */
517
518static CORE_ADDR
519mips64_linux_register_addr (int regno, CORE_ADDR blockend)
520{
521 int regaddr;
522
523 if (regno < 0 || regno >= NUM_REGS)
524 error ("Bogon register number %d.", regno);
525
526 if (regno < 32)
527 regaddr = regno;
56cea623
AC
528 else if ((regno >= mips_regnum (current_gdbarch)->fp0)
529 && (regno < mips_regnum (current_gdbarch)->fp0 + 32))
96f026fc 530 regaddr = MIPS64_FPR_BASE + (regno - FP0_REGNUM);
56cea623 531 else if (regno == mips_regnum (current_gdbarch)->pc)
96f026fc 532 regaddr = MIPS64_PC;
56cea623 533 else if (regno == mips_regnum (current_gdbarch)->cause)
96f026fc 534 regaddr = MIPS64_CAUSE;
56cea623 535 else if (regno == mips_regnum (current_gdbarch)->badvaddr)
96f026fc 536 regaddr = MIPS64_BADVADDR;
56cea623 537 else if (regno == mips_regnum (current_gdbarch)->lo)
96f026fc 538 regaddr = MIPS64_MMLO;
56cea623 539 else if (regno == mips_regnum (current_gdbarch)->hi)
96f026fc 540 regaddr = MIPS64_MMHI;
56cea623 541 else if (regno == mips_regnum (current_gdbarch)->fp_control_status)
96f026fc 542 regaddr = MIPS64_FPC_CSR;
56cea623 543 else if (regno == mips_regnum (current_gdbarch)->fp_implementation_revision)
96f026fc
KB
544 regaddr = MIPS64_FPC_EIR;
545 else
546 error ("Unknowable register number %d.", regno);
547
548 return regaddr;
549}
550
2aa830e4
DJ
551/* Use a local version of this function to get the correct types for
552 regsets, until multi-arch core support is ready. */
553
554static void
555fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
556 int which, CORE_ADDR reg_addr)
557{
558 elf_gregset_t gregset;
559 elf_fpregset_t fpregset;
96f026fc
KB
560 mips64_elf_gregset_t gregset64;
561 mips64_elf_fpregset_t fpregset64;
2aa830e4
DJ
562
563 if (which == 0)
564 {
96f026fc 565 if (core_reg_size == sizeof (gregset))
2aa830e4 566 {
96f026fc
KB
567 memcpy ((char *) &gregset, core_reg_sect, sizeof (gregset));
568 supply_gregset (&gregset);
569 }
570 else if (core_reg_size == sizeof (gregset64))
571 {
572 memcpy ((char *) &gregset64, core_reg_sect, sizeof (gregset64));
573 mips64_supply_gregset (&gregset64);
2aa830e4
DJ
574 }
575 else
576 {
96f026fc 577 warning ("wrong size gregset struct in core file");
2aa830e4
DJ
578 }
579 }
580 else if (which == 2)
581 {
96f026fc 582 if (core_reg_size == sizeof (fpregset))
2aa830e4 583 {
96f026fc
KB
584 memcpy ((char *) &fpregset, core_reg_sect, sizeof (fpregset));
585 supply_fpregset (&fpregset);
586 }
587 else if (core_reg_size == sizeof (fpregset64))
588 {
589 memcpy ((char *) &fpregset64, core_reg_sect, sizeof (fpregset64));
590 mips64_supply_fpregset (&fpregset64);
2aa830e4
DJ
591 }
592 else
593 {
96f026fc 594 warning ("wrong size fpregset struct in core file");
2aa830e4
DJ
595 }
596 }
597}
598
599/* Register that we are able to handle ELF file formats using standard
600 procfs "regset" structures. */
601
602static struct core_fns regset_core_fns =
603{
604 bfd_target_elf_flavour, /* core_flavour */
605 default_check_format, /* check_format */
606 default_core_sniffer, /* core_sniffer */
607 fetch_core_registers, /* core_read_registers */
608 NULL /* next */
609};
610
611/* Fetch (and possibly build) an appropriate link_map_offsets
75c9abc6 612 structure for native GNU/Linux MIPS targets using the struct offsets
2aa830e4
DJ
613 defined in link.h (but without actual reference to that file).
614
75c9abc6
DJ
615 This makes it possible to access GNU/Linux MIPS shared libraries from a
616 GDB that was built on a different host platform (for cross debugging). */
2aa830e4 617
19ed69dd 618static struct link_map_offsets *
96f026fc 619mips64_linux_svr4_fetch_link_map_offsets (void)
2aa830e4
DJ
620{
621 static struct link_map_offsets lmo;
622 static struct link_map_offsets *lmp = NULL;
623
624 if (lmp == NULL)
625 {
626 lmp = &lmo;
627
96f026fc 628 lmo.r_debug_size = 16; /* The actual size is 40 bytes, but
2aa830e4 629 this is all we need. */
96f026fc
KB
630 lmo.r_map_offset = 8;
631 lmo.r_map_size = 8;
2aa830e4 632
96f026fc 633 lmo.link_map_size = 40;
2aa830e4
DJ
634
635 lmo.l_addr_offset = 0;
96f026fc 636 lmo.l_addr_size = 8;
2aa830e4 637
96f026fc
KB
638 lmo.l_name_offset = 8;
639 lmo.l_name_size = 8;
2aa830e4 640
96f026fc
KB
641 lmo.l_next_offset = 24;
642 lmo.l_next_size = 8;
2aa830e4 643
96f026fc
KB
644 lmo.l_prev_offset = 32;
645 lmo.l_prev_size = 8;
2aa830e4
DJ
646 }
647
648 return lmp;
649}
650
96f026fc
KB
651/* Handle for obtaining pointer to the current register_addr() function
652 for a given architecture. */
653static struct gdbarch_data *register_addr_data;
654
655CORE_ADDR
656register_addr (int regno, CORE_ADDR blockend)
657{
658 CORE_ADDR (*register_addr_ptr) (int, CORE_ADDR) =
659 gdbarch_data (current_gdbarch, register_addr_data);
660
661 gdb_assert (register_addr_ptr != 0);
662
663 return register_addr_ptr (regno, blockend);
664}
665
666static void
667set_mips_linux_register_addr (struct gdbarch *gdbarch,
668 CORE_ADDR (*register_addr_ptr) (int, CORE_ADDR))
669{
670 set_gdbarch_data (gdbarch, register_addr_data, register_addr_ptr);
671}
672
673static void *
674init_register_addr_data (struct gdbarch *gdbarch)
675{
676 return 0;
677}
678
19ed69dd
KB
679static void
680mips_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
681{
96f026fc
KB
682 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
683 enum mips_abi abi = mips_abi (gdbarch);
684
685 switch (abi)
686 {
687 case MIPS_ABI_O32:
688 set_gdbarch_get_longjmp_target (gdbarch,
689 mips_linux_get_longjmp_target);
690 set_solib_svr4_fetch_link_map_offsets
691 (gdbarch, mips_linux_svr4_fetch_link_map_offsets);
692 set_mips_linux_register_addr (gdbarch, mips_linux_register_addr);
693 break;
694 case MIPS_ABI_N32:
695 set_gdbarch_get_longjmp_target (gdbarch,
696 mips_linux_get_longjmp_target);
697 set_solib_svr4_fetch_link_map_offsets
698 (gdbarch, mips_linux_svr4_fetch_link_map_offsets);
699 set_mips_linux_register_addr (gdbarch, mips64_linux_register_addr);
700 break;
701 case MIPS_ABI_N64:
702 set_gdbarch_get_longjmp_target (gdbarch,
703 mips64_linux_get_longjmp_target);
704 set_solib_svr4_fetch_link_map_offsets
705 (gdbarch, mips64_linux_svr4_fetch_link_map_offsets);
706 set_mips_linux_register_addr (gdbarch, mips64_linux_register_addr);
707 break;
708 default:
709 internal_error (__FILE__, __LINE__, "can't handle ABI");
710 break;
711 }
19ed69dd
KB
712}
713
2aa830e4 714void
d1bacddc 715_initialize_mips_linux_tdep (void)
2aa830e4 716{
96f026fc
KB
717 const struct bfd_arch_info *arch_info;
718
719 register_addr_data =
1062ca82 720 register_gdbarch_data (init_register_addr_data);
96f026fc
KB
721
722 for (arch_info = bfd_lookup_arch (bfd_arch_mips, 0);
723 arch_info != NULL;
724 arch_info = arch_info->next)
725 {
726 gdbarch_register_osabi (bfd_arch_mips, arch_info->mach, GDB_OSABI_LINUX,
727 mips_linux_init_abi);
728 }
729
2aa830e4
DJ
730 add_core_fns (&regset_core_fns);
731}
This page took 0.276413 seconds and 4 git commands to generate.