1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // 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_ 7 8 #include <stddef.h> 9 10 #include <iosfwd> 11 #include <string> 12 13 #include "base/base_export.h" 14 #include "base/macros.h" 15 #include "build/build_config.h" 16 17 #if defined(OS_POSIX) 18 #include <unistd.h> 19 #endif 20 21 #if defined(OS_WIN) 22 struct _EXCEPTION_POINTERS; 23 struct _CONTEXT; 24 #endif 25 26 // TODO(699863): Clean up HAVE_TRACE_STACK_FRAME_POINTERS. 27 #if defined(OS_POSIX) 28 29 #if defined(__i386__) || defined(__x86_64__) 30 #define HAVE_TRACE_STACK_FRAME_POINTERS 1 31 #elif defined(__arm__) && !defined(__thumb__) 32 #define HAVE_TRACE_STACK_FRAME_POINTERS 1 33 #else // defined(__arm__) && !defined(__thumb__) 34 #define HAVE_TRACE_STACK_FRAME_POINTERS 0 35 #endif // defined(__arm__) && !defined(__thumb__) 36 37 #elif defined(OS_WIN) 38 #define HAVE_TRACE_STACK_FRAME_POINTERS 1 39 40 #else // defined(OS_WIN) 41 #define HAVE_TRACE_STACK_FRAME_POINTERS 0 42 #endif // defined(OS_WIN) 43 44 namespace base { 45 namespace debug { 46 47 // Enables stack dump to console output on exception and signals. 48 // When enabled, the process will quit immediately. This is meant to be used in 49 // unit_tests only! This is not thread-safe: only call from main thread. 50 // In sandboxed processes, this has to be called before the sandbox is turned 51 // on. 52 // Calling this function on Linux opens /proc/self/maps and caches its 53 // contents. In non-official builds, this function also opens the object files 54 // that are loaded in memory and caches their file descriptors (this cannot be 55 // done in official builds because it has security implications). 56 BASE_EXPORT bool EnableInProcessStackDumping(); 57 58 // Returns end of the stack, or 0 if we couldn't get it. 59 #if HAVE_TRACE_STACK_FRAME_POINTERS 60 BASE_EXPORT uintptr_t GetStackEnd(); 61 #endif 62 63 // A stacktrace can be helpful in debugging. For example, you can include a 64 // stacktrace member in a object (probably around #ifndef NDEBUG) so that you 65 // can later see where the given object was created from. 66 class BASE_EXPORT StackTrace { 67 public: 68 // Creates a stacktrace from the current location. 69 StackTrace(); 70 71 // Creates a stacktrace from the current location, of up to |count| entries. 72 // |count| will be limited to at most |kMaxTraces|. 73 explicit StackTrace(size_t count); 74 75 // Creates a stacktrace from an existing array of instruction 76 // pointers (such as returned by Addresses()). |count| will be 77 // limited to at most |kMaxTraces|. 78 StackTrace(const void* const* trace, size_t count); 79 80 #if defined(OS_WIN) 81 // Creates a stacktrace for an exception. 82 // Note: this function will throw an import not found (StackWalk64) exception 83 // on system without dbghelp 5.1. 84 StackTrace(_EXCEPTION_POINTERS* exception_pointers); 85 StackTrace(const _CONTEXT* context); 86 #endif 87 88 // Copying and assignment are allowed with the default functions. 89 90 // Gets an array of instruction pointer values. |*count| will be set to the 91 // number of elements in the returned array. 92 const void* const* Addresses(size_t* count) const; 93 94 // Prints the stack trace to stderr. 95 void Print() const; 96 97 #if !defined(__UCLIBC__) 98 // Resolves backtrace to symbols and write to stream. 99 void OutputToStream(std::ostream* os) const; 100 #endif 101 102 // Resolves backtrace to symbols and returns as string. 103 std::string ToString() const; 104 105 private: 106 #if defined(OS_WIN) 107 void InitTrace(const _CONTEXT* context_record); 108 #endif 109 110 // From http://msdn.microsoft.com/en-us/library/bb204633.aspx, 111 // the sum of FramesToSkip and FramesToCapture must be less than 63, 112 // so set it to 62. Even if on POSIX it could be a larger value, it usually 113 // doesn't give much more information. 114 static const int kMaxTraces = 62; 115 116 void* trace_[kMaxTraces]; 117 118 // The number of valid frames in |trace_|. 119 size_t count_; 120 }; 121 122 #if HAVE_TRACE_STACK_FRAME_POINTERS 123 // Traces the stack by using frame pointers. This function is faster but less 124 // reliable than StackTrace. It should work for debug and profiling builds, 125 // but not for release builds (although there are some exceptions). 126 // 127 // Writes at most |max_depth| frames (instruction pointers) into |out_trace| 128 // after skipping |skip_initial| frames. Note that the function itself is not 129 // added to the trace so |skip_initial| should be 0 in most cases. 130 // Returns number of frames written. 131 BASE_EXPORT size_t TraceStackFramePointers(const void** out_trace, 132 size_t max_depth, 133 size_t skip_initial); 134 135 #if !defined(OS_WIN) 136 // Links stack frame |fp| to |parent_fp|, so that during stack unwinding 137 // TraceStackFramePointers() visits |parent_fp| after visiting |fp|. 138 // Both frame pointers must come from __builtin_frame_address(). 139 // Destructor restores original linkage of |fp| to avoid corrupting caller's 140 // frame register on return. 141 // 142 // This class can be used to repair broken stack frame chain in cases 143 // when execution flow goes into code built without frame pointers: 144 // 145 // void DoWork() { 146 // Call_SomeLibrary(); 147 // } 148 // static __thread void* g_saved_fp; 149 // void Call_SomeLibrary() { 150 // g_saved_fp = __builtin_frame_address(0); 151 // some_library_call(...); // indirectly calls SomeLibrary_Callback() 152 // } 153 // void SomeLibrary_Callback() { 154 // ScopedStackFrameLinker linker(__builtin_frame_address(0), g_saved_fp); 155 // ... 156 // TraceStackFramePointers(...); 157 // } 158 // 159 // This produces the following trace: 160 // 161 // #0 SomeLibrary_Callback() 162 // #1 <address of the code inside SomeLibrary that called #0> 163 // #2 DoWork() 164 // ...rest of the trace... 165 // 166 // SomeLibrary doesn't use frame pointers, so when SomeLibrary_Callback() 167 // is called, stack frame register contains bogus value that becomes callback' 168 // parent frame address. Without ScopedStackFrameLinker unwinding would've 169 // stopped at that bogus frame address yielding just two first frames (#0, #1). 170 // ScopedStackFrameLinker overwrites callback's parent frame address with 171 // Call_SomeLibrary's frame, so unwinder produces full trace without even 172 // noticing that stack frame chain was broken. 173 class BASE_EXPORT ScopedStackFrameLinker { 174 public: 175 ScopedStackFrameLinker(void* fp, void* parent_fp); 176 ~ScopedStackFrameLinker(); 177 178 private: 179 void* fp_; 180 void* parent_fp_; 181 void* original_parent_fp_; 182 183 DISALLOW_COPY_AND_ASSIGN(ScopedStackFrameLinker); 184 }; 185 #endif // !defined(OS_WIN) 186 187 #endif // HAVE_TRACE_STACK_FRAME_POINTERS 188 189 namespace internal { 190 191 #if defined(OS_POSIX) && !defined(OS_ANDROID) 192 // POSIX doesn't define any async-signal safe function for converting 193 // an integer to ASCII. We'll have to define our own version. 194 // itoa_r() converts a (signed) integer to ASCII. It returns "buf", if the 195 // conversion was successful or NULL otherwise. It never writes more than "sz" 196 // bytes. Output will be truncated as needed, and a NUL character is always 197 // appended. 198 BASE_EXPORT char *itoa_r(intptr_t i, 199 char *buf, 200 size_t sz, 201 int base, 202 size_t padding); 203 #endif // defined(OS_POSIX) && !defined(OS_ANDROID) 204 205 } // namespace internal 206 207 } // namespace debug 208 } // namespace base 209 210 #endif // BASE_DEBUG_STACK_TRACE_H_ 211