Hello, I've included with this mail a complete patch build agains the current HEAD, and checked that there was no regression in the testsuite Kevin On Mon, May 16, 2011 at 7:23 AM, Kevin Pouget wrote: > Hello, > > I prepared some tests which show the behavior of this new Breakpoint > type in various environment: > - normal termination, forced termination (gdb return) > - longjmp > - c++ exception > - breakpoint condition > > there is two bits which differs from what I expected, in the > breakpoint conditions > > * setting a BP in a DUMMY_FRAME: the `stop' function will be triggerd, > but it's return value (stop or continue/booleans) won't be taken into > account. I'm not sure whether the kind of FinishBreakpoint should be > forbidden or not, because I may want to track ALL the calls to that > function, including GDB inferior calls > > * the "normal_stop" notification if not triggered during condition > evaluation, so the `out_of_scope_notif' flag is not turn off (more > generally, the notification should be disabled when the breakpoint is > hit, and not when GDB stops) > > > otherwise, for c++ exception, the return PC of a frame surrounded by a > try/catch is at the end of the catch, so with > try { fct_1() } catch { ... }, a FinishBreakpoint in fct_1 will be > correcty catch, but it won't work for function nested within fct_1. > > > > Does this testsuite match your expectations, or would you like it to > be more advanced? (I'll need more hints in this case) > > > cordially, > > Kevin > > > diff --git a/gdb/testsuite/gdb.python/py-finish-breakpoint-cc.cc > b/gdb/testsuite/gdb.python/py-finish-breakpoint-cc.cc > new file mode 100644 > index 0000000..a0eea06 > --- /dev/null > +++ b/gdb/testsuite/gdb.python/py-finish-breakpoint-cc.cc > @@ -0,0 +1,59 @@ > +/* This testcase is part of GDB, the GNU debugger. > + > +   Copyright 2011 Free Software Foundation, Inc. > + > +   This program is free software; you can redistribute it and/or modify > +   it under the terms of the GNU General Public License as published by > +   the Free Software Foundation; either version 3 of the License, or > +   (at your option) any later version. > + > +   This program is distributed in the hope that it will be useful, > +   but WITHOUT ANY WARRANTY; without even the implied warranty of > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the > +   GNU General Public License for more details. > + > +   You should have received a copy of the GNU General Public License > +   along with this program.  If not, see  . > +*/ > + > + > +#include > + > +void > +throw_exception_1 (int e) > +{ > +  throw new int (e); > +} > + > +void > +throw_exception (int e) > +{ > +  throw_exception_1 (e); > +} > + > +int > +main (void) > +{ > +  int i; > +  try > +    { > +      throw_exception_1 (10); > +    } > +  catch (const int *e) > +    { > +        std::cerr << "Exception #" << *e << std::endl; > +    } > +  i += 1; /* Break after exception 1.  */ > + > +  try > +    { > +      throw_exception (10); > +    } > +  catch (const int *e) > +    { > +        std::cerr << "Exception #" << *e << std::endl; > +    } > +  i += 1; /* Break after exception 2.  */ > + > +  return i; > +} > diff --git a/gdb/testsuite/gdb.python/py-finish-breakpoint-cc.exp > b/gdb/testsuite/gdb.python/py-finish-breakpoint-cc.exp > new file mode 100644 > index 0000000..e74023d > --- /dev/null > +++ b/gdb/testsuite/gdb.python/py-finish-breakpoint-cc.exp > @@ -0,0 +1,59 @@ > +# Copyright (C) 2011 Free Software Foundation, Inc. > +# > +# This program is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License as published by > +# the Free Software Foundation; either version 3 of the License, or > +# (at your option) any later version. > +# > +# This program is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program.  If not, see . > + > +# This file is part of the GDB testsuite.  It tests the mechanism > +# exposing values to Python. > + > +if $tracelevel then { > +    strace $tracelevel > +} > + > +load_lib gdb-python.exp > + > +set testfile "py-finish-breakpoint-cc" > +set srcfile ${testfile}.cc > +set binfile ${objdir}/${subdir}/${testfile} > +set pyfile  ${srcdir}/${subdir}/${testfile}.py > + > +# Start with a fresh gdb. > +gdb_exit > +gdb_start > +gdb_reinitialize_dir $srcdir/$subdir > +gdb_load ${binfile} > + > +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" > executable {debug c++}] != "" } { > +    untested "Couldn't compile ${srcfile}" > +    return -1 > +} > + > +if ![runto_main] then { > +    fail "Cannot run to main." > +    return 0 > +} > + > +gdb_test "source $pyfile" ".*Python script imported.*" \ > +         "import python scripts" > + > +gdb_test "break [gdb_get_line_number "Break after exception 1."]" > "Breakpoint.* at .*" \ > +         "set watchdog after the exception 1" > +gdb_test "break [gdb_get_line_number "Break after exception 2."]" > "Breakpoint.* at .*" \ > +         "set watchdog after the exception 2" > + > +gdb_test "python ExceptionBreakpoint()" "ExceptionBreakpoint init" > "set BP before throwing the exception" > +gdb_test "python print len(gdb.breakpoints())" "4" "check number of BPs" > +gdb_test "continue" ".*stopped at ExceptionFinishBreakpoint.*" "check > FinishBreakpoint in catch()" > +gdb_test "python print len(gdb.breakpoints())" "4" "check finish BP removal" > + > +gdb_test "continue" ".*exception did not finish.*" "FinishBreakpoint > with exception thrown not caught" > diff --git a/gdb/testsuite/gdb.python/py-finish-breakpoint-cc.py > b/gdb/testsuite/gdb.python/py-finish-breakpoint-cc.py > new file mode 100644 > index 0000000..d0dfe2f > --- /dev/null > +++ b/gdb/testsuite/gdb.python/py-finish-breakpoint-cc.py > @@ -0,0 +1,43 @@ > +# Copyright (C) 2011 Free Software Foundation, Inc. > + > +# This program is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License as published by > +# the Free Software Foundation; either version 3 of the License, or > +# (at your option) any later version. > +# > +# This program is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program.  If not, see . > + > +# This file is part of the GDB testsuite.  It tests python Finish > +# Breakpoints. > + > +class ExceptionBreakpoint(gdb.Breakpoint): > +    def __init__(self): > +        gdb.Breakpoint.__init__(self, spec="throw_exception_1", internal=1) > +        self.silent = True > +        print "ExceptionBreakpoint init" > + > +    def stop(self): > +        ExceptionFinishBreakpoint(gdb.newest_frame()) > +        return False > + > +class ExceptionFinishBreakpoint(gdb.FinishBreakpoint): > +    def __init__(self, frame): > +        gdb.FinishBreakpoint.__init__(self, frame, internal=1) > +        self.silent = True; > + > +    def stop(self): > +       print "stopped at ExceptionFinishBreakpoint" > +       gdb.post_event(self.delete) > +        return True > + > +    def out_of_scope(self): > +        print "exception did not finish ..." > + > + > +print "Python script imported" > diff --git a/gdb/testsuite/gdb.python/py-finish-breakpoint.c > b/gdb/testsuite/gdb.python/py-finish-breakpoint.c > new file mode 100644 > index 0000000..32b8b38 > --- /dev/null > +++ b/gdb/testsuite/gdb.python/py-finish-breakpoint.c > @@ -0,0 +1,82 @@ > +/* This testcase is part of GDB, the GNU debugger. > + > +   Copyright 2011 Free Software Foundation, Inc. > + > +   This program is free software; you can redistribute it and/or modify > +   it under the terms of the GNU General Public License as published by > +   the Free Software Foundation; either version 3 of the License, or > +   (at your option) any later version. > + > +   This program is distributed in the hope that it will be useful, > +   but WITHOUT ANY WARRANTY; without even the implied warranty of > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the > +   GNU General Public License for more details. > + > +   You should have received a copy of the GNU General Public License > +   along with this program.  If not, see  . > +*/ > +#include > + > +int increase_1(int *a) > +{ > +  *a += 1; > +  return -5; > +} > + > +void increase(int *a) > +{ > +  increase_1(a); > +} > + > +int > +test_1(int i, int j) > +{ > +  return i == j; > +} > + > +int > +test(int i, int j) > +{ > +  return test_1(i, j); > +} > + > +int > +call_longjmp_1 (jmp_buf *buf) > +{ > +  longjmp (*buf, 1); > +} > + > +int > +call_longjmp (jmp_buf *buf) > +{ > +  call_longjmp_1 (buf); > +} > + > + > +int main (int argc, char *argv[]) > +{ > +  jmp_buf env; > +  int foo = 5; > +  int bar = 42; > +  int i, j; > + > +  i = 0 ; > +  /* Break at increase. */ > +  increase (&i) ; > +  increase (&i) ; > +  increase (&i) ; > + > +  for (i = 0; i < 10; i++) > +    { > +      j += 1; /* Condition Break. */ > +    } > + > +  if (setjmp (env) == 0) /* longjmp caught */ > +    { > +      call_longjmp (&env); > +    } > +  else > +         j += 1; /* after longjmp. */ > + > +  return j; /* Break at end. */ > +} > diff --git a/gdb/testsuite/gdb.python/py-finish-breakpoint.exp > b/gdb/testsuite/gdb.python/py-finish-breakpoint.exp > new file mode 100644 > index 0000000..65eebc9 > --- /dev/null > +++ b/gdb/testsuite/gdb.python/py-finish-breakpoint.exp > @@ -0,0 +1,183 @@ > +# Copyright (C) 2011 Free Software Foundation, Inc. > +# > +# This program is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License as published by > +# the Free Software Foundation; either version 3 of the License, or > +# (at your option) any later version. > +# > +# This program is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program.  If not, see . > + > +# This file is part of the GDB testsuite.  It tests the mechanism > +# exposing values to Python. > + > +if $tracelevel then { > +    strace $tracelevel > +} > + > +load_lib gdb-python.exp > + > +set testfile "py-finish-breakpoint" > +set srcfile ${testfile}.c > + > +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } { > +    return -1 > +} > + > +set remote_python_file [remote_download host > ${srcdir}/${subdir}/${testfile}.py] > + > + > +# Skip all tests if Python scripting is not enabled. > +if { [skip_python_tests] } { continue } > + > +# > +# Test FinishBreakpoint in function returned by longjmp > +# > + > +clean_restart ${testfile} > + > +if ![runto call_longjmp_1] then { > +    perror "couldn't run to breakpoint call_longjmp" > +    continue > +} > + > +gdb_test "source $remote_python_file" ".*Python script imported.*" \ > +         "import python scripts" > + > +gdb_test "python ljmpBP = LongjmpFinishBreakpoint(gdb.newest_frame())" \ > +         "LongjmpFinishBreakpoint init" \ > +         "set finish breakpoint" > +gdb_test "break [gdb_get_line_number "after longjmp."]" "Breakpoint.* at .*" \ > +         "set BP after the jump" > +gdb_test "continue" ".*Longjmp didn't finish.*" "check FinishBP out > of scope notification" > + > +# > +# Test FinishBreakpoint in BP condition evaluation > +# (finish in dummy frame) > +# > + > +clean_restart ${testfile} > + > +set cond_line [gdb_get_line_number "Condition Break."] > +if ![runto_main] then { > +    fail "Cannot run to main." > +    return 0 > +} > + > +gdb_test "source $remote_python_file" ".*Python script imported.*" \ > +         "import python scripts" > + > +gdb_test "break ${cond_line} if test_1(i,8)" ".*Breakpoint .* at .*" > "set conditional BP" > +gdb_test "python TestBreakpoint()" "TestBreakpoint init" "set BP in condition" > + > + > +set msg "check FinishBreakpoint don't stop in GDB Dummy Frame" > +gdb_test_multiple "continue" $msg { > +       -re ".*test don't stop 2.*test stop.*test don't stop 4.*" { > +               pass $msg > +       } > +       -re ".*test don't stop 2.*test stop.*$gdb_prompt" { > +               fail $msg > +       } > +} > + > +gdb_test "print i" "8" "check stopped location" > + > +# > +# Test FinishBreakpoint in BP condition evaluation > +# (finish in normal frame) > +# > + > +clean_restart ${testfile} > + > +gdb_test "source $remote_python_file" ".*Python script imported.*" \ > +         "import python scripts" > + > +if ![runto_main] then { > +    fail "Cannot run to main." > +    return 0 > +} > + > +gdb_test "break ${cond_line} if test(i,8)" ".*Breakpoint .* at .*" > "set conditional BP" > +gdb_test "python TestBreakpoint()" "TestBreakpoint init" "set BP in condition" > + > +gdb_test "continue" ".*test don't stop 1.*test don't stop 2.*test > stop.*Error in testing breakpoint condition.*The program being > debugged stopped while in a function called from GDB.*" \ > +         "stop in condition function" > + > +setup_kfail "normal_stop_notification not triggered during condition > evaluation" *-*-* > +gdb_test "python print gdb.breakpoints()\[2\].out_of_scope_notif" > ".*False.*" "check out_of_scope notification disabled" > +gdb_test_no_output "python gdb.breakpoints()\[2\].out_of_scope_notif > = False" "reestablish correct value" > + > +gdb_test "continue" "Continuing.*" "finish condition evaluation" > +gdb_test "continue" "Breakpoint.*" "stop at conditional breakpoint" > +gdb_test "print i" "8" "check stopped location" > + > +# > +# Test FinishBreakpoint in normal conditions > +# > + > +clean_restart ${testfile} > + > +if ![runto_main] then { > +    fail "Cannot run to main." > +    return 0 > +} > +gdb_test_no_output "set confirm off" "disable confirmation" > +gdb_test "source $remote_python_file" ".*Python script imported.*" \ > +         "import python scripts" > +gdb_test "python MyBreakpoint(\"increase_1\")" ".*Breakpoint 2.*" \ > +         "create Python function breakpoint" > +gdb_test "continue" ".*Arrived at MyBreakpoint with 0.*" "check > MyBreakpoint hit" > + > +# set FinishBreakpoint > + > +gdb_test "python finishbp = MyFinishBreakpoint (gdb.parse_and_eval > (\"a\"), gdb.selected_frame ())" \ > +         ".*Breakpoint 3.*" "set FinishBreakpoint" > +gdb_test "python print finishbp.out_of_scope_notif" ".*True.*" \ > +         "check out_of_scope_notif at init" > +gdb_test "python print finishbp.return_value" ".*None.*" \ > +         "check return_value at init" > + > +# check normal bp hit > + > +gdb_test "continue" ".*MyFinishBreakpoint stop with.*#0.*increase.*" \ > +         "check MyFinishBreakpoint hit" > +gdb_test "python print finishbp.return_value" ".*-5.*" "check return_value" > +gdb_test "python print finishbp.out_of_scope_notif" ".*False.*" \ > +         "check out_of_scope_notif disabled after hit" > +gdb_test "finish" ".*main.*" "return to main()" > +gdb_test "python print finishbp.return_value" ".*None.*" "check return_value" > + > +# check forced return / check out of scpop > +gdb_test_no_output "python finishbp.out_of_scope_notif = True" \ > +         "re-enable out_of_scope_notif" > + > +gdb_test "continue" ".*Arrived at MyBreakpoint with.*" "check > MyBreakpoint second hit" > +gdb_test "up" ".*increase_1.*" "go one frame up" > +gdb_test_no_output "return" "return from the frame" > +gdb_test "python print finishbp.check_scope()" ".*MyFinishBreakpoint > out of scope.*True.*" \ > +         "go one frame up" > + > +# check forced return / automatic notification > + > +gdb_test_no_output "python finishbp.out_of_scope_notif = True" \ > +         "re-enable out_of_scope_notif" > + > +gdb_test "continue" ".*Arrived at MyBreakpoint with.*" "check > MyBreakpoint third hit" > +gdb_test "up" ".*increase_1.*" "go one frame up" > +gdb_test_no_output "return" "return from the frame" > +gdb_test "next" ".*MyFinishBreakpoint out of scope.*" "check Finish > breakpoint discard" > +gdb_test "python print finishbp.out_of_scope_notif" ".*False.*" > "check out_of_scope_notif" > + > +# check FinishBreakpoint in main > + > +gdb_test "python MyFinishBreakpoint (None, gdb.selected_frame ())" \ > +         ".*ValueError: \"FinishBreakpoint\" not meaningful in the > outermost frame..*" \ > +         "check FinishBP not allowed in main" > + > + > diff --git a/gdb/testsuite/gdb.python/py-finish-breakpoint.py > b/gdb/testsuite/gdb.python/py-finish-breakpoint.py > new file mode 100644 > index 0000000..f014cc6 > --- /dev/null > +++ b/gdb/testsuite/gdb.python/py-finish-breakpoint.py > @@ -0,0 +1,85 @@ > +# Copyright (C) 2011 Free Software Foundation, Inc. > + > +# This program is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License as published by > +# the Free Software Foundation; either version 3 of the License, or > +# (at your option) any later version. > +# > +# This program is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program.  If not, see . > + > +# This file is part of the GDB testsuite.  It tests python Finish > +# Breakpoints. > + > +class MyBreakpoint(gdb.Breakpoint): > +       def stop(self): > +               val = gdb.parse_and_eval ("a") > +               print "Arrived at MyBreakpoint with %d" % int(val.dereference()) > +               return True > + > +class MyFinishBreakpoint(gdb.FinishBreakpoint): > +       def __init__(self, val, frame): > +               super (MyFinishBreakpoint, self).__init__ (frame) > +               print "MyFinishBreakpoint init" > +               self.val = val > + > +       def stop(self): > +               print "MyFinishBreakpoint stop with %d" % int(self.val.dereference()) > +               gdb.execute("where 1") > +               return True > + > +       def out_of_scope(self): > +               print "MyFinishBreakpoint out of scope..." > + > +test_finish_bp = None > +class TestBreakpoint(gdb.Breakpoint): > +    def __init__(self): > +        gdb.Breakpoint.__init__(self, spec="test_1", internal=1) > +        self.silent = True > +        self.finish = None > +        print "TestBreakpoint init" > + > +    def stop(self): > +       global test_finish_bp > +        if (self.finish == None): > +            self.finish = TestFinishBreakpoint(gdb.newest_frame()) > +            test_finish_bp = self.finish > +        return False > + > + > +class TestFinishBreakpoint(gdb.FinishBreakpoint): > +    def __init__(self, frame): > +        gdb.FinishBreakpoint.__init__(self, frame, internal=1) > +        self.count = 0 > + > +    def stop(self): > +        self.count += 1 > +        if (self.count == 3): > +            print "test stop ..." > +            return True > +        else: > +            print "test don't stop %d" % self.count > +            return False > + > + > +    def out_of_scope(self): > +        print "test didn't finish ..." > + > +class LongjmpFinishBreakpoint(gdb.FinishBreakpoint): > +       def __init__(self, frame): > +               gdb.FinishBreakpoint.__init__(self, frame, internal=1) > +               print "LongjmpFinishBreakpoint init" > + > +       def stop(self): > +               print "Stopped at LongjmpFinishBreakpoint" > + > + > +       def out_of_scope(self): > +               print "Longjmp didn't finish ..." > + > +print "Python script imported" > -- > 1.7.4.4 >