[RFC,1/3] Fix parsing of auxiliary vector on Solaris.

Message ID MWHPR1001MB2224F174213907E33585FEDEFF139@MWHPR1001MB2224.namprd10.prod.outlook.com
State New
Headers show
Series
  • [RFC,1/3] Fix parsing of auxiliary vector on Solaris.
Related show

Commit Message

Simon Marchi via Gdb-patches July 14, 2021, 1:16 p.m.
From b9986bb324f03a16693f01ae0bbdf315cbe9811c Mon Sep 17 00:00:00 2001
From: Libor Bukata <libor.bukata@oracle.com>
Date: Wed, 14 Jul 2021 09:43:27 +0200
Subject: [PATCH 1/3] [gdb] Fix parsing of auxiliary vector on Solaris.

GDB fails to parse auxv vector on Solaris:
$ echo 'int main(void) { return *(volatile int *)0=0; }' | \
  gcc -o segv -Og -g -fPIE -pie -x c -
$ ./segv
Segmentation Fault (core dumped)
$ gdb -batch ./segv core -ex 'info auxv'
...
Core was generated by `./segv'.
Program terminated with signal SIGSEGV, Segmentation fault.
0  0xffffffff7f400f04 in ?? ()
...
8650064134145  ???                 0xffffffff7ffff9f4
8624294339865  ???                 0xffffffff7ffff9f9
12884901888    ???                 0xffffffff7f400040
19327352832    ???                 0x38
23622254592    ???                 0x5
38654705664    ???                 0xffffffff7f400ca0
8658654068736  ???                 0xffffffff7f344000
30064771072    ???                 0xffffffff7f100000
34359738368    ???                 0xb00
25769803776    ???                 0x2000
8662949036032  ???                 0x102
8628589297664  ???                 0x3ff68df7
8688718839808  ???                 0xc01fe
8693013807104  ???                 0x0
0              AT_NULL             End of vector     0x0

Backtrace stopped prematurely because AT_ENTRY value was
not correctly parsed from auxiliary vector. The reason
why GDB failed to parse Solaris's auxiliary vector is
that auxiliary type has 4 bytes (int type) on Solaris.

Tested on Solaris x86_64/sparcv9 and Linux x86_64.

gdb/ChangeLog:

2021-07-12 Libor Bukata <libor.bukata@oracle.com>

  * gdb/auxv.c (generic_auxv_parse): Read only 4 bytes as an
  auxiliary type on Solaris.
  (default_print_auxv_entry): Added AT_SUN_CAP_HW3 tag desc.
  * include/elf/common.h (AT_SUN_CAP_HW3): Added a new type.
---
 gdb/auxv.c           | 11 +++++++++++
 include/elf/common.h |  1 +
 2 files changed, 12 insertions(+)

Comments

Simon Marchi via Gdb-patches July 15, 2021, 12:45 a.m. | #1
On 2021-07-14 9:16 a.m., Libor Bukata via Gdb-patches wrote:
> From b9986bb324f03a16693f01ae0bbdf315cbe9811c Mon Sep 17 00:00:00 2001

> From: Libor Bukata <libor.bukata@oracle.com>

> Date: Wed, 14 Jul 2021 09:43:27 +0200

> Subject: [PATCH 1/3] [gdb] Fix parsing of auxiliary vector on Solaris.

> 

> GDB fails to parse auxv vector on Solaris:

> $ echo 'int main(void) { return *(volatile int *)0=0; }' | \

>   gcc -o segv -Og -g -fPIE -pie -x c -

> $ ./segv

> Segmentation Fault (core dumped)

> $ gdb -batch ./segv core -ex 'info auxv'

> ...

> Core was generated by `./segv'.

> Program terminated with signal SIGSEGV, Segmentation fault.

> 0  0xffffffff7f400f04 in ?? ()

> ...

> 8650064134145  ???                 0xffffffff7ffff9f4

> 8624294339865  ???                 0xffffffff7ffff9f9

> 12884901888    ???                 0xffffffff7f400040

> 19327352832    ???                 0x38

> 23622254592    ???                 0x5

> 38654705664    ???                 0xffffffff7f400ca0

> 8658654068736  ???                 0xffffffff7f344000

> 30064771072    ???                 0xffffffff7f100000

> 34359738368    ???                 0xb00

> 25769803776    ???                 0x2000

> 8662949036032  ???                 0x102

> 8628589297664  ???                 0x3ff68df7

> 8688718839808  ???                 0xc01fe

> 8693013807104  ???                 0x0

> 0              AT_NULL             End of vector     0x0

> 

> Backtrace stopped prematurely because AT_ENTRY value was

> not correctly parsed from auxiliary vector. The reason

> why GDB failed to parse Solaris's auxiliary vector is

> that auxiliary type has 4 bytes (int type) on Solaris.

> 

> Tested on Solaris x86_64/sparcv9 and Linux x86_64.

> 

> gdb/ChangeLog:

> 

> 2021-07-12 Libor Bukata <libor.bukata@oracle.com>

> 

>   * gdb/auxv.c (generic_auxv_parse): Read only 4 bytes as an

>   auxiliary type on Solaris.

>   (default_print_auxv_entry): Added AT_SUN_CAP_HW3 tag desc.


You can omit the gdb part of the ChangeLog, we don't use it anymore for
GDB.

>   * include/elf/common.h (AT_SUN_CAP_HW3): Added a new type.


This one will go into include/ChangeLog, so the entry should be relative
to the file.  You can use:

	* elf/common.h (AT_SUN_CAP_HW3): New.

Also, this is managed by the binutils maintainers, so you'll need to CC
binutils@sourceware.org on your patch to get approval from them.

> ---

>  gdb/auxv.c           | 11 +++++++++++

>  include/elf/common.h |  1 +

>  2 files changed, 12 insertions(+)

> 

> diff --git a/gdb/auxv.c b/gdb/auxv.c

> index 2bcf9f452e3..945d9f5c2bb 100644

> --- a/gdb/auxv.c

> +++ b/gdb/auxv.c

> @@ -267,7 +267,16 @@ generic_auxv_parse (struct gdbarch *gdbarch, gdb_byte **readptr,

>    if (endptr - ptr < 2 * sizeof_auxv_val)

>      return -1;

>  

> +  #if !defined(__sun) && !defined(__SVR4)

>    *typep = extract_unsigned_integer (ptr, sizeof_auxv_type, byte_order);

> +  #else

> +  // On Solaris auxv_type is int, therefore, we have to load

> +  // just 4 bytes to have valid type values (SPARC big-endian).

> +  // Note that it is required for X86 as well as padding is

> +  // not always filled with zeros...

> +  *typep = extract_unsigned_integer (ptr, sizeof(int), byte_order);

> +  #endif


This is not right, we don't want conditional compilation like that here.
Imagine that you are moving your Solaris core file to a Linux or Windows
machine and want to debug it there it needs to work.  So we can't base
decisions like this statically on the machine where GDB is compiled.

Note that the generic_auxv_parse already takes a sizeof_auxv_type.  And
note how svr4_auxv_parse seems to be doing what you want, passing the
size of an int.  It was introduced by this commit:

  https://gitlab.com/gnutools/gdb/-/commit/206c98a6503de9c78550b7e503526f59b5b2f491

So I think that what you need to do is call set_gdbarch_auxv_parse with
svr4_auxv_parse whenever a Solaris gdbarch is created.  That's probably
in sol2_init_abi, but I haven't tried.

Simon

Patch

diff --git a/gdb/auxv.c b/gdb/auxv.c
index 2bcf9f452e3..945d9f5c2bb 100644
--- a/gdb/auxv.c
+++ b/gdb/auxv.c
@@ -267,7 +267,16 @@  generic_auxv_parse (struct gdbarch *gdbarch, gdb_byte **readptr,
   if (endptr - ptr < 2 * sizeof_auxv_val)
     return -1;
 
+  #if !defined(__sun) && !defined(__SVR4)
   *typep = extract_unsigned_integer (ptr, sizeof_auxv_type, byte_order);
+  #else
+  // On Solaris auxv_type is int, therefore, we have to load
+  // just 4 bytes to have valid type values (SPARC big-endian).
+  // Note that it is required for X86 as well as padding is
+  // not always filled with zeros...
+  *typep = extract_unsigned_integer (ptr, sizeof(int), byte_order);
+  #endif
+
   /* Even if the auxv type takes less space than an auxv value, there is
      padding after the type such that the value is aligned on a multiple of
      its size (and this is why we advance by `sizeof_auxv_val` and not
@@ -541,6 +550,8 @@  default_print_auxv_entry (struct gdbarch *gdbarch, struct ui_file *file,
 	   AUXV_FORMAT_HEX);
       TAG (AT_SUN_CAP_HW2, _("Machine-dependent CPU capability hints 2"),
 	   AUXV_FORMAT_HEX);
+      TAG (AT_SUN_CAP_HW3, _("Machine-dependent CPU capability hints 3"),
+	   AUXV_FORMAT_HEX);
     }
 
   fprint_auxv_entry (file, name, description, format, type, val);
diff --git a/include/elf/common.h b/include/elf/common.h
index 0d381f0d27b..6e6287206ca 100644
--- a/include/elf/common.h
+++ b/include/elf/common.h
@@ -1377,5 +1377,6 @@ 
 #define	AT_SUN_BRAND_AUX2 2021
 #define	AT_SUN_BRAND_AUX3 2022
 #define	AT_SUN_CAP_HW2	2023	/* Extension of AT_SUN_CAP_HW1.  */
+#define	AT_SUN_CAP_HW3	2024	/* Extension of AT_SUN_CAP_HW2.  */
 
 #endif /* _ELF_COMMON_H */