diff options
author | mseaborn@chromium.org <mseaborn@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-24 18:11:38 +0000 |
---|---|---|
committer | mseaborn@chromium.org <mseaborn@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-24 18:11:38 +0000 |
commit | fb335fe0cf9bce0888dd72b84359e83cc5b08991 (patch) | |
tree | da4a9a8ade30b26eac8d128e2eafe72fc4823b86 /chrome/nacl | |
parent | 2ded2ee298c09a45032fe6cdf8349370f01003d3 (diff) | |
download | chromium_src-fb335fe0cf9bce0888dd72b84359e83cc5b08991.zip chromium_src-fb335fe0cf9bce0888dd72b84359e83cc5b08991.tar.gz chromium_src-fb335fe0cf9bce0888dd72b84359e83cc5b08991.tar.bz2 |
NaCl: Make hardware exception handling work on 64-bit Windows
In order to support untrusted hardware exception handling on 64-bit
Windows, we need to have a 64-bit process attach as a debugger to the
64-bit NaCl loader process, so we extend the NaCl broker process to do
this.
The new code in nacl_broker_listener.cc for attaching a 64-bit
debugger is similar to the 32-bit code in nacl_process_host.cc. I
intend to unify the two in a later change.
BUG=http://code.google.com/p/nativeclient/issues/detail?id=2651
TEST=run_inbrowser_exception_test in nacl_integration
Review URL: https://chromiumcodereview.appspot.com/9835003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@128764 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/nacl')
-rw-r--r-- | chrome/nacl/nacl_broker_listener.cc | 83 | ||||
-rw-r--r-- | chrome/nacl/nacl_broker_listener.h | 1 |
2 files changed, 83 insertions, 1 deletions
diff --git a/chrome/nacl/nacl_broker_listener.cc b/chrome/nacl/nacl_broker_listener.cc index 32fc9ef..97346e9 100644 --- a/chrome/nacl/nacl_broker_listener.cc +++ b/chrome/nacl/nacl_broker_listener.cc @@ -1,19 +1,87 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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 "chrome/nacl/nacl_broker_listener.h" #include "base/base_switches.h" +#include "base/bind.h" #include "base/command_line.h" #include "base/message_loop.h" +#include "base/message_loop_proxy.h" #include "base/path_service.h" #include "base/process_util.h" +#include "base/threading/platform_thread.h" #include "chrome/common/nacl_cmd_line.h" #include "chrome/common/nacl_messages.h" #include "content/common/sandbox_policy.h" #include "content/public/common/content_switches.h" #include "ipc/ipc_switches.h" +#include "native_client/src/trusted/service_runtime/win/debug_exception_handler.h" + +namespace { + +void SendReply(IPC::Channel* channel, int32 pid) { + channel->Send(new NaClProcessMsg_DebugExceptionHandlerLaunched(pid)); +} + +class DebugExceptionHandler : public base::PlatformThread::Delegate { + public: + DebugExceptionHandler(base::MessageLoopProxy* message_loop, + IPC::Channel* channel, int32 pid) + : message_loop_(message_loop), channel_(channel), pid_(pid) { + } + + virtual void ThreadMain() OVERRIDE { + // In the Windows API, the set of processes being debugged is + // thread-local, so we have to attach to the process (using + // DebugActiveProcess()) on the same thread on which + // NaClDebugLoop() receives debug events for the process. + BOOL attached = false; + base::ProcessHandle process_handle = base::kNullProcessHandle; + if (!base::OpenProcessHandleWithAccess( + pid_, + base::kProcessAccessQueryInformation | + base::kProcessAccessSuspendResume | + base::kProcessAccessTerminate | + base::kProcessAccessVMOperation | + base::kProcessAccessVMRead | + base::kProcessAccessVMWrite | + base::kProcessAccessWaitForTermination, + &process_handle)) { + LOG(ERROR) << "Failed to get process handle"; + } else { + attached = DebugActiveProcess(pid_); + if (!attached) { + LOG(ERROR) << "Failed to connect to the process"; + } + } + // At the moment we do not say in the reply whether attaching as a + // debugger succeeded. In the future, when we attach on demand + // when an exception handler is first registered, we can make the + // NaCl syscall indicate whether attaching succeeded. + message_loop_->PostDelayedTask(FROM_HERE, + base::Bind(SendReply, channel_, pid_), base::TimeDelta()); + + if (attached) { + DWORD exit_code; + NaClDebugLoop(process_handle, &exit_code); + } + if (process_handle != base::kNullProcessHandle) { + base::CloseProcessHandle(process_handle); + } + delete this; + } + + private: + base::MessageLoopProxy* message_loop_; + IPC::Channel* channel_; + int32 pid_; + + DISALLOW_COPY_AND_ASSIGN(DebugExceptionHandler); +}; + +} // namespace NaClBrokerListener::NaClBrokerListener() : browser_handle_(base::kNullProcessHandle) { @@ -43,6 +111,8 @@ bool NaClBrokerListener::OnMessageReceived(const IPC::Message& msg) { IPC_BEGIN_MESSAGE_MAP(NaClBrokerListener, msg) IPC_MESSAGE_HANDLER(NaClProcessMsg_LaunchLoaderThroughBroker, OnLaunchLoaderThroughBroker) + IPC_MESSAGE_HANDLER(NaClProcessMsg_LaunchDebugExceptionHandler, + OnLaunchDebugExceptionHandler) IPC_MESSAGE_HANDLER(NaClProcessMsg_StopBroker, OnStopBroker) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() @@ -85,6 +155,17 @@ void NaClBrokerListener::OnLaunchLoaderThroughBroker( loader_handle_in_browser)); } +void NaClBrokerListener::OnLaunchDebugExceptionHandler(int32 pid) { + // The new PlatformThread will take ownership of the + // DebugExceptionHandler object, which will delete itself on exit. + DebugExceptionHandler* handler = new DebugExceptionHandler( + base::MessageLoopProxy::current(), channel_.get(), pid); + if (!base::PlatformThread::CreateNonJoinable(0, handler)) { + SendReply(channel_.get(), pid); + delete handler; + } +} + void NaClBrokerListener::OnStopBroker() { MessageLoop::current()->Quit(); } diff --git a/chrome/nacl/nacl_broker_listener.h b/chrome/nacl/nacl_broker_listener.h index e1c3dd7..dccf57c 100644 --- a/chrome/nacl/nacl_broker_listener.h +++ b/chrome/nacl/nacl_broker_listener.h @@ -27,6 +27,7 @@ class NaClBrokerListener : public IPC::Channel::Listener { private: void OnLaunchLoaderThroughBroker(const std::wstring& loader_channel_id); + void OnLaunchDebugExceptionHandler(int32 pid); void OnStopBroker(); base::ProcessHandle browser_handle_; |