* linux-low.c (usr_fetch_inferior_registers): Remove check for regno 0.
[binutils-gdb.git] / gdb / gdbserver / regcache.c
index f1d0fe51f14efe838b67fa953153576bb237f108..c61a6052420e0c93f42f9f64696b8c9e1a435dfb 100644 (file)
@@ -1,12 +1,12 @@
 /* Register support routines for the remote server for GDB.
-   Copyright 2001, 2002, 2004, 2005
+   Copyright (C) 2001, 2002, 2004, 2005, 2007, 2008, 2009
    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,
@@ -15,9 +15,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 "server.h"
 #include "regdef.h"
@@ -55,7 +53,7 @@ get_regcache (struct thread_info *inf, int fetch)
   /* FIXME - fetch registers for INF */
   if (fetch && regcache->registers_valid == 0)
     {
-      fetch_inferior_registers (0);
+      fetch_inferior_registers (-1);
       regcache->registers_valid = 1;
     }
 
@@ -88,25 +86,20 @@ regcache_invalidate ()
   for_each_inferior (&all_threads, regcache_invalidate_one);
 }
 
-int
-registers_length (void)
-{
-  return 2 * register_bytes;
-}
-
 void *
 new_register_cache (void)
 {
   struct inferior_regcache_data *regcache;
 
-  regcache = malloc (sizeof (*regcache));
+  if (register_bytes == 0)
+    return NULL; /* The architecture hasn't been initialized yet.  */
+
+  regcache = xmalloc (sizeof (*regcache));
 
   /* Make sure to zero-initialize the register cache when it is created,
      in case there are registers the target never fetches.  This way they'll
      read as zero instead of garbage.  */
-  regcache->registers = calloc (1, register_bytes);
-  if (regcache->registers == NULL)
-    fatal ("Could not allocate register cache.");
+  regcache->registers = xcalloc (1, register_bytes);
 
   regcache->registers_valid = 0;
 
@@ -119,15 +112,27 @@ free_register_cache (void *regcache_p)
   struct inferior_regcache_data *regcache
     = (struct inferior_regcache_data *) regcache_p;
 
-  free (regcache->registers);
-  free (regcache);
+  if (regcache)
+    {
+      free (regcache->registers);
+      free (regcache);
+    }
+}
+
+static void
+realloc_register_cache (struct inferior_list_entry *thread_p)
+{
+  struct thread_info *thread = (struct thread_info *) thread_p;
+
+  free_register_cache (inferior_regcache_data (thread));
+  set_inferior_regcache_data (thread, new_register_cache ());
 }
 
 void
 set_register_cache (struct reg *regs, int n)
 {
   int offset, i;
-  
+
   reg_defs = regs;
   num_registers = n;
 
@@ -139,6 +144,13 @@ set_register_cache (struct reg *regs, int n)
     }
 
   register_bytes = offset / 8;
+
+  /* Make sure PBUFSIZ is large enough to hold a full register packet.  */
+  if (2 * register_bytes + 32 > PBUFSIZ)
+    fatal ("Register packet size exceeds PBUFSIZ.");
+
+  /* Re-allocate all pre-existing register caches.  */
+  for_each_inferior (&all_threads, realloc_register_cache);
 }
 
 void
@@ -157,7 +169,8 @@ registers_from_string (char *buf)
 
   if (len != register_bytes * 2)
     {
-      warning ("Wrong sized register packet (expected %d bytes, got %d)", 2*register_bytes, len);
+      warning ("Wrong sized register packet (expected %d bytes, got %d)",
+              2*register_bytes, len);
       if (len > register_bytes * 2)
        len = register_bytes * 2;
     }