debugger_win.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2010 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)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/debugger.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <dbghelp.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace debug {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Minimalist key reader.
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: Does not use the CRT.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RegReadString(HKEY root, const wchar_t* subkey,
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   const wchar_t* value_name, wchar_t* buffer, int* len) {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HKEY key = NULL;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD res = RegOpenKeyEx(root, subkey, 0, KEY_READ, &key);
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ERROR_SUCCESS != res || key == NULL)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD type = 0;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD buffer_size = *len * sizeof(wchar_t);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't support REG_EXPAND_SZ.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  res = RegQueryValueEx(key, value_name, NULL, &type,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        reinterpret_cast<BYTE*>(buffer), &buffer_size);
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ERROR_SUCCESS == res && buffer_size != 0 && type == REG_SZ) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make sure the buffer is NULL terminated.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer[*len - 1] = 0;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *len = lstrlen(buffer);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RegCloseKey(key);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RegCloseKey(key);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Replaces each "%ld" in input per a value. Not efficient but it works.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: Does not use the CRT.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool StringReplace(const wchar_t* input, int value, wchar_t* output,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   int output_len) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(output, 0, output_len*sizeof(wchar_t));
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int input_len = lstrlen(input);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < input_len; ++i) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int current_output_len = lstrlen(output);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (input[i] == L'%' && input[i + 1] == L'l' && input[i + 2] == L'd') {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Make sure we have enough place left.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((current_output_len + 12) >= output_len)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Cheap _itow().
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wsprintf(output+current_output_len, L"%d", value);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i += 2;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (current_output_len >= output_len)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      output[current_output_len] = input[i];
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: Does not use the CRT.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpawnDebuggerOnProcess(unsigned process_id) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wchar_t reg_value[1026];
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int len = arraysize(reg_value);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (RegReadString(HKEY_LOCAL_MACHINE,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug",
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      L"Debugger", reg_value, &len)) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wchar_t command_line[1026];
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (StringReplace(reg_value, process_id, command_line,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      arraysize(command_line))) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We don't mind if the debugger is present because it will simply fail
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // to attach to this process.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      STARTUPINFO startup_info = {0};
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      startup_info.cb = sizeof(startup_info);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PROCESS_INFORMATION process_info = {0};
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (CreateProcess(NULL, command_line, NULL, NULL, FALSE, 0, NULL, NULL,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        &startup_info, &process_info)) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CloseHandle(process_info.hThread);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        WaitForInputIdle(process_info.hProcess, 10000);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CloseHandle(process_info.hProcess);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BeingDebugged() {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ::IsDebuggerPresent() != 0;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BreakDebugger() {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsDebugUISuppressed())
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    _exit(1);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  __debugbreak();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(NDEBUG)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  _exit(1);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace debug
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
115