[RFA] Use rust_demangle

Tom Tromey
2017-04-18T12:31:29Z

PR rust/20268 is about using the extra Rust-specific demangling that
was added to libiberty.

Initially this looked easy: just change rust_language_defn to
reference rust_demangle. However, it's not quite so simple:

* Writing a "real" test was tricky because some bugs in the Rust
compiler cause gdb to pick funny names for the affected functions,
and when debuginfo is available it's hard to access the minsyms.
This I fixed by adding a comment and compiling without debuginfo.

* This revealed a couple of spots in symtab.c where gdb wasn't
checking for language_rust.

* The C++ demangler runs before the Rust demangler. And, because the
Rust mangling scheme is C++-like, Rust symbols will never be seen by
the Rust demangler. The fix is to have the C++ demangler return
NULL for Rust symbols.

* ... but that affects some tests cases, like demangle.exp, because
gdb then need special treatment for DMGL_AUTO.

* ... and, in light of this change, "set demangle-style" seems a bit
weird because it allows the setting of styles to things obviously
not related to C++ at all, hence a change in demangle.c.

Two future ideas came to mind. One is to remove obsolete things like
the Lucide demangling style. The other is to change the demangler's
"auto" mode to also return the language of the symbol, if it could be
discovered. This would avoid double demangling.

Built and regtested on the buildbot.

ChangeLog
2017-04-16 Tom Tromey <tom@tromey.com>

PR rust/20268:
* demangle.c (_initialize_demangler): Filter out non-C++ styles.
* symtab.c (symbol_natural_name, symbol_demangled_name): Demangle
for language_rust.
* cp-support.h (gdb_demangle_cxx): Declare.
* cp-support.c (gdb_demangle_cxx): New function.
(gdb_sniff_from_mangled_name): Use it.
* c-lang.c (cplus_language_defn): Reference gdb_demangle_cxx.
* rust-lang.c (rust_sniff_from_mangled_name): Call rust_demangle.
(rust_language_defn): Reference rust_demangle.

testsuite/ChangeLog
2017-04-14 Tom Tromey <tom@tromey.com>

PR rust/20268:
* gdb.rust/rdemangle.exp: New file.
* gdb.rust/rdemangle.rs: New file.
---
gdb/ChangeLog | 13 +++++++++++
gdb/c-lang.c | 2 +-
gdb/cp-support.c | 23 ++++++++++++++++++-
gdb/cp-support.h | 8 ++++++-
gdb/demangle.c | 36 ++++++++++++++++++++----------
gdb/rust-lang.c | 4 ++--
gdb/symtab.c | 2 ++
gdb/testsuite/ChangeLog | 6 +++++
gdb/testsuite/gdb.rust/rdemangle.exp | 39 ++++++++++++++++++++++++++++++++
gdb/testsuite/gdb.rust/rdemangle.rs | 43 ++++++++++++++++++++++++++++++++++++
10 files changed, 159 insertions(+), 17 deletions(-)
create mode 100644 gdb/testsuite/gdb.rust/rdemangle.exp
create mode 100644 gdb/testsuite/gdb.rust/rdemangle.rs

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index f033ced..a96507a 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,16 @@
+2017-04-16 Tom Tromey <tom@tromey.com>
+
+ PR rust/20268:
+ * demangle.c (_initialize_demangler): Filter out non-C++ styles.
+ * symtab.c (symbol_natural_name, symbol_demangled_name): Demangle
+ for language_rust.
+ * cp-support.h (gdb_demangle_cxx): Declare.
+ * cp-support.c (gdb_demangle_cxx): New function.
+ (gdb_sniff_from_mangled_name): Use it.
+ * c-lang.c (cplus_language_defn): Reference gdb_demangle_cxx.
+ * rust-lang.c (rust_sniff_from_mangled_name): Call rust_demangle.
+ (rust_language_defn): Reference rust_demangle.
+
2017-04-17 Joel Brobecker <brobecker@adacore.com>

* NEWS: Create a new section for the next release branch.
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 19a8608..874916e 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -995,7 +995,7 @@ const struct language_defn cplus_language_defn =
"this", /* name_of_this */
cp_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
cp_lookup_transparent_type, /* lookup_transparent_type */
- gdb_demangle, /* Language specific symbol demangler */
+ gdb_demangle_cxx, /* Language specific symbol demangler */
gdb_sniff_from_mangled_name,
cp_class_name_from_physname, /* Language specific
class_name_from_physname */
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index 5704466..1a86532 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -1588,10 +1588,31 @@ gdb_demangle (const char *name, int options)

/* See cp-support.h. */

+char *
+gdb_demangle_cxx (const char *mangled, int options)
+{
+ int style = (DMGL_GNU | DMGL_LUCID | DMGL_ARM
+ | DMGL_HP | DMGL_EDG | DMGL_GNU_V3);
+
+ if ((current_demangling_style & DMGL_AUTO) == 0)
+ style &= current_demangling_style;
+
+ char *ret = gdb_demangle (mangled, (options | DMGL_PARAMS | DMGL_ANSI
+ | style));
+ if (rust_is_mangled (ret))
+ {
+ xfree (ret);
+ ret = NULL;
+ }
+ return ret;
+}
+
+/* See cp-support.h. */
+
int
gdb_sniff_from_mangled_name (const char *mangled, char **demangled)
{
- *demangled = gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
+ *demangled = gdb_demangle_cxx (mangled, 0);
return *demangled != NULL;
}

diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index 9054bf6..aaca67e 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -157,7 +157,13 @@ extern struct cmd_list_element *maint_cplus_cmd_list;

char *gdb_demangle (const char *name, int options);

-/* Like gdb_demangle, but suitable for use as la_sniff_from_mangled_name. */
+/* A wrapper for gdb_demangle that will only successfully demangle C++
+ names. */
+
+char *gdb_demangle_cxx (const char *mangled, int options);
+
+/* Like gdb_demangle_cxx, but suitable for use as
+ la_sniff_from_mangled_name. */

int gdb_sniff_from_mangled_name (const char *mangled, char **demangled);

diff --git a/gdb/demangle.c b/gdb/demangle.c
index 2d79c1d..d9ed896 100644
--- a/gdb/demangle.c
+++ b/gdb/demangle.c
@@ -232,25 +232,37 @@ extern initialize_file_ftype _initialize_demangler; /* -Wmissing-prototypes */
void
_initialize_demangler (void)
{
- int i, ndems;
+ int i, out, ndems;

/* Fill the demangling_style_names[] array, and set the default
demangling style chosen at compilation time. */
- for (ndems = 0;
- libiberty_demanglers[ndems].demangling_style != unknown_demangling;
- ndems++)
- ;
+ for (i = ndems = 0;
+ libiberty_demanglers[i].demangling_style != unknown_demangling;
+ i++)
+ {
+ if (libiberty_demanglers[i].demangling_style != gnat_demangling
+ && libiberty_demanglers[i].demangling_style != dlang_demangling
+ && libiberty_demanglers[i].demangling_style != rust_demangling)
+ ++ndems;
+ }
demangling_style_names = XCNEWVEC (const char *, ndems + 1);
- for (i = 0;
+ for (i = out = 0;
libiberty_demanglers[i].demangling_style != unknown_demangling;
i++)
{
- demangling_style_names[i]
- = xstrdup (libiberty_demanglers[i].demangling_style_name);
-
- if (current_demangling_style_string == NULL
- && strcmp (DEFAULT_DEMANGLING_STYLE, demangling_style_names[i]) == 0)
- current_demangling_style_string = demangling_style_names[i];
+ if (libiberty_demanglers[i].demangling_style != gnat_demangling
+ && libiberty_demanglers[i].demangling_style != dlang_demangling
+ && libiberty_demanglers[i].demangling_style != rust_demangling)
+ {
+ demangling_style_names[out]
+ = xstrdup (libiberty_demanglers[out].demangling_style_name);
+
+ if (current_demangling_style_string == NULL
+ && strcmp (DEFAULT_DEMANGLING_STYLE,
+ demangling_style_names[out]) == 0)
+ current_demangling_style_string = demangling_style_names[out];
+ ++out;
+ }
}

add_setshow_boolean_cmd ("demangle", class_support, &demangle, _("\
diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c
index fe8a58c..13c88d9 100644
--- a/gdb/rust-lang.c
+++ b/gdb/rust-lang.c
@@ -2116,7 +2116,7 @@ rust_lookup_symbol_nonlocal (const struct language_defn *langdef,
static int
rust_sniff_from_mangled_name (const char *mangled, char **demangled)
{
- *demangled = gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
+ *demangled = rust_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
return *demangled != NULL;
}

@@ -2163,7 +2163,7 @@ static const struct language_defn rust_language_defn =
NULL, /* name_of_this */
rust_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
basic_lookup_transparent_type,/* lookup_transparent_type */
- gdb_demangle, /* Language specific symbol demangler */
+ rust_demangle, /* Language specific symbol demangler */
rust_sniff_from_mangled_name,
NULL, /* Language specific
class_name_from_physname */
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 20ef76d..4cfc85d 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -893,6 +893,7 @@ symbol_natural_name (const struct general_symbol_info *gsymbol)
case language_go:
case language_objc:
case language_fortran:
+ case language_rust:
if (symbol_get_demangled_name (gsymbol) != NULL)
return symbol_get_demangled_name (gsymbol);
break;
@@ -919,6 +920,7 @@ symbol_demangled_name (const struct general_symbol_info *gsymbol)
case language_go:
case language_objc:
case language_fortran:
+ case language_rust:
dem_name = symbol_get_demangled_name (gsymbol);
break;
case language_ada:
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 42d6a8d..d60b719 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2017-04-14 Tom Tromey <tom@tromey.com>
+
+ PR rust/20268:
+ * gdb.rust/rdemangle.exp: New file.
+ * gdb.rust/rdemangle.rs: New file.
+
2017-04-12 Pedro Alves <palves@redhat.com>

PR gdb/21323
diff --git a/gdb/testsuite/gdb.rust/rdemangle.exp b/gdb/testsuite/gdb.rust/rdemangle.exp
new file mode 100644
index 0000000..7bfbf71
--- /dev/null
+++ b/gdb/testsuite/gdb.rust/rdemangle.exp
@@ -0,0 +1,39 @@
+# Copyright (C) 2017 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/>.
+
+# Test Rust-specific demangling.
+
+load_lib rust-support.exp
+if {[skip_rust_tests]} {
+ continue
+}
+
+standard_testfile .rs
+# The rust compiler emits some funny debuginfo for trait impls; and if
+# gdb sees debuginfo, "info func" will prefer the debuginfo symbols to
+# the minsyms, printing the wrong thing. So, don't enable debugging.
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile {rust}]} {
+ return -1
+}
+
+gdb_test "info func what" ".*$hex *<rdemangle::X as rdemangle::What>::what" \
+ "rust demangle minsym"
+
+set symbol "_ZN34_\$LT\$bc..X\$u20\$as\$u20\$bc..What\$GT\$4what17hec04869420f7eb7fE"
+
+gdb_test "demangle -l rust -- $symbol" "<bc::X as bc::What>::what" \
+ "demangle rust symbol"
+gdb_test "demangle -l c++ -- $symbol" "Can't demangle \"\[^\"\]*\"" \
+ "do not demangle rust symbol as c++"
diff --git a/gdb/testsuite/gdb.rust/rdemangle.rs b/gdb/testsuite/gdb.rust/rdemangle.rs
new file mode 100644
index 0000000..69f937f
--- /dev/null
+++ b/gdb/testsuite/gdb.rust/rdemangle.rs
@@ -0,0 +1,43 @@
+// Copyright (C) 2017 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/>.
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+
+struct X {}
+
+pub trait What {
+ fn what(&self);
+}
+
+impl X {
+ fn what(&self) {
+ ()
+ }
+}
+
+impl What for X {
+ fn what(&self) {
+ println!("{}", 32);
+ }
+}
+
+fn main() {
+ let x = X{};
+ x.what();
+ <X as What>::what(&x);
+ ()
+}
--
2.9.3