This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[commit] unbreak gdbserver on uclinux


Hi all,

I've checked in the attached, which unbreaks gdbserver on uclinux.
Approved offline by Daniel.

With the introduction of biarch support in gdbserver, the register
cache size initialization was defered into after the first wait
in linux-low.c:

linux_wait_for_process:

  /* Architecture-specific setup after inferior is running.
     This needs to happen after we have attached to the inferior
     and it is stopped for the first time, but before we access
     any inferior registers.  */
  if (new_inferior)
    {
      the_low_target.arch_setup ();
#ifdef HAVE_LINUX_REGSETS
      memset (disabled_regsets, 0, num_regsets);
#endif
      new_inferior = 0;
    }


But, before that is reached, we already added the main thread to
the thread list with add_thread in linux_create_inferior, which tries
to set up a register cache for the new thread.  At this point, the
register cache size hasn't been setup yet, so register_bytes is
still 0:

 void *
 new_register_cache (void)
 {
   struct inferior_regcache_data *regcache;

   regcache = malloc (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_valid = 0;

   return regcache;
 }

Later on, when the architecture is initialized, we'll fill in a real
register cache for all threads (set_register_cache/realloc_register_cache).

The issue is, that on linux/glibc, calloc(1, 0) returns != NULL above, so
we'd not trip on the fatal call; but, on uclibc, *alloc(0)
returns NULL, hence, gdbserver would refuse to start.

The attached patch fixes it and it should be safe.  It is not valid
to access the register cache until the architecture is initialized, so,
if we see a NULL dereference due to this, that's itself another bug.

I ran the testsuite locally against a x86_64-unknown-linux-gnu gdbserver,
and saw no regressions.

-- 
Pedro Alves
2008-09-08  Pedro Alves  <pedro@codesourcery.com>

	gdb/gdbserver/
	* regcache.c (new_register_cache): Return NULL if the register
	cache size isn't known yet.
	(free_register_cache): Avoid dereferencing a NULL regcache.

---
 gdb/gdbserver/regcache.c |   10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

Index: src/gdb/gdbserver/regcache.c
===================================================================
--- src.orig/gdb/gdbserver/regcache.c	2008-09-04 14:38:59.000000000 +0100
+++ src/gdb/gdbserver/regcache.c	2008-09-04 15:04:32.000000000 +0100
@@ -91,6 +91,9 @@ new_register_cache (void)
 {
   struct inferior_regcache_data *regcache;
 
+  if (register_bytes == 0)
+    return NULL; /* The architecture hasn't been initialized yet.  */
+
   regcache = malloc (sizeof (*regcache));
 
   /* Make sure to zero-initialize the register cache when it is created,
@@ -111,8 +114,11 @@ 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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]