public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Carl Love <cel@us.ibm.com>
To: "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>,
	Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
Cc: cel@us.ibm.com
Subject: [PATCH] PowerPC: fix _Float128 type output string
Date: Wed, 05 Apr 2023 08:28:10 -0700	[thread overview]
Message-ID: <184c0edcf067acccdf71d4dcdd66447bb5d93d4c.camel@us.ibm.com> (raw)

GDB maintainers:

PowerPC supports the IBM and IEEE 128-bit floating point formats. 
However the DWARF information does not distinguish between the two. 
The PowerPC GCC support created a workaround to identify the two
formats.  Unfortunately, the workaround is not transparent to GDB when
printing the name of the typedef.  The issue occurs on systems where
GCC is now set to generate the IEEE 128-bit format by default.

This patch fixes the printing of the typedef.  It fixes 74 test
failures in gdb.base/whatis-ptype-typedefs.exp and 1 failure in
gdb.base/complex-parts.exp.

The patch has been tested on a Power 10 platform where GCC generates
the IEEE 128-bit floats by default and on a Power 10 platform where the
IBM 128-bit floating point format is used by default.  Additionally,
the patch has been tested on X86-64.  The patch passes the regression
runs with no new regressions.

Please let me know if the patch is acceptable for mainline.  Thanks.

                     Carl 

------------------------------------------------------
PowerPC: fix _Float128 type output string

PowerPC supports two 128-bit floating point formats, the IBM long double
and IEEE 128-bit float.  The issue is the DWARF information does not
distinguish between the two.  There have been proposals of how to extend
the DWARF information as discussed in

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104194

but has not been fully implemented.

GCC introduced the _Float128 internal type as a work around for the issue.
The workaround is not transparent to GDB.  The internal _Float128 type
name is printed rather then the user specified long double type.  This
patch adds a new gdbarch method to allow PowerPC to detect the GCC
workaround.  The workaround checks for "_Float128" name when reading the
base typedef from the die_info.  If the workaround is detected, the type
and format fields from the _Float128 typedef are copied to the long
double typedef.  The same is done for the complex long double typedef.

This patch fixes 74 regression test failures in
gdb.base/whatis-ptype-typedefs.exp on PowerPC with IEEE float 128 as the
default on GCC.  It fixes one regression test failure in
gdb.base/complex-parts.exp.

The patch has been tested on Power 10 where GCC defaults to IEEE Float
128-bit and on Power 10 where GCC defaults to the IBM 128-bit float.  The
patch as also been tested on X86-64 with no new regression failures.
---
 gdb/arch-utils.c          |  7 +++++++
 gdb/arch-utils.h          |  5 +++++
 gdb/dwarf2/read.c         | 16 ++++++++++++----
 gdb/gdbarch-gen.h         |  8 ++++++++
 gdb/gdbarch.c             | 22 ++++++++++++++++++++++
 gdb/gdbarch_components.py | 19 +++++++++++++++++++
 gdb/ppc-linux-tdep.c      | 38 +++++++++++++++++++++++++++++++++++++-
 gdb/ppc-tdep.h            |  3 +++
 8 files changed, 113 insertions(+), 5 deletions(-)

diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c
index e3af9ce2dbc..997a292e9ef 100644
--- a/gdb/arch-utils.c
+++ b/gdb/arch-utils.c
@@ -1098,6 +1098,13 @@ default_get_return_buf_addr (struct type *val_type, frame_info_ptr cur_frame)
   return 0;
 }
 
+bool
+default_dwarf2_omit_typedef_p (struct type *target_type, const char *producer,
+			       const char *name)
+{
+  return false;
+}
+
 /* Non-zero if we want to trace architecture code.  */
 
 #ifndef GDBARCH_DEBUG
diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h
index 56690f0fd43..fc0c0b16793 100644
--- a/gdb/arch-utils.h
+++ b/gdb/arch-utils.h
@@ -309,6 +309,11 @@ extern void default_read_core_file_mappings
 extern CORE_ADDR default_get_return_buf_addr (struct type *val_typegdbarch,
 					      frame_info_ptr cur_frame);
 
+/* Default implementation of gdbaarch default_dwarf2_omit_typedef_p method.  */
+extern bool default_dwarf2_omit_typedef_p (struct type *target_type,
+					   const char *producer,
+					   const char *name);
+
 extern enum return_value_convention default_gdbarch_return_value
      (struct gdbarch *gdbarch, struct value *function, struct type *valtype,
       struct regcache *regcache, struct value **read_value,
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index c9208a097bf..fa319e346c0 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -14702,14 +14702,22 @@ static struct type *
 read_typedef (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct objfile *objfile = cu->per_objfile->objfile;
-  const char *name = NULL;
-  struct type *this_type, *target_type;
+  const char *name = dwarf2_full_name (NULL, die, cu);
+  struct type *this_type;
+  struct gdbarch *gdbarch = objfile->arch ();
+  struct type *target_type = die_type (die, cu);
+
+  if (gdbarch_dwarf2_omit_typedef_p (gdbarch, target_type, cu->producer, name))
+    {
+      this_type = copy_type (target_type);
+      this_type->set_name (name);
+      set_die_type (die, this_type, cu);
+      return this_type;
+    }
 
-  name = dwarf2_full_name (NULL, die, cu);
   this_type = type_allocator (objfile).new_type (TYPE_CODE_TYPEDEF, 0, name);
   this_type->set_target_is_stub (true);
   set_die_type (die, this_type, cu);
-  target_type = die_type (die, cu);
   if (target_type != this_type)
     this_type->set_target_type (target_type);
   else
diff --git a/gdb/gdbarch-gen.h b/gdb/gdbarch-gen.h
index a3fc0b9272b..3d8aafd5ea6 100644
--- a/gdb/gdbarch-gen.h
+++ b/gdb/gdbarch-gen.h
@@ -468,6 +468,14 @@ typedef CORE_ADDR (gdbarch_get_return_buf_addr_ftype) (struct type *val_type, fr
 extern CORE_ADDR gdbarch_get_return_buf_addr (struct gdbarch *gdbarch, struct type *val_type, frame_info_ptr cur_frame);
 extern void set_gdbarch_get_return_buf_addr (struct gdbarch *gdbarch, gdbarch_get_return_buf_addr_ftype *get_return_buf_addr);
 
+/* Return true if the typedef record needs to be replaced.".
+
+   Return 0 by default */
+
+typedef bool (gdbarch_dwarf2_omit_typedef_p_ftype) (struct type *target_type, const char *producer, const char *name);
+extern bool gdbarch_dwarf2_omit_typedef_p (struct gdbarch *gdbarch, struct type *target_type, const char *producer, const char *name);
+extern void set_gdbarch_dwarf2_omit_typedef_p (struct gdbarch *gdbarch, gdbarch_dwarf2_omit_typedef_p_ftype *dwarf2_omit_typedef_p);
+
 /* Return true if the return value of function is stored in the first hidden
    parameter.  In theory, this feature should be language-dependent, specified
    by language and its ABI, such as C++.  Unfortunately, compiler may
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index b676e346fd0..00e7191653a 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -114,6 +114,7 @@ struct gdbarch
   gdbarch_return_value_ftype *return_value = nullptr;
   gdbarch_return_value_as_value_ftype *return_value_as_value = default_gdbarch_return_value;
   gdbarch_get_return_buf_addr_ftype *get_return_buf_addr = default_get_return_buf_addr;
+  gdbarch_dwarf2_omit_typedef_p_ftype *dwarf2_omit_typedef_p = default_dwarf2_omit_typedef_p;
   gdbarch_return_in_first_hidden_param_p_ftype *return_in_first_hidden_param_p = default_return_in_first_hidden_param_p;
   gdbarch_skip_prologue_ftype *skip_prologue = nullptr;
   gdbarch_skip_main_prologue_ftype *skip_main_prologue = nullptr;
@@ -370,6 +371,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   if ((gdbarch->return_value_as_value == default_gdbarch_return_value) == (gdbarch->return_value == nullptr))
     log.puts ("\n\treturn_value_as_value");
   /* Skip verify of get_return_buf_addr, invalid_p == 0 */
+  /* Skip verify of dwarf2_omit_typedef_p, invalid_p == 0 */
   /* Skip verify of return_in_first_hidden_param_p, invalid_p == 0 */
   if (gdbarch->skip_prologue == 0)
     log.puts ("\n\tskip_prologue");
@@ -788,6 +790,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
   gdb_printf (file,
 	      "gdbarch_dump: get_return_buf_addr = <%s>\n",
 	      host_address_to_string (gdbarch->get_return_buf_addr));
+  gdb_printf (file,
+	      "gdbarch_dump: dwarf2_omit_typedef_p = <%s>\n",
+	      host_address_to_string (gdbarch->dwarf2_omit_typedef_p));
   gdb_printf (file,
 	      "gdbarch_dump: return_in_first_hidden_param_p = <%s>\n",
 	      host_address_to_string (gdbarch->return_in_first_hidden_param_p));
@@ -2617,6 +2622,23 @@ set_gdbarch_get_return_buf_addr (struct gdbarch *gdbarch,
   gdbarch->get_return_buf_addr = get_return_buf_addr;
 }
 
+bool
+gdbarch_dwarf2_omit_typedef_p (struct gdbarch *gdbarch, struct type *target_type, const char *producer, const char *name)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->dwarf2_omit_typedef_p != NULL);
+  if (gdbarch_debug >= 2)
+    gdb_printf (gdb_stdlog, "gdbarch_dwarf2_omit_typedef_p called\n");
+  return gdbarch->dwarf2_omit_typedef_p (target_type, producer, name);
+}
+
+void
+set_gdbarch_dwarf2_omit_typedef_p (struct gdbarch *gdbarch,
+				   gdbarch_dwarf2_omit_typedef_p_ftype dwarf2_omit_typedef_p)
+{
+  gdbarch->dwarf2_omit_typedef_p = dwarf2_omit_typedef_p;
+}
+
 int
 gdbarch_return_in_first_hidden_param_p (struct gdbarch *gdbarch, struct type *type)
 {
diff --git a/gdb/gdbarch_components.py b/gdb/gdbarch_components.py
index 2b1a2b4f602..7a64d9e006b 100644
--- a/gdb/gdbarch_components.py
+++ b/gdb/gdbarch_components.py
@@ -901,6 +901,25 @@ May return 0 when unable to determine that address.""",
     invalid=False,
 )
 
+
+# The DWARF info currently does not distinquish between IEEE 128-bit floating
+# point values and the IBM 128-bit floating point format.  GCC has an internal
+# hack that uses the _Float128 base typdef for IEEE 128-bit float values.  The
+# following method is used to "fix" the long double typedef so the _Float128
+# name is not printed.
+Function(
+    comment="""
+Return true if the typedef record needs to be replaced.".
+
+Return 0 by default""",
+    type="bool",
+    name="dwarf2_omit_typedef_p",
+    params=[("struct type *", "target_type"), ("const char *", "producer"),
+            ("const char *", "name")],
+    predefault="default_dwarf2_omit_typedef_p",
+    invalid=False,
+)
+
 Method(
     comment="""
 Return true if the return value of function is stored in the first hidden
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index fcddb2008a0..830a60fd49b 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -1,4 +1,4 @@
-/* Target-dependent code for GDB, the GNU debugger.
+* Target-dependent code for GDB, the GNU debugger.
 
    Copyright (C) 1986-2023 Free Software Foundation, Inc.
 
@@ -62,6 +62,7 @@
 #include "user-regs.h"
 #include <ctype.h>
 #include "elf-bfd.h"
+#include "producer.h"
 
 #include "features/rs6000/powerpc-32l.c"
 #include "features/rs6000/powerpc-altivec32l.c"
@@ -2006,6 +2007,38 @@ ppc_floatformat_for_type (struct gdbarch *gdbarch,
   return default_floatformat_for_type (gdbarch, name, len);
 }
 
+bool
+linux_dwarf2_omit_typedef_p (struct type *target_type,
+			     const char *producer, const char *name)
+{
+  int gcc_major, gcc_minor;
+
+  if (producer_is_gcc (producer, &gcc_major, &gcc_minor))
+    {
+      if ((target_type->code () == TYPE_CODE_FLT
+	   || target_type->code () == TYPE_CODE_COMPLEX)
+	  && (strcmp (name, "long double") == 0
+	      || strcmp (name, "complex long double") == 0))
+	{
+	  /* IEEE 128-bit floating point and IBM long double are two
+	     encodings for 128-bit values.  The DWARF debug data can't
+	     distinguish between them.  See bugzilla:
+	     https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104194
+
+	     A GCC hack was introduced to still allow the debugger to identify
+	     the case where "long double" uses the IEEE 128-bit floating point
+	     format: GCC will emit a bogus DWARF type record pretending that
+	     "long double" is a typedef alias for the _Float128 type.
+
+	     This hack should not be visible to the GDB user, so we replace
+	     this bogus typedef by a normal floating-point type, copying the
+	     format information from the target type of the bogus typedef.  */
+	  return true;
+	}
+    }
+  return false;
+}
+
 /* Specify the powerpc64le target triplet.
    This can be variations of
 	ppc64le-{distro}-linux-gcc
@@ -2083,6 +2116,9 @@ ppc_linux_init_abi (struct gdbarch_info info,
   /* Support for floating-point data type variants.  */
   set_gdbarch_floatformat_for_type (gdbarch, ppc_floatformat_for_type);
 
+  /* Support for replacing typedef record.  */
+  set_gdbarch_dwarf2_omit_typedef_p (gdbarch, linux_dwarf2_omit_typedef_p);
+
   /* Handle inferior calls during interrupted system calls.  */
   set_gdbarch_write_pc (gdbarch, ppc_linux_write_pc);
 
diff --git a/gdb/ppc-tdep.h b/gdb/ppc-tdep.h
index db4e53205a6..f078b3d45ab 100644
--- a/gdb/ppc-tdep.h
+++ b/gdb/ppc-tdep.h
@@ -176,6 +176,9 @@ extern void ppc_collect_vsxregset (const struct regset *regset,
 				  int regnum, void *vsxregs, size_t len);
 
 extern CORE_ADDR ppc64_sysv_get_return_buf_addr (type*, frame_info_ptr);
+extern bool linux_dwarf2_omit_typedef_p (struct type *target_type,
+					 const char *producer,
+					 const char *name);
 
 /* Private data that this module attaches to struct gdbarch.  */
 
-- 
2.37.2



             reply	other threads:[~2023-04-05 15:28 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-04-05 15:28 Carl Love [this message]
2023-04-05 20:18 ` Carl Love
2023-04-07 21:51   ` Kevin Buettner
2023-04-10 15:43     ` Carl Love
2023-04-10 15:46   ` [PATCH ver 2] " Carl Love
2023-04-10 16:01 ` Carl Love
2023-04-13 14:18   ` Tom Tromey
2023-04-13 16:13     ` Carl Love
2023-04-13 16:35       ` Carl Love
2023-04-13 17:12         ` Tom Tromey
2023-04-13 22:08           ` Carl Love
2023-04-17 15:45             ` [PATCH ver 3] " Carl Love
2023-04-18 10:18               ` Ulrich Weigand
2023-04-14 13:44       ` [PATCH ver 2] " Tom Tromey
2023-04-14 15:35         ` Carl Love
2023-04-17 10:26         ` Ulrich Weigand
2023-04-17 20:17           ` Tom Tromey
2023-04-18 10:17             ` Ulrich Weigand

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=184c0edcf067acccdf71d4dcdd66447bb5d93d4c.camel@us.ibm.com \
    --to=cel@us.ibm.com \
    --cc=Ulrich.Weigand@de.ibm.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).