From bd69330db86b2367aac8aac5915f1686451c9d5d Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Wed, 29 Nov 2017 19:33:24 +0000 Subject: Breakpoints in symbols with ABI tags (PR c++/19436) Trying to set a breakpoint in a function with an ABI tag does not work currently. E.g., debugging gdb itself, we see this with the "string_printf" function: (top-gdb) b string_print [TAB] (top-gdb) b string_printf[abi:cxx11](char const*, ...) [RET] No source file named string_printf[abi. Make breakpoint pending on future shared library load? (y or [n]) Quoting doesn't help: (top-gdb) b 'string_printf[abi:cxx11]'(char const*, ...) malformed linespec error: unexpected string, "(char const*, ...)" (top-gdb) b 'string_printf[abi:cxx11](char const*, ...)' No source file named string_printf[abi. Make breakpoint pending on future shared library load? (y or [n]) n This patch fixes this, and takes it a bit further. The actual symbol name as demangled by libiberty's demangler is really string_printf[abi:cxx11](char const*, ...) however, this patch makes it possible to set the breakpoint with string_printf(char const*, ...) too. I.e., ignoring the ABI tag. And to match, it teaches the completer to complete the symbol name without the ABI tag, i.e., "string_pri" -> "string_printf(char const*, ...)" If however, you really want to break on a symbol with the tag, then you simply start writing the tag, and GDB will preserve it, like: "string_printf[a" -> "string_printf[abi:cxx11](char const*, ...)" Grows the gdb.linespec/ tests like this: -# of expected passes 8977 +# of expected passes 9176 gdb/ChangeLog: 2017-11-29 Pedro Alves PR c++/19436 * NEWS: Mention setting breakpoints on functions with C++ ABI tags. * completer.h (completion_match_for_lcd) : New methods. : Consider ignored ranges. : Clear ignored ranges. : New fields. * cp-support.c (cp_search_name_hash): Ignore ABI tags. (cp_symbol_name_matches_1, cp_fq_symbol_name_matches): Pass the completion_match_for_lcd pointer to strncmp_iw_with_mode. (test_cp_symbol_name_cmp): Add [abi:...] tags unit tests. * language.c (default_symbol_name_matcher): Pass the completion_match_for_lcd pointer to strncmp_iw_with_mode. * linespec.c (linespec_lexer_lex_string): Don't tokenize ABI tags. * utils.c (skip_abi_tag): New function. (strncmp_iw_with_mode): Add completion_match_for_lcd parameter. Handle ABI tags. * utils.h (strncmp_iw_with_mode): Add completion_match_for_lcd parameter. gdb/testsuite/ChangeLog: 2017-11-29 Pedro Alves PR c++/19436 * gdb.linespec/cpls-abi-tag.cc: New file. * gdb.linespec/cpls-abi-tag.exp: New file. gdb/doc/ChangeLog: 2017-11-29 Pedro Alves PR c++/19436 * gdb.texinfo (Debugging C Plus Plus): Document setting breakpoints in functions with ABI tags. --- gdb/completer.h | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 4 deletions(-) (limited to 'gdb/completer.h') diff --git a/gdb/completer.h b/gdb/completer.h index f756412..9ce70bf 100644 --- a/gdb/completer.h +++ b/gdb/completer.h @@ -122,28 +122,82 @@ private: "b push_ba" on a C++ program usually completes to std::vector<...>::push_back, std::string::push_back etc. In such case, the symbol comparison routine will set the LCD match to point - into the "push_back" substring within the symbol's name string. */ + into the "push_back" substring within the symbol's name string. + Also, in some cases, the symbol comparison routine will want to + ignore parts of the symbol name for LCD purposes, such as for + example symbols with abi tags in C++. In such cases, the symbol + comparison routine will set MARK_IGNORED_RANGE to mark the ignored + substrings of the matched string. The resulting LCD string with + the ignored parts stripped out is computed at the end of a + completion match sequence iff we had a positive match. */ class completion_match_for_lcd { public: + /* Get the resulting LCD, after a successful match. */ + const char *match () + { return m_match; } + /* Set the match for LCD. See m_match's description. */ void set_match (const char *match) { m_match = match; } - /* Get the resulting LCD, after a successful match. */ + /* Mark the range between [BEGIN, END) as ignored. */ + void mark_ignored_range (const char *begin, const char *end) + { m_ignored_ranges.emplace_back (begin, end); } + + /* Get the resulting LCD, after a successful match. If there are + ignored ranges, then this builds a new string with the ignored + parts removed (and stores it internally). As such, the result of + this call is only good for the current completion match + sequence. */ const char *finish () - { return m_match; } + { + if (m_ignored_ranges.empty ()) + return m_match; + else + { + m_finished_storage.clear (); + + const char *prev = m_match; + for (const auto &range : m_ignored_ranges) + { + m_finished_storage.append (prev, range.first); + prev = range.second; + } + m_finished_storage.append (prev); + + return m_finished_storage.c_str (); + } + } /* Prepare for another completion matching sequence. */ void clear () - { m_match = NULL; } + { + m_match = NULL; + m_ignored_ranges.clear (); + } private: /* The completion match result for LCD. This is usually either a pointer into to a substring within a symbol's name, or to the storage of the pairing completion_match object. */ const char *m_match; + + /* The ignored substring ranges within M_MATCH. E.g., if we were + looking for completion matches for C++ functions starting with + "functio" + and successfully match: + "function[abi:cxx11](int)" + the ignored ranges vector will contain an entry that delimits the + "[abi:cxx11]" substring, such that calling finish() results in: + "function(int)" + */ + std::vector> m_ignored_ranges; + + /* Storage used by the finish() method, if it has to compute a new + string. */ + std::string m_finished_storage; }; /* Convenience aggregate holding info returned by the symbol name -- cgit v1.1