22
33#include " cinderx/Jit/stack_walk.h"
44
5+ #if defined(__APPLE__) || defined(__linux__)
6+
57#include < fmt/format.h>
68#include < sys/syscall.h>
79#include < sys/uio.h>
10+ #ifdef __APPLE__
11+ #include < sys/ucontext.h>
12+ #else
813#include < ucontext.h>
14+ #endif
915#include < unistd.h>
1016
1117#include < atomic>
1723#include < cstring>
1824#include < ctime>
1925#include < mutex>
26+ #include < stdexcept>
27+ #include < system_error>
2028
2129namespace cinderx {
2230
23- #if defined(__APPLE__) || defined(__linux__)
2431namespace {
2532
2633// How far above the previous record a caller's record may sit when the stack's
@@ -393,7 +400,9 @@ static std::atomic<StackWalk*> s_active;
393400bool StackWalk::installHandler (int signum, struct sigaction * prev) {
394401 struct sigaction action = {};
395402 action.sa_sigaction = handleSignal;
396- ::sigemptyset (&action.sa_mask);
403+ // Darwin exposes the signal-set helpers as macros, so they cannot be
404+ // namespace-qualified.
405+ sigemptyset (&action.sa_mask );
397406 action.sa_flags = SA_SIGINFO | SA_RESTART ;
398407 return ::sigaction (signum, &action, prev) == 0 ;
399408}
@@ -420,7 +429,7 @@ bool StackWalk::handlerIsOurs(int signum) {
420429// terminates the process.
421430int StackWalk::claimSignum () {
422431 sigset_t blocked;
423- :: sigemptyset (&blocked);
432+ sigemptyset (&blocked);
424433 ::pthread_sigmask (SIG_BLOCK , nullptr , &blocked);
425434
426435 auto claim = [&blocked](int signum) {
@@ -429,7 +438,7 @@ int StackWalk::claimSignum() {
429438 // it reads as unclaimed below and taking it would be undetectable - but a
430439 // thread that waits on a signal has to block it first, and the convention
431440 // is to block it in every thread before any of them start.
432- if (:: sigismember (&blocked, signum) == 1 ) {
441+ if (sigismember (&blocked, signum) == 1 ) {
433442 return false ;
434443 }
435444 // Already carrying this class's handler, which means an earlier scan
@@ -516,7 +525,7 @@ void StackWalk::resetSignumCache() {
516525 if (signum > 0 && handlerIsOurs (signum)) {
517526 struct sigaction action = {};
518527 action.sa_handler = SIG_DFL ;
519- :: sigemptyset (&action.sa_mask);
528+ sigemptyset (&action.sa_mask );
520529 ::sigaction (signum, &action, nullptr );
521530 }
522531}
@@ -837,12 +846,22 @@ StackWalk::Publish StackWalk::publishBatch(size_t count) {
837846void StackWalk::captureFrames (const void * ucontext) {
838847 auto uc = static_cast <const ucontext_t *>(ucontext);
839848
840- #if defined(__x86_64__)
849+ #if defined(__APPLE__) && defined(__aarch64__)
850+ // StackWalk is compile-only on macOS because sem_init() is unsupported and
851+ // its constructor always throws. The context extraction still has to build
852+ // as part of the JIT library.
853+ const auto & state = uc->uc_mcontext ->__ss ;
854+ auto frame = reinterpret_cast <const StackFrame*>(
855+ __darwin_arm_thread_state64_get_fp (state));
856+ auto pc =
857+ reinterpret_cast <const void *>(__darwin_arm_thread_state64_get_pc (state));
858+ auto sp = static_cast <uintptr_t >(__darwin_arm_thread_state64_get_sp (state));
859+ #elif defined(__linux__) && defined(__x86_64__)
841860 auto frame =
842861 reinterpret_cast <const StackFrame*>(uc->uc_mcontext .gregs [REG_RBP ]);
843862 auto pc = reinterpret_cast <const void *>(uc->uc_mcontext .gregs [REG_RIP ]);
844863 auto sp = static_cast <uintptr_t >(uc->uc_mcontext .gregs [REG_RSP ]);
845- #elif defined(__aarch64__)
864+ #elif defined(__linux__) && defined( __aarch64__)
846865 auto frame = reinterpret_cast <const StackFrame*>(uc->uc_mcontext .regs [29 ]);
847866 auto pc = reinterpret_cast <const void *>(uc->uc_mcontext .pc );
848867 auto sp = static_cast <uintptr_t >(uc->uc_mcontext .sp );
@@ -907,5 +926,6 @@ void StackWalk::captureFrames(const void* ucontext) {
907926 ::sem_post (&handler_exited_);
908927 }
909928}
910- #endif
911929} // namespace cinderx
930+
931+ #endif
0 commit comments