1 /*
2 * sigsegv_beos_x86.cpp - x86/x86_64 BeOS/Haiku SIGSEGV handler
3 *
4 * Copyright (c) 2018 Thorsten Otto of ARAnyM dev team (see AUTHORS)
5 *
6 * This file is part of the ARAnyM project which builds a new and powerful
7 * TOS/FreeMiNT compatible virtual machine running on almost any hardware.
8 *
9 * ARAnyM is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * ARAnyM is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ARAnyM; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
23 * 2013-06-16 : Adapted to 64 Bit Linux - Jens Heitmann
24 * 2014-07-05 : Merged with 64bit version,
25 * lots of fixes - Thorsten Otto
26 *
27 */
28
29 #include "sysdeps.h"
30 #include "cpu_emulation.h"
31
32 #define DEBUG 1
33 #include "debug.h"
34
35 #if defined(__BEOS__) || defined(__HAIKU__)
36
37 #include <csignal>
38
39 #ifdef CPU_i386
40 #define CONTEXT_REGS (&CONTEXT_NAME->uc_mcontext.eip)
41 #define REG_EFL (offsetof(mcontext_t, eflags) / sizeof(CONTEXT_NAME->uc_mcontext.eip))
42 #define REG_RIP (offsetof(mcontext_t, eip) / sizeof(CONTEXT_NAME->uc_mcontext.eip))
43 #define REG_RAX (offsetof(mcontext_t, eax) / sizeof(CONTEXT_NAME->uc_mcontext.eip))
44 #define REG_RBX (offsetof(mcontext_t, ebx) / sizeof(CONTEXT_NAME->uc_mcontext.eip))
45 #define REG_RCX (offsetof(mcontext_t, ecx) / sizeof(CONTEXT_NAME->uc_mcontext.eip))
46 #define REG_RDX (offsetof(mcontext_t, edx) / sizeof(CONTEXT_NAME->uc_mcontext.eip))
47 #define REG_RBP (offsetof(mcontext_t, ebp) / sizeof(CONTEXT_NAME->uc_mcontext.eip))
48 #define REG_RSI (offsetof(mcontext_t, esi) / sizeof(CONTEXT_NAME->uc_mcontext.eip))
49 #define REG_RDI (offsetof(mcontext_t, edi) / sizeof(CONTEXT_NAME->uc_mcontext.eip))
50 #define REG_RSP (offsetof(mcontext_t, esp) / sizeof(CONTEXT_NAME->uc_mcontext.eip))
51 #endif
52 #if defined(CPU_x86_64)
53 #define CONTEXT_REGS (&CONTEXT_NAME->uc_mcontext.rax)
54 #define REG_EFL (offsetof(mcontext_t, rflags) / sizeof(CONTEXT_NAME->uc_mcontext.rax))
55 #define REG_RIP (offsetof(mcontext_t, rip) / sizeof(CONTEXT_NAME->uc_mcontext.rax))
56 #define REG_RAX (offsetof(mcontext_t, rax) / sizeof(CONTEXT_NAME->uc_mcontext.rax))
57 #define REG_RBX (offsetof(mcontext_t, rbx) / sizeof(CONTEXT_NAME->uc_mcontext.rax))
58 #define REG_RCX (offsetof(mcontext_t, rcx) / sizeof(CONTEXT_NAME->uc_mcontext.rax))
59 #define REG_RDX (offsetof(mcontext_t, rdx) / sizeof(CONTEXT_NAME->uc_mcontext.rax))
60 #define REG_RBP (offsetof(mcontext_t, rbp) / sizeof(CONTEXT_NAME->uc_mcontext.rax))
61 #define REG_RSI (offsetof(mcontext_t, rsi) / sizeof(CONTEXT_NAME->uc_mcontext.rax))
62 #define REG_RDI (offsetof(mcontext_t, rdi) / sizeof(CONTEXT_NAME->uc_mcontext.rax))
63 #define REG_RSP (offsetof(mcontext_t, rsp) / sizeof(CONTEXT_NAME->uc_mcontext.rax))
64 #define REG_R8 (offsetof(mcontext_t, r8) / sizeof(CONTEXT_NAME->uc_mcontext.rax))
65 #define REG_R9 (offsetof(mcontext_t, r9) / sizeof(CONTEXT_NAME->uc_mcontext.rax))
66 #define REG_R10 (offsetof(mcontext_t, r10) / sizeof(CONTEXT_NAME->uc_mcontext.rax))
67 #define REG_R11 (offsetof(mcontext_t, r11) / sizeof(CONTEXT_NAME->uc_mcontext.rax))
68 #define REG_R12 (offsetof(mcontext_t, r12) / sizeof(CONTEXT_NAME->uc_mcontext.rax))
69 #define REG_R13 (offsetof(mcontext_t, r13) / sizeof(CONTEXT_NAME->uc_mcontext.rax))
70 #define REG_R14 (offsetof(mcontext_t, r14) / sizeof(CONTEXT_NAME->uc_mcontext.rax))
71 #define REG_R15 (offsetof(mcontext_t, r15) / sizeof(CONTEXT_NAME->uc_mcontext.rax))
72 #endif
73 #if defined(CPU_i386) || defined(CPU_x86_64)
74 #define CONTEXT_NAME ucp
75 #define CONTEXT_TYPE volatile ucontext_t
76 #define CONTEXT_ATYPE CONTEXT_TYPE *
77 #define CONTEXT_AEFLAGS CONTEXT_REGS[REG_EFL]
78 #define CONTEXT_AEIP CONTEXT_REGS[REG_RIP]
79 #define CONTEXT_AEAX CONTEXT_REGS[REG_RAX]
80 #define CONTEXT_AEBX CONTEXT_REGS[REG_RBX]
81 #define CONTEXT_AECX CONTEXT_REGS[REG_RCX]
82 #define CONTEXT_AEDX CONTEXT_REGS[REG_RDX]
83 #define CONTEXT_AEBP CONTEXT_REGS[REG_RBP]
84 #define CONTEXT_AESI CONTEXT_REGS[REG_RSI]
85 #define CONTEXT_AEDI CONTEXT_REGS[REG_RDI]
86 #endif
87
88
89 #include "sigsegv_common_x86.h"
90
segfault_vec(int,siginfo_t * sip,void * _ucp)91 static void segfault_vec(int /* sig */, siginfo_t *sip, void *_ucp)
92 {
93 CONTEXT_ATYPE CONTEXT_NAME = (CONTEXT_ATYPE) _ucp;
94 uintptr faultaddr = (uintptr)sip->si_addr; /* CONTEXT_REGS[REG_CR2] */
95 memptr addr = (memptr)(faultaddr - fixed_memory_offset);
96 #if DEBUG
97 if (addr >= 0xff000000)
98 addr &= 0x00ffffff;
99 if (addr < 0x00f00000 || addr > 0x00ffffff) // YYY
100 bug("\nsegfault: pc=%08x, " REG_RIP_NAME " =%p, addr=%p (0x%08x)", m68k_getpc(), (void *)CONTEXT_AEIP, sip->si_addr, addr);
101 if (faultaddr < (uintptr)(fixed_memory_offset - 0x1000000UL)
102 #ifdef CPU_x86_64
103 || faultaddr >= ((uintptr)fixed_memory_offset + 0x100000000UL)
104 #endif
105 )
106 {
107 #ifdef HAVE_DISASM_X86
108 if (CONTEXT_AEIP != 0)
109 {
110 char buf[256];
111
112 x86_disasm((const uint8 *)CONTEXT_AEIP, buf, 1);
113 panicbug("%s", buf);
114 }
115 #endif
116 // raise(SIGBUS);
117 }
118 #endif
119 if (faultaddr == 0 || CONTEXT_AEIP == 0)
120 {
121 real_segmentationfault();
122 /* not reached (hopefully) */
123 return;
124 }
125 handle_access_fault(CONTEXT_NAME, addr);
126 }
127
install_sigsegv()128 void install_sigsegv() {
129 struct sigaction act;
130 memset(&act, 0, sizeof(act));
131 sigemptyset(&act.sa_mask);
132 act.sa_sigaction = segfault_vec;
133 act.sa_flags = SA_SIGINFO;
134 sigaction(SIGSEGV, &act, NULL);
135 #if defined(CPU_x86_64) /* XXX is this really neccessary? */
136 sigaction(SIGILL, &act, NULL);
137 #endif
138 }
139
uninstall_sigsegv()140 void uninstall_sigsegv()
141 {
142 signal(SIGSEGV, SIG_DFL);
143 #ifdef HW_SIGSEGV_STATISTICS
144 for (unsigned int i = 0; i < 256; i++)
145 if (x86_opcodes[i] != 0)
146 bug("opcodes: %02x = %lu", i, x86_opcodes[i]);
147 #endif
148 }
149
150 #endif
151