gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / rs6000-nat.c
index 8cdd86f8d198bf3fb139f0186487788c2fc76ca4..654e06e3e4bf319206787f86685817b173e7fcfe 100644 (file)
@@ -1,6 +1,6 @@
 /* IBM RS/6000 native-dependent code for GDB, the GNU debugger.
 
-   Copyright (C) 1986-2015 Free Software Foundation, Inc.
+   Copyright (C) 1986-2020 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -23,7 +23,6 @@
 #include "gdbcore.h"
 #include "symfile.h"
 #include "objfiles.h"
-#include "libbfd.h"            /* For bfd_default_set_arch_mach (FIXME) */
 #include "bfd.h"
 #include "gdb-stabs.h"
 #include "regcache.h"
@@ -34,7 +33,7 @@
 #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
@@ -143,9 +169,9 @@ rs6000_ptrace64 (int req, int id, long long addr, int data, void *buf)
 {
 #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;
@@ -162,9 +188,10 @@ rs6000_ptrace64 (int req, int id, long long addr, int data, void *buf)
 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;
@@ -173,7 +200,7 @@ fetch_register (struct regcache *regcache, int regno)
 
   /* 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)
@@ -189,15 +216,13 @@ fetch_register (struct regcache *regcache, int regno)
   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
@@ -206,7 +231,7 @@ fetch_register (struct regcache *regcache, int regno)
     }
 
   if (!errno)
-    regcache_raw_supply (regcache, regno, (char *) addr);
+    regcache->raw_supply (regno, (char *) addr);
   else
     {
 #if 0
@@ -222,12 +247,13 @@ fetch_register (struct regcache *regcache, int regno)
 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;
@@ -236,7 +262,7 @@ store_register (struct regcache *regcache, int regno)
 
   /* 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)
@@ -254,8 +280,7 @@ store_register (struct regcache *regcache, int regno)
          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
@@ -265,8 +290,7 @@ store_register (struct regcache *regcache, int regno)
            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);
        }
     }
 
@@ -280,11 +304,10 @@ store_register (struct regcache *regcache, int regno)
 /* 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);
 
@@ -323,11 +346,10 @@ rs6000_fetch_inferior_registers (struct target_ops *ops,
    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);
 
@@ -364,21 +386,22 @@ rs6000_store_inferior_registers (struct target_ops *ops,
 
 /* 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
@@ -470,9 +493,9 @@ rs6000_xfer_partial (struct target_ops *ops, enum target_object object,
    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;
@@ -483,7 +506,7 @@ rs6000_wait (struct target_ops *ops,
 
       do
        {
-         pid = waitpid (ptid_get_pid (ptid), &status, 0);
+         pid = waitpid (ptid.pid (), &status, 0);
          save_errno = errno;
        }
       while (pid == -1 && errno == EINTR);
@@ -503,7 +526,7 @@ rs6000_wait (struct target_ops *ops,
        }
 
       /* 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);
@@ -520,25 +543,24 @@ rs6000_wait (struct target_ops *ops,
   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 ())
     {
@@ -584,25 +606,23 @@ rs6000_create_inferior (struct target_ops * ops, char *exec_file,
 /* 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.  */
@@ -611,8 +631,7 @@ rs6000_ptrace_ldinfo (ptid_t ptid)
        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;
@@ -621,15 +640,13 @@ rs6000_ptrace_ldinfo (ptid_t ptid)
 /* 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.  */
@@ -638,14 +655,9 @@ rs6000_xfer_shared_libraries
   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;
@@ -656,22 +668,9 @@ rs6000_xfer_shared_libraries
     }
 }
 
-void _initialize_rs6000_nat (void);
-
+void _initialize_rs6000_nat ();
 void
-_initialize_rs6000_nat (void)
+_initialize_rs6000_nat ()
 {
-  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);
 }
This page took 0.02899 seconds and 4 git commands to generate.