From 965bc1df876f87dfc502169c0713ad275fba4803 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Tue, 6 Jul 2021 13:05:27 -0600 Subject: [PATCH] Handle compiler-generated suffixes in Ada names The compiler may add a suffix to a mangled name. A typical example would be splitting a function and creating a ".cold" variant. This patch changes Ada decoding (aka demangling) to handle these suffixes. It also changes the encoding process to handle them as well. A symbol like "function.cold" will now be displayed to the user as "function[cold]". The "." is not simply preserved because that is already used in Ada. --- gdb/ada-lang.c | 47 ++++++++++++++ gdb/testsuite/gdb.ada/complete.exp | 2 +- gdb/testsuite/gdb.dwarf2/ada-cold-name.exp | 72 ++++++++++++++++++++++ 3 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 gdb/testsuite/gdb.dwarf2/ada-cold-name.exp diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index caf8780fe7c..6680a4fd657 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -846,6 +846,21 @@ const struct ada_opname_map ada_opname_table[] = { {NULL, NULL} }; +/* If STR is a decoded version of a compiler-provided suffix (like the + "[cold]" in "symbol[cold]"), return true. Otherwise, return + false. */ + +static bool +is_compiler_suffix (const char *str) +{ + gdb_assert (*str == '['); + ++str; + while (*str != '\0' && isalpha (*str)) + ++str; + /* We accept a missing "]" in order to support completion. */ + return *str == '\0' || (str[0] == ']' && str[1] == '\0'); +} + /* The "encoded" form of DECODED, according to GNAT conventions. If THROW_ERRORS, throw an error if invalid operator name is found. Otherwise, return the empty string in that case. */ @@ -861,6 +876,13 @@ ada_encode_1 (const char *decoded, bool throw_errors) { if (*p == '.') encoding_buffer.append ("__"); + else if (*p == '[' && is_compiler_suffix (p)) + { + encoding_buffer = encoding_buffer + "." + (p + 1); + if (encoding_buffer.back () == ']') + encoding_buffer.pop_back (); + break; + } else if (*p == '"') { const struct ada_opname_map *mapping; @@ -977,6 +999,24 @@ ada_remove_po_subprogram_suffix (const char *encoded, int *len) *len = *len - 1; } +/* If ENCODED ends with a compiler-provided suffix (like ".cold"), + then update *LEN to remove the suffix and return the offset of the + character just past the ".". Otherwise, return -1. */ + +static int +remove_compiler_suffix (const char *encoded, int *len) +{ + int offset = *len - 1; + while (offset > 0 && isalpha (encoded[offset])) + --offset; + if (offset > 0 && encoded[offset] == '.') + { + *len = offset; + return offset + 1; + } + return -1; +} + /* See ada-lang.h. */ std::string @@ -987,6 +1027,7 @@ ada_decode (const char *encoded, bool wrap) const char *p; int at_start_name; std::string decoded; + int suffix = -1; /* With function descriptors on PPC64, the value of a symbol named ".FN", if it exists, is the entry point of the function "FN". */ @@ -1007,6 +1048,8 @@ ada_decode (const char *encoded, bool wrap) len0 = strlen (encoded); + suffix = remove_compiler_suffix (encoded, &len0); + ada_remove_trailing_digits (encoded, &len0); ada_remove_po_subprogram_suffix (encoded, &len0); @@ -1212,6 +1255,10 @@ ada_decode (const char *encoded, bool wrap) if (isupper (decoded[i]) || decoded[i] == ' ') goto Suppress; + /* If the compiler added a suffix, append it now. */ + if (suffix >= 0) + decoded = decoded + "[" + &encoded[suffix] + "]"; + return decoded; Suppress: diff --git a/gdb/testsuite/gdb.ada/complete.exp b/gdb/testsuite/gdb.ada/complete.exp index facf445d706..32b58f5907a 100644 --- a/gdb/testsuite/gdb.ada/complete.exp +++ b/gdb/testsuite/gdb.ada/complete.exp @@ -226,7 +226,7 @@ gdb_test_no_output "set max-completions unlimited" set test "complete break ada" gdb_test_multiple "$test" $test { - -re "^$test$eol\(break ada\[-a-z0-9._@/\]*$eol\)+$gdb_prompt $" { + -re "^$test$eol\(break ada\[\]\[a-z0-9._@/-\]*$eol\)+$gdb_prompt $" { pass $test } -re "\[A-Z\].*$gdb_prompt $" { diff --git a/gdb/testsuite/gdb.dwarf2/ada-cold-name.exp b/gdb/testsuite/gdb.dwarf2/ada-cold-name.exp new file mode 100644 index 00000000000..2e4441aee35 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/ada-cold-name.exp @@ -0,0 +1,72 @@ +# Copyright 2019-2021 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 . + +# Test "cold" suffix handling. + +load_lib dwarf.exp + +# This test can only be run on targets which support DWARF-2 and use gas. +if {![dwarf2_support]} { + return 0 +} + +standard_testfile ada-linkage-name.c -debug.S + +# Set up the DWARF for the test. + +set asm_file [standard_output_file $srcfile2] +Dwarf::assemble $asm_file { + global srcdir subdir srcfile + + cu {} { + DW_TAG_compile_unit { + {DW_AT_language @DW_LANG_Ada95} + {DW_AT_name $srcfile} + {DW_AT_comp_dir /tmp} + } { + declare_labels b_l + + b_l: DW_TAG_base_type { + {DW_AT_byte_size 1 DW_FORM_sdata} + {DW_AT_encoding @DW_ATE_signed} + {DW_AT_name bool} + } + + DW_TAG_subprogram { + {name pck__xtra__function.cold} + {MACRO_AT_range {first}} + {type :$b_l} + } + + DW_TAG_subprogram { + {name pck__xtra__function} + {MACRO_AT_range {second}} + {type :$b_l} + } + } + } +} + +if { [prepare_for_testing "failed to prepare" ${testfile} \ + [list $srcfile $asm_file] {nodebug}] } { + return -1 +} + +gdb_test_no_output "set language ada" +gdb_breakpoint "pck.xtra.function" message +gdb_breakpoint "pck.xtra.function\[cold\]" message +gdb_test "complete break pck.xtra.function\[co" \ + "break pck.xtra.function\\\[cold\\\]" \ + "test completion of cold function" -- 2.30.2