2003-11-16 Andrew Cagney <cagney@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
96f026fc
KB
114 supply_32bit_reg (LO_REGNUM, (char *)(regp + EF_LO));
115 supply_32bit_reg (HI_REGNUM, (char *)(regp + EF_HI));
2aa830e4 116
96f026fc
KB
117 supply_32bit_reg (PC_REGNUM, (char *)(regp + EF_CP0_EPC));
118 supply_32bit_reg (BADVADDR_REGNUM, (char *)(regp + EF_CP0_BADVADDR));
119 supply_32bit_reg (PS_REGNUM, (char *)(regp + EF_CP0_STATUS));
120 supply_32bit_reg (CAUSE_REGNUM, (char *)(regp + EF_CP0_CAUSE));
2aa830e4
DJ
121
122 /* Fill inaccessible registers with zero. */
2aa830e4
DJ
123 supply_register (UNUSED_REGNUM, zerobuf);
124 for (regi = FIRST_EMBED_REGNUM; regi < LAST_EMBED_REGNUM; regi++)
125 supply_register (regi, zerobuf);
126}
127
128/* Pack our registers (or one register) into an elf_gregset_t. */
129
130void
131fill_gregset (elf_gregset_t *gregsetp, int regno)
132{
133 int regaddr, regi;
134 elf_greg_t *regp = *gregsetp;
96f026fc 135 void *dst;
2aa830e4
DJ
136
137 if (regno == -1)
138 {
139 memset (regp, 0, sizeof (elf_gregset_t));
140 for (regi = 0; regi < 32; regi++)
141 fill_gregset (gregsetp, regi);
142 fill_gregset (gregsetp, LO_REGNUM);
143 fill_gregset (gregsetp, HI_REGNUM);
144 fill_gregset (gregsetp, PC_REGNUM);
145 fill_gregset (gregsetp, BADVADDR_REGNUM);
146 fill_gregset (gregsetp, PS_REGNUM);
147 fill_gregset (gregsetp, CAUSE_REGNUM);
148
149 return;
150 }
151
152 if (regno < 32)
153 {
2aa830e4 154 dst = regp + regno + EF_REG0;
96f026fc 155 regcache_collect (regno, dst);
2aa830e4
DJ
156 return;
157 }
158
159 regaddr = -1;
160 switch (regno)
161 {
162 case LO_REGNUM:
163 regaddr = EF_LO;
164 break;
165 case HI_REGNUM:
166 regaddr = EF_HI;
167 break;
168 case PC_REGNUM:
169 regaddr = EF_CP0_EPC;
170 break;
171 case BADVADDR_REGNUM:
172 regaddr = EF_CP0_BADVADDR;
173 break;
174 case PS_REGNUM:
175 regaddr = EF_CP0_STATUS;
176 break;
177 case CAUSE_REGNUM:
178 regaddr = EF_CP0_CAUSE;
179 break;
180 }
181
182 if (regaddr != -1)
183 {
2aa830e4 184 dst = regp + regaddr;
96f026fc 185 regcache_collect (regno, dst);
2aa830e4
DJ
186 }
187}
188
189/* Likewise, unpack an elf_fpregset_t. */
190
191void
192supply_fpregset (elf_fpregset_t *fpregsetp)
193{
52f0bd74 194 int regi;
d9d9c31f 195 char zerobuf[MAX_REGISTER_SIZE];
bf072999 196
d9d9c31f 197 memset (zerobuf, 0, MAX_REGISTER_SIZE);
2aa830e4
DJ
198
199 for (regi = 0; regi < 32; regi++)
200 supply_register (FP0_REGNUM + regi,
201 (char *)(*fpregsetp + regi));
202
203 supply_register (FCRCS_REGNUM, (char *)(*fpregsetp + 32));
204
205 /* FIXME: how can we supply FCRIR_REGNUM? The ABI doesn't tell us. */
206 supply_register (FCRIR_REGNUM, zerobuf);
207}
208
209/* Likewise, pack one or all floating point registers into an
210 elf_fpregset_t. */
211
212void
213fill_fpregset (elf_fpregset_t *fpregsetp, int regno)
214{
215 char *from, *to;
216
217 if ((regno >= FP0_REGNUM) && (regno < FP0_REGNUM + 32))
218 {
62700349 219 from = (char *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)];
2aa830e4 220 to = (char *) (*fpregsetp + regno - FP0_REGNUM);
12c266ea 221 memcpy (to, from, DEPRECATED_REGISTER_RAW_SIZE (regno - FP0_REGNUM));
2aa830e4
DJ
222 }
223 else if (regno == FCRCS_REGNUM)
224 {
62700349 225 from = (char *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)];
2aa830e4 226 to = (char *) (*fpregsetp + 32);
12c266ea 227 memcpy (to, from, DEPRECATED_REGISTER_RAW_SIZE (regno));
2aa830e4
DJ
228 }
229 else if (regno == -1)
230 {
231 int regi;
232
233 for (regi = 0; regi < 32; regi++)
234 fill_fpregset (fpregsetp, FP0_REGNUM + regi);
235 fill_fpregset(fpregsetp, FCRCS_REGNUM);
236 }
237}
238
239/* Map gdb internal register number to ptrace ``address''.
240 These ``addresses'' are normally defined in <asm/ptrace.h>. */
241
96f026fc
KB
242static CORE_ADDR
243mips_linux_register_addr (int regno, CORE_ADDR blockend)
2aa830e4
DJ
244{
245 int regaddr;
246
247 if (regno < 0 || regno >= NUM_REGS)
248 error ("Bogon register number %d.", regno);
249
250 if (regno < 32)
251 regaddr = regno;
252 else if ((regno >= FP0_REGNUM) && (regno < FP0_REGNUM + 32))
253 regaddr = FPR_BASE + (regno - FP0_REGNUM);
254 else if (regno == PC_REGNUM)
255 regaddr = PC;
256 else if (regno == CAUSE_REGNUM)
257 regaddr = CAUSE;
258 else if (regno == BADVADDR_REGNUM)
259 regaddr = BADVADDR;
260 else if (regno == LO_REGNUM)
261 regaddr = MMLO;
262 else if (regno == HI_REGNUM)
263 regaddr = MMHI;
264 else if (regno == FCRCS_REGNUM)
265 regaddr = FPC_CSR;
266 else if (regno == FCRIR_REGNUM)
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
389 supply_register (LO_REGNUM, (char *)(regp + MIPS64_EF_LO));
390 supply_register (HI_REGNUM, (char *)(regp + MIPS64_EF_HI));
391
392 supply_register (PC_REGNUM, (char *)(regp + MIPS64_EF_CP0_EPC));
393 supply_register (BADVADDR_REGNUM, (char *)(regp + MIPS64_EF_CP0_BADVADDR));
394 supply_register (PS_REGNUM, (char *)(regp + MIPS64_EF_CP0_STATUS));
395 supply_register (CAUSE_REGNUM, (char *)(regp + MIPS64_EF_CP0_CAUSE));
396
397 /* Fill inaccessible registers with zero. */
398 supply_register (UNUSED_REGNUM, zerobuf);
399 for (regi = FIRST_EMBED_REGNUM; regi < LAST_EMBED_REGNUM; regi++)
400 supply_register (regi, zerobuf);
401}
402
403/* Pack our registers (or one register) into an elf_gregset_t. */
404
405static void
406mips64_fill_gregset (mips64_elf_gregset_t *gregsetp, int regno)
407{
408 int regaddr, regi;
409 mips64_elf_greg_t *regp = *gregsetp;
410 void *src, *dst;
411
412 if (regno == -1)
413 {
414 memset (regp, 0, sizeof (mips64_elf_gregset_t));
415 for (regi = 0; regi < 32; regi++)
416 mips64_fill_gregset (gregsetp, regi);
417 mips64_fill_gregset (gregsetp, LO_REGNUM);
418 mips64_fill_gregset (gregsetp, HI_REGNUM);
419 mips64_fill_gregset (gregsetp, PC_REGNUM);
420 mips64_fill_gregset (gregsetp, BADVADDR_REGNUM);
421 mips64_fill_gregset (gregsetp, PS_REGNUM);
422 mips64_fill_gregset (gregsetp, CAUSE_REGNUM);
423
424 return;
425 }
426
427 if (regno < 32)
428 {
429 dst = regp + regno + MIPS64_EF_REG0;
430 regcache_collect (regno, dst);
431 return;
432 }
433
434 regaddr = -1;
435 switch (regno)
436 {
437 case LO_REGNUM:
438 regaddr = MIPS64_EF_LO;
439 break;
440 case HI_REGNUM:
441 regaddr = MIPS64_EF_HI;
442 break;
443 case PC_REGNUM:
444 regaddr = MIPS64_EF_CP0_EPC;
445 break;
446 case BADVADDR_REGNUM:
447 regaddr = MIPS64_EF_CP0_BADVADDR;
448 break;
449 case PS_REGNUM:
450 regaddr = MIPS64_EF_CP0_STATUS;
451 break;
452 case CAUSE_REGNUM:
453 regaddr = MIPS64_EF_CP0_CAUSE;
454 break;
455 }
456
457 if (regaddr != -1)
458 {
459 dst = regp + regaddr;
460 regcache_collect (regno, dst);
461 }
462}
463
464/* Likewise, unpack an elf_fpregset_t. */
465
466static void
467mips64_supply_fpregset (mips64_elf_fpregset_t *fpregsetp)
468{
52f0bd74 469 int regi;
d9d9c31f 470 char zerobuf[MAX_REGISTER_SIZE];
96f026fc 471
d9d9c31f 472 memset (zerobuf, 0, MAX_REGISTER_SIZE);
96f026fc
KB
473
474 for (regi = 0; regi < 32; regi++)
475 supply_register (FP0_REGNUM + regi,
476 (char *)(*fpregsetp + regi));
477
478 supply_register (FCRCS_REGNUM, (char *)(*fpregsetp + 32));
479
480 /* FIXME: how can we supply FCRIR_REGNUM? The ABI doesn't tell us. */
481 supply_register (FCRIR_REGNUM, zerobuf);
482}
483
484/* Likewise, pack one or all floating point registers into an
485 elf_fpregset_t. */
486
487static void
488mips64_fill_fpregset (mips64_elf_fpregset_t *fpregsetp, int regno)
489{
490 char *from, *to;
491
492 if ((regno >= FP0_REGNUM) && (regno < FP0_REGNUM + 32))
493 {
62700349 494 from = (char *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)];
96f026fc 495 to = (char *) (*fpregsetp + regno - FP0_REGNUM);
12c266ea 496 memcpy (to, from, DEPRECATED_REGISTER_RAW_SIZE (regno - FP0_REGNUM));
96f026fc
KB
497 }
498 else if (regno == FCRCS_REGNUM)
499 {
62700349 500 from = (char *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)];
96f026fc 501 to = (char *) (*fpregsetp + 32);
12c266ea 502 memcpy (to, from, DEPRECATED_REGISTER_RAW_SIZE (regno));
96f026fc
KB
503 }
504 else if (regno == -1)
505 {
506 int regi;
507
508 for (regi = 0; regi < 32; regi++)
509 mips64_fill_fpregset (fpregsetp, FP0_REGNUM + regi);
510 mips64_fill_fpregset(fpregsetp, FCRCS_REGNUM);
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;
528 else if ((regno >= FP0_REGNUM) && (regno < FP0_REGNUM + 32))
529 regaddr = MIPS64_FPR_BASE + (regno - FP0_REGNUM);
530 else if (regno == PC_REGNUM)
531 regaddr = MIPS64_PC;
532 else if (regno == CAUSE_REGNUM)
533 regaddr = MIPS64_CAUSE;
534 else if (regno == BADVADDR_REGNUM)
535 regaddr = MIPS64_BADVADDR;
536 else if (regno == LO_REGNUM)
537 regaddr = MIPS64_MMLO;
538 else if (regno == HI_REGNUM)
539 regaddr = MIPS64_MMHI;
540 else if (regno == FCRCS_REGNUM)
541 regaddr = MIPS64_FPC_CSR;
542 else if (regno == FCRIR_REGNUM)
543 regaddr = MIPS64_FPC_EIR;
544 else
545 error ("Unknowable register number %d.", regno);
546
547 return regaddr;
548}
549
2aa830e4
DJ
550/* Use a local version of this function to get the correct types for
551 regsets, until multi-arch core support is ready. */
552
553static void
554fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
555 int which, CORE_ADDR reg_addr)
556{
557 elf_gregset_t gregset;
558 elf_fpregset_t fpregset;
96f026fc
KB
559 mips64_elf_gregset_t gregset64;
560 mips64_elf_fpregset_t fpregset64;
2aa830e4
DJ
561
562 if (which == 0)
563 {
96f026fc 564 if (core_reg_size == sizeof (gregset))
2aa830e4 565 {
96f026fc
KB
566 memcpy ((char *) &gregset, core_reg_sect, sizeof (gregset));
567 supply_gregset (&gregset);
568 }
569 else if (core_reg_size == sizeof (gregset64))
570 {
571 memcpy ((char *) &gregset64, core_reg_sect, sizeof (gregset64));
572 mips64_supply_gregset (&gregset64);
2aa830e4
DJ
573 }
574 else
575 {
96f026fc 576 warning ("wrong size gregset struct in core file");
2aa830e4
DJ
577 }
578 }
579 else if (which == 2)
580 {
96f026fc 581 if (core_reg_size == sizeof (fpregset))
2aa830e4 582 {
96f026fc
KB
583 memcpy ((char *) &fpregset, core_reg_sect, sizeof (fpregset));
584 supply_fpregset (&fpregset);
585 }
586 else if (core_reg_size == sizeof (fpregset64))
587 {
588 memcpy ((char *) &fpregset64, core_reg_sect, sizeof (fpregset64));
589 mips64_supply_fpregset (&fpregset64);
2aa830e4
DJ
590 }
591 else
592 {
96f026fc 593 warning ("wrong size fpregset struct in core file");
2aa830e4
DJ
594 }
595 }
596}
597
598/* Register that we are able to handle ELF file formats using standard
599 procfs "regset" structures. */
600
601static struct core_fns regset_core_fns =
602{
603 bfd_target_elf_flavour, /* core_flavour */
604 default_check_format, /* check_format */
605 default_core_sniffer, /* core_sniffer */
606 fetch_core_registers, /* core_read_registers */
607 NULL /* next */
608};
609
610/* Fetch (and possibly build) an appropriate link_map_offsets
75c9abc6 611 structure for native GNU/Linux MIPS targets using the struct offsets
2aa830e4
DJ
612 defined in link.h (but without actual reference to that file).
613
75c9abc6
DJ
614 This makes it possible to access GNU/Linux MIPS shared libraries from a
615 GDB that was built on a different host platform (for cross debugging). */
2aa830e4 616
19ed69dd 617static struct link_map_offsets *
96f026fc 618mips64_linux_svr4_fetch_link_map_offsets (void)
2aa830e4
DJ
619{
620 static struct link_map_offsets lmo;
621 static struct link_map_offsets *lmp = NULL;
622
623 if (lmp == NULL)
624 {
625 lmp = &lmo;
626
96f026fc 627 lmo.r_debug_size = 16; /* The actual size is 40 bytes, but
2aa830e4 628 this is all we need. */
96f026fc
KB
629 lmo.r_map_offset = 8;
630 lmo.r_map_size = 8;
2aa830e4 631
96f026fc 632 lmo.link_map_size = 40;
2aa830e4
DJ
633
634 lmo.l_addr_offset = 0;
96f026fc 635 lmo.l_addr_size = 8;
2aa830e4 636
96f026fc
KB
637 lmo.l_name_offset = 8;
638 lmo.l_name_size = 8;
2aa830e4 639
96f026fc
KB
640 lmo.l_next_offset = 24;
641 lmo.l_next_size = 8;
2aa830e4 642
96f026fc
KB
643 lmo.l_prev_offset = 32;
644 lmo.l_prev_size = 8;
2aa830e4
DJ
645 }
646
647 return lmp;
648}
649
96f026fc
KB
650/* Handle for obtaining pointer to the current register_addr() function
651 for a given architecture. */
652static struct gdbarch_data *register_addr_data;
653
654CORE_ADDR
655register_addr (int regno, CORE_ADDR blockend)
656{
657 CORE_ADDR (*register_addr_ptr) (int, CORE_ADDR) =
658 gdbarch_data (current_gdbarch, register_addr_data);
659
660 gdb_assert (register_addr_ptr != 0);
661
662 return register_addr_ptr (regno, blockend);
663}
664
665static void
666set_mips_linux_register_addr (struct gdbarch *gdbarch,
667 CORE_ADDR (*register_addr_ptr) (int, CORE_ADDR))
668{
669 set_gdbarch_data (gdbarch, register_addr_data, register_addr_ptr);
670}
671
672static void *
673init_register_addr_data (struct gdbarch *gdbarch)
674{
675 return 0;
676}
677
19ed69dd
KB
678static void
679mips_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
680{
96f026fc
KB
681 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
682 enum mips_abi abi = mips_abi (gdbarch);
683
684 switch (abi)
685 {
686 case MIPS_ABI_O32:
687 set_gdbarch_get_longjmp_target (gdbarch,
688 mips_linux_get_longjmp_target);
689 set_solib_svr4_fetch_link_map_offsets
690 (gdbarch, mips_linux_svr4_fetch_link_map_offsets);
691 set_mips_linux_register_addr (gdbarch, mips_linux_register_addr);
692 break;
693 case MIPS_ABI_N32:
694 set_gdbarch_get_longjmp_target (gdbarch,
695 mips_linux_get_longjmp_target);
696 set_solib_svr4_fetch_link_map_offsets
697 (gdbarch, mips_linux_svr4_fetch_link_map_offsets);
698 set_mips_linux_register_addr (gdbarch, mips64_linux_register_addr);
699 break;
700 case MIPS_ABI_N64:
701 set_gdbarch_get_longjmp_target (gdbarch,
702 mips64_linux_get_longjmp_target);
703 set_solib_svr4_fetch_link_map_offsets
704 (gdbarch, mips64_linux_svr4_fetch_link_map_offsets);
705 set_mips_linux_register_addr (gdbarch, mips64_linux_register_addr);
706 break;
707 default:
708 internal_error (__FILE__, __LINE__, "can't handle ABI");
709 break;
710 }
19ed69dd
KB
711}
712
2aa830e4 713void
d1bacddc 714_initialize_mips_linux_tdep (void)
2aa830e4 715{
96f026fc
KB
716 const struct bfd_arch_info *arch_info;
717
718 register_addr_data =
1062ca82 719 register_gdbarch_data (init_register_addr_data);
96f026fc
KB
720
721 for (arch_info = bfd_lookup_arch (bfd_arch_mips, 0);
722 arch_info != NULL;
723 arch_info = arch_info->next)
724 {
725 gdbarch_register_osabi (bfd_arch_mips, arch_info->mach, GDB_OSABI_LINUX,
726 mips_linux_init_abi);
727 }
728
2aa830e4
DJ
729 add_core_fns (&regset_core_fns);
730}
This page took 0.29341 seconds and 4 git commands to generate.