1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jsnativestack.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,162 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "jsnativestack.h" 1.11 + 1.12 +#ifdef XP_WIN 1.13 +# include "jswin.h" 1.14 + 1.15 +#elif defined(XP_MACOSX) || defined(DARWIN) || defined(XP_UNIX) 1.16 +# include <pthread.h> 1.17 + 1.18 +# if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) 1.19 +# include <pthread_np.h> 1.20 +# endif 1.21 + 1.22 +# if defined(ANDROID) 1.23 +# include <sys/types.h> 1.24 +# include <unistd.h> 1.25 +# endif 1.26 + 1.27 +#else 1.28 +# error "Unsupported platform" 1.29 + 1.30 +#endif 1.31 + 1.32 +#if defined(XP_WIN) 1.33 + 1.34 +void * 1.35 +js::GetNativeStackBaseImpl() 1.36 +{ 1.37 +# if defined(_M_IX86) && defined(_MSC_VER) 1.38 + /* 1.39 + * offset 0x18 from the FS segment register gives a pointer to 1.40 + * the thread information block for the current thread 1.41 + */ 1.42 + NT_TIB* pTib; 1.43 + __asm { 1.44 + MOV EAX, FS:[18h] 1.45 + MOV pTib, EAX 1.46 + } 1.47 + return static_cast<void*>(pTib->StackBase); 1.48 + 1.49 +# elif defined(_M_X64) 1.50 + PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb()); 1.51 + return reinterpret_cast<void*>(pTib->StackBase); 1.52 + 1.53 +# elif defined(_WIN32) && defined(__GNUC__) 1.54 + NT_TIB* pTib; 1.55 + asm ("movl %%fs:0x18, %0\n" : "=r" (pTib)); 1.56 + return static_cast<void*>(pTib->StackBase); 1.57 + 1.58 +# endif 1.59 +} 1.60 + 1.61 +#elif defined(SOLARIS) 1.62 + 1.63 +#include <ucontext.h> 1.64 + 1.65 +JS_STATIC_ASSERT(JS_STACK_GROWTH_DIRECTION < 0); 1.66 + 1.67 +void * 1.68 +js::GetNativeStackBaseImpl() 1.69 +{ 1.70 + stack_t st; 1.71 + stack_getbounds(&st); 1.72 + return static_cast<char*>(st.ss_sp) + st.ss_size; 1.73 +} 1.74 + 1.75 +#elif defined(AIX) 1.76 + 1.77 +#include <ucontext.h> 1.78 + 1.79 +JS_STATIC_ASSERT(JS_STACK_GROWTH_DIRECTION < 0); 1.80 + 1.81 +void * 1.82 +js::GetNativeStackBaseImpl() 1.83 +{ 1.84 + ucontext_t context; 1.85 + getcontext(&context); 1.86 + return static_cast<char*>(context.uc_stack.ss_sp) + 1.87 + context.uc_stack.ss_size; 1.88 +} 1.89 + 1.90 +#else /* XP_UNIX */ 1.91 + 1.92 +void * 1.93 +js::GetNativeStackBaseImpl() 1.94 +{ 1.95 + pthread_t thread = pthread_self(); 1.96 +# if defined(XP_MACOSX) || defined(DARWIN) 1.97 + return pthread_get_stackaddr_np(thread); 1.98 + 1.99 +# else 1.100 + pthread_attr_t sattr; 1.101 + pthread_attr_init(&sattr); 1.102 +# if defined(__OpenBSD__) 1.103 + stack_t ss; 1.104 +# elif defined(PTHREAD_NP_H) || defined(_PTHREAD_NP_H_) || defined(NETBSD) 1.105 + /* e.g. on FreeBSD 4.8 or newer, neundorf@kde.org */ 1.106 + pthread_attr_get_np(thread, &sattr); 1.107 +# else 1.108 + /* 1.109 + * FIXME: this function is non-portable; 1.110 + * other POSIX systems may have different np alternatives 1.111 + */ 1.112 + pthread_getattr_np(thread, &sattr); 1.113 +# endif 1.114 + 1.115 + void *stackBase = 0; 1.116 + size_t stackSize = 0; 1.117 + int rc; 1.118 +# if defined(__OpenBSD__) 1.119 + rc = pthread_stackseg_np(pthread_self(), &ss); 1.120 + stackBase = (void*)((size_t) ss.ss_sp - ss.ss_size); 1.121 + stackSize = ss.ss_size; 1.122 +# elif defined(ANDROID) 1.123 + if (gettid() == getpid()) { 1.124 + // bionic's pthread_attr_getstack doesn't tell the truth for the main 1.125 + // thread (see bug 846670). So we scan /proc/self/maps to find the 1.126 + // segment which contains the stack. 1.127 + rc = -1; 1.128 + FILE *fs = fopen("/proc/self/maps", "r"); 1.129 + if (fs) { 1.130 + char line[100]; 1.131 + unsigned long stackAddr = (unsigned long)&sattr; 1.132 + while (fgets(line, sizeof(line), fs) != nullptr) { 1.133 + unsigned long stackStart; 1.134 + unsigned long stackEnd; 1.135 + if (sscanf(line, "%lx-%lx ", &stackStart, &stackEnd) == 2 && 1.136 + stackAddr >= stackStart && stackAddr < stackEnd) { 1.137 + stackBase = (void *)stackStart; 1.138 + stackSize = stackEnd - stackStart; 1.139 + rc = 0; 1.140 + break; 1.141 + } 1.142 + } 1.143 + fclose(fs); 1.144 + } 1.145 + } else 1.146 + // For non main-threads pthread allocates the stack itself so it tells 1.147 + // the truth. 1.148 + rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize); 1.149 +# else 1.150 + rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize); 1.151 +# endif 1.152 + if (rc) 1.153 + MOZ_CRASH(); 1.154 + JS_ASSERT(stackBase); 1.155 + pthread_attr_destroy(&sattr); 1.156 + 1.157 +# if JS_STACK_GROWTH_DIRECTION > 0 1.158 + return stackBase; 1.159 +# else 1.160 + return static_cast<char*>(stackBase) + stackSize; 1.161 +# endif 1.162 +# endif 1.163 +} 1.164 + 1.165 +#endif /* !XP_WIN */