Patchwork [15/40] target_ops/C++: Solaris/procfs

login
register
mail settings
Submitter Pedro Alves
Date April 14, 2018, 7:09 p.m.
Message ID <20180414190953.24481-16-palves@redhat.com>
Download mbox | patch
Permalink /patch/26739/
State New
Headers show

Comments

Pedro Alves - April 14, 2018, 7:09 p.m.
Straighforward conversion.  I'd tested this on a Solaris VM.
---
 gdb/procfs.c     | 304 ++++++++++++++++++++++++-------------------------------
 gdb/sol-thread.c | 165 +++++++++++++++---------------
 2 files changed, 220 insertions(+), 249 deletions(-)

Patch

diff --git a/gdb/procfs.c b/gdb/procfs.c
index 478770d0fe..abae358c44 100644
--- a/gdb/procfs.c
+++ b/gdb/procfs.c
@@ -86,69 +86,88 @@ 
 
 /* This module defines the GDB target vector and its methods.  */
 
-static void procfs_attach (struct target_ops *, const char *, int);
-static void procfs_detach (struct target_ops *, inferior *, int);
-static void procfs_resume (struct target_ops *,
-			   ptid_t, int, enum gdb_signal);
-static void procfs_files_info (struct target_ops *);
-static void procfs_fetch_registers (struct target_ops *,
-				    struct regcache *, int);
-static void procfs_store_registers (struct target_ops *,
-				    struct regcache *, int);
-static void procfs_pass_signals (struct target_ops *self,
-				 int, unsigned char *);
-static void procfs_kill_inferior (struct target_ops *ops);
-static void procfs_mourn_inferior (struct target_ops *ops);
-static void procfs_create_inferior (struct target_ops *, const char *,
-				    const std::string &, char **, int);
-static ptid_t procfs_wait (struct target_ops *,
-			   ptid_t, struct target_waitstatus *, int);
+
 static enum target_xfer_status procfs_xfer_memory (gdb_byte *,
 						   const gdb_byte *,
 						   ULONGEST, ULONGEST,
 						   ULONGEST *);
-static target_xfer_partial_ftype procfs_xfer_partial;
 
-static int procfs_thread_alive (struct target_ops *ops, ptid_t);
+class procfs_target final : public inf_child_target
+{
+public:
+  void create_inferior (const char *, const std::string &,
+			char **, int) override;
+
+  void kill () override;
+
+  void mourn_inferior () override;
+
+  void attach (const char *, int) override;
+  void detach (inferior *inf, int) override;
+
+  void resume (ptid_t, int, enum gdb_signal) override;
+  ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
+
+  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 pass_signals (int, unsigned char *) override;
 
-static void procfs_update_thread_list (struct target_ops *ops);
-static const char *procfs_pid_to_str (struct target_ops *, ptid_t);
+  void files_info () override;
 
-static int proc_find_memory_regions (struct target_ops *self,
-				     find_memory_region_ftype, void *);
+  void update_thread_list () override;
 
-static char *procfs_make_note_section (struct target_ops *self,
-				       bfd *, int *);
+  int thread_alive (ptid_t ptid) override;
 
-static int procfs_can_use_hw_breakpoint (struct target_ops *self,
-					 enum bptype, int, int);
+  const char *pid_to_str (ptid_t) override;
 
-static void procfs_info_proc (struct target_ops *, const char *,
-			      enum info_proc_what);
+  thread_control_capabilities get_thread_control_capabilities () override
+  { return tc_schedlock; }
 
-static int procfs_stopped_by_watchpoint (struct target_ops *);
+  /* find_memory_regions support method for gcore */
+  int find_memory_regions (find_memory_region_ftype func, void *data)
+    override;
 
-static int procfs_insert_watchpoint (struct target_ops *,
-				     CORE_ADDR, int,
-				     enum target_hw_bp_type,
-				     struct expression *);
+  char *make_corefile_notes (bfd *, int *) override;
 
-static int procfs_remove_watchpoint (struct target_ops *,
-				     CORE_ADDR, int,
-				     enum target_hw_bp_type,
-				     struct expression *);
+  bool info_proc (const char *, enum info_proc_what) override;
+
+#if defined(PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64)
+  int auxv_parse (gdb_byte **readptr,
+		  gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
+    override;
+#endif
+
+  int stopped_by_watchpoint () override;
+
+  int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
+			 struct expression *) override;
+
+  int remove_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
+			 struct expression *) override;
+
+  int region_ok_for_hw_watchpoint (CORE_ADDR, int) override;
+
+  int can_use_hw_breakpoint (enum bptype, int, int) override;
+  int stopped_data_address (CORE_ADDR *) override;
+};
 
-static int procfs_region_ok_for_hw_watchpoint (struct target_ops *,
-					       CORE_ADDR, int);
-static int procfs_stopped_data_address (struct target_ops *, CORE_ADDR *);
+static procfs_target the_procfs_target;
 
 #if defined (PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64)
 /* When GDB is built as 64-bit application on Solaris, the auxv data
    is presented in 64-bit format.  We need to provide a custom parser
    to handle that.  */
-static int
-procfs_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
-		   gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
+int
+procfs_target::auxv_parse (gdb_byte **readptr,
+			   gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
   gdb_byte *ptr = *readptr;
@@ -171,51 +190,6 @@  procfs_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
 }
 #endif
 
-/* Create a procfs target.  */
-
-static struct target_ops *
-procfs_target (void)
-{
-  struct target_ops *t = inf_child_target ();
-
-  t->to_create_inferior = procfs_create_inferior;
-  t->to_kill = procfs_kill_inferior;
-  t->to_mourn_inferior = procfs_mourn_inferior;
-  t->to_attach = procfs_attach;
-  t->to_detach = procfs_detach;
-  t->to_wait = procfs_wait;
-  t->to_resume = procfs_resume;
-  t->to_fetch_registers = procfs_fetch_registers;
-  t->to_store_registers = procfs_store_registers;
-  t->to_xfer_partial = procfs_xfer_partial;
-  t->to_pass_signals = procfs_pass_signals;
-  t->to_files_info = procfs_files_info;
-
-  t->to_update_thread_list = procfs_update_thread_list;
-  t->to_thread_alive = procfs_thread_alive;
-  t->to_pid_to_str = procfs_pid_to_str;
-
-  t->to_has_thread_control = tc_schedlock;
-  t->to_find_memory_regions = proc_find_memory_regions;
-  t->to_make_corefile_notes = procfs_make_note_section;
-  t->to_info_proc = procfs_info_proc;
-
-#if defined(PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64)
-  t->to_auxv_parse = procfs_auxv_parse;
-#endif
-
-  t->to_stopped_by_watchpoint = procfs_stopped_by_watchpoint;
-  t->to_insert_watchpoint = procfs_insert_watchpoint;
-  t->to_remove_watchpoint = procfs_remove_watchpoint;
-  t->to_region_ok_for_hw_watchpoint = procfs_region_ok_for_hw_watchpoint;
-  t->to_can_use_hw_breakpoint = procfs_can_use_hw_breakpoint;
-  t->to_stopped_data_address = procfs_stopped_data_address;
-
-  t->to_magic = OPS_MAGIC;
-
-  return t;
-}
-
 /* =================== END, TARGET_OPS "MODULE" =================== */
 
 /* World Unification:
@@ -1912,8 +1886,8 @@  procfs_debug_inferior (procinfo *pi)
   return 0;
 }
 
-static void
-procfs_attach (struct target_ops *ops, const char *args, int from_tty)
+void
+procfs_target::attach (const char *args, int from_tty)
 {
   char *exec_file;
   int   pid;
@@ -1937,12 +1911,12 @@  procfs_attach (struct target_ops *ops, const char *args, int from_tty)
       fflush (stdout);
     }
   inferior_ptid = do_attach (pid_to_ptid (pid));
-  if (!target_is_pushed (ops))
-    push_target (ops);
+  if (!target_is_pushed (this))
+    push_target (this);
 }
 
-static void
-procfs_detach (struct target_ops *ops, inferior *inf, int from_tty)
+void
+procfs_target::detach (inferior *inf, int from_tty)
 {
   int pid = ptid_get_pid (inferior_ptid);
 
@@ -1963,7 +1937,7 @@  procfs_detach (struct target_ops *ops, inferior *inf, int from_tty)
 
   inferior_ptid = null_ptid;
   detach_inferior (pid);
-  inf_child_maybe_unpush_target (ops);
+  maybe_unpush_target ();
 }
 
 static ptid_t
@@ -2092,9 +2066,8 @@  do_detach ()
    registers.  So we cache the results, and mark the cache invalid
    when the process is resumed.  */
 
-static void
-procfs_fetch_registers (struct target_ops *ops,
-			struct regcache *regcache, int regnum)
+void
+procfs_target::fetch_registers (struct regcache *regcache, int regnum)
 {
   gdb_gregset_t *gregs;
   procinfo *pi;
@@ -2142,9 +2115,8 @@  procfs_fetch_registers (struct target_ops *ops,
    FIXME: is that a really bad idea?  Have to think about cases where
    writing one register might affect the value of others, etc.  */
 
-static void
-procfs_store_registers (struct target_ops *ops,
-			struct regcache *regcache, int regnum)
+void
+procfs_target::store_registers (struct regcache *regcache, int regnum)
 {
   gdb_gregset_t *gregs;
   procinfo *pi;
@@ -2228,9 +2200,9 @@  syscall_is_lwp_create (procinfo *pi, int scall)
    Returns the id of process (and possibly thread) that incurred the
    event.  Event codes are returned through a pointer parameter.  */
 
-static ptid_t
-procfs_wait (struct target_ops *ops,
-	     ptid_t ptid, struct target_waitstatus *status, int options)
+ptid_t
+procfs_target::wait (ptid_t ptid, struct target_waitstatus *status,
+		     int options)
 {
   /* First cut: loosely based on original version 2.1.  */
   procinfo *pi;
@@ -2271,7 +2243,7 @@  wait_again:
 	      int wait_retval;
 
 	      /* /proc file not found; presumably child has terminated.  */
-	      wait_retval = wait (&wstat); /* "wait" for the child's exit.  */
+	      wait_retval = ::wait (&wstat); /* "wait" for the child's exit.  */
 
 	      /* Wrong child?  */
 	      if (wait_retval != ptid_get_pid (inferior_ptid))
@@ -2364,7 +2336,7 @@  wait_again:
 		      }
 		    else
 		      {
-			int temp = wait (&wstat);
+			int temp = ::wait (&wstat);
 
 			/* FIXME: shouldn't I make sure I get the right
 			   event from the right process?  If (for
@@ -2594,11 +2566,11 @@  wait_again:
 /* Perform a partial transfer to/from the specified object.  For
    memory transfers, fall back to the old memory xfer functions.  */
 
-static enum target_xfer_status
-procfs_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
+procfs_target::xfer_partial (enum target_object object,
+			     const char *annex, gdb_byte *readbuf,
+			     const gdb_byte *writebuf, ULONGEST offset,
+			     ULONGEST len, ULONGEST *xfered_len)
 {
   switch (object)
     {
@@ -2606,13 +2578,13 @@  procfs_xfer_partial (struct target_ops *ops, enum target_object object,
       return procfs_xfer_memory (readbuf, writebuf, offset, len, xfered_len);
 
     case TARGET_OBJECT_AUXV:
-      return memory_xfer_auxv (ops, object, annex, readbuf, writebuf,
+      return memory_xfer_auxv (this, object, annex, readbuf, writebuf,
 			       offset, len, xfered_len);
 
     default:
-      return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
-					    readbuf, writebuf, offset, len,
-					    xfered_len);
+      return this->beneath->xfer_partial (object, annex,
+					  readbuf, writebuf, offset, len,
+					  xfered_len);
     }
 }
 
@@ -2741,9 +2713,8 @@  make_signal_thread_runnable (procinfo *process, procinfo *pi, void *ptr)
    allow any child thread to run; if non-zero, then allow only the
    indicated thread to run.  (not implemented yet).  */
 
-static void
-procfs_resume (struct target_ops *ops,
-	       ptid_t ptid, int step, enum gdb_signal signo)
+void
+procfs_target::resume (ptid_t ptid, int step, enum gdb_signal signo)
 {
   procinfo *pi, *thread;
   int native_signo;
@@ -2821,9 +2792,8 @@  procfs_resume (struct target_ops *ops,
 
 /* Set up to trace signals in the child process.  */
 
-static void
-procfs_pass_signals (struct target_ops *self,
-		     int numsigs, unsigned char *pass_signals)
+void
+procfs_target::pass_signals (int numsigs, unsigned char *pass_signals)
 {
   sigset_t signals;
   procinfo *pi = find_procinfo_or_die (ptid_get_pid (inferior_ptid), 0);
@@ -2844,8 +2814,8 @@  procfs_pass_signals (struct target_ops *self,
 
 /* Print status information about the child process.  */
 
-static void
-procfs_files_info (struct target_ops *ignore)
+void
+procfs_target::files_info ()
 {
   struct inferior *inf = current_inferior ();
 
@@ -2887,8 +2857,8 @@  unconditionally_kill_inferior (procinfo *pi)
 /* We're done debugging it, and we want it to go away.  Then we want
    GDB to forget all about it.  */
 
-static void
-procfs_kill_inferior (struct target_ops *ops)
+void
+procfs_target::kill ()
 {
   if (!ptid_equal (inferior_ptid, null_ptid)) /* ? */
     {
@@ -2903,8 +2873,8 @@  procfs_kill_inferior (struct target_ops *ops)
 
 /* Forget we ever debugged this thing!  */
 
-static void
-procfs_mourn_inferior (struct target_ops *ops)
+void
+procfs_target::mourn_inferior ()
 {
   procinfo *pi;
 
@@ -2918,7 +2888,7 @@  procfs_mourn_inferior (struct target_ops *ops)
 
   generic_mourn_inferior ();
 
-  inf_child_maybe_unpush_target (ops);
+  maybe_unpush_target ();
 }
 
 /* When GDB forks to create a runnable inferior process, this function
@@ -3081,9 +3051,10 @@  procfs_set_exec_trap (void)
    abstracted out and shared with other unix targets such as
    inf-ptrace?  */
 
-static void
-procfs_create_inferior (struct target_ops *ops, const char *exec_file,
-			const std::string &allargs, char **env, int from_tty)
+void
+procfs_target::create_inferior (const char *exec_file,
+				const std::string &allargs,
+				char **env, int from_tty)
 {
   char *shell_file = getenv ("SHELL");
   char *tryname;
@@ -3165,7 +3136,7 @@  procfs_create_inferior (struct target_ops *ops, const char *exec_file,
      pid shouldn't change.  */
   add_thread_silent (pid_to_ptid (pid));
 
-  procfs_init_inferior (ops, pid);
+  procfs_init_inferior (this, pid);
 }
 
 /* An observer for the "inferior_created" event.  */
@@ -3191,8 +3162,8 @@  procfs_notice_thread (procinfo *pi, procinfo *thread, void *ptr)
 /* Query all the threads that the target knows about, and give them
    back to GDB to add to its list.  */
 
-static void
-procfs_update_thread_list (struct target_ops *ops)
+void
+procfs_target::update_thread_list ()
 {
   procinfo *pi;
 
@@ -3208,8 +3179,8 @@  procfs_update_thread_list (struct target_ops *ops)
    really seem to be doing his job.  Got to investigate how to tell
    when a thread is really gone.  */
 
-static int
-procfs_thread_alive (struct target_ops *ops, ptid_t ptid)
+int
+procfs_target::thread_alive (ptid_t ptid)
 {
   int proc, thread;
   procinfo *pi;
@@ -3235,8 +3206,8 @@  procfs_thread_alive (struct target_ops *ops, ptid_t ptid)
 /* Convert PTID to a string.  Returns the string in a static
    buffer.  */
 
-static const char *
-procfs_pid_to_str (struct target_ops *ops, ptid_t ptid)
+const char *
+procfs_target::pid_to_str (ptid_t ptid)
 {
   static char buf[80];
 
@@ -3306,10 +3277,8 @@  procfs_set_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int rwflag,
    procfs.c targets due to the fact that some of them still define
    target_can_use_hardware_watchpoint.  */
 
-static int
-procfs_can_use_hw_breakpoint (struct target_ops *self,
-			      enum bptype type,
-			      int cnt, int othertype)
+int
+procfs_target::can_use_hw_breakpoint (enum bptype type, int cnt, int othertype)
 {
   /* Due to the way that proc_set_watchpoint() is implemented, host
      and target pointers must be of the same size.  If they are not,
@@ -3332,8 +3301,8 @@  procfs_can_use_hw_breakpoint (struct target_ops *self,
 /* Returns non-zero if process is stopped on a hardware watchpoint
    fault, else returns zero.  */
 
-static int
-procfs_stopped_by_watchpoint (struct target_ops *ops)
+int
+procfs_target::stopped_by_watchpoint ()
 {
   procinfo *pi;
 
@@ -3356,8 +3325,8 @@  procfs_stopped_by_watchpoint (struct target_ops *ops)
    procfs_stopped_by_watchpoint returned 1, thus no further checks are
    done.  The function also assumes that ADDR is not NULL.  */
 
-static int
-procfs_stopped_data_address (struct target_ops *targ, CORE_ADDR *addr)
+int
+procfs_target::stopped_data_address (CORE_ADDR *addr)
 {
   procinfo *pi;
 
@@ -3365,11 +3334,10 @@  procfs_stopped_data_address (struct target_ops *targ, CORE_ADDR *addr)
   return proc_watchpoint_address (pi, addr);
 }
 
-static int
-procfs_insert_watchpoint (struct target_ops *self,
-			  CORE_ADDR addr, int len,
-			  enum target_hw_bp_type type,
-			  struct expression *cond)
+int
+procfs_target::insert_watchpoint (CORE_ADDR addr, int len,
+				  enum target_hw_bp_type type,
+				  struct expression *cond)
 {
   if (!target_have_steppable_watchpoint
       && !gdbarch_have_nonsteppable_watchpoint (target_gdbarch ()))
@@ -3389,18 +3357,16 @@  procfs_insert_watchpoint (struct target_ops *self,
     }
 }
 
-static int
-procfs_remove_watchpoint (struct target_ops *self,
-			  CORE_ADDR addr, int len,
-			  enum target_hw_bp_type type,
-			  struct expression *cond)
+int
+procfs_target::remove_watchpoint (CORE_ADDR addr, int len,
+				  enum target_hw_bp_type type,
+				  struct expression *cond)
 {
   return procfs_set_watchpoint (inferior_ptid, addr, 0, 0, 0);
 }
 
-static int
-procfs_region_ok_for_hw_watchpoint (struct target_ops *self,
-				    CORE_ADDR addr, int len)
+int
+procfs_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
 {
   /* The man page for proc(4) on Solaris 2.6 and up says that the
      system can support "thousands" of hardware watchpoints, but gives
@@ -3494,9 +3460,8 @@  find_memory_regions_callback (struct prmap *map,
    Stops iterating and returns the first non-zero value returned by
    the callback.  */
 
-static int
-proc_find_memory_regions (struct target_ops *self,
-			  find_memory_region_ftype func, void *data)
+int
+procfs_target::find_memory_regions (find_memory_region_ftype func, void *data)
 {
   procinfo *pi = find_procinfo_or_die (ptid_get_pid (inferior_ptid), 0);
 
@@ -3586,9 +3551,8 @@  info_proc_mappings (procinfo *pi, int summary)
 
 /* Implement the "info proc" command.  */
 
-static void
-procfs_info_proc (struct target_ops *ops, const char *args,
-		  enum info_proc_what what)
+bool
+procfs_target::info_proc (const char *args, enum info_proc_what what)
 {
   struct cleanup *old_chain;
   procinfo *process  = NULL;
@@ -3673,6 +3637,8 @@  procfs_info_proc (struct target_ops *ops, const char *args,
     }
 
   do_cleanups (old_chain);
+
+  return true;
 }
 
 /* Modify the status of the system call identified by SYSCALLNUM in
@@ -3773,7 +3739,7 @@  _initialize_procfs (void)
   add_com ("proc-untrace-exit", no_class, proc_untrace_sysexit_cmd,
 	   _("Cancel a trace of exits from the syscall."));
 
-  add_target (procfs_target ());
+  add_target (&the_procfs_target);
 }
 
 /* =================== END, GDB  "MODULE" =================== */
@@ -3881,8 +3847,8 @@  find_stop_signal (void)
     return GDB_SIGNAL_0;
 }
 
-static char *
-procfs_make_note_section (struct target_ops *self, bfd *obfd, int *note_size)
+char *
+procfs_target::make_corefile_notes (bfd *obfd, int *note_size)
 {
   struct cleanup *old_chain;
   gdb_gregset_t gregs;
diff --git a/gdb/sol-thread.c b/gdb/sol-thread.c
index 62d839cd41..0572da30c0 100644
--- a/gdb/sol-thread.c
+++ b/gdb/sol-thread.c
@@ -69,7 +69,41 @@ 
 #include "minsyms.h"
 #include "objfiles.h"
 
-struct target_ops sol_thread_ops;
+class sol_thread_target : public target_ops
+{
+public:
+  sol_thread_target ()
+  { this->to_stratum = thread_stratum; }
+
+  const char *shortname () override
+  { return "solaris-threads"; }
+  const char *longname () override
+  { return _("Solaris threads and pthread."); }
+  const char *doc () override
+  { return _("Solaris threads and pthread support."); }
+
+  void detach (inferior *, int) override;
+  ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
+  void resume (ptid_t, int, enum gdb_signal) override;
+  void mourn_inferior () override;
+  const char *pid_to_str (ptid_t) override;
+  ptid_t get_ada_task_ptid (long lwp, long thread) override;
+
+  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;
+
+  int thread_alive (ptid_t ptid) override;
+  void update_thread_list () override;
+};
+
+static sol_thread_target sol_thread_ops;
 
 /* Prototypes for supply_gregset etc.  */
 #include "gregset.h"
@@ -93,8 +127,6 @@  static struct ps_prochandle main_ph;
 static td_thragent_t *main_ta;
 static int sol_thread_active = 0;
 
-static void init_sol_thread_ops (void);
-
 /* Default definitions: These must be defined in tm.h if they are to
    be shared with a process module such as procfs.  */
 
@@ -347,15 +379,15 @@  lwp_to_thread (ptid_t lwp)
    process to have been previously attached.  It *might* work if the
    program was started via the normal ptrace (PTRACE_TRACEME).  */
 
-static void
-sol_thread_detach (struct target_ops *ops, inferior *inf, int from_tty)
+void
+sol_thread_target::detach (inferior *inf, int from_tty)
 {
-  struct target_ops *beneath = find_target_beneath (ops);
+  struct target_ops *beneath = find_target_beneath (this);
 
   sol_thread_active = 0;
   inferior_ptid = pid_to_ptid (ptid_get_pid (main_ph.ptid));
-  unpush_target (ops);
-  beneath->to_detach (beneath, inf, from_tty);
+  unpush_target (this);
+  beneath->detach (inf, from_tty);
 }
 
 /* Resume execution of process PTID.  If STEP is nozero, then just
@@ -363,11 +395,10 @@  sol_thread_detach (struct target_ops *ops, inferior *inf, int from_tty)
    activated.  We may have to convert PTID from a thread ID to an LWP
    ID for procfs.  */
 
-static void
-sol_thread_resume (struct target_ops *ops,
-		   ptid_t ptid, int step, enum gdb_signal signo)
+void
+sol_thread_target::resume (ptid_t ptid, int step, enum gdb_signal signo)
 {
-  struct target_ops *beneath = find_target_beneath (ops);
+  struct target_ops *beneath = find_target_beneath (this);
 
   scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
 
@@ -387,19 +418,19 @@  sol_thread_resume (struct target_ops *ops,
 		 ptid_get_tid (save_ptid));
     }
 
-  beneath->to_resume (beneath, ptid, step, signo);
+  beneath->resume (ptid, step, signo);
 }
 
 /* Wait for any threads to stop.  We may have to convert PTID from a
    thread ID to an LWP ID, and vice versa on the way out.  */
 
-static ptid_t
-sol_thread_wait (struct target_ops *ops,
-		 ptid_t ptid, struct target_waitstatus *ourstatus, int options)
+ptid_t
+sol_thread_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
+			 int options)
 {
   ptid_t rtnval;
   ptid_t save_ptid;
-  struct target_ops *beneath = find_target_beneath (ops);
+  struct target_ops *beneath = find_target_beneath (this);
 
   save_ptid = inferior_ptid;
   scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
@@ -420,7 +451,7 @@  sol_thread_wait (struct target_ops *ops,
 		 ptid_get_tid (save_ptid));
     }
 
-  rtnval = beneath->to_wait (beneath, ptid, ourstatus, options);
+  rtnval = beneath->wait (ptid, ourstatus, options);
 
   if (ourstatus->kind != TARGET_WAITKIND_EXITED)
     {
@@ -444,9 +475,8 @@  sol_thread_wait (struct target_ops *ops,
   return rtnval;
 }
 
-static void
-sol_thread_fetch_registers (struct target_ops *ops,
-			    struct regcache *regcache, int regnum)
+void
+sol_thread_target::fetch_registers (struct regcache *regcache, int regnum)
 {
   thread_t thread;
   td_thrhandle_t thandle;
@@ -455,13 +485,13 @@  sol_thread_fetch_registers (struct target_ops *ops,
   prfpregset_t fpregset;
   gdb_gregset_t *gregset_p = &gregset;
   gdb_fpregset_t *fpregset_p = &fpregset;
-  struct target_ops *beneath = find_target_beneath (ops);
+  struct target_ops *beneath = find_target_beneath (this);
   ptid_t ptid = regcache_get_ptid (regcache);
 
   if (!ptid_tid_p (ptid))
     {
       /* It's an LWP; pass the request on to the layer beneath.  */
-      beneath->to_fetch_registers (beneath, regcache, regnum);
+      beneath->fetch_registers (regcache, regnum);
       return;
     }
 
@@ -500,9 +530,8 @@  sol_thread_fetch_registers (struct target_ops *ops,
   supply_fpregset (regcache, (const gdb_fpregset_t *) fpregset_p);
 }
 
-static void
-sol_thread_store_registers (struct target_ops *ops,
-			    struct regcache *regcache, int regnum)
+void
+sol_thread_target::store_registers (struct regcache *regcache, int regnum)
 {
   thread_t thread;
   td_thrhandle_t thandle;
@@ -513,10 +542,10 @@  sol_thread_store_registers (struct target_ops *ops,
 
   if (!ptid_tid_p (ptid))
     {
-      struct target_ops *beneath = find_target_beneath (ops);
+      struct target_ops *beneath = find_target_beneath (this);
 
       /* It's an LWP; pass the request on to the layer beneath.  */
-      beneath->to_store_registers (beneath, regcache, regnum);
+      beneath->store_registers (regcache, regnum);
       return;
     }
 
@@ -557,13 +586,14 @@  sol_thread_store_registers (struct target_ops *ops,
    target_write_partial for details of each variant.  One, and only
    one, of readbuf or writebuf must be non-NULL.  */
 
-static enum target_xfer_status
-sol_thread_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
+sol_thread_target::xfer_partial (enum target_object object,
+				 const char *annex, gdb_byte *readbuf,
+				 const gdb_byte *writebuf,
+				 ULONGEST offset, ULONGEST len,
+				 ULONGEST *xfered_len)
 {
-  struct target_ops *beneath = find_target_beneath (ops);
+  struct target_ops *beneath = find_target_beneath (this);
 
   scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
 
@@ -577,8 +607,8 @@  sol_thread_xfer_partial (struct target_ops *ops, enum target_object object,
       inferior_ptid = procfs_first_available ();
     }
 
-  return beneath->to_xfer_partial (beneath, object, annex, readbuf,
-				   writebuf, offset, len, xfered_len);
+  return beneath->xfer_partial (object, annex, readbuf,
+				writebuf, offset, len, xfered_len);
 }
 
 static void
@@ -588,7 +618,7 @@  check_for_thread_db (void)
   ptid_t ptid;
 
   /* Don't attempt to use thread_db for remote targets.  */
-  if (!(target_can_run (&current_target) || core_bfd))
+  if (!(target_can_run () || core_bfd))
     return;
 
   /* Do nothing if we couldn't load libthread_db.so.1.  */
@@ -656,22 +686,22 @@  sol_thread_new_objfile (struct objfile *objfile)
 
 /* Clean up after the inferior dies.  */
 
-static void
-sol_thread_mourn_inferior (struct target_ops *ops)
+void
+sol_thread_target::mourn_inferior ()
 {
-  struct target_ops *beneath = find_target_beneath (ops);
+  struct target_ops *beneath = find_target_beneath (this);
 
   sol_thread_active = 0;
 
-  unpush_target (ops);
+  unpush_target (this);
 
-  beneath->to_mourn_inferior (beneath);
+  beneath->mourn_inferior ();
 }
 
 /* Return true if PTID is still active in the inferior.  */
 
-static int
-sol_thread_alive (struct target_ops *ops, ptid_t ptid)
+int
+sol_thread_target::thread_alive (ptid_t ptid)
 {
   if (ptid_tid_p (ptid))
     {
@@ -689,10 +719,10 @@  sol_thread_alive (struct target_ops *ops, ptid_t ptid)
     }
   else
     {
-      struct target_ops *beneath = find_target_beneath (ops);
+      struct target_ops *beneath = find_target_beneath (this);
 
       /* It's an LPW; pass the request on to the layer below.  */
-      return beneath->to_thread_alive (beneath, ptid);
+      return beneath->thread_alive (ptid);
     }
 }
 
@@ -976,8 +1006,8 @@  ps_lgetLDT (struct ps_prochandle *ph, lwpid_t lwpid,
 
 /* Convert PTID to printable form.  */
 
-static const char *
-solaris_pid_to_str (struct target_ops *ops, ptid_t ptid)
+const char *
+sol_thread_target::pid_to_str (ptid_t ptid)
 {
   static char buf[100];
 
@@ -1027,16 +1057,16 @@  sol_update_thread_list_callback (const td_thrhandle_t *th, void *ignored)
   return 0;
 }
 
-static void
-sol_update_thread_list (struct target_ops *ops)
+void
+sol_thread_target::update_thread_list ()
 {
-  struct target_ops *beneath = find_target_beneath (ops);
+  struct target_ops *beneath = find_target_beneath (this);
 
   /* Delete dead threads.  */
   prune_threads ();
 
   /* Find any new LWP's.  */
-  beneath->to_update_thread_list (beneath);
+  beneath->update_thread_list ();
 
   /* Then find any new user-level threads.  */
   p_td_ta_thr_iter (main_ta, sol_update_thread_list_callback, (void *) 0,
@@ -1143,8 +1173,8 @@  thread_db_find_thread_from_tid (struct thread_info *thread, void *data)
   return 0;
 }
 
-static ptid_t
-sol_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
+ptid_t
+sol_thread_target::get_ada_task_ptid (long lwp, long thread)
 {
   struct thread_info *thread_info =
     iterate_over_threads (thread_db_find_thread_from_tid, &thread);
@@ -1153,7 +1183,7 @@  sol_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
     {
       /* The list of threads is probably not up to date.  Find any
          thread that is missing from the list, and try again.  */
-      sol_update_thread_list (&current_target);
+      update_thread_list ();
       thread_info = iterate_over_threads (thread_db_find_thread_from_tid,
                                           &thread);
     }
@@ -1163,34 +1193,11 @@  sol_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
   return (thread_info->ptid);
 }
 
-static void
-init_sol_thread_ops (void)
-{
-  sol_thread_ops.to_shortname = "solaris-threads";
-  sol_thread_ops.to_longname = "Solaris threads and pthread.";
-  sol_thread_ops.to_doc = "Solaris threads and pthread support.";
-  sol_thread_ops.to_detach = sol_thread_detach;
-  sol_thread_ops.to_resume = sol_thread_resume;
-  sol_thread_ops.to_wait = sol_thread_wait;
-  sol_thread_ops.to_fetch_registers = sol_thread_fetch_registers;
-  sol_thread_ops.to_store_registers = sol_thread_store_registers;
-  sol_thread_ops.to_xfer_partial = sol_thread_xfer_partial;
-  sol_thread_ops.to_mourn_inferior = sol_thread_mourn_inferior;
-  sol_thread_ops.to_thread_alive = sol_thread_alive;
-  sol_thread_ops.to_pid_to_str = solaris_pid_to_str;
-  sol_thread_ops.to_update_thread_list = sol_update_thread_list;
-  sol_thread_ops.to_stratum = thread_stratum;
-  sol_thread_ops.to_get_ada_task_ptid = sol_get_ada_task_ptid;
-  sol_thread_ops.to_magic = OPS_MAGIC;
-}
-
 void
 _initialize_sol_thread (void)
 {
   void *dlhandle;
 
-  init_sol_thread_ops ();
-
   dlhandle = dlopen ("libthread_db.so.1", RTLD_NOW);
   if (!dlhandle)
     goto die;
@@ -1223,8 +1230,6 @@  _initialize_sol_thread (void)
   resolve (td_thr_getgregs);
   resolve (td_thr_setgregs);
 
-  complete_target_initialization (&sol_thread_ops);
-
   add_cmd ("sol-threads", class_maintenance, info_solthreads,
 	   _("Show info on Solaris user threads."), &maintenanceinfolist);