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) 75