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