gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / bsd-uthread.c
index c73932a8a49691203de1547c0f2e6de5277f364e..15d538c16db5f470a4213b565f293c1cd3ba3b7f 100644 (file)
@@ -1,6 +1,6 @@
 /* BSD user-level threads support.
 
-   Copyright (C) 2005-2014 Free Software Foundation, Inc.
+   Copyright (C) 2005-2020 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "gdbthread.h"
 #include "inferior.h"
 #include "objfiles.h"
-#include "observer.h"
+#include "observable.h"
 #include "regcache.h"
 #include "solib.h"
 #include "solist.h"
 #include "symfile.h"
 #include "target.h"
 
-#include "gdb_assert.h"
 #include "gdb_obstack.h"
 
 #include "bsd-uthread.h"
 
-/* HACK: Save the bsd_uthreads ops returned by bsd_uthread_target.  */
-static struct target_ops *bsd_uthread_ops_hack;
+static const target_info bsd_uthread_target_info = {
+  "bsd-uthreads",
+  N_("BSD user-level threads"),
+  N_("BSD user-level threads")
+};
+
+struct bsd_uthread_target final : public target_ops
+{
+  const target_info &info () const override
+  { return bsd_uthread_target_info; }
+
+  strata stratum () const override { return thread_stratum; }
+
+  void close () override;
+
+  void mourn_inferior () override;
+
+  void fetch_registers (struct regcache *, int) override;
+  void store_registers (struct regcache *, int) override;
+
+  ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
+  void resume (ptid_t, int, enum gdb_signal) override;
+
+  bool thread_alive (ptid_t ptid) override;
+
+  void update_thread_list () override;
+
+  const char *extra_thread_info (struct thread_info *) override;
+
+  std::string pid_to_str (ptid_t) override;
+};
+
+static bsd_uthread_target bsd_uthread_ops;
 \f
 
 /* Architecture-specific operations.  */
@@ -69,7 +99,9 @@ bsd_uthread_set_supply_uthread (struct gdbarch *gdbarch,
                                void (*supply_uthread) (struct regcache *,
                                                        int, CORE_ADDR))
 {
-  struct bsd_uthread_ops *ops = gdbarch_data (gdbarch, bsd_uthread_data);
+  struct bsd_uthread_ops *ops
+    = (struct bsd_uthread_ops *) gdbarch_data (gdbarch, bsd_uthread_data);
+
   ops->supply_uthread = supply_uthread;
 }
 
@@ -81,7 +113,9 @@ bsd_uthread_set_collect_uthread (struct gdbarch *gdbarch,
                         void (*collect_uthread) (const struct regcache *,
                                                  int, CORE_ADDR))
 {
-  struct bsd_uthread_ops *ops = gdbarch_data (gdbarch, bsd_uthread_data);
+  struct bsd_uthread_ops *ops
+    = (struct bsd_uthread_ops *) gdbarch_data (gdbarch, bsd_uthread_data);
+
   ops->collect_uthread = collect_uthread;
 }
 
@@ -162,7 +196,8 @@ static int
 bsd_uthread_activate (struct objfile *objfile)
 {
   struct gdbarch *gdbarch = target_gdbarch ();
-  struct bsd_uthread_ops *ops = gdbarch_data (gdbarch, bsd_uthread_data);
+  struct bsd_uthread_ops *ops
+    = (struct bsd_uthread_ops *) gdbarch_data (gdbarch, bsd_uthread_data);
 
   /* Skip if the thread stratum has already been activated.  */
   if (bsd_uthread_active)
@@ -196,15 +231,15 @@ bsd_uthread_activate (struct objfile *objfile)
   bsd_uthread_thread_ctx_offset =
     bsd_uthread_lookup_offset ("_thread_ctx_offset", objfile);
 
-  push_target (bsd_uthread_ops_hack);
+  push_target (&bsd_uthread_ops);
   bsd_uthread_active = 1;
   return 1;
 }
 
 /* Cleanup due to deactivation.  */
 
-static void
-bsd_uthread_close (struct target_ops *self)
+void
+bsd_uthread_target::close ()
 {
   bsd_uthread_active = 0;
   bsd_uthread_thread_run_addr = 0;
@@ -224,7 +259,7 @@ bsd_uthread_deactivate (void)
   if (!bsd_uthread_active)
     return;
 
-  unpush_target (bsd_uthread_ops_hack);
+  unpush_target (&bsd_uthread_ops);
 }
 
 static void
@@ -248,7 +283,7 @@ bsd_uthread_solib_loaded (struct so_list *so)
 
   for (names = bsd_uthread_solib_names; *names; names++)
     {
-      if (strncmp (so->so_original_name, *names, strlen (*names)) == 0)
+      if (startswith (so->so_original_name, *names))
        {
          solib_read_symbols (so, 0);
 
@@ -271,26 +306,30 @@ bsd_uthread_solib_unloaded (struct so_list *so)
     bsd_uthread_deactivate ();
 }
 
-static void
-bsd_uthread_mourn_inferior (struct target_ops *ops)
+void
+bsd_uthread_target::mourn_inferior ()
 {
-  struct target_ops *beneath = find_target_beneath (ops);
-  beneath->to_mourn_inferior (beneath);
+  beneath ()->mourn_inferior ();
   bsd_uthread_deactivate ();
 }
 
-static void
-bsd_uthread_fetch_registers (struct target_ops *ops,
-                            struct regcache *regcache, int regnum)
+void
+bsd_uthread_target::fetch_registers (struct regcache *regcache, int regnum)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
-  struct bsd_uthread_ops *uthread_ops = gdbarch_data (gdbarch, bsd_uthread_data);
-  CORE_ADDR addr = ptid_get_tid (inferior_ptid);
-  struct target_ops *beneath = find_target_beneath (ops);
+  struct gdbarch *gdbarch = regcache->arch ();
+  struct bsd_uthread_ops *uthread_ops
+    = (struct bsd_uthread_ops *) gdbarch_data (gdbarch, bsd_uthread_data);
+  ptid_t ptid = regcache->ptid ();
+  CORE_ADDR addr = ptid.tid ();
   CORE_ADDR active_addr;
+  scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
+
+  /* We are doing operations (e.g. reading memory) that rely on
+     inferior_ptid.  */
+  inferior_ptid = ptid;
 
   /* Always fetch the appropriate registers from the layer beneath.  */
-  beneath->to_fetch_registers (beneath, regcache, regnum);
+  beneath ()->fetch_registers (regcache, regnum);
 
   /* FIXME: That might have gotten us more than we asked for.  Make
      sure we overwrite all relevant registers with values from the
@@ -306,15 +345,20 @@ bsd_uthread_fetch_registers (struct target_ops *ops,
     }
 }
 
-static void
-bsd_uthread_store_registers (struct target_ops *ops,
-                            struct regcache *regcache, int regnum)
+void
+bsd_uthread_target::store_registers (struct regcache *regcache, int regnum)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
-  struct bsd_uthread_ops *uthread_ops = gdbarch_data (gdbarch, bsd_uthread_data);
-  struct target_ops *beneath = find_target_beneath (ops);
-  CORE_ADDR addr = ptid_get_tid (inferior_ptid);
+  struct gdbarch *gdbarch = regcache->arch ();
+  struct bsd_uthread_ops *uthread_ops
+    = (struct bsd_uthread_ops *) gdbarch_data (gdbarch, bsd_uthread_data);
+  ptid_t ptid = regcache->ptid ();
+  CORE_ADDR addr = ptid.tid ();
   CORE_ADDR active_addr;
+  scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
+
+  /* We are doing operations (e.g. reading memory) that rely on
+     inferior_ptid.  */
+  inferior_ptid = ptid;
 
   active_addr = bsd_uthread_read_memory_address (bsd_uthread_thread_run_addr);
   if (addr != 0 && addr != active_addr)
@@ -327,20 +371,21 @@ bsd_uthread_store_registers (struct target_ops *ops,
     {
       /* Updating the thread that is currently running; pass the
          request to the layer beneath.  */
-      beneath->to_store_registers (beneath, regcache, regnum);
+      beneath ()->store_registers (regcache, regnum);
     }
 }
 
-static ptid_t
-bsd_uthread_wait (struct target_ops *ops,
-                 ptid_t ptid, struct target_waitstatus *status, int options)
+ptid_t
+bsd_uthread_target::wait (ptid_t ptid, struct target_waitstatus *status,
+                         int options)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
   CORE_ADDR addr;
-  struct target_ops *beneath = find_target_beneath (ops);
+  process_stratum_target *beneath
+    = as_process_stratum_target (this->beneath ());
 
   /* Pass the request to the layer beneath.  */
-  ptid = beneath->to_wait (beneath, ptid, status, options);
+  ptid = beneath->wait (ptid, status, options);
 
   /* If the process is no longer alive, there's no point in figuring
      out the thread ID.  It will fail anyway.  */
@@ -363,39 +408,37 @@ bsd_uthread_wait (struct target_ops *ops,
        {
          ULONGEST magic = extract_unsigned_integer (buf, 4, byte_order);
          if (magic == BSD_UTHREAD_PTHREAD_MAGIC)
-           ptid = ptid_build (ptid_get_pid (ptid), 0, addr);
+           ptid = ptid_t (ptid.pid (), 0, addr);
        }
     }
 
   /* If INFERIOR_PTID doesn't have a tid member yet, and we now have a
      ptid with tid set, then ptid is still the initial thread of
      the process.  Notify GDB core about it.  */
-  if (ptid_get_tid (inferior_ptid) == 0
-      && ptid_get_tid (ptid) != 0 && !in_thread_list (ptid))
-    thread_change_ptid (inferior_ptid, ptid);
+  if (inferior_ptid.tid () == 0
+      && ptid.tid () != 0 && !in_thread_list (beneath, ptid))
+    thread_change_ptid (beneath, inferior_ptid, ptid);
 
   /* Don't let the core see a ptid without a corresponding thread.  */
-  if (!in_thread_list (ptid) || is_exited (ptid))
-    add_thread (ptid);
+  thread_info *thread = find_thread_ptid (beneath, ptid);
+  if (thread == NULL || thread->state == THREAD_EXITED)
+    add_thread (beneath, ptid);
 
   return ptid;
 }
 
-static void
-bsd_uthread_resume (struct target_ops *ops,
-                   ptid_t ptid, int step, enum gdb_signal sig)
+void
+bsd_uthread_target::resume (ptid_t ptid, int step, enum gdb_signal sig)
 {
   /* Pass the request to the layer beneath.  */
-  struct target_ops *beneath = find_target_beneath (ops);
-  beneath->to_resume (beneath, ptid, step, sig);
+  beneath ()->resume (ptid, step, sig);
 }
 
-static int
-bsd_uthread_thread_alive (struct target_ops *ops, ptid_t ptid)
+bool
+bsd_uthread_target::thread_alive (ptid_t ptid)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
-  struct target_ops *beneath = find_target_beneath (ops);
-  CORE_ADDR addr = ptid_get_tid (inferior_ptid);
+  CORE_ADDR addr = ptid.tid ();
 
   if (addr != 0)
     {
@@ -406,33 +449,38 @@ bsd_uthread_thread_alive (struct target_ops *ops, ptid_t ptid)
 
       state = read_memory_unsigned_integer (addr + offset, 4, byte_order);
       if (state == BSD_UTHREAD_PS_DEAD)
-       return 0;
+       return false;
     }
 
-  return beneath->to_thread_alive (beneath, ptid);
+  return beneath ()->thread_alive (ptid);
 }
 
-static void
-bsd_uthread_find_new_threads (struct target_ops *ops)
+void
+bsd_uthread_target::update_thread_list ()
 {
-  pid_t pid = ptid_get_pid (inferior_ptid);
+  pid_t pid = inferior_ptid.pid ();
   int offset = bsd_uthread_thread_next_offset;
   CORE_ADDR addr;
 
+  prune_threads ();
+
   addr = bsd_uthread_read_memory_address (bsd_uthread_thread_list_addr);
   while (addr != 0)
     {
-      ptid_t ptid = ptid_build (pid, 0, addr);
+      ptid_t ptid = ptid_t (pid, 0, addr);
 
-      if (!in_thread_list (ptid) || is_exited (ptid))
+      process_stratum_target *proc_target
+       = as_process_stratum_target (this->beneath ());
+      thread_info *thread = find_thread_ptid (proc_target, ptid);
+      if (thread == nullptr || thread->state == THREAD_EXITED)
        {
          /* If INFERIOR_PTID doesn't have a tid member yet, then ptid
             is still the initial thread of the process.  Notify GDB
             core about it.  */
-         if (ptid_get_tid (inferior_ptid) == 0)
-           thread_change_ptid (inferior_ptid, ptid);
+         if (inferior_ptid.tid () == 0)
+           thread_change_ptid (proc_target, inferior_ptid, ptid);
          else
-           add_thread (ptid);
+           add_thread (proc_target, ptid);
        }
 
       addr = bsd_uthread_read_memory_address (addr + offset);
@@ -440,7 +488,7 @@ bsd_uthread_find_new_threads (struct target_ops *ops)
 }
 
 /* Possible states a thread can be in.  */
-static char *bsd_uthread_state[] =
+static const char *bsd_uthread_state[] =
 {
   "RUNNING",
   "SIGTHREAD",
@@ -467,12 +515,11 @@ static char *bsd_uthread_state[] =
 /* Return a string describing th state of the thread specified by
    INFO.  */
 
-static char *
-bsd_uthread_extra_thread_info (struct target_ops *self,
-                              struct thread_info *info)
+const char *
+bsd_uthread_target::extra_thread_info (thread_info *info)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
-  CORE_ADDR addr = ptid_get_tid (info->ptid);
+  CORE_ADDR addr = info->ptid.tid ();
 
   if (addr != 0)
     {
@@ -487,57 +534,23 @@ bsd_uthread_extra_thread_info (struct target_ops *self,
   return NULL;
 }
 
-static char *
-bsd_uthread_pid_to_str (struct target_ops *ops, ptid_t ptid)
+std::string
+bsd_uthread_target::pid_to_str (ptid_t ptid)
 {
-  if (ptid_get_tid (ptid) != 0)
-    {
-      static char buf[64];
-
-      xsnprintf (buf, sizeof buf, "process %d, thread 0x%lx",
-                ptid_get_pid (ptid), ptid_get_tid (ptid));
-      return buf;
-    }
+  if (ptid.tid () != 0)
+    return string_printf ("process %d, thread 0x%lx",
+                         ptid.pid (), ptid.tid ());
 
   return normal_pid_to_str (ptid);
 }
 
-static struct target_ops *
-bsd_uthread_target (void)
-{
-  struct target_ops *t = XCNEW (struct target_ops);
-
-  t->to_shortname = "bsd-uthreads";
-  t->to_longname = "BSD user-level threads";
-  t->to_doc = "BSD user-level threads";
-  t->to_close = bsd_uthread_close;
-  t->to_mourn_inferior = bsd_uthread_mourn_inferior;
-  t->to_fetch_registers = bsd_uthread_fetch_registers;
-  t->to_store_registers = bsd_uthread_store_registers;
-  t->to_wait = bsd_uthread_wait;
-  t->to_resume = bsd_uthread_resume;
-  t->to_thread_alive = bsd_uthread_thread_alive;
-  t->to_find_new_threads = bsd_uthread_find_new_threads;
-  t->to_extra_thread_info = bsd_uthread_extra_thread_info;
-  t->to_pid_to_str = bsd_uthread_pid_to_str;
-  t->to_stratum = thread_stratum;
-  t->to_magic = OPS_MAGIC;
-  bsd_uthread_ops_hack = t;
-
-  return t;
-}
-
-/* Provide a prototype to silence -Wmissing-prototypes.  */
-extern initialize_file_ftype _initialize_bsd_uthread;
-
+void _initialize_bsd_uthread ();
 void
-_initialize_bsd_uthread (void)
+_initialize_bsd_uthread ()
 {
-  complete_target_initialization (bsd_uthread_target ());
-
   bsd_uthread_data = gdbarch_data_register_pre_init (bsd_uthread_init);
 
-  observer_attach_inferior_created (bsd_uthread_inferior_created);
-  observer_attach_solib_loaded (bsd_uthread_solib_loaded);
-  observer_attach_solib_unloaded (bsd_uthread_solib_unloaded);
+  gdb::observers::inferior_created.attach (bsd_uthread_inferior_created);
+  gdb::observers::solib_loaded.attach (bsd_uthread_solib_loaded);
+  gdb::observers::solib_unloaded.attach (bsd_uthread_solib_unloaded);
 }
This page took 0.032936 seconds and 4 git commands to generate.