https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124050

Xi Ruoyao <xry111 at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|WAITING                     |UNCONFIRMED
     Ever confirmed|1                           |0

--- Comment #7 from Xi Ruoyao <xry111 at gcc dot gnu.org> ---
At the very least the situation is not so good on RISC-V.  With a simplified
glibc test case:

#include <execinfo.h>
#include <inttypes.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>

static void
handler (int signal, siginfo_t *info, void *ctx)
{
  void *callstack[10];
  int callstack_count = backtrace (callstack, 10);
  bool found = false;
  for (int i = 0; i < callstack_count; ++i)
    printf ("info: call stack entry %d: 0x%" PRIxPTR "\n",
            i, (uintptr_t) callstack[i]);
}

int
main (void)
{
  struct sigaction sa =
    {
     .sa_sigaction = &handler,
     .sa_flags = SA_SIGINFO
    };
  sigaction (SIGUSR1, &sa, NULL);
  raise (SIGUSR1);
  return 0;
}

Debugging it on RISC-V shows:

(gdb) b _Unwind_Find_FDE
❌️ Function "_Unwind_Find_FDE" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (_Unwind_Find_FDE) pending.
(gdb) r 
Starting program: /home/xry111/a.out 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".

Program received signal SIGUSR1, User defined signal 1.
__pthread_kill_implementation (threadid=<optimized out>, signo=-877095168, 
    no_tid=0) at pthread_kill.c:44
⚠️ warning: 44   pthread_kill.c: no such file or directory
(gdb) c
Continuing.

Breakpoint 1, _Unwind_Find_FDE (pc=0x3ff7e1b323 <_Unwind_Backtrace+131>, 
    bases=bases@entry=0x3fffffe4b8) at ../../../libgcc/unwind-dw2-fde-dip.c:541
⚠️ warning: 541  ../../../libgcc/unwind-dw2-fde-dip.c: no such file or directory
(gdb) c
Continuing.

Breakpoint 1, _Unwind_Find_FDE (pc=0x3ff7f20251 <__GI___backtrace+81>, 
    bases=bases@entry=0x3fffffe4b8) at ../../../libgcc/unwind-dw2-fde-dip.c:541
541     in ../../../libgcc/unwind-dw2-fde-dip.c
(gdb) c
Continuing.

Breakpoint 1, _Unwind_Find_FDE (pc=0x2aaaaaa87d <handler+49>, 
    bases=bases@entry=0x3fffffe4b8) at ../../../libgcc/unwind-dw2-fde-dip.c:541
541     in ../../../libgcc/unwind-dw2-fde-dip.c
(gdb) c
Continuing.

Breakpoint 1, _Unwind_Find_FDE (pc=0x3ff7fd358f, 
    bases=bases@entry=0x3fffffe4b8) at ../../../libgcc/unwind-dw2-fde-dip.c:541
541     in ../../../libgcc/unwind-dw2-fde-dip.c
(gdb) p pc+1
$1 = (void *) 0x3ff7fd3590 <__vdso_rt_sigreturn>
(gdb) finish
Run till exit from #0  _Unwind_Find_FDE (pc=0x3ff7fd358f, 
    bases=bases@entry=0x3fffffe4b8) at ../../../libgcc/unwind-dw2-fde-dip.c:541
0x0000003ff7e18af2 in uw_frame_state_for (context=context@entry=0x3fffffe090, 
    fs=fs@entry=0x3fffffe570) at ../../../libgcc/unwind-dw2.c:1008
⚠️ warning: 1008 ../../../libgcc/unwind-dw2.c: no such file or directory
Value returned is $2 = (const fde *) 0x0

We can see the pc passed to _Unwind_Find_FDE is subtracted with 1, and
_Unwind_Find_FDE cannot find the FDE.  Thus it relies on
MD_FALLBACK_FRAME_STATE_FOR.

To make the situation more fragile: the fall back only works because on RISC-V
__vdso_rt_sigreturn happens to be the first function in the text section. 
Otherwise using the subtracted pc will cause _Unwind_Find_FDE to return the FDE
of the previous function and break unwinding completely.

Reply via email to