diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-16 21:17:30 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-16 21:17:30 +0000 |
commit | 5485cdcb5bc72c71dd67d982dadf76dd9c78328c (patch) | |
tree | 7f3bc0080230211be3adf17777cdf697c91bebb5 | |
parent | 32a66aed0e57642c8f0da0a4a34383bbc9250a32 (diff) | |
download | chromium_src-5485cdcb5bc72c71dd67d982dadf76dd9c78328c.zip chromium_src-5485cdcb5bc72c71dd67d982dadf76dd9c78328c.tar.gz chromium_src-5485cdcb5bc72c71dd67d982dadf76dd9c78328c.tar.bz2 |
Add StackTrace debugging utility class.
For the moment, it only works on Linux, although it should be pretty easy to
get it working on Mac with __builtin_return_address and __builtin_frame_address.
It will mostly fail to resolve functions. Use this wrapper script:
import os
import sys
import subprocess
import re
address = re.compile('.*\[(0x[0-9a-fA-F]{4,8})\].*')
if __name__ == '__main__':
p = subprocess.Popen(sys.argv[1:], stderr = subprocess.STDOUT, stdout = subprocess.PIPE)
addr2line = subprocess.Popen(['addr2line', '-e', sys.argv[1], '-f', '-C', '-s'],
stdout = subprocess.PIPE, stdin = subprocess.PIPE)
for line in p.stdout.readlines():
m = address.match(line);
if m is not None:
addr2line.stdin.write(m.groups()[0] + '\n')
function = addr2line.stdout.readline()[:-1]
location = addr2line.stdout.readline()[:-1]
sys.stdout.write('%s (%s)\n' % (function, location))
else:
sys.stdout.write(line)
Review URL: http://codereview.chromium.org/18303
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8218 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | base/debug_util.h | 24 | ||||
-rw-r--r-- | base/debug_util_posix.cc | 41 | ||||
-rw-r--r-- | base/debug_util_win.cc | 12 |
3 files changed, 76 insertions, 1 deletions
diff --git a/base/debug_util.h b/base/debug_util.h index 4572948..b7b5180 100644 --- a/base/debug_util.h +++ b/base/debug_util.h @@ -9,6 +9,29 @@ #ifndef BASE_DEBUG_UTIL_H_ #define BASE_DEBUG_UTIL_H_ +#include "base/basictypes.h" + +#include <vector> + +// A stacktrace can be helpful in debugging. For example, you can include a +// stacktrace member in a object (probably around #ifndef NDEBUG) so that you +// can later see where the given object was created from. +class StackTrace { + public: + // Create a stacktrace from the current location + StackTrace(); + // Get an array of instruction pointer values. + // count: (output) the number of elements in the returned array + const void *const *Addresses(size_t* count); + // Print a backtrace to stderr + void PrintBacktrace(); + + private: + std::vector<void*> trace_; + + DISALLOW_EVIL_CONSTRUCTORS(StackTrace); +}; + class DebugUtil { public: // Starts the registered system-wide JIT debugger to attach it to specified @@ -27,4 +50,3 @@ class DebugUtil { }; #endif // BASE_DEBUG_UTIL_H_ - diff --git a/base/debug_util_posix.cc b/base/debug_util_posix.cc index a83e144..466bb0e 100644 --- a/base/debug_util_posix.cc +++ b/base/debug_util_posix.cc @@ -2,8 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "build/build_config.h" #include "base/debug_util.h" +#if defined(OS_LINUX) +#include <unistd.h> +#include <execinfo.h> +#endif + +#include <stdio.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/sysctl.h> @@ -90,3 +97,37 @@ bool DebugUtil::BeingDebugged() { void DebugUtil::BreakDebugger() { asm ("int3"); } + +#if defined(OS_LINUX) + +StackTrace::StackTrace() { + static const unsigned kMaxCallers = 256; + + void* callers[kMaxCallers]; + int count = backtrace(callers, kMaxCallers); + trace_.resize(count); + memcpy(&trace_[0], callers, sizeof(void*) * count); +} + +void StackTrace::PrintBacktrace() { + fflush(stderr); + backtrace_symbols_fd(&trace_[0], trace_.size(), STDERR_FILENO); +} + +#elif defined(OS_MACOSX) + +// TODO(port): complete this code +StackTrace::StackTrace() { } + +StackTrace::PrintBacktrace() { + NOTIMPLEMENTED(); +} + +#endif // defined(OS_MACOSX) + +const void *const *StackTrace::Addresses(size_t* count) { + *count = trace_.size(); + if (trace_.size()) + return &trace_[0]; + return NULL; +} diff --git a/base/debug_util_win.cc b/base/debug_util_win.cc index 906b71e..348bf44 100644 --- a/base/debug_util_win.cc +++ b/base/debug_util_win.cc @@ -101,3 +101,15 @@ void DebugUtil::BreakDebugger() { __debugbreak(); } +// TODO(port): not implemented on Windows +StackTrace::StackTrace() { +} + +const void *const *StackTrace::Addresses(size_t* count) { + *count = 0; + return NULL; +} + +void PrintBacktrace() { + NOTIMPLEMENTED(); +} |