* exec.c: #include "arch-utils.h"
[deliverable/binutils-gdb.git] / gdb / user-regs.c
index 3d60b2f90f6815445677fc4c8eee055fa18b2f17..fb04b3be89b8a722bb7b927be6a2b155f0771162 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, 2003, 2004, 2007, 2008 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,
@@ -17,9 +17,7 @@
    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"
 /* 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);
+  struct value *(*read) (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 *user;
-  int nr;
+  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)
+append_user_reg (struct gdb_user_regs *regs, const char *name,
+                user_reg_read_ftype *read, const void *baton,
+                struct user_reg *reg)
 {
-  regs->nr++;
-  regs->user = xrealloc (regs->user,
-                           regs->nr * sizeof (struct user_reg));
-  regs->user[regs->nr - 1].name = name;
-  regs->user[regs->nr - 1].read = read;
+  /* 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->baton = baton;
+  reg->next = NULL;
+  (*regs->last) = reg;
+  regs->last = &(*regs->last)->next;
 }
 
 /* An array of the builtin user registers.  */
 
-static struct user_regs builtin_user_regs;
+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 *read,
+                     const void *baton)
 {
-  append_user_reg (&builtin_user_regs, name, read);
+  append_user_reg (&builtin_user_regs, name, read, baton,
+                  XMALLOC (struct user_reg));
 }
 
 /* Per-architecture user registers.  Start with the builtin user
@@ -79,36 +94,29 @@ static struct gdbarch_data *user_regs_data;
 static void *
 user_regs_init (struct gdbarch *gdbarch)
 {
-  int i;
-  struct user_regs *regs = XMALLOC (struct user_regs);
-  memset (regs, 0, sizeof (struct user_regs));
-  for (i = 0; i < builtin_user_regs.nr; i++)
-    append_user_reg (regs, builtin_user_regs.user[i].name,
-                    builtin_user_regs.user[i].read);
+  struct user_reg *reg;
+  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, reg->baton,
+                    GDBARCH_OBSTACK_ZALLOC (gdbarch, struct user_reg));
   return regs;
 }
 
-static void
-user_regs_free (struct gdbarch *gdbarch, void *data)
-{
-  struct user_regs *regs = data;
-  xfree (regs->user);
-  xfree (regs);
-}
-
 void
 user_reg_add (struct gdbarch *gdbarch, const char *name,
-                user_reg_read_ftype *read)
+             user_reg_read_ftype *read, const void *baton)
 {
-  struct user_regs *regs = gdbarch_data (gdbarch, user_regs_data);
+  struct gdb_user_regs *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);
+      deprecated_set_gdbarch_data (gdbarch, user_regs_data, regs);
     }
-  append_user_reg (regs, name, read);
+  append_user_reg (regs, name, read, baton,
+                  GDBARCH_OBSTACK_ZALLOC (gdbarch, struct user_reg));
 }
 
 int
@@ -138,43 +146,64 @@ 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);
-    int reg;
-    for (reg = 0; reg < regs->nr; reg++)
+    struct gdb_user_regs *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 (regs->user[reg].name, name))
-           || (len == strlen (regs->user[reg].name)
-               && strncmp (regs->user[reg].name, name, len) == 0))
-         return NUM_REGS + NUM_PSEUDO_REGS + reg;
+       if ((len < 0 && strcmp (reg->name, name))
+           || (len == strlen (reg->name)
+               && strncmp (reg->name, name, len) == 0))
+         return gdbarch_num_regs (gdbarch)
+                + gdbarch_num_pseudo_regs (gdbarch) + nr;
       }
   }
 
   return -1;
 }
 
+static struct user_reg *
+usernum_to_user_reg (struct gdbarch *gdbarch, int usernum)
+{
+  struct gdb_user_regs *regs = gdbarch_data (gdbarch, user_regs_data);
+  struct user_reg *reg;
+  for (reg = regs->first; reg != NULL; reg = reg->next)
+    {
+      if (usernum == 0)
+       return reg;
+      usernum--;
+    }
+  return NULL;
+}
+
 const char *
 user_reg_map_regnum_to_name (struct gdbarch *gdbarch, int regnum)
 {
   int maxregs = (gdbarch_num_regs (gdbarch)
                 + gdbarch_num_pseudo_regs (gdbarch));
-  struct user_regs *regs = gdbarch_data (gdbarch, user_regs_data);
   if (regnum < 0)
     return NULL;
-  if (regnum < maxregs)
+  else if (regnum < maxregs)
     return gdbarch_register_name (gdbarch, regnum);
-  if (regnum < (maxregs + regs->nr))
-    return regs->user[regnum - maxregs].name;
-  return NULL;
+  else
+    {
+      struct user_reg *reg = usernum_to_user_reg (gdbarch, regnum - maxregs);
+      if (reg == NULL)
+       return NULL;
+      else
+       return reg->name;
+    }
 }
 
 struct value *
 value_of_user_reg (int regnum, struct frame_info *frame)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
-  struct user_regs *regs = gdbarch_data (gdbarch, user_regs_data);
-  int reg = regnum - (NUM_REGS + NUM_PSEUDO_REGS);
-  gdb_assert (reg >= 0 && reg < regs->nr);
-  return regs->user[reg].read (frame);
+  int maxregs = (gdbarch_num_regs (gdbarch)
+                + gdbarch_num_pseudo_regs (gdbarch));
+  struct user_reg *reg = usernum_to_user_reg (gdbarch, regnum - maxregs);
+  gdb_assert (reg != NULL);
+  return reg->read (frame, reg->baton);
 }
 
 extern initialize_file_ftype _initialize_user_regs; /* -Wmissing-prototypes */
@@ -182,5 +211,5 @@ extern initialize_file_ftype _initialize_user_regs; /* -Wmissing-prototypes */
 void
 _initialize_user_regs (void)
 {
-  user_regs_data = register_gdbarch_data (user_regs_init, user_regs_free);
+  user_regs_data = gdbarch_data_register_post_init (user_regs_init);
 }
This page took 0.03955 seconds and 4 git commands to generate.