aboutsummaryrefslogtreecommitdiff
path: root/gdb/utils.c
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2017-11-29 19:33:24 +0000
committerPedro Alves <palves@redhat.com>2017-11-29 19:46:41 +0000
commitbd69330db86b2367aac8aac5915f1686451c9d5d (patch)
treeb5eb5bd097e439561f74f8d2bf440a99104c0ce9 /gdb/utils.c
parenta20714ff39f621961151d0c204e89062ab2107eb (diff)
downloadgdb-bd69330db86b2367aac8aac5915f1686451c9d5d.zip
gdb-bd69330db86b2367aac8aac5915f1686451c9d5d.tar.gz
gdb-bd69330db86b2367aac8aac5915f1686451c9d5d.tar.bz2
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/utils.c')
-rw-r--r--gdb/utils.c96
1 files changed, 94 insertions, 2 deletions
diff --git a/gdb/utils.c b/gdb/utils.c
index 3e817ed..98ef6ac 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -2247,12 +2247,40 @@ cp_is_operator (const char *string, const char *start)
&& !valid_identifier_name_char (string[CP_OPERATOR_LEN]));
}
+/* If *NAME points at an ABI tag, skip it and return true. Otherwise
+ leave *NAME unmodified and return false. (see GCC's abi_tag
+ attribute), such names are demangled as e.g.,
+ "function[abi:cxx11]()". */
+
+static bool
+skip_abi_tag (const char **name)
+{
+ const char *p = *name;
+
+ if (startswith (p, "[abi:"))
+ {
+ p += 5;
+
+ while (valid_identifier_name_char (*p))
+ p++;
+
+ if (*p == ']')
+ {
+ p++;
+ *name = p;
+ return true;
+ }
+ }
+ return false;
+}
+
/* See utils.h. */
int
strncmp_iw_with_mode (const char *string1, const char *string2,
size_t string2_len, strncmp_iw_mode mode,
- enum language language)
+ enum language language,
+ completion_match_for_lcd *match_for_lcd)
{
const char *string1_start = string1;
const char *end_str2 = string2 + string2_len;
@@ -2271,6 +2299,37 @@ strncmp_iw_with_mode (const char *string1, const char *string2,
skip_spaces = false;
}
+ /* Skip [abi:cxx11] tags in the symbol name if the lookup name
+ doesn't include them. E.g.:
+
+ string1: function[abi:cxx1](int)
+ string2: function
+
+ string1: function[abi:cxx1](int)
+ string2: function(int)
+
+ string1: Struct[abi:cxx1]::function()
+ string2: Struct::function()
+
+ string1: function(Struct[abi:cxx1], int)
+ string2: function(Struct, int)
+ */
+ if (string2 == end_str2
+ || (*string2 != '[' && !valid_identifier_name_char (*string2)))
+ {
+ const char *abi_start = string1;
+
+ /* There can be more than one tag. */
+ while (*string1 == '[' && skip_abi_tag (&string1))
+ ;
+
+ if (match_for_lcd != NULL && abi_start != string1)
+ match_for_lcd->mark_ignored_range (abi_start, string1);
+
+ while (isspace (*string1))
+ string1++;
+ }
+
if (*string1 == '\0' || string2 == end_str2)
break;
@@ -2405,7 +2464,40 @@ strncmp_iw_with_mode (const char *string1, const char *string2,
if (string2 == end_str2)
{
if (mode == strncmp_iw_mode::NORMAL)
- return 0;
+ {
+ /* Strip abi tag markers from the matched symbol name.
+ Usually the ABI marker will be found on function name
+ (automatically added because the function returns an
+ object marked with an ABI tag). However, it's also
+ possible to see a marker in one of the function
+ parameters, for example.
+
+ string2 (lookup name):
+ func
+ symbol name:
+ function(some_struct[abi:cxx11], int)
+
+ and for completion LCD computation we want to say that
+ the match was for:
+ function(some_struct, int)
+ */
+ if (match_for_lcd != NULL)
+ {
+ while ((string1 = strstr (string1, "[abi:")) != NULL)
+ {
+ const char *abi_start = string1;
+
+ /* There can be more than one tag. */
+ while (skip_abi_tag (&string1) && *string1 == '[')
+ ;
+
+ if (abi_start != string1)
+ match_for_lcd->mark_ignored_range (abi_start, string1);
+ }
+ }
+
+ return 0;
+ }
else
return (*string1 != '\0' && *string1 != '(');
}