| 1921 | #else |
| 1922 | |
| 1923 | static void signal_handler(int /*sig*/, siginfo_t* info, void* uct) noexcept |
| 1924 | { |
| 1925 | ucontext_t* context = static_cast<ucontext_t*>(uct); |
| 1926 | |
| 1927 | #if defined(ARCH_X64) |
| 1928 | #ifdef __APPLE__ |
| 1929 | const u64 err = context->uc_mcontext->__es.__err; |
| 1930 | #elif defined(__DragonFly__) || defined(__FreeBSD__) |
| 1931 | const u64 err = context->uc_mcontext.mc_err; |
| 1932 | #elif defined(__OpenBSD__) |
| 1933 | const u64 err = context->sc_err; |
| 1934 | #elif defined(__NetBSD__) |
| 1935 | const u64 err = context->uc_mcontext.__gregs[_REG_ERR]; |
| 1936 | #else |
| 1937 | const u64 err = context->uc_mcontext.gregs[REG_ERR]; |
| 1938 | #endif |
| 1939 | |
| 1940 | const bool is_executing = err & 0x10; |
| 1941 | const bool is_writing = err & 0x2; |
| 1942 | #elif defined(ARCH_ARM64) |
| 1943 | const bool is_executing = uptr(info->si_addr) == uptr(RIP(context)); |
| 1944 | |
| 1945 | #if defined(__linux__) || defined(__APPLE__) |
| 1946 | // Current CPU state decoder is reverse-engineered from the linux kernel and may not work on other platforms. |
| 1947 | const auto decoded_reason = aarch64::decode_fault_reason(context); |
| 1948 | const bool is_writing = (decoded_reason == aarch64::fault_reason::data_write); |
| 1949 | |
| 1950 | if (decoded_reason != aarch64::fault_reason::data_write && |
| 1951 | decoded_reason != aarch64::fault_reason::data_read) |
| 1952 | { |
| 1953 | // We don't expect other classes of exceptions during normal executions |
| 1954 | sig_log.warning("Unexpected fault. Reason: %d", static_cast<int>(decoded_reason)); |
| 1955 | } |
| 1956 | |
| 1957 | #else |
| 1958 | const u32 insn = is_executing ? 0 : *reinterpret_cast<u32*>(RIP(context)); |
| 1959 | const bool is_writing = |
| 1960 | (insn & 0xbfff0000) == 0x0c000000 || // STR <Wt>, [<Xn>, #<imm>] (store word with immediate offset) |
| 1961 | (insn & 0xbfe00000) == 0x0c800000 || // STP <Wt1>, <Wt2>, [<Xn>, #<imm>] (store pair of registers with immediate offset) |
| 1962 | (insn & 0xbfdf0000) == 0x0d000000 || // STR <Wt>, [<Xn>, <Xm>] (store word with register offset) |
| 1963 | (insn & 0xbfc00000) == 0x0d800000 || // STP <Wt1>, <Wt2>, [<Xn>, <Xm>] (store pair of registers with register offset) |
| 1964 | (insn & 0x3f400000) == 0x08000000 || // STR <Vd>, [<Xn>, #<imm>] (store SIMD/FP register with immediate offset) |
| 1965 | (insn & 0x3bc00000) == 0x39000000 || // STR <Wt>, [<Xn>, #<imm>] (store word with immediate offset) |
| 1966 | (insn & 0x3fc00000) == 0x3d800000 || // STR <Vd>, [<Xn>, <Xm>] (store SIMD/FP register with register offset) |
| 1967 | (insn & 0x3bc00000) == 0x38000000 || // STR <Wt>, [<Xn>, <Xm>] (store word with register offset) |
| 1968 | (insn & 0x3fe00000) == 0x3c800000 || // STUR <Vd>, [<Xn>, #<imm>] (store unprivileged register with immediate offset) |
| 1969 | (insn & 0x3fe00000) == 0x3ca00000 || // STR <Vd>, [<Xn>, #<imm>] (store SIMD/FP register with immediate offset) |
| 1970 | (insn & 0x3a400000) == 0x28000000 || // STP <Wt1>, <Wt2>, [<Xn>, #<imm>] (store pair of registers with immediate offset) |
| 1971 | (insn & 0xbf000000) == 0xad000000 || // STP <Vd1>, <Vd2>, [<Xn>, #<imm>] (store SIMD/FP 128-bit register pair with immediate offset) |
| 1972 | (insn & 0xbf000000) == 0x6d000000; // STP <Dd1>, <Dd2>, [<Xn>, #<imm>] (store SIMD/FP 64-bit register pair with immediate offset) |
| 1973 | #endif |
| 1974 | |
| 1975 | #else |
| 1976 | #error "signal_handler not implemented" |
| 1977 | #endif |
| 1978 | |
| 1979 | const u64 exec64 = (reinterpret_cast<u64>(info->si_addr) - reinterpret_cast<u64>(vm::g_exec_addr)) / 2; |
| 1980 | const auto cause = is_executing ? "executing" : is_writing ? "writing" : |
nothing calls this directly
no test coverage detected