Home | History | Annotate | Download | only in x86
      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 
     69 namespace art {
     70 
     71 #if defined(__APPLE__) && defined(__x86_64__)
     72 // mac symbols have a prefix of _ on x86_64
     73 extern "C" void _art_quick_throw_null_pointer_exception();
     74 extern "C" void _art_quick_throw_stack_overflow();
     75 extern "C" void _art_quick_test_suspend();
     76 #define EXT_SYM(sym) _ ## sym
     77 #else
     78 extern "C" void art_quick_throw_null_pointer_exception();
     79 extern "C" void art_quick_throw_stack_overflow();
     80 extern "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.
     88 extern "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.
     92 static 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 0x89:            // mov
    169       case 0x8b:
    170       case 0x38:        // cmp with memory.
    171       case 0x39:
    172       case 0x3a:
    173       case 0x3b:
    174       case 0x3c:
    175       case 0x3d:
    176       case 0x85:        // test.
    177         modrm = *pc++;
    178         has_modrm = true;
    179         break;
    180 
    181       case 0x80:        // group 1, byte immediate.
    182       case 0x83:
    183         modrm = *pc++;
    184         has_modrm = true;
    185         immediate_size = 1;
    186         break;
    187 
    188       case 0x81:        // group 1, word immediate.
    189         modrm = *pc++;
    190         has_modrm = true;
    191         immediate_size = 4;
    192         break;
    193 
    194       default:
    195         unhandled_instruction = true;
    196         break;
    197     }
    198   }
    199 
    200   if (unhandled_instruction) {
    201     VLOG(signals) << "Unhandled x86 instruction with opcode " << static_cast<int>(opcode);
    202     return 0;
    203   }
    204 
    205   if (has_modrm) {
    206     uint8_t mod = (modrm >> 6) & 0b11;
    207 
    208     // Check for SIB.
    209     if (mod != 0b11 && (modrm & 0b111) == 4) {
    210       ++pc;     // SIB
    211     }
    212 
    213     switch (mod) {
    214       case 0b00: break;
    215       case 0b01: displacement_size = 1; break;
    216       case 0b10: displacement_size = 4; break;
    217       case 0b11:
    218         break;
    219     }
    220   }
    221 
    222   // Skip displacement and immediate.
    223   pc += displacement_size + immediate_size;
    224 
    225   VLOG(signals) << "x86 instruction length calculated as " << (pc - startpc);
    226   return pc - startpc;
    227 }
    228 
    229 void FaultManager::HandleNestedSignal(int sig, siginfo_t* info, void* context) {
    230   // For the Intel architectures we need to go to an assembly language
    231   // stub.  This is because the 32 bit call to longjmp is much different
    232   // from the 64 bit ABI call and pushing things onto the stack inside this
    233   // handler was unwieldy and ugly.  The use of the stub means we can keep
    234   // this code the same for both 32 and 64 bit.
    235 
    236   Thread* self = Thread::Current();
    237   CHECK(self != nullptr);       // This will cause a SIGABRT if self is nullptr.
    238 
    239   struct ucontext* uc = reinterpret_cast<struct ucontext*>(context);
    240   uc->CTX_JMP_BUF = reinterpret_cast<uintptr_t>(*self->GetNestedSignalState());
    241   uc->CTX_EIP = reinterpret_cast<uintptr_t>(art_nested_signal_return);
    242 }
    243 
    244 void FaultManager::GetMethodAndReturnPcAndSp(siginfo_t* siginfo, void* context,
    245                                              mirror::ArtMethod** out_method,
    246                                              uintptr_t* out_return_pc, uintptr_t* out_sp) {
    247   struct ucontext* uc = reinterpret_cast<struct ucontext*>(context);
    248   *out_sp = static_cast<uintptr_t>(uc->CTX_ESP);
    249   VLOG(signals) << "sp: " << std::hex << *out_sp;
    250   if (*out_sp == 0) {
    251     return;
    252   }
    253 
    254   // In the case of a stack overflow, the stack is not valid and we can't
    255   // get the method from the top of the stack.  However it's in EAX(x86)/RDI(x86_64).
    256   uintptr_t* fault_addr = reinterpret_cast<uintptr_t*>(siginfo->si_addr);
    257   uintptr_t* overflow_addr = reinterpret_cast<uintptr_t*>(
    258 #if defined(__x86_64__)
    259       reinterpret_cast<uint8_t*>(*out_sp) - GetStackOverflowReservedBytes(kX86_64));
    260 #else
    261       reinterpret_cast<uint8_t*>(*out_sp) - GetStackOverflowReservedBytes(kX86));
    262 #endif
    263   if (overflow_addr == fault_addr) {
    264     *out_method = reinterpret_cast<mirror::ArtMethod*>(uc->CTX_METHOD);
    265   } else {
    266     // The method is at the top of the stack.
    267     *out_method = (reinterpret_cast<StackReference<mirror::ArtMethod>* >(*out_sp)[0]).AsMirrorPtr();
    268   }
    269 
    270   uint8_t* pc = reinterpret_cast<uint8_t*>(uc->CTX_EIP);
    271   VLOG(signals) << HexDump(pc, 32, true, "PC ");
    272 
    273   uint32_t instr_size = GetInstructionSize(pc);
    274   if (instr_size == 0) {
    275     // Unknown instruction, tell caller it's not ours.
    276     *out_method = nullptr;
    277     return;
    278   }
    279   *out_return_pc = reinterpret_cast<uintptr_t>(pc + instr_size);
    280 }
    281 
    282 bool NullPointerHandler::Action(int sig, siginfo_t* info, void* context) {
    283   struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
    284   uint8_t* pc = reinterpret_cast<uint8_t*>(uc->CTX_EIP);
    285   uint8_t* sp = reinterpret_cast<uint8_t*>(uc->CTX_ESP);
    286 
    287   uint32_t instr_size = GetInstructionSize(pc);
    288   if (instr_size == 0) {
    289     // Unknown instruction, can't really happen.
    290     return false;
    291   }
    292 
    293   // We need to arrange for the signal handler to return to the null pointer
    294   // exception generator.  The return address must be the address of the
    295   // next instruction (this instruction + instruction size).  The return address
    296   // is on the stack at the top address of the current frame.
    297 
    298   // Push the return address onto the stack.
    299   uintptr_t retaddr = reinterpret_cast<uintptr_t>(pc + instr_size);
    300   uintptr_t* next_sp = reinterpret_cast<uintptr_t*>(sp - sizeof(uintptr_t));
    301   *next_sp = retaddr;
    302   uc->CTX_ESP = reinterpret_cast<uintptr_t>(next_sp);
    303 
    304   uc->CTX_EIP = reinterpret_cast<uintptr_t>(EXT_SYM(art_quick_throw_null_pointer_exception));
    305   VLOG(signals) << "Generating null pointer exception";
    306   return true;
    307 }
    308 
    309 // A suspend check is done using the following instruction sequence:
    310 // (x86)
    311 // 0xf720f1df:         648B058C000000      mov     eax, fs:[0x8c]  ; suspend_trigger
    312 // .. some intervening instructions.
    313 // 0xf720f1e6:                   8500      test    eax, [eax]
    314 // (x86_64)
    315 // 0x7f579de45d9e: 65488B0425A8000000      movq    rax, gs:[0xa8]  ; suspend_trigger
    316 // .. some intervening instructions.
    317 // 0x7f579de45da7:               8500      test    eax, [eax]
    318 
    319 // The offset from fs is Thread::ThreadSuspendTriggerOffset().
    320 // To check for a suspend check, we examine the instructions that caused
    321 // the fault.
    322 bool SuspensionHandler::Action(int sig, siginfo_t* info, void* context) {
    323   // These are the instructions to check for.  The first one is the mov eax, fs:[xxx]
    324   // where xxx is the offset of the suspend trigger.
    325 #if defined(__x86_64__)
    326   uint32_t trigger = Thread::ThreadSuspendTriggerOffset<8>().Int32Value();
    327 #else
    328   uint32_t trigger = Thread::ThreadSuspendTriggerOffset<4>().Int32Value();
    329 #endif
    330 
    331   VLOG(signals) << "Checking for suspension point";
    332 #if defined(__x86_64__)
    333   uint8_t checkinst1[] = {0x65, 0x48, 0x8b, 0x04, 0x25, static_cast<uint8_t>(trigger & 0xff),
    334       static_cast<uint8_t>((trigger >> 8) & 0xff), 0, 0};
    335 #else
    336   uint8_t checkinst1[] = {0x64, 0x8b, 0x05, static_cast<uint8_t>(trigger & 0xff),
    337       static_cast<uint8_t>((trigger >> 8) & 0xff), 0, 0};
    338 #endif
    339   uint8_t checkinst2[] = {0x85, 0x00};
    340 
    341   struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
    342   uint8_t* pc = reinterpret_cast<uint8_t*>(uc->CTX_EIP);
    343   uint8_t* sp = reinterpret_cast<uint8_t*>(uc->CTX_ESP);
    344 
    345   if (pc[0] != checkinst2[0] || pc[1] != checkinst2[1]) {
    346     // Second instruction is not correct (test eax,[eax]).
    347     VLOG(signals) << "Not a suspension point";
    348     return false;
    349   }
    350 
    351   // The first instruction can a little bit up the stream due to load hoisting
    352   // in the compiler.
    353   uint8_t* limit = pc - 100;   // Compiler will hoist to a max of 20 instructions.
    354   uint8_t* ptr = pc - sizeof(checkinst1);
    355   bool found = false;
    356   while (ptr > limit) {
    357     if (memcmp(ptr, checkinst1, sizeof(checkinst1)) == 0) {
    358       found = true;
    359       break;
    360     }
    361     ptr -= 1;
    362   }
    363 
    364   if (found) {
    365     VLOG(signals) << "suspend check match";
    366 
    367     // We need to arrange for the signal handler to return to the null pointer
    368     // exception generator.  The return address must be the address of the
    369     // next instruction (this instruction + 2).  The return address
    370     // is on the stack at the top address of the current frame.
    371 
    372     // Push the return address onto the stack.
    373     uintptr_t retaddr = reinterpret_cast<uintptr_t>(pc + 2);
    374     uintptr_t* next_sp = reinterpret_cast<uintptr_t*>(sp - sizeof(uintptr_t));
    375     *next_sp = retaddr;
    376     uc->CTX_ESP = reinterpret_cast<uintptr_t>(next_sp);
    377 
    378     uc->CTX_EIP = reinterpret_cast<uintptr_t>(EXT_SYM(art_quick_test_suspend));
    379 
    380     // Now remove the suspend trigger that caused this fault.
    381     Thread::Current()->RemoveSuspendTrigger();
    382     VLOG(signals) << "removed suspend trigger invoking test suspend";
    383     return true;
    384   }
    385   VLOG(signals) << "Not a suspend check match, first instruction mismatch";
    386   return false;
    387 }
    388 
    389 // The stack overflow check is done using the following instruction:
    390 // test eax, [esp+ -xxx]
    391 // where 'xxx' is the size of the overflow area.
    392 //
    393 // This is done before any frame is established in the method.  The return
    394 // address for the previous method is on the stack at ESP.
    395 
    396 bool StackOverflowHandler::Action(int sig, siginfo_t* info, void* context) {
    397   struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
    398   uintptr_t sp = static_cast<uintptr_t>(uc->CTX_ESP);
    399 
    400   uintptr_t fault_addr = reinterpret_cast<uintptr_t>(info->si_addr);
    401   VLOG(signals) << "fault_addr: " << std::hex << fault_addr;
    402   VLOG(signals) << "checking for stack overflow, sp: " << std::hex << sp <<
    403     ", fault_addr: " << fault_addr;
    404 
    405 #if defined(__x86_64__)
    406   uintptr_t overflow_addr = sp - GetStackOverflowReservedBytes(kX86_64);
    407 #else
    408   uintptr_t overflow_addr = sp - GetStackOverflowReservedBytes(kX86);
    409 #endif
    410 
    411   // Check that the fault address is the value expected for a stack overflow.
    412   if (fault_addr != overflow_addr) {
    413     VLOG(signals) << "Not a stack overflow";
    414     return false;
    415   }
    416 
    417   VLOG(signals) << "Stack overflow found";
    418 
    419   // Since the compiler puts the implicit overflow
    420   // check before the callee save instructions, the SP is already pointing to
    421   // the previous frame.
    422 
    423   // Now arrange for the signal handler to return to art_quick_throw_stack_overflow.
    424   uc->CTX_EIP = reinterpret_cast<uintptr_t>(EXT_SYM(art_quick_throw_stack_overflow));
    425 
    426   return true;
    427 }
    428 }       // namespace art
    429