Index: base/debug/stack_trace.cc |
diff --git a/base/debug/stack_trace.cc b/base/debug/stack_trace.cc |
index ac0ead76be2b1cf62339e55fa20b59f6488acbe9..775e54f7cd5118941d46b7c3c40b6a4d1c8bd1e9 100644 |
--- a/base/debug/stack_trace.cc |
+++ b/base/debug/stack_trace.cc |
@@ -7,16 +7,25 @@ |
#include <string.h> |
#include <algorithm> |
+#include <limits> |
#include <sstream> |
#include "base/macros.h" |
-#if HAVE_TRACE_STACK_FRAME_POINTERS && defined(OS_ANDROID) |
+#if HAVE_TRACE_STACK_FRAME_POINTERS |
+ |
+#if defined(OS_LINUX) || defined(OS_ANDROID) |
#include <pthread.h> |
#include "base/process/process_handle.h" |
#include "base/threading/platform_thread.h" |
#endif |
+#if defined(OS_LINUX) && defined(__GLIBC__) |
+extern "C" void* __libc_stack_end; |
+#endif |
+ |
+#endif // HAVE_TRACE_STACK_FRAME_POINTERS |
+ |
namespace base { |
namespace debug { |
@@ -47,9 +56,8 @@ std::string StackTrace::ToString() const { |
#if HAVE_TRACE_STACK_FRAME_POINTERS |
-#if defined(OS_ANDROID) |
- |
static uintptr_t GetStackEnd() { |
+#if defined(OS_ANDROID) |
// Bionic reads proc/maps on every call to pthread_getattr_np() when called |
// from the main thread. So we need to cache end of stack in that case to get |
// acceptable performance. |
@@ -58,7 +66,6 @@ static uintptr_t GetStackEnd() { |
static uintptr_t main_stack_end = 0; |
bool is_main_thread = GetCurrentProcId() == PlatformThread::CurrentId(); |
- |
if (is_main_thread && main_stack_end) { |
return main_stack_end; |
} |
@@ -81,9 +88,25 @@ static uintptr_t GetStackEnd() { |
main_stack_end = stack_end; |
} |
return stack_end; |
-} |
-#endif // defined(OS_ANDROID) |
+#elif defined(OS_LINUX) && defined(__GLIBC__) |
+ |
+ if (GetCurrentProcId() == PlatformThread::CurrentId()) { |
+ // For the main thread we have a shortcut. |
+ return reinterpret_cast<uintptr_t>(__libc_stack_end); |
+ } |
+ |
+ // No easy way to get stack end for non-main threads, see crbug.com/617730. |
+ |
+#else |
+ |
+ // TODO(dskiba): support Windows, macOS |
+ |
+#endif |
+ |
+ // Couldn't get end of stack address. |
+ return std::numeric_limits<uintptr_t>::max(); |
+} |
size_t TraceStackFramePointers(const void** out_trace, |
size_t max_depth, |
@@ -93,9 +116,7 @@ size_t TraceStackFramePointers(const void** out_trace, |
// be valid. |
uintptr_t sp = reinterpret_cast<uintptr_t>(__builtin_frame_address(0)); |
-#if defined(OS_ANDROID) |
uintptr_t stack_end = GetStackEnd(); |
-#endif |
size_t depth = 0; |
while (depth < max_depth) { |
@@ -106,12 +127,10 @@ size_t TraceStackFramePointers(const void** out_trace, |
sp -= sizeof(uintptr_t); |
#endif |
-#if defined(OS_ANDROID) |
// Both sp[0] and s[1] must be valid. |
if (sp + 2 * sizeof(uintptr_t) > stack_end) { |
break; |
} |
-#endif |
if (skip_initial != 0) { |
skip_initial--; |