https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124050
Bug ID: 124050
Summary: libgcc unwinder incorrectly handles signal frames
without the machine-specific fallback
Product: gcc
Version: 16.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libgcc
Assignee: unassigned at gcc dot gnu.org
Reporter: xry111 at gcc dot gnu.org
Target Milestone: ---
I've discussed this issue with H. Peter Anvin via the kernel list, beginning at
https://lore.kernel.org/all/[email protected]/.
The code current reads:
fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1,
&context->bases);
if (fde == NULL)
{
#ifdef MD_FALLBACK_FRAME_STATE_FOR
/* Couldn't find frame unwind info for this function. Try a
target-specific fallback mechanism. This will necessarily
not provide a personality routine or LSDA. */
return MD_FALLBACK_FRAME_STATE_FOR (context, fs);
#else
return _URC_END_OF_STACK;
#endif
}
fs->pc = context->bases.func;
cie = get_cie (fde);
insn = extract_cie_info (cie, context, fs);
It indeed attempts to avoid subtracting 1 for a signal frame, but
_Unwind_IsSignalFrame (context) actually extracts a flag in context
which will only be raised up by extract_cie_info. So the logic never worked.
On many existing Linux targets, the unwinding from signal handler actually
works by using MD_FALLBACK_FRAME_STATE_FOR (sometimes only coincidentally).
For example, on AArch64 and LoongArch it's simply the unwind info isn't emitted
for vDSO as at now, if the kernel developers want to add the unwind info for
them, they still need a hack (inserting a NOP before the sigreturn trampoline,
x86 is already doing this) for unwinding from signal frame.