blob: 4c9b73e87d61bca3db0965dda59bc46ca162d857 [file] [log] [blame]
[email protected]e645c7a2012-07-25 21:43:441// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]58580352010-10-26 04:07:502// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef BASE_DEBUG_STACK_TRACE_H_
6#define BASE_DEBUG_STACK_TRACE_H_
[email protected]58580352010-10-26 04:07:507
aviebe805c2015-12-24 08:20:288#include <stddef.h>
9
[email protected]58580352010-10-26 04:07:5010#include <iosfwd>
[email protected]d4114ba2011-10-12 16:13:4011#include <string>
[email protected]58580352010-10-26 04:07:5012
[email protected]0bea7252011-08-05 15:34:0013#include "base/base_export.h"
dskibaa8c951e2016-10-25 23:39:1114#include "base/macros.h"
[email protected]58580352010-10-26 04:07:5015#include "build/build_config.h"
16
[email protected]47c45562012-11-17 14:33:2517#if defined(OS_POSIX)
18#include <unistd.h>
19#endif
20
[email protected]58580352010-10-26 04:07:5021#if defined(OS_WIN)
22struct _EXCEPTION_POINTERS;
wittman7808da72015-02-03 17:46:5123struct _CONTEXT;
[email protected]58580352010-10-26 04:07:5024#endif
25
dskiba79080da02016-04-23 00:10:2726#if defined(OS_POSIX) && ( \
27 defined(__i386__) || defined(__x86_64__) || \
28 (defined(__arm__) && !defined(__thumb__)))
29#define HAVE_TRACE_STACK_FRAME_POINTERS 1
30#else
31#define HAVE_TRACE_STACK_FRAME_POINTERS 0
32#endif
33
[email protected]58580352010-10-26 04:07:5034namespace base {
35namespace debug {
36
[email protected]11b93faa2012-11-01 21:58:3037// Enables stack dump to console output on exception and signals.
38// When enabled, the process will quit immediately. This is meant to be used in
39// unit_tests only! This is not thread-safe: only call from main thread.
jam79dc59a2015-08-17 03:38:1640// In sandboxed processes, this has to be called before the sandbox is turned
41// on.
[email protected]ad9a0122014-03-22 00:34:5242// Calling this function on Linux opens /proc/self/maps and caches its
jam79dc59a2015-08-17 03:38:1643// contents. In non-official builds, this function also opens the object files
44// that are loaded in memory and caches their file descriptors (this cannot be
[email protected]ad9a0122014-03-22 00:34:5245// done in official builds because it has security implications).
jam79dc59a2015-08-17 03:38:1646BASE_EXPORT bool EnableInProcessStackDumping();
[email protected]ad9a0122014-03-22 00:34:5247
erikchend6b2b822017-02-22 21:10:3148// Returns end of the stack, or 0 if we couldn't get it.
49#if HAVE_TRACE_STACK_FRAME_POINTERS
50BASE_EXPORT uintptr_t GetStackEnd();
51#endif
52
[email protected]58580352010-10-26 04:07:5053// A stacktrace can be helpful in debugging. For example, you can include a
54// stacktrace member in a object (probably around #ifndef NDEBUG) so that you
55// can later see where the given object was created from.
[email protected]0bea7252011-08-05 15:34:0056class BASE_EXPORT StackTrace {
[email protected]58580352010-10-26 04:07:5057 public:
58 // Creates a stacktrace from the current location.
59 StackTrace();
60
wez73f8d7e2017-01-29 06:18:1361 // Creates a stacktrace from the current location, of up to |count| entries.
62 // |count| will be limited to at most |kMaxTraces|.
63 explicit StackTrace(size_t count);
64
[email protected]f01ae9812011-08-30 19:33:0465 // Creates a stacktrace from an existing array of instruction
66 // pointers (such as returned by Addresses()). |count| will be
wez73f8d7e2017-01-29 06:18:1367 // limited to at most |kMaxTraces|.
[email protected]f01ae9812011-08-30 19:33:0468 StackTrace(const void* const* trace, size_t count);
69
[email protected]58580352010-10-26 04:07:5070#if defined(OS_WIN)
71 // Creates a stacktrace for an exception.
72 // Note: this function will throw an import not found (StackWalk64) exception
73 // on system without dbghelp 5.1.
jam79dc59a2015-08-17 03:38:1674 StackTrace(_EXCEPTION_POINTERS* exception_pointers);
rnk0565cdd62015-10-06 16:48:3075 StackTrace(const _CONTEXT* context);
[email protected]58580352010-10-26 04:07:5076#endif
77
78 // Copying and assignment are allowed with the default functions.
79
[email protected]58580352010-10-26 04:07:5080 // Gets an array of instruction pointer values. |*count| will be set to the
81 // number of elements in the returned array.
[email protected]501dfc42011-04-14 16:34:0082 const void* const* Addresses(size_t* count) const;
[email protected]58580352010-10-26 04:07:5083
[email protected]5ddbf1c2013-08-29 01:59:3884 // Prints the stack trace to stderr.
85 void Print() const;
[email protected]58580352010-10-26 04:07:5086
[email protected]7cf10ed2014-06-27 09:21:0387#if !defined(__UCLIBC__)
[email protected]58580352010-10-26 04:07:5088 // Resolves backtrace to symbols and write to stream.
[email protected]501dfc42011-04-14 16:34:0089 void OutputToStream(std::ostream* os) const;
[email protected]816e50452014-04-09 22:29:3890#endif
[email protected]58580352010-10-26 04:07:5091
[email protected]d4114ba2011-10-12 16:13:4092 // Resolves backtrace to symbols and returns as string.
93 std::string ToString() const;
94
[email protected]58580352010-10-26 04:07:5095 private:
wittman7808da72015-02-03 17:46:5196#if defined(OS_WIN)
rnk0565cdd62015-10-06 16:48:3097 void InitTrace(const _CONTEXT* context_record);
wittman7808da72015-02-03 17:46:5198#endif
99
[email protected]58580352010-10-26 04:07:50100 // From http://msdn.microsoft.com/en-us/library/bb204633.aspx,
101 // the sum of FramesToSkip and FramesToCapture must be less than 63,
102 // so set it to 62. Even if on POSIX it could be a larger value, it usually
103 // doesn't give much more information.
104 static const int kMaxTraces = 62;
105
106 void* trace_[kMaxTraces];
[email protected]e645c7a2012-07-25 21:43:44107
108 // The number of valid frames in |trace_|.
109 size_t count_;
[email protected]58580352010-10-26 04:07:50110};
111
dskiba79080da02016-04-23 00:10:27112#if HAVE_TRACE_STACK_FRAME_POINTERS
113// Traces the stack by using frame pointers. This function is faster but less
114// reliable than StackTrace. It should work for debug and profiling builds,
115// but not for release builds (although there are some exceptions).
116//
117// Writes at most |max_depth| frames (instruction pointers) into |out_trace|
118// after skipping |skip_initial| frames. Note that the function itself is not
119// added to the trace so |skip_initial| should be 0 in most cases.
120// Returns number of frames written.
121BASE_EXPORT size_t TraceStackFramePointers(const void** out_trace,
122 size_t max_depth,
123 size_t skip_initial);
dskibaa8c951e2016-10-25 23:39:11124
125// Links stack frame |fp| to |parent_fp|, so that during stack unwinding
126// TraceStackFramePointers() visits |parent_fp| after visiting |fp|.
127// Both frame pointers must come from __builtin_frame_address().
128// Destructor restores original linkage of |fp| to avoid corrupting caller's
129// frame register on return.
130//
131// This class can be used to repair broken stack frame chain in cases
132// when execution flow goes into code built without frame pointers:
133//
134// void DoWork() {
135// Call_SomeLibrary();
136// }
137// static __thread void* g_saved_fp;
138// void Call_SomeLibrary() {
139// g_saved_fp = __builtin_frame_address(0);
140// some_library_call(...); // indirectly calls SomeLibrary_Callback()
141// }
142// void SomeLibrary_Callback() {
143// ScopedStackFrameLinker linker(__builtin_frame_address(0), g_saved_fp);
144// ...
145// TraceStackFramePointers(...);
146// }
147//
148// This produces the following trace:
149//
150// #0 SomeLibrary_Callback()
151// #1 <address of the code inside SomeLibrary that called #0>
152// #2 DoWork()
153// ...rest of the trace...
154//
155// SomeLibrary doesn't use frame pointers, so when SomeLibrary_Callback()
156// is called, stack frame register contains bogus value that becomes callback'
157// parent frame address. Without ScopedStackFrameLinker unwinding would've
158// stopped at that bogus frame address yielding just two first frames (#0, #1).
159// ScopedStackFrameLinker overwrites callback's parent frame address with
160// Call_SomeLibrary's frame, so unwinder produces full trace without even
161// noticing that stack frame chain was broken.
162class BASE_EXPORT ScopedStackFrameLinker {
163 public:
164 ScopedStackFrameLinker(void* fp, void* parent_fp);
165 ~ScopedStackFrameLinker();
166
167 private:
168 void* fp_;
169 void* parent_fp_;
170 void* original_parent_fp_;
171
172 DISALLOW_COPY_AND_ASSIGN(ScopedStackFrameLinker);
173};
174
dskiba79080da02016-04-23 00:10:27175#endif // HAVE_TRACE_STACK_FRAME_POINTERS
176
[email protected]1e218b72012-11-14 19:32:23177namespace internal {
178
179#if defined(OS_POSIX) && !defined(OS_ANDROID)
180// POSIX doesn't define any async-signal safe function for converting
181// an integer to ASCII. We'll have to define our own version.
182// itoa_r() converts a (signed) integer to ASCII. It returns "buf", if the
183// conversion was successful or NULL otherwise. It never writes more than "sz"
184// bytes. Output will be truncated as needed, and a NUL character is always
185// appended.
[email protected]22d5b9822013-01-10 18:21:52186BASE_EXPORT char *itoa_r(intptr_t i,
187 char *buf,
188 size_t sz,
189 int base,
190 size_t padding);
[email protected]1e218b72012-11-14 19:32:23191#endif // defined(OS_POSIX) && !defined(OS_ANDROID)
192
193} // namespace internal
194
[email protected]58580352010-10-26 04:07:50195} // namespace debug
196} // namespace base
197
198#endif // BASE_DEBUG_STACK_TRACE_H_