1 /*
2 * sigsegv_linux_x86.cpp - x86/x86_64 Linux 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 #define DEBUG 0
34 #include "debug.h"
35
36 #include <csignal>
37
38 #ifdef CPU_i386
39 #define REG_RIP REG_EIP
40 #define REG_RAX REG_EAX
41 #define REG_RBX REG_EBX
42 #define REG_RCX REG_ECX
43 #define REG_RDX REG_EDX
44 #define REG_RBP REG_EBP
45 #define REG_RSI REG_ESI
46 #define REG_RDI REG_EDI
47 #define REG_RSP REG_ESP
48 #endif
49 #if defined(CPU_i386) || defined(CPU_x86_64)
50 #define CONTEXT_NAME ucp
51 #define CONTEXT_TYPE volatile ucontext_t
52 #define CONTEXT_ATYPE CONTEXT_TYPE *
53 #define CONTEXT_REGS CONTEXT_NAME->uc_mcontext.gregs
54 #define CONTEXT_AEFLAGS CONTEXT_REGS[REG_EFL]
55 #define CONTEXT_AEIP CONTEXT_REGS[REG_RIP]
56 #define CONTEXT_AEAX CONTEXT_REGS[REG_RAX]
57 #define CONTEXT_AEBX CONTEXT_REGS[REG_RBX]
58 #define CONTEXT_AECX CONTEXT_REGS[REG_RCX]
59 #define CONTEXT_AEDX CONTEXT_REGS[REG_RDX]
60 #define CONTEXT_AEBP CONTEXT_REGS[REG_RBP]
61 #define CONTEXT_AESI CONTEXT_REGS[REG_RSI]
62 #define CONTEXT_AEDI CONTEXT_REGS[REG_RDI]
63 #endif
64
65
66 #include "sigsegv_common_x86.h"
67
segfault_vec(int,siginfo_t * sip,void * _ucp)68 static void segfault_vec(int /* sig */, siginfo_t *sip, void *_ucp)
69 {
70 CONTEXT_ATYPE CONTEXT_NAME = (CONTEXT_ATYPE) _ucp;
71 uintptr faultaddr = (uintptr)sip->si_addr; /* CONTEXT_REGS[REG_CR2] */
72 memptr addr = (memptr)(faultaddr - fixed_memory_offset);
73 #if DEBUG
74 if (addr >= 0xff000000)
75 addr &= 0x00ffffff;
76 if (addr < 0x00f00000 || addr > 0x00ffffff) // YYY
77 bug("\nsegfault: pc=%08x, " REG_RIP_NAME " =%p, addr=%p (0x%08x)", m68k_getpc(), (void *)CONTEXT_AEIP, sip->si_addr, addr);
78 if (faultaddr < (uintptr)(fixed_memory_offset - 0x1000000UL)
79 #ifdef CPU_x86_64
80 || faultaddr >= ((uintptr)fixed_memory_offset + 0x100000000UL)
81 #endif
82 )
83 {
84 #ifdef HAVE_DISASM_X86
85 if (CONTEXT_AEIP != 0)
86 {
87 char buf[256];
88
89 x86_disasm((const uint8 *)CONTEXT_AEIP, buf, 1);
90 panicbug("%s", buf);
91 }
92 #endif
93 // raise(SIGBUS);
94 }
95 #endif
96 if (faultaddr == 0 || CONTEXT_AEIP == 0)
97 {
98 real_segmentationfault();
99 /* not reached (hopefully) */
100 return;
101 }
102 handle_access_fault(CONTEXT_NAME, addr);
103 }
104
install_sigsegv()105 void install_sigsegv() {
106 struct sigaction act;
107 memset(&act, 0, sizeof(act));
108 sigemptyset(&act.sa_mask);
109 act.sa_sigaction = segfault_vec;
110 act.sa_flags = SA_SIGINFO;
111 sigaction(SIGSEGV, &act, NULL);
112 #if defined(CPU_x86_64) /* XXX is this really neccessary? */
113 sigaction(SIGILL, &act, NULL);
114 #endif
115 }
116
uninstall_sigsegv()117 void uninstall_sigsegv()
118 {
119 signal(SIGSEGV, SIG_DFL);
120 #ifdef HW_SIGSEGV_STATISTICS
121 for (unsigned int i = 0; i < 256; i++)
122 if (x86_opcodes[i] != 0)
123 bug("opcodes: %02x = %lu", i, x86_opcodes[i]);
124 #endif
125 }
126