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