Fix auxv data parsing on 64-bit solaris
authorVladimir Prus <vladimir@codesourcery.com>
Sun, 4 May 2008 09:28:27 +0000 (09:28 +0000)
committerVladimir Prus <vladimir@codesourcery.com>
Sun, 4 May 2008 09:28:27 +0000 (09:28 +0000)
* 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.

gdb/ChangeLog
gdb/auxv.c
gdb/procfs.c
gdb/target.h

index 5a002a79b1765cda749eb83cefbb757b3661136b..a41bf8741cd33a0a07921c9a00c3d880ea9f2b65 100644 (file)
@@ -1,3 +1,14 @@
+2008-05-04  Vladimir Prus  <vladimir@codesourcery.com>
+
+       * 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-05-03  Adam Nemet  <anemet@caviumnetworks.com>
 
        * symfile.c (add_symbol_file_command):  Use paddress rather than
index d1d93e78400cdc52905de556843af55fd488d9a8..292a0d6fa717e853c5d3365c537919b82bc901c7 100644 (file)
@@ -79,7 +79,7 @@ procfs_xfer_auxv (struct target_ops *ops,
    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,
+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);
@@ -100,6 +100,22 @@ target_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
   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 f40b3883b4c64ebff767d3a188e8c6a2dbed5bfd..da9fd4cbbe4d63de99549d5984c30eea7aacc247 100644 (file)
@@ -152,6 +152,35 @@ static int procfs_can_use_hw_breakpoint (int, int, int);
 
 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 @@ init_procfs_ops (void)
   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 3b424ba585f749f5b2b421d1efd04f1544d010e0..8822a4061b1eac2193de256296d17d6d6ff2ed84 100644 (file)
@@ -498,6 +498,13 @@ struct target_ops
        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?
      */