#include "defs.h"
#include "inferior.h"
#include "regcache.h"
+#include "target.h"
+#include "gdb_assert.h"
#include <signal.h>
#include "gdb_string.h"
#include <sys/ptrace.h>
#include "sparc-tdep.h"
#include "sparc-nat.h"
+#include "inf-ptrace.h"
/* With some trickery we can use the code in this file for most (if
not all) ptrace(2) based SPARC systems, which includes SunOS 4,
{
gregset_t regs;
- if (ptrace (PTRACE_GETREGS, pid, (PTRACE_ARG3_TYPE) ®s, 0) == -1)
+ if (ptrace (PTRACE_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1)
perror_with_name ("Couldn't get registers");
sparc_supply_gregset (sparc_gregset, regcache, -1, ®s);
{
fpregset_t fpregs;
- if (ptrace (PTRACE_GETFPREGS, pid, (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
+ if (ptrace (PTRACE_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
perror_with_name ("Couldn't get floating point status");
sparc_supply_fpregset (regcache, -1, &fpregs);
{
gregset_t regs;
- if (ptrace (PTRACE_GETREGS, pid, (PTRACE_ARG3_TYPE) ®s, 0) == -1)
+ if (ptrace (PTRACE_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1)
perror_with_name ("Couldn't get registers");
sparc_collect_gregset (sparc_gregset, regcache, regnum, ®s);
- if (ptrace (PTRACE_SETREGS, pid, (PTRACE_ARG3_TYPE) ®s, 0) == -1)
+ if (ptrace (PTRACE_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1)
perror_with_name ("Couldn't write registers");
/* Deal with the stack regs. */
{
fpregset_t fpregs, saved_fpregs;
- if (ptrace (PTRACE_GETFPREGS, pid, (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
+ if (ptrace (PTRACE_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
perror_with_name ("Couldn't get floating-point registers");
memcpy (&saved_fpregs, &fpregs, sizeof (fpregs));
if (memcmp (&saved_fpregs, &fpregs, sizeof (fpregs)) != 0)
{
if (ptrace (PTRACE_SETFPREGS, pid,
- (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
+ (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
perror_with_name ("Couldn't write floating-point registers");
}
return;
}
}
+
+\f
+/* Fetch StackGhost Per-Process XOR cookie. */
+
+LONGEST
+sparc_xfer_wcookie (struct target_ops *ops, enum target_object object,
+ const char *annex, void *readbuf, const void *writebuf,
+ ULONGEST offset, LONGEST len)
+{
+ unsigned long wcookie = 0;
+ char *buf = (char *)&wcookie;
+
+ gdb_assert (object == TARGET_OBJECT_WCOOKIE);
+ gdb_assert (readbuf && writebuf == NULL);
+
+ if (offset >= sizeof (unsigned long))
+ return -1;
+
+#ifdef PT_WCOOKIE
+ /* If PT_WCOOKIE is defined (by <sys/ptrace.h>), assume we're
+ running on an OpenBSD release that uses StackGhost (3.1 or
+ later). As of release 3.4, OpenBSD doesn't use a randomized
+ cookie yet, but a future release probably will. */
+ {
+ int pid;
+
+ pid = TIDGET (inferior_ptid);
+ if (pid == 0)
+ pid = PIDGET (inferior_ptid);
+
+ /* Sanity check. The proper type for a cookie is register_t, but
+ we can't assume that this type exists on all systems supported
+ by the code in this file. */
+ gdb_assert (sizeof (wcookie) == sizeof (register_t));
+
+ /* Fetch the cookie. */
+ if (ptrace (PT_WCOOKIE, pid, (PTRACE_TYPE_ARG3) &wcookie, 0) == -1)
+ {
+ if (errno != EINVAL)
+ perror_with_name ("Couldn't get StackGhost cookie");
+
+ /* Although PT_WCOOKIE is defined on OpenBSD 3.1 and later,
+ the request wasn't implemented until after OpenBSD 3.4. If
+ the kernel doesn't support the PT_WCOOKIE request, assume
+ we're running on a kernel that uses non-randomized cookies. */
+ wcookie = 0x3;
+ }
+ }
+#endif /* PT_WCOOKIE */
+
+ if (len > sizeof (unsigned long) - offset)
+ len = sizeof (unsigned long) - offset;
+
+ memcpy (readbuf, buf + offset, len);
+ return len;
+}
+
+LONGEST (*inf_ptrace_xfer_partial) (struct target_ops *, enum target_object,
+ const char *, void *, const void *,
+ ULONGEST, LONGEST);
+
+static LONGEST
+sparc_xfer_partial (struct target_ops *ops, enum target_object object,
+ const char *annex, void *readbuf, const void *writebuf,
+ ULONGEST offset, LONGEST len)
+{
+ if (object == TARGET_OBJECT_WCOOKIE)
+ return sparc_xfer_wcookie (ops, object, annex, readbuf, writebuf,
+ offset, len);
+
+ return inf_ptrace_xfer_partial (ops, object, annex, readbuf, writebuf,
+ offset, len);
+}
\f
+/* Create a prototype generic SPARC target. The client can override
+ it with local methods. */
+struct target_ops *
+sparc_target (void)
+{
+ struct target_ops *t;
+
+ t = inf_ptrace_target ();
+ t->to_fetch_registers = fetch_inferior_registers;
+ t->to_store_registers = store_inferior_registers;
+ inf_ptrace_xfer_partial = t->to_xfer_partial;
+ t->to_xfer_partial = sparc_xfer_partial;
+ return t;
+}
+
+\f
/* Provide a prototype to silence -Wmissing-prototypes. */
void _initialize_sparc_nat (void);