/* IBM RS/6000 native-dependent code for GDB, the GNU debugger.
- Copyright (C) 1986-2014 Free Software Foundation, Inc.
+ Copyright (C) 1986-2020 Free Software Foundation, Inc.
This file is part of GDB.
#include "gdbcore.h"
#include "symfile.h"
#include "objfiles.h"
-#include "libbfd.h" /* For bfd_default_set_arch_mach (FIXME) */
#include "bfd.h"
-#include "exceptions.h"
#include "gdb-stabs.h"
#include "regcache.h"
#include "arch-utils.h"
#include "rs6000-tdep.h"
#include "rs6000-aix-tdep.h"
#include "exec.h"
-#include "observer.h"
+#include "observable.h"
#include "xcoffread.h"
#include <sys/ptrace.h>
# define ARCH64() (register_size (target_gdbarch (), 0) == 8)
#endif
-static target_xfer_partial_ftype rs6000_xfer_shared_libraries;
+class rs6000_nat_target final : public inf_ptrace_target
+{
+public:
+ void fetch_registers (struct regcache *, int) override;
+ void store_registers (struct regcache *, int) override;
+
+ enum target_xfer_status xfer_partial (enum target_object object,
+ const char *annex,
+ gdb_byte *readbuf,
+ const gdb_byte *writebuf,
+ ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len) override;
+
+ void create_inferior (const char *, const std::string &,
+ char **, int) override;
+
+ ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
+
+private:
+ enum target_xfer_status
+ xfer_shared_libraries (enum target_object object,
+ const char *annex, gdb_byte *readbuf,
+ const gdb_byte *writebuf,
+ ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len);
+};
+
+static rs6000_nat_target the_rs6000_nat_target;
/* Given REGNO, a gdb register number, return the corresponding
number suitable for use as a ptrace() parameter. Return -1 if
{
#ifdef ARCH3264
# ifdef HAVE_PTRACE64
- int ret = ptrace64 (req, id, addr, data, buf);
+ int ret = ptrace64 (req, id, addr, data, (PTRACE_TYPE_ARG5) buf);
# else
- int ret = ptracex (req, id, addr, data, buf);
+ int ret = ptracex (req, id, addr, data, (PTRACE_TYPE_ARG5) buf);
# endif
#else
int ret = 0;
static void
fetch_register (struct regcache *regcache, int regno)
{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- int addr[MAX_REGISTER_SIZE];
+ struct gdbarch *gdbarch = regcache->arch ();
+ int addr[PPC_MAX_REGISTER_SIZE];
int nr, isfloat;
+ pid_t pid = regcache->ptid ().pid ();
/* Retrieved values may be -1, so infer errors from errno. */
errno = 0;
/* Floating-point registers. */
if (isfloat)
- rs6000_ptrace32 (PT_READ_FPR, ptid_get_pid (inferior_ptid), addr, nr, 0);
+ rs6000_ptrace32 (PT_READ_FPR, pid, addr, nr, 0);
/* Bogus register number. */
else if (nr < 0)
else
{
if (!ARCH64 ())
- *addr = rs6000_ptrace32 (PT_READ_GPR, ptid_get_pid (inferior_ptid),
- (int *) nr, 0, 0);
+ *addr = rs6000_ptrace32 (PT_READ_GPR, pid, (int *) nr, 0, 0);
else
{
/* PT_READ_GPR requires the buffer parameter to point to long long,
even if the register is really only 32 bits. */
long long buf;
- rs6000_ptrace64 (PT_READ_GPR, ptid_get_pid (inferior_ptid),
- nr, 0, &buf);
+ rs6000_ptrace64 (PT_READ_GPR, pid, nr, 0, &buf);
if (register_size (gdbarch, regno) == 8)
memcpy (addr, &buf, 8);
else
}
if (!errno)
- regcache_raw_supply (regcache, regno, (char *) addr);
+ regcache->raw_supply (regno, (char *) addr);
else
{
#if 0
static void
store_register (struct regcache *regcache, int regno)
{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- int addr[MAX_REGISTER_SIZE];
+ struct gdbarch *gdbarch = regcache->arch ();
+ int addr[PPC_MAX_REGISTER_SIZE];
int nr, isfloat;
+ pid_t pid = regcache->ptid ().pid ();
/* Fetch the register's value from the register cache. */
- regcache_raw_collect (regcache, regno, addr);
+ regcache->raw_collect (regno, addr);
/* -1 can be a successful return value, so infer errors from errno. */
errno = 0;
/* Floating-point registers. */
if (isfloat)
- rs6000_ptrace32 (PT_WRITE_FPR, ptid_get_pid (inferior_ptid), addr, nr, 0);
+ rs6000_ptrace32 (PT_WRITE_FPR, pid, addr, nr, 0);
/* Bogus register number. */
else if (nr < 0)
the register's value is passed by value, but for 64-bit inferiors,
the address of a buffer containing the value is passed. */
if (!ARCH64 ())
- rs6000_ptrace32 (PT_WRITE_GPR, ptid_get_pid (inferior_ptid),
- (int *) nr, *addr, 0);
+ rs6000_ptrace32 (PT_WRITE_GPR, pid, (int *) nr, *addr, 0);
else
{
/* PT_WRITE_GPR requires the buffer parameter to point to an 8-byte
memcpy (&buf, addr, 8);
else
buf = *addr;
- rs6000_ptrace64 (PT_WRITE_GPR, ptid_get_pid (inferior_ptid),
- nr, 0, &buf);
+ rs6000_ptrace64 (PT_WRITE_GPR, pid, nr, 0, &buf);
}
}
/* Read from the inferior all registers if REGNO == -1 and just register
REGNO otherwise. */
-static void
-rs6000_fetch_inferior_registers (struct target_ops *ops,
- struct regcache *regcache, int regno)
+void
+rs6000_nat_target::fetch_registers (struct regcache *regcache, int regno)
{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
if (regno != -1)
fetch_register (regcache, regno);
If REGNO is -1, do this for all registers.
Otherwise, REGNO specifies which register (so we can save time). */
-static void
-rs6000_store_inferior_registers (struct target_ops *ops,
- struct regcache *regcache, int regno)
+void
+rs6000_nat_target::store_registers (struct regcache *regcache, int regno)
{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
if (regno != -1)
store_register (regcache, regno);
/* Implement the to_xfer_partial target_ops method. */
-static enum target_xfer_status
-rs6000_xfer_partial (struct target_ops *ops, enum target_object object,
- const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf,
- ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
+enum target_xfer_status
+rs6000_nat_target::xfer_partial (enum target_object object,
+ const char *annex, gdb_byte *readbuf,
+ const gdb_byte *writebuf,
+ ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len)
{
- pid_t pid = ptid_get_pid (inferior_ptid);
+ pid_t pid = inferior_ptid.pid ();
int arch64 = ARCH64 ();
switch (object)
{
case TARGET_OBJECT_LIBRARIES_AIX:
- return rs6000_xfer_shared_libraries (ops, object, annex,
- readbuf, writebuf,
- offset, len, xfered_len);
+ return xfer_shared_libraries (object, annex,
+ readbuf, writebuf,
+ offset, len, xfered_len);
case TARGET_OBJECT_MEMORY:
{
union
process ID of the child, or MINUS_ONE_PTID in case of error; store
the status in *OURSTATUS. */
-static ptid_t
-rs6000_wait (struct target_ops *ops,
- ptid_t ptid, struct target_waitstatus *ourstatus, int options)
+ptid_t
+rs6000_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
+ int options)
{
pid_t pid;
int status, save_errno;
do
{
- pid = waitpid (ptid_get_pid (ptid), &status, 0);
+ pid = waitpid (ptid.pid (), &status, 0);
save_errno = errno;
}
while (pid == -1 && errno == EINTR);
}
/* Ignore terminated detached child processes. */
- if (!WIFSTOPPED (status) && pid != ptid_get_pid (inferior_ptid))
+ if (!WIFSTOPPED (status) && pid != inferior_ptid.pid ())
pid = -1;
}
while (pid == -1);
else
store_waitstatus (ourstatus, status);
- return pid_to_ptid (pid);
+ return ptid_t (pid);
}
\f
/* Set the current architecture from the host running GDB. Called when
starting a child process. */
-static void (*super_create_inferior) (struct target_ops *,char *exec_file,
- char *allargs, char **env, int from_tty);
-static void
-rs6000_create_inferior (struct target_ops * ops, char *exec_file,
- char *allargs, char **env, int from_tty)
+void
+rs6000_nat_target::create_inferior (const char *exec_file,
+ const std::string &allargs,
+ char **env, int from_tty)
{
enum bfd_architecture arch;
unsigned long mach;
bfd abfd;
struct gdbarch_info info;
- super_create_inferior (ops, exec_file, allargs, env, from_tty);
+ inf_ptrace_target::create_inferior (exec_file, allargs, env, from_tty);
if (__power_rs ())
{
/* Shared Object support. */
/* Return the LdInfo data for the given process. Raises an error
- if the data could not be obtained.
-
- The returned value must be deallocated after use. */
+ if the data could not be obtained. */
-static gdb_byte *
+static gdb::byte_vector
rs6000_ptrace_ldinfo (ptid_t ptid)
{
- const int pid = ptid_get_pid (ptid);
- int ldi_size = 1024;
- gdb_byte *ldi = xmalloc (ldi_size);
+ const int pid = ptid.pid ();
+ gdb::byte_vector ldi (1024);
int rc = -1;
while (1)
{
if (ARCH64 ())
- rc = rs6000_ptrace64 (PT_LDINFO, pid, (unsigned long) ldi, ldi_size,
- NULL);
+ rc = rs6000_ptrace64 (PT_LDINFO, pid, (unsigned long) ldi.data (),
+ ldi.size (), NULL);
else
- rc = rs6000_ptrace32 (PT_LDINFO, pid, (int *) ldi, ldi_size, NULL);
+ rc = rs6000_ptrace32 (PT_LDINFO, pid, (int *) ldi.data (),
+ ldi.size (), NULL);
if (rc != -1)
break; /* Success, we got the entire ld_info data. */
perror_with_name (_("ptrace ldinfo"));
/* ldi is not big enough. Double it and try again. */
- ldi_size *= 2;
- ldi = xrealloc (ldi, ldi_size);
+ ldi.resize (ldi.size () * 2);
}
return ldi;
/* Implement the to_xfer_partial target_ops method for
TARGET_OBJECT_LIBRARIES_AIX objects. */
-static enum target_xfer_status
-rs6000_xfer_shared_libraries
- (struct target_ops *ops, enum target_object object,
+enum target_xfer_status
+rs6000_nat_target::xfer_shared_libraries
+ (enum target_object object,
const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
- gdb_byte *ldi_buf;
ULONGEST result;
- struct cleanup *cleanup;
/* This function assumes that it is being run with a live process.
Core files are handled via gdbarch. */
if (writebuf)
return TARGET_XFER_E_IO;
- ldi_buf = rs6000_ptrace_ldinfo (inferior_ptid);
- gdb_assert (ldi_buf != NULL);
- cleanup = make_cleanup (xfree, ldi_buf);
- result = rs6000_aix_ld_info_to_xml (target_gdbarch (), ldi_buf,
+ gdb::byte_vector ldi_buf = rs6000_ptrace_ldinfo (inferior_ptid);
+ result = rs6000_aix_ld_info_to_xml (target_gdbarch (), ldi_buf.data (),
readbuf, offset, len, 1);
- xfree (ldi_buf);
-
- do_cleanups (cleanup);
if (result == 0)
return TARGET_XFER_EOF;
}
}
-void _initialize_rs6000_nat (void);
-
void
_initialize_rs6000_nat (void)
{
- struct target_ops *t;
-
- t = inf_ptrace_target ();
- t->to_fetch_registers = rs6000_fetch_inferior_registers;
- t->to_store_registers = rs6000_store_inferior_registers;
- t->to_xfer_partial = rs6000_xfer_partial;
-
- super_create_inferior = t->to_create_inferior;
- t->to_create_inferior = rs6000_create_inferior;
-
- t->to_wait = rs6000_wait;
-
- add_target (t);
+ add_inf_child_target (&the_rs6000_nat_target);
}