| Index: third_party/tcmalloc/chromium/src/stacktrace_android-inl.h
|
| diff --git a/third_party/tcmalloc/chromium/src/stacktrace_libunwind-inl.h b/third_party/tcmalloc/chromium/src/stacktrace_android-inl.h
|
| similarity index 54%
|
| copy from third_party/tcmalloc/chromium/src/stacktrace_libunwind-inl.h
|
| copy to third_party/tcmalloc/chromium/src/stacktrace_android-inl.h
|
| index 82b0cfeb7aee7db0a2d7c96ce7c6769b23c32f3e..1f04bc9de27b31ea5b697f79de3743b86bae733f 100644
|
| --- a/third_party/tcmalloc/chromium/src/stacktrace_libunwind-inl.h
|
| +++ b/third_party/tcmalloc/chromium/src/stacktrace_android-inl.h
|
| @@ -1,4 +1,4 @@
|
| -// Copyright (c) 2005, Google Inc.
|
| +// Copyright (c) 2013, Google Inc.
|
| // All rights reserved.
|
| //
|
| // Redistribution and use in source and binary forms, with or without
|
| @@ -28,36 +28,76 @@
|
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
| // ---
|
| -// Author: Arun Sharma
|
| +// Author: Marcus Bulach
|
| +// This is inspired by Doug Kwan's ARM's stacktrace code and Dai Mikurube's
|
| +// stack trace for chromium on android.
|
| //
|
| -// Produce stack trace using libunwind
|
|
|
| -#ifndef BASE_STACKTRACE_LIBINWIND_INL_H_
|
| -#define BASE_STACKTRACE_LIBINWIND_INL_H_
|
| +#ifndef BASE_STACKTRACE_ANDROID_INL_H_
|
| +#define BASE_STACKTRACE_ANDROID_INL_H_
|
| // Note: this file is included into stacktrace.cc more than once.
|
| // Anything that should only be defined once should be here:
|
|
|
| -// We only need local unwinder.
|
| -#define UNW_LOCAL_ONLY
|
| +#include <stdint.h> // for uintptr_t
|
| +// See http://crbug.com/236855, would be better to use Bionic's
|
| +// new get_backtrace().
|
| +#include <unwind.h>
|
|
|
| -extern "C" {
|
| -#include <assert.h>
|
| -#include <string.h> // for memset()
|
| -#include <libunwind.h>
|
| -}
|
| -#include "gperftools/stacktrace.h"
|
| -#include "base/logging.h"
|
| +/* Depends on the system definition for _Unwind_Context */
|
| +#ifdef HAVE_UNWIND_CONTEXT_STRUCT
|
| +typedef struct _Unwind_Context __unwind_context;
|
| +#else
|
| +typedef _Unwind_Context __unwind_context;
|
| +#endif
|
| +
|
| +struct stack_crawl_state_t {
|
| + uintptr_t* frames;
|
| + size_t frame_count;
|
| + int max_depth;
|
| + int skip_count;
|
| + bool have_skipped_self;
|
| +
|
| + stack_crawl_state_t(uintptr_t* frames, int max_depth, int skip_count)
|
| + : frames(frames),
|
| + frame_count(0),
|
| + max_depth(max_depth),
|
| + skip_count(skip_count),
|
| + have_skipped_self(false) {
|
| + }
|
| +};
|
| +
|
| +static _Unwind_Reason_Code tracer(__unwind_context* context, void* arg) {
|
| + stack_crawl_state_t* state = static_cast<stack_crawl_state_t*>(arg);
|
| +
|
| +#if defined(__clang__)
|
| + // Vanilla Clang's unwind.h doesn't have _Unwind_GetIP for ARM.
|
| + // See http://crbug.com/236855, too.
|
| + uintptr_t ip = 0;
|
| + _Unwind_VRS_Get(context, _UVRSC_CORE, 15, _UVRSD_UINT32, &ip);
|
| + ip &= ~(uintptr_t)0x1; // remove thumb mode bit
|
| +#else
|
| + uintptr_t ip = _Unwind_GetIP(context);
|
| +#endif
|
| +
|
| + // The first stack frame is this function itself. Skip it.
|
| + if (ip != 0 && !state->have_skipped_self) {
|
| + state->have_skipped_self = true;
|
| + return _URC_NO_REASON;
|
| + }
|
| +
|
| + if (state->skip_count) {
|
| + --state->skip_count;
|
| + return _URC_NO_REASON;
|
| + }
|
|
|
| -// Sometimes, we can try to get a stack trace from within a stack
|
| -// trace, because libunwind can call mmap (maybe indirectly via an
|
| -// internal mmap based memory allocator), and that mmap gets trapped
|
| -// and causes a stack-trace request. If were to try to honor that
|
| -// recursive request, we'd end up with infinite recursion or deadlock.
|
| -// Luckily, it's safe to ignore those subsequent traces. In such
|
| -// cases, we return 0 to indicate the situation.
|
| -static __thread int recursive;
|
| + state->frames[state->frame_count++] = ip;
|
| + if (state->frame_count >= state->max_depth)
|
| + return _URC_END_OF_STACK;
|
| + else
|
| + return _URC_NO_REASON;
|
| +}
|
|
|
| -#endif // BASE_STACKTRACE_LIBINWIND_INL_H_
|
| +#endif // BASE_STACKTRACE_ANDROID_INL_H_
|
|
|
| // Note: this part of the file is included several times.
|
| // Do not put globals below.
|
| @@ -74,55 +114,8 @@ static __thread int recursive;
|
| // int skip_count: how many stack pointers to skip before storing in result
|
| // void* ucp: a ucontext_t* (GetStack{Trace,Frames}WithContext only)
|
| int GET_STACK_TRACE_OR_FRAMES {
|
| - void *ip;
|
| - int n = 0;
|
| - unw_cursor_t cursor;
|
| - unw_context_t uc;
|
| -#if IS_STACK_FRAMES
|
| - unw_word_t sp = 0, next_sp = 0;
|
| -#endif
|
| -
|
| - if (recursive) {
|
| - return 0;
|
| - }
|
| - ++recursive;
|
| -
|
| - unw_getcontext(&uc);
|
| - int ret = unw_init_local(&cursor, &uc);
|
| - assert(ret >= 0);
|
| - skip_count++; // Do not include current frame
|
| -
|
| - while (skip_count--) {
|
| - if (unw_step(&cursor) <= 0) {
|
| - goto out;
|
| - }
|
| -#if IS_STACK_FRAMES
|
| - if (unw_get_reg(&cursor, UNW_REG_SP, &next_sp)) {
|
| - goto out;
|
| - }
|
| -#endif
|
| - }
|
| -
|
| - while (n < max_depth) {
|
| - if (unw_get_reg(&cursor, UNW_REG_IP, (unw_word_t *) &ip) < 0) {
|
| - break;
|
| - }
|
| -#if IS_STACK_FRAMES
|
| - sizes[n] = 0;
|
| -#endif
|
| - result[n++] = ip;
|
| - if (unw_step(&cursor) <= 0) {
|
| - break;
|
| - }
|
| -#if IS_STACK_FRAMES
|
| - sp = next_sp;
|
| - if (unw_get_reg(&cursor, UNW_REG_SP, &next_sp) , 0) {
|
| - break;
|
| - }
|
| - sizes[n - 1] = next_sp - sp;
|
| -#endif
|
| - }
|
| -out:
|
| - --recursive;
|
| - return n;
|
| + stack_crawl_state_t state(
|
| + reinterpret_cast<uintptr_t*>(result), max_depth, skip_count);
|
| + _Unwind_Backtrace(tracer, &state);
|
| + return state.frame_count;
|
| }
|
|
|