Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(627)

Side by Side Diff: base/debug/stack_trace_win.cc

Issue 3945002: Move debug-related stuff from base to the base/debug directory and use the... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/debug/stack_trace_unittest.cc ('k') | base/debug/trace_event.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/debug_util.h" 5 #include "base/debug/stack_trace.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <dbghelp.h> 8 #include <dbghelp.h>
9 9
10 #include <iostream> 10 #include <iostream>
11 11
12 #include "base/basictypes.h" 12 #include "base/basictypes.h"
13 #include "base/lock.h" 13 #include "base/lock.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/singleton.h" 15 #include "base/singleton.h"
16 16
17 namespace base {
18 namespace debug {
19
17 namespace { 20 namespace {
18 21
19 // Minimalist key reader.
20 // Note: Does not use the CRT.
21 bool RegReadString(HKEY root, const wchar_t* subkey,
22 const wchar_t* value_name, wchar_t* buffer, int* len) {
23 HKEY key = NULL;
24 DWORD res = RegOpenKeyEx(root, subkey, 0, KEY_READ, &key);
25 if (ERROR_SUCCESS != res || key == NULL)
26 return false;
27
28 DWORD type = 0;
29 DWORD buffer_size = *len * sizeof(wchar_t);
30 // We don't support REG_EXPAND_SZ.
31 res = RegQueryValueEx(key, value_name, NULL, &type,
32 reinterpret_cast<BYTE*>(buffer), &buffer_size);
33 if (ERROR_SUCCESS == res && buffer_size != 0 && type == REG_SZ) {
34 // Make sure the buffer is NULL terminated.
35 buffer[*len - 1] = 0;
36 *len = lstrlen(buffer);
37 RegCloseKey(key);
38 return true;
39 }
40 RegCloseKey(key);
41 return false;
42 }
43
44 // Replaces each "%ld" in input per a value. Not efficient but it works.
45 // Note: Does not use the CRT.
46 bool StringReplace(const wchar_t* input, int value, wchar_t* output,
47 int output_len) {
48 memset(output, 0, output_len*sizeof(wchar_t));
49 int input_len = lstrlen(input);
50
51 for (int i = 0; i < input_len; ++i) {
52 int current_output_len = lstrlen(output);
53
54 if (input[i] == L'%' && input[i + 1] == L'l' && input[i + 2] == L'd') {
55 // Make sure we have enough place left.
56 if ((current_output_len + 12) >= output_len)
57 return false;
58
59 // Cheap _itow().
60 wsprintf(output+current_output_len, L"%d", value);
61 i += 2;
62 } else {
63 if (current_output_len >= output_len)
64 return false;
65 output[current_output_len] = input[i];
66 }
67 }
68 return true;
69 }
70
71 // SymbolContext is a threadsafe singleton that wraps the DbgHelp Sym* family 22 // SymbolContext is a threadsafe singleton that wraps the DbgHelp Sym* family
72 // of functions. The Sym* family of functions may only be invoked by one 23 // of functions. The Sym* family of functions may only be invoked by one
73 // thread at a time. SymbolContext code may access a symbol server over the 24 // thread at a time. SymbolContext code may access a symbol server over the
74 // network while holding the lock for this singleton. In the case of high 25 // network while holding the lock for this singleton. In the case of high
75 // latency, this code will adversly affect performance. 26 // latency, this code will adversly affect performance.
76 // 27 //
77 // There is also a known issue where this backtrace code can interact 28 // There is also a known issue where this backtrace code can interact
78 // badly with breakpad if breakpad is invoked in a separate thread while 29 // badly with breakpad if breakpad is invoked in a separate thread while
79 // we are using the Sym* functions. This is because breakpad does now 30 // we are using the Sym* functions. This is because breakpad does now
80 // share a lock with this function. See this related bug: 31 // share a lock with this function. See this related bug:
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 } 128 }
178 } 129 }
179 130
180 DWORD init_error_; 131 DWORD init_error_;
181 Lock lock_; 132 Lock lock_;
182 DISALLOW_COPY_AND_ASSIGN(SymbolContext); 133 DISALLOW_COPY_AND_ASSIGN(SymbolContext);
183 }; 134 };
184 135
185 } // namespace 136 } // namespace
186 137
187 // Note: Does not use the CRT.
188 bool DebugUtil::SpawnDebuggerOnProcess(unsigned process_id) {
189 wchar_t reg_value[1026];
190 int len = arraysize(reg_value);
191 if (RegReadString(HKEY_LOCAL_MACHINE,
192 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug",
193 L"Debugger", reg_value, &len)) {
194 wchar_t command_line[1026];
195 if (StringReplace(reg_value, process_id, command_line,
196 arraysize(command_line))) {
197 // We don't mind if the debugger is present because it will simply fail
198 // to attach to this process.
199 STARTUPINFO startup_info = {0};
200 startup_info.cb = sizeof(startup_info);
201 PROCESS_INFORMATION process_info = {0};
202
203 if (CreateProcess(NULL, command_line, NULL, NULL, FALSE, 0, NULL, NULL,
204 &startup_info, &process_info)) {
205 CloseHandle(process_info.hThread);
206 WaitForInputIdle(process_info.hProcess, 10000);
207 CloseHandle(process_info.hProcess);
208 return true;
209 }
210 }
211 }
212 return false;
213 }
214
215 // static
216 bool DebugUtil::BeingDebugged() {
217 return ::IsDebuggerPresent() != 0;
218 }
219
220 // static
221 void DebugUtil::BreakDebugger() {
222 if (suppress_dialogs_)
223 _exit(1);
224
225 __debugbreak();
226 }
227
228 StackTrace::StackTrace() { 138 StackTrace::StackTrace() {
229 // When walking our own stack, use CaptureStackBackTrace(). 139 // When walking our own stack, use CaptureStackBackTrace().
230 count_ = CaptureStackBackTrace(0, arraysize(trace_), trace_, NULL); 140 count_ = CaptureStackBackTrace(0, arraysize(trace_), trace_, NULL);
231 } 141 }
232 142
233 StackTrace::StackTrace(EXCEPTION_POINTERS* exception_pointers) { 143 StackTrace::StackTrace(EXCEPTION_POINTERS* exception_pointers) {
234 // When walking an exception stack, we need to use StackWalk64(). 144 // When walking an exception stack, we need to use StackWalk64().
235 count_ = 0; 145 count_ = 0;
236 // Initialize stack walking. 146 // Initialize stack walking.
237 STACKFRAME64 stack_frame; 147 STACKFRAME64 stack_frame;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 (*os) << "Error initializing symbols (" << error 185 (*os) << "Error initializing symbols (" << error
276 << "). Dumping unresolved backtrace:\n"; 186 << "). Dumping unresolved backtrace:\n";
277 for (int i = 0; (i < count_) && os->good(); ++i) { 187 for (int i = 0; (i < count_) && os->good(); ++i) {
278 (*os) << "\t" << trace_[i] << "\n"; 188 (*os) << "\t" << trace_[i] << "\n";
279 } 189 }
280 } else { 190 } else {
281 (*os) << "Backtrace:\n"; 191 (*os) << "Backtrace:\n";
282 context->OutputTraceToStream(trace_, count_, os); 192 context->OutputTraceToStream(trace_, count_, os);
283 } 193 }
284 } 194 }
195
196 } // namespace debug
197 } // namespace base
OLDNEW
« no previous file with comments | « base/debug/stack_trace_unittest.cc ('k') | base/debug/trace_event.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698