# HG changeset patch # User gromero # Date 1553115575 14400 # Wed Mar 20 16:59:35 2019 -0400 # Node ID c799c9a11c17fbf5d6914bb0a4f4e0c32f690b90 # Parent 18547cad9ec65a273b40e7793a37ef101179a289 8220794: PPC64: Fix signal handler for SIGSEGV on branch to illegal address Reviewed-by: diff --git a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp --- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp +++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp @@ -132,6 +132,10 @@ return NULL; } +static unsigned long ucontext_get_trap(const ucontext_t * uc) { + return uc->uc_mcontext.regs->trap; +} + ExtendedPC os::fetch_frame_from_context(const void* ucVoid, intptr_t** ret_sp, intptr_t** ret_fp) { @@ -304,9 +308,22 @@ // Handle ALL stack overflow variations here if (sig == SIGSEGV) { - // Si_addr may not be valid due to a bug in the linux-ppc64 kernel (see + // si_addr may not be valid due to a bug in the linux-ppc64 kernel (see // comment below). Use get_stack_bang_address instead of si_addr. - address addr = ((NativeInstruction*)pc)->get_stack_bang_address(uc); + // If SIGSEGV is caused due to a branch to an invalid address an + // "Instruction Storage" interruption is generated and 'pc' (NIP) already + // contains the invalid address. Otherwise, the SIGSEGV is caused due to + // load/store instruction trying to load/store from/to an invalid address + // and causing a "Data Storage" interruption, so we inspect the intruction + // in order to extract the faulty data addresss. + address addr; + if ((ucontext_get_trap(uc) & 0x0F00 /* no IRQ reply bits */) == 0x0400) { + // Instruction interruption + addr = pc; + } else { + // Data interruption (0x0300): extract faulty data address + addr = ((NativeInstruction*)pc)->get_stack_bang_address(uc); + } // Check if fault address is within thread stack. if (thread->on_local_stack(addr)) {