i386: Align branches within a fixed boundary
[deliverable/binutils-gdb.git] / gdb / bsd-kvm.c
index 5e4c57d9c6deb818f59137fd2914df6a6ed5537e..21f978728da629ef3569f996af9cfe7aa12fe8f6 100644 (file)
@@ -1,12 +1,12 @@
 /* BSD Kernel Data Access Library (libkvm) interface.
 
-   Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2004-2019 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
+#define _KMEMUSER
 #include "defs.h"
 #include "cli/cli-cmds.h"
 #include "command.h"
 #include "frame.h"
 #include "regcache.h"
 #include "target.h"
+#include "process-stratum-target.h"
 #include "value.h"
-#include "gdbcore.h"           /* for get_exec_file */
+#include "gdbcore.h"
+#include "inferior.h"          /* for get_exec_file */
+#include "gdbthread.h"
 
-#include "gdb_assert.h"
 #include <fcntl.h>
 #include <kvm.h>
 #ifdef HAVE_NLIST_H
@@ -38,7 +39,9 @@
 #include "readline/readline.h"
 #include <sys/param.h>
 #include <sys/proc.h>
+#ifdef HAVE_SYS_USER_H
 #include <sys/user.h>
+#endif
 
 #include "bsd-kvm.h"
 
@@ -55,23 +58,65 @@ static struct pcb *bsd_kvm_paddr;
    register state from PCB and supplies it to REGCACHE.  */
 static int (*bsd_kvm_supply_pcb)(struct regcache *regcache, struct pcb *pcb);
 
+/* This is the ptid we use while we're connected to kvm.  The kvm
+   target currently doesn't export any view of the running processes,
+   so this represents the kernel task.  */
+static ptid_t bsd_kvm_ptid;
+
+/* The libkvm target.  */
+
+static const target_info bsd_kvm_target_info = {
+  "kvm",
+  N_("Kernel memory interface"),
+  N_("Use a kernel virtual memory image as a target.\n\
+Optionally specify the filename of a core dump.")
+};
+
+class bsd_kvm_target final : public process_stratum_target
+{
+public:
+  bsd_kvm_target () = default;
+
+  const target_info &info () const override
+  { return bsd_kvm_target_info; }
+
+  void close () override;
+
+  void fetch_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 files_info () override;
+  bool thread_alive (ptid_t ptid) override;
+  std::string pid_to_str (ptid_t) override;
+
+  bool has_memory () override { return true; }
+  bool has_stack () override { return true; }
+  bool has_registers () override { return true; }
+};
+
 /* Target ops for libkvm interface.  */
-static struct target_ops bsd_kvm_ops;
+static bsd_kvm_target bsd_kvm_ops;
 
 static void
-bsd_kvm_open (char *filename, int from_tty)
+bsd_kvm_target_open (const char *arg, int from_tty)
 {
   char errbuf[_POSIX2_LINE_MAX];
   char *execfile = NULL;
   kvm_t *temp_kd;
+  char *filename = NULL;
 
   target_preopen (from_tty);
 
-  if (filename)
+  if (arg)
     {
       char *temp;
 
-      filename = tilde_expand (filename);
+      filename = tilde_expand (arg);
       if (filename[0] != '/')
        {
          temp = concat (current_directory, "/", filename, (char *)NULL);
@@ -91,14 +136,17 @@ bsd_kvm_open (char *filename, int from_tty)
   core_kd = temp_kd;
   push_target (&bsd_kvm_ops);
 
+  add_thread_silent (bsd_kvm_ptid);
+  inferior_ptid = bsd_kvm_ptid;
+
   target_fetch_registers (get_current_regcache (), -1);
 
   reinit_frame_cache ();
-  print_stack_frame (get_selected_frame (NULL), -1, 1);
+  print_stack_frame (get_selected_frame (NULL), 0, SRC_AND_LOC, 1);
 }
 
-static void
-bsd_kvm_close (int quitting)
+void
+bsd_kvm_target::close ()
 {
   if (core_kd)
     {
@@ -106,6 +154,9 @@ bsd_kvm_close (int quitting)
        warning (("%s"), kvm_geterr(core_kd));
       core_kd = NULL;
     }
+
+  inferior_ptid = null_ptid;
+  discard_all_inferiors ();
 }
 
 static LONGEST
@@ -121,24 +172,36 @@ bsd_kvm_xfer_memory (CORE_ADDR addr, ULONGEST len,
   return nbytes;
 }
 
-static LONGEST
-bsd_kvm_xfer_partial (struct target_ops *ops, enum target_object object,
-                     const char *annex, gdb_byte *readbuf,
-                     const gdb_byte *writebuf,
-                     ULONGEST offset, LONGEST len)
+enum target_xfer_status
+bsd_kvm_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)
     {
     case TARGET_OBJECT_MEMORY:
-      return bsd_kvm_xfer_memory (offset, len, readbuf, writebuf);
+      {
+       LONGEST ret = bsd_kvm_xfer_memory (offset, len, readbuf, writebuf);
+
+       if (ret < 0)
+         return TARGET_XFER_E_IO;
+       else if (ret == 0)
+         return TARGET_XFER_EOF;
+       else
+         {
+           *xfered_len = (ULONGEST) ret;
+           return TARGET_XFER_OK;
+         }
+      }
 
     default:
-      return -1;
+      return TARGET_XFER_E_IO;
     }
 }
 
-static void
-bsd_kvm_files_info (struct target_ops *ops)
+void
+bsd_kvm_target::files_info ()
 {
   if (bsd_kvm_corefile && strcmp (bsd_kvm_corefile, _PATH_MEM) != 0)
     printf_filtered (_("\tUsing the kernel crash dump %s.\n"),
@@ -161,8 +224,8 @@ bsd_kvm_fetch_pcb (struct regcache *regcache, struct pcb *paddr)
   return bsd_kvm_supply_pcb (regcache, &pcb);
 }
 
-static void
-bsd_kvm_fetch_registers (struct regcache *regcache, int regnum)
+void
+bsd_kvm_target::fetch_registers (struct regcache *regcache, int regnum)
 {
   struct nlist nl[2];
 
@@ -182,7 +245,7 @@ bsd_kvm_fetch_registers (struct regcache *regcache, int regnum)
 
   if (nl[0].n_value != 0)
     {
-      /* Found dumppcb. If it contains a valid context, return
+      /* Found dumppcb.  If it contains a valid context, return
         immediately.  */
       if (bsd_kvm_fetch_pcb (regcache, (struct pcb *) nl[0].n_value))
        return;
@@ -236,7 +299,7 @@ bsd_kvm_fetch_registers (struct regcache *regcache, int regnum)
     }
 #endif
 
-  /* i18n: PCB == "Process Control Block" */
+  /* i18n: PCB == "Process Control Block" */
   error (_("Cannot find a valid PCB"));
 }
 \f
@@ -245,7 +308,7 @@ bsd_kvm_fetch_registers (struct regcache *regcache, int regnum)
 struct cmd_list_element *bsd_kvm_cmdlist;
 
 static void
-bsd_kvm_cmd (char *arg, int fromtty)
+bsd_kvm_cmd (const char *arg, int fromtty)
 {
   /* ??? Should this become an alias for "target kvm"?  */
 }
@@ -253,7 +316,7 @@ bsd_kvm_cmd (char *arg, int fromtty)
 #ifndef HAVE_STRUCT_THREAD_TD_PCB
 
 static void
-bsd_kvm_proc_cmd (char *arg, int fromtty)
+bsd_kvm_proc_cmd (const char *arg, int fromtty)
 {
   CORE_ADDR addr;
 
@@ -276,16 +339,16 @@ bsd_kvm_proc_cmd (char *arg, int fromtty)
   target_fetch_registers (get_current_regcache (), -1);
 
   reinit_frame_cache ();
-  print_stack_frame (get_selected_frame (NULL), -1, 1);
+  print_stack_frame (get_selected_frame (NULL), 0, SRC_AND_LOC, 1);
 }
 
 #endif
 
 static void
-bsd_kvm_pcb_cmd (char *arg, int fromtty)
+bsd_kvm_pcb_cmd (const char *arg, int fromtty)
 {
   if (arg == NULL)
-    /* i18n: PCB == "Process Control Block" */
+    /* i18n: PCB == "Process Control Block" */
     error_no_arg (_("pcb address"));
 
   if (core_kd == NULL)
@@ -296,7 +359,19 @@ bsd_kvm_pcb_cmd (char *arg, int fromtty)
   target_fetch_registers (get_current_regcache (), -1);
 
   reinit_frame_cache ();
-  print_stack_frame (get_selected_frame (NULL), -1, 1);
+  print_stack_frame (get_selected_frame (NULL), 0, SRC_AND_LOC, 1);
+}
+
+bool
+bsd_kvm_target::thread_alive (ptid_t ptid)
+{
+  return true;
+}
+
+std::string
+bsd_kvm_target::pid_to_str (ptid_t ptid)
+{
+  return "<kvm>";
 }
 
 /* Add the libkvm interface to the list of all possible targets and
@@ -309,22 +384,7 @@ bsd_kvm_add_target (int (*supply_pcb)(struct regcache *, struct pcb *))
   gdb_assert (bsd_kvm_supply_pcb == NULL);
   bsd_kvm_supply_pcb = supply_pcb;
 
-  bsd_kvm_ops.to_shortname = "kvm";
-  bsd_kvm_ops.to_longname = _("Kernel memory interface");
-  bsd_kvm_ops.to_doc = _("Use a kernel virtual memory image as a target.\n\
-Optionally specify the filename of a core dump.");
-  bsd_kvm_ops.to_open = bsd_kvm_open;
-  bsd_kvm_ops.to_close = bsd_kvm_close;
-  bsd_kvm_ops.to_fetch_registers = bsd_kvm_fetch_registers;
-  bsd_kvm_ops.to_xfer_partial = bsd_kvm_xfer_partial;
-  bsd_kvm_ops.to_files_info = bsd_kvm_files_info;
-  bsd_kvm_ops.to_stratum = process_stratum;
-  bsd_kvm_ops.to_has_memory = 1;
-  bsd_kvm_ops.to_has_stack = 1;
-  bsd_kvm_ops.to_has_registers = 1;
-  bsd_kvm_ops.to_magic = OPS_MAGIC;
-
-  add_target (&bsd_kvm_ops);
+  add_target (bsd_kvm_target_info, bsd_kvm_target_open);
   
   add_prefix_cmd ("kvm", class_obscure, bsd_kvm_cmd, _("\
 Generic command for manipulating the kernel memory interface."),
@@ -335,6 +395,22 @@ Generic command for manipulating the kernel memory interface."),
           _("Set current context from proc address"), &bsd_kvm_cmdlist);
 #endif
   add_cmd ("pcb", class_obscure, bsd_kvm_pcb_cmd,
-          /* i18n: PCB == "Process Control Block" */
+          /* i18n: PCB == "Process Control Block" */
           _("Set current context from pcb address"), &bsd_kvm_cmdlist);
+
+  /* Some notes on the ptid usage on this target.
+
+     The pid field represents the kvm inferior instance.  Currently,
+     we don't support multiple kvm inferiors, but we start at 1
+     anyway.  The lwp field is set to != 0, in case the core wants to
+     refer to the whole kvm inferior with ptid(1,0,0).
+
+     If kvm is made to export running processes as gdb threads,
+     the following form can be used:
+     ptid (1, 1, 0) -> kvm inferior 1, in kernel
+     ptid (1, 1, 1) -> kvm inferior 1, process 1
+     ptid (1, 1, 2) -> kvm inferior 1, process 2
+     ptid (1, 1, n) -> kvm inferior 1, process n  */
+
+  bsd_kvm_ptid = ptid_t (1, 1, 0);
 }
This page took 0.027536 seconds and 4 git commands to generate.