summaryrefslogtreecommitdiffstats
path: root/base/debug
diff options
context:
space:
mode:
authorbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-01 19:55:22 +0000
committerbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-01 19:55:22 +0000
commit10f33b1bd6c6adb6306759a45bf3a5c18221d878 (patch)
tree60d8395d4bb748333871726781b6ef75a7d9c559 /base/debug
parent995d592afc0fcee55a67b9f5ebcae7a093de6da0 (diff)
downloadchromium_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.cc74
-rw-r--r--base/debug/debug_on_start_win.h77
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_