| 1962 | #else |
| 1963 | |
| 1964 | static void signal_handler(int /*sig*/, siginfo_t* info, void* uct) noexcept |
| 1965 | { |
| 1966 | ucontext_t* context = static_cast<ucontext_t*>(uct); |
| 1967 | |
| 1968 | #if defined(ARCH_X64) |
| 1969 | #ifdef __APPLE__ |
| 1970 | const u64 err = context->uc_mcontext->__es.__err; |
| 1971 | #elif defined(__DragonFly__) || defined(__FreeBSD__) |
| 1972 | const u64 err = context->uc_mcontext.mc_err; |
| 1973 | #elif defined(__OpenBSD__) |
| 1974 | const u64 err = context->sc_err; |
| 1975 | #elif defined(__NetBSD__) |
| 1976 | const u64 err = context->uc_mcontext.__gregs[_REG_ERR]; |
| 1977 | #else |
| 1978 | const u64 err = context->uc_mcontext.gregs[REG_ERR]; |
| 1979 | #endif |
| 1980 | |
| 1981 | const bool is_executing = err & 0x10; |
| 1982 | const bool is_writing = err & 0x2; |
| 1983 | #elif defined(ARCH_ARM64) |
| 1984 | const bool is_executing = uptr(info->si_addr) == uptr(RIP(context)); |
| 1985 | |
| 1986 | #if defined(__linux__) || defined(__APPLE__) |
| 1987 | // Current CPU state decoder is reverse-engineered from the linux kernel and may not work on other platforms. |
| 1988 | const auto decoded_reason = aarch64::decode_fault_reason(context); |
| 1989 | const bool is_writing = (decoded_reason == aarch64::fault_reason::data_write); |
| 1990 | |
| 1991 | if (decoded_reason != aarch64::fault_reason::data_write && |
| 1992 | decoded_reason != aarch64::fault_reason::data_read) |
| 1993 | { |
| 1994 | // We don't expect other classes of exceptions during normal executions |
| 1995 | sig_log.warning("Unexpected fault. Reason: %d", static_cast<int>(decoded_reason)); |
| 1996 | } |
| 1997 | |
| 1998 | #else |
| 1999 | const u32 insn = is_executing ? 0 : *reinterpret_cast<u32*>(RIP(context)); |
| 2000 | const bool is_writing = |
| 2001 | (insn & 0xbfff0000) == 0x0c000000 || // STR <Wt>, [<Xn>, #<imm>] (store word with immediate offset) |
| 2002 | (insn & 0xbfe00000) == 0x0c800000 || // STP <Wt1>, <Wt2>, [<Xn>, #<imm>] (store pair of registers with immediate offset) |
| 2003 | (insn & 0xbfdf0000) == 0x0d000000 || // STR <Wt>, [<Xn>, <Xm>] (store word with register offset) |
| 2004 | (insn & 0xbfc00000) == 0x0d800000 || // STP <Wt1>, <Wt2>, [<Xn>, <Xm>] (store pair of registers with register offset) |
| 2005 | (insn & 0x3f400000) == 0x08000000 || // STR <Vd>, [<Xn>, #<imm>] (store SIMD/FP register with immediate offset) |
| 2006 | (insn & 0x3bc00000) == 0x39000000 || // STR <Wt>, [<Xn>, #<imm>] (store word with immediate offset) |
| 2007 | (insn & 0x3fc00000) == 0x3d800000 || // STR <Vd>, [<Xn>, <Xm>] (store SIMD/FP register with register offset) |
| 2008 | (insn & 0x3bc00000) == 0x38000000 || // STR <Wt>, [<Xn>, <Xm>] (store word with register offset) |
| 2009 | (insn & 0x3fe00000) == 0x3c800000 || // STUR <Vd>, [<Xn>, #<imm>] (store unprivileged register with immediate offset) |
| 2010 | (insn & 0x3fe00000) == 0x3ca00000 || // STR <Vd>, [<Xn>, #<imm>] (store SIMD/FP register with immediate offset) |
| 2011 | (insn & 0x3a400000) == 0x28000000 || // STP <Wt1>, <Wt2>, [<Xn>, #<imm>] (store pair of registers with immediate offset) |
| 2012 | (insn & 0xbf000000) == 0xad000000 || // STP <Vd1>, <Vd2>, [<Xn>, #<imm>] (store SIMD/FP 128-bit register pair with immediate offset) |
| 2013 | (insn & 0xbf000000) == 0x6d000000; // STP <Dd1>, <Dd2>, [<Xn>, #<imm>] (store SIMD/FP 64-bit register pair with immediate offset) |
| 2014 | #endif |
| 2015 | |
| 2016 | #else |
| 2017 | #error "signal_handler not implemented" |
| 2018 | #endif |
| 2019 | |
| 2020 | const u64 exec64 = (reinterpret_cast<u64>(info->si_addr) - reinterpret_cast<u64>(vm::g_exec_addr)) / 2; |
| 2021 | const auto cause = is_executing ? "executing" : is_writing ? "writing" : "reading"; |
nothing calls this directly
no test coverage detected