| Index: base/debug/stack_trace.cc
|
| diff --git a/base/debug/stack_trace.cc b/base/debug/stack_trace.cc
|
| index 1c96a569d9795544231714f0d0b1f9b0da036355..70a960470569026e02d4b0e1ebd660a497a3876d 100644
|
| --- a/base/debug/stack_trace.cc
|
| +++ b/base/debug/stack_trace.cc
|
| @@ -10,6 +10,7 @@
|
| #include <sstream>
|
|
|
| #include "base/macros.h"
|
| +#include "base/third_party/symbolize/symbolize.h"
|
|
|
| namespace base {
|
| namespace debug {
|
| @@ -41,9 +42,61 @@ std::string StackTrace::ToString() const {
|
|
|
| #if HAVE_TRACE_STACK_FRAME_POINTERS
|
|
|
| +#if defined(OS_ANDROID) && !defined(COMPONENT_BUILD)
|
| +
|
| +#define HAVE_CHROME_CODE_RANGE
|
| +
|
| +bool FindChromeCodeRange(const void** out_start_address,
|
| + const void** out_end_address) {
|
| + struct FindArgs {
|
| + const void** out_start_address;
|
| + const void** out_end_address;
|
| + };
|
| +
|
| + auto find_callback = [](void* data,
|
| + const google::MappedRegion& region) -> bool {
|
| + const void* region_start_address = reinterpret_cast<const void*>(
|
| + static_cast<uintptr_t>(region.start_address));
|
| + const void* region_end_address = reinterpret_cast<const void*>(
|
| + static_cast<uintptr_t>(region.end_address));
|
| +
|
| + const void* self_address = reinterpret_cast<const void*>(
|
| + &FindChromeCodeRange);
|
| + if (self_address >= region_start_address &&
|
| + self_address < region_end_address) {
|
| + FindArgs* args = static_cast<FindArgs*>(data);
|
| + *args->out_start_address = region_start_address;
|
| + *args->out_end_address = region_end_address;
|
| + return true;
|
| + }
|
| +
|
| + return false;
|
| + };
|
| +
|
| + FindArgs args = {
|
| + out_start_address,
|
| + out_end_address
|
| + };
|
| + return google::FindMappedRegion(&args, find_callback);
|
| +}
|
| +
|
| +#endif // !defined(COMPONENT_BUILD)
|
| +
|
| size_t TraceStackFramePointers(const void** out_trace,
|
| size_t max_depth,
|
| size_t skip_initial) {
|
| +#if defined(HAVE_CHROME_CODE_RANGE)
|
| + static const void* chrome_code_start = 0;
|
| + static const void* chrome_code_end = 0;
|
| + if (!chrome_code_start || !chrome_code_end) {
|
| + if (!FindChromeCodeRange(&chrome_code_start, &chrome_code_end)) {
|
| + // Something went wrong; disable unwinding.
|
| + chrome_code_start = reinterpret_cast<const void*>(UINTPTR_MAX);
|
| + chrome_code_end = reinterpret_cast<const void*>(UINTPTR_MAX);
|
| + }
|
| + }
|
| +#endif
|
| +
|
| // Usage of __builtin_frame_address() enables frame pointers in this
|
| // function even if they are not enabled globally. So 'sp' will always
|
| // be valid.
|
| @@ -61,7 +114,42 @@ size_t TraceStackFramePointers(const void** out_trace,
|
| if (skip_initial != 0) {
|
| skip_initial--;
|
| } else {
|
| - out_trace[depth++] = reinterpret_cast<const void**>(sp)[1];
|
| +#if defined(HAVE_CHROME_CODE_RANGE) && \
|
| + defined(__clang__) && defined(__thumb__)
|
| +
|
| + // In thumb fp is r7 and lr is r14, so there can be 1-7 registers
|
| + // in between.
|
| + const void* pc;
|
| + for (size_t i = 1; i <= 7; ++i) {
|
| + pc = reinterpret_cast<const void**>(sp)[i];
|
| + if (pc >= chrome_code_start && pc < chrome_code_end) {
|
| + // Looks like code, use it.
|
| + break;
|
| + }
|
| + pc = nullptr;
|
| + }
|
| + if (!pc) {
|
| + // Didn't find anything, stop unwinding.
|
| + break;
|
| + }
|
| + out_trace[depth++] = pc;
|
| +
|
| +#else
|
| +
|
| + // In arm mode we have proper stack frames, so lr always follows fp.
|
| + const void* pc = reinterpret_cast<const void**>(sp)[1];
|
| + out_trace[depth++] = pc;
|
| +#if defined(HAVE_CHROME_CODE_RANGE)
|
| + if (pc < chrome_code_start || pc >= chrome_code_end) {
|
| + // Stop unwinding after first non-Chrome PC - it's either bogus,
|
| + // or from a system library. But since system libraries on Android
|
| + // and Linux are built without frame pointers, there is no point
|
| + // diving into them.
|
| + break;
|
| + }
|
| +#endif
|
| +
|
| +#endif // HAVE_CHROME_CODE_RANGE && __clang__ && __thumb__
|
| }
|
|
|
| // Find out next frame pointer
|
|
|