gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / user-regs.c
index 8b4600d43386b5b1658bbde174ad2fe251158965..cb922313b0c855b616ba8228022f3245882f4548 100644 (file)
@@ -1,6 +1,6 @@
 /* User visible, per-frame registers, for GDB, the GNU debugger.
 
-   Copyright 2002 Free Software Foundation, Inc.
+   Copyright (C) 2002-2020 Free Software Foundation, Inc.
 
    Contributed by Red Hat.
 
@@ -8,7 +8,7 @@
 
    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., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "user-regs.h"
 #include "gdbtypes.h"
-#include "gdb_string.h"
-#include "gdb_assert.h"
 #include "frame.h"
+#include "arch-utils.h"
+#include "command.h"
+#include "cli/cli-cmds.h"
 
 /* A table of user registers.
 
    User registers have regnum's that live above of the range [0
-   .. NUM_REGS + NUM_PSEUDO_REGS) (which is controlled by the target).
+   .. gdbarch_num_regs + gdbarch_num_pseudo_regs)
+   (which is controlled by the target).
    The target should never see a user register's regnum value.
 
    Always append, never delete.  By doing this, the relative regnum
-   (offset from NUM_REGS + NUM_PSEUDO_REGS) assigned to each user
-   register never changes.  */
+   (offset from gdbarch_num_regs + gdbarch_num_pseudo_regs)
+    assigned to each user  register never changes.  */
 
 struct user_reg
 {
   const char *name;
-  struct value *(*read) (struct frame_info * frame);
+  /* Avoid the "read" symbol name as it conflicts with a preprocessor symbol
+     in the NetBSD header for Stack Smashing Protection, that wraps the read(2)
+     syscall.  */
+  struct value *(*xread) (struct frame_info * frame, const void *baton);
+  const void *baton;
   struct user_reg *next;
 };
 
-struct user_regs
+/* This structure is named gdb_user_regs instead of user_regs to avoid
+   conflicts with any "struct user_regs" in system headers.  For instance,
+   on ARM GNU/Linux native builds, nm-linux.h includes <signal.h> includes
+   <sys/ucontext.h> includes <sys/procfs.h> includes <sys/user.h>, which
+   declares "struct user_regs".  */
+
+struct gdb_user_regs
 {
   struct user_reg *first;
   struct user_reg **last;
 };
 
 static void
-append_user_reg (struct user_regs *regs, const char *name,
-                user_reg_read_ftype *read, struct user_reg *reg)
+append_user_reg (struct gdb_user_regs *regs, const char *name,
+                user_reg_read_ftype *xread, const void *baton,
+                struct user_reg *reg)
 {
   /* The caller is responsible for allocating memory needed to store
      the register.  By doing this, the function can operate on a
      register list stored in the common heap or a specific obstack.  */
   gdb_assert (reg != NULL);
   reg->name = name;
-  reg->read = read;
+  reg->xread = xread;
+  reg->baton = baton;
   reg->next = NULL;
   (*regs->last) = reg;
   regs->last = &(*regs->last)->next;
@@ -68,13 +80,16 @@ append_user_reg (struct user_regs *regs, const char *name,
 
 /* An array of the builtin user registers.  */
 
-static struct user_regs builtin_user_regs = { NULL, &builtin_user_regs.first };
+static struct gdb_user_regs builtin_user_regs = {
+  NULL, &builtin_user_regs.first
+};
 
 void
-user_reg_add_builtin (const char *name, user_reg_read_ftype *read)
+user_reg_add_builtin (const char *name, user_reg_read_ftype *xread,
+                     const void *baton)
 {
-  append_user_reg (&builtin_user_regs, name, read,
-                  XMALLOC (struct user_reg));
+  append_user_reg (&builtin_user_regs, name, xread, baton,
+                  XNEW (struct user_reg));
 }
 
 /* Per-architecture user registers.  Start with the builtin user
@@ -86,27 +101,31 @@ static void *
 user_regs_init (struct gdbarch *gdbarch)
 {
   struct user_reg *reg;
-  struct user_regs *regs = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct user_regs);
+  struct gdb_user_regs *regs 
+    = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct gdb_user_regs);
+
   regs->last = &regs->first;
   for (reg = builtin_user_regs.first; reg != NULL; reg = reg->next)
-    append_user_reg (regs, reg->name, reg->read,
+    append_user_reg (regs, reg->name, reg->xread, reg->baton,
                     GDBARCH_OBSTACK_ZALLOC (gdbarch, struct user_reg));
   return regs;
 }
 
 void
 user_reg_add (struct gdbarch *gdbarch, const char *name,
-                user_reg_read_ftype *read)
+             user_reg_read_ftype *xread, const void *baton)
 {
-  struct user_regs *regs = gdbarch_data (gdbarch, user_regs_data);
+  struct gdb_user_regs *regs
+    = (struct gdb_user_regs *) gdbarch_data (gdbarch, user_regs_data);
+
   if (regs == NULL)
     {
       /* ULGH, called during architecture initialization.  Patch
          things up.  */
-      regs = user_regs_init (gdbarch);
-      set_gdbarch_data (gdbarch, user_regs_data, regs);
+      regs = (struct gdb_user_regs *) user_regs_init (gdbarch);
+      deprecated_set_gdbarch_data (gdbarch, user_regs_data, regs);
     }
-  append_user_reg (regs, name, read,
+  append_user_reg (regs, name, xread, baton,
                   GDBARCH_OBSTACK_ZALLOC (gdbarch, struct user_reg));
 }
 
@@ -122,11 +141,12 @@ user_reg_map_name_to_regnum (struct gdbarch *gdbarch, const char *name,
      specific register override the user registers.  */
   {
     int i;
-    int maxregs = (gdbarch_num_regs (gdbarch)
-                  + gdbarch_num_pseudo_regs (gdbarch));
+    int maxregs = gdbarch_num_cooked_regs (gdbarch);
+
     for (i = 0; i < maxregs; i++)
       {
        const char *regname = gdbarch_register_name (gdbarch, i);
+
        if (regname != NULL && len == strlen (regname)
            && strncmp (regname, name, len) == 0)
          {
@@ -137,15 +157,17 @@ user_reg_map_name_to_regnum (struct gdbarch *gdbarch, const char *name,
 
   /* Search the user name space.  */
   {
-    struct user_regs *regs = gdbarch_data (gdbarch, user_regs_data);
+    struct gdb_user_regs *regs
+      = (struct gdb_user_regs *) gdbarch_data (gdbarch, user_regs_data);
     struct user_reg *reg;
     int nr;
+
     for (nr = 0, reg = regs->first; reg != NULL; reg = reg->next, nr++)
       {
        if ((len < 0 && strcmp (reg->name, name))
            || (len == strlen (reg->name)
                && strncmp (reg->name, name, len) == 0))
-         return NUM_REGS + NUM_PSEUDO_REGS + nr;
+         return gdbarch_num_cooked_regs (gdbarch) + nr;
       }
   }
 
@@ -155,8 +177,10 @@ user_reg_map_name_to_regnum (struct gdbarch *gdbarch, const char *name,
 static struct user_reg *
 usernum_to_user_reg (struct gdbarch *gdbarch, int usernum)
 {
-  struct user_regs *regs = gdbarch_data (gdbarch, user_regs_data);
+  struct gdb_user_regs *regs
+    = (struct gdb_user_regs *) gdbarch_data (gdbarch, user_regs_data);
   struct user_reg *reg;
+
   for (reg = regs->first; reg != NULL; reg = reg->next)
     {
       if (usernum == 0)
@@ -169,8 +193,8 @@ usernum_to_user_reg (struct gdbarch *gdbarch, int usernum)
 const char *
 user_reg_map_regnum_to_name (struct gdbarch *gdbarch, int regnum)
 {
-  int maxregs = (gdbarch_num_regs (gdbarch)
-                + gdbarch_num_pseudo_regs (gdbarch));
+  int maxregs = gdbarch_num_cooked_regs (gdbarch);
+
   if (regnum < 0)
     return NULL;
   else if (regnum < maxregs)
@@ -189,17 +213,37 @@ struct value *
 value_of_user_reg (int regnum, struct frame_info *frame)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
-  int maxregs = (gdbarch_num_regs (gdbarch)
-                + gdbarch_num_pseudo_regs (gdbarch));
+  int maxregs = gdbarch_num_cooked_regs (gdbarch);
   struct user_reg *reg = usernum_to_user_reg (gdbarch, regnum - maxregs);
+
   gdb_assert (reg != NULL);
-  return reg->read (frame);
+  return reg->xread (frame, reg->baton);
 }
 
-extern initialize_file_ftype _initialize_user_regs; /* -Wmissing-prototypes */
+static void
+maintenance_print_user_registers (const char *args, int from_tty)
+{
+  struct gdbarch *gdbarch = get_current_arch ();
+  struct gdb_user_regs *regs;
+  struct user_reg *reg;
+  int regnum;
+
+  regs = (struct gdb_user_regs *) gdbarch_data (gdbarch, user_regs_data);
+  regnum = gdbarch_num_cooked_regs (gdbarch);
+
+  fprintf_unfiltered (gdb_stdout, " %-11s %3s\n", "Name", "Nr");
+  for (reg = regs->first; reg != NULL; reg = reg->next, ++regnum)
+    fprintf_unfiltered (gdb_stdout, " %-11s %3d\n", reg->name, regnum);
+}
 
+void _initialize_user_regs ();
 void
-_initialize_user_regs (void)
+_initialize_user_regs ()
 {
-  user_regs_data = register_gdbarch_data (user_regs_init, NULL);
+  user_regs_data = gdbarch_data_register_post_init (user_regs_init);
+
+  add_cmd ("user-registers", class_maintenance,
+          maintenance_print_user_registers,
+          _("List the names of the current user registers."),
+          &maintenanceprintlist);
 }
This page took 0.027079 seconds and 4 git commands to generate.