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]

Fix auxv parsing on Solaris


Presently, gdb does not properly parse auxv data on Solaris when GDB is
built as 64-bit binary, and the program been debugger is 32-bit. On Solaris,
32-or-64-bitness of the application accessing /proc/*/auxv determines format
of the data read, while GDB presently only uses size of target types during
parsing. 

This issue causes quite some breakage in our testing, because we use AT_BASE
item of auxv data to find linker's base address, and if we misparse auxv we
end up recognizing regular program code as part of dynamic linker, and stepping
out of that code automatically.

The ideal solution is to add a new target method for parsing auxv data, and 
then make sparc-sol2-nat.c define new target ops with that method defined. That,
however, is a little bit tricky, because right now, Solaris uses procfs_target_ops
for running, and procfs.c is not quite written with the expectation that any target
will want to extend it. For that reason, I've made procfs.c itself register new
target method if we sees we're on solaris and compiled as 64-bit application.

OK?

- Volodya

        * target.h (struct target_ops): New field to_auxv_parse.
        * auxv.c (default_auxv_parse): New, renamed from previous
        target_auxv_parse.
        (target_auxv_parse): Try to call target method.  Fallback to
        default_auxv_parse if not found.
        * procfs.c (procfs_auxv_parse): New.
        (init_procfs_ops): On Solaris, in 64-bit mode, install
        procfs_auxv_parse.

Index: gdb/target.h
===================================================================
--- gdb/target.h	(revision 202921)
+++ gdb/target.h	(working copy)
@@ -505,6 +505,13 @@
        was available.  */
     const struct target_desc *(*to_read_description) (struct target_ops *ops);
 
+    /* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
+       Return 0 if *READPTR is already at the end of the buffer.
+       Return -1 if there is insufficient buffer for a whole entry.
+       Return 1 if an entry was read into *TYPEP and *VALP.  */
+    int (*to_auxv_parse) (struct target_ops *ops, gdb_byte **readptr,
+			  gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp);
+
     int to_magic;
     /* Need sub-structure for target machine related rather than comm related?
      */
Index: gdb/auxv.c
===================================================================
--- gdb/auxv.c	(revision 202921)
+++ gdb/auxv.c	(working copy)
@@ -79,8 +79,8 @@
    Return -1 if there is insufficient buffer for a whole entry.
    Return 1 if an entry was read into *TYPEP and *VALP.  */
 int
-target_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
-		   gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
+default_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
+		    gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
 {
   const int sizeof_auxv_field = TYPE_LENGTH (builtin_type_void_data_ptr);
   gdb_byte *ptr = *readptr;
@@ -100,6 +100,22 @@
   return 1;
 }
 
+/* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
+   Return 0 if *READPTR is already at the end of the buffer.
+   Return -1 if there is insufficient buffer for a whole entry.
+   Return 1 if an entry was read into *TYPEP and *VALP.  */
+int
+target_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
+		   gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
+{
+  struct target_ops *t;
+  for (t = ops; t != NULL; t = t->beneath)
+    if (t->to_auxv_parse != NULL)
+      return t->to_auxv_parse (t, readptr, endptr, typep, valp);
+  
+  return default_auxv_parse (ops, readptr, endptr, typep, valp);
+}
+
 /* Extract the auxiliary vector entry with a_type matching MATCH.
    Return zero if no such entry was found, or -1 if there was
    an error getting the information.  On success, return 1 after
Index: gdb/procfs.c
===================================================================
--- gdb/procfs.c	(revision 202921)
+++ gdb/procfs.c	(working copy)
@@ -152,6 +152,35 @@
 
 struct target_ops procfs_ops;		/* the target vector */
 
+#if defined (PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64)
+/* When GDB is built as 64-bit application on Solaris, the auxv data is
+   presented in 64-bit format.  We need to provide a custom parser to handle 
+   that.  */
+static int
+procfs_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
+		   gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
+{
+  const int pointer_size = TYPE_LENGTH (builtin_type_void_data_ptr);
+  gdb_byte *ptr = *readptr;
+
+  if (endptr == ptr)
+    return 0;
+  
+  if (endptr - ptr < 8 * 2)
+    return -1;
+
+  *typep = extract_unsigned_integer (ptr, 4);
+  ptr += 8;
+  /* The size of data is always 64-bit.  If the application is 32-bit,
+     it will be zero extended, as expected.  */
+  *valp = extract_unsigned_integer (ptr, 8);
+  ptr += 8;
+
+  *readptr = ptr;
+  return 1;
+}
+#endif
+
 static void
 init_procfs_ops (void)
 {
@@ -200,6 +229,11 @@
   procfs_ops.to_find_memory_regions = proc_find_memory_regions;
   procfs_ops.to_make_corefile_notes = procfs_make_note_section;
   procfs_ops.to_can_use_hw_breakpoint = procfs_can_use_hw_breakpoint;
+
+#if defined(PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64)
+  procfs_ops.to_auxv_parse = procfs_auxv_parse;
+#endif
+
   procfs_ops.to_magic               = OPS_MAGIC;
 }
 
Index: ChangeLog.csl
===================================================================
--- ChangeLog.csl	(revision 202921)
+++ ChangeLog.csl	(working copy)
@@ -1,3 +1,16 @@
+2008-04-10  Vladimir Prus  <vladimir@codesourcery.com>
+
+	Issue #2775.
+	gdb/
+	* target.h (struct target_ops): New field to_auxv_parse.
+	* auxv.c (default_auxv_parse): New, renamed from previous
+	target_auxv_parse.
+	(target_auxv_parse): Try to call target method.  Fallback to
+	default_auxv_parse if not found.
+	* procfs.c (procfs_auxv_parse): New.
+	(init_procfs_ops): On Solaris, in 64-bit mode, install
+	procfs_auxv_parse.	
+	
 2008-03-28  Daniel Jacobowitz  <dan@codesourcery.com>
 
 	Issue #2696

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