/* Prototypes for supply_gregset etc. */
#include "gregset.h"
#include "ppc-tdep.h"
+#include "ppc-linux-tdep.h"
+
+/* This sometimes isn't defined. */
+#ifndef PT_ORIG_R3
+#define PT_ORIG_R3 34
+#endif
+#ifndef PT_TRAP
+#define PT_TRAP 40
+#endif
/* Glibc's headers don't define PTRACE_GETVRREGS so we cannot use a
configure time check. Some older glibc's (for instance 2.2.1)
/* *INDENT_ON * */
static int
-ppc_register_u_addr (int regno)
+ppc_register_u_addr (struct gdbarch *gdbarch, int regno)
{
int u_addr = -1;
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
/* NOTE: cagney/2003-11-25: This is the word size used by the ptrace
interface, and not the wordsize of the program's ABI. */
int wordsize = sizeof (long);
u_addr = (PT_FPR0 * wordsize) + ((regno - tdep->ppc_fp0_regnum) * 8);
/* UISA special purpose registers: 1 slot each */
- if (regno == gdbarch_pc_regnum (current_gdbarch))
+ if (regno == gdbarch_pc_regnum (gdbarch))
u_addr = PT_NIP * wordsize;
if (regno == tdep->ppc_lr_regnum)
u_addr = PT_LNK * wordsize;
#endif
if (regno == tdep->ppc_ps_regnum)
u_addr = PT_MSR * wordsize;
+ if (regno == PPC_ORIG_R3_REGNUM)
+ u_addr = PT_ORIG_R3 * wordsize;
+ if (regno == PPC_TRAP_REGNUM)
+ u_addr = PT_TRAP * wordsize;
if (tdep->ppc_fpscr_regnum >= 0
&& regno == tdep->ppc_fpscr_regnum)
{
struct gdbarch *gdbarch = get_regcache_arch (regcache);
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
/* This isn't really an address. But ptrace thinks of it as one. */
- CORE_ADDR regaddr = ppc_register_u_addr (regno);
+ CORE_ADDR regaddr = ppc_register_u_addr (gdbarch, regno);
int bytes_transferred;
unsigned int offset; /* Offset of registers within the u area. */
char buf[MAX_REGISTER_SIZE];
fetch_register (regcache, tid, tdep->ppc_xer_regnum);
if (tdep->ppc_mq_regnum != -1)
fetch_register (regcache, tid, tdep->ppc_mq_regnum);
+ if (ppc_linux_trap_reg_p (gdbarch))
+ {
+ fetch_register (regcache, tid, PPC_ORIG_R3_REGNUM);
+ fetch_register (regcache, tid, PPC_TRAP_REGNUM);
+ }
if (tdep->ppc_fpscr_regnum != -1)
fetch_register (regcache, tid, tdep->ppc_fpscr_regnum);
if (have_ptrace_getvrregs)
struct gdbarch *gdbarch = get_regcache_arch (regcache);
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
/* This isn't really an address. But ptrace thinks of it as one. */
- CORE_ADDR regaddr = ppc_register_u_addr (regno);
+ CORE_ADDR regaddr = ppc_register_u_addr (gdbarch, regno);
int i;
size_t bytes_to_transfer;
char buf[MAX_REGISTER_SIZE];
regaddr += sizeof (long);
if (errno == EIO
- && regno == tdep->ppc_fpscr_regnum)
+ && (regno == tdep->ppc_fpscr_regnum
+ || regno == PPC_ORIG_R3_REGNUM
+ || regno == PPC_TRAP_REGNUM))
{
- /* Some older kernel versions don't allow fpscr to be written. */
+ /* Some older kernel versions don't allow fpscr, orig_r3
+ or trap to be written. */
continue;
}
store_register (regcache, tid, tdep->ppc_mq_regnum);
if (tdep->ppc_fpscr_regnum != -1)
store_register (regcache, tid, tdep->ppc_fpscr_regnum);
+ if (ppc_linux_trap_reg_p (gdbarch))
+ {
+ store_register (regcache, tid, PPC_ORIG_R3_REGNUM);
+ store_register (regcache, tid, PPC_TRAP_REGNUM);
+ }
if (have_ptrace_getvrregs)
if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
store_altivec_registers (regcache, tid);
return ppc_linux_stopped_data_address (¤t_target, &addr);
}
+static int
+ppc_linux_watchpoint_addr_within_range (struct target_ops *target,
+ CORE_ADDR addr,
+ CORE_ADDR start, int length)
+{
+ addr &= ~7;
+ /* Check whether [start, start+length-1] intersects [addr, addr+7]. */
+ return start <= addr + 7 && start + length - 1 >= addr;
+}
+
static void
ppc_linux_store_inferior_registers (struct regcache *regcache, int regno)
{
static const struct target_desc *
ppc_linux_read_description (struct target_ops *ops)
{
+ int altivec = 0;
+
+ int tid = TIDGET (inferior_ptid);
+ if (tid == 0)
+ tid = PIDGET (inferior_ptid);
+
if (have_ptrace_getsetevrregs)
{
struct gdb_evrregset_t evrregset;
- int tid = TIDGET (inferior_ptid);
-
- if (tid == 0)
- tid = PIDGET (inferior_ptid);
if (ptrace (PTRACE_GETEVRREGS, tid, 0, &evrregset) >= 0)
- return tdesc_powerpc_e500;
- else
- {
- /* EIO means that the PTRACE_GETEVRREGS request isn't supported. */
- if (errno == EIO)
- return NULL;
- else
- /* Anything else needs to be reported. */
- perror_with_name (_("Unable to fetch SPE registers"));
- }
+ return tdesc_powerpc_e500l;
+
+ /* EIO means that the PTRACE_GETEVRREGS request isn't supported.
+ Anything else needs to be reported. */
+ else if (errno != EIO)
+ perror_with_name (_("Unable to fetch SPE registers"));
}
- return NULL;
+ if (have_ptrace_getvrregs)
+ {
+ gdb_vrregset_t vrregset;
+
+ if (ptrace (PTRACE_GETVRREGS, tid, 0, &vrregset) >= 0)
+ altivec = 1;
+
+ /* EIO means that the PTRACE_GETVRREGS request isn't supported.
+ Anything else needs to be reported. */
+ else if (errno != EIO)
+ perror_with_name (_("Unable to fetch AltiVec registers"));
+ }
+
+ /* Check for 64-bit inferior process. This is the case when the host is
+ 64-bit, and in addition the top bit of the MSR register is set. */
+#ifdef __powerpc64__
+ {
+ long msr;
+ errno = 0;
+ msr = (long) ptrace (PTRACE_PEEKUSER, tid, PT_MSR * 8, 0);
+ if (errno == 0 && msr < 0)
+ return altivec? tdesc_powerpc_altivec64l : tdesc_powerpc_64l;
+ }
+#endif
+
+ return altivec? tdesc_powerpc_altivec32l : tdesc_powerpc_32l;
}
void _initialize_ppc_linux_nat (void);
t->to_remove_watchpoint = ppc_linux_remove_watchpoint;
t->to_stopped_by_watchpoint = ppc_linux_stopped_by_watchpoint;
t->to_stopped_data_address = ppc_linux_stopped_data_address;
+ t->to_watchpoint_addr_within_range = ppc_linux_watchpoint_addr_within_range;
t->to_read_description = ppc_linux_read_description;