1a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "components/nacl/common/nacl_debug_exception_handler_win.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_handle.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "native_client/src/trusted/service_runtime/win/debug_exception_handler.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DebugExceptionHandler : public base::PlatformThread::Delegate {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DebugExceptionHandler(base::ProcessHandle nacl_process,
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const std::string& startup_info,
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        base::MessageLoopProxy* message_loop,
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const base::Callback<void(bool)>& on_connected)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : nacl_process_(nacl_process),
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        startup_info_(startup_info),
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        message_loop_(message_loop),
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        on_connected_(on_connected) {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ThreadMain() OVERRIDE {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In the Windows API, the set of processes being debugged is
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // thread-local, so we have to attach to the process (using
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // DebugActiveProcess()) on the same thread on which
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // NaClDebugExceptionHandlerRun() receives debug events for the
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // process.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool attached = false;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int pid = GetProcessId(nacl_process_);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pid == 0) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Invalid process handle";
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!DebugActiveProcess(pid)) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(ERROR) << "Failed to connect to the process";
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        attached = true;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_loop_->PostTask(FROM_HERE, base::Bind(on_connected_, attached));
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (attached) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NaClDebugExceptionHandlerRun(
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          nacl_process_,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reinterpret_cast<const void*>(startup_info_.data()),
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          startup_info_.size());
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete this;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedHandle nacl_process_;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string startup_info_;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::MessageLoopProxy* message_loop_;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Callback<void(bool)> on_connected_;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DebugExceptionHandler);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NaClStartDebugExceptionHandlerThread(
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::ProcessHandle nacl_process,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& startup_info,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::MessageLoopProxy* message_loop,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Callback<void(bool)>& on_connected) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The new PlatformThread will take ownership of the
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // DebugExceptionHandler object, which will delete itself on exit.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DebugExceptionHandler* handler = new DebugExceptionHandler(
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nacl_process, startup_info, message_loop, on_connected);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!base::PlatformThread::CreateNonJoinable(0, handler)) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    on_connected.Run(false);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete handler;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
79