fault_handler_x86.cc revision 63c051a540e6dfc806f656b88ac3a63e99395429
1/*
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"
24#include "mirror/art_method.h"
25#include "mirror/art_method-inl.h"
26#include "thread.h"
27#include "thread-inl.h"
28
29#if defined(__APPLE__)
30#define ucontext __darwin_ucontext
31
32#if defined(__x86_64__)
33// 64 bit mac build.
34#define CTX_ESP uc_mcontext->__ss.__rsp
35#define CTX_EIP uc_mcontext->__ss.__rip
36#define CTX_EAX uc_mcontext->__ss.__rax
37#define CTX_METHOD uc_mcontext->__ss.__rdi
38#else
39// 32 bit mac build.
40#define CTX_ESP uc_mcontext->__ss.__esp
41#define CTX_EIP uc_mcontext->__ss.__eip
42#define CTX_EAX uc_mcontext->__ss.__eax
43#define CTX_METHOD uc_mcontext->__ss.__eax
44#endif
45
46#elif defined(__x86_64__)
47// 64 bit linux build.
48#define CTX_ESP uc_mcontext.gregs[REG_RSP]
49#define CTX_EIP uc_mcontext.gregs[REG_RIP]
50#define CTX_EAX uc_mcontext.gregs[REG_RAX]
51#define CTX_METHOD uc_mcontext.gregs[REG_RDI]
52#else
53// 32 bit linux build.
54#define CTX_ESP uc_mcontext.gregs[REG_ESP]
55#define CTX_EIP uc_mcontext.gregs[REG_EIP]
56#define CTX_EAX uc_mcontext.gregs[REG_EAX]
57#define CTX_METHOD uc_mcontext.gregs[REG_EAX]
58#endif
59
60//
61// X86 (and X86_64) specific fault handler functions.
62//
63
64namespace art {
65
66#if defined(__APPLE__) && defined(__x86_64__)
67// mac symbols have a prefix of _ on x86_64
68extern "C" void _art_quick_throw_null_pointer_exception();
69extern "C" void _art_quick_throw_stack_overflow_from_signal();
70extern "C" void _art_quick_test_suspend();
71#define EXT_SYM(sym) _ ## sym
72#else
73extern "C" void art_quick_throw_null_pointer_exception();
74extern "C" void art_quick_throw_stack_overflow();
75extern "C" void art_quick_test_suspend();
76#define EXT_SYM(sym) sym
77#endif
78
79// Get the size of an instruction in bytes.
80// Return 0 if the instruction is not handled.
81static uint32_t GetInstructionSize(const uint8_t* pc) {
82#if defined(__x86_64)
83  const bool x86_64 = true;
84#else
85  const bool x86_64 = false;
86#endif
87
88  const uint8_t* startpc = pc;
89
90  uint8_t opcode = *pc++;
91  uint8_t modrm;
92  bool has_modrm = false;
93  bool two_byte = false;
94  uint32_t displacement_size = 0;
95  uint32_t immediate_size = 0;
96
97  // Prefixes.
98  while (true) {
99    bool prefix_present = false;
100    switch (opcode) {
101      // Group 1
102      case 0xf0:
103      case 0xf2:
104      case 0xf3:
105
106      // Group 2
107      case 0x2e:
108      case 0x36:
109      case 0x3e:
110      case 0x26:
111      case 0x64:
112      case 0x65:
113
114      // Group 3
115      case 0x66:
116
117      // Group 4
118      case 0x67:
119        opcode = *pc++;
120        prefix_present = true;
121        break;
122    }
123    if (!prefix_present) {
124      break;
125    }
126  }
127
128  if (x86_64 && opcode >= 0x40 && opcode <= 0x4f) {
129    opcode = *pc++;
130  }
131
132  if (opcode == 0x0f) {
133    // Two byte opcode
134    two_byte = true;
135    opcode = *pc++;
136  }
137
138  bool unhandled_instruction = false;
139
140  if (two_byte) {
141    switch (opcode) {
142      case 0x10:            // vmovsd/ss
143      case 0x11:            // vmovsd/ss
144      case 0xb6:        // movzx
145      case 0xb7:
146      case 0xbe:        // movsx
147      case 0xbf:
148        modrm = *pc++;
149        has_modrm = true;
150        break;
151      default:
152        unhandled_instruction = true;
153        break;
154    }
155  } else {
156    switch (opcode) {
157      case 0x89:            // mov
158      case 0x8b:
159      case 0x38:        // cmp with memory.
160      case 0x39:
161      case 0x3a:
162      case 0x3b:
163      case 0x3c:
164      case 0x3d:
165      case 0x85:        // test.
166        modrm = *pc++;
167        has_modrm = true;
168        break;
169
170      case 0x80:        // group 1, byte immediate.
171      case 0x83:
172        modrm = *pc++;
173        has_modrm = true;
174        immediate_size = 1;
175        break;
176
177      case 0x81:        // group 1, word immediate.
178        modrm = *pc++;
179        has_modrm = true;
180        immediate_size = 4;
181        break;
182
183      default:
184        unhandled_instruction = true;
185        break;
186    }
187  }
188
189  if (unhandled_instruction) {
190    VLOG(signals) << "Unhandled x86 instruction with opcode " << static_cast<int>(opcode);
191    return 0;
192  }
193
194  if (has_modrm) {
195    uint8_t mod = (modrm >> 6) & 0b11;
196
197    // Check for SIB.
198    if (mod != 0b11 && (modrm & 0b111) == 4) {
199      ++pc;     // SIB
200    }
201
202    switch (mod) {
203      case 0b00: break;
204      case 0b01: displacement_size = 1; break;
205      case 0b10: displacement_size = 4; break;
206      case 0b11:
207        break;
208    }
209  }
210
211  // Skip displacement and immediate.
212  pc += displacement_size + immediate_size;
213
214  VLOG(signals) << "x86 instruction length calculated as " << (pc - startpc);
215  return pc - startpc;
216}
217
218void FaultManager::GetMethodAndReturnPcAndSp(siginfo_t* siginfo, void* context,
219                                             mirror::ArtMethod** out_method,
220                                             uintptr_t* out_return_pc, uintptr_t* out_sp) {
221  struct ucontext* uc = reinterpret_cast<struct ucontext*>(context);
222  *out_sp = static_cast<uintptr_t>(uc->CTX_ESP);
223  VLOG(signals) << "sp: " << std::hex << *out_sp;
224  if (*out_sp == 0) {
225    return;
226  }
227
228  // In the case of a stack overflow, the stack is not valid and we can't
229  // get the method from the top of the stack.  However it's in EAX(x86)/RDI(x86_64).
230  uintptr_t* fault_addr = reinterpret_cast<uintptr_t*>(siginfo->si_addr);
231  uintptr_t* overflow_addr = reinterpret_cast<uintptr_t*>(
232#if defined(__x86_64__)
233      reinterpret_cast<uint8_t*>(*out_sp) - GetStackOverflowReservedBytes(kX86_64));
234#else
235      reinterpret_cast<uint8_t*>(*out_sp) - GetStackOverflowReservedBytes(kX86));
236#endif
237  if (overflow_addr == fault_addr) {
238    *out_method = reinterpret_cast<mirror::ArtMethod*>(uc->CTX_METHOD);
239  } else {
240    // The method is at the top of the stack.
241    *out_method = (reinterpret_cast<StackReference<mirror::ArtMethod>* >(*out_sp)[0]).AsMirrorPtr();
242  }
243
244  uint8_t* pc = reinterpret_cast<uint8_t*>(uc->CTX_EIP);
245  VLOG(signals) << HexDump(pc, 32, true, "PC ");
246
247  uint32_t instr_size = GetInstructionSize(pc);
248  if (instr_size == 0) {
249    // Unknown instruction, tell caller it's not ours.
250    *out_method = nullptr;
251    return;
252  }
253  *out_return_pc = reinterpret_cast<uintptr_t>(pc + instr_size);
254}
255
256bool NullPointerHandler::Action(int sig, siginfo_t* info, void* context) {
257  struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
258  uint8_t* pc = reinterpret_cast<uint8_t*>(uc->CTX_EIP);
259  uint8_t* sp = reinterpret_cast<uint8_t*>(uc->CTX_ESP);
260
261  uint32_t instr_size = GetInstructionSize(pc);
262  if (instr_size == 0) {
263    // Unknown instruction, can't really happen.
264    return false;
265  }
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 + instruction size).  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  uintptr_t retaddr = reinterpret_cast<uintptr_t>(pc + instr_size);
274  uintptr_t* next_sp = reinterpret_cast<uintptr_t*>(sp - sizeof(uintptr_t));
275  *next_sp = retaddr;
276  uc->CTX_ESP = reinterpret_cast<uintptr_t>(next_sp);
277
278  uc->CTX_EIP = reinterpret_cast<uintptr_t>(EXT_SYM(art_quick_throw_null_pointer_exception));
279  VLOG(signals) << "Generating null pointer exception";
280  return true;
281}
282
283// A suspend check is done using the following instruction sequence:
284// (x86)
285// 0xf720f1df:         648B058C000000      mov     eax, fs:[0x8c]  ; suspend_trigger
286// .. some intervening instructions.
287// 0xf720f1e6:                   8500      test    eax, [eax]
288// (x86_64)
289// 0x7f579de45d9e: 65488B0425A8000000      movq    rax, gs:[0xa8]  ; suspend_trigger
290// .. some intervening instructions.
291// 0x7f579de45da7:               8500      test    eax, [eax]
292
293// The offset from fs is Thread::ThreadSuspendTriggerOffset().
294// To check for a suspend check, we examine the instructions that caused
295// the fault.
296bool SuspensionHandler::Action(int sig, siginfo_t* info, void* context) {
297  // These are the instructions to check for.  The first one is the mov eax, fs:[xxx]
298  // where xxx is the offset of the suspend trigger.
299#if defined(__x86_64__)
300  uint32_t trigger = Thread::ThreadSuspendTriggerOffset<8>().Int32Value();
301#else
302  uint32_t trigger = Thread::ThreadSuspendTriggerOffset<4>().Int32Value();
303#endif
304
305  VLOG(signals) << "Checking for suspension point";
306#if defined(__x86_64__)
307  uint8_t checkinst1[] = {0x65, 0x48, 0x8b, 0x04, 0x25, static_cast<uint8_t>(trigger & 0xff),
308      static_cast<uint8_t>((trigger >> 8) & 0xff), 0, 0};
309#else
310  uint8_t checkinst1[] = {0x64, 0x8b, 0x05, static_cast<uint8_t>(trigger & 0xff),
311      static_cast<uint8_t>((trigger >> 8) & 0xff), 0, 0};
312#endif
313  uint8_t checkinst2[] = {0x85, 0x00};
314
315  struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
316  uint8_t* pc = reinterpret_cast<uint8_t*>(uc->CTX_EIP);
317  uint8_t* sp = reinterpret_cast<uint8_t*>(uc->CTX_ESP);
318
319  if (pc[0] != checkinst2[0] || pc[1] != checkinst2[1]) {
320    // Second instruction is not correct (test eax,[eax]).
321    VLOG(signals) << "Not a suspension point";
322    return false;
323  }
324
325  // The first instruction can a little bit up the stream due to load hoisting
326  // in the compiler.
327  uint8_t* limit = pc - 100;   // Compiler will hoist to a max of 20 instructions.
328  uint8_t* ptr = pc - sizeof(checkinst1);
329  bool found = false;
330  while (ptr > limit) {
331    if (memcmp(ptr, checkinst1, sizeof(checkinst1)) == 0) {
332      found = true;
333      break;
334    }
335    ptr -= 1;
336  }
337
338  if (found) {
339    VLOG(signals) << "suspend check match";
340
341    // We need to arrange for the signal handler to return to the null pointer
342    // exception generator.  The return address must be the address of the
343    // next instruction (this instruction + 2).  The return address
344    // is on the stack at the top address of the current frame.
345
346    // Push the return address onto the stack.
347    uintptr_t retaddr = reinterpret_cast<uintptr_t>(pc + 2);
348    uintptr_t* next_sp = reinterpret_cast<uintptr_t*>(sp - sizeof(uintptr_t));
349    *next_sp = retaddr;
350    uc->CTX_ESP = reinterpret_cast<uintptr_t>(next_sp);
351
352    uc->CTX_EIP = reinterpret_cast<uintptr_t>(EXT_SYM(art_quick_test_suspend));
353
354    // Now remove the suspend trigger that caused this fault.
355    Thread::Current()->RemoveSuspendTrigger();
356    VLOG(signals) << "removed suspend trigger invoking test suspend";
357    return true;
358  }
359  VLOG(signals) << "Not a suspend check match, first instruction mismatch";
360  return false;
361}
362
363// The stack overflow check is done using the following instruction:
364// test eax, [esp+ -xxx]
365// where 'xxx' is the size of the overflow area.
366//
367// This is done before any frame is established in the method.  The return
368// address for the previous method is on the stack at ESP.
369
370bool StackOverflowHandler::Action(int sig, siginfo_t* info, void* context) {
371  struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
372  uintptr_t sp = static_cast<uintptr_t>(uc->CTX_ESP);
373
374  uintptr_t fault_addr = reinterpret_cast<uintptr_t>(info->si_addr);
375  VLOG(signals) << "fault_addr: " << std::hex << fault_addr;
376  VLOG(signals) << "checking for stack overflow, sp: " << std::hex << sp <<
377    ", fault_addr: " << fault_addr;
378
379#if defined(__x86_64__)
380  uintptr_t overflow_addr = sp - GetStackOverflowReservedBytes(kX86_64);
381#else
382  uintptr_t overflow_addr = sp - GetStackOverflowReservedBytes(kX86);
383#endif
384
385  // Check that the fault address is the value expected for a stack overflow.
386  if (fault_addr != overflow_addr) {
387    VLOG(signals) << "Not a stack overflow";
388    return false;
389  }
390
391  VLOG(signals) << "Stack overflow found";
392
393  // Since the compiler puts the implicit overflow
394  // check before the callee save instructions, the SP is already pointing to
395  // the previous frame.
396
397  // Now arrange for the signal handler to return to art_quick_throw_stack_overflow.
398  uc->CTX_EIP = reinterpret_cast<uintptr_t>(art_quick_throw_stack_overflow);
399
400  return true;
401}
402}       // namespace art
403