// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. #include "vm/globals.h" #include "vm/instructions.h" #include "vm/signal_handler.h" #include "vm/simulator.h" #if defined(DART_HOST_OS_ANDROID) namespace dart { uintptr_t SignalHandler::GetProgramCounter(const mcontext_t& mcontext) { uintptr_t pc = 0; #if defined(HOST_ARCH_IA32) pc = static_cast(mcontext.gregs[REG_EIP]); #elif defined(HOST_ARCH_X64) pc = static_cast(mcontext.gregs[REG_RIP]); #elif defined(HOST_ARCH_ARM) pc = static_cast(mcontext.arm_pc); #elif defined(HOST_ARCH_ARM64) pc = static_cast(mcontext.pc); #elif defined(HOST_ARCH_RISCV64) pc = static_cast(mcontext.__gregs[REG_PC]); #else #error Unsupported architecture. #endif // HOST_ARCH_... return pc; } uintptr_t SignalHandler::GetFramePointer(const mcontext_t& mcontext) { uintptr_t fp = 0; #if defined(HOST_ARCH_IA32) fp = static_cast(mcontext.gregs[REG_EBP]); #elif defined(HOST_ARCH_X64) fp = static_cast(mcontext.gregs[REG_RBP]); #elif defined(HOST_ARCH_ARM) // B1.3.3 Program Status Registers (PSRs) if ((mcontext.arm_cpsr & (1 << 5)) != 0) { // Thumb mode. fp = static_cast(mcontext.arm_r7); } else { // ARM mode. fp = static_cast(mcontext.arm_fp); } #elif defined(HOST_ARCH_ARM64) fp = static_cast(mcontext.regs[29]); #elif defined(HOST_ARCH_RISCV64) fp = static_cast(mcontext.__gregs[REG_S0]); #else #error Unsupported architecture. #endif // HOST_ARCH_... return fp; } uintptr_t SignalHandler::GetCStackPointer(const mcontext_t& mcontext) { uintptr_t sp = 0; #if defined(HOST_ARCH_IA32) sp = static_cast(mcontext.gregs[REG_ESP]); #elif defined(HOST_ARCH_X64) sp = static_cast(mcontext.gregs[REG_RSP]); #elif defined(HOST_ARCH_ARM) sp = static_cast(mcontext.arm_sp); #elif defined(HOST_ARCH_ARM64) sp = static_cast(mcontext.sp); #elif defined(HOST_ARCH_RISCV64) sp = static_cast(mcontext.__gregs[REG_SP]); #else #error Unsupported architecture. #endif // HOST_ARCH_... return sp; } uintptr_t SignalHandler::GetDartStackPointer(const mcontext_t& mcontext) { #if defined(TARGET_ARCH_ARM64) && !defined(DART_INCLUDE_SIMULATOR) return static_cast(mcontext.regs[SPREG]); #else return GetCStackPointer(mcontext); #endif } uintptr_t SignalHandler::GetLinkRegister(const mcontext_t& mcontext) { uintptr_t lr = 0; #if defined(HOST_ARCH_IA32) lr = 0; #elif defined(HOST_ARCH_X64) lr = 0; #elif defined(HOST_ARCH_ARM) lr = static_cast(mcontext.arm_lr); #elif defined(HOST_ARCH_ARM64) lr = static_cast(mcontext.regs[30]); #elif defined(HOST_ARCH_RISCV64) lr = static_cast(mcontext.__gregs[REG_RA]); #else #error Unsupported architecture. #endif // HOST_ARCH_... return lr; } void SignalHandler::Install(SignalAction action) { // Bionic implementation of setjmp temporary mangles SP register // in place which breaks signal delivery on the thread stack - when // kernel tries to deliver SIGPROF and we are in the middle of // setjmp SP value is invalid - might be pointing to random memory // or outside of writable space at all. In the first case we // get memory corruption and in the second case kernel would send // SIGSEGV to the process. See b/152210274 for details. // To work around this issue we request SIGPROF signals to be delivered // on the alternative signal stack by setting SA_ONSTACK. The stack itself // is configured when interrupts are enabled for a particular thread. // In reality Bionic's |pthread_create| eagerly creates and assigns an // alternative signal stack for each thread. However older versions of Bionic // (L and below) make the size of alternative stack too small which causes // stack overflows and crashes. struct sigaction act = {}; act.sa_sigaction = action; sigemptyset(&act.sa_mask); sigaddset(&act.sa_mask, SIGPROF); // Prevent nested signals. act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; int r = sigaction(SIGPROF, &act, nullptr); ASSERT(r == 0); } void SignalHandler::Remove() { // Ignore future SIGPROF signals because by default SIGPROF will terminate // the process and we may have some signals in flight. struct sigaction act = {}; act.sa_handler = SIG_IGN; sigemptyset(&act.sa_mask); int r = sigaction(SIGPROF, &act, nullptr); RELEASE_ASSERT(r == 0); } } // namespace dart #endif // defined(DART_HOST_OS_ANDROID)