static int get_stack(void **addr, size_t *size) { #define CHECK_ERR(expr) \ {int err = (expr); if (err) return err;} #if defined HAVE_PTHREAD_GETATTR_NP || defined HAVE_PTHREAD_ATTR_GET_NP pthread_attr_t attr; size_t guard = 0; # ifdef HAVE_PTHREAD_GETATTR_NP CHECK_ERR(pthread_getattr_np(pthread_self(), &attr)); # ifdef HAVE_PTHREAD_ATTR_GETSTACK CHECK_ERR(pthread_attr_getstack(&attr, addr, size)); # else CHECK_ERR(pthread_attr_getstackaddr(&attr, addr)); CHECK_ERR(pthread_attr_getstacksize(&attr, size)); # endif if (pthread_attr_getguardsize(&attr, &guard) == 0) { STACK_GROW_DIR_DETECTION; STACK_DIR_UPPER((void)0, (void)(*addr = (char *)*addr + guard)); *size -= guard; } # else CHECK_ERR(pthread_attr_init(&attr)); CHECK_ERR(pthread_attr_get_np(pthread_self(), &attr)); CHECK_ERR(pthread_attr_getstackaddr(&attr, addr)); CHECK_ERR(pthread_attr_getstacksize(&attr, size)); # endif CHECK_ERR(pthread_attr_getguardsize(&attr, &guard)); *size -= guard; # ifndef HAVE_PTHREAD_GETATTR_NP pthread_attr_destroy(&attr); # endif #elif defined HAVE_PTHREAD_GET_STACKADDR_NP && defined HAVE_PTHREAD_GET_STACKSIZE_NP pthread_t th = pthread_self(); *addr = pthread_get_stackaddr_np(th); *size = pthread_get_stacksize_np(th); #elif defined HAVE_THR_STKSEGMENT || defined HAVE_PTHREAD_STACKSEG_NP stack_t stk; # if defined HAVE_THR_STKSEGMENT CHECK_ERR(thr_stksegment(&stk)); # else CHECK_ERR(pthread_stackseg_np(pthread_self(), &stk)); # endif *addr = stk.ss_sp; *size = stk.ss_size; #elif defined HAVE_PTHREAD_GETTHRDS_NP pthread_t th = pthread_self(); struct __pthrdsinfo thinfo; char reg[256]; int regsiz=sizeof(reg); CHECK_ERR(pthread_getthrds_np(&th, PTHRDSINFO_QUERY_ALL, &thinfo, sizeof(thinfo), ®, ®siz)); *addr = thinfo.__pi_stackaddr; *size = thinfo.__pi_stacksize; #endif return 0; #undef CHECK_ERR }
static void * threadfunc2(void *arg) { static uintptr_t i = 0; uintptr_t j; pthread_attr_t attr; size_t stacksize; j = (uintptr_t)arg; #ifdef __FreeBSD__ pthread_attr_init(&attr); #endif ATF_REQUIRE(pthread_attr_get_np(pthread_self(), &attr) == 0); ATF_REQUIRE(pthread_attr_getstacksize(&attr, &stacksize) == 0); ATF_REQUIRE(stacksize == STACKSIZE * (j + 1)); ATF_REQUIRE(pthread_attr_destroy(&attr) == 0); if (i++ == j) error = false; pthread_exit((void *)i); return NULL; }
size_t MachineThreads::Thread::getRegisters(MachineThreads::Thread::Registers& registers) { Thread::Registers::PlatformRegisters& regs = registers.regs; #if OS(DARWIN) #if CPU(X86) unsigned user_count = sizeof(regs)/sizeof(int); thread_state_flavor_t flavor = i386_THREAD_STATE; #elif CPU(X86_64) unsigned user_count = x86_THREAD_STATE64_COUNT; thread_state_flavor_t flavor = x86_THREAD_STATE64; #elif CPU(PPC) unsigned user_count = PPC_THREAD_STATE_COUNT; thread_state_flavor_t flavor = PPC_THREAD_STATE; #elif CPU(PPC64) unsigned user_count = PPC_THREAD_STATE64_COUNT; thread_state_flavor_t flavor = PPC_THREAD_STATE64; #elif CPU(ARM) unsigned user_count = ARM_THREAD_STATE_COUNT; thread_state_flavor_t flavor = ARM_THREAD_STATE; #elif CPU(ARM64) unsigned user_count = ARM_THREAD_STATE64_COUNT; thread_state_flavor_t flavor = ARM_THREAD_STATE64; #else #error Unknown Architecture #endif kern_return_t result = thread_get_state(platformThread, flavor, (thread_state_t)®s, &user_count); if (result != KERN_SUCCESS) { WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, "JavaScript garbage collection failed because thread_get_state returned an error (%d). This is probably the result of running inside Rosetta, which is not supported.", result); CRASH(); } return user_count * sizeof(uintptr_t); // end OS(DARWIN) #elif OS(WINDOWS) regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; GetThreadContext(platformThreadHandle, ®s); return sizeof(CONTEXT); #elif USE(PTHREADS) pthread_attr_init(®s); #if HAVE(PTHREAD_NP_H) || OS(NETBSD) #if !OS(OPENBSD) // e.g. on FreeBSD 5.4, [email protected] pthread_attr_get_np(platformThread, ®s); #endif #else // FIXME: this function is non-portable; other POSIX systems may have different np alternatives pthread_getattr_np(platformThread, ®s); #endif return 0; #else #error Need a way to get thread registers on this platform #endif }
void *nativeStackBase() { pthread_attr_t attr; size_t size; void *addr; pthread_attr_init(&attr); pthread_attr_get_np(pthread_self(), &attr); pthread_attr_getstack(&attr, &addr, &size); return addr+size; }
void mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize) { pthread_attr_t attr; *staddr = NULL; *stsize = (size_t)-1; pthread_attr_init (&attr); pthread_attr_get_np (pthread_self (), &attr); pthread_attr_getstack (&attr, (void**)staddr, stsize); pthread_attr_destroy (&attr); }
static int get_stack(void **addr, size_t *size) { #define CHECK_ERR(expr) \ {int err = (expr); if (err) return err;} #if defined HAVE_PTHREAD_GETATTR_NP || defined HAVE_PTHREAD_ATTR_GET_NP pthread_attr_t attr; size_t guard = 0; # ifdef HAVE_PTHREAD_GETATTR_NP CHECK_ERR(pthread_getattr_np(pthread_self(), &attr)); # ifdef HAVE_PTHREAD_ATTR_GETSTACK CHECK_ERR(pthread_attr_getstack(&attr, addr, size)); # else CHECK_ERR(pthread_attr_getstackaddr(&attr, addr)); CHECK_ERR(pthread_attr_getstacksize(&attr, size)); # endif if (pthread_attr_getguardsize(&attr, &guard) == 0) { STACK_GROW_DIR_DETECTION; STACK_DIR_UPPER((void)0, *addr = (char *)*addr + guard); *size -= guard; } # else CHECK_ERR(pthread_attr_init(&attr)); CHECK_ERR(pthread_attr_get_np(pthread_self(), &attr)); CHECK_ERR(pthread_attr_getstackaddr(&attr, addr)); CHECK_ERR(pthread_attr_getstacksize(&attr, size)); # endif CHECK_ERR(pthread_attr_getguardsize(&attr, &guard)); # ifndef HAVE_PTHREAD_GETATTR_NP pthread_attr_destroy(&attr); # endif size -= guard; #elif defined HAVE_PTHREAD_GET_STACKADDR_NP && defined HAVE_PTHREAD_GET_STACKSIZE_NP pthread_t th = pthread_self(); *addr = pthread_get_stackaddr_np(th); *size = pthread_get_stacksize_np(th); #elif defined HAVE_THR_STKSEGMENT || defined HAVE_PTHREAD_STACKSEG_NP stack_t stk; # if defined HAVE_THR_STKSEGMENT CHECK_ERR(thr_stksegment(&stk)); # else CHECK_ERR(pthread_stackseg_np(pthread_self(), &stk)); # endif *addr = stk.ss_sp; *size = stk.ss_size; #endif return 0; #undef CHECK_ERR }
void * 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, [email protected] */ 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; # ifdef DEBUG int rc = # endif # if defined(__OpenBSD__) pthread_stackseg_np(pthread_self(), &ss); stackBase = (void*)((size_t) ss.ss_sp - ss.ss_size); stackSize = ss.ss_size; # else pthread_attr_getstack(&sattr, &stackBase, &stackSize); # endif JS_ASSERT(!rc); JS_ASSERT(stackBase); pthread_attr_destroy(&sattr); # if JS_STACK_GROWTH_DIRECTION > 0 return stackBase; # else return static_cast<char*>(stackBase) + stackSize; # endif # endif }
void StackBounds::initialize() { void* stackBase = 0; size_t stackSize = 0; pthread_t thread = pthread_self(); pthread_attr_t sattr; pthread_attr_init(&sattr); #if HAVE(PTHREAD_NP_H) || OS(NETBSD) // e.g. on FreeBSD 5.4, [email protected] 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 int rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize); (void)rc; // FIXME: Deal with error code somehow? Seems fatal. ASSERT(stackBase); pthread_attr_destroy(&sattr); m_bound = stackBase; m_origin = static_cast<char*>(stackBase) + stackSize; }
inline int find_stack_addr_size(void** paddr, size_t* psize) { #if defined (HAIKU) int status; thread_info info; thread_id this_thread = find_thread(NULL); status = get_thread_info(this_thread,&info); *paddr = info.stack_base; *psize = (size_t)info.stack_base - (size_t)info.stack_end; return 0; #else int err; pthread_attr_t pthread_attr; void* stack_addr; size_t stack_size; pthread_t thread = pthread_self(); if (!paddr) return EINVAL; err = pthread_attr_init(&pthread_attr); if (err != 0) return err; #if defined(FREEBSD) err = pthread_attr_get_np(thread, &pthread_attr); #else err = pthread_getattr_np(thread, &pthread_attr); #endif if (err != 0) return err; err = pthread_attr_getstack(&pthread_attr, &stack_addr, &stack_size); if (err != 0) return err; pthread_attr_destroy(&pthread_attr); *paddr = (void*)((size_t)stack_addr + stack_size); *psize = stack_size; return 0; #endif }
void attach_os_thread(init_thread_data *scribble) { os_thread_t os = pthread_self(); odxprint(misc, "attach_os_thread: attaching to %p", os); struct thread *th = create_thread_struct(NIL); block_deferrable_signals(&scribble->oldset); th->no_tls_value_marker = NO_TLS_VALUE_MARKER_WIDETAG; /* We don't actually want a pthread_attr here, but rather than add * `if's to the post-mostem, let's just keep that code happy by * keeping it initialized: */ pthread_attr_init(th->os_attr); #ifndef LISP_FEATURE_WIN32 /* On windows, arch_os_thread_init will take care of finding the * stack. */ void *stack_addr; size_t stack_size; #ifdef LISP_FEATURE_OPENBSD stack_t stack; pthread_stackseg_np(os, &stack); stack_size = stack.ss_size; stack_addr = (void*)((size_t)stack.ss_sp - stack_size); #elif defined LISP_FEATURE_SUNOS stack_t stack; thr_stksegment(&stack); stack_size = stack.ss_size; stack_addr = (void*)((size_t)stack.ss_sp - stack_size); #elif defined(LISP_FEATURE_DARWIN) stack_addr = pthread_get_stackaddr_np(os); stack_size = pthread_get_stacksize_np(os); #else pthread_attr_t attr; #ifdef LISP_FEATURE_FREEBSD pthread_attr_get_np(os, &attr); #else int pthread_getattr_np(pthread_t, pthread_attr_t *); pthread_getattr_np(os, &attr); #endif pthread_attr_getstack(&attr, &stack_addr, &stack_size); #endif th->control_stack_start = stack_addr; th->control_stack_end = (void *) (((uintptr_t) stack_addr) + stack_size); #endif init_new_thread(th, scribble, 0); /* We will be calling into Lisp soon, and the functions being called * recklessly ignore the comment in target-thread which says that we * must be careful to not cause GC while initializing a new thread. * Since we first need to create a fresh thread object, it's really * tempting to just perform such unsafe allocation though. So let's * at least try to suppress GC before consing, and hope that it * works: */ bind_variable(GC_INHIBIT, T, th); uword_t stacksize = (uword_t) th->control_stack_end - (uword_t) th->control_stack_start; odxprint(misc, "attach_os_thread: attached %p as %p (0x%lx bytes stack)", os, th, (long) stacksize); }
/********************************************************************************************************* ** 函数名称: pthread_getattr_np ** 功能描述: 获取线程属性控制块 (Linux 扩展接口) ** 输 入 : thread 线程 ID ** pattr 需要设置的 attr 指针. ** 输 出 : ERROR CODE ** 全局变量: ** 调用模块: API 函数 *********************************************************************************************************/ LW_API int pthread_getattr_np (pthread_t thread, pthread_attr_t *pattr) { return (pthread_attr_get_np(thread, pattr)); }
/* * Get the initial address and size of current thread's stack */ static int get_stack(void **addr, size_t *size) { #define CHECK_ERR(expr) \ {int err = (expr); if (err) return err;} #ifdef HAVE_PTHREAD_GETATTR_NP /* Linux */ pthread_attr_t attr; size_t guard = 0; STACK_GROW_DIR_DETECTION; CHECK_ERR(pthread_getattr_np(pthread_self(), &attr)); # ifdef HAVE_PTHREAD_ATTR_GETSTACK CHECK_ERR(pthread_attr_getstack(&attr, addr, size)); STACK_DIR_UPPER((void)0, (void)(*addr = (char *)*addr + *size)); # else CHECK_ERR(pthread_attr_getstackaddr(&attr, addr)); CHECK_ERR(pthread_attr_getstacksize(&attr, size)); # endif CHECK_ERR(pthread_attr_getguardsize(&attr, &guard)); *size -= guard; pthread_attr_destroy(&attr); #elif defined HAVE_PTHREAD_ATTR_GET_NP /* FreeBSD, DragonFly BSD, NetBSD */ pthread_attr_t attr; CHECK_ERR(pthread_attr_init(&attr)); CHECK_ERR(pthread_attr_get_np(pthread_self(), &attr)); # ifdef HAVE_PTHREAD_ATTR_GETSTACK CHECK_ERR(pthread_attr_getstack(&attr, addr, size)); # else CHECK_ERR(pthread_attr_getstackaddr(&attr, addr)); CHECK_ERR(pthread_attr_getstacksize(&attr, size)); # endif STACK_DIR_UPPER((void)0, (void)(*addr = (char *)*addr + *size)); pthread_attr_destroy(&attr); #elif (defined HAVE_PTHREAD_GET_STACKADDR_NP && defined HAVE_PTHREAD_GET_STACKSIZE_NP) /* MacOS X */ pthread_t th = pthread_self(); *addr = pthread_get_stackaddr_np(th); *size = pthread_get_stacksize_np(th); #elif defined HAVE_THR_STKSEGMENT || defined HAVE_PTHREAD_STACKSEG_NP stack_t stk; # if defined HAVE_THR_STKSEGMENT /* Solaris */ CHECK_ERR(thr_stksegment(&stk)); # else /* OpenBSD */ CHECK_ERR(pthread_stackseg_np(pthread_self(), &stk)); # endif *addr = stk.ss_sp; *size = stk.ss_size; #elif defined HAVE_PTHREAD_GETTHRDS_NP /* AIX */ pthread_t th = pthread_self(); struct __pthrdsinfo thinfo; char reg[256]; int regsiz=sizeof(reg); CHECK_ERR(pthread_getthrds_np(&th, PTHRDSINFO_QUERY_ALL, &thinfo, sizeof(thinfo), ®, ®siz)); *addr = thinfo.__pi_stackaddr; *size = thinfo.__pi_stacksize; STACK_DIR_UPPER((void)0, (void)(*addr = (char *)*addr + *size)); #else #error STACKADDR_AVAILABLE is defined but not implemented. #endif return 0; #undef CHECK_ERR }
static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs) { #if OS(DARWIN) #if CPU(X86) unsigned user_count = sizeof(regs)/sizeof(int); thread_state_flavor_t flavor = i386_THREAD_STATE; #elif CPU(X86_64) unsigned user_count = x86_THREAD_STATE64_COUNT; thread_state_flavor_t flavor = x86_THREAD_STATE64; #elif CPU(PPC) unsigned user_count = PPC_THREAD_STATE_COUNT; thread_state_flavor_t flavor = PPC_THREAD_STATE; #elif CPU(PPC64) unsigned user_count = PPC_THREAD_STATE64_COUNT; thread_state_flavor_t flavor = PPC_THREAD_STATE64; #elif CPU(ARM) unsigned user_count = ARM_THREAD_STATE_COUNT; thread_state_flavor_t flavor = ARM_THREAD_STATE; #else #error Unknown Architecture #endif kern_return_t result = thread_get_state(platformThread, flavor, (thread_state_t)®s, &user_count); if (result != KERN_SUCCESS) { WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, "JavaScript garbage collection failed because thread_get_state returned an error (%d). This is probably the result of running inside Rosetta, which is not supported.", result); CRASH(); } return user_count * sizeof(usword_t); // end OS(DARWIN) #elif OS(WINDOWS) regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; GetThreadContext(platformThread, ®s); return sizeof(CONTEXT); #elif OS(QNX) memset(®s, 0, sizeof(regs)); regs.tid = platformThread; // FIXME: If we find this hurts performance, we can consider caching the fd and keeping it open. int fd = open("/proc/self/as", O_RDONLY); if (fd == -1) { LOG_ERROR("Unable to open /proc/self/as (errno: %d)", errno); CRASH(); } int rc = devctl(fd, DCMD_PROC_TIDSTATUS, ®s, sizeof(regs), 0); if (rc != EOK) { LOG_ERROR("devctl(DCMD_PROC_TIDSTATUS) failed (error: %d)", rc); CRASH(); } close(fd); return sizeof(struct _debug_thread_info); #elif USE(PTHREADS) pthread_attr_init(®s); #if HAVE(PTHREAD_NP_H) || OS(NETBSD) // e.g. on FreeBSD 5.4, [email protected] pthread_attr_get_np(platformThread, ®s); #else // FIXME: this function is non-portable; other POSIX systems may have different np alternatives pthread_getattr_np(platformThread, ®s); #endif return 0; #else #error Need a way to get thread registers on this platform #endif }
void mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize) { #if defined(HAVE_PTHREAD_GET_STACKSIZE_NP) && defined(HAVE_PTHREAD_GET_STACKADDR_NP) /* Mac OS X */ *staddr = (guint8*)pthread_get_stackaddr_np (pthread_self()); *stsize = pthread_get_stacksize_np (pthread_self()); #ifdef TARGET_OSX /* * Mavericks reports stack sizes as 512kb: * http://permalink.gmane.org/gmane.comp.java.openjdk.hotspot.devel/11590 * https://bugs.openjdk.java.net/browse/JDK-8020753 */ if (pthread_main_np () && *stsize == 512 * 1024) *stsize = 2048 * mono_pagesize (); #endif /* staddr points to the start of the stack, not the end */ *staddr -= *stsize; /* When running under emacs, sometimes staddr is not aligned to a page size */ *staddr = (guint8*)((gssize)*staddr & ~(mono_pagesize() - 1)); return; #elif (defined(HAVE_PTHREAD_GETATTR_NP) || defined(HAVE_PTHREAD_ATTR_GET_NP)) && defined(HAVE_PTHREAD_ATTR_GETSTACK) /* Linux, BSD */ pthread_attr_t attr; guint8 *current = (guint8*)&attr; *staddr = NULL; *stsize = (size_t)-1; pthread_attr_init (&attr); #if defined(HAVE_PTHREAD_GETATTR_NP) /* Linux */ pthread_getattr_np (pthread_self(), &attr); #elif defined(HAVE_PTHREAD_ATTR_GET_NP) /* BSD */ pthread_attr_get_np (pthread_self(), &attr); #else #error Cannot determine which API is needed to retrieve pthread attributes. #endif pthread_attr_getstack (&attr, (void**)staddr, stsize); pthread_attr_destroy (&attr); if (*staddr) g_assert ((current > *staddr) && (current < *staddr + *stsize)); /* When running under emacs, sometimes staddr is not aligned to a page size */ *staddr = (guint8*)((gssize)*staddr & ~(mono_pagesize () - 1)); return; #elif defined(__OpenBSD__) /* OpenBSD */ /* TODO : Determine if this code is actually still needed. It may already be covered by the case above. */ pthread_attr_t attr; guint8 *current = (guint8*)&attr; *staddr = NULL; *stsize = (size_t)-1; pthread_attr_init (&attr); stack_t ss; int rslt; rslt = pthread_stackseg_np(pthread_self(), &ss); g_assert (rslt == 0); *staddr = (guint8*)((size_t)ss.ss_sp - ss.ss_size); *stsize = ss.ss_size; pthread_attr_destroy (&attr); if (*staddr) g_assert ((current > *staddr) && (current < *staddr + *stsize)); /* When running under emacs, sometimes staddr is not aligned to a page size */ *staddr = (guint8*)((gssize)*staddr & ~(mono_pagesize () - 1)); return; #elif defined(sun) || defined(__native_client__) /* Solaris/Illumos, NaCl */ pthread_attr_t attr; pthread_attr_init (&attr); pthread_attr_getstacksize (&attr, &stsize); pthread_attr_destroy (&attr); *staddr = NULL; return; #else /* FIXME: It'd be better to use the 'error' preprocessor macro here so we know at compile-time if the target platform isn't supported. */ #warning "Unable to determine how to retrieve a thread's stack-bounds for this platform in 'mono_thread_get_stack_bounds()'." *staddr = NULL; *stsize = 0; return; #endif }
static void internal_pthread_backtrace(pthread_t thread, void** buffer, size_t max, size_t* depth, size_t skip) { *depth = 0; //! Get information about the stack (pos & size). uint8_t* stackbot; size_t stack_size; //! in bytes size_t guard_size; //! in bytes #if defined(__FreeBSD__) pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_get_np(thread, &attr); pthread_attr_getstack(&attr, (void**)&stackbot, &stack_size); pthread_attr_getguardsize(&attr, &guard_size); pthread_attr_destroy(&attr); #elif defined(__APPLE__) stackbot = (uint8_t*)pthread_get_stackaddr_np(thread); stack_size = pthread_get_stacksize_np(thread); guard_size = 0; //FIXME anyway to get that? #else pthread_attr_t attr; pthread_getattr_np(thread, &attr); pthread_attr_getstack(&attr, (void**)&stackbot, &stack_size); pthread_attr_getguardsize(&attr, &guard_size); pthread_attr_destroy(&attr); #endif stack_size -= guard_size; //! The thread is is still running!!! //! So make a buffer copy of the stack, else it gets changed while we reading from it! std::vector<uint8_t> sbuffer(stack_size); uint8_t* stack_buffer = &sbuffer[0]; memcpy(stack_buffer, stackbot, stack_size); //! It is impossible to get the current frame (the current function pos) on the stack //! for other pthreads, so we need to find it ourself. The beneath method is very naive //! and just searchs for the starting address that gives us the longest stackdepth. unsigned longest_stack = 0; unsigned longest_offset = 0; int check_area = MAX(0, stack_size - 1024*sizeof(uintptr_t)); check_area *= 0.8f; //! only check ~20% from the top of the stack for (int offset = stack_size - sizeof(uintptr_t); offset >= check_area; offset -= sizeof(uintptr_t)) { unsigned stack_depth = 0; uint8_t* frame = stack_buffer + offset; frame = TranslateStackAddrToBufferAddr(frame, stackbot, stack_buffer); uint8_t* last_frame = frame; while (INSTACK(frame) && (frame > last_frame)) { last_frame = frame; frame = TranslateStackAddrToBufferAddr(frame, stackbot, stack_buffer); stack_depth++; } if (stack_depth > longest_stack) { longest_stack = stack_depth; longest_offset = offset; } } //! Now get the list of function addresses from the stack. uint8_t* frame = stack_buffer + longest_offset; if(!INSTACK(frame)) return; while (skip--) { uint8_t* next = TranslateStackAddrToBufferAddr(frame, stackbot, stack_buffer); if(!INSTACK(next)) return; frame = next; } while (max--) { uint8_t* next = TranslateStackAddrToBufferAddr(frame, stackbot, stack_buffer); buffer[*depth] = (void*)*((uintptr_t*)frame + FP_OFFSET); (*depth)++; if(!INSTACK(next)) return; frame = next; } }