fault_handler_x86.cc revision ab9a0dbf3b63d517da5278b8298e6cd316e09f68
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