2008-05-17 Pedro Alves * longjmp.c, longjmp.exp: Add tests to test ignoring inner longjmp resumes while stepping, and update current tests. --- gdb/testsuite/gdb.base/longjmp.c | 103 ++++++++++++++++++++++++++++++++----- gdb/testsuite/gdb.base/longjmp.exp | 96 ++++++++++++++++++---------------- 2 files changed, 142 insertions(+), 57 deletions(-) Index: src/gdb/testsuite/gdb.base/longjmp.c =================================================================== --- src.orig/gdb/testsuite/gdb.base/longjmp.c 2008-05-04 20:43:31.000000000 +0100 +++ src/gdb/testsuite/gdb.base/longjmp.c 2008-05-17 02:36:56.000000000 +0100 @@ -19,6 +19,7 @@ #include jmp_buf env; +jmp_buf env2; volatile int longjmps = 0; volatile int resumes = 0; @@ -33,7 +34,7 @@ call_longjmp (jmp_buf *buf) void hidden_longjmp (void) { - if (setjmp (env) == 0) /* longjmp caught */ + if (setjmp (env) == 0) { call_longjmp (&env); } @@ -41,41 +42,117 @@ hidden_longjmp (void) resumes++; } +void +hidden_longjmp_2 (void) +{ + if (setjmp (env) == 0) + { + if (setjmp (env2) == 0) + { + longjmps++; + longjmp (env2, 1); + } + else + { + resumes++; + longjmps++; + longjmp (env, 1); + } + } + else + { + resumes++; + } +} + +void +hidden_longjmp_3_1 (void) +{ + if (setjmp (env2) == 0) + { + longjmps++; + longjmp (env2, 1); + } + else + { + resumes++; + longjmps++; + longjmp (env, 1); + } +} + +void +hidden_longjmp_3 (void) +{ + hidden_longjmp_3_1 (); +} + int main () { volatile int i = 0; /* Pattern 1 - simple longjmp. */ - if (setjmp (env) == 0) /* patt1 */ + if (setjmp (env) == 0) { longjmps++; - longjmp (env, 1); + longjmp (env, 1); /* patt1 */ } else { - resumes++; + resumes++; /* resume1 */ } - i = 1; /* miss_step_1 */ - /* Pattern 2 - longjmp from an inner function. */ - if (setjmp (env) == 0) /* patt2 */ + if (setjmp (env) == 0) { - call_longjmp (&env); + call_longjmp (&env); /* patt2 */ } else { - resumes++; + resumes++; /* resume2 */ } - i = 2; /* miss_step_2 */ - /* Pattern 3 - setjmp/longjmp inside stepped-over function. */ - hidden_longjmp (); /* patt3 */ + /* Pattern 3 - prefer longjmp resume. + + This tests if GDB chooses the longjmp-resume over the step-resume + breakpoint. If GDB chooses wrongly, a step over the + hidden_longjmp_3 function will resume the inferior and pass + straight the else clause without stopping to step. */ + if (setjmp (env) == 0) + hidden_longjmp_3 (); /* patt3 */ + else + resumes++; /* resume3 */ + + + /* Pattern 4 - prefer longjmp resume after step. + + Quite similar, but in this case, we step into hidden_longjmp_3 + before next'ing over the longjmp. In this case, the step-resume + breakpoint will be set in an inner stack. Check if GDB still + detects that the longjmp-resume address is prefered. */ + if (setjmp (env) == 0) + hidden_longjmp_3 (); /* patt4 */ + else + resumes++; /* resume4 */ + + + /* Pattern 5 - setjmp/longjmp handled inside stepped-over function. + + Test that we don't miss-handle internal setjmp/longjmp sequences. + A next over this should not stop at the longjmp resume + address. */ + hidden_longjmp (); /* patt5 */ + i = 5; /* patt_end5. */ + + + /* Pattern 6 - nested setjmp/longjmp handled inside stepped-over + function. */ + hidden_longjmp_2 (); /* patt6 */ + i = 6; /* patt_end6. */ - i = 3; /* patt_end3. */ return 0; } Index: src/gdb/testsuite/gdb.base/longjmp.exp =================================================================== --- src.orig/gdb/testsuite/gdb.base/longjmp.exp 2008-05-04 20:43:31.000000000 +0100 +++ src/gdb/testsuite/gdb.base/longjmp.exp 2008-05-17 02:30:18.000000000 +0100 @@ -47,12 +47,12 @@ if ![runto_main] then { return 0 } -set bp_miss_step_1 [gdb_get_line_number "miss_step_1"] -set bp_miss_step_2 [gdb_get_line_number "miss_step_2"] - set bp_start_test_1 [gdb_get_line_number "patt1"] set bp_start_test_2 [gdb_get_line_number "patt2"] set bp_start_test_3 [gdb_get_line_number "patt3"] +set bp_start_test_4 [gdb_get_line_number "patt4"] +set bp_start_test_5 [gdb_get_line_number "patt5"] +set bp_start_test_6 [gdb_get_line_number "patt6"] # # Pattern 1 - simple longjmp. @@ -65,25 +65,7 @@ gdb_test "break $bp_start_test_1" \ "breakpoint at pattern 1 start" gdb_test "continue" "patt1.*" "continue to breakpoint at pattern 1 start" -# set safe-net break -gdb_test "break $bp_miss_step_1" \ - "Breakpoint.*at.* file .*$srcfile, line.*$bp_miss_step_1.*" \ - "breakpoint at miss_step_1" - -gdb_test "next" "longjmps\\+\\+;.*" "next over setjmp (1)" -gdb_test "next" "longjmp \\(env, 1\\);.*" "next to longjmp (1)" - -set msg "next over longjmp(1)" -gdb_test_multiple "next" $msg { - -re ".*patt1.*" { - pass $msg - gdb_test "next" "resumes\\+\\+.*" "next into else block (1)" - gdb_test "next" "miss_step_1.*" "next into safety net (1)" - } - -re "miss_step_1.*" { - fail $msg - } -} +gdb_test "next" ".*resume1.*" "next over longjmp(1)" # # Pattern 2 - longjmp from an inner function. @@ -96,28 +78,10 @@ gdb_test "break $bp_start_test_2" \ "breakpoint at pattern 2 start" gdb_test "continue" "patt2.*" "continue to breakpoint at pattern 2 start" -# set safe-net break -gdb_test "break $bp_miss_step_2" \ - "Breakpoint.*at.* file .*$srcfile, line.*$bp_miss_step_2.*" \ - "breakpoint at miss_step_2" - -gdb_test "next" "call_longjmp.*" "next over setjmp (2)" - -set msg "next over call_longjmp (2)" -gdb_test_multiple "next" $msg { - -re ".*patt2.*" { - pass $msg - - gdb_test "next" "resumes\\+\\+.*" "next into else block (2)" - gdb_test "next" "miss_step_2.*" "next into safety net (2)" - } - -re "miss_step_2.*" { - fail $msg - } -} +gdb_test "next" ".*resume2.*" "next over call_longjmp (2)" # -# Pattern 3 - setjmp/longjmp inside stepped-over function. +# Pattern 3 - prefer longjmp resume # delete_breakpoints @@ -125,6 +89,50 @@ delete_breakpoints gdb_test "break $bp_start_test_3" \ "Breakpoint.*at.* file .*$srcfile, line.*$bp_start_test_3.*" \ "breakpoint at pattern 3 start" -gdb_test "continue" "patt3.*" "continue to breakpoint at pattern 3 start" +gdb_test "continue" "patt3.*" \ + "continue to breakpoint at pattern 3 start" + +gdb_test "next" "resume3.*" "next over hidden_longjmp_3 (3)" + + +# +# Pattern 4 - prefer longjmp resume after step +# + +delete_breakpoints + +gdb_test "break $bp_start_test_4" \ + "Breakpoint.*at.* file .*$srcfile, line.*$bp_start_test_4.*" \ + "breakpoint at pattern 4 start" +gdb_test "continue" "patt4.*" "continue to breakpoint at pattern 4 start" + +gdb_test "step" "hidden_longjmp_3_1 \\(\\).*" "step into hidden_longjmp_3 (4)" + +gdb_test "next" "resume4.*" "next over hidden_longjmp_3_1 (4)" + +# +# Pattern 5 - setjmp/longjmp handled inside stepped-over function. +# + +delete_breakpoints + +gdb_test "break $bp_start_test_5" \ + "Breakpoint.*at.* file .*$srcfile, line.*$bp_start_test_5.*" \ + "breakpoint at pattern 5 start" +gdb_test "continue" "patt5.*" "continue to breakpoint at pattern 5 start" + +gdb_test "next" "patt_end5.*" "next over patt5" + +# +# Pattern 6 - nested setjmp/longjmp handled inside stepped-over +# function. +# + +delete_breakpoints + +gdb_test "break $bp_start_test_6" \ + "Breakpoint.*at.* file .*$srcfile, line.*$bp_start_test_6.*" \ + "breakpoint at pattern 6 start" +gdb_test "continue" "patt6.*" "continue to breakpoint at pattern 6 start" -gdb_test "next" "longjmp caught.*" "next over patt3" +gdb_test "next" "patt_end6.*" "next over patt6"