From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 26022 invoked by alias); 21 Feb 2006 22:09:25 -0000 Received: (qmail 25974 invoked by uid 48); 21 Feb 2006 22:09:16 -0000 Date: Tue, 21 Feb 2006 22:09:00 -0000 Message-ID: <20060221220916.25972.qmail@sourceware.org> X-Bugzilla-Reason: CC References: Subject: [Bug other/26208] Serious problem with unwinding through signal frames In-Reply-To: Reply-To: gcc-bugzilla@gcc.gnu.org To: gcc-bugs@gcc.gnu.org From: "jakub at gcc dot gnu dot org" Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org X-SW-Source: 2006-02/txt/msg02459.txt.bz2 List-Id: ------- Comment #11 from jakub at gcc dot gnu dot org 2006-02-21 22:09 ------- Treating all signal frames as _Unwind_Find_FDE (context->ra, ...) and fs->pc <= context->ra is certainly better than what we are doing now, but it will only work say on s390 (other arches that raise exception after the not yet executed insn?) provided: a) the faulting instructions that raise the exception after the insn don't affect unwind info in any way b) they are never the last insn in a FDE On i386 I understand that even when the SIGFPE shows up on the next FPU insn, PC in the sigframe will be before that insn, not after it, but on s390 that's different. Consider e.g. (ok, agree, convoluted): #define _GNU_SOURCE #include #include #include void sigfpe (int signo) { _exit (0); } /* This routine is effectively noreturn, it divides by zero. */ extern void foo (double, double); asm ("\n" ".text\n" ".balign 16\n" ".globl foo\n" ".type foo, @function\n" ".cfi_startproc\n" "foo:\n" "ddbr %f0,%f2\n" ".cfi_endproc\n" ".size foo, .-foo\n" ".skip 64\n" ".previous\n"); int main (void) { struct sigaction sa; sa.sa_handler = sigfpe; sigemptyset (&sa.sa_mask); sa.sa_flags = 0; sigaction (SIGFPE, &sa, 0); feenableexcept (FE_ALL_EXCEPT); foo (1.0, 0.0); return 0; } on s390x vs. #define _GNU_SOURCE #include #include #include double d = 1.0, e = 0.0; void sigfpe (int signo) { _exit (0); } /* This routine is effectively noreturn, it divides by zero. */ extern void foo (void); asm ("\n" ".text\n" ".skip 16\n" ".balign 16\n" ".globl foo\n" ".type foo, @function\n" ".cfi_startproc\n" "foo:\n" "fldl e\n" "fdivrl d\n" "nop;nop;nop;nop;nop\n" "jmp bar\n" ".cfi_endproc\n" ".size foo, .-foo\n" ".skip 64\n" ".previous\n"); asm ("\n" ".text\n" ".skip 16\n" ".balign 16\n" ".globl bar\n" ".type bar, @function\n" ".cfi_startproc\n" "bar:\n" "fstpl d\n" ".cfi_endproc\n" ".size bar, .-bar\n" ".skip 64\n" ".previous\n"); int main (void) { struct sigaction sa; sa.sa_handler = sigfpe; sigemptyset (&sa.sa_mask); sa.sa_flags = 0; sigaction (SIGFPE, &sa, 0); feenableexcept (FE_ALL_EXCEPT); foo (); return 0; } on i386 (-O0 -fasynchronous-unwind-tables -fexceptions -lm flags in both cases). If sigfpe decides to call _Unwind_Backtrace, _Unwind_RaiseException etc., with vanilla GCC it will DTRT on s390{,x} and do the wrong thing on i386 (will not find FDE when the exception triggers with PC at the start of fstpl insn). With the patches here, GCC will DTRT on i386, but will fail with the testcase above on s390{,x}. In http://sources.redhat.com/bugzilla/show_bug.cgi?id=300 in third option you were proposing having S flag in CIE augmentation string correspond to .uleb128 len; CFA expression pair in FDE augmentation area and assuming we are able to write simple rules that for each arch from struct sigcontext and/or siginfo_t compute "is this signal sent with PC at first not fully executed insn or after it?", we are fine. Regarding PPC/PPC64, it seems the kernel does it unconditionally, it apparently never honored SA_RESTORER and doesn't do it even now :(. /* Set up to return from userspace. */ if (vdso64_rt_sigtramp && current->thread.vdso_base) { regs->link = current->thread.vdso_base + vdso64_rt_sigtramp; } else { err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); if (err) goto badframe; regs->link = (unsigned long) &frame->tramp[0]; } and similarly for 32-bit. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26208