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 |