Bug 26967 - FAIL: gdb.base/longjmp.exp: next over longjmp(1)
Summary: FAIL: gdb.base/longjmp.exp: next over longjmp(1)
Status: NEW
Alias: None
Product: gdb
Classification: Unclassified
Component: testsuite (show other bugs)
Version: HEAD
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
: 29850 (view as bug list)
Depends on:
Blocks:
 
Reported: 2020-11-28 12:44 UTC by Tom de Vries
Modified: 2024-03-20 18:24 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Tom de Vries 2020-11-28 12:44:37 UTC
On SLE-11, I ran into:
...
FAIL: gdb.base/longjmp.exp: next over longjmp(1)
...

In more detail:
...
(gdb) next^M
52            longjmp (env, 1);^M
(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)
...

What is expected:
...
(gdb) next^M
52            longjmp (env, 1);^M
(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)
...

I've analyzed this behaviour to be caused by the lack of presence of longjmp probes in libc.  On SLE-11, we have glibc-2.11.3, the probes were added in 2.16 for x86_64.

I can reproduce the same behaviour with a current glibc by forcing probe_safe_evaluate_at_pc to return NULL (which makes you wonder whether a gdb command probes ignore could be useful).
Comment 1 Tom de Vries 2021-01-08 14:28:41 UTC
(In reply to Tom de Vries from comment #0)
> (which makes you wonder whether a
> gdb command probes ignore could be useful).

Filed https://sourceware.org/bugzilla/show_bug.cgi?id=27159
Comment 2 Tom de Vries 2021-01-27 15:17:20 UTC
While working on PR27205 I figured out what happens.

Without longjmp probes in libc, we try to fall back to using longjmp_names breakpoints, but when these trigger we don't manage to recuperate the pc from jmp_buf because tdep->jb_pc_offset is not set (in other words, -1).

Perhaps this once was set, but switched off due to problems.  There are known issues with this for linux related to pointer guarding of the pc in jmp_buf.

Anyway, we could detect this in the "set debug infrun 1" output:
...
  [infrun] process_event_stop_test: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)
...
and then allow the behaviour reported in this PR.

However, AFAIU that still wouldn't work for -m32, because there tdep->jb_pc_offset is defined and then we run into pointer guarding (see PR27205 for what that looks like).
Comment 3 Tom Tromey 2022-12-05 23:33:35 UTC
(In reply to Tom de Vries from comment #2)

> Perhaps this once was set, but switched off due to problems.  There are
> known issues with this for linux related to pointer guarding of the pc in
> jmp_buf.

My recollection is that this is why it isn't enabled.
If we know a platform uses pointer guarding, we should
disable this approach.  The probes approach doesn't have
this problem IIRC.
Comment 4 Tom de Vries 2022-12-07 08:33:20 UTC
*** Bug 29850 has been marked as a duplicate of this bug. ***
Comment 5 Tom de Vries 2022-12-07 10:31:03 UTC
(In reply to Tom Tromey from comment #3)
> (In reply to Tom de Vries from comment #2)
> 
> > Perhaps this once was set, but switched off due to problems.  There are
> > known issues with this for linux related to pointer guarding of the pc in
> > jmp_buf.
> 
> My recollection is that this is why it isn't enabled.
> If we know a platform uses pointer guarding, we should
> disable this approach.  The probes approach doesn't have
> this problem IIRC.

Thanks for the info.

Ack, the probes approach doesn't have that problem.

I suppose the difficulty lies in determining whether a platform indeed does use pointer guarding.

Maybe a configure time test could be used, like so:
...
$ cat test.c
#include <stdio.h>
#include <setjmp.h>

jmp_buf env;

void * __attribute__((noinline))
current_pc (void)
{
  return __builtin_return_address (0);
}
  
int
main (void)
{
  void *pc1, *pc2;

  pc1 = current_pc ();
  int res = setjmp (env);
  pc2 = current_pc ();

  int found = 0;
  if (res == 0)
    {
      int n = sizeof (env->__jmpbuf) / sizeof (env->__jmpbuf[0]);
      for (int i = 0; i < n; ++i)
        {
          void *entry = (void *) env->__jmpbuf[i];
          if (pc1 <= entry && entry <= pc2)
            {
              /* printf ("found pc in jmp_buf at index %d\n", i); */
              found = 1;
            }
        }
      longjmp (env, 1);
    }

  if (found)
    printf ("no pointer mangling\n");
  else
    printf ("pointer mangling\n");

  return 0;
}
...
but this one already doesn't compile on s390x due to a different jmp_buf layout.
Comment 6 Tom de Vries 2022-12-07 10:36:38 UTC
Proposal to add kfails: https://sourceware.org/pipermail/gdb-patches/2022-December/194537.html
Comment 7 Tom de Vries 2022-12-07 15:10:49 UTC
Sorry, I've been using "pointer guarding" here, but I meant to say "pointer mangling" ( https://sourceware.org/glibc/wiki/PointerEncryption ).
Comment 8 Sourceware Commits 2022-12-07 15:45:31 UTC
The master branch has been updated by Tom de Vries <vries@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=b5e7cd5cd3d1f90d0e7e58679a0782816bd5434f

commit b5e7cd5cd3d1f90d0e7e58679a0782816bd5434f
Author: Tom de Vries <tdevries@suse.de>
Date:   Wed Dec 7 16:45:26 2022 +0100

    [gdb/testsuite] Add KFAILs in gdb.base/longjmp.exp
    
    Add KFAILs in test-case gdb.base/longjmp.exp for PR gdb/26967, covering
    various ways that gdb is unable to recover the longjmp target if the libc
    probe is not supported.
    
    Tested on x86_64-linux.
    
    Approved-By: Simon Marchi <simon.marchi@efficios.com>
Comment 9 Sourceware Commits 2024-03-20 18:24:11 UTC
The master branch has been updated by Tom de Vries <vries@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d51a931152993fb095fd52083f2ba17d19e32ffd

commit d51a931152993fb095fd52083f2ba17d19e32ffd
Author: Tom de Vries <tdevries@suse.de>
Date:   Wed Mar 20 19:23:48 2024 +0100

    [gdb/testsuite] Add PR gdb/26967 KFAIL in two more test-cases
    
    On aarch64-linux (debian 12), when running test-case
    gdb.base/longjmp-until-in-main.exp, I run into:
    ...
    (gdb) until 33^M
    warning: Breakpoint address adjusted from 0x70f727c678928489 to 0xfff727c678928489.^M
    Warning:^M
    Cannot insert breakpoint 0.^M
    Cannot access memory at address 0xfff727c678928489^M
    ^M
    0x0000fffff7e3a580 in siglongjmp () from /lib/aarch64-linux-gnu/libc.so.6^M
    (gdb) FAIL: gdb.base/longjmp-until-in-main.exp: until $line, in main
    ...
    
    This is PR gdb/26967: no longjmp probe is available:
    ...
    (gdb) info probes stap libc ^longjmp$^M
    No probes matched.^M
    ...
    and glibc applies pointer mangling which makes it fairly difficult for gdb to
    get the longjmp target.
    
    There's a KFAIL for this in test-case gdb.base/longjmp.exp, added in commit
    b5e7cd5cd3d ("[gdb/testsuite] Add KFAILs in gdb.base/longjmp.exp").
    
    Factor out new proc have_longjmp_probe, and use it to add similar KFAIL in
    this and one more test-case.
    
    Tested on aarch64-linux.
    
    Approved-By: Tom Tromey <tom@tromey.com>