| Index: base/debug/stack_trace.cc
|
| diff --git a/base/debug/stack_trace.cc b/base/debug/stack_trace.cc
|
| index 2250c8fb14cc43b76c9a1236f59722b8317a74a2..cedc7be29951e7f75088ab27abb97071ed89d4fe 100644
|
| --- a/base/debug/stack_trace.cc
|
| +++ b/base/debug/stack_trace.cc
|
| @@ -39,5 +39,54 @@ std::string StackTrace::ToString() const {
|
| return stream.str();
|
| }
|
|
|
| +#if HAVE_TRACE_STACK_FRAME_POINTERS
|
| +
|
| +size_t TraceStackFramePointers(const void** out_trace,
|
| + size_t max_depth,
|
| + size_t skip_initial) {
|
| + // Usage of __builtin_frame_address() enables frame pointers in this
|
| + // function even if they are not enabled globally. So 'sp' will always
|
| + // be valid.
|
| + uintptr_t sp = reinterpret_cast<uintptr_t>(__builtin_frame_address(0));
|
| +
|
| + size_t depth = 0;
|
| + while (depth < max_depth) {
|
| + if (skip_initial != 0) {
|
| + skip_initial--;
|
| + } else {
|
| + out_trace[depth++] = reinterpret_cast<const void**>(sp)[1];
|
| + }
|
| +
|
| +#if defined(__arm__) && defined(__GNUC__) && !defined(__clang__)
|
| + // GCC and LLVM generate slightly different frames on ARM, see
|
| + // https://llvm.org/bugs/show_bug.cgi?id=18505 - LLVM generates
|
| + // x86-compatible frame, while GCC needs adjustment.
|
| + sp -= sizeof(uintptr_t);
|
| +#endif
|
| +
|
| + // Find out next frame pointer
|
| + // (heuristics are from TCMalloc's stacktrace functions)
|
| + {
|
| + uintptr_t next_sp = reinterpret_cast<const uintptr_t*>(sp)[0];
|
| +
|
| + // With the stack growing downwards, older stack frame must be
|
| + // at a greater address that the current one.
|
| + if (next_sp <= sp) break;
|
| +
|
| + // Assume stack frames larger than 100,000 bytes are bogus.
|
| + if (next_sp - sp > 100000) break;
|
| +
|
| + // Check alignment.
|
| + if (sp & (sizeof(void*) - 1)) break;
|
| +
|
| + sp = next_sp;
|
| + }
|
| + }
|
| +
|
| + return depth;
|
| +}
|
| +
|
| +#endif // HAVE_TRACE_STACK_FRAME_POINTERS
|
| +
|
| } // namespace debug
|
| } // namespace base
|
|
|