diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-01 19:55:22 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-01 19:55:22 +0000 |
commit | 10f33b1bd6c6adb6306759a45bf3a5c18221d878 (patch) | |
tree | 60d8395d4bb748333871726781b6ef75a7d9c559 /base/debug | |
parent | 995d592afc0fcee55a67b9f5ebcae7a093de6da0 (diff) | |
download | chromium_src-10f33b1bd6c6adb6306759a45bf3a5c18221d878.zip chromium_src-10f33b1bd6c6adb6306759a45bf3a5c18221d878.tar.gz chromium_src-10f33b1bd6c6adb6306759a45bf3a5c18221d878.tar.bz2 |
Move base/debug_on_start to base/debugger and rename it to be _win since it
only does anything on Windows.
TEST=it compiles
BUG=none
Review URL: http://codereview.chromium.org/5984007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@70362 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/debug')
-rw-r--r-- | base/debug/debug_on_start_win.cc | 74 | ||||
-rw-r--r-- | base/debug/debug_on_start_win.h | 77 |
2 files changed, 151 insertions, 0 deletions
diff --git a/base/debug/debug_on_start_win.cc b/base/debug/debug_on_start_win.cc new file mode 100644 index 0000000..b5c1094 --- /dev/null +++ b/base/debug/debug_on_start_win.cc @@ -0,0 +1,74 @@ +// Copyright (c) 2011 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 "base/debug/debug_on_start_win.h" + +#include <windows.h> + +#include "base/base_switches.h" +#include "base/basictypes.h" +#include "base/debug/debugger.h" + +namespace base { +namespace debug { + +// Minimalist implementation to try to find a command line argument. We can use +// kernel32 exported functions but not the CRT functions because we're too early +// in the process startup. +// The code is not that bright and will find things like ---argument or +// /-/argument. +// Note: command_line is non-destructively modified. +bool DebugOnStart::FindArgument(wchar_t* command_line, const char* argument_c) { + wchar_t argument[50]; + for (int i = 0; argument_c[i]; ++i) + argument[i] = argument_c[i]; + + int argument_len = lstrlen(argument); + int command_line_len = lstrlen(command_line); + while (command_line_len > argument_len) { + wchar_t first_char = command_line[0]; + wchar_t last_char = command_line[argument_len+1]; + // Try to find an argument. + if ((first_char == L'-' || first_char == L'/') && + (last_char == L' ' || last_char == 0 || last_char == L'=')) { + command_line[argument_len+1] = 0; + // Skip the - or / + if (lstrcmpi(command_line+1, argument) == 0) { + // Found it. + command_line[argument_len+1] = last_char; + return true; + } + // Fix back. + command_line[argument_len+1] = last_char; + } + // Continue searching. + ++command_line; + --command_line_len; + } + return false; +} + +// static +int __cdecl DebugOnStart::Init() { + // Try to find the argument. + if (FindArgument(GetCommandLine(), switches::kDebugOnStart)) { + // We can do 2 things here: + // - Ask for a debugger to attach to us. This involve reading the registry + // key and creating the process. + // - Do a int3. + + // It will fails if we run in a sandbox. That is expected. + base::debug::SpawnDebuggerOnProcess(GetCurrentProcessId()); + + // Wait for a debugger to come take us. + base::debug::WaitForDebugger(60, false); + } else if (FindArgument(GetCommandLine(), switches::kWaitForDebugger)) { + // Wait for a debugger to come take us. + base::debug::WaitForDebugger(60, true); + } + return 0; +} + +} // namespace debug +} // namespace base diff --git a/base/debug/debug_on_start_win.h b/base/debug/debug_on_start_win.h new file mode 100644 index 0000000..5a1081d --- /dev/null +++ b/base/debug/debug_on_start_win.h @@ -0,0 +1,77 @@ +// Copyright (c) 2011 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. + +// Define the necessary code and global data to look for kDebugOnStart command +// line argument. When the command line argument is detected, it invokes the +// debugger, if no system-wide debugger is registered, a debug break is done. + +#ifndef BASE_DEBUG_DEBUG_ON_START_WIN_H_ +#define BASE_DEBUG_DEBUG_ON_START_WIN_H_ +#pragma once + +#include "base/basictypes.h" +#include "build/build_config.h" + +// This only works on Windows. It's legal to include on other platforms, but +// will be a NOP. +#if defined(OS_WIN) + +#ifndef DECLSPEC_SELECTANY +#define DECLSPEC_SELECTANY __declspec(selectany) +#endif + +namespace base { +namespace debug { + +// Debug on start functions and data. +class DebugOnStart { + public: + // Expected function type in the .CRT$XI* section. + // Note: See VC\crt\src\internal.h for reference. + typedef int (__cdecl *PIFV)(void); + + // Looks at the command line for kDebugOnStart argument. If found, it invokes + // the debugger, if this fails, it crashes. + static int __cdecl Init(); + + // Returns true if the 'argument' is present in the 'command_line'. It does + // not use the CRT, only Kernel32 functions. + static bool FindArgument(wchar_t* command_line, const char* argument); +}; + +// Set the function pointer to our function to look for a crash on start. The +// XIB section is started pretty early in the program initialization so in +// theory it should be called before any user created global variable +// initialization code and CRT initialization code. +// Note: See VC\crt\src\defsects.inc and VC\crt\src\crt0.c for reference. +#ifdef _WIN64 + +// "Fix" the segment. On x64, the .CRT segment is merged into the .rdata segment +// so it contains const data only. +#pragma const_seg(push, ".CRT$XIB") +// Declare the pointer so the CRT will find it. +extern const DebugOnStart::PIFV debug_on_start; +DECLSPEC_SELECTANY const DebugOnStart::PIFV debug_on_start = + &DebugOnStart::Init; +// Fix back the segment. +#pragma const_seg(pop) + +#else // _WIN64 + +// "Fix" the segment. On x86, the .CRT segment is merged into the .data segment +// so it contains non-const data only. +#pragma data_seg(push, ".CRT$XIB") +// Declare the pointer so the CRT will find it. +DECLSPEC_SELECTANY DebugOnStart::PIFV debug_on_start = &DebugOnStart::Init; +// Fix back the segment. +#pragma data_seg(pop) + +#endif // _WIN64 + +} // namespace debug +} // namespace base + +#endif // defined(OS_WIN) + +#endif // BASE_DEBUG_DEBUG_ON_START_WIN_H_ |