| // Copyright (c) 2013, Google Inc. |
| // All rights reserved. |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are |
| // met: |
| // |
| // * Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // * Redistributions in binary form must reproduce the above |
| // copyright notice, this list of conditions and the following disclaimer |
| // in the documentation and/or other materials provided with the |
| // distribution. |
| // * Neither the name of Google Inc. nor the names of its |
| // contributors may be used to endorse or promote products derived from |
| // this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| // --- |
| // Author: Marcus Bulach |
| // This is inspired by Doug Kwan's ARM's stacktrace code and Dai Mikurube's |
| // stack trace for chromium on android. |
| // |
| |
| #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: |
| |
| #include <stdint.h> // for uintptr_t |
| // See http://crbug.com/236855, would be better to use Bionic's |
| // new get_backtrace(). |
| #include <unwind.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; |
| } |
| |
| 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_ANDROID_INL_H_ |
| |
| // Note: this part of the file is included several times. |
| // Do not put globals below. |
| |
| // The following 4 functions are generated from the code below: |
| // GetStack{Trace,Frames}() |
| // GetStack{Trace,Frames}WithContext() |
| // |
| // These functions take the following args: |
| // void** result: the stack-trace, as an array |
| // int* sizes: the size of each stack frame, as an array |
| // (GetStackFrames* only) |
| // int max_depth: the size of the result (and sizes) array(s) |
| // 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 { |
| stack_crawl_state_t state( |
| reinterpret_cast<uintptr_t*>(result), max_depth, skip_count); |
| _Unwind_Backtrace(tracer, &state); |
| return state.frame_count; |
| } |