From 6e41445bb006f3afc784862f8eb1bf0f2691a94a Mon Sep 17 00:00:00 2001 From: Tom de Vries Date: Tue, 6 Dec 2022 12:01:46 +0100 Subject: [PATCH] [gdb/testsuite] Make gdb.base/longjmp.exp FAIL more stable across archs When running test-case gdb.base/longjmp.exp on x86_64-linux, the master longjmp breakpoint is set using probes and the test-case passes: ... (gdb) PASS: gdb.base/longjmp.exp: next to longjmp (1) next^M 0x00000000004005cc 49 if (setjmp (env) == 0) /* patt1 */^M (gdb) PASS: gdb.base/longjmp.exp: next over longjmp(1) next^M 56 resumes++;^M (gdb) PASS: gdb.base/longjmp.exp: next into else block (1) ... However, if I disable create_longjmp_master_breakpoint_probe, we have instead: ... (gdb) PASS: gdb.base/longjmp.exp: next to longjmp (1) next^M 56 resumes++;^M (gdb) FAIL: gdb.base/longjmp.exp: next over longjmp(1) ... At first glance, the failure mode doesn't look too bad: we stop a few insns later than the passing scenario. For contrast, if we do the same on powerpc64le, the failure mode is: ... (gdb) PASS: gdb.base/longjmp.exp: next to longjmp (1) next^M ^M Breakpoint 3, main () at longjmp.c:59^M 59 i = 1; /* miss_step_1 */^M (gdb) FAIL: gdb.base/longjmp.exp: next over longjmp(1) ... Here we only stop because of running into the safety net breakpoint at miss_step_1. So, how does this happen on x86_64? Let's look at the code: ... 4005c7: e8 94 fe ff ff call 400460 <_setjmp@plt> 4005cc: 85 c0 test %eax,%eax 4005ce: 75 1e jne 4005ee 4005d0: 8b 05 8e 0a 20 00 mov 0x200a8e(%rip),%eax # 601064 4005d6: 83 c0 01 add $0x1,%eax 4005d9: 89 05 85 0a 20 00 mov %eax,0x200a85(%rip) # 601064 4005df: be 01 00 00 00 mov $0x1,%esi 4005e4: bf 80 10 60 00 mov $0x601080,%edi 4005e9: e8 82 fe ff ff call 400470 4005ee: 8b 05 74 0a 20 00 mov 0x200a74(%rip),%eax # 601068 ... The next over the longjmp call at 4005e9 is supposed to stop at the longjmp target at 4005cc, but instead we stop at 4005ee, where we have the step-resume breakpoint inserted by the next. In other words, we accidentally "return" from the longjmp call to the insn immediately after it (even though a longjmp is a noreturn function). Try to avoid this accident and make the failure mode on x86_64 the same as on powerpc64le, by switching the then and else branch. Tested on x86_64-linux. --- gdb/testsuite/gdb.base/longjmp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gdb/testsuite/gdb.base/longjmp.c b/gdb/testsuite/gdb.base/longjmp.c index 4139e49e6f1..ce6990ca99a 100644 --- a/gdb/testsuite/gdb.base/longjmp.c +++ b/gdb/testsuite/gdb.base/longjmp.c @@ -46,14 +46,14 @@ main () volatile int i = 0; /* Pattern 1 - simple longjmp. */ - if (setjmp (env) == 0) /* patt1 */ + if (setjmp (env) != 0) /* patt1 */ { - longjmps++; - longjmp (env, 1); + resumes++; } else { - resumes++; + longjmps++; + longjmp (env, 1); } i = 1; /* miss_step_1 */ -- 2.30.2