python: Add qualified parameter to gdb.Breakpoint

This patch adds the possibility to pass a qualified=True|False parameter
when creating a breakpoint in Python.  It is equivalent to using
-qualified in a linespec.  The parameter actually accepts any Python
value, and converts it to boolean using Python's standard rules for
that (https://docs.python.org/3/library/stdtypes.html#truth).

Unlike the -source/-line/-function/-label parameters, it is possible to
use -qualified with a "normal" (non-explicit) linespec.  Therefore, it
is possible (unlike these other parameters) to use this new parameter
along with the spec parameter.

I updated the py-breakpoint.exp test.  To be able to test multiple
locations using a namespace, I had to switch the test case to compile as
C++.  If we really wanted to, we could run it as both C and C++, but
omit the C++-specific parts when running it as C.

gdb/ChangeLog:

	* location.h (string_to_event_location): Add match_type
	parameter.
	* location.c (string_to_event_location): Likewise.
	* python/py-breakpoint.c (bppy_init): Handle qualified
	parameter.

gdb/doc/ChangeLog:

	* python.texi (Manipulating breakpoints using Python): Document
	qualified parameter to gdb.Breakpoint.

gdb/testsuite/ChangeLog:

	* gdb.python/py-breakpoint.c (foo_ns::multiply): New function.
	* gdb.python/py-breakpoint.exp: Compile the test case as c++,
	call test_bkpt_qualified.
	(test_bkpt_qualified): New proc.
This commit is contained in:
Simon Marchi
2017-12-13 11:37:09 -05:00
parent 6892d2e4df
commit b89641bab5
10 changed files with 138 additions and 15 deletions

View File

@ -1,3 +1,11 @@
2017-12-13 Simon Marchi <simon.marchi@ericsson.com>
* location.h (string_to_event_location): Add match_type
parameter.
* location.c (string_to_event_location): Likewise.
* python/py-breakpoint.c (bppy_init): Handle qualified
parameter.
2017-12-13 Pedro Alves <palves@redhat.com> 2017-12-13 Pedro Alves <palves@redhat.com>
* completer.c (completion_tracker::maybe_add_completion): New * completer.c (completion_tracker::maybe_add_completion): New

View File

@ -81,7 +81,9 @@
GDB interpret the specified function name as a complete GDB interpret the specified function name as a complete
fully-qualified name instead. For example, using the same C++ fully-qualified name instead. For example, using the same C++
program, the "break -q B::func" command sets a breakpoint on program, the "break -q B::func" command sets a breakpoint on
"B::func", only. "B::func", only. A parameter has been added to the Python
gdb.Breakpoint constructor to achieve the same result when creating
a breakpoint from Python.
* Breakpoints on functions marked with C++ ABI tags * Breakpoints on functions marked with C++ ABI tags

View File

@ -1,3 +1,8 @@
2017-12-13 Simon Marchi <simon.marchi@ericsson.com>
* python.texi (Manipulating breakpoints using Python): Document
qualified parameter to gdb.Breakpoint.
2017-12-13 Simon Marchi <simon.marchi@ericsson.com> 2017-12-13 Simon Marchi <simon.marchi@ericsson.com>
* python.texi (Manipulating breakpoints using Python): Split doc * python.texi (Manipulating breakpoints using Python): Split doc

View File

@ -4887,7 +4887,7 @@ create both breakpoints and watchpoints. The second accepts separate Python
arguments similar to @ref{Explicit Locations}, and can only be used to create arguments similar to @ref{Explicit Locations}, and can only be used to create
breakpoints. breakpoints.
@defun Breakpoint.__init__ (spec @r{[}, type @r{][}, wp_class @r{][}, internal @r{][}, temporary @r{]}) @defun Breakpoint.__init__ (spec @r{[}, type @r{][}, wp_class @r{][}, internal @r{][}, temporary @r{][}, qualified @r{]})
Create a new breakpoint according to @var{spec}, which is a string naming the Create a new breakpoint according to @var{spec}, which is a string naming the
location of a breakpoint, or an expression that defines a watchpoint. The location of a breakpoint, or an expression that defines a watchpoint. The
string should describe a location in a format recognized by the @code{break} string should describe a location in a format recognized by the @code{break}
@ -4911,15 +4911,22 @@ The optional @var{temporary} argument makes the breakpoint a temporary
breakpoint. Temporary breakpoints are deleted after they have been hit. Any breakpoint. Temporary breakpoints are deleted after they have been hit. Any
further access to the Python breakpoint after it has been hit will result in a further access to the Python breakpoint after it has been hit will result in a
runtime error (as that breakpoint has now been automatically deleted). runtime error (as that breakpoint has now been automatically deleted).
The optional @var{qualified} argument is a boolean that allows interpreting
the function passed in @code{spec} as a fully-qualified name. It is equivalent
to @code{break}'s @code{-qualified} flag (@pxref{Linespec Locations} and
@ref{Explicit Locations}).
@end defun @end defun
@defun Breakpoint.__init__ (@r{[} source @r{][}, function @r{][}, label @r{][}, line @r{]}, @r{][} internal @r{][}, temporary @r{]}) @defun Breakpoint.__init__ (@r{[} source @r{][}, function @r{][}, label @r{][}, line @r{]}, @r{][} internal @r{][}, temporary @r{][}, qualified @r{]})
This second form of creating a new breakpoint specifies the explicit This second form of creating a new breakpoint specifies the explicit
location (@pxref{Explicit Locations}) using keywords. The new breakpoint will location (@pxref{Explicit Locations}) using keywords. The new breakpoint will
be created in the specified source file @var{source}, at the specified be created in the specified source file @var{source}, at the specified
@var{function}, @var{label} and @var{line}. @var{function}, @var{label} and @var{line}.
@var{internal} and @var{temporary} have the same usage as explained previously. @var{internal}, @var{temporary} and @var{qualified} have the same usage as
explained previously.
@end defun @end defun
The available types are represented by constants defined in the @code{gdb} The available types are represented by constants defined in the @code{gdb}

View File

@ -915,10 +915,10 @@ string_to_event_location_basic (const char **stringp,
event_location_up event_location_up
string_to_event_location (const char **stringp, string_to_event_location (const char **stringp,
const struct language_defn *language) const struct language_defn *language,
symbol_name_match_type match_type)
{ {
const char *arg, *orig; const char *arg, *orig;
symbol_name_match_type match_type = symbol_name_match_type::WILD;
/* Try an explicit location. */ /* Try an explicit location. */
orig = arg = *stringp; orig = arg = *stringp;

View File

@ -220,11 +220,14 @@ extern event_location_up
This function is intended to be used by CLI commands and will parse This function is intended to be used by CLI commands and will parse
explicit locations in a CLI-centric way. Other interfaces should use explicit locations in a CLI-centric way. Other interfaces should use
string_to_event_location_basic if they want to maintain support for string_to_event_location_basic if they want to maintain support for
legacy specifications of probe, address, and linespec locations. */ legacy specifications of probe, address, and linespec locations.
extern event_location_up MATCH_TYPE should be either WILD or FULL. If -q/--qualified is specified
string_to_event_location (const char **argp, in the input string, it will take precedence over this parameter. */
const struct language_defn *langauge);
extern event_location_up string_to_event_location
(const char **argp, const struct language_defn *langauge,
symbol_name_match_type match_type = symbol_name_match_type::WILD);
/* Like string_to_event_location, but does not attempt to parse /* Like string_to_event_location, but does not attempt to parse
explicit locations. MATCH_TYPE indicates how function names should explicit locations. MATCH_TYPE indicates how function names should

View File

@ -694,7 +694,7 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
{ {
static const char *keywords[] = { "spec", "type", "wp_class", "internal", static const char *keywords[] = { "spec", "type", "wp_class", "internal",
"temporary","source", "function", "temporary","source", "function",
"label", "line", NULL }; "label", "line", "qualified", NULL };
const char *spec = NULL; const char *spec = NULL;
enum bptype type = bp_breakpoint; enum bptype type = bp_breakpoint;
int access_type = hw_write; int access_type = hw_write;
@ -707,12 +707,14 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
char *label = NULL; char *label = NULL;
char *source = NULL; char *source = NULL;
char *function = NULL; char *function = NULL;
int qualified = 0;
if (!gdb_PyArg_ParseTupleAndKeywords (args, kwargs, "|siiOOsssO", keywords, if (!gdb_PyArg_ParseTupleAndKeywords (args, kwargs, "|siiOOsssOp", keywords,
&spec, &type, &access_type, &spec, &type, &access_type,
&internal, &internal,
&temporary, &source, &temporary, &source,
&function, &label, &lineobj)) &function, &label, &lineobj,
&qualified))
return -1; return -1;
@ -759,6 +761,10 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
case bp_breakpoint: case bp_breakpoint:
{ {
event_location_up location; event_location_up location;
symbol_name_match_type func_name_match_type
= (qualified
? symbol_name_match_type::FULL
: symbol_name_match_type::WILD);
if (spec != NULL) if (spec != NULL)
{ {
@ -767,7 +773,8 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
const char *copy = copy_holder.get (); const char *copy = copy_holder.get ();
location = string_to_event_location (&copy, location = string_to_event_location (&copy,
current_language); current_language,
func_name_match_type);
} }
else else
{ {
@ -782,6 +789,8 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
explicit_loc.line_offset = explicit_loc.line_offset =
linespec_parse_line_offset (line.get ()); linespec_parse_line_offset (line.get ());
explicit_loc.func_name_match_type = func_name_match_type;
location = new_explicit_location (&explicit_loc); location = new_explicit_location (&explicit_loc);
} }

View File

@ -1,3 +1,10 @@
2017-12-13 Simon Marchi <simon.marchi@ericsson.com>
* gdb.python/py-breakpoint.c (foo_ns::multiply): New function.
* gdb.python/py-breakpoint.exp: Compile the test case as c++,
call test_bkpt_qualified.
(test_bkpt_qualified): New proc.
2017-12-13 Pedro Alves <palves@redhat.com> 2017-12-13 Pedro Alves <palves@redhat.com>
* lib/completion-support.exp (test_gdb_complete_tab_multiple): * lib/completion-support.exp (test_gdb_complete_tab_multiple):

View File

@ -17,6 +17,14 @@
int result = 0; int result = 0;
namespace foo_ns
{
int multiply (int i)
{
return i * i;
}
}
int multiply (int i) int multiply (int i)
{ {
return i * i; return i * i;

View File

@ -20,7 +20,9 @@ load_lib gdb-python.exp
standard_testfile standard_testfile
if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } { set options {debug c++}
if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} ${options}] } {
return -1 return -1
} }
@ -608,6 +610,77 @@ proc_with_prefix test_bkpt_explicit_loc {} {
"set invalid explicit breakpoint by missing function" "set invalid explicit breakpoint by missing function"
} }
proc_with_prefix test_bkpt_qualified {} {
global decimal hex testfile
# Start with a fresh gdb.
clean_restart ${testfile}
set one_location_re "Breakpoint $decimal at $hex:.*line $decimal."
set two_location_re "Breakpoint $decimal at $hex:.*2 locations."
if ![runto_main] then {
fail "cannot run to main."
return 0
}
# Test the default value of "qualified".
delete_breakpoints
gdb_test \
"python gdb.Breakpoint(\"multiply\")" \
$two_location_re \
"qualified implicitly false"
# Test qualified=False.
delete_breakpoints
gdb_test \
"python gdb.Breakpoint(\"multiply\", qualified=False)" \
$two_location_re \
"qualified false"
# Test qualified=True.
delete_breakpoints
gdb_test \
"python gdb.Breakpoint(\"multiply\", qualified=True)" \
$one_location_re \
"qualified true"
# Test qualified=True with an explicit function.
delete_breakpoints
gdb_test \
"python gdb.Breakpoint(function=\"multiply\", qualified=True)" \
$one_location_re \
"qualified true and explicit"
# Test qualified=False with an explicit function.
delete_breakpoints
gdb_test \
"python gdb.Breakpoint(function=\"multiply\", qualified=False)" \
$two_location_re \
"qualified false and explicit"
# Test -q in the spec string.
delete_breakpoints
gdb_test \
"python gdb.Breakpoint(\"-q multiply\")" \
$one_location_re \
"-q in spec string"
# Test -q in the spec string with explicit location.
delete_breakpoints
gdb_test \
"python gdb.Breakpoint(\"-q -function multiply\")" \
$one_location_re \
"-q in spec string with explicit location"
# Test -q in the spec string and qualified=False (-q should win).
delete_breakpoints
gdb_test \
"python gdb.Breakpoint(\"-q multiply\", qualified=False)" \
$one_location_re \
"-q in spec string and qualified false"
}
test_bkpt_basic test_bkpt_basic
test_bkpt_deletion test_bkpt_deletion
test_bkpt_cond_and_cmds test_bkpt_cond_and_cmds
@ -620,3 +693,4 @@ test_bkpt_address
test_bkpt_pending test_bkpt_pending
test_bkpt_events test_bkpt_events
test_bkpt_explicit_loc test_bkpt_explicit_loc
test_bkpt_qualified