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
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
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., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "inferior.h"
#include "regcache.h"
#include "linux-nat.h"
#include "mips-linux-tdep.h"
+#include "target-descriptions.h"
+#include "xml-support.h"
#include "gdb_proc_service.h"
#include "gregset.h"
+#include <sgidefs.h>
#include <sys/ptrace.h>
#ifndef PTRACE_GET_THREAD_AREA
/* 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
- FCRIR via ptrace(). */
-
-int
-mips_linux_cannot_fetch_register (int regno)
-{
- if (regno > MIPS_ZERO_REGNUM && regno < MIPS_ZERO_REGNUM + 32)
- return 0;
- else if (regno >= mips_regnum (current_gdbarch)->fp0
- && regno <= mips_regnum (current_gdbarch)->fp0 + 32)
- return 0;
- else if (regno == mips_regnum (current_gdbarch)->lo
- || regno == mips_regnum (current_gdbarch)->hi
- || regno == mips_regnum (current_gdbarch)->badvaddr
- || regno == mips_regnum (current_gdbarch)->cause
- || regno == mips_regnum (current_gdbarch)->pc
- || regno == mips_regnum (current_gdbarch)->fp_control_status
- || regno == mips_regnum (current_gdbarch)->fp_implementation_revision)
- return 0;
- else
- return 1;
-}
-
-int
-mips_linux_cannot_store_register (int regno)
-{
- if (regno > MIPS_ZERO_REGNUM && regno < MIPS_ZERO_REGNUM + 32)
- return 0;
- else if (regno >= FP0_REGNUM && regno <= FP0_REGNUM + 32)
- return 0;
- else if (regno == mips_regnum (current_gdbarch)->lo
- || regno == mips_regnum (current_gdbarch)->hi
- || regno == mips_regnum (current_gdbarch)->pc
- || regno == mips_regnum (current_gdbarch)->fp_control_status)
- return 0;
- else
- return 1;
-}
+void (*super_fetch_registers) (struct regcache *, int);
+void (*super_store_registers) (struct regcache *, int);
/* Map gdb internal register number to ptrace ``address''.
- These ``addresses'' are normally defined in <asm/ptrace.h>. */
+ These ``addresses'' are normally defined in <asm/ptrace.h>.
+
+ 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 FCRIR via ptrace(). */
static CORE_ADDR
-mips_linux_register_addr (int regno)
+mips_linux_register_addr (struct gdbarch *gdbarch, int regno, int store)
{
- int regaddr;
+ CORE_ADDR regaddr;
- if (regno < 0 || regno >= NUM_REGS)
+ if (regno < 0 || regno >= gdbarch_num_regs (current_gdbarch))
error (_("Bogon register number %d."), regno);
- if (regno < 32)
+ if (regno > MIPS_ZERO_REGNUM && regno < MIPS_ZERO_REGNUM + 32)
regaddr = regno;
- else if ((regno >= mips_regnum (current_gdbarch)->fp0)
- && (regno < mips_regnum (current_gdbarch)->fp0 + 32))
- regaddr = FPR_BASE + (regno - mips_regnum (current_gdbarch)->fp0);
- else if (regno == mips_regnum (current_gdbarch)->pc)
+ else if ((regno >= mips_regnum (gdbarch)->fp0)
+ && (regno < mips_regnum (gdbarch)->fp0 + 32))
+ regaddr = FPR_BASE + (regno - mips_regnum (gdbarch)->fp0);
+ else if (regno == mips_regnum (gdbarch)->pc)
regaddr = PC;
- else if (regno == mips_regnum (current_gdbarch)->cause)
- regaddr = CAUSE;
- else if (regno == mips_regnum (current_gdbarch)->badvaddr)
- regaddr = BADVADDR;
- else if (regno == mips_regnum (current_gdbarch)->lo)
+ else if (regno == mips_regnum (gdbarch)->cause)
+ regaddr = store? (CORE_ADDR) -1 : CAUSE;
+ else if (regno == mips_regnum (gdbarch)->badvaddr)
+ regaddr = store? (CORE_ADDR) -1 : BADVADDR;
+ else if (regno == mips_regnum (gdbarch)->lo)
regaddr = MMLO;
- else if (regno == mips_regnum (current_gdbarch)->hi)
+ else if (regno == mips_regnum (gdbarch)->hi)
regaddr = MMHI;
- else if (regno == mips_regnum (current_gdbarch)->fp_control_status)
+ else if (regno == mips_regnum (gdbarch)->fp_control_status)
regaddr = FPC_CSR;
- else if (regno == mips_regnum (current_gdbarch)->fp_implementation_revision)
- regaddr = FPC_EIR;
+ else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
+ regaddr = store? (CORE_ADDR) -1 : FPC_EIR;
+ else if (mips_linux_restart_reg_p (gdbarch) && regno == MIPS_RESTART_REGNUM)
+ regaddr = 0;
else
- error (_("Unknowable register number %d."), regno);
+ regaddr = (CORE_ADDR) -1;
return regaddr;
}
static CORE_ADDR
-mips64_linux_register_addr (int regno)
+mips64_linux_register_addr (struct gdbarch *gdbarch, int regno, int store)
{
- int regaddr;
+ CORE_ADDR regaddr;
- if (regno < 0 || regno >= NUM_REGS)
+ if (regno < 0 || regno >= gdbarch_num_regs (current_gdbarch))
error (_("Bogon register number %d."), regno);
- if (regno < 32)
+ if (regno > MIPS_ZERO_REGNUM && regno < MIPS_ZERO_REGNUM + 32)
regaddr = regno;
- else if ((regno >= mips_regnum (current_gdbarch)->fp0)
- && (regno < mips_regnum (current_gdbarch)->fp0 + 32))
- regaddr = MIPS64_FPR_BASE + (regno - FP0_REGNUM);
- else if (regno == mips_regnum (current_gdbarch)->pc)
+ else if ((regno >= mips_regnum (gdbarch)->fp0)
+ && (regno < mips_regnum (gdbarch)->fp0 + 32))
+ regaddr = MIPS64_FPR_BASE + (regno - gdbarch_fp0_regnum (current_gdbarch));
+ else if (regno == mips_regnum (gdbarch)->pc)
regaddr = MIPS64_PC;
- else if (regno == mips_regnum (current_gdbarch)->cause)
- regaddr = MIPS64_CAUSE;
- else if (regno == mips_regnum (current_gdbarch)->badvaddr)
- regaddr = MIPS64_BADVADDR;
- else if (regno == mips_regnum (current_gdbarch)->lo)
+ else if (regno == mips_regnum (gdbarch)->cause)
+ regaddr = store? (CORE_ADDR) -1 : MIPS64_CAUSE;
+ else if (regno == mips_regnum (gdbarch)->badvaddr)
+ regaddr = store? (CORE_ADDR) -1 : MIPS64_BADVADDR;
+ else if (regno == mips_regnum (gdbarch)->lo)
regaddr = MIPS64_MMLO;
- else if (regno == mips_regnum (current_gdbarch)->hi)
+ else if (regno == mips_regnum (gdbarch)->hi)
regaddr = MIPS64_MMHI;
- else if (regno == mips_regnum (current_gdbarch)->fp_control_status)
+ else if (regno == mips_regnum (gdbarch)->fp_control_status)
regaddr = MIPS64_FPC_CSR;
- else if (regno == mips_regnum (current_gdbarch)->fp_implementation_revision)
- regaddr = MIPS64_FPC_EIR;
+ else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
+ regaddr = store? (CORE_ADDR) -1 : MIPS64_FPC_EIR;
+ else if (mips_linux_restart_reg_p (gdbarch) && regno == MIPS_RESTART_REGNUM)
+ regaddr = 0;
else
- error (_("Unknowable register number %d."), regno);
+ regaddr = (CORE_ADDR) -1;
return regaddr;
}
using PTRACE_GETREGS et al. */
static void
-mips64_linux_regsets_fetch_registers (int regno)
+mips64_linux_regsets_fetch_registers (struct regcache *regcache, int regno)
{
int is_fp;
int tid;
perror_with_name (_("Couldn't get registers"));
}
- mips64_supply_gregset (current_regcache,
+ mips64_supply_gregset (regcache,
(const mips64_elf_gregset_t *) ®s);
}
perror_with_name (_("Couldn't get FP registers"));
}
- mips64_supply_fpregset (current_regcache,
+ mips64_supply_fpregset (regcache,
(const mips64_elf_fpregset_t *) &fp_regs);
}
}
using PTRACE_SETREGS et al. */
static void
-mips64_linux_regsets_store_registers (int regno)
+mips64_linux_regsets_store_registers (const struct regcache *regcache, int regno)
{
int is_fp;
int tid;
if (ptrace (PTRACE_GETREGS, tid, 0L, (PTRACE_TYPE_ARG3) ®s) == -1)
perror_with_name (_("Couldn't get registers"));
- mips64_fill_gregset (current_regcache, ®s, regno);
+ mips64_fill_gregset (regcache, ®s, regno);
if (ptrace (PTRACE_SETREGS, tid, 0L, (PTRACE_TYPE_ARG3) ®s) == -1)
perror_with_name (_("Couldn't set registers"));
(PTRACE_TYPE_ARG3) &fp_regs) == -1)
perror_with_name (_("Couldn't get FP registers"));
- mips64_fill_fpregset (current_regcache, &fp_regs, regno);
+ mips64_fill_fpregset (regcache, &fp_regs, regno);
if (ptrace (PTRACE_SETFPREGS, tid, 0L,
(PTRACE_TYPE_ARG3) &fp_regs) == -1)
using any working method. */
static void
-mips64_linux_fetch_registers (int regnum)
+mips64_linux_fetch_registers (struct regcache *regcache, int regnum)
{
/* Unless we already know that PTRACE_GETREGS does not work, try it. */
if (have_ptrace_regsets)
- mips64_linux_regsets_fetch_registers (regnum);
+ mips64_linux_regsets_fetch_registers (regcache, 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);
+ super_fetch_registers (regcache, regnum);
}
/* Store REGNO (or all registers if REGNO == -1) to the target
using any working method. */
static void
-mips64_linux_store_registers (int regnum)
+mips64_linux_store_registers (struct regcache *regcache, int regnum)
{
/* Unless we already know that PTRACE_GETREGS does not work, try it. */
if (have_ptrace_regsets)
- mips64_linux_regsets_store_registers (regnum);
+ mips64_linux_regsets_store_registers (regcache, 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);
+ super_store_registers (regcache, regnum);
}
/* Return the address in the core dump or inferior of register
REGNO. */
static CORE_ADDR
-mips_linux_register_u_offset (int regno)
+mips_linux_register_u_offset (struct gdbarch *gdbarch, int regno, int store_p)
{
- if (mips_abi_regsize (current_gdbarch) == 8)
- return mips64_linux_register_addr (regno);
+ if (mips_abi_regsize (gdbarch) == 8)
+ return mips64_linux_register_addr (gdbarch, regno, store_p);
else
- return mips_linux_register_addr (regno);
+ return mips_linux_register_addr (gdbarch, regno, store_p);
+}
+
+static LONGEST (*super_xfer_partial) (struct target_ops *, enum target_object,
+ const char *, gdb_byte *, const gdb_byte *,
+ ULONGEST, LONGEST);
+
+static LONGEST
+mips_linux_xfer_partial (struct target_ops *ops,
+ enum target_object object,
+ const char *annex,
+ gdb_byte *readbuf, const gdb_byte *writebuf,
+ ULONGEST offset, LONGEST len)
+{
+ if (object == TARGET_OBJECT_AVAILABLE_FEATURES)
+ {
+ if (annex != NULL && strcmp (annex, "target.xml") == 0)
+ {
+ /* Report that target registers are a size we know for sure
+ that we can get from ptrace. */
+ if (_MIPS_SIM == _ABIO32)
+ annex = "mips-linux.xml";
+ else
+ annex = "mips64-linux.xml";
+ }
+
+ return xml_builtin_xfer_partial (annex, readbuf, writebuf, offset, len);
+ }
+
+ return super_xfer_partial (ops, object, annex, readbuf, writebuf,
+ offset, len);
}
void _initialize_mips_linux_nat (void);
t->to_fetch_registers = mips64_linux_fetch_registers;
t->to_store_registers = mips64_linux_store_registers;
+ /* Override the default to_xfer_partial. */
+ super_xfer_partial = t->to_xfer_partial;
+ t->to_xfer_partial = mips_linux_xfer_partial;
+
linux_nat_add_target (t);
}