| 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; | 
| } | 
|  |