From c47ffbe3b159da69fcc66cb7ad3a69077641b384 Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Sun, 4 May 2008 09:28:27 +0000 Subject: [PATCH] Fix auxv data parsing on 64-bit solaris * 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 | 11 +++++++++++ gdb/auxv.c | 18 +++++++++++++++++- gdb/procfs.c | 34 ++++++++++++++++++++++++++++++++++ gdb/target.h | 7 +++++++ 4 files changed, 69 insertions(+), 1 deletion(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 5a002a7..a41bf87 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2008-05-04 Vladimir Prus + + * 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 * symfile.c (add_symbol_file_command): Use paddress rather than diff --git a/gdb/auxv.c b/gdb/auxv.c index d1d93e7..292a0d6 100644 --- a/gdb/auxv.c +++ b/gdb/auxv.c @@ -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 diff --git a/gdb/procfs.c b/gdb/procfs.c index f40b388..da9fd4c 100644 --- a/gdb/procfs.c +++ b/gdb/procfs.c @@ -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; } diff --git a/gdb/target.h b/gdb/target.h index 3b424ba..8822a40 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -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? */ -- 2.7.4