diff options
Diffstat (limited to 'chrome')
-rwxr-xr-x | chrome/chrome.gyp | 1 | ||||
-rw-r--r-- | chrome/plugin/plugin_main.cc | 10 | ||||
-rw-r--r-- | chrome/plugin/plugin_main_linux.cc | 72 |
3 files changed, 82 insertions, 1 deletions
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index d1ab06c..ab54446 100755 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -438,6 +438,7 @@ 'plugin/plugin_interpose_util_mac.mm', 'plugin/plugin_interpose_util_mac.h', 'plugin/plugin_main.cc', + 'plugin/plugin_main_linux.cc', 'plugin/plugin_main_mac.mm', 'plugin/plugin_thread.cc', 'plugin/plugin_thread.h', diff --git a/chrome/plugin/plugin_main.cc b/chrome/plugin/plugin_main.cc index 1cbcc57..1e77325 100644 --- a/chrome/plugin/plugin_main.cc +++ b/chrome/plugin/plugin_main.cc @@ -39,7 +39,10 @@ void TrimInterposeEnvironment(); // Initializes the global Cocoa application object. void InitializeChromeApplication(); -#endif // OS_MACOSX +#elif defined(OS_LINUX) +// Work around an unimplemented instruction in 64-bit Flash. +void WorkaroundFlashLAHF(); +#endif // main() routine for running as the plugin process. int PluginMain(const MainFunctionParams& parameters) { @@ -67,6 +70,11 @@ int PluginMain(const MainFunctionParams& parameters) { // process name that shows up in "ps" etc. for plugins show as "exe" // instead of "chrome" or something reasonable. Try to fix it. CommandLine::SetProcTitle(); + +#if defined(ARCH_CPU_64_BITS) + WorkaroundFlashLAHF(); +#endif + #elif defined(OS_WIN) sandbox::TargetServices* target_services = parameters.sandbox_info_.TargetServices(); diff --git a/chrome/plugin/plugin_main_linux.cc b/chrome/plugin/plugin_main_linux.cc new file mode 100644 index 0000000..6bb9da7 --- /dev/null +++ b/chrome/plugin/plugin_main_linux.cc @@ -0,0 +1,72 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <signal.h> +#include <string.h> +#include <sys/types.h> +#include <syscall.h> +#include <unistd.h> + +#include "build/build_config.h" + +// This whole file is only useful on 64-bit architectures. +#if defined(ARCH_CPU_64_BITS) + +namespace { + +// Signal handler for SIGILL; see WorkaroundFlashLAHF(). +void SignalHandler(int signum, siginfo_t* info, void* void_context) { + const char kLAHFInstruction = 0x9f; + ucontext_t* context = static_cast<ucontext_t*>(void_context); + greg_t* regs = context->uc_mcontext.gregs; + char instruction = *reinterpret_cast<char*>(regs[REG_RIP]); + + // Check whether this is the kind of SIGILL we care about. + // (info->si_addr can be NULL when we get a SIGILL via other means, + // like with kill.) + if (signum != SIGILL || instruction != kLAHFInstruction) { + // Not the problem we're interested in. Reraise the signal. We + // need to be careful to handle threads etc. properly. + + struct sigaction sa; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sa.sa_handler = SIG_DFL; + sigaction(signum, &sa, NULL); + + // block the current signal + sigset_t block_set; + sigemptyset(&block_set); + sigaddset(&block_set, signum); + sigprocmask(SIG_BLOCK, &block_set, NULL); + + // Re-raise signal. It won't be delivered until we return. + syscall(SYS_tkill, syscall(SYS_gettid), signum); + return; + } + + // LAHF moves the low byte of the EFLAGS register to AH. Emulate that. + reinterpret_cast<char*>(®s[REG_RAX])[1] = + reinterpret_cast<char*>(®s[REG_EFL])[0]; + // And advance the instruction pointer past the (one-byte) instruction. + ++regs[REG_RIP]; +} + +} // namespace + +// 64-bit Flash sometimes uses the LAHF instruction which isn't +// available on some CPUs. We can work around it by catching SIGILL +// (illegal instruction), checking if the signal was caused by this +// particular circumstance, emulating the instruction, and resuming. +// This function registers the signal handler. +void WorkaroundFlashLAHF() { + struct sigaction action; + memset(&action, 0, sizeof(action)); + action.sa_flags = SA_SIGINFO; + action.sa_sigaction = &SignalHandler; + + sigaction(SIGILL, &action, NULL); +} + +#endif // defined(ARCH_CPU_64_BITS) |