blob: 435f280a6b14f1c8bb52d85dd67f2f051e29d925 [file] [log] [blame]
Dave Allisonb373e092014-02-20 16:06:36 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18#include "fault_handler.h"
19#include <sys/ucontext.h>
20#include "base/macros.h"
21#include "globals.h"
22#include "base/logging.h"
23#include "base/hex_dump.h"
Dave Allison69dfe512014-07-11 17:11:58 +000024#include "mirror/art_method.h"
25#include "mirror/art_method-inl.h"
26#include "thread.h"
27#include "thread-inl.h"
Dave Allisonb373e092014-02-20 16:06:36 -080028
Dave Allison69dfe512014-07-11 17:11:58 +000029#if defined(__APPLE__)
30#define ucontext __darwin_ucontext
31#define CTX_ESP uc_mcontext->__ss.__esp
32#define CTX_EIP uc_mcontext->__ss.__eip
33#define CTX_EAX uc_mcontext->__ss.__eax
34#else
35#define CTX_ESP uc_mcontext.gregs[REG_ESP]
36#define CTX_EIP uc_mcontext.gregs[REG_EIP]
37#define CTX_EAX uc_mcontext.gregs[REG_EAX]
38#endif
Dave Allisonb373e092014-02-20 16:06:36 -080039
40//
41// X86 specific fault handler functions.
42//
43
44namespace art {
45
Dave Allison69dfe512014-07-11 17:11:58 +000046extern "C" void art_quick_throw_null_pointer_exception();
47extern "C" void art_quick_throw_stack_overflow_from_signal();
48extern "C" void art_quick_test_suspend();
49
50// From the x86 disassembler...
51enum SegmentPrefix {
52 kCs = 0x2e,
53 kSs = 0x36,
54 kDs = 0x3e,
55 kEs = 0x26,
56 kFs = 0x64,
57 kGs = 0x65,
58};
59
60// Get the size of an instruction in bytes.
61static uint32_t GetInstructionSize(uint8_t* pc) {
62 uint8_t* instruction_start = pc;
63 bool have_prefixes = true;
64 bool two_byte = false;
65
66 // Skip all the prefixes.
67 do {
68 switch (*pc) {
69 // Group 1 - lock and repeat prefixes:
70 case 0xF0:
71 case 0xF2:
72 case 0xF3:
73 // Group 2 - segment override prefixes:
74 case kCs:
75 case kSs:
76 case kDs:
77 case kEs:
78 case kFs:
79 case kGs:
80 // Group 3 - operand size override:
81 case 0x66:
82 // Group 4 - address size override:
83 case 0x67:
84 break;
85 default:
86 have_prefixes = false;
87 break;
88 }
89 if (have_prefixes) {
90 pc++;
91 }
92 } while (have_prefixes);
93
94#if defined(__x86_64__)
95 // Skip REX is present.
96 if (*pc >= 0x40 && *pc <= 0x4F) {
97 ++pc;
98 }
99#endif
100
101 // Check for known instructions.
102 uint32_t known_length = 0;
103 switch (*pc) {
104 case 0x83: // cmp [r + v], b: 4 byte instruction
105 known_length = 4;
106 break;
107 }
108
109 if (known_length > 0) {
110 VLOG(signals) << "known instruction with length " << known_length;
111 return known_length;
112 }
113
114 // Unknown instruction, work out length.
115
116 // Work out if we have a ModR/M byte.
117 uint8_t opcode = *pc++;
118 if (opcode == 0xf) {
119 two_byte = true;
120 opcode = *pc++;
121 }
122
123 bool has_modrm = false; // Is ModR/M byte present?
124 uint8_t hi = opcode >> 4; // Opcode high nybble.
125 uint8_t lo = opcode & 0b1111; // Opcode low nybble.
126
127 // From the Intel opcode tables.
128 if (two_byte) {
129 has_modrm = true; // TODO: all of these?
130 } else if (hi < 4) {
131 has_modrm = lo < 4 || (lo >= 8 && lo <= 0xb);
132 } else if (hi == 6) {
133 has_modrm = lo == 3 || lo == 9 || lo == 0xb;
134 } else if (hi == 8) {
135 has_modrm = lo != 0xd;
136 } else if (hi == 0xc) {
137 has_modrm = lo == 1 || lo == 2 || lo == 6 || lo == 7;
138 } else if (hi == 0xd) {
139 has_modrm = lo < 4;
140 } else if (hi == 0xf) {
141 has_modrm = lo == 6 || lo == 7;
142 }
143
144 if (has_modrm) {
145 uint8_t modrm = *pc++;
146 uint8_t mod = (modrm >> 6) & 0b11;
147 uint8_t reg = (modrm >> 3) & 0b111;
148 switch (mod) {
149 case 0:
150 break;
151 case 1:
152 if (reg == 4) {
153 // SIB + 1 byte displacement.
154 pc += 2;
155 } else {
156 pc += 1;
157 }
158 break;
159 case 2:
160 // SIB + 4 byte displacement.
161 pc += 5;
162 break;
163 case 3:
164 break;
165 }
166 }
167
168 VLOG(signals) << "calculated X86 instruction size is " << (pc - instruction_start);
169 return pc - instruction_start;
170}
171
172void FaultManager::GetMethodAndReturnPCAndSP(siginfo_t* siginfo, void* context,
173 mirror::ArtMethod** out_method,
Mathieu Chartierc751fdc2014-03-30 15:25:44 -0700174 uintptr_t* out_return_pc, uintptr_t* out_sp) {
Dave Allison69dfe512014-07-11 17:11:58 +0000175 struct ucontext* uc = reinterpret_cast<struct ucontext*>(context);
176 *out_sp = static_cast<uintptr_t>(uc->CTX_ESP);
177 VLOG(signals) << "sp: " << std::hex << *out_sp;
178 if (*out_sp == 0) {
179 return;
180 }
181
182 // In the case of a stack overflow, the stack is not valid and we can't
183 // get the method from the top of the stack. However it's in EAX.
184 uintptr_t* fault_addr = reinterpret_cast<uintptr_t*>(siginfo->si_addr);
185 uintptr_t* overflow_addr = reinterpret_cast<uintptr_t*>(
186 reinterpret_cast<uint8_t*>(*out_sp) - GetStackOverflowReservedBytes(kX86));
187 if (overflow_addr == fault_addr) {
188 *out_method = reinterpret_cast<mirror::ArtMethod*>(uc->CTX_EAX);
189 } else {
190 // The method is at the top of the stack.
191 *out_method = reinterpret_cast<mirror::ArtMethod*>(reinterpret_cast<uintptr_t*>(*out_sp)[0]);
192 }
193
194 uint8_t* pc = reinterpret_cast<uint8_t*>(uc->CTX_EIP);
195 VLOG(signals) << HexDump(pc, 32, true, "PC ");
196
197 uint32_t instr_size = GetInstructionSize(pc);
198 *out_return_pc = reinterpret_cast<uintptr_t>(pc + instr_size);
Dave Allisonb373e092014-02-20 16:06:36 -0800199}
200
201bool NullPointerHandler::Action(int sig, siginfo_t* info, void* context) {
Dave Allison69dfe512014-07-11 17:11:58 +0000202 struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
203 uint8_t* pc = reinterpret_cast<uint8_t*>(uc->CTX_EIP);
204 uint8_t* sp = reinterpret_cast<uint8_t*>(uc->CTX_ESP);
205
206 uint32_t instr_size = GetInstructionSize(pc);
207 // We need to arrange for the signal handler to return to the null pointer
208 // exception generator. The return address must be the address of the
209 // next instruction (this instruction + instruction size). The return address
210 // is on the stack at the top address of the current frame.
211
212 // Push the return address onto the stack.
213 uint32_t retaddr = reinterpret_cast<uint32_t>(pc + instr_size);
214 uint32_t* next_sp = reinterpret_cast<uint32_t*>(sp - 4);
215 *next_sp = retaddr;
216 uc->CTX_ESP = reinterpret_cast<uint32_t>(next_sp);
217
218 uc->CTX_EIP = reinterpret_cast<uintptr_t>(art_quick_throw_null_pointer_exception);
219 VLOG(signals) << "Generating null pointer exception";
220 return true;
221}
222
223// A suspend check is done using the following instruction sequence:
224// 0xf720f1df: 648B058C000000 mov eax, fs:[0x8c] ; suspend_trigger
225// .. some intervening instructions.
226// 0xf720f1e6: 8500 test eax, [eax]
227
228// The offset from fs is Thread::ThreadSuspendTriggerOffset().
229// To check for a suspend check, we examine the instructions that caused
230// the fault.
231bool SuspensionHandler::Action(int sig, siginfo_t* info, void* context) {
232 // These are the instructions to check for. The first one is the mov eax, fs:[xxx]
233 // where xxx is the offset of the suspend trigger.
234 uint32_t trigger = Thread::ThreadSuspendTriggerOffset<4>().Int32Value();
235
236 VLOG(signals) << "Checking for suspension point";
237 uint8_t checkinst1[] = {0x64, 0x8b, 0x05, static_cast<uint8_t>(trigger & 0xff),
238 static_cast<uint8_t>((trigger >> 8) & 0xff), 0, 0};
239 uint8_t checkinst2[] = {0x85, 0x00};
240
241 struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
242 uint8_t* pc = reinterpret_cast<uint8_t*>(uc->CTX_EIP);
243 uint8_t* sp = reinterpret_cast<uint8_t*>(uc->CTX_ESP);
244
245 if (pc[0] != checkinst2[0] || pc[1] != checkinst2[1]) {
246 // Second instruction is not correct (test eax,[eax]).
247 VLOG(signals) << "Not a suspension point";
248 return false;
249 }
250
251 // The first instruction can a little bit up the stream due to load hoisting
252 // in the compiler.
253 uint8_t* limit = pc - 100; // Compiler will hoist to a max of 20 instructions.
254 uint8_t* ptr = pc - sizeof(checkinst1);
255 bool found = false;
256 while (ptr > limit) {
257 if (memcmp(ptr, checkinst1, sizeof(checkinst1)) == 0) {
258 found = true;
259 break;
260 }
261 ptr -= 1;
262 }
263
264 if (found) {
265 VLOG(signals) << "suspend check match";
266
267 // We need to arrange for the signal handler to return to the null pointer
268 // exception generator. The return address must be the address of the
269 // next instruction (this instruction + 2). The return address
270 // is on the stack at the top address of the current frame.
271
272 // Push the return address onto the stack.
273 uint32_t retaddr = reinterpret_cast<uint32_t>(pc + 2);
274 uint32_t* next_sp = reinterpret_cast<uint32_t*>(sp - 4);
275 *next_sp = retaddr;
276 uc->CTX_ESP = reinterpret_cast<uint32_t>(next_sp);
277
278 uc->CTX_EIP = reinterpret_cast<uintptr_t>(art_quick_test_suspend);
279
280 // Now remove the suspend trigger that caused this fault.
281 Thread::Current()->RemoveSuspendTrigger();
282 VLOG(signals) << "removed suspend trigger invoking test suspend";
283 return true;
284 }
285 VLOG(signals) << "Not a suspend check match, first instruction mismatch";
Dave Allisonb373e092014-02-20 16:06:36 -0800286 return false;
287}
288
Dave Allison69dfe512014-07-11 17:11:58 +0000289// The stack overflow check is done using the following instruction:
290// test eax, [esp+ -xxx]
291// where 'xxx' is the size of the overflow area.
292//
293// This is done before any frame is established in the method. The return
294// address for the previous method is on the stack at ESP.
Dave Allisonb373e092014-02-20 16:06:36 -0800295
296bool StackOverflowHandler::Action(int sig, siginfo_t* info, void* context) {
Dave Allison69dfe512014-07-11 17:11:58 +0000297 struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
298 uintptr_t sp = static_cast<uintptr_t>(uc->CTX_ESP);
299
300 uintptr_t fault_addr = reinterpret_cast<uintptr_t>(info->si_addr);
301 VLOG(signals) << "fault_addr: " << std::hex << fault_addr;
302 VLOG(signals) << "checking for stack overflow, sp: " << std::hex << sp <<
303 ", fault_addr: " << fault_addr;
304
305 uintptr_t overflow_addr = sp - GetStackOverflowReservedBytes(kX86);
306
307 Thread* self = Thread::Current();
308 uintptr_t pregion = reinterpret_cast<uintptr_t>(self->GetStackEnd()) -
309 Thread::kStackOverflowProtectedSize;
310
311 // Check that the fault address is the value expected for a stack overflow.
312 if (fault_addr != overflow_addr) {
313 VLOG(signals) << "Not a stack overflow";
314 return false;
315 }
316
317 // We know this is a stack overflow. We need to move the sp to the overflow region
318 // that exists below the protected region. Determine the address of the next
319 // available valid address below the protected region.
320 VLOG(signals) << "setting sp to overflow region at " << std::hex << pregion;
321
322 // Since the compiler puts the implicit overflow
323 // check before the callee save instructions, the SP is already pointing to
324 // the previous frame.
325
326 // Tell the stack overflow code where the new stack pointer should be.
327 uc->CTX_EAX = pregion;
328
329 // Now arrange for the signal handler to return to art_quick_throw_stack_overflow_from_signal.
330 uc->CTX_EIP = reinterpret_cast<uintptr_t>(art_quick_throw_stack_overflow_from_signal);
331
332 return true;
Dave Allisonb373e092014-02-20 16:06:36 -0800333}
334} // namespace art