diff options
author | Pedro Alves <palves@redhat.com> | 2017-11-29 19:33:24 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2017-11-29 19:46:41 +0000 |
commit | bd69330db86b2367aac8aac5915f1686451c9d5d (patch) | |
tree | b5eb5bd097e439561f74f8d2bf440a99104c0ce9 /gdb/cp-support.c | |
parent | a20714ff39f621961151d0c204e89062ab2107eb (diff) | |
download | binutils-gdb-bd69330db86b2367aac8aac5915f1686451c9d5d.tar.gz |
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<TAB>" -> "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<TAB>" -> "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 <palves@redhat.com>
PR c++/19436
* NEWS: Mention setting breakpoints on functions with C++ ABI
tags.
* completer.h (completion_match_for_lcd) <match,
mark_ignored_range>: New methods.
<finish>: Consider ignored ranges.
<clear>: Clear ignored ranges.
<m_ignored_ranges, m_finished_storage>: 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 <palves@redhat.com>
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 <palves@redhat.com>
PR c++/19436
* gdb.texinfo (Debugging C Plus Plus): Document setting
breakpoints in functions with ABI tags.
Diffstat (limited to 'gdb/cp-support.c')
-rw-r--r-- | gdb/cp-support.c | 53 |
1 files changed, 49 insertions, 4 deletions
diff --git a/gdb/cp-support.c b/gdb/cp-support.c index 172d8219f47..34a84395f40 100644 --- a/gdb/cp-support.c +++ b/gdb/cp-support.c @@ -1629,7 +1629,23 @@ cp_search_name_hash (const char *search_name) if (prefix_len != 0) search_name += prefix_len + 2; - return default_search_name_hash (search_name); + unsigned int hash = 0; + for (const char *string = search_name; *string != '\0'; ++string) + { + string = skip_spaces (string); + + if (*string == '(') + break; + + /* Ignore ABI tags such as "[abi:cxx11]. */ + if (*string == '[' + && startswith (string + 1, "abi:") + && string[5] != ':') + break; + + hash = SYMBOL_HASH_NEXT (hash, *string); + } + return hash; } /* Helper for cp_symbol_name_matches (i.e., symbol_name_matcher_ftype @@ -1674,11 +1690,13 @@ cp_symbol_name_matches_1 (const char *symbol_search_name, completion_match_result *comp_match_res) { const char *sname = symbol_search_name; + completion_match_for_lcd *match_for_lcd + = (comp_match_res != NULL ? &comp_match_res->match_for_lcd : NULL); while (true) { if (strncmp_iw_with_mode (sname, lookup_name, lookup_name_len, - mode, language_cplus) == 0) + mode, language_cplus, match_for_lcd) == 0) { if (comp_match_res != NULL) { @@ -1728,14 +1746,15 @@ cp_fq_symbol_name_matches (const char *symbol_search_name, { /* Get the demangled name. */ const std::string &name = lookup_name.cplus ().lookup_name (); - + completion_match_for_lcd *match_for_lcd + = (comp_match_res != NULL ? &comp_match_res->match_for_lcd : NULL); strncmp_iw_mode mode = (lookup_name.completion_mode () ? strncmp_iw_mode::NORMAL : strncmp_iw_mode::MATCH_PARAMS); if (strncmp_iw_with_mode (symbol_search_name, name.c_str (), name.size (), - mode, language_cplus) == 0) + mode, language_cplus, match_for_lcd) == 0) { if (comp_match_res != NULL) comp_match_res->set_match (symbol_search_name); @@ -1950,6 +1969,32 @@ test_cp_symbol_name_matches () CHECK_NOT_MATCH_C ("foo::function()", "::function()"); CHECK_NOT_MATCH_C ("foo::function(int)", "::function()"); CHECK_NOT_MATCH_C ("foo::function(int)", "::function(int)"); + + /* Test ABI tag matching/ignoring. */ + + /* If the symbol name has an ABI tag, but the lookup name doesn't, + then the ABI tag in the symbol name is ignored. */ + CHECK_MATCH_C ("function[abi:foo]()", "function"); + CHECK_MATCH_C ("function[abi:foo](int)", "function"); + CHECK_MATCH_C ("function[abi:foo]()", "function ()"); + CHECK_NOT_MATCH_C ("function[abi:foo]()", "function (int)"); + + CHECK_MATCH_C ("function[abi:foo]()", "function[abi:foo]"); + CHECK_MATCH_C ("function[abi:foo](int)", "function[abi:foo]"); + CHECK_MATCH_C ("function[abi:foo]()", "function[abi:foo] ()"); + CHECK_MATCH_C ("function[abi:foo][abi:bar]()", "function"); + CHECK_MATCH_C ("function[abi:foo][abi:bar](int)", "function"); + CHECK_MATCH_C ("function[abi:foo][abi:bar]()", "function[abi:foo]"); + CHECK_MATCH_C ("function[abi:foo][abi:bar](int)", "function[abi:foo]"); + CHECK_MATCH_C ("function[abi:foo][abi:bar]()", "function[abi:foo] ()"); + CHECK_NOT_MATCH_C ("function[abi:foo][abi:bar]()", "function[abi:foo] (int)"); + + CHECK_MATCH_C ("function [abi:foo][abi:bar] ( )", "function [abi:foo]"); + + /* If the symbol name does not have an ABI tag, while the lookup + name has one, then there's no match. */ + CHECK_NOT_MATCH_C ("function()", "function[abi:foo]()"); + CHECK_NOT_MATCH_C ("function()", "function[abi:foo]"); } /* If non-NULL, return STR wrapped in quotes. Otherwise, return a |