[RFC] regresssion(internal-error) printing subprogram argument

Message ID 20180129103841.kdkomcjbuwiat5b4@adacore.com
State New, archived
Headers

Commit Message

Joel Brobecker Jan. 29, 2018, 10:38 a.m. UTC
  > Indeed, looks like I don't have that.  I have "interfacesS".
> I've attached the whole file.

That explains it :).

> So it may be that we still need to add another special case
> for Ada somewhere.  Would old GDB from before the C++
> wildmatching pass this test for you?

I went binary searching for the source of the regression and
when I found that it was "caused" by the change requiring variables
without debugging information to be cast before they can be printed,
I gently head-slapped myself, adjusted the testcase to use something
other than an integer variable, and voila - even GDB 7.10 suffers
from the problem.  We just didn't see it for integer variables simply
because we were lucky!

I ran out of time again today, but at least the WIP patch got
augmented with a testcase that currently fails before the patch
is applied.

I think the patch itself is probably correct, although I'd like
to do some archeology to understand the comment attached to
that location. I'm pretty confused by it, when we could simply
say that symbols from languages that do not follow the C++ mangling
should not be demangled by gdb_demangle -- at least for as long
as gdb_demangle is equivalent to cplusplus_demangle in practice...

And just as a reminder for myself, I said in my other email
last week that I wanted also to review all the calls to gdb_demangle.
  

Comments

Pedro Alves Jan. 29, 2018, 3:33 p.m. UTC | #1
On 01/29/2018 10:38 AM, Joel Brobecker wrote:
>> Indeed, looks like I don't have that.  I have "interfacesS".
>> I've attached the whole file.
> 
> That explains it :).
> 
>> So it may be that we still need to add another special case
>> for Ada somewhere.  Would old GDB from before the C++
>> wildmatching pass this test for you?
> 
> I went binary searching for the source of the regression and
> when I found that it was "caused" by the change requiring variables
> without debugging information to be cast before they can be printed,
> I gently head-slapped myself, adjusted the testcase to use something
> other than an integer variable, and voila - even GDB 7.10 suffers
> from the problem.  We just didn't see it for integer variables simply
> because we were lucky!
> 
> I ran out of time again today, but at least the WIP patch got
> augmented with a testcase that currently fails before the patch
> is applied.
> 
> I think the patch itself is probably correct, although I'd like
> to do some archeology to understand the comment attached to
> that location. I'm pretty confused by it, when we could simply
> say that symbols from languages that do not follow the C++ mangling
> should not be demangled by gdb_demangle -- at least for as long
> as gdb_demangle is equivalent to cplusplus_demangle in practice...

Yeah, the commentary around that code isn't exactly clear.
Why doesn't that code use language->la_demangle instead,
for example.

The other day I noticed that gdb_demangle -> bfd_demangle ->
cplus_demangle does have support for demangling other languages.
For Ada, see the GNAT_DEMANGLING handling in
libiberty.c:cplus-dem.c:cplus_demangle, which takes you to:

 /* Demangle ada names.  The encoding is documented in gcc/ada/exp_dbug.ads.  */

 char *
 ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
 {


When I saw that, I wondered why is it that GDB has a separate
implementation of Ada decoding in gdb/ada-lang.c.  The only plausible
explanation I came up with is that gdb's version decodes into a
buffer that is shared between invocations while libiberty's version
always heap-allocates the result.  Maybe it was an efficiency thing?
Do you know?

I ran into that around this discussion
<https://sourceware.org/ml/gdb/2017-11/msg00029.html> where I
was wondering whether we could speed up demangling by letting
bfd_demangle / cplus_demangle try all languages and return back
which one worked:

 ~~~
 An idea I had would be to try to combine most the language_sniff_from_mangled_name
 implementations in one call, by deferring to cplus_demangle which seems
 like could take care of gnu v3, rust, java, gnat, dlang and old C++ mangling
 schemes all at once.  This would avoid the overhead of gdb_demangle and
 bfd_demangle for each language-specific demangling call, at least.  Not sure.
 ~~~

Because ada_decode comes up high in profiles today...

> 
> And just as a reminder for myself, I said in my other email
> last week that I wanted also to review all the calls to gdb_demangle.

Thanks,
Pedro Alves
  
Joel Brobecker Jan. 30, 2018, 3:56 a.m. UTC | #2
> The other day I noticed that gdb_demangle -> bfd_demangle ->
> cplus_demangle does have support for demangling other languages.
> For Ada, see the GNAT_DEMANGLING handling in
> libiberty.c:cplus-dem.c:cplus_demangle, which takes you to:
> 
>  /* Demangle ada names.  The encoding is documented in gcc/ada/exp_dbug.ads.  */
> 
>  char *
>  ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
>  {

Ha! Thanks for digging; who would have thought...

> When I saw that, I wondered why is it that GDB has a separate
> implementation of Ada decoding in gdb/ada-lang.c.  The only plausible
> explanation I came up with is that gdb's version decodes into a
> buffer that is shared between invocations while libiberty's version
> always heap-allocates the result.  Maybe it was an efficiency thing?
> Do you know?

I don't unfortunately. I'm pretty sure GDB's ada_decode was already
present before I joined AdaCore...

It is true that start up performance is critical, particularly in Ada,
because one of the strengths of Ada is to help design very large apps.
I think that, eventually, we're going to have to accept that computing
power is gained by adding parallelism, and try to take advantage of that
to speed things up (with the dangers in terms of stability that it
entails), so that aspect might become less relevant once we make that
transition.

> I ran into that around this discussion
> <https://sourceware.org/ml/gdb/2017-11/msg00029.html> where I
> was wondering whether we could speed up demangling by letting
> bfd_demangle / cplus_demangle try all languages and return back
> which one worked:
> 
>  ~~~
>  An idea I had would be to try to combine most the language_sniff_from_mangled_name
>  implementations in one call, by deferring to cplus_demangle which seems
>  like could take care of gnu v3, rust, java, gnat, dlang and old C++ mangling
>  schemes all at once.  This would avoid the overhead of gdb_demangle and
>  bfd_demangle for each language-specific demangling call, at least.  Not sure.
>  ~~~
> 
> Because ada_decode comes up high in profiles today...

Can we avoid the calls to most demanglers entirely by passing
the language to symbol_set_names? I didn't do an extensive search
of all the callers. We could have a fallback where language_unknown
means try all the demanglers, but for the cases we care about,
which is mostly DWARF debugging info, that could save a lot of
unnecessary attempts, like you say.

My feeling on the global situation with those demanglers is that
we take a risk each time we use the demanglers themselves to
try to determine which language the symbol belongs to. Both
the C++ and the Ada mangling/encoding algorithms are not exclusive
enough, and we're seeing in this thread how easy it is to get
it wrong. For minimal symbols, we don't have the information,
so that's one valid situation where we have no choice but to guess.
But when reading DWARF debugging information, for instance, we do
have the language information, so we should take advantage of it.

Thinking out loud, this leads me to wonder whether it's a good idea
to store the demangled name instead of the linkage name. You'd do
the search on the mangled name rather than on the demangled one,
so you would not have to guess when loading the symbols. Maybe it's
a good idea if it helps performance, and perhaps we can plug that
weakness differently...
  

Patch

From 6f24c49e7c3ba2c6246aa3de92ef48c1315778f8 Mon Sep 17 00:00:00 2001
From: Joel Brobecker <brobecker@adacore.com>
Date: Thu, 25 Jan 2018 23:23:54 -0500
Subject: [PATCH] WIP: dwarf2read.c::dwarf2_physname: do not call gdb_demangle
 with Ada symbols

---
 gdb/dwarf2read.c                           |  2 +-
 gdb/testsuite/gdb.ada/notcplusplus.exp     | 45 ++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.ada/notcplusplus/foo.adb | 21 ++++++++++++++
 gdb/testsuite/gdb.ada/notcplusplus/pck.adb | 21 ++++++++++++++
 gdb/testsuite/gdb.ada/notcplusplus/pck.ads | 19 +++++++++++++
 gdb/testsuite/gdb.ada/notcplusplus/ver.ads | 22 +++++++++++++++
 6 files changed, 129 insertions(+), 1 deletion(-)
 create mode 100644 gdb/testsuite/gdb.ada/notcplusplus.exp
 create mode 100644 gdb/testsuite/gdb.ada/notcplusplus/foo.adb
 create mode 100644 gdb/testsuite/gdb.ada/notcplusplus/pck.adb
 create mode 100644 gdb/testsuite/gdb.ada/notcplusplus/pck.ads
 create mode 100644 gdb/testsuite/gdb.ada/notcplusplus/ver.ads

diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 51d0f39..7febade 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -11150,7 +11150,7 @@  dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
 	 variant `long name(params)' does not have the proper inferior type.
 	 */
 
-      if (cu->language == language_go)
+      if (cu->language == language_go || cu->language == language_ada)
 	{
 	  /* This is a lie, but we already lie to the caller new_symbol.
 	     new_symbol assumes we return the mangled name.
diff --git a/gdb/testsuite/gdb.ada/notcplusplus.exp b/gdb/testsuite/gdb.ada/notcplusplus.exp
new file mode 100644
index 0000000..b2a24e8
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/notcplusplus.exp
@@ -0,0 +1,45 @@ 
+# Copyright 2018 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+load_lib "ada.exp"
+
+if { [skip_ada_tests] } { return -1 }
+
+standard_ada_testfile foo
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable {debug}] != ""} {
+    return -1
+}
+
+clean_restart ${testfile}
+
+gdb_test "print /x <symada__cS>" \
+         "= \\(a => 0x60287af\\)" \
+         "print <symada__cS> before loading symbols from ver.ads"
+
+# Force the partial symbosl from ver.ads to be expanded into full symbols.
+
+gdb_test \
+     "list ver.ads:16" \
+     [multi_line ".*" \
+                 "16\\s+package Ver is" \
+                 "17\\s+type Wrapper is record" \
+                 "18\\s+A : Integer;" \
+                 "19\\s+end record;" \
+                 "20\\s+u00045 : constant Wrapper := \\(A => 16#060287af#\\);"]
+
+gdb_test "print /x <symada__cS>" \
+         "= \\(a => 0x60287af\\)" \
+         "print <symada__cS> after loading symbols from ver.ads"
diff --git a/gdb/testsuite/gdb.ada/notcplusplus/foo.adb b/gdb/testsuite/gdb.ada/notcplusplus/foo.adb
new file mode 100644
index 0000000..89e42f9
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/notcplusplus/foo.adb
@@ -0,0 +1,21 @@ 
+--  Copyright 2018 Free Software Foundation, Inc.
+--
+--  This program is free software; you can redistribute it and/or modify
+--  it under the terms of the GNU General Public License as published by
+--  the Free Software Foundation; either version 3 of the License, or
+--  (at your option) any later version.
+--
+--  This program is distributed in the hope that it will be useful,
+--  but WITHOUT ANY WARRANTY; without even the implied warranty of
+--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+--  GNU General Public License for more details.
+--
+--  You should have received a copy of the GNU General Public License
+--  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+with Pck; use Pck;
+with Ver; use Ver;
+procedure Foo is
+begin
+   Do_Nothing (u00045'Address);
+end Foo;
diff --git a/gdb/testsuite/gdb.ada/notcplusplus/pck.adb b/gdb/testsuite/gdb.ada/notcplusplus/pck.adb
new file mode 100644
index 0000000..dcfb306
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/notcplusplus/pck.adb
@@ -0,0 +1,21 @@ 
+--  Copyright 2018 Free Software Foundation, Inc.
+--
+--  This program is free software; you can redistribute it and/or modify
+--  it under the terms of the GNU General Public License as published by
+--  the Free Software Foundation; either version 3 of the License, or
+--  (at your option) any later version.
+--
+--  This program is distributed in the hope that it will be useful,
+--  but WITHOUT ANY WARRANTY; without even the implied warranty of
+--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+--  GNU General Public License for more details.
+--
+--  You should have received a copy of the GNU General Public License
+--  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+package body Pck is
+   procedure Do_Nothing (A : System.Address) is
+   begin
+      null;
+   end Do_Nothing;
+end Pck;
diff --git a/gdb/testsuite/gdb.ada/notcplusplus/pck.ads b/gdb/testsuite/gdb.ada/notcplusplus/pck.ads
new file mode 100644
index 0000000..33e369e
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/notcplusplus/pck.ads
@@ -0,0 +1,19 @@ 
+--  Copyright 2018 Free Software Foundation, Inc.
+--
+--  This program is free software; you can redistribute it and/or modify
+--  it under the terms of the GNU General Public License as published by
+--  the Free Software Foundation; either version 3 of the License, or
+--  (at your option) any later version.
+--
+--  This program is distributed in the hope that it will be useful,
+--  but WITHOUT ANY WARRANTY; without even the implied warranty of
+--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+--  GNU General Public License for more details.
+--
+--  You should have received a copy of the GNU General Public License
+--  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+with System;
+package Pck is
+   procedure Do_Nothing (A : System.Address);
+end Pck;
diff --git a/gdb/testsuite/gdb.ada/notcplusplus/ver.ads b/gdb/testsuite/gdb.ada/notcplusplus/ver.ads
new file mode 100644
index 0000000..8f264d0
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/notcplusplus/ver.ads
@@ -0,0 +1,22 @@ 
+--  Copyright 2018 Free Software Foundation, Inc.
+--
+--  This program is free software; you can redistribute it and/or modify
+--  it under the terms of the GNU General Public License as published by
+--  the Free Software Foundation; either version 3 of the License, or
+--  (at your option) any later version.
+--
+--  This program is distributed in the hope that it will be useful,
+--  but WITHOUT ANY WARRANTY; without even the implied warranty of
+--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+--  GNU General Public License for more details.
+--
+--  You should have received a copy of the GNU General Public License
+--  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+package Ver is
+   type Wrapper is record
+      A : Integer;
+   end record;
+   u00045 : constant Wrapper := (A => 16#060287af#);
+   pragma Export (C, u00045, "symada__cS");
+end Ver;
-- 
2.1.4