7755ddb77d
FreeBSD/mips kernels were recently changed to include the floating point implementation revision register in the floating point register set exported in process cores and via ptrace() (r318067). This change will first ship in FreeBSD 12.0 when it is eventually released. The space used to hold FIR was previously reserved in 'struct fpreg' as a zero-filled dummy for padding, so 'struct fpreg' has not changed in size. Since FIR should be non-zero on all MIPS processors supported by FreeBSD, ignore a value of 0 from 'struct fpreg' and only report non-zero values as a valid FIR register. gdb/ChangeLog: * mips-fbsd-nat.c (getfpregs_supplies): Return true for FIR. * mips-fbsd-tdep.c (mips_fbsd_supply_fpregs): Split supply of FSR out of loop and add supply of FIR. (mips_fbsd_collect_fpregs): Split collect of FSR out of loop and add collect of FIR.
137 lines
3.9 KiB
C
137 lines
3.9 KiB
C
/* Native-dependent code for FreeBSD/mips.
|
||
|
||
Copyright (C) 2017 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 3 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, see <http://www.gnu.org/licenses/>. */
|
||
|
||
#include "defs.h"
|
||
#include "inferior.h"
|
||
#include "regcache.h"
|
||
#include "target.h"
|
||
|
||
#include <sys/types.h>
|
||
#include <sys/ptrace.h>
|
||
#include <machine/reg.h>
|
||
|
||
#include "fbsd-nat.h"
|
||
#include "mips-tdep.h"
|
||
#include "mips-fbsd-tdep.h"
|
||
#include "inf-ptrace.h"
|
||
|
||
/* Determine if PT_GETREGS fetches REGNUM. */
|
||
|
||
static bool
|
||
getregs_supplies (struct gdbarch *gdbarch, int regnum)
|
||
{
|
||
return (regnum >= MIPS_ZERO_REGNUM
|
||
&& regnum <= mips_regnum (gdbarch)->pc);
|
||
}
|
||
|
||
/* Determine if PT_GETFPREGS fetches REGNUM. */
|
||
|
||
static bool
|
||
getfpregs_supplies (struct gdbarch *gdbarch, int regnum)
|
||
{
|
||
return (regnum >= mips_regnum (gdbarch)->fp0
|
||
&& regnum <= mips_regnum (gdbarch)->fp_implementation_revision);
|
||
}
|
||
|
||
/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
|
||
for all registers. */
|
||
|
||
static void
|
||
mips_fbsd_fetch_inferior_registers (struct target_ops *ops,
|
||
struct regcache *regcache, int regnum)
|
||
{
|
||
pid_t pid = get_ptrace_pid (regcache_get_ptid (regcache));
|
||
|
||
struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
||
if (regnum == -1 || getregs_supplies (gdbarch, regnum))
|
||
{
|
||
struct reg regs;
|
||
|
||
if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1)
|
||
perror_with_name (_("Couldn't get registers"));
|
||
|
||
mips_fbsd_supply_gregs (regcache, regnum, ®s, sizeof (register_t));
|
||
}
|
||
|
||
if (regnum == -1 || getfpregs_supplies (gdbarch, regnum))
|
||
{
|
||
struct fpreg fpregs;
|
||
|
||
if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
|
||
perror_with_name (_("Couldn't get floating point status"));
|
||
|
||
mips_fbsd_supply_fpregs (regcache, regnum, &fpregs,
|
||
sizeof (f_register_t));
|
||
}
|
||
}
|
||
|
||
/* Store register REGNUM back into the inferior. If REGNUM is -1, do
|
||
this for all registers. */
|
||
|
||
static void
|
||
mips_fbsd_store_inferior_registers (struct target_ops *ops,
|
||
struct regcache *regcache, int regnum)
|
||
{
|
||
pid_t pid = get_ptrace_pid (regcache_get_ptid (regcache));
|
||
|
||
struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
||
if (regnum == -1 || getregs_supplies (gdbarch, regnum))
|
||
{
|
||
struct reg regs;
|
||
|
||
if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1)
|
||
perror_with_name (_("Couldn't get registers"));
|
||
|
||
mips_fbsd_collect_gregs (regcache, regnum, (char *) ®s,
|
||
sizeof (register_t));
|
||
|
||
if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1)
|
||
perror_with_name (_("Couldn't write registers"));
|
||
}
|
||
|
||
if (regnum == -1 || getfpregs_supplies (gdbarch, regnum))
|
||
{
|
||
struct fpreg fpregs;
|
||
|
||
if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
|
||
perror_with_name (_("Couldn't get floating point status"));
|
||
|
||
mips_fbsd_collect_fpregs (regcache, regnum, (char *) &fpregs,
|
||
sizeof (f_register_t));
|
||
|
||
if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
|
||
perror_with_name (_("Couldn't write floating point status"));
|
||
}
|
||
}
|
||
|
||
|
||
/* Provide a prototype to silence -Wmissing-prototypes. */
|
||
void _initialize_mips_fbsd_nat (void);
|
||
|
||
void
|
||
_initialize_mips_fbsd_nat (void)
|
||
{
|
||
struct target_ops *t;
|
||
|
||
t = inf_ptrace_target ();
|
||
t->to_fetch_registers = mips_fbsd_fetch_inferior_registers;
|
||
t->to_store_registers = mips_fbsd_store_inferior_registers;
|
||
fbsd_nat_add_target (t);
|
||
}
|