[PATCH] Handle block-local names for Ada
Tom Tromey
tromey@adacore.com
Tue Nov 10 16:55:03 GMT 2020
GNAT can generate a mangled name with "B_N" (where N is a number) in
the middle, like "hello__B_1__fourth.0". This is used for names local
to a block. This patch changes gdb to handle these names.
This patch updates the wild name matcher in a straightforward way.
For the full matcher, it changes gdb to build a regular expression to
match the symbol name. The hash function is updated to ensure that
this works.
One possible concern here is performance, but testing on a large Ada
program showed that, while the slowdown was perhaps bad in percentage
terms, in absolute terms it seems fine:
For the test of "break nosuch.function", "maint time 1" reports:
before: Command execution time: 0.101233 (cpu), 0.101482 (wall)
after : Command execution time: 0.136016 (cpu), 0.136306 (wall)
This result is typical, so about 4/100 of a second slowdown.
gdb/ChangeLog
2020-11-10 Tom Tromey <tromey@adacore.com>
* ada-lang.c (advance_wild_match): Ignore "B".
(full_match): Remove.
(ada_lookup_name_info::match_regex): New method.
(do_full_match): Rewrite.
* dictionary.c (language_defn::search_name_hash): Ignore "B".
* gdb_regex.c (~compiled_regex): Check m_owned.
* gdb_regex.h (compiled_regex): Add move constructor.
<m_owned>: New member.
* symtab.h (ada_lookup_name_info::match_regex): Declare
new method.
(ada_lookup_name_info::m_full_regex): New member.
gdb/testsuite/ChangeLog
2020-11-10 Tom Tromey <tromey@adacore.com>
* gdb.ada/nested.exp: Add new tests.
* gdb.ada/nested/hello.adb (Fourth): New procedure.
---
gdb/ChangeLog | 14 ++++++
gdb/ada-lang.c | 59 ++++++++++++++++----------
gdb/dictionary.c | 7 +++
gdb/gdb_regex.c | 3 +-
gdb/gdb_regex.h | 8 ++++
gdb/symtab.h | 7 +++
gdb/testsuite/ChangeLog | 5 +++
gdb/testsuite/gdb.ada/nested.exp | 7 +++
gdb/testsuite/gdb.ada/nested/hello.adb | 10 ++++-
9 files changed, 94 insertions(+), 26 deletions(-)
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index fe3ea7009a6..7aa738b9187 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -6034,6 +6034,13 @@ advance_wild_match (const char **namep, const char *name0, char target0)
name += 2;
break;
}
+ else if (t1 == '_' && name[2] == 'B' && name[3] == '_')
+ {
+ /* Names like "pkg__B_N__name", where N is a number, are
+ block-local. We can handle these by simply skipping
+ the "B_" here. */
+ name += 4;
+ }
else
return 0;
}
@@ -6078,28 +6085,6 @@ wild_match (const char *name, const char *patn)
}
}
-/* Returns true iff symbol name SYM_NAME matches SEARCH_NAME, ignoring
- any trailing suffixes that encode debugging information or leading
- _ada_ on SYM_NAME (see is_name_suffix commentary for the debugging
- information that is ignored). */
-
-static bool
-full_match (const char *sym_name, const char *search_name)
-{
- size_t search_name_len = strlen (search_name);
-
- if (strncmp (sym_name, search_name, search_name_len) == 0
- && is_name_suffix (sym_name + search_name_len))
- return true;
-
- if (startswith (sym_name, "_ada_")
- && strncmp (sym_name + 5, search_name, search_name_len) == 0
- && is_name_suffix (sym_name + search_name_len + 5))
- return true;
-
- return false;
-}
-
/* Add symbols from BLOCK matching LOOKUP_NAME in DOMAIN to vector
*defn_symbols, updating the list of symbols in OBSTACKP (if
necessary). OBJFILE is the section containing BLOCK. */
@@ -13634,6 +13619,26 @@ do_wild_match (const char *symbol_search_name,
return wild_match (symbol_search_name, ada_lookup_name (lookup_name));
}
+/* See symtab.h. */
+
+compiled_regex &
+ada_lookup_name_info::match_regex () const
+{
+ if (!m_full_regex.has_value ())
+ {
+ std::string rx = "^(_ada_)?" + m_encoded_name;
+
+ auto where = rx.rfind ("__");
+ if (where != std::string::npos)
+ rx.insert (where, "(__B_[0-9]*)?");
+
+ m_full_regex.emplace (rx.c_str (), REG_EXTENDED,
+ "could not convert search name to regular expression");
+ }
+
+ return *m_full_regex;
+}
+
/* symbol_name_matcher_ftype adapter for full_match. */
static bool
@@ -13641,7 +13646,15 @@ do_full_match (const char *symbol_search_name,
const lookup_name_info &lookup_name,
completion_match_result *comp_match_res)
{
- return full_match (symbol_search_name, ada_lookup_name (lookup_name));
+ compiled_regex &rx = lookup_name.ada ().match_regex ();
+
+ regmatch_t matches[2];
+ if (rx.exec (symbol_search_name, 2, matches, 0) != 0)
+ return false;
+
+ if (is_name_suffix (symbol_search_name + matches[0].rm_eo))
+ return true;
+ return false;
}
/* symbol_name_matcher_ftype for exact (verbatim) matches. */
diff --git a/gdb/dictionary.c b/gdb/dictionary.c
index c94a49ee373..d51f209e715 100644
--- a/gdb/dictionary.c
+++ b/gdb/dictionary.c
@@ -761,6 +761,13 @@ language_defn::search_name_hash (const char *string0) const
{
int c = string[2];
+ if (c == 'B' && string[3] == '_')
+ {
+ for (string += 4; ISDIGIT (*string); ++string)
+ ;
+ continue;
+ }
+
if ((c < 'a' || c > 'z') && c != 'O')
return hash;
hash = 0;
diff --git a/gdb/gdb_regex.c b/gdb/gdb_regex.c
index 063c68b097b..7d991d520fd 100644
--- a/gdb/gdb_regex.c
+++ b/gdb/gdb_regex.c
@@ -38,7 +38,8 @@ compiled_regex::compiled_regex (const char *regex, int cflags,
compiled_regex::~compiled_regex ()
{
- regfree (&m_pattern);
+ if (m_owned)
+ regfree (&m_pattern);
}
int
diff --git a/gdb/gdb_regex.h b/gdb/gdb_regex.h
index 311cb3fd89d..1a1d3d1b378 100644
--- a/gdb/gdb_regex.h
+++ b/gdb/gdb_regex.h
@@ -45,6 +45,12 @@ class compiled_regex
DISABLE_COPY_AND_ASSIGN (compiled_regex);
+ explicit compiled_regex (compiled_regex &&other)
+ : m_pattern (other.m_pattern)
+ {
+ other.m_owned = false;
+ }
+
/* Wrapper around ::regexec. */
int exec (const char *string,
size_t nmatch, regmatch_t pmatch[],
@@ -56,6 +62,8 @@ class compiled_regex
int range, struct re_registers *regs);
private:
+ bool m_owned = true;
+
/* The compiled pattern. */
regex_t m_pattern;
};
diff --git a/gdb/symtab.h b/gdb/symtab.h
index dd67f864f3e..49a880dcdf2 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -120,10 +120,17 @@ class ada_lookup_name_info final
bool verbatim_p () const
{ return m_verbatim_p; }
+ compiled_regex &match_regex () const;
+
private:
/* The Ada-encoded lookup name. */
std::string m_encoded_name;
+ /* A regular expression that matches the full name of a symbol.
+ This is lazily constructed and only used when doing full
+ matches. */
+ mutable gdb::optional<compiled_regex> m_full_regex;
+
/* Whether the user-provided lookup name was Ada encoded. If so,
then return encoded names in the 'matches' method's 'completion
match result' output. */
diff --git a/gdb/testsuite/gdb.ada/nested.exp b/gdb/testsuite/gdb.ada/nested.exp
index ea4bb4de355..ca146f95786 100644
--- a/gdb/testsuite/gdb.ada/nested.exp
+++ b/gdb/testsuite/gdb.ada/nested.exp
@@ -34,3 +34,10 @@ gdb_test "break first" \
"Breakpoint $any_nb at $any_addr: file .*hello.adb, line $any_nb." \
"break on nested function First"
+gdb_test "break fourth" \
+ "Breakpoint $any_nb at $any_addr: file .*hello.adb, line $any_nb." \
+ "break on nested function fourth"
+
+gdb_test "break hello.fourth" \
+ "Breakpoint $any_nb at $any_addr: file .*hello.adb, line $any_nb." \
+ "full-qualified break on nested function fourth"
diff --git a/gdb/testsuite/gdb.ada/nested/hello.adb b/gdb/testsuite/gdb.ada/nested/hello.adb
index 2d1e532e47d..d335ee43fc3 100644
--- a/gdb/testsuite/gdb.ada/nested/hello.adb
+++ b/gdb/testsuite/gdb.ada/nested/hello.adb
@@ -31,6 +31,12 @@ procedure Hello is
end Third;
begin
- Third;
+ declare
+ procedure Fourth is
+ begin
+ Third;
+ end Fourth;
+ begin
+ Fourth;
+ end;
end Hello;
-
--
2.26.2
More information about the Gdb-patches
mailing list