33#ifdef __linux__
44#include " profiler.h"
55#include " vmStructs.h"
6+ #include " guards.h"
67
78#include < cassert>
89#include < dlfcn.h>
@@ -31,7 +32,7 @@ void LibraryPatcher::initialize() {
3132class RoutineInfo {
3233private:
3334 func_start_routine _routine;
34- void * const _args;
35+ void * _args;
3536public:
3637 RoutineInfo (func_start_routine routine, void * args) :
3738 _routine (routine), _args(args) {
@@ -41,23 +42,40 @@ class RoutineInfo {
4142 return _routine;
4243 }
4344
44- void * const args () const {
45+ void * args () const {
4546 return _args;
4647 }
4748};
4849
50+ #ifdef __aarch64__
51+ // Initialize the current thread's TLS with profiling signals blocked.
52+ // Kept in a separate noinline function so that SignalBlocker's 128-byte
53+ // sigset_t lives in its own frame and does not trigger stack-protector
54+ // canary placement in start_routine_wrapper on aarch64.
55+ __attribute__ ((noinline))
56+ static void init_thread_tls() {
57+ // Block profiling signals during TLS initialization: TLS init
58+ // (pthread_once, pthread_key_create, pthread_setspecific) is not
59+ // async-signal-safe. A profiling signal here can corrupt
60+ // internal TLS bookkeeping on the stack.
61+ SignalBlocker blocker;
62+ ProfiledThread::initCurrentThread ();
63+ }
64+
4965// Wrapper around the real start routine.
5066// The wrapper:
5167// 1. Register the newly created thread to profiler
5268// 2. Call real start routine
5369// 3. Unregister the thread from profiler once the routine is completed.
54- static void * start_routine_wrapper (void * args) {
70+ // This version is to workaround a precarious stack guard corruption,
71+ // which only happens in Linux/musl/aarch64/jdk11
72+ __attribute__ ((visibility(" hidden" )))
73+ static void* start_routine_wrapper_spec(void * args) {
5574 RoutineInfo* thr = (RoutineInfo*)args;
5675 func_start_routine routine = thr->routine ();
57- void * const params = thr->args ();
76+ void * params = thr->args ();
5877 delete thr;
59-
60- ProfiledThread::initCurrentThread ();
78+ init_thread_tls ();
6179 int tid = ProfiledThread::currentTid ();
6280 Profiler::registerThread (tid);
6381 void * result = routine (params);
@@ -66,12 +84,59 @@ static void* start_routine_wrapper(void* args) {
6684 return result;
6785}
6886
87+ static int pthread_create_hook_spec (pthread_t * thread,
88+ const pthread_attr_t * attr,
89+ func_start_routine start_routine,
90+ void * args) {
91+ RoutineInfo* thr = new RoutineInfo (start_routine, args);
92+ int ret = pthread_create (thread, attr, start_routine_wrapper_spec, (void *)thr);
93+ if (ret != 0 ) delete thr;
94+ return ret;
95+ }
96+
97+ #endif // __aarch64__
98+
99+ static void thread_cleanup (void * arg) {
100+ int tid = *static_cast <int *>(arg);
101+ Profiler::unregisterThread (tid);
102+ ProfiledThread::release ();
103+ }
104+
105+ // Wrapper around the real start routine.
106+ // See comments for start_routine_wrapper_spec() for details
107+ __attribute__ ((visibility(" hidden" )))
108+ static void* start_routine_wrapper(void * args) {
109+ RoutineInfo* thr = (RoutineInfo*)args;
110+ func_start_routine routine = thr->routine ();
111+ void * params = thr->args ();
112+ delete thr;
113+ {
114+ // Block profiling signals during TLS initialization: TLS init
115+ // (pthread_once, pthread_key_create, pthread_setspecific) is not
116+ // async-signal-safe. A profiling signal here can corrupt
117+ // internal TLS bookkeeping on the stack.
118+ SignalBlocker blocker;
119+ ProfiledThread::initCurrentThread ();
120+ }
121+ int tid = ProfiledThread::currentTid ();
122+ Profiler::registerThread (tid);
123+ void * result = nullptr ;
124+ // Handle pthread_exit() bypass - the thread calls pthread_exit()
125+ // instead of normal termination
126+ pthread_cleanup_push (thread_cleanup, &tid);
127+ result = routine (params);
128+ pthread_cleanup_pop (1 );
129+ return result;
130+ }
131+
69132static int pthread_create_hook (pthread_t * thread,
70133 const pthread_attr_t * attr,
71134 func_start_routine start_routine,
72135 void * args) {
73136 RoutineInfo* thr = new RoutineInfo (start_routine, args);
74- return pthread_create (thread, attr, start_routine_wrapper, (void *)thr);
137+ int ret = pthread_create (thread, attr, start_routine_wrapper, (void *)thr);
138+ if (ret != 0 ) delete thr;
139+ return ret;
75140}
76141
77142void LibraryPatcher::patch_libraries () {
@@ -105,10 +170,18 @@ void LibraryPatcher::patch_library_unlocked(CodeCache* lib) {
105170 }
106171 }
107172 TEST_LOG (" Patching: %s" , lib->name ());
173+ void * func = (void *)pthread_create_hook;
174+
175+ #ifdef __aarch64__
176+ // Workaround stack guard corruption in Linux/aarch64/musl/jdk11
177+ if (VM::isHotspot () && OS::isMusl () && VM::java_version () == 11 ) {
178+ func = (void *)pthread_create_hook_spec;
179+ }
180+ #endif
108181 _patched_entries[_size]._lib = lib;
109182 _patched_entries[_size]._location = pthread_create_location;
110183 _patched_entries[_size]._func = (void *)__atomic_load_n (pthread_create_location, __ATOMIC_RELAXED);
111- __atomic_store_n (pthread_create_location, ( void *)pthread_create_hook , __ATOMIC_RELAXED);
184+ __atomic_store_n (pthread_create_location, func , __ATOMIC_RELAXED);
112185 _size++;
113186}
114187
0 commit comments