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.