Bug 1113930 - Use the actual stack end address on x86 OSX and Android for the stack walker. r=froydnj
authorMike Hommey <mh+mozilla@glandium.org>
Tue, 22 Dec 2015 17:19:37 +0900
changeset 317677 acdd7908ca0ff345c509dd9e2c0395bb00277289
parent 317676 500961db039b155507d69ab2b56a7e084ae4804c
child 317678 691f2e687e46d1b166b88b0a3f9dbd480bff9afa
push id8746
push userananuti@gmail.com
push dateSun, 27 Dec 2015 23:03:33 +0000
reviewersfroydnj
bugs1113930, 989499
milestone46.0a1
Bug 1113930 - Use the actual stack end address on x86 OSX and Android for the stack walker. r=froydnj Also, in the unlikely case none of the supported methods is available, error out at compile time, because it's not supposed to happen, apart if something like what bug 989499 did happens again.
mozglue/misc/StackWalk.cpp
--- a/mozglue/misc/StackWalk.cpp
+++ b/mozglue/misc/StackWalk.cpp
@@ -52,16 +52,22 @@ static CriticalAddress gCriticalAddress;
 #else
 #define HAVE___LIBC_STACK_END 0
 #endif
 
 #if HAVE___LIBC_STACK_END
 extern MOZ_EXPORT void* __libc_stack_end; // from ld-linux.so
 #endif
 
+#ifdef ANDROID
+#include <algorithm>
+#include <unistd.h>
+#include <pthread.h>
+#endif
+
 #if MOZ_STACKWALK_SUPPORTS_MACOSX
 #include <pthread.h>
 #include <sys/errno.h>
 #ifdef MOZ_WIDGET_COCOA
 #include <CoreServices/CoreServices.h>
 #endif
 
 typedef void
@@ -896,18 +902,45 @@ MozStackWalk(MozWalkStackCallback aCallb
   StackWalkInitCriticalAddress();
 
   // Get the frame pointer
   void** bp = (void**)__builtin_frame_address(0);
 
   void* stackEnd;
 #if HAVE___LIBC_STACK_END
   stackEnd = __libc_stack_end;
+#elif defined(XP_DARWIN)
+  stackEnd = pthread_get_stackaddr_np(pthread_self());
+#elif defined(ANDROID)
+  pthread_attr_t sattr;
+  pthread_attr_init(&sattr);
+  pthread_getattr_np(pthread_self(), &sattr);
+  void* stackBase = stackEnd = nullptr;
+  size_t stackSize = 0;
+  if (gettid() != getpid()) {
+    // bionic's pthread_attr_getstack doesn't tell the truth for the main
+    // thread (see bug 846670). So don't use it for the main thread.
+    if (!pthread_attr_getstack(&sattr, &stackBase, &stackSize)) {
+      stackEnd = static_cast<char*>(stackBase) + stackSize;
+    } else {
+      stackEnd = nullptr;
+    }
+  }
+  if (!stackEnd) {
+    // So consider the current frame pointer + an arbitrary size of 8MB
+    // (modulo overflow ; not really arbitrary as it's the default stack
+    // size for the main thread) if pthread_attr_getstack failed for
+    // some reason (or was skipped).
+    static const uintptr_t kMaxStackSize = 8 * 1024 * 1024;
+    uintptr_t maxStackStart = uintptr_t(-1) - kMaxStackSize;
+    uintptr_t stackStart = std::max(maxStackStart, uintptr_t(bp));
+    stackEnd = reinterpret_cast<void*>(stackStart + kMaxStackSize);
+  }
 #else
-  stackEnd = reinterpret_cast<void*>(-1);
+#  error Unsupported configuration
 #endif
   return FramePointerStackWalk(aCallback, aSkipFrames, aMaxFrames,
                                aClosure, bp, stackEnd);
 }
 
 #elif defined(HAVE__UNWIND_BACKTRACE)
 
 // libgcc_s.so symbols _Unwind_Backtrace@@GCC_3.3 and _Unwind_GetIP@@GCC_3.0