Skip to content

Instantly share code, notes, and snippets.

@saagarjha
Last active October 8, 2022 04:36
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save saagarjha/d1ddd98537150e4a09520ed3ede54f5e to your computer and use it in GitHub Desktop.
Save saagarjha/d1ddd98537150e4a09520ed3ede54f5e to your computer and use it in GitHub Desktop.
Fix applications that use JIT on Apple silicon but don't know about pthread_jit_write_protect_np
// The usual: compile with clang libfixjit.c -arch arm64 -arch arm64e -shared -o libfixjit.dylib, add to DYLD_INSERT_LIBRARIES.
#include <errno.h>
#include <pthread.h>
#include <stdatomic.h>
__attribute__((constructor)) static void fix_jit() {
unsigned long long mask;
__asm__ volatile("mrs %0, s3_4_c15_c2_7" : "=r"(mask): :);
__asm__ volatile("msr s3_4_c15_c2_7, %0" : : "r"(mask & 0xfffffffff0ffffff) :);
}
typedef struct {
void *(*function)();
void *argument;
} pthread_context;
static pthread_context context_arena[4096 /* ought to be enough for anybody */];
static atomic_size_t arena_top = sizeof(context_arena) / sizeof(*context_arena);
static void *fix_jit_trampoline(void *argument) {
fix_jit();
pthread_context *context = (pthread_context *)argument;
return context->function(context->argument);
}
int overriden_pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) {
size_t context;
if ((context = --arena_top)) {
context_arena[context] = (pthread_context) { start_routine, arg };
return pthread_create(thread, attr, fix_jit_trampoline, context_arena + context);
} else {
return EAGAIN;
}
}
__attribute__((used, section("__DATA,__interpose"))) static struct {
int (*overriden_pthread_create)();
int (*pthread_create)();
} pthread_create_interpose = {overriden_pthread_create, pthread_create};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment