1 /*
2  * sigsegv_xbsd_x86.cpp - x86/x86_64 BSD SIGSEGV handler
3  *
4  * Copyright (c) 2001-2005 Milan Jurik of ARAnyM dev team (see AUTHORS)
5  *
6  * Inspired by Bernie Meyer's UAE-JIT and Gwenole Beauchesne's Basilisk II-JIT
7  *
8  * This file is part of the ARAnyM project which builds a new and powerful
9  * TOS/FreeMiNT compatible virtual machine running on almost any hardware.
10  *
11  * ARAnyM is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * ARAnyM is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with ARAnyM; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  *
25  * 2013-06-16 : Adapted to 64 Bit Linux - Jens Heitmann
26  * 2014-07-05 : Merged with 64bit version,
27  *              lots of fixes - Thorsten Otto
28  *
29  */
30 
31 #include "sysdeps.h"
32 #include "cpu_emulation.h"
33 #include "memory-uae.h"
34 #define DEBUG 0
35 #include "debug.h"
36 
37 #include <csignal>
38 
39 #ifndef HAVE_SIGHANDLER_T
40 typedef void (*sighandler_t)(int);
41 #endif
42 
43 #if defined(OS_freebsd)
44 #include <ucontext.h>
45 
46 enum {
47 #ifdef CPU_i386
48 #	define CONTEXT_REGS    ((uae_u32 *)&CONTEXT_NAME->uc_mcontext.mc_edi)
49 	REG_EDI = 0,
50 	REG_ESI = 1,
51 	REG_EBP = 2,
52 	REG_EBX = 4,
53 	REG_EDX = 5,
54 	REG_ECX = 6,
55 	REG_EAX = 7,
56 	REG_EIP = 10,
57 	REG_EFL = 12,
58 	REG_ESP = 13,
59 #endif
60 #if defined(CPU_x86_64)
61 #	define CONTEXT_REGS    ((uae_u64 *)&CONTEXT_NAME->uc_mcontext.mc_rdi)
62 	REG_RDI = 0,
63 	REG_RSI = 1,
64 	REG_RDX = 2,
65 	REG_RCX = 3,
66 
67 	REG_R8  = 4,
68 	REG_R9  = 5,
69 
70 	REG_RAX = 6,
71 	REG_RBX = 7,
72 	REG_RBP = 8,
73 
74 	REG_R10 = 9,
75 	REG_R11 = 10,
76 	REG_R12 = 11,
77 	REG_R13 = 12,
78 	REG_R14 = 13,
79 	REG_R15 = 14,
80 
81 	REG_EFL = 21,
82 
83 	REG_RIP = 19,
84 
85 	REG_RSP = 22,
86 
87 #endif
88 };
89 #endif
90 
91 #if defined(OS_openbsd)
92 enum {
93 #ifdef CPU_i386
94 #	define CONTEXT_REGS    ((uae_u32 *)&CONTEXT_NAME->sc_edi)
95 	REG_EDI = 0,
96 	REG_ESI = 1,
97 	REG_EBP = 2,
98 	REG_EBX = 3,
99 	REG_EDX = 4,
100 	REG_ECX = 5,
101 	REG_EAX = 6,
102 	REG_EIP = 7,
103 	REG_EFL = 8,
104 	REG_ESP = 9,
105 #endif
106 #if defined(CPU_x86_64)
107 #	define CONTEXT_REGS    ((uae_u64 *)&CONTEXT_NAME->sc_rdi)
108 	REG_RDI = 0,
109 	REG_RSI = 1,
110 	REG_RDX = 2,
111 	REG_RCX = 3,
112 
113 	REG_R8  = 4,
114 	REG_R9  = 5,
115 	REG_R10 = 6,
116 	REG_R11 = 7,
117 	REG_R12 = 8,
118 	REG_R13 = 9,
119 	REG_R14 = 10,
120 	REG_R15 = 11,
121 
122 	REG_RBP = 12,
123 	REG_RBX = 13,
124 	REG_RAX = 14,
125 
126 	REG_RIP = 21,
127 
128 	REG_EFL = 23,
129 
130 	REG_RSP = 24,
131 
132 #endif
133 };
134 #endif
135 
136 #ifdef CPU_i386
137 #define REG_RIP REG_EIP
138 #define REG_RAX REG_EAX
139 #define REG_RBX REG_EBX
140 #define REG_RCX REG_ECX
141 #define REG_RDX REG_EDX
142 #define REG_RBP REG_EBP
143 #define REG_RSI REG_ESI
144 #define REG_RDI REG_EDI
145 #define REG_RSP REG_ESP
146 #endif
147 
148 #if defined(CPU_i386) || defined(CPU_x86_64)
149 #define CONTEXT_NAME	uap
150 #define CONTEXT_TYPE	volatile ucontext_t
151 #define CONTEXT_ATYPE	CONTEXT_TYPE *
152 #define CONTEXT_AEFLAGS	CONTEXT_REGS[REG_EFL]
153 #define CONTEXT_AEIP	CONTEXT_REGS[REG_RIP]
154 #define CONTEXT_AEAX	CONTEXT_REGS[REG_RAX]
155 #define CONTEXT_AEBX	CONTEXT_REGS[REG_RBX]
156 #define CONTEXT_AECX	CONTEXT_REGS[REG_RCX]
157 #define CONTEXT_AEDX	CONTEXT_REGS[REG_RDX]
158 #define CONTEXT_AEBP	CONTEXT_REGS[REG_RBP]
159 #define CONTEXT_AESI	CONTEXT_REGS[REG_RSI]
160 #define CONTEXT_AEDI	CONTEXT_REGS[REG_RDI]
161 #endif
162 
163 #include "sigsegv_common_x86.h"
164 
segfault_vec(int,siginfo_t * sip,void * _ucp)165 static void segfault_vec(int /* sig */, siginfo_t *sip, void *_ucp)
166 {
167 	CONTEXT_ATYPE CONTEXT_NAME = (CONTEXT_ATYPE) _ucp;
168 	char *fault_addr = (char *)sip->si_addr;
169 	memptr addr = (memptr)(uintptr)(fault_addr - fixed_memory_offset);
170 #if DEBUG
171 	if (addr >= 0xff000000)
172 		addr &= 0x00ffffff;
173 	if (addr < 0x00f00000 || addr > 0x00ffffff) // YYY
174 		bug("\nsegfault: pc=%08x, " REG_RIP_NAME " =%p, addr=%p (0x%08x)", m68k_getpc(), (void *)CONTEXT_AEIP, fault_addr, addr);
175 	if (fault_addr < (char *)(fixed_memory_offset - 0x1000000UL)
176 #ifdef CPU_x86_64
177 		|| fault_addr >= ((char *)fixed_memory_offset + 0x100000000UL)
178 #endif
179 		)
180 	{
181 #ifdef HAVE_DISASM_X86
182 		if (CONTEXT_AEIP != 0)
183 		{
184 			char buf[256];
185 
186 			x86_disasm((const uint8 *)CONTEXT_AEIP, buf, 1);
187 			panicbug("%s", buf);
188 		}
189 #endif
190 		// raise(SIGBUS);
191 	}
192 #endif
193 	if (fault_addr == 0 || CONTEXT_AEIP == 0)
194 	{
195 		real_segmentationfault();
196 		/* not reached (hopefully) */
197 		return;
198 	}
199 	handle_access_fault((CONTEXT_ATYPE) CONTEXT_NAME, addr);
200 }
201 
install_sigsegv()202 void install_sigsegv() {
203 	struct sigaction sigsegv_sa;
204 	memset(&sigsegv_sa, 0, sizeof(sigsegv_sa));
205 	sigemptyset(&sigsegv_sa.sa_mask);
206 	sigsegv_sa.sa_handler = (sighandler_t) segfault_vec;
207 	sigsegv_sa.sa_flags = SA_SIGINFO;
208 	sigaction(SIGSEGV, &sigsegv_sa, NULL);
209 }
210 
uninstall_sigsegv()211 void uninstall_sigsegv()
212 {
213 	signal(SIGSEGV, SIG_DFL);
214 }
215