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/browser/nacl_host | |
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/browser/nacl_host')
-rw-r--r-- | chrome/browser/nacl_host/nacl_broker_host_win.cc | 10 | ||||
-rw-r--r-- | chrome/browser/nacl_host/nacl_broker_host_win.h | 4 | ||||
-rw-r--r-- | chrome/browser/nacl_host/nacl_broker_service_win.cc | 19 | ||||
-rw-r--r-- | chrome/browser/nacl_host/nacl_broker_service_win.h | 13 | ||||
-rw-r--r-- | chrome/browser/nacl_host/nacl_process_host.cc | 79 | ||||
-rw-r--r-- | chrome/browser/nacl_host/nacl_process_host.h | 3 |
6 files changed, 90 insertions, 38 deletions
diff --git a/chrome/browser/nacl_host/nacl_broker_host_win.cc b/chrome/browser/nacl_host/nacl_broker_host_win.cc index 92e1453..3df9731 100644 --- a/chrome/browser/nacl_host/nacl_broker_host_win.cc +++ b/chrome/browser/nacl_host/nacl_broker_host_win.cc @@ -54,6 +54,8 @@ bool NaClBrokerHost::OnMessageReceived(const IPC::Message& msg) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(NaClBrokerHost, msg) IPC_MESSAGE_HANDLER(NaClProcessMsg_LoaderLaunched, OnLoaderLaunched) + IPC_MESSAGE_HANDLER(NaClProcessMsg_DebugExceptionHandlerLaunched, + OnDebugExceptionHandlerLaunched) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -70,6 +72,14 @@ void NaClBrokerHost::OnLoaderLaunched(const std::wstring& loader_channel_id, NaClBrokerService::GetInstance()->OnLoaderLaunched(loader_channel_id, handle); } +bool NaClBrokerHost::LaunchDebugExceptionHandler(int32 pid) { + return process_->Send(new NaClProcessMsg_LaunchDebugExceptionHandler(pid)); +} + +void NaClBrokerHost::OnDebugExceptionHandlerLaunched(int32 pid) { + NaClBrokerService::GetInstance()->OnDebugExceptionHandlerLaunched(pid); +} + void NaClBrokerHost::StopBroker() { process_->Send(new NaClProcessMsg_StopBroker()); } diff --git a/chrome/browser/nacl_host/nacl_broker_host_win.h b/chrome/browser/nacl_host/nacl_broker_host_win.h index 3ea6a33..353badd 100644 --- a/chrome/browser/nacl_host/nacl_broker_host_win.h +++ b/chrome/browser/nacl_host/nacl_broker_host_win.h @@ -28,6 +28,8 @@ class NaClBrokerHost : public content::BrowserChildProcessHostDelegate { // a Native Client loader process. bool LaunchLoader(const std::wstring& loader_channel_id); + bool LaunchDebugExceptionHandler(int32 pid); + // Stop the broker process. void StopBroker(); @@ -35,6 +37,8 @@ class NaClBrokerHost : public content::BrowserChildProcessHostDelegate { // Handler for NaClProcessMsg_LoaderLaunched message void OnLoaderLaunched(const std::wstring& loader_channel_id, base::ProcessHandle handle); + // Handler for NaClProcessMsg_DebugExceptionHandlerLaunched message + void OnDebugExceptionHandlerLaunched(int32 pid); // BrowserChildProcessHostDelegate implementation: virtual bool OnMessageReceived(const IPC::Message& msg); diff --git a/chrome/browser/nacl_host/nacl_broker_service_win.cc b/chrome/browser/nacl_host/nacl_broker_service_win.cc index 16bceb5..a338f09 100644 --- a/chrome/browser/nacl_host/nacl_broker_service_win.cc +++ b/chrome/browser/nacl_host/nacl_broker_service_win.cc @@ -65,6 +65,25 @@ void NaClBrokerService::OnLoaderDied() { } } +bool NaClBrokerService::LaunchDebugExceptionHandler( + NaClProcessHost* nacl_process_host, int32 pid) { + pending_debuggers_[pid] = nacl_process_host; + NaClBrokerHost* broker_host = GetBrokerHost(); + if (!broker_host) + return false; + return broker_host->LaunchDebugExceptionHandler(pid); +} + +void NaClBrokerService::OnDebugExceptionHandlerLaunched(int32 pid) { + PendingDebugExceptionHandlersMap::iterator it = pending_debuggers_.find(pid); + if (pending_debuggers_.end() == it) + NOTREACHED(); + + NaClProcessHost* client = it->second; + client->OnDebugExceptionHandlerLaunchedByBroker(); + pending_debuggers_.erase(it); +} + NaClBrokerHost* NaClBrokerService::GetBrokerHost() { BrowserChildProcessHostIterator iter(content::PROCESS_TYPE_NACL_BROKER); if (iter.Done()) diff --git a/chrome/browser/nacl_host/nacl_broker_service_win.h b/chrome/browser/nacl_host/nacl_broker_service_win.h index c69da7b..2b04938 100644 --- a/chrome/browser/nacl_host/nacl_broker_service_win.h +++ b/chrome/browser/nacl_host/nacl_broker_service_win.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 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. @@ -34,9 +34,15 @@ class NaClBrokerService { // Called by NaClProcessHost when a loader process is terminated void OnLoaderDied(); + bool LaunchDebugExceptionHandler(NaClProcessHost* client, int32 pid); + + // Called by NaClBrokerHost to notify the service that a debug + // exception handler was started. + void OnDebugExceptionHandlerLaunched(int32 pid); + private: - typedef std::map<std::wstring, NaClProcessHost*> - PendingLaunchesMap; + typedef std::map<std::wstring, NaClProcessHost*> PendingLaunchesMap; + typedef std::map<int, NaClProcessHost*> PendingDebugExceptionHandlersMap; friend struct DefaultSingletonTraits<NaClBrokerService>; @@ -47,6 +53,7 @@ class NaClBrokerService { int loaders_running_; PendingLaunchesMap pending_launches_; + PendingDebugExceptionHandlersMap pending_debuggers_; DISALLOW_COPY_AND_ASSIGN(NaClBrokerService); }; diff --git a/chrome/browser/nacl_host/nacl_process_host.cc b/chrome/browser/nacl_host/nacl_process_host.cc index 1cbab6f..65ce107 100644 --- a/chrome/browser/nacl_host/nacl_process_host.cc +++ b/chrome/browser/nacl_host/nacl_process_host.cc @@ -258,9 +258,7 @@ NaClProcessHost::NaClProcessHost(const std::wstring& url) getenv("NACL_UNTRUSTED_EXCEPTION_HANDLING") != NULL) { enable_exception_handling_ = true; #if defined(OS_WIN) - if (!RunningOnWOW64()) { - debug_context_ = new DebugContext(); - } + debug_context_ = new DebugContext(); #endif } } @@ -505,14 +503,18 @@ bool NaClProcessHost::LaunchSelLdr() { return true; } -void NaClProcessHost::OnProcessLaunchedByBroker(base::ProcessHandle handle) { #if defined(OS_WIN) +void NaClProcessHost::OnProcessLaunchedByBroker(base::ProcessHandle handle) { process_launched_by_broker_ = true; -#endif process_->SetHandle(handle); OnProcessLaunched(); } +void NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker() { + debug_context_->AllowAndSendStartMessage(); +} +#endif + void NaClProcessHost::OnProcessCrashed(int exit_code) { std::string message = base::StringPrintf( "NaCl process exited with status %i (0x%x)", exit_code, exit_code); @@ -646,38 +648,45 @@ void NaClProcessHost::OnChannelConnected(int32 peer_pid) { if (debug_context_ == NULL) { return; } - // Start new thread for debug loop debug_context_->SetChildProcessHost(process_->GetHost()); - // We can't use process_->GetData().handle because it doesn't have necessary - // access rights. - base::ProcessHandle process; - if (!base::OpenProcessHandleWithAccess( - peer_pid, - base::kProcessAccessQueryInformation | - base::kProcessAccessSuspendResume | - base::kProcessAccessTerminate | - base::kProcessAccessVMOperation | - base::kProcessAccessVMRead | - base::kProcessAccessVMWrite | - base::kProcessAccessWaitForTermination, - &process)) { - LOG(ERROR) << "Failed to open the process"; - debug_context_->AllowAndSendStartMessage(); - return; - } - base::Thread* dbg_thread = new base::Thread("Debug thread"); - if (!dbg_thread->Start()) { - LOG(ERROR) << "Debug thread not started"; - debug_context_->AllowAndSendStartMessage(); - base::CloseProcessHandle(process); - return; + if (RunningOnWOW64()) { + if (!NaClBrokerService::GetInstance()->LaunchDebugExceptionHandler( + this, peer_pid)) { + debug_context_->AllowAndSendStartMessage(); + } + } else { + // Start new thread for debug loop + // We can't use process_->GetData().handle because it doesn't have necessary + // access rights. + base::ProcessHandle process; + if (!base::OpenProcessHandleWithAccess( + peer_pid, + base::kProcessAccessQueryInformation | + base::kProcessAccessSuspendResume | + base::kProcessAccessTerminate | + base::kProcessAccessVMOperation | + base::kProcessAccessVMRead | + base::kProcessAccessVMWrite | + base::kProcessAccessWaitForTermination, + &process)) { + LOG(ERROR) << "Failed to open the process"; + debug_context_->AllowAndSendStartMessage(); + return; + } + base::Thread* dbg_thread = new base::Thread("Debug thread"); + if (!dbg_thread->Start()) { + LOG(ERROR) << "Debug thread not started"; + debug_context_->AllowAndSendStartMessage(); + base::CloseProcessHandle(process); + return; + } + debug_context_->SetDebugThread(dbg_thread); + // System can not reallocate pid until we close process handle. So using + // pid in different thread is fine. + dbg_thread->message_loop()->PostTask(FROM_HERE, + base::Bind(&NaClProcessHost::DebugContext::AttachDebugger, + debug_context_, peer_pid, process)); } - debug_context_->SetDebugThread(dbg_thread); - // System can not reallocate pid until we close process handle. So using - // pid in different thread is fine. - dbg_thread->message_loop()->PostTask(FROM_HERE, - base::Bind(&NaClProcessHost::DebugContext::AttachDebugger, - debug_context_, peer_pid, process)); } #else void NaClProcessHost::OnChannelConnected(int32 peer_pid) { diff --git a/chrome/browser/nacl_host/nacl_process_host.h b/chrome/browser/nacl_host/nacl_process_host.h index d050179..f5e51ec 100644 --- a/chrome/browser/nacl_host/nacl_process_host.h +++ b/chrome/browser/nacl_host/nacl_process_host.h @@ -47,7 +47,10 @@ class NaClProcessHost : public content::BrowserChildProcessHostDelegate { virtual void OnChannelConnected(int32 peer_pid) OVERRIDE; +#if defined(OS_WIN) void OnProcessLaunchedByBroker(base::ProcessHandle handle); + void OnDebugExceptionHandlerLaunchedByBroker(); +#endif private: // Internal class that holds the nacl::Handle objecs so that |