diff options
author | Daniel Jacobowitz <drow@false.org> | 2006-03-15 17:13:36 +0000 |
---|---|---|
committer | Daniel Jacobowitz <drow@false.org> | 2006-03-15 17:13:36 +0000 |
commit | d37eb719b8e408c0569b5cbe0439821c56efade2 (patch) | |
tree | 9bba5d656b9e616cc3f6df03261e242936ff3de4 /gdb | |
parent | 9f62d0e2125fa78dee913398b568b1345053fe6c (diff) | |
download | gdb-d37eb719b8e408c0569b5cbe0439821c56efade2.zip gdb-d37eb719b8e408c0569b5cbe0439821c56efade2.tar.gz gdb-d37eb719b8e408c0569b5cbe0439821c56efade2.tar.bz2 |
* Makefile.in (mips_linux_tdep_h): New.
(mpis-linux-nat.o, mips-linux-tdep.o): Update.
* mips-linux-nat.c: Include "inferior.h", "mips-linux-tdep.h", and
<sys/ptrace.h>.
(have_ptrace_regsets, super_fetch_registers, super_store_registers)
(mips64_linux_regsets_fetch_registers)
(mips64_linux_regsets_store_registers, mips64_linux_fetch_registers)
(mips64_linux_store_registers): New.
(_initialize_mips_linux_nat): Override to_fetch_registers and
to_store_registers.
* mips-linux-tdep.h: New file.
* mips-linux-tdep.c: Include "mips-linux-tdep.c".
(ELF_NGREG, ELF_NFPREG, elf_greg_t, elf_gregset_t, elf_fpreg_t)
(elf_fpregset_t, FPR_BASE, PC, CAUSE, BADVADDR, MMHI, MMLO)
(FPC_CSR, FPC_EIR, EF_REG0, EF_REG31, EF_LO, EF_HI, EF_CP0_EPC)
(EF_CP0_BADVADDR, EF_CP0_STATUS, EF_CP0_CAUSE, EF_SIZE)
(MIPS64_ELF_NGREG, MIPS64_ELF_NFPREG, mips64_elf_greg_t)
(mips64_elf_gregset_t, mips64_elf_fpreg_t, mips64_elf_fpregset_t)
(MIPS64_FPR_BASE, MIPS64_PC, MIPS64_CAUSE, MIPS64_BADVADDR)
(MIPS64_MMHI, MIPS64_MMLO, MIPS64_FPC_CSR, MIPS64_FPC_EIR)
(MIPS64_EF_REG0, MIPS64_EF_REG31, MIPS64_EF_LO, MIPS64_EF_HI)
(MIPS64_EF_CP0_EPC, MIPS64_EF_CP0_BADVADDR, MIPS64_EF_CP0_STATUS)
(MIPS64_EF_CP0_CAUSE, MIPS64_EF_SIZE): Delete.
(supply_32bit_reg): Use gdb_byte.
(supply_64bit_reg): New.
(mips_supply_gregset, mips_fill_gregset, mips_supply_fpregset)
(mips_fill_fpregset, fetch_core_registers, supply_gregset)
(fill_gregset, supply_fpregset): Update for renamed types.
(mips64_supply_gregset): Use gdb_byte and supply_64bit_reg.
(mips64_fill_gregset): Make global. Handle 32-bit register
sizes.
(mips64_fill_fpregset): Make global. Use gdb_byte. Handle
FP regsets properly.
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 36 | ||||
-rw-r--r-- | gdb/Makefile.in | 6 | ||||
-rw-r--r-- | gdb/mips-linux-nat.c | 167 | ||||
-rw-r--r-- | gdb/mips-linux-tdep.c | 267 | ||||
-rw-r--r-- | gdb/mips-linux-tdep.h | 94 |
5 files changed, 429 insertions, 141 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 622c083..5b76385 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,41 @@ 2006-03-15 Daniel Jacobowitz <dan@codesourcery.com> + * Makefile.in (mips_linux_tdep_h): New. + (mpis-linux-nat.o, mips-linux-tdep.o): Update. + * mips-linux-nat.c: Include "inferior.h", "mips-linux-tdep.h", and + <sys/ptrace.h>. + (have_ptrace_regsets, super_fetch_registers, super_store_registers) + (mips64_linux_regsets_fetch_registers) + (mips64_linux_regsets_store_registers, mips64_linux_fetch_registers) + (mips64_linux_store_registers): New. + (_initialize_mips_linux_nat): Override to_fetch_registers and + to_store_registers. + * mips-linux-tdep.h: New file. + * mips-linux-tdep.c: Include "mips-linux-tdep.c". + (ELF_NGREG, ELF_NFPREG, elf_greg_t, elf_gregset_t, elf_fpreg_t) + (elf_fpregset_t, FPR_BASE, PC, CAUSE, BADVADDR, MMHI, MMLO) + (FPC_CSR, FPC_EIR, EF_REG0, EF_REG31, EF_LO, EF_HI, EF_CP0_EPC) + (EF_CP0_BADVADDR, EF_CP0_STATUS, EF_CP0_CAUSE, EF_SIZE) + (MIPS64_ELF_NGREG, MIPS64_ELF_NFPREG, mips64_elf_greg_t) + (mips64_elf_gregset_t, mips64_elf_fpreg_t, mips64_elf_fpregset_t) + (MIPS64_FPR_BASE, MIPS64_PC, MIPS64_CAUSE, MIPS64_BADVADDR) + (MIPS64_MMHI, MIPS64_MMLO, MIPS64_FPC_CSR, MIPS64_FPC_EIR) + (MIPS64_EF_REG0, MIPS64_EF_REG31, MIPS64_EF_LO, MIPS64_EF_HI) + (MIPS64_EF_CP0_EPC, MIPS64_EF_CP0_BADVADDR, MIPS64_EF_CP0_STATUS) + (MIPS64_EF_CP0_CAUSE, MIPS64_EF_SIZE): Delete. + (supply_32bit_reg): Use gdb_byte. + (supply_64bit_reg): New. + (mips_supply_gregset, mips_fill_gregset, mips_supply_fpregset) + (mips_fill_fpregset, fetch_core_registers, supply_gregset) + (fill_gregset, supply_fpregset): Update for renamed types. + (mips64_supply_gregset): Use gdb_byte and supply_64bit_reg. + (mips64_fill_gregset): Make global. Handle 32-bit register + sizes. + (mips64_fill_fpregset): Make global. Use gdb_byte. Handle + FP regsets properly. + +2006-03-15 Daniel Jacobowitz <dan@codesourcery.com> + * mips-linux-tdep.c (mips_supply_gregset): Renamed from supply_gregset. (mips_fill_gregset): Renamed from fill_gregset. (mips_supply_fpregset): Renamed from supply_fpregset. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 45139fb..04ceed3 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -737,6 +737,7 @@ macrotab_h = macrotab.h main_h = main.h mdebugread_h = mdebugread.h $(coff_sym_h) $(coff_symconst_h) memattr_h = memattr.h +mips_linux_tdep_h = mips-linux-tdep.h mips_mdebug_tdep_h = mips-mdebug-tdep.h mipsnbsd_tdep_h = mipsnbsd-tdep.h mips_tdep_h = mips-tdep.h @@ -2295,11 +2296,12 @@ mips64obsd-tdep.o: mips64obsd-tdep.c $(defs_h) $(osabi_h) $(regcache_h) \ $(gdb_string_h) $(mips_tdep_h) $(solib_svr4_h) mips-irix-tdep.o: mips-irix-tdep.c $(defs_h) $(osabi_h) $(elf_bfd_h) mips-linux-nat.o: mips-linux-nat.c $(defs_h) $(mips_tdep_h) $(target_h) \ - $(linux_nat_h) $(gdb_proc_service_h) + $(linux_nat_h) $(gdb_proc_service_h) $(mips_linux_tdep_h) \ + $(inferior_h) mips-linux-tdep.o: mips-linux-tdep.c $(defs_h) $(gdbcore_h) $(target_h) \ $(solib_svr4_h) $(osabi_h) $(mips_tdep_h) $(gdb_string_h) \ $(gdb_assert_h) $(frame_h) $(regcache_h) $(trad_frame_h) \ - $(tramp_frame_h) $(floatformat_h) + $(tramp_frame_h) $(floatformat_h) $(mips_linux_tdep_h) mips-mdebug-tdep.o: mips-mdebug-tdep.c $(defs_h) $(frame_h) $(mips_tdep_h) \ $(trad_frame_h) $(block_h) $(symtab_h) $(objfiles_h) $(elf_mips_h) \ $(elf_bfd_h) $(gdb_assert_h) $(frame_unwind_h) $(frame_base_h) \ diff --git a/gdb/mips-linux-nat.c b/gdb/mips-linux-nat.c index 1f18771..985ff27 100644 --- a/gdb/mips-linux-nat.c +++ b/gdb/mips-linux-nat.c @@ -21,16 +21,30 @@ Boston, MA 02110-1301, USA. */ #include "defs.h" +#include "inferior.h" #include "mips-tdep.h" #include "target.h" #include "linux-nat.h" +#include "mips-linux-tdep.h" #include "gdb_proc_service.h" +#include <sys/ptrace.h> + #ifndef PTRACE_GET_THREAD_AREA #define PTRACE_GET_THREAD_AREA 25 #endif +/* Assume that we have PTRACE_GETREGS et al. support. If we do not, + we'll clear this and use PTRACE_PEEKUSER instead. */ +static int have_ptrace_regsets = 1; + +/* Saved function pointers to fetch and store a single register using + PTRACE_PEEKUSER and PTRACE_POKEUSER. */ + +void (*super_fetch_registers) (int); +void (*super_store_registers) (int); + /* Pseudo registers can not be read. ptrace does not provide a way to read (or set) MIPS_PS_REGNUM, and there's no point in reading or setting MIPS_ZERO_REGNUM. We also can not set BADVADDR, CAUSE, or @@ -89,10 +103,161 @@ ps_get_thread_area (const struct ps_prochandle *ph, return PS_OK; } +/* Fetch REGNO (or all registers if REGNO == -1) from the target + using PTRACE_GETREGS et al. */ + +static void +mips64_linux_regsets_fetch_registers (int regno) +{ + int is_fp; + int tid; + + if (regno >= mips_regnum (current_gdbarch)->fp0 + && regno <= mips_regnum (current_gdbarch)->fp0 + 32) + is_fp = 1; + else if (regno == mips_regnum (current_gdbarch)->fp_control_status) + is_fp = 1; + else if (regno == mips_regnum (current_gdbarch)->fp_implementation_revision) + is_fp = 1; + else + is_fp = 0; + + tid = ptid_get_lwp (inferior_ptid); + if (tid == 0) + tid = ptid_get_pid (inferior_ptid); + + if (regno == -1 || !is_fp) + { + mips64_elf_gregset_t regs; + + if (ptrace (PTRACE_GETREGS, tid, 0L, (PTRACE_TYPE_ARG3) ®s) == -1) + { + if (errno == EIO) + { + have_ptrace_regsets = 0; + return; + } + perror_with_name (_("Couldn't get registers")); + } + + mips64_supply_gregset (®s); + } + + if (regno == -1 || is_fp) + { + mips64_elf_fpregset_t fp_regs; + + if (ptrace (PTRACE_GETFPREGS, tid, 0L, + (PTRACE_TYPE_ARG3) &fp_regs) == -1) + { + if (errno == EIO) + { + have_ptrace_regsets = 0; + return; + } + perror_with_name (_("Couldn't get FP registers")); + } + + mips64_supply_fpregset (&fp_regs); + } +} + +/* Store REGNO (or all registers if REGNO == -1) to the target + using PTRACE_SETREGS et al. */ + +static void +mips64_linux_regsets_store_registers (int regno) +{ + int is_fp; + int tid; + + if (regno >= mips_regnum (current_gdbarch)->fp0 + && regno <= mips_regnum (current_gdbarch)->fp0 + 32) + is_fp = 1; + else if (regno == mips_regnum (current_gdbarch)->fp_control_status) + is_fp = 1; + else if (regno == mips_regnum (current_gdbarch)->fp_implementation_revision) + is_fp = 1; + else + is_fp = 0; + + tid = ptid_get_lwp (inferior_ptid); + if (tid == 0) + tid = ptid_get_pid (inferior_ptid); + + if (regno == -1 || !is_fp) + { + mips64_elf_gregset_t regs; + + if (ptrace (PTRACE_GETREGS, tid, 0L, (PTRACE_TYPE_ARG3) ®s) == -1) + perror_with_name (_("Couldn't get registers")); + + mips64_fill_gregset (®s, regno); + + if (ptrace (PTRACE_SETREGS, tid, 0L, (PTRACE_TYPE_ARG3) ®s) == -1) + perror_with_name (_("Couldn't set registers")); + } + + if (regno == -1 || is_fp) + { + mips64_elf_fpregset_t fp_regs; + + if (ptrace (PTRACE_GETFPREGS, tid, 0L, + (PTRACE_TYPE_ARG3) &fp_regs) == -1) + perror_with_name (_("Couldn't get FP registers")); + + mips64_fill_fpregset (&fp_regs, regno); + + if (ptrace (PTRACE_SETFPREGS, tid, 0L, + (PTRACE_TYPE_ARG3) &fp_regs) == -1) + perror_with_name (_("Couldn't set FP registers")); + } +} + +/* Fetch REGNO (or all registers if REGNO == -1) from the target + using any working method. */ + +static void +mips64_linux_fetch_registers (int regnum) +{ + /* Unless we already know that PTRACE_GETREGS does not work, try it. */ + if (have_ptrace_regsets) + mips64_linux_regsets_fetch_registers (regnum); + + /* If we know, or just found out, that PTRACE_GETREGS does not work, fall + back to PTRACE_PEEKUSER. */ + if (!have_ptrace_regsets) + super_fetch_registers (regnum); +} + +/* Store REGNO (or all registers if REGNO == -1) to the target + using any working method. */ + +static void +mips64_linux_store_registers (int regnum) +{ + /* Unless we already know that PTRACE_GETREGS does not work, try it. */ + if (have_ptrace_regsets) + mips64_linux_regsets_store_registers (regnum); + + /* If we know, or just found out, that PTRACE_GETREGS does not work, fall + back to PTRACE_PEEKUSER. */ + if (!have_ptrace_regsets) + super_store_registers (regnum); +} + void _initialize_mips_linux_nat (void); void _initialize_mips_linux_nat (void) { - add_target (linux_target ()); + struct target_ops *t = linux_target (); + + super_fetch_registers = t->to_fetch_registers; + super_store_registers = t->to_store_registers; + + t->to_fetch_registers = mips64_linux_fetch_registers; + t->to_store_registers = mips64_linux_store_registers; + + add_target (t); } diff --git a/gdb/mips-linux-tdep.c b/gdb/mips-linux-tdep.c index 1aaeeb6..5d789d2 100644 --- a/gdb/mips-linux-tdep.c +++ b/gdb/mips-linux-tdep.c @@ -33,37 +33,7 @@ #include "trad-frame.h" #include "tramp-frame.h" #include "floatformat.h" - -/* Copied from <asm/elf.h>. */ -#define ELF_NGREG 45 -#define ELF_NFPREG 33 - -typedef unsigned char elf_greg_t[4]; -typedef elf_greg_t elf_gregset_t[ELF_NGREG]; - -typedef unsigned char elf_fpreg_t[8]; -typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; - -/* 0 - 31 are integer registers, 32 - 63 are fp registers. */ -#define FPR_BASE 32 -#define PC 64 -#define CAUSE 65 -#define BADVADDR 66 -#define MMHI 67 -#define MMLO 68 -#define FPC_CSR 69 -#define FPC_EIR 70 - -#define EF_REG0 6 -#define EF_REG31 37 -#define EF_LO 38 -#define EF_HI 39 -#define EF_CP0_EPC 40 -#define EF_CP0_BADVADDR 41 -#define EF_CP0_STATUS 42 -#define EF_CP0_CAUSE 43 - -#define EF_SIZE 180 +#include "mips-linux-tdep.h" /* Figure out where the longjmp will land. We expect the first arg to be a pointer to the jmp_buf structure @@ -99,7 +69,7 @@ mips_linux_get_longjmp_target (CORE_ADDR *pc) static void supply_32bit_reg (int regnum, const void *addr) { - char buf[MAX_REGISTER_SIZE]; + gdb_byte buf[MAX_REGISTER_SIZE]; store_signed_integer (buf, register_size (current_gdbarch, regnum), extract_signed_integer (addr, 4)); regcache_raw_supply (current_regcache, regnum, buf); @@ -107,11 +77,11 @@ supply_32bit_reg (int regnum, const void *addr) /* Unpack an elf_gregset_t into GDB's register cache. */ -static void -mips_supply_gregset (elf_gregset_t *gregsetp) +void +mips_supply_gregset (mips_elf_gregset_t *gregsetp) { int regi; - elf_greg_t *regp = *gregsetp; + mips_elf_greg_t *regp = *gregsetp; char zerobuf[MAX_REGISTER_SIZE]; memset (zerobuf, 0, MAX_REGISTER_SIZE); @@ -142,16 +112,16 @@ mips_supply_gregset (elf_gregset_t *gregsetp) /* Pack our registers (or one register) into an elf_gregset_t. */ -static void -mips_fill_gregset (elf_gregset_t *gregsetp, int regno) +void +mips_fill_gregset (mips_elf_gregset_t *gregsetp, int regno) { int regaddr, regi; - elf_greg_t *regp = *gregsetp; + mips_elf_greg_t *regp = *gregsetp; void *dst; if (regno == -1) { - memset (regp, 0, sizeof (elf_gregset_t)); + memset (regp, 0, sizeof (mips_elf_gregset_t)); for (regi = 0; regi < 32; regi++) mips_fill_gregset (gregsetp, regi); mips_fill_gregset (gregsetp, mips_regnum (current_gdbarch)->lo); @@ -195,8 +165,8 @@ mips_fill_gregset (elf_gregset_t *gregsetp, int regno) /* Likewise, unpack an elf_fpregset_t. */ -static void -mips_supply_fpregset (elf_fpregset_t *fpregsetp) +void +mips_supply_fpregset (mips_elf_fpregset_t *fpregsetp) { int regi; char zerobuf[MAX_REGISTER_SIZE]; @@ -220,8 +190,8 @@ mips_supply_fpregset (elf_fpregset_t *fpregsetp) /* Likewise, pack one or all floating point registers into an elf_fpregset_t. */ -static void -mips_fill_fpregset (elf_fpregset_t *fpregsetp, int regno) +void +mips_fill_fpregset (mips_elf_fpregset_t *fpregsetp, int regno) { char *from, *to; @@ -284,37 +254,6 @@ mips_linux_register_addr (int regno, CORE_ADDR blockend) /* Support for 64-bit ABIs. */ -/* Copied from <asm/elf.h>. */ -#define MIPS64_ELF_NGREG 45 -#define MIPS64_ELF_NFPREG 33 - -typedef unsigned char mips64_elf_greg_t[8]; -typedef mips64_elf_greg_t mips64_elf_gregset_t[MIPS64_ELF_NGREG]; - -typedef unsigned char mips64_elf_fpreg_t[8]; -typedef mips64_elf_fpreg_t mips64_elf_fpregset_t[MIPS64_ELF_NFPREG]; - -/* 0 - 31 are integer registers, 32 - 63 are fp registers. */ -#define MIPS64_FPR_BASE 32 -#define MIPS64_PC 64 -#define MIPS64_CAUSE 65 -#define MIPS64_BADVADDR 66 -#define MIPS64_MMHI 67 -#define MIPS64_MMLO 68 -#define MIPS64_FPC_CSR 69 -#define MIPS64_FPC_EIR 70 - -#define MIPS64_EF_REG0 0 -#define MIPS64_EF_REG31 31 -#define MIPS64_EF_LO 32 -#define MIPS64_EF_HI 33 -#define MIPS64_EF_CP0_EPC 34 -#define MIPS64_EF_CP0_BADVADDR 35 -#define MIPS64_EF_CP0_STATUS 36 -#define MIPS64_EF_CP0_CAUSE 37 - -#define MIPS64_EF_SIZE 304 - /* Figure out where the longjmp will land. We expect the first arg to be a pointer to the jmp_buf structure from which we extract the pc (MIPS_LINUX_JB_PC) that we will land @@ -343,39 +282,49 @@ mips64_linux_get_longjmp_target (CORE_ADDR *pc) return 1; } -/* Unpack an elf_gregset_t into GDB's register cache. */ +/* Register set support functions. These operate on standard 64-bit + regsets, but work whether the target is 32-bit or 64-bit. A 32-bit + target will still use the 64-bit format for PTRACE_GETREGS. */ + +/* Supply a 64-bit register. */ -static void +void +supply_64bit_reg (int regnum, const gdb_byte *buf) +{ + if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG + && register_size (current_gdbarch, regnum) == 4) + regcache_raw_supply (current_regcache, regnum, buf + 4); + else + regcache_raw_supply (current_regcache, regnum, buf); +} + +/* Unpack a 64-bit elf_gregset_t into GDB's register cache. */ + +void mips64_supply_gregset (mips64_elf_gregset_t *gregsetp) { int regi; mips64_elf_greg_t *regp = *gregsetp; - char zerobuf[MAX_REGISTER_SIZE]; + gdb_byte zerobuf[MAX_REGISTER_SIZE]; memset (zerobuf, 0, MAX_REGISTER_SIZE); for (regi = MIPS64_EF_REG0; regi <= MIPS64_EF_REG31; regi++) - regcache_raw_supply (current_regcache, (regi - MIPS64_EF_REG0), - (char *)(regp + regi)); - - regcache_raw_supply (current_regcache, - mips_regnum (current_gdbarch)->lo, - (char *) (regp + MIPS64_EF_LO)); - regcache_raw_supply (current_regcache, - mips_regnum (current_gdbarch)->hi, - (char *) (regp + MIPS64_EF_HI)); - - regcache_raw_supply (current_regcache, - mips_regnum (current_gdbarch)->pc, - (char *) (regp + MIPS64_EF_CP0_EPC)); - regcache_raw_supply (current_regcache, - mips_regnum (current_gdbarch)->badvaddr, - (char *) (regp + MIPS64_EF_CP0_BADVADDR)); - regcache_raw_supply (current_regcache, MIPS_PS_REGNUM, - (char *) (regp + MIPS64_EF_CP0_STATUS)); - regcache_raw_supply (current_regcache, - mips_regnum (current_gdbarch)->cause, - (char *) (regp + MIPS64_EF_CP0_CAUSE)); + supply_64bit_reg (regi - MIPS64_EF_REG0, (gdb_byte *)(regp + regi)); + + supply_64bit_reg (mips_regnum (current_gdbarch)->lo, + (gdb_byte *) (regp + MIPS64_EF_LO)); + supply_64bit_reg (mips_regnum (current_gdbarch)->hi, + (gdb_byte *) (regp + MIPS64_EF_HI)); + + supply_64bit_reg (mips_regnum (current_gdbarch)->pc, + (gdb_byte *) (regp + MIPS64_EF_CP0_EPC)); + supply_64bit_reg (mips_regnum (current_gdbarch)->badvaddr, + (gdb_byte *) (regp + MIPS64_EF_CP0_BADVADDR)); + supply_64bit_reg (MIPS_PS_REGNUM, + (gdb_byte *) (regp + MIPS64_EF_CP0_STATUS)); + supply_64bit_reg (mips_regnum (current_gdbarch)->cause, + (gdb_byte *) (regp + MIPS64_EF_CP0_CAUSE)); /* Fill inaccessible registers with zero. */ regcache_raw_supply (current_regcache, MIPS_UNUSED_REGNUM, zerobuf); @@ -385,9 +334,9 @@ mips64_supply_gregset (mips64_elf_gregset_t *gregsetp) regcache_raw_supply (current_regcache, regi, zerobuf); } -/* Pack our registers (or one register) into an elf_gregset_t. */ +/* Pack our registers (or one register) into a 64-bit elf_gregset_t. */ -static void +void mips64_fill_gregset (mips64_elf_gregset_t *gregsetp, int regno) { int regaddr, regi; @@ -412,13 +361,8 @@ mips64_fill_gregset (mips64_elf_gregset_t *gregsetp, int regno) } if (regno < 32) - { - dst = regp + regno + MIPS64_EF_REG0; - regcache_raw_collect (current_regcache, regno, dst); - return; - } - - if (regno == mips_regnum (current_gdbarch)->lo) + regaddr = regno + MIPS64_EF_REG0; + else if (regno == mips_regnum (current_gdbarch)->lo) regaddr = MIPS64_EF_LO; else if (regno == mips_regnum (current_gdbarch)->hi) regaddr = MIPS64_EF_HI; @@ -435,52 +379,97 @@ mips64_fill_gregset (mips64_elf_gregset_t *gregsetp, int regno) if (regaddr != -1) { + gdb_byte buf[MAX_REGISTER_SIZE]; + LONGEST val; + + regcache_raw_collect (current_regcache, regno, buf); + val = extract_signed_integer (buf, + register_size (current_gdbarch, regno)); dst = regp + regaddr; - regcache_raw_collect (current_regcache, regno, dst); + store_signed_integer (dst, 8, val); } } /* Likewise, unpack an elf_fpregset_t. */ -static void +void mips64_supply_fpregset (mips64_elf_fpregset_t *fpregsetp) { int regi; - char zerobuf[MAX_REGISTER_SIZE]; - - memset (zerobuf, 0, MAX_REGISTER_SIZE); - - for (regi = 0; regi < 32; regi++) - regcache_raw_supply (current_regcache, FP0_REGNUM + regi, - (char *)(*fpregsetp + regi)); - regcache_raw_supply (current_regcache, - mips_regnum (current_gdbarch)->fp_control_status, - (char *)(*fpregsetp + 32)); - - /* FIXME: how can we supply FCRIR? The ABI doesn't tell us. */ - regcache_raw_supply (current_regcache, - mips_regnum (current_gdbarch)->fp_implementation_revision, - zerobuf); + /* See mips_linux_o32_sigframe_init for a description of the + peculiar FP register layout. */ + if (register_size (current_gdbarch, FP0_REGNUM) == 4) + for (regi = 0; regi < 32; regi++) + { + gdb_byte *reg_ptr = (gdb_byte *) (*fpregsetp + (regi & ~1)); + if ((TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) != (regi & 1)) + reg_ptr += 4; + regcache_raw_supply (current_regcache, FP0_REGNUM + regi, reg_ptr); + } + else + for (regi = 0; regi < 32; regi++) + regcache_raw_supply (current_regcache, FP0_REGNUM + regi, + (char *)(*fpregsetp + regi)); + + supply_32bit_reg (mips_regnum (current_gdbarch)->fp_control_status, + (gdb_byte *)(*fpregsetp + 32)); + + /* The ABI doesn't tell us how to supply FCRIR, and core dumps don't + include it - but the result of PTRACE_GETFPREGS does. The best we + can do is to assume that its value is present. */ + supply_32bit_reg (mips_regnum (current_gdbarch)->fp_implementation_revision, + (gdb_byte *)(*fpregsetp + 32) + 4); } /* Likewise, pack one or all floating point registers into an elf_fpregset_t. */ -static void +void mips64_fill_fpregset (mips64_elf_fpregset_t *fpregsetp, int regno) { - char *from, *to; + gdb_byte *to; if ((regno >= FP0_REGNUM) && (regno < FP0_REGNUM + 32)) { - to = (char *) (*fpregsetp + regno - FP0_REGNUM); - regcache_raw_collect (current_regcache, regno, to); + /* See mips_linux_o32_sigframe_init for a description of the + peculiar FP register layout. */ + if (register_size (current_gdbarch, regno) == 4) + { + int regi = regno - FP0_REGNUM; + + to = (gdb_byte *) (*fpregsetp + (regi & ~1)); + if ((TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) != (regi & 1)) + to += 4; + regcache_raw_collect (current_regcache, regno, to); + } + else + { + to = (gdb_byte *) (*fpregsetp + regno - FP0_REGNUM); + regcache_raw_collect (current_regcache, regno, to); + } } else if (regno == mips_regnum (current_gdbarch)->fp_control_status) { - to = (char *) (*fpregsetp + 32); - regcache_raw_collect (current_regcache, regno, to); + gdb_byte buf[MAX_REGISTER_SIZE]; + LONGEST val; + + regcache_raw_collect (current_regcache, regno, buf); + val = extract_signed_integer (buf, + register_size (current_gdbarch, regno)); + to = (gdb_byte *) (*fpregsetp + 32); + store_signed_integer (to, 4, val); + } + else if (regno == mips_regnum (current_gdbarch)->fp_implementation_revision) + { + gdb_byte buf[MAX_REGISTER_SIZE]; + LONGEST val; + + regcache_raw_collect (current_regcache, regno, buf); + val = extract_signed_integer (buf, + register_size (current_gdbarch, regno)); + to = (gdb_byte *) (*fpregsetp + 32) + 4; + store_signed_integer (to, 4, val); } else if (regno == -1) { @@ -488,8 +477,10 @@ mips64_fill_fpregset (mips64_elf_fpregset_t *fpregsetp, int regno) for (regi = 0; regi < 32; regi++) mips64_fill_fpregset (fpregsetp, FP0_REGNUM + regi); - mips64_fill_fpregset(fpregsetp, - mips_regnum (current_gdbarch)->fp_control_status); + mips64_fill_fpregset (fpregsetp, + mips_regnum (current_gdbarch)->fp_control_status); + mips64_fill_fpregset (fpregsetp, (mips_regnum (current_gdbarch) + ->fp_implementation_revision)); } } @@ -537,8 +528,8 @@ static void fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which, CORE_ADDR reg_addr) { - elf_gregset_t gregset; - elf_fpregset_t fpregset; + mips_elf_gregset_t gregset; + mips_elf_fpregset_t fpregset; mips64_elf_gregset_t gregset64; mips64_elf_fpregset_t fpregset64; @@ -1088,7 +1079,7 @@ mips_linux_n32n64_sigframe_init (const struct tramp_frame *self, /* Wrapper functions. These are only used by libthread_db. */ void -supply_gregset (elf_gregset_t *gregsetp) +supply_gregset (mips_elf_gregset_t *gregsetp) { if (mips_isa_regsize (current_gdbarch) == 4) mips_supply_gregset (gregsetp); @@ -1097,7 +1088,7 @@ supply_gregset (elf_gregset_t *gregsetp) } void -fill_gregset (elf_gregset_t *gregsetp, int regno) +fill_gregset (mips_elf_gregset_t *gregsetp, int regno) { if (mips_isa_regsize (current_gdbarch) == 4) mips_fill_gregset (gregsetp, regno); @@ -1108,7 +1099,7 @@ fill_gregset (elf_gregset_t *gregsetp, int regno) /* Likewise, unpack an elf_fpregset_t. */ void -supply_fpregset (elf_fpregset_t *fpregsetp) +supply_fpregset (mips_elf_fpregset_t *fpregsetp) { if (mips_isa_regsize (current_gdbarch) == 4) mips_supply_fpregset (fpregsetp); @@ -1120,7 +1111,7 @@ supply_fpregset (elf_fpregset_t *fpregsetp) elf_fpregset_t. */ void -fill_fpregset (elf_fpregset_t *fpregsetp, int regno) +fill_fpregset (mips_elf_fpregset_t *fpregsetp, int regno) { if (mips_isa_regsize (current_gdbarch) == 4) mips_fill_fpregset (fpregsetp, regno); diff --git a/gdb/mips-linux-tdep.h b/gdb/mips-linux-tdep.h new file mode 100644 index 0000000..4914b63 --- /dev/null +++ b/gdb/mips-linux-tdep.h @@ -0,0 +1,94 @@ +/* Target-dependent code for GNU/Linux on MIPS processors. + + Copyright 2006 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Copied from <asm/elf.h>. */ +#define ELF_NGREG 45 +#define ELF_NFPREG 33 + +typedef unsigned char mips_elf_greg_t[4]; +typedef mips_elf_greg_t mips_elf_gregset_t[ELF_NGREG]; + +typedef unsigned char mips_elf_fpreg_t[8]; +typedef mips_elf_fpreg_t mips_elf_fpregset_t[ELF_NFPREG]; + +/* 0 - 31 are integer registers, 32 - 63 are fp registers. */ +#define FPR_BASE 32 +#define PC 64 +#define CAUSE 65 +#define BADVADDR 66 +#define MMHI 67 +#define MMLO 68 +#define FPC_CSR 69 +#define FPC_EIR 70 + +#define EF_REG0 6 +#define EF_REG31 37 +#define EF_LO 38 +#define EF_HI 39 +#define EF_CP0_EPC 40 +#define EF_CP0_BADVADDR 41 +#define EF_CP0_STATUS 42 +#define EF_CP0_CAUSE 43 + +#define EF_SIZE 180 + +void mips_supply_gregset (mips_elf_gregset_t *); +void mips_fill_gregset (mips_elf_gregset_t *, int); +void mips_supply_fpregset (mips_elf_fpregset_t *); +void mips_fill_fpregset (mips_elf_fpregset_t *, int); + +/* 64-bit support. */ + +/* Copied from <asm/elf.h>. */ +#define MIPS64_ELF_NGREG 45 +#define MIPS64_ELF_NFPREG 33 + +typedef unsigned char mips64_elf_greg_t[8]; +typedef mips64_elf_greg_t mips64_elf_gregset_t[MIPS64_ELF_NGREG]; + +typedef unsigned char mips64_elf_fpreg_t[8]; +typedef mips64_elf_fpreg_t mips64_elf_fpregset_t[MIPS64_ELF_NFPREG]; + +/* 0 - 31 are integer registers, 32 - 63 are fp registers. */ +#define MIPS64_FPR_BASE 32 +#define MIPS64_PC 64 +#define MIPS64_CAUSE 65 +#define MIPS64_BADVADDR 66 +#define MIPS64_MMHI 67 +#define MIPS64_MMLO 68 +#define MIPS64_FPC_CSR 69 +#define MIPS64_FPC_EIR 70 + +#define MIPS64_EF_REG0 0 +#define MIPS64_EF_REG31 31 +#define MIPS64_EF_LO 32 +#define MIPS64_EF_HI 33 +#define MIPS64_EF_CP0_EPC 34 +#define MIPS64_EF_CP0_BADVADDR 35 +#define MIPS64_EF_CP0_STATUS 36 +#define MIPS64_EF_CP0_CAUSE 37 + +#define MIPS64_EF_SIZE 304 + +void mips64_supply_gregset (mips64_elf_gregset_t *); +void mips64_fill_gregset (mips64_elf_gregset_t *, int); +void mips64_supply_fpregset (mips64_elf_fpregset_t *); +void mips64_fill_fpregset (mips64_elf_fpregset_t *, int); |