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