OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/debug/stack_trace.h" | 5 #include "base/debug/stack_trace.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <sstream> | 10 #include <sstream> |
11 | 11 |
12 #include "base/macros.h" | 12 #include "base/macros.h" |
13 | 13 |
14 // TODO(dskiba): use blink::StackFrameDepth::getStackStart() instead | |
15 #if HAVE_TRACE_STACK_FRAME_POINTERS && \ | |
16 (defined(OS_ANDROID) || defined(OS_LINUX)) | |
17 #define HAVE_STACK_START | |
18 #include <pthread.h> | |
19 #if defined(__GLIBC__) | |
20 #include "base/process/process_handle.h" | |
21 #include "base/threading/platform_thread.h" | |
22 extern "C" void* __libc_stack_end; // NOLINT | |
23 #endif | |
24 #endif | |
25 | |
14 namespace base { | 26 namespace base { |
15 namespace debug { | 27 namespace debug { |
16 | 28 |
17 StackTrace::StackTrace(const void* const* trace, size_t count) { | 29 StackTrace::StackTrace(const void* const* trace, size_t count) { |
18 count = std::min(count, arraysize(trace_)); | 30 count = std::min(count, arraysize(trace_)); |
19 if (count) | 31 if (count) |
20 memcpy(trace_, trace, count * sizeof(trace_[0])); | 32 memcpy(trace_, trace, count * sizeof(trace_[0])); |
21 count_ = count; | 33 count_ = count; |
22 } | 34 } |
23 | 35 |
(...skipping 10 matching lines...) Expand all Loading... | |
34 std::string StackTrace::ToString() const { | 46 std::string StackTrace::ToString() const { |
35 std::stringstream stream; | 47 std::stringstream stream; |
36 #if !defined(__UCLIBC__) | 48 #if !defined(__UCLIBC__) |
37 OutputToStream(&stream); | 49 OutputToStream(&stream); |
38 #endif | 50 #endif |
39 return stream.str(); | 51 return stream.str(); |
40 } | 52 } |
41 | 53 |
42 #if HAVE_TRACE_STACK_FRAME_POINTERS | 54 #if HAVE_TRACE_STACK_FRAME_POINTERS |
43 | 55 |
56 #if defined(HAVE_STACK_START) | |
57 | |
58 static uintptr_t GetStackStart() { | |
59 #if defined(__GLIBC__) | |
60 if (GetCurrentProcId() == PlatformThread::CurrentId()) { | |
61 // Calling pthread_getattr_np() on the main thread sometimes fails, | |
62 // and also causes reentrancy deadlock in the renderer. | |
63 return reinterpret_cast<uintptr_t>(__libc_stack_end); | |
64 } | |
65 #endif | |
66 | |
67 uintptr_t stack_base = 0; | |
68 size_t stack_size = 0; | |
69 pthread_attr_t attributes; | |
70 int error = pthread_getattr_np(pthread_self(), &attributes); | |
71 if (!error) { | |
72 error = pthread_attr_getstack( | |
73 &attributes, | |
74 reinterpret_cast<void**>(&stack_base), | |
75 &stack_size); | |
76 pthread_attr_destroy(&attributes); | |
77 } | |
78 CHECK(!error); | |
mmenke
2016/05/27 17:39:43
include base/logging.h
| |
79 | |
80 return stack_base + stack_size; | |
81 } | |
82 | |
83 #endif // HAVE_STACK_START | |
84 | |
85 PerThreadStackInfo::PerThreadStackInfo(): start_address(0) {} | |
86 | |
44 size_t TraceStackFramePointers(const void** out_trace, | 87 size_t TraceStackFramePointers(const void** out_trace, |
45 size_t max_depth, | 88 size_t max_depth, |
46 size_t skip_initial) { | 89 size_t skip_initial, |
90 PerThreadStackInfo* stack_info) { | |
47 // Usage of __builtin_frame_address() enables frame pointers in this | 91 // Usage of __builtin_frame_address() enables frame pointers in this |
48 // function even if they are not enabled globally. So 'sp' will always | 92 // function even if they are not enabled globally. So 'sp' will always |
49 // be valid. | 93 // be valid. |
50 uintptr_t sp = reinterpret_cast<uintptr_t>(__builtin_frame_address(0)); | 94 uintptr_t sp = reinterpret_cast<uintptr_t>(__builtin_frame_address(0)); |
51 | 95 |
96 #if defined(HAVE_STACK_START) | |
97 if (stack_info && !stack_info->start_address) { | |
98 stack_info->start_address = GetStackStart(); | |
99 } | |
100 #endif | |
101 | |
52 size_t depth = 0; | 102 size_t depth = 0; |
53 while (depth < max_depth) { | 103 while (depth < max_depth) { |
54 #if defined(__arm__) && defined(__GNUC__) && !defined(__clang__) | 104 #if defined(__arm__) && defined(__GNUC__) && !defined(__clang__) |
55 // GCC and LLVM generate slightly different frames on ARM, see | 105 // GCC and LLVM generate slightly different frames on ARM, see |
56 // https://llvm.org/bugs/show_bug.cgi?id=18505 - LLVM generates | 106 // https://llvm.org/bugs/show_bug.cgi?id=18505 - LLVM generates |
57 // x86-compatible frame, while GCC needs adjustment. | 107 // x86-compatible frame, while GCC needs adjustment. |
58 sp -= sizeof(uintptr_t); | 108 sp -= sizeof(uintptr_t); |
59 #endif | 109 #endif |
60 | 110 |
111 #if defined(HAVE_STACK_START) | |
112 // Both sp[0] and s[1] must be valid. Note that since the stack | |
113 // is growing downwards, 'start_address' is the highest valid address. | |
114 if (stack_info && | |
115 sp + 2 * sizeof(uintptr_t) > stack_info->start_address) { | |
116 break; | |
117 } | |
118 #endif | |
119 | |
61 if (skip_initial != 0) { | 120 if (skip_initial != 0) { |
62 skip_initial--; | 121 skip_initial--; |
63 } else { | 122 } else { |
64 out_trace[depth++] = reinterpret_cast<const void**>(sp)[1]; | 123 out_trace[depth++] = reinterpret_cast<const void**>(sp)[1]; |
65 } | 124 } |
66 | 125 |
67 // Find out next frame pointer | 126 // Find out next frame pointer |
68 // (heuristics are from TCMalloc's stacktrace functions) | 127 // (heuristics are from TCMalloc's stacktrace functions) |
69 { | 128 { |
70 uintptr_t next_sp = reinterpret_cast<const uintptr_t*>(sp)[0]; | 129 uintptr_t next_sp = reinterpret_cast<const uintptr_t*>(sp)[0]; |
(...skipping 12 matching lines...) Expand all Loading... | |
83 } | 142 } |
84 } | 143 } |
85 | 144 |
86 return depth; | 145 return depth; |
87 } | 146 } |
88 | 147 |
89 #endif // HAVE_TRACE_STACK_FRAME_POINTERS | 148 #endif // HAVE_TRACE_STACK_FRAME_POINTERS |
90 | 149 |
91 } // namespace debug | 150 } // namespace debug |
92 } // namespace base | 151 } // namespace base |
OLD | NEW |