| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include <signal.h> | |
| 6 #include <string.h> | |
| 7 #include <sys/types.h> | |
| 8 #include <syscall.h> | |
| 9 #include <unistd.h> | |
| 10 | |
| 11 #include "build/build_config.h" | |
| 12 | |
| 13 // This whole file is only useful on 64-bit architectures. | |
| 14 #if defined(ARCH_CPU_64_BITS) | |
| 15 | |
| 16 namespace content { | |
| 17 | |
| 18 namespace { | |
| 19 | |
| 20 // Signal handler for SIGILL; see WorkaroundFlashLAHF(). | |
| 21 void SignalHandler(int signum, siginfo_t* info, void* void_context) { | |
| 22 const char kLAHFInstruction = 0x9f; | |
| 23 ucontext_t* context = static_cast<ucontext_t*>(void_context); | |
| 24 greg_t* regs = context->uc_mcontext.gregs; | |
| 25 char instruction = *reinterpret_cast<char*>(regs[REG_RIP]); | |
| 26 | |
| 27 // Check whether this is the kind of SIGILL we care about. | |
| 28 // (info->si_addr can be NULL when we get a SIGILL via other means, | |
| 29 // like with kill.) | |
| 30 if (signum != SIGILL || instruction != kLAHFInstruction) { | |
| 31 // Not the problem we're interested in. Reraise the signal. We | |
| 32 // need to be careful to handle threads etc. properly. | |
| 33 | |
| 34 struct sigaction sa = { { NULL } }; | |
| 35 sigemptyset(&sa.sa_mask); | |
| 36 sa.sa_handler = SIG_DFL; | |
| 37 sigaction(signum, &sa, NULL); | |
| 38 | |
| 39 // block the current signal | |
| 40 sigset_t block_set; | |
| 41 sigemptyset(&block_set); | |
| 42 sigaddset(&block_set, signum); | |
| 43 sigprocmask(SIG_BLOCK, &block_set, NULL); | |
| 44 | |
| 45 // Re-raise signal. It won't be delivered until we return. | |
| 46 syscall(SYS_tkill, syscall(SYS_gettid), signum); | |
| 47 return; | |
| 48 } | |
| 49 | |
| 50 // LAHF moves the low byte of the EFLAGS register to AH. Emulate that. | |
| 51 reinterpret_cast<char*>(®s[REG_RAX])[1] = | |
| 52 reinterpret_cast<char*>(®s[REG_EFL])[0]; | |
| 53 // And advance the instruction pointer past the (one-byte) instruction. | |
| 54 ++regs[REG_RIP]; | |
| 55 } | |
| 56 | |
| 57 } // namespace | |
| 58 | |
| 59 // 64-bit Flash sometimes uses the LAHF instruction which isn't | |
| 60 // available on some CPUs. We can work around it by catching SIGILL | |
| 61 // (illegal instruction), checking if the signal was caused by this | |
| 62 // particular circumstance, emulating the instruction, and resuming. | |
| 63 // This function registers the signal handler. | |
| 64 void WorkaroundFlashLAHF() { | |
| 65 struct sigaction action = { { NULL } }; | |
| 66 action.sa_flags = SA_SIGINFO; | |
| 67 action.sa_sigaction = &SignalHandler; | |
| 68 | |
| 69 sigaction(SIGILL, &action, NULL); | |
| 70 } | |
| 71 | |
| 72 } // namespace content | |
| 73 | |
| 74 #endif // defined(ARCH_CPU_64_BITS) | |
| OLD | NEW |