diff -r 000000000000 -r 6474c204b198 js/src/jsnativestack.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/js/src/jsnativestack.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,162 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "jsnativestack.h" + +#ifdef XP_WIN +# include "jswin.h" + +#elif defined(XP_MACOSX) || defined(DARWIN) || defined(XP_UNIX) +# include + +# if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) +# include +# endif + +# if defined(ANDROID) +# include +# include +# endif + +#else +# error "Unsupported platform" + +#endif + +#if defined(XP_WIN) + +void * +js::GetNativeStackBaseImpl() +{ +# if defined(_M_IX86) && defined(_MSC_VER) + /* + * offset 0x18 from the FS segment register gives a pointer to + * the thread information block for the current thread + */ + NT_TIB* pTib; + __asm { + MOV EAX, FS:[18h] + MOV pTib, EAX + } + return static_cast(pTib->StackBase); + +# elif defined(_M_X64) + PNT_TIB64 pTib = reinterpret_cast(NtCurrentTeb()); + return reinterpret_cast(pTib->StackBase); + +# elif defined(_WIN32) && defined(__GNUC__) + NT_TIB* pTib; + asm ("movl %%fs:0x18, %0\n" : "=r" (pTib)); + return static_cast(pTib->StackBase); + +# endif +} + +#elif defined(SOLARIS) + +#include + +JS_STATIC_ASSERT(JS_STACK_GROWTH_DIRECTION < 0); + +void * +js::GetNativeStackBaseImpl() +{ + stack_t st; + stack_getbounds(&st); + return static_cast(st.ss_sp) + st.ss_size; +} + +#elif defined(AIX) + +#include + +JS_STATIC_ASSERT(JS_STACK_GROWTH_DIRECTION < 0); + +void * +js::GetNativeStackBaseImpl() +{ + ucontext_t context; + getcontext(&context); + return static_cast(context.uc_stack.ss_sp) + + context.uc_stack.ss_size; +} + +#else /* XP_UNIX */ + +void * +js::GetNativeStackBaseImpl() +{ + pthread_t thread = pthread_self(); +# if defined(XP_MACOSX) || defined(DARWIN) + return pthread_get_stackaddr_np(thread); + +# else + pthread_attr_t sattr; + pthread_attr_init(&sattr); +# if defined(__OpenBSD__) + stack_t ss; +# elif defined(PTHREAD_NP_H) || defined(_PTHREAD_NP_H_) || defined(NETBSD) + /* e.g. on FreeBSD 4.8 or newer, neundorf@kde.org */ + pthread_attr_get_np(thread, &sattr); +# else + /* + * FIXME: this function is non-portable; + * other POSIX systems may have different np alternatives + */ + pthread_getattr_np(thread, &sattr); +# endif + + void *stackBase = 0; + size_t stackSize = 0; + int rc; +# if defined(__OpenBSD__) + rc = pthread_stackseg_np(pthread_self(), &ss); + stackBase = (void*)((size_t) ss.ss_sp - ss.ss_size); + stackSize = ss.ss_size; +# elif defined(ANDROID) + if (gettid() == getpid()) { + // bionic's pthread_attr_getstack doesn't tell the truth for the main + // thread (see bug 846670). So we scan /proc/self/maps to find the + // segment which contains the stack. + rc = -1; + FILE *fs = fopen("/proc/self/maps", "r"); + if (fs) { + char line[100]; + unsigned long stackAddr = (unsigned long)&sattr; + while (fgets(line, sizeof(line), fs) != nullptr) { + unsigned long stackStart; + unsigned long stackEnd; + if (sscanf(line, "%lx-%lx ", &stackStart, &stackEnd) == 2 && + stackAddr >= stackStart && stackAddr < stackEnd) { + stackBase = (void *)stackStart; + stackSize = stackEnd - stackStart; + rc = 0; + break; + } + } + fclose(fs); + } + } else + // For non main-threads pthread allocates the stack itself so it tells + // the truth. + rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize); +# else + rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize); +# endif + if (rc) + MOZ_CRASH(); + JS_ASSERT(stackBase); + pthread_attr_destroy(&sattr); + +# if JS_STACK_GROWTH_DIRECTION > 0 + return stackBase; +# else + return static_cast(stackBase) + stackSize; +# endif +# endif +} + +#endif /* !XP_WIN */